packetgen 2.6.0 → 2.7.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.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +28 -0
  4. data/Rakefile +6 -6
  5. data/bin/pgconsole +6 -6
  6. data/lib/packetgen.rb +4 -3
  7. data/lib/packetgen/capture.rb +5 -7
  8. data/lib/packetgen/config.rb +3 -3
  9. data/lib/packetgen/deprecation.rb +17 -0
  10. data/lib/packetgen/header.rb +40 -38
  11. data/lib/packetgen/header/arp.rb +46 -31
  12. data/lib/packetgen/header/asn1_base.rb +8 -8
  13. data/lib/packetgen/header/base.rb +108 -36
  14. data/lib/packetgen/header/bootp.rb +28 -19
  15. data/lib/packetgen/header/crypto.rb +6 -8
  16. data/lib/packetgen/header/dhcp.rb +4 -5
  17. data/lib/packetgen/header/dhcp/option.rb +46 -34
  18. data/lib/packetgen/header/dhcp/options.rb +0 -1
  19. data/lib/packetgen/header/dhcpv6.rb +10 -10
  20. data/lib/packetgen/header/dhcpv6/duid.rb +2 -3
  21. data/lib/packetgen/header/dhcpv6/option.rb +16 -21
  22. data/lib/packetgen/header/dhcpv6/relay.rb +6 -4
  23. data/lib/packetgen/header/dns.rb +13 -11
  24. data/lib/packetgen/header/dns/name.rb +4 -6
  25. data/lib/packetgen/header/dns/opt.rb +31 -31
  26. data/lib/packetgen/header/dns/option.rb +0 -2
  27. data/lib/packetgen/header/dns/qdsection.rb +1 -2
  28. data/lib/packetgen/header/dns/question.rb +19 -13
  29. data/lib/packetgen/header/dns/rr.rb +11 -14
  30. data/lib/packetgen/header/dns/rrsection.rb +5 -7
  31. data/lib/packetgen/header/dot11.rb +45 -29
  32. data/lib/packetgen/header/dot11/control.rb +3 -5
  33. data/lib/packetgen/header/dot11/data.rb +34 -6
  34. data/lib/packetgen/header/dot11/element.rb +0 -1
  35. data/lib/packetgen/header/dot11/management.rb +9 -5
  36. data/lib/packetgen/header/dot11/sub_mngt.rb +13 -14
  37. data/lib/packetgen/header/dot1q.rb +2 -2
  38. data/lib/packetgen/header/dot1x.rb +3 -4
  39. data/lib/packetgen/header/eap.rb +62 -53
  40. data/lib/packetgen/header/eap/fast.rb +0 -1
  41. data/lib/packetgen/header/eap/md5.rb +1 -2
  42. data/lib/packetgen/header/eap/tls.rb +9 -10
  43. data/lib/packetgen/header/eap/ttls.rb +9 -10
  44. data/lib/packetgen/header/esp.rb +33 -33
  45. data/lib/packetgen/header/eth.rb +11 -8
  46. data/lib/packetgen/header/gre.rb +5 -6
  47. data/lib/packetgen/header/http/headers.rb +11 -14
  48. data/lib/packetgen/header/http/request.rb +20 -20
  49. data/lib/packetgen/header/http/response.rb +16 -18
  50. data/lib/packetgen/header/http/verbs.rb +5 -5
  51. data/lib/packetgen/header/icmp.rb +1 -3
  52. data/lib/packetgen/header/icmpv6.rb +1 -3
  53. data/lib/packetgen/header/igmp.rb +5 -6
  54. data/lib/packetgen/header/igmpv3.rb +5 -9
  55. data/lib/packetgen/header/igmpv3/group_record.rb +4 -5
  56. data/lib/packetgen/header/igmpv3/mq.rb +2 -2
  57. data/lib/packetgen/header/igmpv3/mr.rb +4 -3
  58. data/lib/packetgen/header/ike.rb +33 -8
  59. data/lib/packetgen/header/ike/auth.rb +4 -6
  60. data/lib/packetgen/header/ike/cert.rb +0 -2
  61. data/lib/packetgen/header/ike/certreq.rb +1 -3
  62. data/lib/packetgen/header/ike/id.rb +1 -3
  63. data/lib/packetgen/header/ike/ke.rb +0 -2
  64. data/lib/packetgen/header/ike/nonce.rb +0 -2
  65. data/lib/packetgen/header/ike/notify.rb +22 -24
  66. data/lib/packetgen/header/ike/payload.rb +198 -199
  67. data/lib/packetgen/header/ike/sa.rb +21 -30
  68. data/lib/packetgen/header/ike/sk.rb +16 -17
  69. data/lib/packetgen/header/ike/ts.rb +22 -24
  70. data/lib/packetgen/header/ike/vendor_id.rb +0 -2
  71. data/lib/packetgen/header/ip.rb +30 -23
  72. data/lib/packetgen/header/ip/addr.rb +5 -6
  73. data/lib/packetgen/header/ip/option.rb +11 -15
  74. data/lib/packetgen/header/ip/options.rb +1 -2
  75. data/lib/packetgen/header/ipv6.rb +27 -12
  76. data/lib/packetgen/header/ipv6/addr.rb +2 -2
  77. data/lib/packetgen/header/ipv6/extension.rb +1 -1
  78. data/lib/packetgen/header/ipv6/hop_by_hop.rb +11 -11
  79. data/lib/packetgen/header/llc.rb +4 -3
  80. data/lib/packetgen/header/mdns.rb +11 -5
  81. data/lib/packetgen/header/mld.rb +4 -4
  82. data/lib/packetgen/header/mldv2.rb +4 -3
  83. data/lib/packetgen/header/mldv2/mcast_address_record.rb +3 -4
  84. data/lib/packetgen/header/mldv2/mlq.rb +3 -4
  85. data/lib/packetgen/header/mldv2/mlr.rb +4 -3
  86. data/lib/packetgen/header/netbios.rb +18 -5
  87. data/lib/packetgen/header/ospfv2.rb +6 -7
  88. data/lib/packetgen/header/ospfv2/db_description.rb +3 -4
  89. data/lib/packetgen/header/ospfv2/hello.rb +2 -3
  90. data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -3
  91. data/lib/packetgen/header/ospfv2/ls_request.rb +2 -3
  92. data/lib/packetgen/header/ospfv2/ls_update.rb +5 -6
  93. data/lib/packetgen/header/ospfv2/lsa.rb +13 -14
  94. data/lib/packetgen/header/ospfv2/lsa_header.rb +4 -5
  95. data/lib/packetgen/header/ospfv3.rb +3 -4
  96. data/lib/packetgen/header/ospfv3/db_description.rb +3 -5
  97. data/lib/packetgen/header/ospfv3/hello.rb +2 -3
  98. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +7 -8
  99. data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -3
  100. data/lib/packetgen/header/ospfv3/ls_request.rb +2 -3
  101. data/lib/packetgen/header/ospfv3/ls_update.rb +5 -6
  102. data/lib/packetgen/header/ospfv3/lsa.rb +10 -11
  103. data/lib/packetgen/header/ospfv3/lsa_header.rb +3 -4
  104. data/lib/packetgen/header/snmp.rb +45 -32
  105. data/lib/packetgen/header/tcp.rb +13 -9
  106. data/lib/packetgen/header/tcp/option.rb +16 -11
  107. data/lib/packetgen/header/tcp/options.rb +3 -4
  108. data/lib/packetgen/header/tftp.rb +15 -17
  109. data/lib/packetgen/header/udp.rb +10 -4
  110. data/lib/packetgen/inspect.rb +7 -9
  111. data/lib/packetgen/packet.rb +44 -22
  112. data/lib/packetgen/pcapng.rb +1 -5
  113. data/lib/packetgen/pcapng/block.rb +17 -11
  114. data/lib/packetgen/pcapng/epb.rb +6 -11
  115. data/lib/packetgen/pcapng/file.rb +37 -44
  116. data/lib/packetgen/pcapng/idb.rb +17 -22
  117. data/lib/packetgen/pcapng/shb.rb +7 -10
  118. data/lib/packetgen/pcapng/spb.rb +21 -17
  119. data/lib/packetgen/pcapng/unknown_block.rb +17 -13
  120. data/lib/packetgen/proto.rb +1 -2
  121. data/lib/packetgen/types/array.rb +119 -34
  122. data/lib/packetgen/types/cstring.rb +1 -5
  123. data/lib/packetgen/types/enum.rb +8 -10
  124. data/lib/packetgen/types/fields.rb +34 -28
  125. data/lib/packetgen/types/int.rb +11 -13
  126. data/lib/packetgen/types/int_string.rb +6 -8
  127. data/lib/packetgen/types/oui.rb +3 -6
  128. data/lib/packetgen/types/string.rb +4 -6
  129. data/lib/packetgen/types/tlv.rb +11 -14
  130. data/lib/packetgen/utils.rb +15 -23
  131. data/lib/packetgen/utils/arp_spoofer.rb +12 -18
  132. data/lib/packetgen/version.rb +1 -1
  133. data/packetgen.gemspec +9 -8
  134. metadata +19 -17
