packetfu 1.1.8 → 1.1.9
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/README.rdoc +11 -12
- data/bench/octets.rb +9 -9
- data/examples/100kpackets.rb +13 -12
- data/examples/ackscan.rb +17 -16
- data/examples/arp.rb +36 -35
- data/examples/arphood.rb +37 -36
- data/examples/dissect_thinger.rb +7 -6
- data/examples/ethernet.rb +1 -0
- data/examples/examples.rb +1 -0
- data/examples/ifconfig.rb +1 -0
- data/examples/new-simple-stats.rb +24 -23
- data/examples/packetfu-shell.rb +26 -25
- data/examples/simple-sniffer.rb +10 -9
- data/examples/simple-stats.rb +24 -23
- data/examples/slammer.rb +4 -3
- data/lib/packetfu.rb +128 -127
- data/lib/packetfu/capture.rb +170 -169
- data/lib/packetfu/config.rb +53 -52
- data/lib/packetfu/inject.rb +57 -56
- data/lib/packetfu/packet.rb +529 -528
- data/lib/packetfu/pcap.rb +580 -579
- data/lib/packetfu/protos/arp.rb +91 -90
- data/lib/packetfu/protos/arp/header.rb +159 -158
- data/lib/packetfu/protos/arp/mixin.rb +37 -36
- data/lib/packetfu/protos/eth.rb +45 -44
- data/lib/packetfu/protos/eth/header.rb +244 -243
- data/lib/packetfu/protos/eth/mixin.rb +4 -3
- data/lib/packetfu/protos/hsrp.rb +70 -69
- data/lib/packetfu/protos/hsrp/header.rb +108 -107
- data/lib/packetfu/protos/hsrp/mixin.rb +30 -29
- data/lib/packetfu/protos/icmp.rb +72 -71
- data/lib/packetfu/protos/icmp/header.rb +83 -82
- data/lib/packetfu/protos/icmp/mixin.rb +15 -14
- data/lib/packetfu/protos/invalid.rb +50 -49
- data/lib/packetfu/protos/ip.rb +70 -69
- data/lib/packetfu/protos/ip/header.rb +292 -291
- data/lib/packetfu/protos/ip/mixin.rb +41 -40
- data/lib/packetfu/protos/ipv6.rb +51 -50
- data/lib/packetfu/protos/ipv6/header.rb +189 -188
- data/lib/packetfu/protos/ipv6/mixin.rb +30 -29
- data/lib/packetfu/protos/lldp.rb +3 -1
- data/lib/packetfu/protos/lldp/header.rb +1 -0
- data/lib/packetfu/protos/lldp/mixin.rb +1 -0
- data/lib/packetfu/protos/tcp.rb +177 -176
- data/lib/packetfu/protos/tcp/ecn.rb +36 -35
- data/lib/packetfu/protos/tcp/flags.rb +75 -74
- data/lib/packetfu/protos/tcp/header.rb +269 -268
- data/lib/packetfu/protos/tcp/hlen.rb +33 -32
- data/lib/packetfu/protos/tcp/mixin.rb +47 -46
- data/lib/packetfu/protos/tcp/option.rb +322 -321
- data/lib/packetfu/protos/tcp/options.rb +96 -95
- data/lib/packetfu/protos/tcp/reserved.rb +36 -35
- data/lib/packetfu/protos/udp.rb +117 -116
- data/lib/packetfu/protos/udp/header.rb +92 -91
- data/lib/packetfu/protos/udp/mixin.rb +4 -3
- data/lib/packetfu/structfu.rb +281 -280
- data/lib/packetfu/utils.rb +211 -208
- data/lib/packetfu/version.rb +42 -41
- data/packetfu.gemspec +1 -1
- data/spec/ethpacket_spec.rb +48 -48
- data/spec/packet_spec.rb +57 -57
- data/spec/packet_subclasses_spec.rb +8 -8
- data/spec/packetfu_spec.rb +59 -59
- data/spec/structfu_spec.rb +268 -268
- data/spec/tcp_spec.rb +75 -75
- data/test/all_tests.rb +13 -13
- data/test/func_lldp.rb +3 -3
- data/test/ptest.rb +2 -2
- data/test/test_arp.rb +116 -116
- data/test/test_capture.rb +45 -45
- data/test/test_eth.rb +68 -68
- data/test/test_hsrp.rb +9 -9
- data/test/test_icmp.rb +52 -52
- data/test/test_inject.rb +18 -18
- data/test/test_invalid.rb +16 -16
- data/test/test_ip.rb +36 -36
- data/test/test_ip6.rb +48 -48
- data/test/test_octets.rb +21 -21
- data/test/test_packet.rb +154 -154
- data/test/test_pcap.rb +170 -170
- data/test/test_structfu.rb +97 -97
- data/test/test_tcp.rb +320 -320
- data/test/test_udp.rb +76 -76
- metadata +2 -2
@@ -1,38 +1,39 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
3
|
+
# This Mixin simplifies access to the ARPHeaders. Mix this in with your
|
4
|
+
# packet interface, and it will add methods that essentially delegate to
|
5
|
+
# the 'arp_header' method (assuming that it is a ARPHeader object)
|
6
|
+
module ARPHeaderMixin
|
7
|
+
def arp_hw=(v); self.arp_header.arp_hw= v; end
|
8
|
+
def arp_hw; self.arp_header.arp_hw; end
|
9
|
+
def arp_proto=(v); self.arp_header.arp_proto= v; end
|
10
|
+
def arp_proto; self.arp_header.arp_proto; end
|
11
|
+
def arp_hw_len=(v); self.arp_header.arp_hw_len= v; end
|
12
|
+
def arp_hw_len; self.arp_header.arp_hw_len; end
|
13
|
+
def arp_proto_len=(v); self.arp_header.arp_proto_len= v; end
|
14
|
+
def arp_proto_len; self.arp_header.arp_proto_len; end
|
15
|
+
def arp_opcode=(v); self.arp_header.arp_opcode= v; end
|
16
|
+
def arp_opcode; self.arp_header.arp_opcode; end
|
17
|
+
def arp_src_mac=(v); self.arp_header.arp_src_mac= v; end
|
18
|
+
def arp_src_mac; self.arp_header.arp_src_mac; end
|
19
|
+
def arp_src_ip=(v); self.arp_header.arp_src_ip= v; end
|
20
|
+
def arp_src_ip; self.arp_header.arp_src_ip; end
|
21
|
+
def arp_dst_mac=(v); self.arp_header.arp_dst_mac= v; end
|
22
|
+
def arp_dst_mac; self.arp_header.arp_dst_mac; end
|
23
|
+
def arp_dst_ip=(v); self.arp_header.arp_dst_ip= v; end
|
24
|
+
def arp_dst_ip; self.arp_header.arp_dst_ip; end
|
25
|
+
def arp_saddr_mac=(v); self.arp_header.arp_saddr_mac= v; end
|
26
|
+
def arp_saddr_mac; self.arp_header.arp_saddr_mac; end
|
27
|
+
def arp_daddr_mac=(v); self.arp_header.arp_daddr_mac= v; end
|
28
|
+
def arp_daddr_mac; self.arp_header.arp_daddr_mac; end
|
29
|
+
def arp_saddr_ip=(v); self.arp_header.arp_saddr_ip= v; end
|
30
|
+
def arp_saddr_ip; self.arp_header.arp_saddr_ip; end
|
31
|
+
def arp_daddr_ip=(v); self.arp_header.arp_daddr_ip= v; end
|
32
|
+
def arp_daddr_ip; self.arp_header.arp_daddr_ip; end
|
33
|
+
def arp_src_mac_readable; self.arp_header.arp_src_mac_readable; end
|
34
|
+
def arp_dst_mac_readable; self.arp_header.arp_dst_mac_readable; end
|
35
|
+
def arp_src_ip_readable; self.arp_header.arp_src_ip_readable; end
|
36
|
+
def arp_dst_ip_readable; self.arp_header.arp_dst_ip_readable; end
|
37
|
+
def arp_proto_readable; self.arp_header.arp_proto_readable; end
|
38
|
+
end
|
38
39
|
end
|
data/lib/packetfu/protos/eth.rb
CHANGED
@@ -1,53 +1,54 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
require 'packetfu/protos/eth/header'
|
2
3
|
require 'packetfu/protos/eth/mixin'
|
3
4
|
|
4
5
|
module PacketFu
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
6
|
+
# EthPacket is used to construct Ethernet packets. They contain an
|
7
|
+
# Ethernet header, and that's about it.
|
8
|
+
#
|
9
|
+
# == Example
|
10
|
+
#
|
11
|
+
# require 'packetfu'
|
12
|
+
# eth_pkt = PacketFu::EthPacket.new
|
13
|
+
# eth_pkt.eth_saddr="00:1c:23:44:55:66"
|
14
|
+
# eth_pkt.eth_daddr="00:1c:24:aa:bb:cc"
|
15
|
+
#
|
16
|
+
# eth_pkt.to_w('eth0') # Inject on the wire. (require root)
|
17
|
+
#
|
18
|
+
class EthPacket < Packet
|
18
19
|
include ::PacketFu::EthHeaderMixin
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
21
|
+
attr_accessor :eth_header
|
22
|
+
|
23
|
+
def self.can_parse?(str)
|
24
|
+
# XXX Temporary fix. Need to extend the EthHeader class to handle more.
|
25
|
+
valid_eth_types = [0x0800, 0x0806, 0x86dd, 0x88cc]
|
26
|
+
return false unless str.size >= 14
|
27
|
+
type = str[12,2].unpack("n").first rescue nil
|
28
|
+
return false unless valid_eth_types.include? type
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def read(str=nil,args={})
|
33
|
+
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
34
|
+
@eth_header.read(str)
|
35
|
+
super(args)
|
36
|
+
return self
|
37
|
+
end
|
38
|
+
|
39
|
+
# Does nothing, really, since there's no length or
|
40
|
+
# checksum to calculate for a straight Ethernet packet.
|
41
|
+
def recalc(args={})
|
42
|
+
@headers[0].inspect
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(args={})
|
46
|
+
@eth_header = EthHeader.new(args).read(args[:eth])
|
47
|
+
@headers = [@eth_header]
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
51
52
|
|
52
53
|
end
|
53
54
|
|
@@ -1,247 +1,248 @@
|
|
1
|
+
# -*- coding: binary -*-
|
1
2
|
module PacketFu
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
3
|
+
# EthOui is the Organizationally Unique Identifier portion of a MAC address, used in EthHeader.
|
4
|
+
#
|
5
|
+
# See the OUI list at http://standards.ieee.org/regauth/oui/oui.txt
|
6
|
+
#
|
7
|
+
# ==== Header Definition
|
8
|
+
#
|
9
|
+
# Fixnum :b0
|
10
|
+
# Fixnum :b1
|
11
|
+
# Fixnum :b2
|
12
|
+
# Fixnum :b3
|
13
|
+
# Fixnum :b4
|
14
|
+
# Fixnum :b5
|
15
|
+
# Fixnum :local
|
16
|
+
# Fixnum :multicast
|
17
|
+
# Int16 :oui, Default: 0x1ac5 :)
|
18
|
+
class EthOui < Struct.new(:b5, :b4, :b3, :b2, :b1, :b0, :local, :multicast, :oui)
|
19
|
+
|
20
|
+
# EthOui is unusual in that the bit values do not enjoy StructFu typing.
|
21
|
+
def initialize(args={})
|
22
|
+
args[:local] ||= 0
|
23
|
+
args[:oui] ||= 0x1ac # :)
|
24
|
+
args.each_pair {|k,v| args[k] = 0 unless v}
|
25
|
+
super(args[:b5], args[:b4], args[:b3], args[:b2],
|
26
|
+
args[:b1], args[:b0], args[:local], args[:multicast],
|
27
|
+
args[:oui])
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the object in string form.
|
31
|
+
def to_s
|
32
|
+
byte = 0
|
33
|
+
byte += 0b10000000 if b5.to_i == 1
|
34
|
+
byte += 0b01000000 if b4.to_i == 1
|
35
|
+
byte += 0b00100000 if b3.to_i == 1
|
36
|
+
byte += 0b00010000 if b2.to_i == 1
|
37
|
+
byte += 0b00001000 if b1.to_i == 1
|
38
|
+
byte += 0b00000100 if b0.to_i == 1
|
39
|
+
byte += 0b00000010 if local.to_i == 1
|
40
|
+
byte += 0b00000001 if multicast.to_i == 1
|
41
|
+
[byte,oui].pack("Cn")
|
42
|
+
end
|
43
|
+
|
44
|
+
# Reads a string to populate the object.
|
45
|
+
def read(str)
|
46
|
+
force_binary(str)
|
47
|
+
return self if str.nil?
|
48
|
+
if 1.respond_to? :ord
|
49
|
+
byte = str[0].ord
|
50
|
+
else
|
51
|
+
byte = str[0]
|
52
|
+
end
|
53
|
+
self[:b5] = byte & 0b10000000 == 0b10000000 ? 1 : 0
|
54
|
+
self[:b4] = byte & 0b01000000 == 0b01000000 ? 1 : 0
|
55
|
+
self[:b3] = byte & 0b00100000 == 0b00100000 ? 1 : 0
|
56
|
+
self[:b2] = byte & 0b00010000 == 0b00010000 ? 1 : 0
|
57
|
+
self[:b1] = byte & 0b00001000 == 0b00001000 ? 1 : 0
|
58
|
+
self[:b0] = byte & 0b00000100 == 0b00000100 ? 1 : 0
|
59
|
+
self[:local] = byte & 0b00000010 == 0b00000010 ? 1 : 0
|
60
|
+
self[:multicast] = byte & 0b00000001 == 0b00000001 ? 1 : 0
|
61
|
+
self[:oui] = str[1,2].unpack("n").first
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
65
66
|
|
66
67
|
# EthNic is the Network Interface Controler portion of a MAC address, used in EthHeader.
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
68
|
+
#
|
69
|
+
# ==== Header Definition
|
70
|
+
#
|
71
|
+
# Fixnum :n1
|
72
|
+
# Fixnum :n2
|
73
|
+
# Fixnum :n3
|
74
|
+
#
|
75
|
+
class EthNic < Struct.new(:n0, :n1, :n2)
|
76
|
+
|
77
|
+
# EthNic does not enjoy StructFu typing.
|
78
|
+
def initialize(args={})
|
79
|
+
args.each_pair {|k,v| args[k] = 0 unless v}
|
80
|
+
super(args[:n0], args[:n1], args[:n2])
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the object in string form.
|
84
|
+
def to_s
|
85
|
+
[n0,n1,n2].map {|x| x.to_i}.pack("C3")
|
86
|
+
end
|
87
|
+
|
88
|
+
# Reads a string to populate the object.
|
89
|
+
def read(str)
|
90
|
+
force_binary(str)
|
91
|
+
return self if str.nil?
|
92
|
+
self[:n0], self[:n1], self[:n2] = str[0,3].unpack("C3")
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
# EthMac is the combination of an EthOui and EthNic, used in EthHeader.
|
99
|
+
#
|
100
|
+
# ==== Header Definition
|
101
|
+
#
|
102
|
+
# EthOui :oui # See EthOui
|
103
|
+
# EthNic :nic # See EthNic
|
104
|
+
class EthMac < Struct.new(:oui, :nic)
|
105
|
+
|
106
|
+
def initialize(args={})
|
107
|
+
super(
|
108
|
+
EthOui.new.read(args[:oui]),
|
109
|
+
EthNic.new.read(args[:nic]))
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns the object in string form.
|
113
|
+
def to_s
|
114
|
+
"#{self[:oui]}#{self[:nic]}"
|
115
|
+
end
|
116
|
+
|
117
|
+
# Reads a string to populate the object.
|
118
|
+
def read(str)
|
119
|
+
force_binary(str)
|
120
|
+
return self if str.nil?
|
121
|
+
self.oui.read str[0,3]
|
122
|
+
self.nic.read str[3,3]
|
123
|
+
self
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
# EthHeader is a complete Ethernet struct, used in EthPacket.
|
129
|
+
# It's the base header for all other protocols, such as IPHeader,
|
130
|
+
# TCPHeader, etc.
|
131
|
+
#
|
132
|
+
# For more on the construction on MAC addresses, see
|
133
|
+
# http://en.wikipedia.org/wiki/MAC_address
|
134
|
+
#
|
135
|
+
# TODO: Need to come up with a good way of dealing with vlan
|
136
|
+
# tagging. Having a usually empty struct member seems weird,
|
137
|
+
# but there may not be another way to do it if I want to preserve
|
138
|
+
# the Eth-ness of vlan-tagged 802.1Q packets. Also, may as well
|
139
|
+
# deal with 0x88a8 as well (http://en.wikipedia.org/wiki/802.1ad)
|
140
|
+
#
|
141
|
+
# ==== Header Definition
|
142
|
+
#
|
143
|
+
# EthMac :eth_dst # See EthMac
|
144
|
+
# EthMac :eth_src # See EthMac
|
145
|
+
# Int16 :eth_proto, Default: 0x8000 # IP 0x0800, Arp 0x0806
|
146
|
+
# String :body
|
147
|
+
class EthHeader < Struct.new(:eth_dst, :eth_src, :eth_proto, :body)
|
148
|
+
include StructFu
|
149
|
+
|
150
|
+
def initialize(args={})
|
151
|
+
super(
|
152
|
+
EthMac.new.read(args[:eth_dst]),
|
153
|
+
EthMac.new.read(args[:eth_src]),
|
154
|
+
Int16.new(args[:eth_proto] || 0x0800),
|
155
|
+
StructFu::String.new.read(args[:body])
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Setter for the Ethernet destination address.
|
160
|
+
def eth_dst=(i); typecast(i); end
|
161
|
+
# Getter for the Ethernet destination address.
|
162
|
+
def eth_dst; self[:eth_dst].to_s; end
|
163
|
+
# Setter for the Ethernet source address.
|
164
|
+
def eth_src=(i); typecast(i); end
|
165
|
+
# Getter for the Ethernet source address.
|
166
|
+
def eth_src; self[:eth_src].to_s; end
|
167
|
+
# Setter for the Ethernet protocol number.
|
168
|
+
def eth_proto=(i); typecast(i); end
|
169
|
+
# Getter for the Ethernet protocol number.
|
170
|
+
def eth_proto; self[:eth_proto].to_i; end
|
171
|
+
|
172
|
+
# Returns the object in string form.
|
173
|
+
def to_s
|
174
|
+
self.to_a.map {|x| x.to_s}.join
|
175
|
+
end
|
176
|
+
|
177
|
+
# Reads a string to populate the object.
|
178
|
+
def read(str)
|
179
|
+
force_binary(str)
|
180
|
+
return self if str.nil?
|
181
|
+
self[:eth_dst].read str[0,6]
|
182
|
+
self[:eth_src].read str[6,6]
|
183
|
+
self[:eth_proto].read str[12,2]
|
184
|
+
self[:body].read str[14,str.size]
|
185
|
+
self
|
186
|
+
end
|
187
|
+
|
188
|
+
# Converts a readable MAC (11:22:33:44:55:66) to a binary string.
|
189
|
+
# Readable MAC's may be split on colons, dots, spaces, or underscores.
|
190
|
+
#
|
191
|
+
# irb> PacketFu::EthHeader.mac2str("11:22:33:44:55:66")
|
192
|
+
#
|
193
|
+
# #=> "\021\"3DUf"
|
194
|
+
def self.mac2str(mac)
|
195
|
+
if mac.split(/[:\x2d\x2e\x5f]+/).size == 6
|
196
|
+
ret = mac.split(/[:\x2d\x2e\x20\x5f]+/).collect {|x| x.to_i(16)}.pack("C6")
|
197
|
+
else
|
198
|
+
raise ArgumentError, "Unkown format for mac address."
|
199
|
+
end
|
200
|
+
return ret
|
201
|
+
end
|
202
|
+
|
203
|
+
# Converts a binary string to a readable MAC (11:22:33:44:55:66).
|
204
|
+
#
|
205
|
+
# irb> PacketFu::EthHeader.str2mac("\x11\x22\x33\x44\x55\x66")
|
206
|
+
#
|
207
|
+
# #=> "11:22:33:44:55:66"
|
208
|
+
def self.str2mac(mac='')
|
209
|
+
if mac.to_s.size == 6 && mac.kind_of?(::String)
|
210
|
+
ret = mac.unpack("C6").map {|x| sprintf("%02x",x)}.join(":")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Sets the source MAC address in a more readable way.
|
215
|
+
def eth_saddr=(mac)
|
216
|
+
mac = EthHeader.mac2str(mac)
|
217
|
+
self[:eth_src].read mac
|
218
|
+
self[:eth_src]
|
219
|
+
end
|
220
|
+
|
221
|
+
# Gets the source MAC address in a more readable way.
|
222
|
+
def eth_saddr
|
223
|
+
EthHeader.str2mac(self[:eth_src].to_s)
|
224
|
+
end
|
225
|
+
|
226
|
+
# Set the destination MAC address in a more readable way.
|
227
|
+
def eth_daddr=(mac)
|
228
|
+
mac = EthHeader.mac2str(mac)
|
229
|
+
self[:eth_dst].read mac
|
230
|
+
self[:eth_dst]
|
231
|
+
end
|
232
|
+
|
233
|
+
# Gets the destination MAC address in a more readable way.
|
234
|
+
def eth_daddr
|
235
|
+
EthHeader.str2mac(self[:eth_dst].to_s)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Readability aliases
|
239
|
+
|
240
|
+
alias :eth_dst_readable :eth_daddr
|
241
|
+
alias :eth_src_readable :eth_saddr
|
242
|
+
|
243
|
+
def eth_proto_readable
|
244
|
+
"0x%04x" % eth_proto
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
247
248
|
end
|