packetfu 1.1.6 → 1.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.mailmap +5 -0
- data/README.rdoc +1 -1
- data/Rakefile +11 -0
- data/examples/arp.rb +1 -1
- data/examples/arphood.rb +8 -7
- data/examples/ethernet.rb +1 -1
- data/examples/new-simple-stats.rb +1 -1
- data/examples/packetfu-shell.rb +1 -1
- data/examples/simple-sniffer.rb +2 -2
- data/examples/simple-stats.rb +1 -1
- data/examples/uniqpcap.rb +1 -1
- data/lib/packetfu/capture.rb +11 -8
- data/lib/packetfu/packet.rb +1 -1
- data/lib/packetfu/protos/eth.rb +1 -1
- data/lib/packetfu/protos/icmp.rb +1 -1
- data/lib/packetfu/protos/lldp.rb +59 -0
- data/lib/packetfu/protos/lldp/header.rb +250 -0
- data/lib/packetfu/protos/lldp/mixin.rb +55 -0
- data/lib/packetfu/utils.rb +7 -3
- data/lib/packetfu/version.rb +1 -1
- data/packetfu.gemspec +3 -3
- data/{test → spec}/ethpacket_spec.rb +2 -2
- data/{test → spec}/packet_spec.rb +0 -0
- data/{test → spec}/packet_subclasses_spec.rb +0 -0
- data/{test → spec}/packetfu_spec.rb +1 -6
- data/spec/sample.pcap +0 -0
- data/spec/sample2.pcap +0 -0
- data/{test → spec}/structfu_spec.rb +0 -0
- data/{test → spec}/tcp_spec.rb +1 -1
- data/spec/vlan-pcapr.cap +0 -0
- data/test/func_lldp.rb +25 -0
- data/test/sample_lldp.pcap +0 -0
- data/test/test_capture.rb +58 -0
- data/test/test_icmp.rb +8 -0
- data/test/test_tcp.rb +20 -0
- data/test/test_udp.rb +8 -0
- metadata +48 -15
data/.mailmap
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
Tod Beardsley <todb@packetfu.com> Tod Beardsley <tod_beardsley@rapid7.com>
|
2
|
+
Tod Beardsley <todb@packetfu.com> Tod Beardsley <todb@metasploit.com>
|
3
|
+
Tod Beardsley <todb@packetfu.com> Tod Beardsley <todb@planb-security.net>
|
4
|
+
Tod Beardsley <todb@packetfu.com> todb <todb@planb-security.net>
|
5
|
+
|
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= PacketFu
|
2
2
|
|
3
|
-
A library for reading
|
3
|
+
A library for reading and writing packets to an interface or to a libpcap-formatted file.
|
4
4
|
|
5
5
|
It is maintained at http://code.google.com/p/packetfu and https://github.com/todb/packetfu (which repository will win?)
|
6
6
|
|
data/Rakefile
ADDED
data/examples/arp.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# (and a wee bit cleaner) is already available as Packet::Utils::arp, since knowing the
|
5
5
|
# MAC address of a target IP turns out to be pretty useful day-to-day.
|
6
6
|
|
7
|
-
require 'examples' # For path setting slight-of-hand
|
7
|
+
require './examples' # For path setting slight-of-hand
|
8
8
|
require 'packetfu'
|
9
9
|
|
10
10
|
def usage
|
data/examples/arphood.rb
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
# A simple local network fingerprinter. Uses the OUI list.
|
4
|
+
# Usage: rvmsudo ./arphood.rb [iface] [network] <oui.txt>
|
4
5
|
|
5
|
-
require 'examples'
|
6
|
+
require './examples'
|
6
7
|
require 'packetfu'
|
7
8
|
require 'open-uri'
|
8
9
|
|
9
10
|
$oui_prefixes = {}
|
10
11
|
$arp_results = []
|
11
12
|
def build_oui_list
|
12
|
-
if ARGV[
|
13
|
-
puts "Fetching the oui.txt from IEEE, it'll be a second. Avoid this with #{$0} <filename>."
|
13
|
+
if ARGV[2].nil?
|
14
|
+
puts "Fetching the oui.txt from IEEE, it'll be a second. Avoid this with #{$0} [iface] [network] <filename>."
|
14
15
|
oui_file = open("http://standards.ieee.org/regauth/oui/oui.txt")
|
15
16
|
else
|
16
|
-
oui_file = File.open(ARGV[
|
17
|
+
oui_file = File.open(ARGV[2], "rb")
|
17
18
|
end
|
18
19
|
oui_file.each do |oui_line|
|
19
20
|
maybe_oui = oui_line.scan(/^[0-9a-f]{2}\-[0-9a-f]{2}\-[0-9a-f]{2}/i)[0]
|
@@ -30,9 +31,9 @@ build_oui_list
|
|
30
31
|
$root_ok = true if Process.euid.zero?
|
31
32
|
|
32
33
|
def arp_everyone
|
33
|
-
my_net = PacketFu::Config.new(PacketFu::Utils.whoami?(:iface => 'wlan0'))
|
34
|
+
my_net = PacketFu::Config.new(PacketFu::Utils.whoami?(:iface =>(ARGV[0] || 'wlan0')))
|
34
35
|
threads = []
|
35
|
-
network = "192.168.2"
|
36
|
+
network = ARGV[1] || "192.168.2"
|
36
37
|
print "Arping around..."
|
37
38
|
253.times do |i|
|
38
39
|
threads[i] = Thread.new do
|
@@ -47,7 +48,7 @@ def arp_everyone
|
|
47
48
|
$arp_results << "%s : %s / %s" % [this_host,colon_mac,$oui_prefixes[hyphen_mac]]
|
48
49
|
end
|
49
50
|
end
|
50
|
-
threads.join
|
51
|
+
threads.each {|thr| thr.join}
|
51
52
|
end
|
52
53
|
|
53
54
|
if $root_ok
|
data/examples/ethernet.rb
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
# every 11 seconds (my own benchmark) for this script, at least
|
9
9
|
# it doesn't hog up all your memory.
|
10
10
|
|
11
|
-
require 'examples' # For path setting slight-of-hand
|
11
|
+
require './examples' # For path setting slight-of-hand
|
12
12
|
require 'packetfu'
|
13
13
|
|
14
14
|
def print_results(stats)
|
data/examples/packetfu-shell.rb
CHANGED
data/examples/simple-sniffer.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require 'examples'
|
2
|
+
require './examples'
|
3
3
|
require 'packetfu'
|
4
4
|
|
5
5
|
puts "Simple sniffer for PacketFu #{PacketFu.version}"
|
@@ -11,7 +11,7 @@ def sniff(iface)
|
|
11
11
|
cap.stream.each do |p|
|
12
12
|
pkt = Packet.parse p
|
13
13
|
if pkt.is_ip?
|
14
|
-
next if pkt.ip_saddr == Utils.ifconfig[:ip_saddr]
|
14
|
+
next if pkt.ip_saddr == Utils.ifconfig(iface)[:ip_saddr]
|
15
15
|
packet_info = [pkt.ip_saddr, pkt.ip_daddr, pkt.size, pkt.proto.last]
|
16
16
|
puts "%-15s -> %-15s %-4d %s" % packet_info
|
17
17
|
end
|
data/examples/simple-stats.rb
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
# See new-simple-stats.rb for an example of the streaming
|
10
10
|
# parsing method.
|
11
11
|
|
12
|
-
require 'examples' # For path setting slight-of-hand
|
12
|
+
require './examples' # For path setting slight-of-hand
|
13
13
|
require 'packetfu'
|
14
14
|
|
15
15
|
# Takes a file name, parses the packets, and records the packet
|
data/examples/uniqpcap.rb
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
# Currently, the timestamp information is lost due to PcapRub's
|
8
8
|
# file read. For me, this isn't a big deal. Future versions
|
9
9
|
# will deal with timestamps correctly.
|
10
|
-
require 'examples' # For path setting slight-of-hand
|
10
|
+
require './examples' # For path setting slight-of-hand
|
11
11
|
require 'packetfu'
|
12
12
|
|
13
13
|
in_array = PacketFu::Read.f2a(:file => ARGV[0])
|
data/lib/packetfu/capture.rb
CHANGED
@@ -26,7 +26,7 @@ module PacketFu
|
|
26
26
|
# Read, Write
|
27
27
|
class Capture
|
28
28
|
attr_accessor :array, :stream # Leave these public and open.
|
29
|
-
attr_reader :iface, :snaplen, :promisc, :timeout
|
29
|
+
attr_reader :iface, :snaplen, :promisc, :timeout, :filter
|
30
30
|
|
31
31
|
def initialize(args={})
|
32
32
|
@array = [] # Where the packet array goes.
|
@@ -35,13 +35,13 @@ module PacketFu
|
|
35
35
|
@snaplen = args[:snaplen] || 0xffff
|
36
36
|
@promisc = args[:promisc] || false # Sensible for some Intel wifi cards
|
37
37
|
@timeout = args[:timeout] || 1
|
38
|
-
|
38
|
+
@filter = args[:filter] || args[:bpf]
|
39
39
|
setup_params(args)
|
40
40
|
end
|
41
41
|
|
42
42
|
# Used by new().
|
43
43
|
def setup_params(args={})
|
44
|
-
filter = args[:filter]
|
44
|
+
filter = args[:filter] || args[:bpf] || @filter
|
45
45
|
start = args[:start] || false
|
46
46
|
capture if start
|
47
47
|
bpf(:filter=>filter) if filter
|
@@ -55,7 +55,7 @@ module PacketFu
|
|
55
55
|
# When true, start capturing packets to the @stream variable. Defaults to true
|
56
56
|
def capture(args={})
|
57
57
|
if Process.euid.zero?
|
58
|
-
filter = args[:filter]
|
58
|
+
filter = args[:filter] || args[:bpf] || @filter
|
59
59
|
start = args[:start] || true
|
60
60
|
if start
|
61
61
|
begin
|
@@ -98,11 +98,14 @@ module PacketFu
|
|
98
98
|
# :filter
|
99
99
|
# Provide a bpf filter to enable for the capture. For example, 'ip and not tcp'
|
100
100
|
def bpf(args={})
|
101
|
-
filter = args[:filter]
|
101
|
+
filter = args[:filter] || args[:bpf] || @filter
|
102
102
|
capture if @stream.class == Array
|
103
|
-
@stream.setfilter(filter)
|
103
|
+
@stream.setfilter(filter) if filter
|
104
|
+
@filter = filter
|
104
105
|
end
|
105
106
|
|
107
|
+
alias :filter :bpf
|
108
|
+
|
106
109
|
# wire_to_array() saves a packet stream as an array of binary strings. From here,
|
107
110
|
# packets may accessed by other functions. Note that the wire_to_array empties
|
108
111
|
# the stream, so multiple calls will append new packets to @array.
|
@@ -111,7 +114,7 @@ module PacketFu
|
|
111
114
|
# :filter
|
112
115
|
# Provide a bpf filter to apply to packets moving from @stream to @array.
|
113
116
|
def wire_to_array(args={})
|
114
|
-
filter = args[:filter]
|
117
|
+
filter = args[:filter] || args[:bpf] || @filter
|
115
118
|
bpf(:filter=>filter) if filter
|
116
119
|
|
117
120
|
while this_pkt = @stream.next
|
@@ -146,7 +149,7 @@ module PacketFu
|
|
146
149
|
# :quiet
|
147
150
|
# TODO: Not implemented yet; do less than peek() at the packets.
|
148
151
|
def show_live(args={})
|
149
|
-
filter = args[:filter]
|
152
|
+
filter = args[:filter] || args[:bpf] || @filter
|
150
153
|
save = args[:save]
|
151
154
|
verbose = args[:verbose] || args[:v] || false
|
152
155
|
quiet = args[:quiet] || args[:q] || false # Setting q and v doesn't make a lot of sense but hey.
|
data/lib/packetfu/packet.rb
CHANGED
@@ -251,7 +251,7 @@ module PacketFu
|
|
251
251
|
case self.name # Lol ran into case's fancy treatment of classes
|
252
252
|
when /InvalidPacket$/; 0
|
253
253
|
when /EthPacket$/; 1
|
254
|
-
when /IPPacket$/, /ARPPacket$/, /IPv6Packet$/; 2
|
254
|
+
when /IPPacket$/, /ARPPacket$/, /LLDPPacket$/, /IPv6Packet$/; 2
|
255
255
|
when /TCPPacket$/, /UDPPacket$/, /ICMPPacket$/; 3
|
256
256
|
when /HSRPPacket$/; 4
|
257
257
|
else; self.new.headers.size
|
data/lib/packetfu/protos/eth.rb
CHANGED
@@ -21,7 +21,7 @@ module PacketFu
|
|
21
21
|
|
22
22
|
def self.can_parse?(str)
|
23
23
|
# XXX Temporary fix. Need to extend the EthHeader class to handle more.
|
24
|
-
valid_eth_types = [0x0800, 0x0806, 0x86dd]
|
24
|
+
valid_eth_types = [0x0800, 0x0806, 0x86dd, 0x88cc]
|
25
25
|
return false unless str.size >= 14
|
26
26
|
type = str[12,2].unpack("n").first rescue nil
|
27
27
|
return false unless valid_eth_types.include? type
|
data/lib/packetfu/protos/icmp.rb
CHANGED
@@ -42,7 +42,7 @@ module PacketFu
|
|
42
42
|
attr_accessor :eth_header, :ip_header, :icmp_header
|
43
43
|
|
44
44
|
def self.can_parse?(str)
|
45
|
-
return false unless str.size >=
|
45
|
+
return false unless str.size >= 38
|
46
46
|
return false unless EthPacket.can_parse? str
|
47
47
|
return false unless IPPacket.can_parse? str
|
48
48
|
return false unless str[23,1] == "\x01"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'packetfu/protos/eth/header'
|
2
|
+
require 'packetfu/protos/eth/mixin'
|
3
|
+
|
4
|
+
require 'packetfu/protos/lldp/header'
|
5
|
+
require 'packetfu/protos/lldp/mixin'
|
6
|
+
|
7
|
+
module PacketFu
|
8
|
+
|
9
|
+
class LLDPPacket < Packet
|
10
|
+
include ::PacketFu::EthHeaderMixin
|
11
|
+
include ::PacketFu::LLDPHeaderMixin
|
12
|
+
|
13
|
+
attr_accessor :eth_header, :lldp_header
|
14
|
+
|
15
|
+
def self.can_parse?(str)
|
16
|
+
return false unless EthPacket.can_parse? str
|
17
|
+
return false unless str.size >= 6
|
18
|
+
return false unless str[12,2] == "\x88\xcc"
|
19
|
+
return false unless str =~ /^\x01\x80\xc2\x00\x00[\x0e\x03\x00]/
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def read(str=nil,args={})
|
24
|
+
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
25
|
+
@eth_header.read(str)
|
26
|
+
super(args)
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(args={})
|
31
|
+
@eth_header = EthHeader.new(args).read(args[:eth])
|
32
|
+
@lldp_header = LLDPHeader.new(args).read(args[:lldp])
|
33
|
+
@eth_header.eth_proto = "\x88\xCC"
|
34
|
+
@eth_header.body=@lldp_header
|
35
|
+
|
36
|
+
@headers = [@eth_header, @lldp_header]
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
# Generates summary data for LLDP packets.
|
41
|
+
def peek_format
|
42
|
+
peek_data = ["A "]
|
43
|
+
peek_data << "%-5d" % self.to_s.size
|
44
|
+
peek_data << lldp_saddr_mac
|
45
|
+
peek_data << "(#{lldp_saddr_mac})"
|
46
|
+
peek_data << "->"
|
47
|
+
peek_data << "01:80:c2:00:00:0e"
|
48
|
+
peek_data.join
|
49
|
+
end
|
50
|
+
|
51
|
+
# While there are lengths in LLDPPackets, there's not
|
52
|
+
# much to do with them.
|
53
|
+
def recalc(args={})
|
54
|
+
@headers[0].inspect
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
|
@@ -0,0 +1,250 @@
|
|
1
|
+
module PacketFu
|
2
|
+
# LLDPHeader is a complete LLDP struct, used in LLDPPacket.
|
3
|
+
|
4
|
+
class LLDPHeader < Struct.new(:lldp_chassis_id_type, :lldp_chassis_id, :lldp_port_id_type, :lldp_port_id, :lldp_ttl, :lldp_port_description, :lldp_system_name, :lldp_system_description, :lldp_capabilty, :lldp_enabled_capability, :lldp_address_type, :lldp_address, :lldp_interface_type, :lldp_interface, :lldp_oid)
|
5
|
+
include StructFu
|
6
|
+
|
7
|
+
def initialize(args={})
|
8
|
+
src_mac = (args[:lldp_port_id] if :lldp_port_id_type == 3) || (args[:config][:eth_src] if args[:config])
|
9
|
+
src_ip_bin = (args[:lldp_address] if :lldp_address_type == 1) || (args[:config][:ip_src_bin] if args[:config])
|
10
|
+
|
11
|
+
super(Int8.new(args[:lldp_chassis_id_type] || 4),
|
12
|
+
StructFu::String.new.read(:lldp_chassis_id),
|
13
|
+
Int8.new(args[:lldp_port_id_type] || 3),
|
14
|
+
EthMac.new.read(src_mac),
|
15
|
+
Int16.new(args[:lldp_ttl] || 120),
|
16
|
+
StructFu::String.new.read(:lldp_port_description) || "",
|
17
|
+
StructFu::String.new.read(:lldp_system_name) || "",
|
18
|
+
StructFu::String.new.read(:lldp_system_description) || "",
|
19
|
+
Int16.new(args[:lldp_capabilty] || 0x0080),
|
20
|
+
Int16.new(args[:lldp_enabled_capability] || 0x0080),
|
21
|
+
Int8.new(args[:lldp_address_type] || 1),
|
22
|
+
StructFu::String.new.read(:lldp_address) || src_ip_bin,
|
23
|
+
Int8.new(args[:lldp_interface_type] || 2),
|
24
|
+
Int32.new(args[:lldp_interface]),
|
25
|
+
StructFu::String.new.read(:lldp_oid) || ""
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the object in string form.
|
30
|
+
def to_s
|
31
|
+
self.to_a.map {|x| x.to_s}.join
|
32
|
+
end
|
33
|
+
|
34
|
+
# Reads a string to populate the object.
|
35
|
+
def read(str)
|
36
|
+
force_binary(str)
|
37
|
+
return self if str.nil?
|
38
|
+
index = 0
|
39
|
+
#check for lldp pdu end
|
40
|
+
while (str[index,2] != "\x00\x00") && (index+2 < str.size)
|
41
|
+
tlv_known = false
|
42
|
+
#chassis subtype
|
43
|
+
if str[index,1] == "\x02"
|
44
|
+
tlv_known = true
|
45
|
+
tlv_length = str[index+1,1].unpack("U*").join.to_i
|
46
|
+
self[:lldp_chassis_id_type].read(str[index+2,1])
|
47
|
+
self[:lldp_chassis_id].read(str[index+3, tlv_length - 1])
|
48
|
+
index += tlv_length + 2
|
49
|
+
end
|
50
|
+
#port subtype
|
51
|
+
if str[index,1] == "\x04"
|
52
|
+
tlv_known = true
|
53
|
+
tlv_length = str[index+1,1].unpack("U*").join.to_i
|
54
|
+
self[:lldp_port_id_type].read(str[index+2,1])
|
55
|
+
self[:lldp_port_id].read(str[index+3, tlv_length - 1])
|
56
|
+
index += tlv_length + 2
|
57
|
+
end
|
58
|
+
#ttl subtype
|
59
|
+
if str[index,1] == "\x06"
|
60
|
+
tlv_known = true
|
61
|
+
tlv_length = str[index+1,1].unpack("U*").join.to_i
|
62
|
+
self[:lldp_ttl].read(str[index+2, tlv_length])
|
63
|
+
index += tlv_length + 2
|
64
|
+
end
|
65
|
+
#port description
|
66
|
+
if str[index,1] == "\x08"
|
67
|
+
tlv_known = true
|
68
|
+
tlv_length = str[index+1,1].unpack("U*").join.to_i
|
69
|
+
self[:lldp_port_description].read(str[index+2, tlv_length])
|
70
|
+
index += tlv_length + 2
|
71
|
+
end
|
72
|
+
#system name
|
73
|
+
if str[index,1] == "\x0a"
|
74
|
+
tlv_known = true
|
75
|
+
tlv_length = str[index+1,1].unpack("U*").join.to_i
|
76
|
+
self[:lldp_system_name].read(str[index+2, tlv_length])
|
77
|
+
index += tlv_length + 2
|
78
|
+
end
|
79
|
+
#system description
|
80
|
+
if str[index,1] == "\x0c"
|
81
|
+
tlv_known = true
|
82
|
+
tlv_length = str[index+1,1].unpack("U*").join.to_i
|
83
|
+
self[:lldp_system_description].read(str[index+2, tlv_length])
|
84
|
+
index += tlv_length + 2
|
85
|
+
end
|
86
|
+
#system capabilities
|
87
|
+
if str[index,1] == "\x0e"
|
88
|
+
tlv_known = true
|
89
|
+
tlv_length = str[index+1,1].unpack("U*").join.to_i
|
90
|
+
self[:lldp_capabilty].read(str[index+2, 2])
|
91
|
+
self[:lldp_enabled_capability].read(str[index+4, 2])
|
92
|
+
index += tlv_length + 2
|
93
|
+
end
|
94
|
+
#management address
|
95
|
+
if str[index,1] == "\x10"
|
96
|
+
tlv_known = true
|
97
|
+
tlv_length = str[index + 1,1].unpack("U*").join.to_i
|
98
|
+
addr_length = str[index + 2, 1].unpack("U*").join.to_i
|
99
|
+
self[:lldp_address_type].read(str[index + 3, 1])
|
100
|
+
self[:lldp_address].read(str[index + 4,addr_length - 1])
|
101
|
+
self[:lldp_interface_type].read(str[index + addr_length + 3, 1].unpack("U*").join.to_i)
|
102
|
+
self[:lldp_interface].read(str[index + addr_length + 4, 4])
|
103
|
+
oid_string_length = str[index + addr_length + 8, 1].unpack("U*").join.to_i
|
104
|
+
if oid_string_length > 0
|
105
|
+
self[:lldp_oid].read(str[index + addr_length + 9, oid_string_length])
|
106
|
+
end
|
107
|
+
index += tlv_length + 2
|
108
|
+
end
|
109
|
+
|
110
|
+
#if tlv type is unknown jump over it
|
111
|
+
unless tlv_known
|
112
|
+
tlv_length = str[index+1,1].unpack("U*").join.to_i
|
113
|
+
index += tlv_length + 2
|
114
|
+
end
|
115
|
+
end
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
# Setter for the LLDP chassis id type.
|
120
|
+
def lldp_chassis_id_type=(i); typecast i; end
|
121
|
+
# Getter for the LLDP chassis id type.
|
122
|
+
def lldp_chassis_id_type; self[:lldp_chassis_id_type].to_i; end
|
123
|
+
# Setter for the LLDP chassis id.
|
124
|
+
def lldp_chassis_id=(i); typecast i; end
|
125
|
+
# Getter for the LLDP chassis id .
|
126
|
+
def lldp_chassis_id_readable()
|
127
|
+
if self[:lldp_chassis_id_type].to_i == 4
|
128
|
+
return EthHeader.str2mac(self[:lldp_chassis_id].to_s)
|
129
|
+
else
|
130
|
+
return self[:lldp_chassis_id].to_s
|
131
|
+
end
|
132
|
+
end
|
133
|
+
# Setter for the LLDP port id type.
|
134
|
+
def lldp_port_id_type=(i); typecast i; end
|
135
|
+
# Getter for the LLDP port id type.
|
136
|
+
def lldp_port_id_type; self[:lldp_port_id_type].to_i; end
|
137
|
+
# Setter for the LLDP port id .
|
138
|
+
def lldp_port_id=(i); typecast i; end
|
139
|
+
# Getter for the LLDP port id.
|
140
|
+
def lldp_port_id_readable()
|
141
|
+
#if mac addr
|
142
|
+
if self[:lldp_port_id_type].to_i == 3
|
143
|
+
return EthHeader.str2mac(self[:lldp_port_id].to_s)
|
144
|
+
else
|
145
|
+
return self[:lldp_port_id].to_s
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Set the source MAC address in a more readable way.
|
150
|
+
def lldp_saddr_mac=(mac)
|
151
|
+
mac = EthHeader.mac2str(mac)
|
152
|
+
self[:lldp_port_id_type] = 3
|
153
|
+
self[:lldp_port_id].read(mac)
|
154
|
+
self.lldp_port_id
|
155
|
+
end
|
156
|
+
|
157
|
+
# Setter for the LLDP ttl.
|
158
|
+
def lldp_ttl=(i); typecast i; end
|
159
|
+
# Getter for the LLDP ttl.
|
160
|
+
def lldp_ttl; self[:lldp_ttl].to_i; end
|
161
|
+
# Setter for the LLDP port description.
|
162
|
+
def lldp_port_description=(i); typecast i; end
|
163
|
+
# Getter for the LLDP port description.
|
164
|
+
def lldp_port_description; self[:lldp_port_description].to_s; end
|
165
|
+
# Setter for the LLDP system name.
|
166
|
+
def lldp_system_name=(i); typecast i; end
|
167
|
+
# Getter for the LLDP system name.
|
168
|
+
def lldp_system_name; self[:lldp_system_name].to_s; end
|
169
|
+
# Setter for the LLDP system description.
|
170
|
+
def lldp_system_description=(i); typecast i; end
|
171
|
+
# Getter for the LLDP system description.
|
172
|
+
def lldp_system_description; self[:lldp_system_description].to_s; end
|
173
|
+
# Setter for the LLDP capability.
|
174
|
+
def lldp_capabilty=(i); typecast i; end
|
175
|
+
# Setter for the LLDP enabled capability.
|
176
|
+
def lldp_enabled_capability=(i); typecast i; end
|
177
|
+
|
178
|
+
# Setter for the LLDP address type.
|
179
|
+
def lldp_address_type=(i); typecast i; end
|
180
|
+
# Getter for the LLDP address type.
|
181
|
+
def lldp_address_type; self[:lldp_address_type].to_i; end
|
182
|
+
# Setter for the LLDP interface type.
|
183
|
+
def lldp_interface_type=(i); typecast i; end
|
184
|
+
# Getter for the LLDP interface type.
|
185
|
+
def lldp_interface_type; self[:lldp_interface_type].to_i; end
|
186
|
+
# Setter for the LLDP interface.
|
187
|
+
def lldp_interface=(i); typecast i; end
|
188
|
+
# Getter for the LLDP interface type.
|
189
|
+
def lldp_interface; self[:lldp_interface].to_i; end
|
190
|
+
# Setter for the LLDP oid.
|
191
|
+
def lldp_oid=(i); typecast i; end
|
192
|
+
# Getter for the LLDP oid type.
|
193
|
+
def lldp_oid; self[:lldp_oid].to_i; end
|
194
|
+
|
195
|
+
|
196
|
+
# Get a more readable source MAC address.
|
197
|
+
def lldp_saddr_mac
|
198
|
+
EthHeader.str2mac(self[:lldp_port_id].to_s)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Set a more readable source IP address.
|
202
|
+
def lldp_saddr_ip=(addr)
|
203
|
+
self[:lldp_address_type] = 1
|
204
|
+
self[:lldp_address].read_quad(addr)
|
205
|
+
end
|
206
|
+
|
207
|
+
# Get a more readable source IP address.
|
208
|
+
def lldp_saddr_ip
|
209
|
+
#ipv4 or ipv6
|
210
|
+
if (self[:lldp_address_type].to_i == 1) or (self[:lldp_address_type].to_i == 2)
|
211
|
+
begin
|
212
|
+
IPAddr::ntop(self[:lldp_address])
|
213
|
+
rescue
|
214
|
+
self[:lldp_address]
|
215
|
+
end
|
216
|
+
elsif self[:lldp_address_type].to_i == 6
|
217
|
+
#mac
|
218
|
+
EthHeader.str2mac(self[:lldp_address].to_s)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def lldp_address_type_readable
|
223
|
+
case lldp_address_type
|
224
|
+
when 1
|
225
|
+
"IPv4"
|
226
|
+
when 2
|
227
|
+
"IPv6"
|
228
|
+
when 6
|
229
|
+
"MAC"
|
230
|
+
else
|
231
|
+
lldp_address_type
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def lldp_capabilty_readable
|
236
|
+
"0x%04x" % lldp_capabilty
|
237
|
+
end
|
238
|
+
|
239
|
+
def lldp_enabled_capability_readable
|
240
|
+
"0x%04x" % lldp_enabled_capability
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
# Readability aliases
|
245
|
+
|
246
|
+
alias :lldp_chassis_id :lldp_saddr_mac
|
247
|
+
alias :lldp_address :lldp_saddr_ip
|
248
|
+
|
249
|
+
end # class LLDPHeader
|
250
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module PacketFu
|
2
|
+
# This Mixin simplifies access to the LLDPHeaders. Mix this in with your
|
3
|
+
# packet interface, and it will add methods that essentially delegate to
|
4
|
+
# the 'lldp_header' method (assuming that it is a LLDPHeader object)
|
5
|
+
module LLDPHeaderMixin
|
6
|
+
def lldp_chassis_id_type=(v); self.lldp_header.lldp_chassis_id_type= v; end
|
7
|
+
def lldp_chassis_id_type; self.lldp_header.lldp_chassis_id_type; end
|
8
|
+
def lldp_chassis_id=(v); self.lldp_header.lldp_chassis_id= v; end
|
9
|
+
def lldp_chassis_id; self.lldp_header.lldp_chassis_id_readable(); end
|
10
|
+
|
11
|
+
def lldp_port_id_type=(v); self.lldp_header.lldp_port_id_type= v; end
|
12
|
+
def lldp_port_id_type; self.lldp_header.lldp_port_id_type; end
|
13
|
+
def lldp_port_id=(v); self.lldp_header.lldp_port_id= v; end
|
14
|
+
def lldp_port_id; self.lldp_header.lldp_port_id_readable(); end
|
15
|
+
|
16
|
+
def lldp_ttl=(v); self.lldp_header.lldp_ttl= v; end
|
17
|
+
def lldp_ttl; self.lldp_header.lldp_ttl; end
|
18
|
+
|
19
|
+
def lldp_port_description=(v); self.lldp_header.lldp_port_description= v; end
|
20
|
+
def lldp_port_description; self.lldp_header.lldp_port_description; end
|
21
|
+
|
22
|
+
def lldp_system_name=(v); self.lldp_header.lldp_system_name= v; end
|
23
|
+
def lldp_system_name; self.lldp_header.lldp_system_name; end
|
24
|
+
|
25
|
+
def lldp_system_description=(v); self.lldp_header.lldp_system_description= v; end
|
26
|
+
def lldp_system_description; self.lldp_header.lldp_system_description; end
|
27
|
+
|
28
|
+
def lldp_capabilty=(v); self.lldp_header.lldp_capabilty= v; end
|
29
|
+
def lldp_capabilty; self.lldp_header.lldp_capabilty_readable(); end
|
30
|
+
|
31
|
+
def lldp_enabled_capability=(v); self.lldp_header.lldp_enabled_capability= v; end
|
32
|
+
def lldp_enabled_capability; self.lldp_header.lldp_enabled_capability_readable(); end
|
33
|
+
|
34
|
+
def lldp_address_type=(v); self.lldp_header.lldp_address_type= v; end
|
35
|
+
def lldp_address_type; self.lldp_header.lldp_address_type; end
|
36
|
+
|
37
|
+
def lldp_address=(v); self.lldp_header.lldp_saddr_ip= v; end
|
38
|
+
def lldp_address; self.lldp_header.lldp_saddr_ip(); end
|
39
|
+
|
40
|
+
def lldp_interface_type=(v); self.lldp_header.lldp_interface_type= v; end
|
41
|
+
def lldp_interface_type; self.lldp_header.lldp_interface_type; end
|
42
|
+
|
43
|
+
def lldp_interface=(v); self.lldp_header.lldp_interface= v; end
|
44
|
+
def lldp_interface; self.lldp_header.lldp_interface; end
|
45
|
+
|
46
|
+
def lldp_oid=(v); self.lldp_header.lldp_oid= v; end
|
47
|
+
def lldp_oid; self.lldp_header.lldp_oid; end
|
48
|
+
|
49
|
+
def lldp_saddr_mac=(v); self.lldp_header.lldp_saddr_mac= v; end
|
50
|
+
def lldp_saddr_mac; self.lldp_header.lldp_saddr_mac; end
|
51
|
+
def lldp_saddr_ip=(v); self.lldp_header.lldp_saddr_ip= v; end
|
52
|
+
def lldp_saddr_ip; self.lldp_header.lldp_saddr_ip(); end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
data/lib/packetfu/utils.rb
CHANGED
@@ -53,6 +53,12 @@ module PacketFu
|
|
53
53
|
cap_thread.value
|
54
54
|
end
|
55
55
|
|
56
|
+
# Since 177/8 is IANA reserved (for now), this network should
|
57
|
+
# be handled by your default gateway and default interface.
|
58
|
+
def self.rand_routable_daddr
|
59
|
+
IPAddr.new((rand(16777216) + 2969567232), Socket::AF_INET)
|
60
|
+
end
|
61
|
+
|
56
62
|
# Discovers the local IP and Ethernet address, which is useful for writing
|
57
63
|
# packets you expect to get a response to. Note, this is a noisy
|
58
64
|
# operation; a UDP packet is generated and dropped on to the default (or named)
|
@@ -74,8 +80,6 @@ module PacketFu
|
|
74
80
|
# you will need to specify a target which will use this interface.
|
75
81
|
# :target => "1.2.3.4"
|
76
82
|
# A target IP address. By default, a packet will be sent to a random address in the 177/8 network.
|
77
|
-
# Since this network is IANA reserved (for now), this network should be handled by your default gateway
|
78
|
-
# and default interface.
|
79
83
|
def self.whoami?(args={})
|
80
84
|
unless args.kind_of? Hash
|
81
85
|
raise ArgumentError, "Argument to `whoami?' must be a Hash"
|
@@ -83,7 +87,7 @@ module PacketFu
|
|
83
87
|
if args[:iface].to_s =~ /^lo/ # Linux loopback more or less. Need a switch for windows loopback, too.
|
84
88
|
dst_host = "127.0.0.1"
|
85
89
|
else
|
86
|
-
dst_host = (args[:target] ||
|
90
|
+
dst_host = (args[:target] || rand_routable_daddr.to_s)
|
87
91
|
end
|
88
92
|
|
89
93
|
dst_port = rand(0xffff-1024)+1024
|
data/lib/packetfu/version.rb
CHANGED
data/packetfu.gemspec
CHANGED
@@ -2,20 +2,20 @@ require 'rake'
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'packetfu'
|
5
|
-
s.version = '1.1.
|
5
|
+
s.version = '1.1.8'
|
6
6
|
s.authors = ['Tod Beardsley']
|
7
7
|
s.email = 'todb@packetfu.com'
|
8
8
|
s.summary = 'PacketFu is a mid-level packet manipulation library.'
|
9
9
|
s.homepage = 'https://github.com/todb/packetfu'
|
10
10
|
s.description = %q{PacketFu is a mid-level packet manipulation library for Ruby. With it, users can read, parse, and write network packets with the level of ease and fun they expect from Ruby. Note that this gem does not automatically require pcaprub, since users may install pcaprub through non-gem means.}
|
11
11
|
s.files = `git ls-files`.split($/)
|
12
|
-
|
12
|
+
s.license = 'BSD'
|
13
13
|
|
14
14
|
s.add_development_dependency('pcaprub', '>= 0.9.2')
|
15
15
|
s.add_development_dependency('rspec', '>= 2.6.2')
|
16
16
|
s.add_development_dependency('sdoc', '>= 0.2.0')
|
17
17
|
|
18
18
|
s.extra_rdoc_files = %w[.document README.rdoc]
|
19
|
-
s.test_files = (s.files & Dir['test/test_*.rb'])
|
19
|
+
s.test_files = (s.files & (Dir['spec/**/*_spec.rb'] + Dir['test/test_*.rb']) )
|
20
20
|
s.rubyforge_project = 'packetfu'
|
21
21
|
end
|
@@ -6,7 +6,7 @@ include PacketFu
|
|
6
6
|
describe EthPacket, "when read from a pcap file" do
|
7
7
|
|
8
8
|
before :all do
|
9
|
-
parsed_packets = PcapFile.read_packets(File.join(
|
9
|
+
parsed_packets = PcapFile.read_packets(File.join(File.dirname(__FILE__),"sample.pcap"))
|
10
10
|
@eth_packet = parsed_packets.first
|
11
11
|
end
|
12
12
|
|
@@ -61,7 +61,7 @@ describe EthPacket, "when read from a pcap file" do
|
|
61
61
|
context "isn't a regular Ethernet packet" do
|
62
62
|
|
63
63
|
subject {
|
64
|
-
parsed_packets = PcapFile.read_packets(File.join(
|
64
|
+
parsed_packets = PcapFile.read_packets(File.join(File.dirname(__FILE__),"vlan-pcapr.cap"))
|
65
65
|
parsed_packets.first
|
66
66
|
}
|
67
67
|
|
File without changes
|
File without changes
|
@@ -1,16 +1,11 @@
|
|
1
1
|
$:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
|
2
2
|
require 'packetfu'
|
3
3
|
|
4
|
-
unless %x{#{$0} --version} =~ /^2\.6/
|
5
|
-
puts "PacketFu needs rspec 2.6 or so."
|
6
|
-
exit 1
|
7
|
-
end
|
8
|
-
|
9
4
|
describe PacketFu, "version information" do
|
10
5
|
it "reports a version number" do
|
11
6
|
PacketFu::VERSION.should match /^1\.[0-9]\.[0-9]$/
|
12
7
|
end
|
13
|
-
its(:version) {should eq PacketFu::VERSION}
|
8
|
+
its(:version) {should eq PacketFu::VERSION}
|
14
9
|
|
15
10
|
it "can compare version strings" do
|
16
11
|
PacketFu.binarize_version("1.2.3").should == 0x010203
|
data/spec/sample.pcap
ADDED
Binary file
|
data/spec/sample2.pcap
ADDED
Binary file
|
File without changes
|
data/{test → spec}/tcp_spec.rb
RENAMED
data/spec/vlan-pcapr.cap
ADDED
Binary file
|
data/test/func_lldp.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# Functional test script contributed by @dmaciejak
|
4
|
+
# Still need a real test set.
|
5
|
+
$:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
|
6
|
+
require 'packetfu'
|
7
|
+
|
8
|
+
def lldp_pcap
|
9
|
+
fname = "./sample_lldp.pcap"
|
10
|
+
fname if File.readable? fname
|
11
|
+
end
|
12
|
+
|
13
|
+
def lldp_test()
|
14
|
+
raise RuntimeError, "Need a sample_lldp.pcap to check!" unless lldp_pcap
|
15
|
+
cap = PacketFu::PcapFile.new.file_to_array(:filename => lldp_pcap)
|
16
|
+
cap.each do |p|
|
17
|
+
pkt = PacketFu::Packet.parse p
|
18
|
+
if pkt.is_lldp?
|
19
|
+
packet_info = [pkt.proto.last, pkt.lldp_capabilty, pkt.lldp_address_type_readable, pkt.lldp_address, pkt.lldp_interface_type, pkt.lldp_interface]
|
20
|
+
puts "%s | %15s | %15s | %15s | %15s | %15s |" % packet_info
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
lldp_test()
|
Binary file
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'test/unit'
|
3
|
+
$:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
|
4
|
+
require 'packetfu'
|
5
|
+
|
6
|
+
|
7
|
+
class CaptureTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
def test_cap
|
10
|
+
assert_nothing_raised { PacketFu::Capture }
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_whoami
|
14
|
+
assert_nothing_raised { PacketFu::Utils.whoami?(:iface => (ENV['IFACE'] || 'lo')) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_new
|
18
|
+
cap = PacketFu::Capture.new
|
19
|
+
assert_kind_of PacketFu::Capture, cap
|
20
|
+
cap = PacketFu::Capture.new(
|
21
|
+
:filter => 'tcp and dst host 1.2.3.4'
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_filter
|
26
|
+
daddr = PacketFu::Utils.rand_routable_daddr.to_s
|
27
|
+
cap = PacketFu::Capture.new( :filter => "icmp and dst host #{daddr}")
|
28
|
+
cap.start
|
29
|
+
%x{ping -c 1 #{daddr}}
|
30
|
+
sleep 1
|
31
|
+
cap.save
|
32
|
+
assert cap.array.size == 1
|
33
|
+
pkt = PacketFu::Packet.parse(cap.array.first)
|
34
|
+
assert pkt.ip_daddr == daddr
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_no_filter
|
38
|
+
daddr = PacketFu::Utils.rand_routable_daddr.to_s
|
39
|
+
daddr2 = PacketFu::Utils.rand_routable_daddr.to_s
|
40
|
+
cap = PacketFu::Capture.new
|
41
|
+
cap.start
|
42
|
+
%x{ping -c 1 #{daddr}}
|
43
|
+
%x{ping -c 1 #{daddr2}}
|
44
|
+
sleep 1
|
45
|
+
cap.save
|
46
|
+
assert cap.array.size > 1
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_bpf_alias
|
50
|
+
daddr = PacketFu::Utils.rand_routable_daddr.to_s
|
51
|
+
cap = PacketFu::Capture.new( :filter => "icmp and dst host #{daddr}")
|
52
|
+
assert cap.filter.object_id == cap.bpf.object_id
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
|
data/test/test_icmp.rb
CHANGED
@@ -44,11 +44,19 @@ class ICMPTest < Test::Unit::TestCase
|
|
44
44
|
def test_icmp_read
|
45
45
|
sample_packet = PcapFile.new.file_to_array(:f => 'sample.pcap')[2]
|
46
46
|
pkt = Packet.parse(sample_packet)
|
47
|
+
assert pkt.is_icmp?
|
47
48
|
assert_kind_of ICMPPacket, pkt
|
48
49
|
assert_equal(0x4d58, pkt.icmp_sum.to_i)
|
49
50
|
assert_equal(8, pkt.icmp_type.to_i)
|
50
51
|
end
|
51
52
|
|
53
|
+
def test_icmp_reread
|
54
|
+
sample_packet = PacketFu::ICMPPacket.new
|
55
|
+
pkt = Packet.parse(sample_packet.to_s)
|
56
|
+
assert sample_packet.is_icmp?
|
57
|
+
assert pkt.is_icmp?
|
58
|
+
end
|
59
|
+
|
52
60
|
end
|
53
61
|
|
54
62
|
# vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
|
data/test/test_tcp.rb
CHANGED
@@ -85,6 +85,18 @@ class TcpFlagsTest < Test::Unit::TestCase
|
|
85
85
|
assert_equal(0x12, t.to_i)
|
86
86
|
end
|
87
87
|
|
88
|
+
def test_tcp_flags_unset
|
89
|
+
t = TcpFlags.new
|
90
|
+
assert_kind_of TcpFlags, t
|
91
|
+
t.syn = 1
|
92
|
+
assert_equal(0x02, t.to_i)
|
93
|
+
t.syn = 0
|
94
|
+
assert_equal(0x00, t.to_i)
|
95
|
+
t.syn = 1
|
96
|
+
t.syn = false
|
97
|
+
assert_equal(0x00, t.to_i)
|
98
|
+
end
|
99
|
+
|
88
100
|
def test_tcp_flags_read
|
89
101
|
t = TcpFlags.new
|
90
102
|
t.read("\x11")
|
@@ -312,6 +324,14 @@ class TCPPacketTest < Test::Unit::TestCase
|
|
312
324
|
stripped.read(str, :strip => true)
|
313
325
|
assert_equal 16, stripped.tcp_header.body.length
|
314
326
|
end
|
327
|
+
|
328
|
+
def test_tcp_reread
|
329
|
+
sample_packet = PacketFu::TCPPacket.new
|
330
|
+
pkt = Packet.parse(sample_packet.to_s)
|
331
|
+
assert sample_packet.is_tcp?
|
332
|
+
assert pkt.is_tcp?
|
333
|
+
end
|
334
|
+
|
315
335
|
end
|
316
336
|
|
317
337
|
class TCPPacketTest < Test::Unit::TestCase
|
data/test/test_udp.rb
CHANGED
@@ -85,6 +85,14 @@ class UDPTest < Test::Unit::TestCase
|
|
85
85
|
pkt.to_f('udp_test.pcap','a')
|
86
86
|
end
|
87
87
|
|
88
|
+
def test_udp_reread
|
89
|
+
sample_packet = PacketFu::UDPPacket.new
|
90
|
+
pkt = Packet.parse(sample_packet.to_s)
|
91
|
+
assert sample_packet.is_udp?
|
92
|
+
assert pkt.is_udp?
|
93
|
+
end
|
94
|
+
|
95
|
+
|
88
96
|
end
|
89
97
|
|
90
98
|
# vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetfu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-06-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pcaprub
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: 0.9.2
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.9.2
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rspec
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: 2.6.2
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.6.2
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: sdoc
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,7 +53,12 @@ dependencies:
|
|
43
53
|
version: 0.2.0
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.2.0
|
47
62
|
description: PacketFu is a mid-level packet manipulation library for Ruby. With it,
|
48
63
|
users can read, parse, and write network packets with the level of ease and fun
|
49
64
|
they expect from Ruby. Note that this gem does not automatically require pcaprub,
|
@@ -57,9 +72,11 @@ extra_rdoc_files:
|
|
57
72
|
files:
|
58
73
|
- .document
|
59
74
|
- .gitignore
|
75
|
+
- .mailmap
|
60
76
|
- INSTALL.rdoc
|
61
77
|
- LICENSE.txt
|
62
78
|
- README.rdoc
|
79
|
+
- Rakefile
|
63
80
|
- bench/after-2012-07-28.txt
|
64
81
|
- bench/before-2012-07-28.txt
|
65
82
|
- bench/benchit.rb
|
@@ -110,6 +127,9 @@ files:
|
|
110
127
|
- lib/packetfu/protos/ipv6.rb
|
111
128
|
- lib/packetfu/protos/ipv6/header.rb
|
112
129
|
- lib/packetfu/protos/ipv6/mixin.rb
|
130
|
+
- lib/packetfu/protos/lldp.rb
|
131
|
+
- lib/packetfu/protos/lldp/header.rb
|
132
|
+
- lib/packetfu/protos/lldp/mixin.rb
|
113
133
|
- lib/packetfu/protos/tcp.rb
|
114
134
|
- lib/packetfu/protos/tcp/ecn.rb
|
115
135
|
- lib/packetfu/protos/tcp/flags.rb
|
@@ -127,19 +147,25 @@ files:
|
|
127
147
|
- lib/packetfu/version.rb
|
128
148
|
- packetfu.gemspec
|
129
149
|
- setup.rb
|
150
|
+
- spec/ethpacket_spec.rb
|
151
|
+
- spec/packet_spec.rb
|
152
|
+
- spec/packet_subclasses_spec.rb
|
153
|
+
- spec/packetfu_spec.rb
|
154
|
+
- spec/sample.pcap
|
155
|
+
- spec/sample2.pcap
|
156
|
+
- spec/structfu_spec.rb
|
157
|
+
- spec/tcp_spec.rb
|
158
|
+
- spec/vlan-pcapr.cap
|
130
159
|
- test/all_tests.rb
|
131
|
-
- test/
|
132
|
-
- test/packet_spec.rb
|
133
|
-
- test/packet_subclasses_spec.rb
|
134
|
-
- test/packetfu_spec.rb
|
160
|
+
- test/func_lldp.rb
|
135
161
|
- test/ptest.rb
|
136
162
|
- test/sample-ipv6.pcap
|
137
163
|
- test/sample.pcap
|
138
164
|
- test/sample2.pcap
|
139
165
|
- test/sample_hsrp_pcapr.cap
|
140
|
-
- test/
|
141
|
-
- test/tcp_spec.rb
|
166
|
+
- test/sample_lldp.pcap
|
142
167
|
- test/test_arp.rb
|
168
|
+
- test/test_capture.rb
|
143
169
|
- test/test_eth.rb
|
144
170
|
- test/test_hsrp.rb
|
145
171
|
- test/test_icmp.rb
|
@@ -175,12 +201,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
175
201
|
version: '0'
|
176
202
|
requirements: []
|
177
203
|
rubyforge_project: packetfu
|
178
|
-
rubygems_version: 1.8.
|
204
|
+
rubygems_version: 1.8.25
|
179
205
|
signing_key:
|
180
206
|
specification_version: 3
|
181
207
|
summary: PacketFu is a mid-level packet manipulation library.
|
182
208
|
test_files:
|
209
|
+
- spec/ethpacket_spec.rb
|
210
|
+
- spec/packet_spec.rb
|
211
|
+
- spec/packet_subclasses_spec.rb
|
212
|
+
- spec/packetfu_spec.rb
|
213
|
+
- spec/structfu_spec.rb
|
214
|
+
- spec/tcp_spec.rb
|
183
215
|
- test/test_arp.rb
|
216
|
+
- test/test_capture.rb
|
184
217
|
- test/test_eth.rb
|
185
218
|
- test/test_hsrp.rb
|
186
219
|
- test/test_icmp.rb
|