@@ -8,11 +8,9 @@
8
8
  module PacketGen
9
9
  module Header
10
10
  class DNS
11
-
12
11
  # DNS option
13
12
  # @author Sylvain Daubert
14
13
  class Option < Types::TLV
15
-
16
14
  # Force {#type} and {#length} fields to be {Types::Int16}
17
15
  # @see TLV#initialize
18
16
  def initialize(options={})
@@ -8,7 +8,6 @@
8
8
  module PacketGen
9
9
  module Header
10
10
  class DNS
11
-
12
11
  # Define a DNS Question Section
13
12
  # @author Sylvain Daubert
14
13
  class QDSection < RRSection
@@ -32,7 +31,7 @@ module PacketGen
32
31
  clear
33
32
  return self if str.nil?
34
33
  force_binary str
35
- while str.length > 0 and self.size < @counter.to_i
34
+ while !str.empty? && (self.size < @counter.to_i)
36
35
  question = Question.new(@dns).read(str)
37
36
  str.slice!(0, question.sz)
38
37
  self.push question
@@ -8,11 +8,9 @@
8
8
  module PacketGen
9
9
  module Header
10
10
  class DNS
11
-
12
11
  # DNS Question
13
12
  # @author Sylvain Daubert
14
13
  class Question < Base
15
-
16
14
  # Ressource Record types
