dot11 0.1.0
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.markdown +4 -0
- data/lib/dot11.rb +17 -0
- data/lib/dot11/dot11.rb +974 -0
- data/lib/dot11/macaddress.rb +51 -0
- data/lib/dot11/packet.rb +45 -0
- data/lib/dot11/packetset.rb +253 -0
- data/lib/dot11/radiotap.rb +37 -0
- data/lib/dot11/raw.rb +19 -0
- data/tests/dot11_test.rb +133 -0
- metadata +64 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
module Dot11
|
2
|
+
class MACAddress
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
attr_accessor :prefix_length
|
6
|
+
|
7
|
+
def initialize(address)
|
8
|
+
if address.kind_of?(Integer)
|
9
|
+
@address = [address].pack("Q").unpack("C8")[0, 6].reverse
|
10
|
+
elsif address.kind_of?(String) && address =~ /^(.*?)(?:\/(.*))?$/
|
11
|
+
@prefix_length = $2.to_i
|
12
|
+
|
13
|
+
@address = $1.split(":").map {|octet| octet.to_i(16)}
|
14
|
+
elsif address.kind_of?(Array)
|
15
|
+
@address = address
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_i
|
20
|
+
("\x00\x00" + @address.pack("C6")).reverse.unpack("Q")[0]
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
@address.map{|byte| "%02x" % byte}.join(":") + (@prefix_length == 0 ? "" : "/#{@prefix_length}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def inspect
|
28
|
+
to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_arr
|
32
|
+
@address
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](*index)
|
36
|
+
@address[*index]
|
37
|
+
end
|
38
|
+
|
39
|
+
def eql?(other)
|
40
|
+
to_i == other.to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
def ==(other)
|
44
|
+
eql?(other)
|
45
|
+
end
|
46
|
+
|
47
|
+
def hash
|
48
|
+
to_i.hash
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/dot11/packet.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'packetset'))
|
2
|
+
|
3
|
+
module Dot11
|
4
|
+
class Packet
|
5
|
+
class <<self
|
6
|
+
alias older_new new
|
7
|
+
|
8
|
+
def new(parameters = {})
|
9
|
+
# Maybe we shouldn't do it this way, but it looks prettier
|
10
|
+
if !parameters.kind_of?(String) && parameters.values.any? {|v| v.kind_of?(Array) || v.kind_of?(Range)}
|
11
|
+
PacketSet.new(self, parameters)
|
12
|
+
else
|
13
|
+
older_new(parameters)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(parameters = {})
|
19
|
+
if parameters.kind_of?(String)
|
20
|
+
dissect(parameters)
|
21
|
+
elsif parameters.kind_of?(Hash)
|
22
|
+
parameters.each_pair do |key, value|
|
23
|
+
send((key.to_s + "=").intern, value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def =~(other)
|
29
|
+
if other.kind_of?(Hash)
|
30
|
+
other.each_pair do |key, value|
|
31
|
+
return false if self.send(key) != value
|
32
|
+
end
|
33
|
+
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_filter
|
39
|
+
PacketSet.new(self.class, self.instance_variables.inject({}) do |accum, var|
|
40
|
+
accum[var[1..-1].intern] = self.instance_variable_get(var).kind_of?(MACAddress) ? self.instance_variable_get(var).to_s : self.instance_variable_get(var).to_s
|
41
|
+
accum
|
42
|
+
end).to_filter
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
module Dot11
|
2
|
+
class PacketSet
|
3
|
+
Pair = Struct.new(:name, :value)
|
4
|
+
|
5
|
+
attr_accessor :packet_class
|
6
|
+
attr_reader :fields
|
7
|
+
|
8
|
+
def initialize(klass, parameters)
|
9
|
+
@fields = []
|
10
|
+
|
11
|
+
@packet_class = klass
|
12
|
+
|
13
|
+
parameters.each_pair do |key, value|
|
14
|
+
@fields << Pair.new(key, value)
|
15
|
+
end
|
16
|
+
|
17
|
+
@field_sizes = @fields.map do |field|
|
18
|
+
if field.value.respond_to?(:size) && !(field.value.kind_of?(String) || field.value.kind_of?(Numeric))
|
19
|
+
field.value.size
|
20
|
+
elsif field.value.respond_to?(:entries)
|
21
|
+
field.value.entries.size
|
22
|
+
else
|
23
|
+
field.value = [field.value]
|
24
|
+
1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def [](index)
|
30
|
+
indices = @field_sizes.inject([]) do |accumulator, size|
|
31
|
+
remainder = index % size
|
32
|
+
index /= size # yeah textmate isn't perfect and that's why I need this slash: /
|
33
|
+
accumulator << remainder
|
34
|
+
end
|
35
|
+
|
36
|
+
field_hash = {}
|
37
|
+
|
38
|
+
indices.each_with_index do |index, i|
|
39
|
+
value = @fields[i].value
|
40
|
+
|
41
|
+
if value.kind_of?(Array) or value.kind_of?(Range)
|
42
|
+
field_hash[@fields[i].name] = @fields[i].value.entries[index]
|
43
|
+
else
|
44
|
+
field_hash[@fields[i].name] = @fields[i].value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
out = @packet_class.new(field_hash)
|
49
|
+
|
50
|
+
out
|
51
|
+
end
|
52
|
+
|
53
|
+
def size
|
54
|
+
@field_sizes.inject(1) { |product, size| size * product }
|
55
|
+
end
|
56
|
+
|
57
|
+
def each(prefix = [])
|
58
|
+
size.times do |i|
|
59
|
+
yield self[i]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def each_with_index
|
64
|
+
size.times do |i|
|
65
|
+
yield self[i], i
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def include?(packet)
|
70
|
+
# This is horrrrrribly inefficient. FIXME
|
71
|
+
each do |pkt|
|
72
|
+
return true if packet == pkt
|
73
|
+
end
|
74
|
+
|
75
|
+
false
|
76
|
+
end
|
77
|
+
|
78
|
+
def bitrange_to_filter(offset, size, bitrange, desired, negated = false)
|
79
|
+
# TODO: Take bitrange.exclude_end? into account
|
80
|
+
mask = ((2 << (bitrange.end - bitrange.begin)) - 1) << bitrange.begin
|
81
|
+
|
82
|
+
value = "(ether[#{offset}:#{size}] & #{'%#x' % mask}) >> #{bitrange.begin}"
|
83
|
+
|
84
|
+
case desired
|
85
|
+
when Range
|
86
|
+
"(#{value} >= #{'%#x' % desired.begin} && #{value} #{desired.exclude_end? ? "<" : "<="} #{'%#x' % desired.end})"
|
87
|
+
when Array
|
88
|
+
# TODO: deal with arrays of ranges
|
89
|
+
'(' + desired.map {|d| "#{value} = #{'%#x' % d}"}.join(" || ") + ')'
|
90
|
+
when Numeric, String
|
91
|
+
"#{value} #{negated ? '!' : ''}= #{'%#x' % desired.to_i}"
|
92
|
+
else
|
93
|
+
raise "unknown"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def int_to_filter(offset, size, desired, negated = false)
|
98
|
+
value = "ether[#{offset}:#{size}]"
|
99
|
+
|
100
|
+
case desired
|
101
|
+
when Range
|
102
|
+
"(#{value} >= #{'%#x' % desired.begin} && #{value} #{desired.exclude_end? ? "<" : "<="} #{'%#x' % desired.end})"
|
103
|
+
when Array
|
104
|
+
# TODO: deal with arrays of ranges
|
105
|
+
desired.map {|d| "#{value} #{negated ? '!' : ''}= #{'%#x' % d}"}.join(" || ")
|
106
|
+
when Numeric
|
107
|
+
"#{value} #{negated ? '!' : ''}= #{'%#x' % desired}"
|
108
|
+
else
|
109
|
+
raise "unknown desired: #{desired.inspect}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def mac_to_filter(offset, size, desired, negated = false)
|
114
|
+
case desired
|
115
|
+
when Range
|
116
|
+
raise "Range of MAC addresses in filter not yet implemented"
|
117
|
+
when Array
|
118
|
+
'(' + desired.map do |d|
|
119
|
+
desired = MACAddress.new(desired) if desired.kind_of?(String)
|
120
|
+
first_four = desired[0, 4].pack("CCCC").unpack("N")[0]
|
121
|
+
second_two = desired[4, 2].pack("CC").unpack("n")[0]
|
122
|
+
|
123
|
+
"(ether[#{offset}:2] = #{'%#x' % first_four} && ether[#{offset + 4}:2] = #{'%#x' % second_two})"
|
124
|
+
end.join(" || ") + ')'
|
125
|
+
when Numeric
|
126
|
+
|
127
|
+
when MACAddress, String
|
128
|
+
desired = MACAddress.new(desired) if desired.kind_of?(String)
|
129
|
+
first_four = desired[0, 4].pack("CCCC").unpack("N")[0]
|
130
|
+
second_two = desired[4, 2].pack("CC").unpack("n")[0]
|
131
|
+
|
132
|
+
|
133
|
+
if desired.prefix_length == 32
|
134
|
+
"ether[#{offset}:4] = #{'%#x' % first_four}"
|
135
|
+
elsif desired.prefix_length == 48 || desired.prefix_length == 0
|
136
|
+
"(ether[#{offset}:4] = #{'%#x' % first_four} && ether[#{offset + 4}:2] = #{'%#x' % second_two})"
|
137
|
+
else
|
138
|
+
raise "unsupport prefix length #{desired.prefix_length}"
|
139
|
+
end
|
140
|
+
else
|
141
|
+
raise "unknown"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def decode_condition(fields, condition)
|
146
|
+
case condition
|
147
|
+
when Array
|
148
|
+
condition.map{|x| decode_condition(fields, x)}.join(" || ")
|
149
|
+
when Hash
|
150
|
+
condition.map do |key, value|
|
151
|
+
# Decode the nasty negation syntax
|
152
|
+
negated, value = value.kind_of?(Array) && value.size == 1 ? [true, value[0]] : [false, value]
|
153
|
+
|
154
|
+
field_info = fields.find{|x| key == x[0]}[1]
|
155
|
+
|
156
|
+
case field_info[:type]
|
157
|
+
when :int
|
158
|
+
if field_info.has_key?(:bitrange)
|
159
|
+
bitrange_to_filter(field_info[:offset], field_info[:size], field_info[:bitrange], value, negated)
|
160
|
+
else
|
161
|
+
int_to_filter(field_info[:offset], field_info[:size], value, negated)
|
162
|
+
end
|
163
|
+
when :mac
|
164
|
+
mac_to_filter(field_info[:offset], field_info[:size], value, negated)
|
165
|
+
else
|
166
|
+
raise "unknown"
|
167
|
+
end
|
168
|
+
end.join(" && ")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def to_filter
|
173
|
+
fields = @packet_class.fields
|
174
|
+
|
175
|
+
@fields.map do |field|
|
176
|
+
'(' + begin
|
177
|
+
field_info = fields.find{|x| field.name == x[0]}
|
178
|
+
|
179
|
+
if field_info.nil?
|
180
|
+
raise "nil field_info"
|
181
|
+
end
|
182
|
+
|
183
|
+
field_info = field_info[1]
|
184
|
+
|
185
|
+
# We don't really want to do this
|
186
|
+
if field_info.nil?
|
187
|
+
raise "nil field_info 2"
|
188
|
+
end
|
189
|
+
|
190
|
+
if field_info.has_key?(:condition)
|
191
|
+
if !field_info[:offset].kind_of?(Numeric)
|
192
|
+
field_info[:offset].map do |key, value|
|
193
|
+
'(' + begin
|
194
|
+
if key == :else
|
195
|
+
field_info[:offset].keys.reject{|k| k == :else}.map do |k|
|
196
|
+
'!(' + decode_condition(fields, k) + ')'
|
197
|
+
end.join(" && ")
|
198
|
+
else
|
199
|
+
'(' + decode_condition(fields, key) + ') && (' + begin
|
200
|
+
case field_info[:type]
|
201
|
+
when :int
|
202
|
+
if field_info.has_key?(:bitrange)
|
203
|
+
bitrange_to_filter(value, field_info[:size], field_info[:bitrange], field.value)
|
204
|
+
else
|
205
|
+
int_to_filter(value, field_info[:size], field.value)
|
206
|
+
end
|
207
|
+
when :mac
|
208
|
+
mac_to_filter(value, field_info[:size], field.value)
|
209
|
+
else
|
210
|
+
raise "unknown"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end + ')'
|
215
|
+
end.join(" && ")
|
216
|
+
else
|
217
|
+
'((' + decode_condition(fields, field_info[:condition]) +') && ('+ case field_info[:type]
|
218
|
+
when :int
|
219
|
+
if field_info.has_key?(:bitrange)
|
220
|
+
bitrange_to_filter(field_info[:offset], field_info[:size], field_info[:bitrange], field.value)
|
221
|
+
else
|
222
|
+
int_to_filter(field_info[:offset], field_info[:size], field.value)
|
223
|
+
end
|
224
|
+
when :mac
|
225
|
+
mac_to_filter(field_info[:offset], field_info[:size], field.value)
|
226
|
+
else
|
227
|
+
raise "unknown"
|
228
|
+
end + '))'
|
229
|
+
end
|
230
|
+
else
|
231
|
+
if !field_info[:offset].kind_of?(Numeric)
|
232
|
+
p "moo"
|
233
|
+
"can"
|
234
|
+
else
|
235
|
+
case field_info[:type]
|
236
|
+
when :int
|
237
|
+
if field_info.has_key?(:bitrange)
|
238
|
+
bitrange_to_filter(field_info[:offset], field_info[:size], field_info[:bitrange], field.value)
|
239
|
+
else
|
240
|
+
int_to_filter(field_info[:offset], field_info[:size], field.value)
|
241
|
+
end
|
242
|
+
when :mac
|
243
|
+
mac_to_filter(field_info[:offset], field_info[:size], field.value)
|
244
|
+
else
|
245
|
+
raise "unknown"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end + ')'
|
250
|
+
end.join(" && ")
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'packet'))
|
2
|
+
|
3
|
+
module Dot11
|
4
|
+
class Radiotap < Packet
|
5
|
+
attr_accessor :revision, :pad, :stuff_length, :stuff
|
6
|
+
|
7
|
+
def data
|
8
|
+
raise "This space intentionally left blank"
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"Radiotap\n" +
|
13
|
+
"-------------\n" +
|
14
|
+
"payload:\n" +
|
15
|
+
payload.to_s.indent(6)
|
16
|
+
end
|
17
|
+
|
18
|
+
def payload
|
19
|
+
return @payload if @payload
|
20
|
+
|
21
|
+
@payload = Dot11.new(@rest)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def dissect(data)
|
27
|
+
fields = data.unpack("CCv")
|
28
|
+
|
29
|
+
@data = data
|
30
|
+
@revision = fields[0]
|
31
|
+
@pad = fields[1]
|
32
|
+
@stuff_length = fields[2]
|
33
|
+
|
34
|
+
@rest = data[@stuff_length..-1]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/dot11/raw.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'packet'))
|
2
|
+
|
3
|
+
module Dot11
|
4
|
+
class Raw < Packet
|
5
|
+
attr_accessor :data
|
6
|
+
|
7
|
+
def to_s
|
8
|
+
"Raw\n" +
|
9
|
+
"------\n" +
|
10
|
+
"data: #{data.inspect}\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def dissect(data)
|
16
|
+
@data = data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/tests/dot11_test.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'dot11', 'dot11'))
|
2
|
+
|
3
|
+
include Dot11
|
4
|
+
|
5
|
+
def test(klass, raw, packet, test_desc)
|
6
|
+
dissector = (klass.new(raw) == packet)
|
7
|
+
builder = (packet.data == raw)
|
8
|
+
|
9
|
+
puts "#{klass} dissector #{dissector ? 'passed' : 'failed'} on #{test_desc}"
|
10
|
+
puts "#{klass} builder #{builder ? 'passed' : 'failed'} on #{test_desc}"
|
11
|
+
end
|
12
|
+
|
13
|
+
#####################################################################################
|
14
|
+
|
15
|
+
beacon_raw = "\x80\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x01\xe3\x41\xbd\x6e\x00\x01\xe3\x41\xbd\x6e\x00\x0e"
|
16
|
+
beacon = Dot11.new(:type => 0,
|
17
|
+
:subtype => 8,
|
18
|
+
:version => 0,
|
19
|
+
:flags => 0,
|
20
|
+
:duration => 0,
|
21
|
+
:addr1 => "ff:ff:ff:ff:ff:ff",
|
22
|
+
:addr2 => "00:01:e3:41:bd:6e",
|
23
|
+
:addr3 => "00:01:e3:41:bd:6e",
|
24
|
+
:sc => 0x0e00)
|
25
|
+
|
26
|
+
test(Dot11, beacon_raw, beacon, "beacon frame")
|
27
|
+
|
28
|
+
#####################################################################################
|
29
|
+
|
30
|
+
data_raw = "\x08\x42\x00\x00\xff\xff\xff\xff\xff\xff\x00\x01\xe3\x41\xbd\x6e\x00\x01\xe3\x42\x9e\x2b\x40\x07"
|
31
|
+
data = Dot11.new(:type => 2,
|
32
|
+
:subtype => 0,
|
33
|
+
:version => 0,
|
34
|
+
:flags => 0x42,
|
35
|
+
:duration => 0,
|
36
|
+
:addr1 => "ff:ff:ff:ff:ff:ff",
|
37
|
+
:addr2 => "00:01:e3:41:bd:6e",
|
38
|
+
:addr3 => "00:01:e3:42:9e:2b",
|
39
|
+
:sc => 0x0740)
|
40
|
+
|
41
|
+
test(Dot11, data_raw, data, "data frame")
|
42
|
+
|
43
|
+
#####################################################################################
|
44
|
+
|
45
|
+
complete_beacon_raw = "\x80\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x01\xe3\x41\xbd\x6e" +
|
46
|
+
"\x00\x01\xe3\x41\xbd\x6e\xf0\x02\x86\xf1\x1b\x6a\x02\x00\x00\x00" +
|
47
|
+
"\x64\x00\x11\x04\x00\x09\x6d\x61\x72\x74\x69\x6e\x65\x74\x33\x01" +
|
48
|
+
"\x08\x82\x84\x8b\x96\x24\x30\x48\x6c\x03\x01\x0b\x05\x04\x00\x01" +
|
49
|
+
"\x00\x00\x2a\x01\x04\x2f\x01\x04\x32\x04\x0c\x12\x18\x60\xdd\x06" +
|
50
|
+
"\x00\x10\x18\x01\x01\x00\xdd\x16\x00\x50\xf2\x01\x01\x00\x00\x50" +
|
51
|
+
"\xf2\x02\x01\x00\x00\x50\xf2\x02\x01\x00\x00\x50\xf2\x02"
|
52
|
+
complete_beacon = Dot11.new(:type => 0,
|
53
|
+
:subtype => 8,
|
54
|
+
:version => 0,
|
55
|
+
:flags => 0,
|
56
|
+
:duration => 0,
|
57
|
+
:addr1 => "ff:ff:ff:ff:ff:ff",
|
58
|
+
:addr2 => "00:01:e3:41:bd:6e",
|
59
|
+
:addr3 => "00:01:e3:41:bd:6e",
|
60
|
+
:sc => 0x02f0) /
|
61
|
+
Dot11Beacon.new(:timestamp => 0x26a1bf186,
|
62
|
+
:beacon_interval => 0x64,
|
63
|
+
:capabilities => 0x1104) /
|
64
|
+
Dot11Elt.new(:id => 0,
|
65
|
+
:info_length => 9,
|
66
|
+
:info => "martinet3") /
|
67
|
+
Dot11Elt.new(:id => 1,
|
68
|
+
:info_length => 8,
|
69
|
+
:info => "\x82\x84\x8b\x96\x24\x30\x48\x6c") /
|
70
|
+
Dot11Elt.new(:id => 3,
|
71
|
+
:info_length => 1,
|
72
|
+
:info => "\x0b") /
|
73
|
+
Dot11Elt.new(:id => 5,
|
74
|
+
:info_length => 4,
|
75
|
+
:info => "\x00\x01\x00\x00") /
|
76
|
+
Dot11Elt.new(:id => 42,
|
77
|
+
:info_length => 1,
|
78
|
+
:info => "\x04") /
|
79
|
+
Dot11Elt.new(:id => 47,
|
80
|
+
:info_length => 1,
|
81
|
+
:info => "\x04") /
|
82
|
+
Dot11Elt.new(:id => 50,
|
83
|
+
:info_length => 4,
|
84
|
+
:info => "\x0c\x12\x18\x60") /
|
85
|
+
Dot11Elt.new(:id => 221,
|
86
|
+
:info_length => 6,
|
87
|
+
:info => "\x00\x10\x18\x01\x01\x00") /
|
88
|
+
Dot11Elt.new(:id => 221,
|
89
|
+
:info_length => 22,
|
90
|
+
:info => "\x00\x50\xf2\x01\x01\x00\x00\x50\xf2\x02\x01\x00\x00\x50\xf2\x02\x01\x00\x00\x50\xf2\x02")
|
91
|
+
|
92
|
+
test(Dot11, complete_beacon_raw, complete_beacon, "complete beacon frame")
|
93
|
+
p complete_beacon
|
94
|
+
|
95
|
+
#####################################################################################
|
96
|
+
|
97
|
+
acknowledgement_raw = "\xd4\x00\x00\x00\x00\x15\x00\x34\x18\x52"
|
98
|
+
acknowledgement = Dot11.new(:type => 1,
|
99
|
+
:subtype => 13,
|
100
|
+
:version => 0,
|
101
|
+
:flags => 0,
|
102
|
+
:duration => 0,
|
103
|
+
:addr1 => "00:15:00:34:18:52")
|
104
|
+
|
105
|
+
test(Dot11, acknowledgement_raw, acknowledgement, "acknowledgement frame")
|
106
|
+
puts("Passed to_i test") if acknowledgement.addr1.to_i == 0x1500341852
|
107
|
+
p acknowledgement
|
108
|
+
|
109
|
+
#####################################################################################
|
110
|
+
|
111
|
+
probereq_raw = "\x40\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x16\xbc\x3d\xaa\x57\xff" +
|
112
|
+
"\xff\xff\xff\xff\xff\xb0\x00\x00\x09\x6d\x61\x72\x74\x69\x6e\x65\x74" +
|
113
|
+
"\x33\x01\x08\x82\x84\x8b\x96\x0c\x12\x18\x24\x03\x01\x09\x32\x04\x30" +
|
114
|
+
"\x48\x60\x6c"
|
115
|
+
probereq = Dot11.new(:type => 0,
|
116
|
+
:subtype => 4,
|
117
|
+
:version => 0,
|
118
|
+
:flags => 0,
|
119
|
+
:duration => 0,
|
120
|
+
:addr1 => "ff:ff:ff:ff:ff:ff",
|
121
|
+
:addr2 => "00:16:bc:3d:aa:57",
|
122
|
+
:addr3 => "ff:ff:ff:ff:ff:ff",
|
123
|
+
:sc => 0x00b0) /
|
124
|
+
Dot11ProbeReq.new() /
|
125
|
+
Dot11Elt.new(:id => 0, :info_length => 9, :info => "martinet3") /
|
126
|
+
Dot11Elt.new(:id => 1, :info_length => 8, :info => "\x82\x84\x8b\x96\x0c\x12\x18\x24") /
|
127
|
+
Dot11Elt.new(:id => 3, :info_length => 1, :info => "\x09") /
|
128
|
+
Dot11Elt.new(:id => 50, :info_length => 4, :info => "\x30\x48\x60\x6c")
|
129
|
+
|
130
|
+
test(Dot11, probereq_raw, probereq, "probe request frame")
|
131
|
+
p probereq
|
132
|
+
|
133
|
+
#####################################################################################
|