packetfu 1.1.5 → 1.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -2
- data/.gitignore +1 -0
- data/LICENSE.txt +1 -1
- data/bench/after-2012-07-28.txt +25 -0
- data/bench/before-2012-07-28.txt +25 -0
- data/bench/benchit.rb +68 -0
- data/bench/calc_delta.rb +17 -0
- data/bench/octets.rb +22 -0
- data/bench/octets_after.txt +8 -0
- data/bench/octets_after_refactor.txt +8 -0
- data/bench/octets_before.txt +8 -0
- data/lib/packetfu.rb +8 -3
- data/lib/packetfu/packet.rb +2 -2
- data/lib/packetfu/pcap.rb +20 -4
- data/lib/packetfu/protos/arp.rb +7 -160
- data/lib/packetfu/protos/arp/header.rb +160 -0
- data/lib/packetfu/protos/arp/mixin.rb +38 -0
- data/lib/packetfu/protos/eth.rb +5 -247
- data/lib/packetfu/protos/eth/header.rb +247 -0
- data/lib/packetfu/protos/eth/mixin.rb +20 -0
- data/lib/packetfu/protos/hsrp.rb +13 -123
- data/lib/packetfu/protos/hsrp/header.rb +120 -0
- data/lib/packetfu/protos/hsrp/mixin.rb +31 -0
- data/lib/packetfu/protos/icmp.rb +10 -97
- data/lib/packetfu/protos/icmp/header.rb +93 -0
- data/lib/packetfu/protos/icmp/mixin.rb +17 -0
- data/lib/packetfu/protos/ip.rb +7 -295
- data/lib/packetfu/protos/ip/header.rb +335 -0
- data/lib/packetfu/protos/ip/mixin.rb +43 -0
- data/lib/packetfu/protos/ipv6.rb +7 -191
- data/lib/packetfu/protos/ipv6/header.rb +190 -0
- data/lib/packetfu/protos/ipv6/mixin.rb +31 -0
- data/lib/packetfu/protos/tcp.rb +13 -939
- data/lib/packetfu/protos/tcp/ecn.rb +42 -0
- data/lib/packetfu/protos/tcp/flags.rb +83 -0
- data/lib/packetfu/protos/tcp/header.rb +307 -0
- data/lib/packetfu/protos/tcp/hlen.rb +40 -0
- data/lib/packetfu/protos/tcp/mixin.rb +48 -0
- data/lib/packetfu/protos/tcp/option.rb +323 -0
- data/lib/packetfu/protos/tcp/options.rb +106 -0
- data/lib/packetfu/protos/tcp/reserved.rb +42 -0
- data/lib/packetfu/protos/udp.rb +12 -110
- data/lib/packetfu/protos/udp/header.rb +107 -0
- data/lib/packetfu/protos/udp/mixin.rb +23 -0
- data/lib/packetfu/utils.rb +24 -24
- data/lib/packetfu/version.rb +1 -1
- data/packetfu.gemspec +2 -2
- data/test/test_ip.rb +0 -19
- data/test/test_octets.rb +18 -21
- data/test/test_tcp.rb +10 -0
- data/test/test_udp.rb +17 -0
- metadata +79 -50
data/.document
CHANGED
data/.gitignore
CHANGED
data/LICENSE.txt
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
Parsing a TCP Packet...
|
2
|
+
user system total real
|
3
|
+
PacketFu::Packet.parse() 1.670000 0.010000 1.680000 ( 1.664486)
|
4
|
+
PacketFu::EthPacket.new.read() 0.180000 0.000000 0.180000 ( 0.179386)
|
5
|
+
PacketFu::IPPacket.new.read() 0.410000 0.000000 0.410000 ( 0.415767)
|
6
|
+
PacketFu::TCPPacket.new.read() 1.380000 0.000000 1.380000 ( 1.375509)
|
7
|
+
|
8
|
+
Parsing a UDP Packet...
|
9
|
+
user system total real
|
10
|
+
PacketFu::Packet.parse() 1.750000 0.000000 1.750000 ( 1.757758)
|
11
|
+
PacketFu::EthPacket.new.read() 0.180000 0.000000 0.180000 ( 0.179951)
|
12
|
+
PacketFu::IPPacket.new.read() 0.420000 0.000000 0.420000 ( 0.416224)
|
13
|
+
PacketFu::UDPPacket.new.read() 0.720000 0.000000 0.720000 ( 0.715579)
|
14
|
+
|
15
|
+
Parsing a ARP Packet...
|
16
|
+
user system total real
|
17
|
+
PacketFu::Packet.parse() 0.820000 0.000000 0.820000 ( 0.823303)
|
18
|
+
PacketFu::EthPacket.new.read() 0.180000 0.000000 0.180000 ( 0.182247)
|
19
|
+
PacketFu::ARPPacket.new.read() 0.670000 0.000000 0.670000 ( 0.672712)
|
20
|
+
|
21
|
+
Parsing a IPv6 Packet...
|
22
|
+
user system total real
|
23
|
+
PacketFu::Packet.parse() 0.700000 0.000000 0.700000 ( 0.695721)
|
24
|
+
PacketFu::EthPacket.new.read() 0.180000 0.000000 0.180000 ( 0.180608)
|
25
|
+
PacketFu::IPv6Packet.new.read() 0.530000 0.000000 0.530000 ( 0.527124)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Parsing a TCP Packet...
|
2
|
+
user system total real
|
3
|
+
PacketFu::Packet.parse() 3.290000 0.000000 3.290000 ( 3.290771)
|
4
|
+
PacketFu::EthPacket.new.read() 0.180000 0.000000 0.180000 ( 0.181850)
|
5
|
+
PacketFu::IPPacket.new.read() 0.490000 0.000000 0.490000 ( 0.484150)
|
6
|
+
PacketFu::TCPPacket.new.read() 2.970000 0.000000 2.970000 ( 2.977186)
|
7
|
+
|
8
|
+
Parsing a UDP Packet...
|
9
|
+
user system total real
|
10
|
+
PacketFu::Packet.parse() 2.530000 0.010000 2.540000 ( 2.529333)
|
11
|
+
PacketFu::EthPacket.new.read() 0.180000 0.000000 0.180000 ( 0.179065)
|
12
|
+
PacketFu::IPPacket.new.read() 0.490000 0.000000 0.490000 ( 0.487412)
|
13
|
+
PacketFu::UDPPacket.new.read() 1.060000 0.000000 1.060000 ( 1.067339)
|
14
|
+
|
15
|
+
Parsing a ARP Packet...
|
16
|
+
user system total real
|
17
|
+
PacketFu::Packet.parse() 0.860000 0.000000 0.860000 ( 0.851042)
|
18
|
+
PacketFu::EthPacket.new.read() 0.180000 0.000000 0.180000 ( 0.183220)
|
19
|
+
PacketFu::ARPPacket.new.read() 0.720000 0.000000 0.720000 ( 0.718533)
|
20
|
+
|
21
|
+
Parsing a IPv6 Packet...
|
22
|
+
user system total real
|
23
|
+
PacketFu::Packet.parse() 0.750000 0.000000 0.750000 ( 0.753657)
|
24
|
+
PacketFu::EthPacket.new.read() 0.180000 0.000000 0.180000 ( 0.182015)
|
25
|
+
PacketFu::IPv6Packet.new.read() 0.610000 0.000000 0.610000 ( 0.611805)
|
data/bench/benchit.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
$:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
|
2
|
+
require 'packetfu'
|
3
|
+
require 'benchmark'
|
4
|
+
class String
|
5
|
+
def bin
|
6
|
+
self.scan(/../).map {|x| x.to_i(16).chr}.join
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
file_pfx = ARGV.shift
|
11
|
+
|
12
|
+
IPV6_PACKET = "3333000000fb442a60c14d7b86dd60000000006611fffe80000000000000462a60fffec14d7bff0200000000000000000000000000fb14e914e900664ed1000000000002000000020000145542432d437573746f6d6572732d695061642d33056c6f63616c0000ff0001c00c00ff0001c00c001c0001000000780010fe80000000000000462a60fffec14d7bc00c0001000100000078000448d77827".bin
|
13
|
+
|
14
|
+
ARP_PACKET = "ffffffffffff001e6837bcf708060001080006040001001e6837bcf748d7780100000000000048d779f7000000000000000000000000000000000000".bin
|
15
|
+
|
16
|
+
UDP_PACKET = "01005e7ffffa100ba9eb63400800450000a12d7c0000011159b446a5fb7ceffffffacdf3076c008d516e4d2d534541524348202a20485454502f312e310d0a486f73743a3233392e3235352e3235352e3235303a313930300d0a53543a75726e3a736368656d61732d75706e702d6f72673a6465766963653a496e7465726e6574476174657761794465766963653a310d0a4d616e3a22737364703a646973636f766572220d0a4d583a330d0a0d0a".bin
|
17
|
+
|
18
|
+
TCP_PACKET = "e0f8472161a600254ba0760608004500004403554000400651d0c0a83207c0a832370224c1d22d94847f0b07c4ba8018ffff30ba00000101080a8731821433564b8c01027165000000000000200000000000".bin
|
19
|
+
|
20
|
+
iters = 5_000
|
21
|
+
data = []
|
22
|
+
data = []
|
23
|
+
data = []
|
24
|
+
data = []
|
25
|
+
puts "Parsing a TCP Packet..."
|
26
|
+
require 'pp'
|
27
|
+
Benchmark.bm do |bm|
|
28
|
+
data << bm.report("PacketFu::Packet.parse() ") { iters.times {PacketFu::Packet.parse(TCP_PACKET)} }
|
29
|
+
data << bm.report("PacketFu::EthPacket.new.read() ") { iters.times {PacketFu::EthPacket.new.read(TCP_PACKET)} }
|
30
|
+
data << bm.report("PacketFu::IPPacket.new.read() ") { iters.times {PacketFu::IPPacket.new.read(TCP_PACKET)} }
|
31
|
+
data << bm.report("PacketFu::TCPPacket.new.read() ") { iters.times {PacketFu::TCPPacket.new.read(TCP_PACKET)} }
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
puts ""
|
36
|
+
puts "Parsing a UDP Packet..."
|
37
|
+
Benchmark.bm do |bm|
|
38
|
+
data << bm.report("PacketFu::Packet.parse() ") { iters.times {PacketFu::Packet.parse(UDP_PACKET)} }
|
39
|
+
data << bm.report("PacketFu::EthPacket.new.read() ") { iters.times {PacketFu::EthPacket.new.read(UDP_PACKET)} }
|
40
|
+
data << bm.report("PacketFu::IPPacket.new.read() ") { iters.times {PacketFu::IPPacket.new.read(UDP_PACKET)} }
|
41
|
+
data << bm.report("PacketFu::UDPPacket.new.read() ") { iters.times {PacketFu::UDPPacket.new.read(UDP_PACKET)} }
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
|
45
|
+
puts ""
|
46
|
+
puts "Parsing a ARP Packet..."
|
47
|
+
Benchmark.bm do |bm|
|
48
|
+
data << bm.report("PacketFu::Packet.parse() ") { iters.times {PacketFu::Packet.parse(ARP_PACKET)} }
|
49
|
+
data << bm.report("PacketFu::EthPacket.new.read() ") { iters.times {PacketFu::EthPacket.new.read(ARP_PACKET)} }
|
50
|
+
data << bm.report("PacketFu::ARPPacket.new.read() ") { iters.times {PacketFu::ARPPacket.new.read(ARP_PACKET)} }
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
puts ""
|
55
|
+
puts "Parsing a IPv6 Packet..."
|
56
|
+
Benchmark.bm do |bm|
|
57
|
+
data << bm.report("PacketFu::Packet.parse() ") { iters.times {PacketFu::Packet.parse(IPV6_PACKET)} }
|
58
|
+
data << bm.report("PacketFu::EthPacket.new.read() ") { iters.times {PacketFu::EthPacket.new.read(IPV6_PACKET)} }
|
59
|
+
data << bm.report("PacketFu::IPv6Packet.new.read() ") { iters.times {PacketFu::IPv6Packet.new.read(IPV6_PACKET)} }
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
if file_pfx
|
63
|
+
filename = "#{file_pfx}.dat"
|
64
|
+
puts "dumping data to #{filename}"
|
65
|
+
fio = File.open(filename, "w")
|
66
|
+
Marshal.dump(data, fio)
|
67
|
+
fio.close
|
68
|
+
end
|
data/bench/calc_delta.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
before = ARGV.shift
|
5
|
+
after = ARGV.shift
|
6
|
+
|
7
|
+
fio = File.open(before)
|
8
|
+
before_data = Marshal.load(fio)
|
9
|
+
fio.close
|
10
|
+
|
11
|
+
fio = File.open(after)
|
12
|
+
after_data = Marshal.load(fio)
|
13
|
+
fio.close
|
14
|
+
|
15
|
+
before_data.each_with_index do |data, i|
|
16
|
+
puts (data.total / after_data[i].total)
|
17
|
+
end
|
data/bench/octets.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
$:.unshift File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib")
|
3
|
+
require 'packetfu'
|
4
|
+
|
5
|
+
IPV4_RAW = "\x01\x02\x03\x04"
|
6
|
+
IPV4_STR = "1.2.3.4"
|
7
|
+
|
8
|
+
|
9
|
+
iters = 50_000
|
10
|
+
Benchmark.bm do |bm|
|
11
|
+
bm.report("Octets.new.read(...) ") {iters.times {PacketFu::Octets.new.read(IPV4_RAW)}}
|
12
|
+
bm.report("Octets.new.read_quad(...) ") {iters.times {PacketFu::Octets.new.read_quad(IPV4_STR)}}
|
13
|
+
|
14
|
+
octets = PacketFu::Octets.new
|
15
|
+
bm.report("octets#read(...) ") {iters.times {octets.read(IPV4_RAW)}}
|
16
|
+
bm.report("octets#read_quad(...) ") {iters.times {octets.read_quad(IPV4_STR)}}
|
17
|
+
|
18
|
+
octets.read(IPV4_RAW)
|
19
|
+
bm.report("octets#to_x() ") {iters.times {octets.to_x}}
|
20
|
+
bm.report("octets#to_i() ") {iters.times {octets.to_i}}
|
21
|
+
bm.report("octets#to_s() ") {iters.times {octets.to_s}}
|
22
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
user system total real
|
2
|
+
Octets.new.read(...) 0.480000 0.000000 0.480000 ( 0.485710)
|
3
|
+
Octets.new.read_quad(...) 0.480000 0.000000 0.480000 ( 0.480071)
|
4
|
+
octets#read(...) 0.180000 0.000000 0.180000 ( 0.184558)
|
5
|
+
octets#read_quad(...) 0.180000 0.000000 0.180000 ( 0.175781)
|
6
|
+
octets#to_x() 0.120000 0.000000 0.120000 ( 0.120217)
|
7
|
+
octets#to_i() 0.040000 0.000000 0.040000 ( 0.043496)
|
8
|
+
octets#to_s() 0.100000 0.010000 0.110000 ( 0.093341)
|
@@ -0,0 +1,8 @@
|
|
1
|
+
user system total real
|
2
|
+
Octets.new.read(...) 0.200000 0.000000 0.200000 ( 0.207577)
|
3
|
+
Octets.new.read_quad(...) 0.290000 0.000000 0.290000 ( 0.285364)
|
4
|
+
octets#read(...) 0.080000 0.000000 0.080000 ( 0.074826)
|
5
|
+
octets#read_quad(...) 0.140000 0.000000 0.140000 ( 0.145170)
|
6
|
+
octets#to_x() 0.140000 0.000000 0.140000 ( 0.139427)
|
7
|
+
octets#to_i() 0.020000 0.000000 0.020000 ( 0.016444)
|
8
|
+
octets#to_s() 0.040000 0.000000 0.040000 ( 0.042925)
|
@@ -0,0 +1,8 @@
|
|
1
|
+
user system total real
|
2
|
+
Octets.new.read(...) 0.480000 0.000000 0.480000 ( 0.482913)
|
3
|
+
Octets.new.read_quad(...) 1.390000 0.460000 1.850000 ( 1.858652)
|
4
|
+
octets#read(...) 0.190000 0.000000 0.190000 ( 0.186785)
|
5
|
+
octets#read_quad(...) 1.030000 0.400000 1.430000 ( 1.435857)
|
6
|
+
octets#to_x() 1.010000 0.470000 1.480000 ( 1.480452)
|
7
|
+
octets#to_i() 0.830000 0.420000 1.250000 ( 1.250348)
|
8
|
+
octets#to_s() 0.150000 0.000000 0.150000 ( 0.157041)
|
data/lib/packetfu.rb
CHANGED
@@ -27,7 +27,7 @@ module PacketFu
|
|
27
27
|
|
28
28
|
# Deal with Ruby's encoding by ignoring it.
|
29
29
|
def self.force_binary(str)
|
30
|
-
str.force_encoding
|
30
|
+
str.force_encoding Encoding::BINARY if str.respond_to? :force_encoding
|
31
31
|
end
|
32
32
|
|
33
33
|
# Sets the expected byte order for a pcap file. See PacketFu::Read.set_byte_order
|
@@ -77,6 +77,7 @@ module PacketFu
|
|
77
77
|
end
|
78
78
|
@packet_classes ||= []
|
79
79
|
@packet_classes << klass
|
80
|
+
@packet_classes_dirty = true
|
80
81
|
@packet_classes.sort! {|x,y| x.name <=> y.name}
|
81
82
|
end
|
82
83
|
|
@@ -85,6 +86,7 @@ module PacketFu
|
|
85
86
|
raise "Need a class" unless klass.kind_of? Class
|
86
87
|
@packet_classes ||= []
|
87
88
|
@packet_classes.delete klass
|
89
|
+
@packet_classes_dirty = true
|
88
90
|
@packet_classes
|
89
91
|
end
|
90
92
|
|
@@ -95,8 +97,11 @@ module PacketFu
|
|
95
97
|
|
96
98
|
# Returns an array of packet types by packet prefix.
|
97
99
|
def self.packet_prefixes
|
98
|
-
return []
|
99
|
-
@
|
100
|
+
return [] if @packet_classes.nil?
|
101
|
+
return @packet_class_prefixes if @packet_classes_dirty == false
|
102
|
+
@packet_classes_dirty = false
|
103
|
+
@packet_class_prefixes = @packet_classes.map {|p| p.to_s.split("::").last.to_s.downcase.gsub(/packet$/,"")}
|
104
|
+
return @packet_class_prefixes
|
100
105
|
end
|
101
106
|
|
102
107
|
# The current inspect style. One of :hex, :dissect, or :default
|
data/lib/packetfu/packet.rb
CHANGED
@@ -19,7 +19,7 @@ module PacketFu
|
|
19
19
|
|
20
20
|
# Force strings into binary.
|
21
21
|
def self.force_binary(str)
|
22
|
-
str.force_encoding
|
22
|
+
str.force_encoding Encoding::BINARY if str.respond_to? :force_encoding
|
23
23
|
end
|
24
24
|
|
25
25
|
# Parse() creates the correct packet type based on the data, and returns the apporpiate
|
@@ -284,7 +284,7 @@ module PacketFu
|
|
284
284
|
|
285
285
|
# Hexify provides a neatly-formatted dump of binary data, familar to hex readers.
|
286
286
|
def hexify(str)
|
287
|
-
str.force_encoding(
|
287
|
+
str.force_encoding(Encoding::BINARY) if str.respond_to? :force_encoding
|
288
288
|
hexascii_lines = str.to_s.unpack("H*")[0].scan(/.{1,32}/)
|
289
289
|
regex = Regexp.new('[\x00-\x1f\x7f-\xff]', nil, 'n')
|
290
290
|
chars = str.to_s.gsub(regex,'.')
|
data/lib/packetfu/pcap.rb
CHANGED
@@ -79,7 +79,7 @@ module PacketFu
|
|
79
79
|
def read(str)
|
80
80
|
force_binary(str)
|
81
81
|
return self if str.nil?
|
82
|
-
str.force_encoding(
|
82
|
+
str.force_encoding(Encoding::BINARY) if str.respond_to? :force_encoding
|
83
83
|
if str[0,4] == self[:magic].to_s
|
84
84
|
self[:magic].read str[0,4]
|
85
85
|
self[:ver_major].read str[4,2]
|
@@ -192,7 +192,7 @@ module PacketFu
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def force_binary(str)
|
195
|
-
str.force_encoding
|
195
|
+
str.force_encoding Encoding::BINARY if str.respond_to? :force_encoding
|
196
196
|
end
|
197
197
|
|
198
198
|
# Reads a string to populate the object. Note, this read takes in the
|
@@ -265,8 +265,11 @@ module PacketFu
|
|
265
265
|
warn "Packet ##{packet_count} is corrupted: expected #{len.to_i}, got #{pcap_packet.data.size}. Exiting."
|
266
266
|
break
|
267
267
|
end
|
268
|
-
|
269
|
-
|
268
|
+
if block
|
269
|
+
yield pcap_packet
|
270
|
+
else
|
271
|
+
pcap_packets << pcap_packet.clone
|
272
|
+
end
|
270
273
|
end
|
271
274
|
ensure
|
272
275
|
file_handle.close
|
@@ -317,6 +320,7 @@ module PacketFu
|
|
317
320
|
|
318
321
|
def initialize(args={})
|
319
322
|
init_fields(args)
|
323
|
+
@filename = args.delete :filename
|
320
324
|
super(args[:endian], args[:head], args[:body])
|
321
325
|
end
|
322
326
|
|
@@ -361,6 +365,18 @@ module PacketFu
|
|
361
365
|
self.read! fdata
|
362
366
|
end
|
363
367
|
|
368
|
+
# Calls the class method with this object's @filename
|
369
|
+
def read_packet_bytes(fname=@filename,&block)
|
370
|
+
raise ArgumentError, "Need a file" unless fname
|
371
|
+
return self.class.read_packet_bytes(fname, &block)
|
372
|
+
end
|
373
|
+
|
374
|
+
# Calls the class method with this object's @filename
|
375
|
+
def read_packets(fname=@filename,&block)
|
376
|
+
raise ArgumentError, "Need a file" unless fname
|
377
|
+
return self.class.read_packets(fname, &block)
|
378
|
+
end
|
379
|
+
|
364
380
|
# file_to_array() translates a libpcap file into an array of packets.
|
365
381
|
# Note that this strips out pcap timestamps -- if you'd like to retain
|
366
382
|
# timestamps and other libpcap file information, you will want to
|
data/lib/packetfu/protos/arp.rb
CHANGED
@@ -1,163 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# ARPHeader is a complete ARP struct, used in ARPPacket.
|
4
|
-
#
|
5
|
-
# ARP is used to discover the machine address of nearby devices.
|
6
|
-
#
|
7
|
-
# See http://www.networksorcery.com/enp/protocol/arp.htm for details.
|
8
|
-
#
|
9
|
-
# ==== Header Definition
|
10
|
-
#
|
11
|
-
# Int16 :arp_hw Default: 1 # Ethernet
|
12
|
-
# Int16 :arp_proto, Default: 0x8000 # IP
|
13
|
-
# Int8 :arp_hw_len, Default: 6
|
14
|
-
# Int8 :arp_proto_len, Default: 4
|
15
|
-
# Int16 :arp_opcode, Default: 1 # 1: Request, 2: Reply, 3: Request-Reverse, 4: Reply-Reverse
|
16
|
-
# EthMac :arp_src_mac # From eth.rb
|
17
|
-
# Octets :arp_src_ip # From ip.rb
|
18
|
-
# EthMac :arp_dst_mac # From eth.rb
|
19
|
-
# Octets :arp_dst_ip # From ip.rb
|
20
|
-
# String :body
|
21
|
-
class ARPHeader < Struct.new(:arp_hw, :arp_proto, :arp_hw_len,
|
22
|
-
:arp_proto_len, :arp_opcode,
|
23
|
-
:arp_src_mac, :arp_src_ip,
|
24
|
-
:arp_dst_mac, :arp_dst_ip,
|
25
|
-
:body)
|
26
|
-
include StructFu
|
27
|
-
|
28
|
-
def initialize(args={})
|
29
|
-
src_mac = args[:arp_src_mac] || (args[:config][:eth_src] if args[:config])
|
30
|
-
src_ip_bin = args[:arp_src_ip] || (args[:config][:ip_src_bin] if args[:config])
|
31
|
-
|
32
|
-
super(
|
33
|
-
Int16.new(args[:arp_hw] || 1),
|
34
|
-
Int16.new(args[:arp_proto] ||0x0800),
|
35
|
-
Int8.new(args[:arp_hw_len] || 6),
|
36
|
-
Int8.new(args[:arp_proto_len] || 4),
|
37
|
-
Int16.new(args[:arp_opcode] || 1),
|
38
|
-
EthMac.new.read(src_mac),
|
39
|
-
Octets.new.read(src_ip_bin),
|
40
|
-
EthMac.new.read(args[:arp_dst_mac]),
|
41
|
-
Octets.new.read(args[:arp_dst_ip]),
|
42
|
-
StructFu::String.new.read(args[:body])
|
43
|
-
)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Returns the object in string form.
|
47
|
-
def to_s
|
48
|
-
self.to_a.map {|x| x.to_s}.join
|
49
|
-
end
|
1
|
+
require 'packetfu/protos/eth/header'
|
2
|
+
require 'packetfu/protos/eth/mixin'
|
50
3
|
|
51
|
-
|
52
|
-
|
53
|
-
force_binary(str)
|
54
|
-
return self if str.nil?
|
55
|
-
self[:arp_hw].read(str[0,2])
|
56
|
-
self[:arp_proto].read(str[2,2])
|
57
|
-
self[:arp_hw_len].read(str[4,1])
|
58
|
-
self[:arp_proto_len].read(str[5,1])
|
59
|
-
self[:arp_opcode].read(str[6,2])
|
60
|
-
self[:arp_src_mac].read(str[8,6])
|
61
|
-
self[:arp_src_ip].read(str[14,4])
|
62
|
-
self[:arp_dst_mac].read(str[18,6])
|
63
|
-
self[:arp_dst_ip].read(str[24,4])
|
64
|
-
self[:body].read(str[28,str.size])
|
65
|
-
self
|
66
|
-
end
|
4
|
+
require 'packetfu/protos/arp/header'
|
5
|
+
require 'packetfu/protos/arp/mixin'
|
67
6
|
|
68
|
-
|
69
|
-
def arp_hw=(i); typecast i; end
|
70
|
-
# Getter for the ARP hardware type.
|
71
|
-
def arp_hw; self[:arp_hw].to_i; end
|
72
|
-
# Setter for the ARP protocol.
|
73
|
-
def arp_proto=(i); typecast i; end
|
74
|
-
# Getter for the ARP protocol.
|
75
|
-
def arp_proto; self[:arp_proto].to_i; end
|
76
|
-
# Setter for the ARP hardware type length.
|
77
|
-
def arp_hw_len=(i); typecast i; end
|
78
|
-
# Getter for the ARP hardware type length.
|
79
|
-
def arp_hw_len; self[:arp_hw_len].to_i; end
|
80
|
-
# Setter for the ARP protocol length.
|
81
|
-
def arp_proto_len=(i); typecast i; end
|
82
|
-
# Getter for the ARP protocol length.
|
83
|
-
def arp_proto_len; self[:arp_proto_len].to_i; end
|
84
|
-
# Setter for the ARP opcode.
|
85
|
-
def arp_opcode=(i); typecast i; end
|
86
|
-
# Getter for the ARP opcode.
|
87
|
-
def arp_opcode; self[:arp_opcode].to_i; end
|
88
|
-
# Setter for the ARP source MAC address.
|
89
|
-
def arp_src_mac=(i); typecast i; end
|
90
|
-
# Getter for the ARP source MAC address.
|
91
|
-
def arp_src_mac; self[:arp_src_mac].to_s; end
|
92
|
-
# Getter for the ARP source IP address.
|
93
|
-
def arp_src_ip=(i); typecast i; end
|
94
|
-
# Setter for the ARP source IP address.
|
95
|
-
def arp_src_ip; self[:arp_src_ip].to_s; end
|
96
|
-
# Setter for the ARP destination MAC address.
|
97
|
-
def arp_dst_mac=(i); typecast i; end
|
98
|
-
# Setter for the ARP destination MAC address.
|
99
|
-
def arp_dst_mac; self[:arp_dst_mac].to_s; end
|
100
|
-
# Setter for the ARP destination IP address.
|
101
|
-
def arp_dst_ip=(i); typecast i; end
|
102
|
-
# Getter for the ARP destination IP address.
|
103
|
-
def arp_dst_ip; self[:arp_dst_ip].to_s; end
|
104
|
-
|
105
|
-
# Set the source MAC address in a more readable way.
|
106
|
-
def arp_saddr_mac=(mac)
|
107
|
-
mac = EthHeader.mac2str(mac)
|
108
|
-
self[:arp_src_mac].read(mac)
|
109
|
-
self.arp_src_mac
|
110
|
-
end
|
111
|
-
|
112
|
-
# Get a more readable source MAC address.
|
113
|
-
def arp_saddr_mac
|
114
|
-
EthHeader.str2mac(self[:arp_src_mac].to_s)
|
115
|
-
end
|
116
|
-
|
117
|
-
# Set the destination MAC address in a more readable way.
|
118
|
-
def arp_daddr_mac=(mac)
|
119
|
-
mac = EthHeader.mac2str(mac)
|
120
|
-
self[:arp_dst_mac].read(mac)
|
121
|
-
self.arp_dst_mac
|
122
|
-
end
|
123
|
-
|
124
|
-
# Get a more readable source MAC address.
|
125
|
-
def arp_daddr_mac
|
126
|
-
EthHeader.str2mac(self[:arp_dst_mac].to_s)
|
127
|
-
end
|
128
|
-
|
129
|
-
# Set a more readable source IP address.
|
130
|
-
def arp_saddr_ip=(addr)
|
131
|
-
self[:arp_src_ip].read_quad(addr)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Get a more readable source IP address.
|
135
|
-
def arp_saddr_ip
|
136
|
-
self[:arp_src_ip].to_x
|
137
|
-
end
|
138
|
-
|
139
|
-
# Set a more readable destination IP address.
|
140
|
-
def arp_daddr_ip=(addr)
|
141
|
-
self[:arp_dst_ip].read_quad(addr)
|
142
|
-
end
|
143
|
-
|
144
|
-
# Get a more readable destination IP address.
|
145
|
-
def arp_daddr_ip
|
146
|
-
self[:arp_dst_ip].to_x
|
147
|
-
end
|
148
|
-
|
149
|
-
# Readability aliases
|
150
|
-
|
151
|
-
alias :arp_src_mac_readable :arp_saddr_mac
|
152
|
-
alias :arp_dst_mac_readable :arp_daddr_mac
|
153
|
-
alias :arp_src_ip_readable :arp_saddr_ip
|
154
|
-
alias :arp_dst_ip_readable :arp_daddr_ip
|
155
|
-
|
156
|
-
def arp_proto_readable
|
157
|
-
"0x%04x" % arp_proto
|
158
|
-
end
|
159
|
-
|
160
|
-
end # class ARPHeader
|
7
|
+
module PacketFu
|
161
8
|
|
162
9
|
# ARPPacket is used to construct ARP packets. They contain an EthHeader and an ARPHeader.
|
163
10
|
# == Example
|
@@ -184,6 +31,8 @@ module PacketFu
|
|
184
31
|
# :config
|
185
32
|
# A hash of return address details, often the output of Utils.whoami?
|
186
33
|
class ARPPacket < Packet
|
34
|
+
include ::PacketFu::EthHeaderMixin
|
35
|
+
include ::PacketFu::ARPHeaderMixin
|
187
36
|
|
188
37
|
attr_accessor :eth_header, :arp_header
|
189
38
|
|
@@ -197,8 +46,6 @@ module PacketFu
|
|
197
46
|
def read(str=nil,args={})
|
198
47
|
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
199
48
|
@eth_header.read(str)
|
200
|
-
@arp_header.read(str[14,str.size])
|
201
|
-
@eth_header.body = @arp_header
|
202
49
|
super(args)
|
203
50
|
self
|
204
51
|
end
|