17
15
  TYPES = {
18
16
  'A' => 1,
@@ -84,12 +82,12 @@ module PacketGen
84
82
  # @param [Integer] val
85
83
  # @return [Integer,String]
86
84
  def rrclass=(val)
87
- v = case val
88
- when String
89
- self.class::CLASSES[val.upcase]
90
- else
91
- val
92
- end
85
+ v = case val
86
+ when String
87
+ self.class::CLASSES[val.upcase]
88
+ else
89
+ val
90
+ end
93
91
  raise ArgumentError, "unknown class #{val.inspect}" unless v
94
92
  self[:rrclass].read v
95
93
  end
@@ -97,30 +95,38 @@ module PacketGen
97
95
  # Check type
98
96
  # @param [String] type name
99
97
  # @return [Boolean]
100
- def has_type?(type)
98
+ # @since 2.7.0
99
+ def type?(type)
101
100
  self.class::TYPES[type] == self.type
102
101
  end
103
102
 
103
+ # @deprecated Use {#type?} instead
104
+ # @return [Boolean]
105
+ def has_type?(type)
106
+ Deprecation.deprecated(self.class, __method__, 'type?')
107
+ type?(type)
108
+ end
109
+
104
110
  # Get human readable type
105
111
  # @return [String]
106
112
  def human_type
107
- self.class::TYPES.key(type) || "0x%04x" % type
113
+ self.class::TYPES.key(type) || '0x%04x' % type
108
114
  end
109
115
 
110
116
  # Get human readable class
111
117
  # @return [String]
112
118
  def human_rrclass
113
119
  if self[:name].dns.is_a? MDNS
114
- self.class::CLASSES.key(self.rrclass & 0x7fff) || "0x%04x" % (self.rrclass & 0x7fff)
120
+ self.class::CLASSES.key(self.rrclass & 0x7fff) || '0x%04x' % (self.rrclass & 0x7fff)
115
121
  else
116
- self.class::CLASSES.key(self.rrclass) || "0x%04x" % self.rrclass
122
+ self.class::CLASSES.key(self.rrclass) || '0x%04x' % self.rrclass
117
123
  end
118
124
  end
119
125
 
120
126
  # @return [String]
121
127
  def to_human
122
128
  if self[:name].dns.is_a? MDNS
123
- unicast_bit = (self.rrclass & 0x8000 == 0x8000) ? 'QU' : 'QM'
129
+ unicast_bit = self.rrclass & 0x8000 == 0x8000 ? 'QU' : 'QM'
124
130
  "#{human_type} #{human_rrclass} #{unicast_bit} #{name}"
125
131
  else
126
132
  "#{human_type} #{human_rrclass} #{name}"
@@ -8,11 +8,9 @@
8
8
  module PacketGen
9
9
  module Header
10
10
  class DNS
11
-
12
11
  # DNS Ressource Record
13
12
  # @author Sylvain Daubert
14
13
  class RR < Question
15
-
16
14
  # @!attribute ttl
17
15
  # 32-bit time to live
18
16
  # @return [Integer]
@@ -37,9 +35,8 @@ module PacketGen
37
35
  # @option options [String] :rdata
38
36
  def initialize(dns, options={})
39
37
  super
40
- if options[:rdata] and options[:rdlength].nil?
41
- self.rdata = options[:rdata]
42
- end
38
+ return unless options[:rdata] && options[:rdlength].nil?
39
+ self.rdata = options[:rdata]
43
40
  end
44
41
 
45
42
  # Set rdata and rdlength from +data+
@@ -49,7 +46,7 @@ module PacketGen
49
46
  self[:rdlength].read data.size
50
47
  self[:rdata].read data
51
48
  end
52
-
49
+
53
50
  # Get human readable rdata
54
51
  # @return [String]
55
52
  def human_rdata
@@ -71,11 +68,11 @@ module PacketGen
71
68
  when TYPES['SOA']
72
69
  mname = name.read(self[:rdata]).dup
73
70
  rname = name.read(self[:rdata][mname.sz..-1])
74
- serial = Types::Int32.new.read(self[:rdata][mname.sz+rname.sz, 4])
75
- refresh = Types::Int32.new.read(self[:rdata][mname.sz+rname.sz+4, 4])
76
- retryi = Types::Int32.new.read(self[:rdata][mname.sz+rname.sz+8, 4])
77
- expire = Types::Int32.new.read(self[:rdata][mname.sz+rname.sz+12, 4])
78
- minimum = Types::Int32.new.read(self[:rdata][mname.sz+rname.sz+16, 4])
71
+ serial = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz, 4])
72
+ refresh = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz + 4, 4])
73
+ retryi = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz + 8, 4])
74
+ expire = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz + 12, 4])
75
+ minimum = Types::Int32.new.read(self[:rdata][mname.sz + rname.sz + 16, 4])
79
76
  str = "#{mname.to_human} #{rname.to_human} #{serial.to_i} #{refresh.to_i} " \
