packetfu 1.0.2.pre → 1.0.3.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/dissect_thinger.rb +22 -0
- data/lib/packetfu.rb +7 -0
- data/lib/packetfu/packet.rb +136 -9
- data/lib/packetfu/pcap.rb +4 -3
- data/lib/packetfu/protos/arp.rb +14 -3
- data/lib/packetfu/protos/eth.rb +9 -0
- data/lib/packetfu/protos/hsrp.rb +13 -7
- data/lib/packetfu/protos/icmp.rb +8 -2
- data/lib/packetfu/protos/ip.rb +15 -2
- data/lib/packetfu/protos/ipv6.rb +6 -1
- data/lib/packetfu/protos/tcp.rb +35 -9
- data/lib/packetfu/protos/udp.rb +8 -2
- data/lib/packetfu/structfu.rb +5 -0
- data/lib/packetfu/version.rb +2 -3
- data/test/dissect_thinger.rb +15 -0
- data/test/icmp_test.pcap +0 -0
- data/test/ip_test.pcap +0 -0
- data/test/packet_spec.rb +72 -0
- data/test/packet_subclasses_spec.rb +12 -0
- data/test/packetfu_spec.rb +23 -9
- data/test/ptest.rb +7 -1
- data/test/structfu_spec.rb +0 -4
- data/test/tcp_test.pcap +0 -0
- data/test/udp_test.pcap +0 -0
- metadata +7 -3
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This just allows you to eyeball the dissection stuff to make sure it's all right.
|
3
|
+
# Some day, there will be a proper test for it.
|
4
|
+
|
5
|
+
fname = ARGV[0] || "../test/sample.pcap"
|
6
|
+
sleep_interval = ARGV[1] || 1
|
7
|
+
|
8
|
+
require File.join("..","lib","packetfu")
|
9
|
+
puts "Loaded: PacketFu v#{PacketFu.version}"
|
10
|
+
# $: << File.join(File.expand_path(File.dirname(__FILE__)),"..","lib")
|
11
|
+
|
12
|
+
include PacketFu
|
13
|
+
|
14
|
+
packets = PcapFile.file_to_array fname
|
15
|
+
packets.each do |packet|
|
16
|
+
puts "_" * 75
|
17
|
+
puts packet.inspect
|
18
|
+
puts "_" * 75
|
19
|
+
pkt = Packet.parse(packet)
|
20
|
+
puts pkt.dissect
|
21
|
+
sleep sleep_interval
|
22
|
+
end
|
data/lib/packetfu.rb
CHANGED
@@ -60,6 +60,13 @@ module PacketFu
|
|
60
60
|
@packet_classes.sort! {|x,y| x.name <=> y.name}
|
61
61
|
end
|
62
62
|
|
63
|
+
def self.remove_packet_class(klass)
|
64
|
+
raise "Need a class" unless klass.kind_of? Class
|
65
|
+
@packet_classes ||= []
|
66
|
+
@packet_classes.delete klass
|
67
|
+
@packet_classes
|
68
|
+
end
|
69
|
+
|
63
70
|
def self.packet_classes
|
64
71
|
@packet_classes || []
|
65
72
|
end
|
data/lib/packetfu/packet.rb
CHANGED
@@ -162,11 +162,71 @@ module PacketFu
|
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
165
|
+
# Packets are bundles of lots of objects, so copying them
|
166
|
+
# is a little complicated -- a dup of a packet is actually
|
167
|
+
# full of pass-by-reference stuff in the @headers, so
|
168
|
+
# if you change one, you're changing all this copies, too.
|
169
|
+
#
|
170
|
+
# Normally, this doesn't seem to be a big deal, and it's
|
171
|
+
# a pretty decent performance tradeoff. But, if you're going
|
172
|
+
# to be creating a template packet to base a bunch of slightly
|
173
|
+
# different ones off of (like a fuzzer might), you'll want
|
174
|
+
# to use clone()
|
175
|
+
def clone
|
176
|
+
Marshal.load(Marshal.dump(self))
|
177
|
+
end
|
178
|
+
|
179
|
+
# If two packets are represented as the same binary string, and
|
180
|
+
# they're both actually PacketFu packets of the same sort, they're equal.
|
181
|
+
#
|
182
|
+
# The intuitive result is that a packet of a higher layer (like DNSPacket)
|
183
|
+
# can be equal to a packet of a lower level (like UDPPacket) as long as
|
184
|
+
# the bytes are equal (this can come up if a transport-layer packet has
|
185
|
+
# a hand-crafted payload that is identical to what would have been created
|
186
|
+
# by using an application layer packet)
|
187
|
+
def ==(other)
|
188
|
+
return false unless other.kind_of? self.class
|
189
|
+
return false unless other.respond_to? :to_s
|
190
|
+
self.to_s == other.to_s
|
191
|
+
end
|
192
|
+
|
165
193
|
# Peek provides summary data on packet contents.
|
166
|
-
#
|
167
|
-
#
|
194
|
+
#
|
195
|
+
# Each packet type should provide a peek_format.
|
168
196
|
def peek(args={})
|
169
|
-
|
197
|
+
idx = @headers.reverse.map {|h| h.respond_to? peek_format}.index(true)
|
198
|
+
if idx
|
199
|
+
@headers.reverse[idx].peek_format
|
200
|
+
else
|
201
|
+
peek_format
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# The peek_format is used to display a single line
|
206
|
+
# of packet data useful for eyeballing. It should not exceed
|
207
|
+
# 80 characters. The Packet superclass defines an example
|
208
|
+
# peek_format, but it should hardly ever be triggered, since
|
209
|
+
# peek traverses the @header list in reverse to find a suitable
|
210
|
+
# format.
|
211
|
+
#
|
212
|
+
# == Format
|
213
|
+
#
|
214
|
+
# * A one or two character protocol initial. It should be unique
|
215
|
+
# * The packet size
|
216
|
+
# * Useful data in a human-usable form.
|
217
|
+
#
|
218
|
+
# Ideally, related peek_formats will all line up with each other
|
219
|
+
# when printed to the screen.
|
220
|
+
#
|
221
|
+
# == Example
|
222
|
+
#
|
223
|
+
# tcp_packet.peek
|
224
|
+
# #=> "T 1054 10.10.10.105:55000 -> 192.168.145.105:80 [......] S:adc7155b|I:8dd0"
|
225
|
+
# tcp_packet.peek.size
|
226
|
+
# #=> 79
|
227
|
+
#
|
228
|
+
def peek_format
|
229
|
+
peek_data = ["? "]
|
170
230
|
peek_data << "%-5d" % self.to_s.size
|
171
231
|
peek_data << "%68s" % self.to_s[0,34].unpack("H*")[0]
|
172
232
|
peek_data.join
|
@@ -281,6 +341,67 @@ module PacketFu
|
|
281
341
|
end
|
282
342
|
end
|
283
343
|
|
344
|
+
def dissection_table
|
345
|
+
table = []
|
346
|
+
@headers.each_with_index do |header,table_idx|
|
347
|
+
proto = header.class.name.sub(/^.*::/,"")
|
348
|
+
table << [proto]
|
349
|
+
header.class.members.each do |elem|
|
350
|
+
elem_sym = RUBY_VERSION[/^1\.8/] ? elem.to_sym : elem
|
351
|
+
next if elem_sym == :body
|
352
|
+
elem_type_value = []
|
353
|
+
elem_type_value[0] = elem
|
354
|
+
readable_element = "#{elem}_readable"
|
355
|
+
if header.respond_to? readable_element
|
356
|
+
elem_type_value[1] = header.send(readable_element)
|
357
|
+
else
|
358
|
+
elem_type_value[1] = header.send(elem)
|
359
|
+
end
|
360
|
+
elem_type_value[2] = header[elem.to_sym].class.name
|
361
|
+
table[table_idx] ||= []
|
362
|
+
table[table_idx] << elem_type_value
|
363
|
+
end
|
364
|
+
end
|
365
|
+
table
|
366
|
+
end
|
367
|
+
|
368
|
+
# Renders the dissection_table suitable for screen printing. Can take
|
369
|
+
# one or two arguments. If just the one, only that layer will be displayed
|
370
|
+
# take either a range or a number -- if a range, only protos within
|
371
|
+
# that range will be rendered. If an integer, only that proto
|
372
|
+
# will be rendered.
|
373
|
+
def dissect(min=nil,max=nil)
|
374
|
+
table = self.dissection_table
|
375
|
+
widest = (0..2).map {|i| table.map {|x| x.map {|y| y[i].size}}.flatten.sort.last}
|
376
|
+
table_formatted = ""
|
377
|
+
begin
|
378
|
+
if min
|
379
|
+
layer_min = min.to_i
|
380
|
+
layer_max = max ? max.to_i : layer_min
|
381
|
+
table_range = (layer_min..layer_max)
|
382
|
+
else
|
383
|
+
layer_min = min
|
384
|
+
end
|
385
|
+
rescue => e
|
386
|
+
raise ArgumentError, "Method `dissect' accepts one or two to_i-able arguments"
|
387
|
+
end
|
388
|
+
header_line_width = widest.inject {|sum,i| sum ? sum + i : i} + 2
|
389
|
+
table.each_with_index do |proto_table,proto_idx|
|
390
|
+
if layer_min
|
391
|
+
next unless table_range.member? proto_idx
|
392
|
+
end
|
393
|
+
table_formatted << "--#{proto_table.first}"
|
394
|
+
table_formatted << "-" * (header_line_width - proto_table.first.size) << "\n"
|
395
|
+
proto_table[1,proto_table.size].each do |elem,value,type|
|
396
|
+
table_formatted << " %-#{widest[0]}s " % elem
|
397
|
+
table_formatted << "%-#{widest[1]}s " % value.to_s
|
398
|
+
table_formatted << type << "\n"
|
399
|
+
end
|
400
|
+
end
|
401
|
+
table_formatted << ("-" * header_line_width)
|
402
|
+
table_formatted
|
403
|
+
end
|
404
|
+
|
284
405
|
alias :orig_kind_of? :kind_of?
|
285
406
|
|
286
407
|
def kind_of?(klass)
|
@@ -330,7 +451,13 @@ module PacketFu
|
|
330
451
|
alias_method :protocol, :proto
|
331
452
|
alias_method :length, :size
|
332
453
|
|
454
|
+
# the Packet class should not be instantiated directly, since it's an
|
455
|
+
# abstract class that real packet types inherit from. Sadly, this
|
456
|
+
# makes the Packet class more difficult to test directly.
|
333
457
|
def initialize(args={})
|
458
|
+
if self.class.name =~ /(::|^)PacketFu::Packet$/
|
459
|
+
raise NoMethodError, "method `new' called for abstract class #{self.class.name}"
|
460
|
+
end
|
334
461
|
if args[:config]
|
335
462
|
args[:config].each_pair do |k,v|
|
336
463
|
case k
|
@@ -385,10 +512,10 @@ module PacketFu
|
|
385
512
|
|
386
513
|
end # class Packet
|
387
514
|
|
388
|
-
|
515
|
+
@inspect_style = :pretty
|
389
516
|
|
390
|
-
# If
|
391
|
-
# By default,
|
517
|
+
# If @inspect_style is :ugly, set the inspect method to the usual inspect.
|
518
|
+
# By default, @inspect_style is :pretty. This default may change if people
|
392
519
|
# hate it.
|
393
520
|
# Since PacketFu is designed with irb in mind, the normal inspect is way too
|
394
521
|
# verbose when new packets are created, and it ruins the aesthetics of the
|
@@ -416,12 +543,12 @@ module PacketFu
|
|
416
543
|
# => #<PacketFu::TCPPacket:0xb7aaf96c @ip_header=#<struct PacketFu::IPHeader ip_v=4, ip_hl=5, ip_tos=#<struct StructFu::Int8 value=nil, endian=nil, width=1, default=0>, ip_len=#<struct StructFu::Int16 value=20, endian=:big, width=2, default=0>, ip_id=#<struct StructFu::Int16 value=58458, endian=:big, width=2, default=0>, ip_frag=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, ip_ttl=#<struct StructFu::Int8 value=32, endian=nil, width=1, default=0>, ip_proto=#<struct StructFu::Int8 value=6, endian=nil, width=1, default=0>, ip_sum=#<struct StructFu::Int16 value=65535, endian=:big, width=2, default=0>, ip_src=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, ip_dst=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, body=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">>, @tcp_header=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">, @eth_header=#<struct PacketFu::EthHeader eth_dst=#<struct PacketFu::EthMac oui=#<struct PacketFu::EthOui b0=nil, b1=nil, b2=nil, b3=nil, b4=nil, b5=nil, local=0, multicast=nil, oui=428>, nic=#<struct PacketFu::EthNic n0=nil, n1=nil, n2=nil>>, eth_src=#<struct PacketFu::EthMac oui=#<struct PacketFu::EthOui b0=nil, b1=nil, b2=nil, b3=nil, b4=nil, b5=nil, local=0, multicast=nil, oui=428>, nic=#<struct PacketFu::EthNic n0=nil, n1=nil, n2=nil>>, eth_proto=#<struct StructFu::Int16 value=2048, endian=:big, width=2, default=0>, body=#<struct PacketFu::IPHeader ip_v=4, ip_hl=5, ip_tos=#<struct StructFu::Int8 value=nil, endian=nil, width=1, default=0>, ip_len=#<struct StructFu::Int16 value=20, endian=:big, width=2, default=0>, ip_id=#<struct StructFu::Int16 value=58458, endian=:big, width=2, default=0>, ip_frag=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, ip_ttl=#<struct StructFu::Int8 value=32, endian=nil, width=1, default=0>, ip_proto=#<struct StructFu::Int8 value=6, endian=nil, width=1, default=0>, ip_sum=#<struct StructFu::Int16 value=65535, endian=:big, width=2, default=0>, ip_src=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, ip_dst=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, body=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">>>, @headers=[#<struct PacketFu::EthHeader eth_dst=#<struct PacketFu::EthMac oui=#<struct PacketFu::EthOui b0=nil, b1=nil, b2=nil, b3=nil, b4=nil, b5=nil, local=0, multicast=nil, oui=428>, nic=#<struct PacketFu::EthNic n0=nil, n1=nil, n2=nil>>, eth_src=#<struct PacketFu::EthMac oui=#<struct PacketFu::EthOui b0=nil, b1=nil, b2=nil, b3=nil, b4=nil, b5=nil, local=0, multicast=nil, oui=428>, nic=#<struct PacketFu::EthNic n0=nil, n1=nil, n2=nil>>, eth_proto=#<struct StructFu::Int16 value=2048, endian=:big, width=2, default=0>, body=#<struct PacketFu::IPHeader ip_v=4, ip_hl=5, ip_tos=#<struct StructFu::Int8 value=nil, endian=nil, width=1, default=0>, ip_len=#<struct StructFu::Int16 value=20, endian=:big, width=2, default=0>, ip_id=#<struct StructFu::Int16 value=58458, endian=:big, width=2, default=0>, ip_frag=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, ip_ttl=#<struct StructFu::Int8 value=32, endian=nil, width=1, default=0>, ip_proto=#<struct StructFu::Int8 value=6, endian=nil, width=1, default=0>, ip_sum=#<struct StructFu::Int16 value=65535, endian=:big, width=2, default=0>, ip_src=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, ip_dst=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, body=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">>>, #<struct PacketFu::IPHeader ip_v=4, ip_hl=5, ip_tos=#<struct StructFu::Int8 value=nil, endian=nil, width=1, default=0>, ip_len=#<struct StructFu::Int16 value=20, endian=:big, width=2, default=0>, ip_id=#<struct StructFu::Int16 value=58458, endian=:big, width=2, default=0>, ip_frag=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, ip_ttl=#<struct StructFu::Int8 value=32, endian=nil, width=1, default=0>, ip_proto=#<struct StructFu::Int8 value=6, endian=nil, width=1, default=0>, ip_sum=#<struct StructFu::Int16 value=65535, endian=:big, width=2, default=0>, ip_src=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, ip_dst=#<struct PacketFu::Octets o1=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o2=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o3=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>, o4=#<struct StructFu::Int8 value=0, endian=nil, width=1, default=0>>, body=#<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">>, #<struct PacketFu::TCPHeader tcp_src=#<struct StructFu::Int16 value=17222, endian=:big, width=2, default=0>, tcp_dst=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_seq=#<struct StructFu::Int32 value=1528113240, endian=:big, width=4, default=0>, tcp_ack=#<struct StructFu::Int32 value=nil, endian=:big, width=4, default=0>, tcp_hlen=#<struct PacketFu::TcpHlen hlen=5>, tcp_reserved=#<struct PacketFu::TcpReserved r1=0, r2=0, r3=0>, tcp_ecn=#<struct PacketFu::TcpEcn n=nil, c=nil, e=nil>, tcp_flags=#<struct PacketFu::TcpFlags urg=0, ack=0, psh=0, rst=0, syn=0, fin=0>, tcp_win=#<struct StructFu::Int16 value=16384, endian=:big, width=2, default=0>, tcp_sum=#<struct StructFu::Int16 value=43333, endian=:big, width=2, default=0>, tcp_urg=#<struct StructFu::Int16 value=nil, endian=:big, width=2, default=0>, tcp_opts=[], body="">]>
|
417
544
|
# irb(main):004:0>
|
418
545
|
def toggle_inspect
|
419
|
-
if
|
546
|
+
if @inspect_style == :pretty
|
420
547
|
eval("class Packet; def inspect; super; end; end")
|
421
|
-
|
548
|
+
@inspect_style = :ugly
|
422
549
|
else
|
423
550
|
eval("class Packet; def inspect; self.proto.join('|') + \"\n\" + self.inspect_hex; end; end")
|
424
|
-
|
551
|
+
@inspect_style = :pretty
|
425
552
|
end
|
426
553
|
end
|
427
554
|
|
data/lib/packetfu/pcap.rb
CHANGED
@@ -274,9 +274,6 @@ module PacketFu
|
|
274
274
|
# Note that this strips out pcap timestamps -- if you'd like to retain
|
275
275
|
# timestamps and other libpcap file information, you will want to
|
276
276
|
# use read() instead.
|
277
|
-
#
|
278
|
-
# Note, invoking this requires the somewhat clumsy sytax of,
|
279
|
-
# PcapFile.new.file_to_array(:f => 'filename.pcap')
|
280
277
|
def file_to_array(args={})
|
281
278
|
filename = args[:filename] || args[:file] || args[:f]
|
282
279
|
if filename
|
@@ -291,6 +288,10 @@ module PacketFu
|
|
291
288
|
|
292
289
|
alias_method :f2a, :file_to_array
|
293
290
|
|
291
|
+
def self.file_to_array(fname)
|
292
|
+
PcapFile.new.file_to_array(:f => fname)
|
293
|
+
end
|
294
|
+
|
294
295
|
# Takes an array of packets (as generated by file_to_array), and writes them
|
295
296
|
# to a file. Valid arguments are:
|
296
297
|
#
|
data/lib/packetfu/protos/arp.rb
CHANGED
@@ -77,7 +77,7 @@ module PacketFu
|
|
77
77
|
# Setter for the ARP protocol length.
|
78
78
|
def arp_proto_len=(i); typecast i; end
|
79
79
|
# Getter for the ARP protocol length.
|
80
|
-
def
|
80
|
+
def arp_proto_len; self[:arp_proto_len].to_i; end
|
81
81
|
# Setter for the ARP opcode.
|
82
82
|
def arp_opcode=(i); typecast i; end
|
83
83
|
# Getter for the ARP opcode.
|
@@ -143,6 +143,17 @@ module PacketFu
|
|
143
143
|
self[:arp_dst_ip].to_x
|
144
144
|
end
|
145
145
|
|
146
|
+
# Readability aliases
|
147
|
+
|
148
|
+
alias :arp_src_mac_readable :arp_saddr_mac
|
149
|
+
alias :arp_dst_mac_readable :arp_daddr_mac
|
150
|
+
alias :arp_src_ip_readable :arp_saddr_ip
|
151
|
+
alias :arp_dst_ip_readable :arp_daddr_ip
|
152
|
+
|
153
|
+
def arp_proto_readable
|
154
|
+
"0x%04x" % arp_proto
|
155
|
+
end
|
156
|
+
|
146
157
|
end # class ARPHeader
|
147
158
|
|
148
159
|
# ARPPacket is used to construct ARP packets. They contain an EthHeader and an ARPHeader.
|
@@ -216,8 +227,8 @@ module PacketFu
|
|
216
227
|
end
|
217
228
|
|
218
229
|
# Generates summary data for ARP packets.
|
219
|
-
def
|
220
|
-
peek_data = ["A
|
230
|
+
def peek_format
|
231
|
+
peek_data = ["A "]
|
221
232
|
peek_data << "%-5d" % self.to_s.size
|
222
233
|
peek_data << arp_saddr_mac
|
223
234
|
peek_data << "(#{arp_saddr_ip})"
|
data/lib/packetfu/protos/eth.rb
CHANGED
@@ -229,6 +229,15 @@ module PacketFu
|
|
229
229
|
EthHeader.str2mac(self[:eth_dst].to_s)
|
230
230
|
end
|
231
231
|
|
232
|
+
# Readability aliases
|
233
|
+
|
234
|
+
alias :eth_dst_readable :eth_daddr
|
235
|
+
alias :eth_src_readable :eth_saddr
|
236
|
+
|
237
|
+
def eth_proto_readable
|
238
|
+
"0x%04x" % eth_proto
|
239
|
+
end
|
240
|
+
|
232
241
|
end
|
233
242
|
|
234
243
|
# EthPacket is used to construct Ethernet packets. They contain an
|
data/lib/packetfu/protos/hsrp.rb
CHANGED
@@ -109,6 +109,13 @@ module PacketFu
|
|
109
109
|
self[:hsrp_vip].to_x
|
110
110
|
end
|
111
111
|
|
112
|
+
# Readability aliases
|
113
|
+
|
114
|
+
alias :hsrp_vip_readable :hsrp_addr
|
115
|
+
|
116
|
+
def hsrp_password_readable
|
117
|
+
hsrp_password.to_s.inspect
|
118
|
+
end
|
112
119
|
|
113
120
|
end
|
114
121
|
|
@@ -182,14 +189,13 @@ module PacketFu
|
|
182
189
|
end
|
183
190
|
|
184
191
|
# Peek provides summary data on packet contents.
|
185
|
-
def
|
186
|
-
peek_data = ["
|
192
|
+
def peek_format
|
193
|
+
peek_data = ["UH "]
|
187
194
|
peek_data << "%-5d" % self.to_s.size
|
188
|
-
peek_data << "%-
|
189
|
-
peek_data << "
|
190
|
-
peek_data << "%-
|
191
|
-
peek_data << "
|
192
|
-
peek_data << "%21s" % "#{self.ip_daddr}:#{self.udp_dport}"
|
195
|
+
peek_data << "%-16s" % self.hsrp_addr
|
196
|
+
peek_data << "%-4d" % self.hsrp_group
|
197
|
+
peek_data << "%-35s" % self.hsrp_password_readable
|
198
|
+
peek_data << "%-15s" % self.ip_saddr
|
193
199
|
peek_data.join
|
194
200
|
end
|
195
201
|
|
data/lib/packetfu/protos/icmp.rb
CHANGED
@@ -83,6 +83,12 @@ module PacketFu
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
# Readability aliases
|
87
|
+
|
88
|
+
def icmp_sum_readable
|
89
|
+
"0x%04x" % icmp_sum
|
90
|
+
end
|
91
|
+
|
86
92
|
end
|
87
93
|
|
88
94
|
# ICMPPacket is used to construct ICMP Packets. They contain an EthHeader, an IPHeader, and a ICMPHeader.
|
@@ -148,8 +154,8 @@ module PacketFu
|
|
148
154
|
end
|
149
155
|
|
150
156
|
# Peek provides summary data on packet contents.
|
151
|
-
def
|
152
|
-
peek_data = ["
|
157
|
+
def peek_format
|
158
|
+
peek_data = ["IC "] # I is taken by IP
|
153
159
|
peek_data << "%-5d" % self.to_s.size
|
154
160
|
type = case self.icmp_type.to_i
|
155
161
|
when 8
|
data/lib/packetfu/protos/ip.rb
CHANGED
@@ -261,6 +261,19 @@ module PacketFu
|
|
261
261
|
end
|
262
262
|
end
|
263
263
|
|
264
|
+
# Readability aliases
|
265
|
+
|
266
|
+
alias :ip_src_readable :ip_saddr
|
267
|
+
alias :ip_dst_readable :ip_daddr
|
268
|
+
|
269
|
+
def ip_id_readable
|
270
|
+
"0x%04x" % ip_id
|
271
|
+
end
|
272
|
+
|
273
|
+
def ip_sum_readable
|
274
|
+
"0x%04x" % ip_sum
|
275
|
+
end
|
276
|
+
|
264
277
|
end
|
265
278
|
|
266
279
|
# IPPacket is used to construct IP packets. They contain an EthHeader, an IPHeader, and usually
|
@@ -329,8 +342,8 @@ module PacketFu
|
|
329
342
|
end
|
330
343
|
|
331
344
|
# Peek provides summary data on packet contents.
|
332
|
-
def
|
333
|
-
peek_data = ["I
|
345
|
+
def peek_format
|
346
|
+
peek_data = ["I "]
|
334
347
|
peek_data << "%-5d" % to_s.size
|
335
348
|
peek_data << "%-21s" % "#{ip_saddr}"
|
336
349
|
peek_data << "->"
|
data/lib/packetfu/protos/ipv6.rb
CHANGED
@@ -182,6 +182,11 @@ module PacketFu
|
|
182
182
|
self[:ipv6_dst].read_x(str)
|
183
183
|
end
|
184
184
|
|
185
|
+
# Readability aliases
|
186
|
+
|
187
|
+
alias :ipv6_src_readable :ipv6_saddr
|
188
|
+
alias :ipv6_dst_readable :ipv6_daddr
|
189
|
+
|
185
190
|
end # class IPv6Header
|
186
191
|
|
187
192
|
# IPv6Packet is used to construct IPv6 Packets. They contain an EthHeader and an IPv6Header, and in
|
@@ -230,7 +235,7 @@ module PacketFu
|
|
230
235
|
|
231
236
|
# Peek provides summary data on packet contents.
|
232
237
|
def peek(args={})
|
233
|
-
peek_data = ["6
|
238
|
+
peek_data = ["6 "]
|
234
239
|
peek_data << "%-5d" % self.to_s.size
|
235
240
|
peek_data << "%-31s" % self.ipv6_saddr
|
236
241
|
peek_data << "-> "
|
data/lib/packetfu/protos/tcp.rb
CHANGED
@@ -842,6 +842,15 @@ module PacketFu
|
|
842
842
|
self[:tcp_opts].decode
|
843
843
|
end
|
844
844
|
|
845
|
+
# Gets a more readable flags list
|
846
|
+
def tcp_flags_dotmap
|
847
|
+
dotmap = tcp_flags.members.map do |flag|
|
848
|
+
status = self.tcp_flags.send flag
|
849
|
+
status == 0 ? "." : flag.to_s.upcase[0]
|
850
|
+
end
|
851
|
+
dotmap.join
|
852
|
+
end
|
853
|
+
|
845
854
|
# Sets a more readable option list.
|
846
855
|
def tcp_options=(arg)
|
847
856
|
self[:tcp_opts].encode arg
|
@@ -887,6 +896,26 @@ module PacketFu
|
|
887
896
|
end
|
888
897
|
end
|
889
898
|
|
899
|
+
# Readability aliases
|
900
|
+
|
901
|
+
alias :tcp_flags_readable :tcp_flags_dotmap
|
902
|
+
|
903
|
+
def tcp_ack_readable
|
904
|
+
"0x%08x" % tcp_ack
|
905
|
+
end
|
906
|
+
|
907
|
+
def tcp_seq_readable
|
908
|
+
"0x%08x" % tcp_seq
|
909
|
+
end
|
910
|
+
|
911
|
+
def tcp_sum_readable
|
912
|
+
"0x%04x" % tcp_sum
|
913
|
+
end
|
914
|
+
|
915
|
+
def tcp_opts_readable
|
916
|
+
tcp_options
|
917
|
+
end
|
918
|
+
|
890
919
|
end
|
891
920
|
|
892
921
|
# TCPPacket is used to construct TCP packets. They contain an EthHeader, an IPHeader, and a TCPHeader.
|
@@ -1057,20 +1086,17 @@ module PacketFu
|
|
1057
1086
|
end
|
1058
1087
|
end
|
1059
1088
|
|
1060
|
-
#
|
1061
|
-
|
1062
|
-
|
1089
|
+
# TCP packets are denoted by a "T ", followed by size,
|
1090
|
+
# source and dest information, packet flags, sequence
|
1091
|
+
# number, and IPID.
|
1092
|
+
def peek_format
|
1093
|
+
peek_data = ["T "]
|
1063
1094
|
peek_data << "%-5d" % self.to_s.size
|
1064
1095
|
peek_data << "%-21s" % "#{self.ip_saddr}:#{self.tcp_src}"
|
1065
1096
|
peek_data << "->"
|
1066
1097
|
peek_data << "%21s" % "#{self.ip_daddr}:#{self.tcp_dst}"
|
1067
1098
|
flags = ' ['
|
1068
|
-
flags <<
|
1069
|
-
flags << (self.tcp_flags.ack.zero? ? "." : "A")
|
1070
|
-
flags << (self.tcp_flags.psh.zero? ? "." : "P")
|
1071
|
-
flags << (self.tcp_flags.rst.zero? ? "." : "R")
|
1072
|
-
flags << (self.tcp_flags.syn.zero? ? "." : "S")
|
1073
|
-
flags << (self.tcp_flags.fin.zero? ? "." : "F")
|
1099
|
+
flags << self.tcp_flags_dotmap
|
1074
1100
|
flags << '] '
|
1075
1101
|
peek_data << flags
|
1076
1102
|
peek_data << "S:"
|
data/lib/packetfu/protos/udp.rb
CHANGED
@@ -97,6 +97,12 @@ module PacketFu
|
|
97
97
|
self.udp_dst=(arg)
|
98
98
|
end
|
99
99
|
|
100
|
+
# Readability aliases
|
101
|
+
|
102
|
+
def udp_sum_readable
|
103
|
+
"0x%04x" % udp_sum
|
104
|
+
end
|
105
|
+
|
100
106
|
end
|
101
107
|
|
102
108
|
# UDPPacket is used to construct UDP Packets. They contain an EthHeader, an IPHeader, and a UDPHeader.
|
@@ -216,8 +222,8 @@ module PacketFu
|
|
216
222
|
end
|
217
223
|
|
218
224
|
# Peek provides summary data on packet contents.
|
219
|
-
def
|
220
|
-
peek_data = ["U
|
225
|
+
def peek_format
|
226
|
+
peek_data = ["U "]
|
221
227
|
peek_data << "%-5d" % self.to_s.size
|
222
228
|
peek_data << "%-21s" % "#{self.ip_saddr}:#{self.udp_sport}"
|
223
229
|
peek_data << "->"
|
data/lib/packetfu/structfu.rb
CHANGED
@@ -33,6 +33,11 @@ module StructFu
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
# Handle deep copies correctly
|
37
|
+
def clone
|
38
|
+
Marshal.load(Marshal.dump(self))
|
39
|
+
end
|
40
|
+
|
36
41
|
# Ints all have a value, an endianness, and a default value.
|
37
42
|
# Note that the signedness of Int values are implicit as
|
38
43
|
# far as the subclasses are concerned; to_i and to_f will
|
data/lib/packetfu/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# This just allows you to eyeball the dissection stuff to make sure it's all right.
|
2
|
+
|
3
|
+
require File.join("..","lib","packetfu")
|
4
|
+
puts "Loaded: PacketFu v#{PacketFu.version}"
|
5
|
+
# $: << File.join(File.expand_path(File.dirname(__FILE__)),"..","lib")
|
6
|
+
|
7
|
+
include PacketFu
|
8
|
+
|
9
|
+
packets = PcapFile.file_to_array "test/sample2.pcap"
|
10
|
+
packets.each do |packet|
|
11
|
+
puts packet.inspect
|
12
|
+
pkt = Packet.parse(packet)
|
13
|
+
puts pkt.dissect
|
14
|
+
sleep 1
|
15
|
+
end
|
data/test/icmp_test.pcap
CHANGED
Binary file
|
data/test/ip_test.pcap
CHANGED
Binary file
|
data/test/packet_spec.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.join("..","lib","packetfu")
|
2
|
+
|
3
|
+
describe PacketFu::Packet, "abstract packet class behavior" do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
class PacketFu::FooPacket < PacketFu::Packet; end
|
7
|
+
class PacketFu::BarPacket < PacketFu::Packet; end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should not be instantiated" do
|
11
|
+
expect { PacketFu::Packet.new }.to raise_error(NoMethodError)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should allow subclasses to instantiate" do
|
15
|
+
expect { PacketFu::FooPacket.new }. to be
|
16
|
+
PacketFu.packet_classes.include?(PacketFu::FooPacket).should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should register packet classes with PacketFu" do
|
20
|
+
PacketFu.packet_classes {should include(FooPacket) }
|
21
|
+
PacketFu.packet_classes {should include(BarPacket) }
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should disallow badly named subclasses" do
|
25
|
+
expect {
|
26
|
+
class PacketFu::PacketNot < PacketFu::Packet
|
27
|
+
end
|
28
|
+
}.to raise_error
|
29
|
+
PacketFu.packet_classes.include?(PacketFu::PacketNot).should be_false
|
30
|
+
PacketFu.packet_classes {should_not include(PacketNot) }
|
31
|
+
end
|
32
|
+
|
33
|
+
before(:each) do
|
34
|
+
@tcp_packet = PacketFu::TCPPacket.new
|
35
|
+
@tcp_packet.ip_saddr = "10.10.10.10"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should shallow copy with dup()" do
|
39
|
+
p2 = @tcp_packet.dup
|
40
|
+
p2.ip_saddr = "20.20.20.20"
|
41
|
+
p2.ip_saddr.should == @tcp_packet.ip_saddr
|
42
|
+
p2.headers[1].object_id.should == @tcp_packet.headers[1].object_id
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should deep copy with clone()" do
|
46
|
+
p3 = @tcp_packet.clone
|
47
|
+
p3.ip_saddr = "30.30.30.30"
|
48
|
+
p3.ip_saddr.should_not == @tcp_packet.ip_saddr
|
49
|
+
p3.headers[1].object_id.should_not == @tcp_packet.headers[1].object_id
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should have senisble equality" do
|
53
|
+
p4 = @tcp_packet.dup
|
54
|
+
p4.should == @tcp_packet
|
55
|
+
p5 = @tcp_packet.clone
|
56
|
+
p5.should == @tcp_packet
|
57
|
+
end
|
58
|
+
|
59
|
+
# It's actually kinda hard to manually create identical TCP packets
|
60
|
+
it "should be possible to manually create identical packets" do
|
61
|
+
p6 = @tcp_packet.clone
|
62
|
+
p6.should == @tcp_packet
|
63
|
+
p7 = PacketFu::TCPPacket.new
|
64
|
+
p7.ip_saddr = p6.ip_saddr
|
65
|
+
p7.ip_id = p6.ip_id
|
66
|
+
p7.tcp_seq = p6.tcp_seq
|
67
|
+
p7.tcp_src = p6.tcp_src
|
68
|
+
p7.tcp_sum = p6.tcp_sum
|
69
|
+
p7.should == p6
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join("..","lib","packetfu")
|
2
|
+
|
3
|
+
PacketFu.packet_classes.each do |pclass|
|
4
|
+
describe pclass, "peek format" do
|
5
|
+
it "will display sensible peek information" do
|
6
|
+
p = pclass.new
|
7
|
+
p.respond_to?(:peek).should be_true
|
8
|
+
p.peek.size.should be_<=(80), p.peek.inspect
|
9
|
+
p.peek.should match(/^[A-Z0-9?]../)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/test/packetfu_spec.rb
CHANGED
@@ -54,17 +54,31 @@ describe PacketFu, "protocol requires" do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
describe PacketFu, "packet class list management" do
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
|
58
|
+
before(:all) do
|
59
|
+
class PacketFu::FooPacket < PacketFu::Packet; end
|
60
|
+
class PacketFu::BarPacket < PacketFu::Packet; end
|
61
|
+
class PacketFu::PacketBaz; end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should allow packet class registration" do
|
65
|
+
PacketFu.add_packet_class(PacketFu::FooPacket).should be_kind_of Array
|
66
|
+
PacketFu.add_packet_class(PacketFu::BarPacket).should be_kind_of Array
|
67
|
+
end
|
68
|
+
|
69
|
+
its(:packet_classes) {should include(PacketFu::FooPacket)}
|
70
|
+
|
62
71
|
it "should disallow non-classes as packet classes" do
|
63
72
|
expect { PacketFu.add_packet_class("A String") }.to raise_error
|
64
73
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
74
|
+
|
75
|
+
its(:packet_prefixes) {should include("bar")}
|
76
|
+
|
77
|
+
# Don't really have much utility for this right now.
|
78
|
+
it "should allow packet class deregistration" do
|
79
|
+
PacketFu.remove_packet_class(PacketFu::BarPacket)
|
80
|
+
PacketFu.packet_prefixes.should_not include("bar")
|
81
|
+
PacketFu.add_packet_class(PacketFu::BarPacket)
|
69
82
|
end
|
83
|
+
|
70
84
|
end
|
data/test/ptest.rb
CHANGED
@@ -4,7 +4,13 @@ require 'pcaprub'
|
|
4
4
|
require 'packetfu'
|
5
5
|
include PacketFu
|
6
6
|
|
7
|
-
|
7
|
+
if Process.euid.zero?
|
8
|
+
puts ">> Interface: " << Pcap.lookupdev
|
9
|
+
else
|
10
|
+
puts ">> No interface access"
|
11
|
+
end
|
12
|
+
puts ">> Version: " << PacketFu.version
|
13
|
+
|
8
14
|
# vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
|
9
15
|
|
10
16
|
|
data/test/structfu_spec.rb
CHANGED
@@ -331,8 +331,4 @@ describe StructFu::IntString do
|
|
331
331
|
expect { @istr.read(data) }.to raise_error
|
332
332
|
end
|
333
333
|
|
334
|
-
# So far, not implemented anywhere. In fact, none of this IntString
|
335
|
-
# business is. Ah well.
|
336
|
-
it "should parse when something actually needs it"
|
337
|
-
|
338
334
|
end
|
data/test/tcp_test.pcap
CHANGED
Binary file
|
data/test/udp_test.pcap
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetfu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: -1237194367
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
9
|
+
- 3
|
10
10
|
- pre
|
11
|
-
version: 1.0.
|
11
|
+
version: 1.0.3.pre
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Tod Beardsley
|
@@ -88,6 +88,7 @@ files:
|
|
88
88
|
- test/udp_test.pcap
|
89
89
|
- test/sample2.pcap
|
90
90
|
- test/sample.pcap
|
91
|
+
- test/dissect_thinger.rb
|
91
92
|
- test/test_ip6.rb
|
92
93
|
- test/all_tests.rb
|
93
94
|
- test/test_invalid.rb
|
@@ -103,6 +104,7 @@ files:
|
|
103
104
|
- test/arp_test.pcap
|
104
105
|
- test/test_inject.rb
|
105
106
|
- test/test_eth.rb
|
107
|
+
- test/packet_spec.rb
|
106
108
|
- test/sample-ipv6.pcap
|
107
109
|
- test/test_hsrp.rb
|
108
110
|
- test/test_structfu.rb
|
@@ -111,8 +113,10 @@ files:
|
|
111
113
|
- test/eth_test.pcap
|
112
114
|
- test/test_ip.rb
|
113
115
|
- test/structfu_spec.rb
|
116
|
+
- test/packet_subclasses_spec.rb
|
114
117
|
- examples/oui.txt
|
115
118
|
- examples/uniqpcap.rb
|
119
|
+
- examples/dissect_thinger.rb
|
116
120
|
- examples/examples.rb
|
117
121
|
- examples/simple-stats.rb
|
118
122
|
- examples/arphood.rb
|