80
77
  "#{retryi.to_i} #{expire.to_i} #{minimum.to_i}"
81
78
  when TYPES['MX']
@@ -93,15 +90,15 @@ module PacketGen
93
90
  str
94
91
  end
95
92
 
96
- def human_rrclass
97
93
  # Get human readable class
98
94
  # @return [String]
95
+ def human_rrclass
99
96
  if self[:name].dns.is_a? MDNS
100
- str = self.class::CLASSES.key(self.rrclass & 0x7fff) || "0x%04x" % (self.rrclass & 0x7fff)
97
+ str = self.class::CLASSES.key(self.rrclass & 0x7fff) || '0x%04x' % (self.rrclass & 0x7fff)
101
98
  str += ' CACHE-FLUSH' if self.rrclass & 0x8000 > 0
102
99
  str
103
100
  else
104
- self.class::CLASSES.key(self.rrclass) || "0x%04x" % self.rrclass
101
+ self.class::CLASSES.key(self.rrclass) || '0x%04x' % self.rrclass
105
102
  end
106
103
  end
107
104
 
@@ -8,17 +8,15 @@
8
8
  module PacketGen
9
9
  module Header
10
10
  class DNS
11
-
12
11
  # Define a DNS Ressource Record Section
13
12
  # @author Sylvain Daubert
14
13
  class RRSection < Types::Array
15
-
16
14
  # @api private
17
15
  # @param [DNS] dns
18
16
  # @param [Types::Int] counter
19
17
  def initialize(dns, counter)
18
+ super(counter: counter)
20
19
  @dns = dns
21
- @counter = counter
22
20
  end
23
21
 
24
22
  # Read RR section from a string
@@ -28,11 +26,11 @@ module PacketGen
28
26
  clear
29
27
  return self if str.nil?
30
28
  force_binary str
31
- while str.length > 0 and self.size < @counter.to_i
29
+ while !str.empty? && (self.size < @counter.to_i)
32
30
  rr = RR.new(@dns).read(str)
33
- rr = OPT.new(@dns).read(str) if rr.has_type?('OPT')
31
+ rr = OPT.new(@dns).read(str) if rr.type?('OPT')
34
32
  str.slice!(0, rr.sz)
35
- self.push rr
33
+ push rr
36
34
  end
37
35
  self
38
36
  end
@@ -40,7 +38,7 @@ module PacketGen
40
38
  private
41
39
 
42
40
  def record_from_hash(hsh)
43
- if hsh.has_key? :rtype
41
+ if hsh.key? :rtype
44
42
  case hsh.delete(:rtype)
45
43
  when 'Question'
46
44
  Question.new(@dns, hsh)
@@ -5,13 +5,14 @@
5
5
  # This program is published under MIT license.
6
6
 
7
7
  # frozen_string_literal: true
8
+
8
9
  require 'zlib'
9
10
 
10
11
  module PacketGen
11
12
  module Header
12
-
13
13
  # PPI (Per-Packet Information) packet
14
- #@author Sylvain Daubert
14
+ # @author Sylvain Daubert
15
+ # @since 1.4.0
15
16
  class PPI < Base
16
17
  # @!attribute version
17
18
  # @return [Integer] 8-bit PPI version
@@ -52,7 +53,7 @@ module PacketGen
52
53
  # Check version field
53
54
  # @see [Base#parse?]
54
55
  def parse?
55
- version == 0 and length >= 8
56
+ version.zero? && (length >= 8)
56
57
  end
57
58
 
58
59
  # Calculate header length
@@ -76,6 +77,7 @@ module PacketGen
76
77
 
77
78
  # Radiotap header (see http://www.radiotap.org/)
78
79
  # @author Sylvain Daubert
80
+ # @since 1.4.0
79
81
  class RadioTap < Base
80
82
  # @!attribute version
81
83
  # @return [Integer] 8-bit version
@@ -113,9 +115,9 @@ module PacketGen
113
115
  # Check version field
114
116
  # @see [Base#parse?]
115
117
  def parse?
116
- version == 0 and length >= 8
118
+ version.zero? && (length >= 8)
117
119
  end
118
-
120
+
119
121
  # Calculate header length
120
122
  # @return [Integer] calculated length
121
123
  # @since 2.1.3
@@ -204,18 +206,34 @@ module PacketGen
204
206
  # pkt.calc
205
207
  # pkt.to_w('wlan0')
206
208
  # @author Sylvain Daubert
209
+ # @since 1.4.0
207
210
  class Dot11 < Base
208
-
209
211
  # Frame types
210
- TYPES = %w(Management Control Data Reserved).freeze
212
+ TYPES = %w[Management Control Data Reserved].freeze
211
213
 
212
214
  class << self
213
215
  # Set a flag for parsing Dot11 packets. If set to +true+, parse FCS field,
214
216
  # else don't. Default is +true+.
215
217
  # @return [Boolean]
216
- attr_accessor :has_fcs
218
+ attr_accessor :fcs
219
+ alias fcs? fcs
220
+
221
+ # rubocop:disable Naming/PredicateName
222
+
223
+ # @deprecated Use {#fcs?} instead.
224
+ def has_fcs
225
+ Deprecation.deprecated(self, __method__, 'fcs?', klass_method: true)
226
+ fcs?
227
+ end
228
+
229
+ # @deprecated Use {#fcs=} instead.
230
+ def has_fcs=(fcs)
231
+ Deprecation.deprecated(self, __method__, 'fcs=', klass_method: true)
232
+ self.fcs = fcs
233
+ end
234
+ # rubocop:enable Naming/PredicateName
217
235
  end
218
- Dot11.has_fcs = true
236
+ Dot11.fcs = true
219
237
 
220
238
  # @!attribute frame_ctrl
221
239
  # @return [Integer] 16-bit frame control word
@@ -273,9 +291,8 @@ module PacketGen
273
291
  # @return [Boolean] from_ds flag from {#frame_ctrl}
274
292
  # @!attribute to_ds
275
293
  # @return [Boolean] to_ds flag from {#frame_ctrl}
276
- define_bit_fields_on :frame_ctrl, :subtype, 4, :type, 2, :proto_version, 2,
277
- :order, :wep, :md, :pwmngt, :retry, :mf, :from_ds, :to_ds
278
-
294
+ define_bit_fields_on :frame_ctrl, :subtype, 4, :type, 2, :proto_version, 2,
295
+ :order, :wep, :md, :pwmngt, :retry, :mf, :from_ds, :to_ds
279
296
 
280
297
  # @!attribute sequence_number (12-bit field from {#sequence_ctrl})
281
298
  # @return [Integer]
@@ -310,7 +327,7 @@ module PacketGen
310
327
  # @return [Dot11] may return a subclass object if a more specific class
311
328
  # may be determined
312
329
  def read(str)
313
- has_fcs = Dot11.has_fcs
330
+ fcs = Dot11.fcs?
314
331
 
315
332
  if self.class == Dot11
316
333
  return self if str.nil?
@@ -325,10 +342,10 @@ module PacketGen
325
342
  when 2
326
343
  Dot11::Data.new.read str
327
344
  else
328
- private_read str, has_fcs
345
+ private_read str, fcs
329
346
  end
330
347
  else
331
- private_read str, has_fcs
348
+ private_read str, fcs
332
349
  end
333
350
  end
334
351
 
@@ -359,7 +376,7 @@ module PacketGen
359
376
  elsif self.respond_to? :human_subtype
360
377
  Inspect.dashed_line("#{self.class} #{human_subtype}", 2)
361
378
  else
362
- Inspect.dashed_line("#{self.class}", 2)
379
+ Inspect.dashed_line(self.class.to_s, 2)
363
380
  end
364
381
  define_applicable_fields
365
382
  @applicable_fields.each do |attr|
@@ -378,25 +395,24 @@ module PacketGen
378
395
  pcap.inject self.to_s
379
396
  pcap.close
380
397
  end
381
-
398
+
382
399
  # Callback called when a Dot11 header is added to a packet
383
400
  # Here, add +#dot11+ method as a shortcut to existing
384
401
  # +#dot11_(control|management|data)+.
385
402
  # @param [Packet] packet
386
403
  # @return [void]
387
404
  def added_to_packet(packet)
388
- unless packet.respond_to? :dot11
389
- packet.instance_eval("def dot11(arg=nil); header(#{self.class}, arg); end")
390
- end
405
+ return if packet.respond_to? :dot11
406
+ packet.instance_eval("def dot11(arg=nil); header(#{self.class}, arg); end")
391
407
  end
392
408
 
393
409
  private
394
410
 
395
411
  def define_applicable_fields
396
- if to_ds? and from_ds?
412
+ if to_ds? && from_ds?
397
413
  @applicable_fields[6, 0] = :mac4 unless @applicable_fields.include? :mac4
398
414
  else
399
- @applicable_fields -= %i(mac4)
415
+ @applicable_fields -= %i[mac4]
400
416
  end
401
417
  if order?
402
418
  unless @applicable_fields.include? :ht_ctrl
@@ -404,19 +420,19 @@ module PacketGen
404
420
  @applicable_fields[idx, 0] = :ht_ctrl
405
421
  end
406
422
  else
407
- @applicable_fields -= %i(ht_ctrl)
423
+ @applicable_fields -= %i[ht_ctrl]
408
424
  end
409
- if Dot11.has_fcs
425
+ if Dot11.fcs?
410
426
  @applicable_fields << :fcs unless @applicable_fields.include? :fcs
411
427
  else
412
- @applicable_fields -= %i(fcs)
428
+ @applicable_fields -= %i[fcs]
413
429
  end
414
430
  end
415
431
 
416
- def private_read(str, has_fcs)
432
+ def private_read(str, fcs)
417
433
  self[:frame_ctrl].read str[0, 2]
418
434
  define_applicable_fields
419
- if has_fcs
435
+ if fcs
420
436
  old_read str[0...-4]
421
437
  self[:fcs].read str[-4..-1]
422
438
  else
@@ -427,8 +443,8 @@ module PacketGen
427
443
  end
428
444
 
429
445
  self.add_class Dot11
430
- PPI.bind_header Dot11, dlt: PcapNG::LINKTYPE_IEEE802_11
431
- RadioTap.bind_header Dot11
446
+ PPI.bind Dot11, dlt: PcapNG::LINKTYPE_IEEE802_11
447
+ RadioTap.bind Dot11
432
448
  end
433
449
  end
434
450
 
@@ -9,7 +9,6 @@
9
9
  module PacketGen
10
10
  module Header
11
11
  class Dot11
12
-
13
12
  # IEEE 802.11 control frame header
14
13
  #
15
14
  # This class make a {Dot11} header with {#type} set to +1+
@@ -24,7 +23,6 @@ module PacketGen
24
23
  # * and a Frame check sequence ({#fcs}, of type {Types::Int32le}).
25
24
  # @author Sylvain Daubert
26
25
  class Control < Dot11
27
-
28
26
  # Control subtypes
29
27
  SUBTYPES = {
30
28
  7 => 'Wrapper',
@@ -44,8 +42,8 @@ module PacketGen
44
42
  # @param [Hash] options
45
43
  # @see Base#initialize
46
44
  def initialize(options={})
47
- super({type: 1}.merge!(options))
48
- @applicable_fields -= %i(mac3 sequence_ctrl mac4 qos_ctrl ht_ctrl)
45
+ super({ type: 1 }.merge!(options))
46
+ @applicable_fields -= %i[mac3 sequence_ctrl mac4 qos_ctrl ht_ctrl]
49
47
  define_applicable_fields
50
48
  end
51
49
 
@@ -60,7 +58,7 @@ module PacketGen
60
58
  def define_applicable_fields
61
59
  super
62
60
  if @applicable_fields.include? :mac2
63
- @applicable_fields -= %i(mac2) unless SUBTYPES_WITH_MAC2.include? self.subtype
61
+ @applicable_fields -= %i[mac2] unless SUBTYPES_WITH_MAC2.include? self.subtype
64
62
  elsif SUBTYPES_WITH_MAC2.include? self.subtype
65
63
  @applicable_fields[3, 0] = :mac2
66
64
  end
@@ -9,7 +9,6 @@
9
9
  module PacketGen
10
10
  module Header
11
11
  class Dot11
12
-
13
12
  # IEEE 802.11 data frame header
14
13
  #
15
14
  # This class make a {Dot11} header with {#type} set to +2+
@@ -27,20 +26,49 @@ module PacketGen
27
26
  # * and a Frame check sequence ({#fcs}, of type {Types::Int32le}).
28
27
  # @author Sylvain Daubert
29
28
  class Data < Dot11
30
-
31
29
  # @param [Hash] options
32
30
  # @see Base#initialize
33
31
  def initialize(options={})
34
- super({type: 2}.merge!(options))
35
- @applicable_fields -= %i(mac4 qos_ctrl ht_ctrl)
32
+ super({ type: 2 }.merge!(options))
33
+ @applicable_fields -= %i[mac4 qos_ctrl ht_ctrl]
36
34
  define_applicable_fields
37
35
  end
38
36
 
37
+ # Invert source and destination addresses (see Table 8-19 from
38
+ # IEEE 802.11-2012 document to known which MAC is SA, and which
39
+ # one is DA).
40
+ # Also invert Receiver and Transmitter address in case ToDS and
41
+ # FromDS are true.
42
+ def reply!
43
+ ds = frame_ctrl & 3
44
+ case ds
45
+ when 0
46
+ # MAC1: RA/DA, MAC2: TA/SA
47
+ self[:mac1], self[:mac2] = self[:mac2], self[:mac1]
48
+ when 1
49
+ # MAC1: RA/BSSID, MAC2: TA/SA, MAC3: DA
50
+ self[:mac2], self[:mac1] = self[:mac1], self[:mac2]
51
+ self.to_ds = false
52
+ self.from_ds = true
53
+ when 2
54
+ # MAC1: RA/DA, MAC2: BSSID, MAC3: SA or BSSID
55
+ self[:mac1], self[:mac2] = self[:mac2], self[:mac1]
56
+ self.to_ds = true
57
+ self.from_ds = false
58
+ when 3
59
+ # MAC1: RA, MAC2: TA
60
+ self[:mac1], self[:mac2] = self[:mac2], self[:mac1]
61
+ # MAC3: DA, MAC4: SA
62
+ self[:mac4], self[:mac3] = self[:mac3], self[:mac4]
63
+ end
64
+ self
65
+ end
66
+
39
67
  private
40
68
 
41
69
  def define_applicable_fields
42
70
  super
43
- if subtype >= 8 and !@applicable_fields.include? :qos_ctrl
71
+ if (subtype >= 8) && !@applicable_fields.include?(:qos_ctrl)
44
72
  # Insert after mac4, if present
45
73
  # else insert after sequence_ctrl
46
74
  if @applicable_fields.include? :mac4
@@ -50,7 +78,7 @@ module PacketGen
50
78
  @applicable_fields[6, 0] = :qos_ctrl
51
79
  end
52
80
  elsif subtype < 8
53
- @applicable_fields -= %i(qos_ctrl)
81
+ @applicable_fields -= %i[qos_ctrl]
54
82
  end
55
83
  end
56
84
  end