packetgen 2.1.2 → 2.1.3

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.
@@ -9,6 +9,17 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # IEEE 802.11 control frame header
12
+ #
13
+ # This class make a {Dot11} header with {#type} set to +1+
14
+ # (control frame).
15
+ #
16
+ # A IEEE 802.11 control header consists of:
17
+ # * a {#frame_ctrl} ({Types::Int16}),
18
+ # * a {#id}/duration ({Types::Int16le}),
19
+ # * a {#mac1} ({Eth::MacAddr}).
20
+ # * sometimes a {#mac2} ({Eth::MacAddr}),
21
+ # * a {#body} (a {Types::String} or another {Base} class),
22
+ # * and a Frame check sequence ({#fcs}, of type {Types::Int32le}).
12
23
  # @author Sylvain Daubert
13
24
  class Control < Dot11
14
25
 
@@ -49,7 +60,6 @@ module PacketGen
49
60
  if @applicable_fields.include? :mac2
50
61
  @applicable_fields -= %i(mac2) unless SUBTYPES_WITH_MAC2.include? self.subtype
51
62
  elsif SUBTYPES_WITH_MAC2.include? self.subtype
52
- sz = self.sz
53
63
  @applicable_fields[3, 0] = :mac2
54
64
  end
55
65
  end
@@ -9,6 +9,20 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # IEEE 802.11 data frame header
12
+ #
13
+ # This class make a {Dot11} header with {#type} set to +2+
14
+ # (data frame).
15
+ #
16
+ # A IEEE 802.11 data header consists of:
17
+ # * a {#frame_ctrl} ({Types::Int16}),
18
+ # * a {#id}/duration ({Types::Int16le}),
19
+ # * a {#mac2} ({Eth::MacAddr}),
20
+ # * a {#mac3} ({Eth::MacAddr}),
21
+ # * a {#sequence_ctrl} ({Types::Int16}),
22
+ # * sometimes a {#mac4} ({Eth::MacAddr}),
23
+ # * sometimes a {#qos_ctrl} ({Types::Int16}),
24
+ # * a {#body} (a {Types::String} or another {Base} class),
25
+ # * and a Frame check sequence ({#fcs}, of type {Types::Int32le}).
12
26
  # @author Sylvain Daubert
13
27
  class Data < Dot11
14
28
 
@@ -9,6 +9,8 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # IEEE 802.11 information element
12
+ #
13
+ # An {Element} is a piece of data contained in a Dot11 management frame.
12
14
  # @author Sylvain Daubert
13
15
  class Element < Types::TLV
14
16
  # Known element types
@@ -9,6 +9,33 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # IEEE 802.11 management frame header
12
+ #
13
+ # This class make a {Dot11} header with {#type} set to +0+
14
+ # (management frame).
15
+ #
16
+ # A IEEE 802.11 management header consists of:
17
+ # * a {#frame_ctrl} ({Types::Int16}),
18
+ # * a {#id}/duration ({Types::Int16le}),
19
+ # * a {#mac1} ({Eth::MacAddr}).
20
+ # * a {#mac2} ({Eth::MacAddr}),
21
+ # * a {#mac3} ({Eth::MacAddr}),
22
+ # * a {#sequence_ctrl} ({Types::Int16}),
23
+ # * a {#body} (a {Types::String} or another {Base} class),
24
+ # * and a Frame check sequence ({#fcs}, of type {Types::Int32le}).
25
+ #
26
+ # Management frames should be constructed with more headers from
27
+ # {SubMngt} subclasses.
28
+ #
29
+ # By example, build a {DeAuth} frame:
30
+ # PacketGen.gen('Dot11::Management').add('Dot11::DeAuth')
31
+ #
32
+ # Some frames need to have {Element}. By example a {Beacon} frame:
33
+ # pkt = PacketGen.gen('Dot11::Management', mac1: broadcast, mac2: bssid, mac3: bssid).
34
+ # add('Dot11::Beacon')
35
+ # pkt.dot11_beacon.add_elements(type: 'SSID', value: ssid)
36
+ # pkt.dot11_beacon.add_elements(type: 'Rates', value: "\x82\x84\x8b\x96\x12\x24\x48\x6c")
37
+ # pkt.dot11_beacon.add_elements(type: 'DSset', value: "\x06")
38
+ # pkt.dot11_beacon.add_elements(type: 'TIM', value: "\x00\x01\x00\x00")
12
39
  # @author Sylvain Daubert
13
40
  class Management < Dot11
14
41
 
@@ -19,6 +46,22 @@ module PacketGen
19
46
  @applicable_fields -= %i(mac4 qos_ctrl ht_ctrl)
20
47
  define_applicable_fields
21
48
  end
49
+
50
+ # Add an {Element}
51
+ # @param [Integer,String] type element type
52
+ # @param [Object] value element value
53
+ # @return [self]
54
+ # @since 2.1.3
55
+ def add_element(type:, value:)
56
+ if self[:body].is_a? SubMngt
57
+ element = Element.new(type: type, value: value)
58
+ self[:body].elements << element
59
+ else
60
+ raise FormatError, 'Before adding an Element, you have to add a Dot11::SubMngt subclass instance'
61
+ end
62
+
63
+ self
64
+ end
22
65
  end
23
66
  end
24
67
  end
@@ -9,6 +9,12 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # @abstract Base class for all subtype management frames
12
+ # Subclasses of this class are used to specialize {Management}. A
13
+ # +SubMngt+ class set +subtype+ field in Dot11 header and may add some
14
+ # fields.
15
+ #
16
+ # All SubMngt subclasses have ability to have {Element}. These elements
17
+ # may be accessed through {#elements}.
12
18
  # @author Sylvain Daubert
13
19
  class SubMngt < Base
14
20
  # @return [Array<Element>]
@@ -38,12 +44,23 @@ module PacketGen
38
44
  # @return [String]
39
45
  def inspect
40
46
  str = super
41
- str << Inspect.dashed_line('Dot11 Elements', level=3)
47
+ str << Inspect.dashed_line('Dot11 Elements', 3)
42
48
  @elements.each do |el|
43
49
  str << Inspect.shift_level(4) << el.to_human << "\n"
44
50
  end
45
51
  str
46
52
  end
53
+
54
+ # Add an {Element} to header
55
+ # @param [Integer,String] type element type
56
+ # @param [Object] value element value
57
+ # @return [self]
58
+ # @since 2.1.3
59
+ def add_element(type:, value:)
60
+ element = Element.new(type: type, value: value)
61
+ @elements << element
62
+ self
63
+ end
47
64
 
48
65
  private
49
66
 
@@ -59,6 +76,12 @@ module PacketGen
59
76
  end
60
77
 
61
78
  # IEEE 802.11 Association Request frame
79
+ #
80
+ # Specialize {Dot11::Management} with +subtype+ set to 0.
81
+ #
82
+ # Add fields:
83
+ # * {#cap} ({Types::Int16le}),
84
+ # * {#listen_interval} ({Types::Int16le}).
62
85
  # @author Sylvain Daubert
63
86
  class AssoReq < SubMngt
64
87
  # @!attribute cap
@@ -72,6 +95,13 @@ module PacketGen
72
95
  Management.bind_header AssoReq, op: :and, type: 0, subtype: 0
73
96
 
74
97
  # IEEE 802.11 Association Response frame
98
+ #
99
+ # Specialize {Dot11::Management} with +subtype+ set to 1.
100
+ #
101
+ # Add fields:
102
+ # * {#cap} ({Types::Int16le}),
103
+ # * {#status} ({Types::Int16le}),
104
+ # * {#aid} ({Types::Int16le}).
75
105
  # @author Sylvain Daubert
76
106
  class AssoResp < SubMngt
77
107
  # @!attribute cap
@@ -88,6 +118,13 @@ module PacketGen
88
118
  Management.bind_header AssoResp, op: :and, type: 0, subtype: 1
89
119
 
90
120
  # IEEE 802.11 ReAssociation Request frame
121
+ #
122
+ # Specialize {Dot11::Management} with +subtype+ set to 2.
123
+ #
124
+ # Add fields:
125
+ # * {#cap} ({Types::Int16le}),
126
+ # * {#listen_interval} ({Types::Int16le}),
127
+ # * {#current_ap} ({Eth::MacAddr}).
91
128
  # @author Sylvain Daubert
92
129
  class ReAssoReq < AssoReq
93
130
  # @!attribute current_ap
@@ -98,6 +135,13 @@ module PacketGen
98
135
  Management.bind_header ReAssoReq, op: :and, type: 0, subtype: 2
99
136
 
100
137
  # IEEE 802.11 ReAssociation Response frame
138
+ #
139
+ # Specialize {Dot11::Management} with +subtype+ set to 3.
140
+ #
141
+ # Add fields:
142
+ # * {#cap} ({Types::Int16le}),
143
+ # * {#status} ({Types::Int16le}),
144
+ # * {#aid} ({Types::Int16le}).
101
145
  # @author Sylvain Daubert
102
146
  class ReAssoResp < AssoResp
103
147
  end
@@ -105,6 +149,10 @@ module PacketGen
105
149
  Management.bind_header ReAssoResp, op: :and, type: 0, subtype: 3
106
150
 
107
151
  # IEEE 802.11 Probe Request frame
152
+ #
153
+ # Specialize {Dot11::Management} with +subtype+ set to 4.
154
+ #
155
+ # This class adds no field.
108
156
  # @author Sylvain Daubert
109
157
  class ProbeReq < SubMngt
110
158
  end
@@ -112,6 +160,13 @@ module PacketGen
112
160
  Management.bind_header ProbeReq, op: :and, type: 0, subtype: 4
113
161
 
114
162
  # IEEE 802.11 Probe Response frame
163
+ #
164
+ # Specialize {Dot11::Management} with +subtype+ set to 5.
165
+ #
166
+ # Add fields:
167
+ # * {#timestamp} ({Types::Int64le}),
168
+ # * {#beacon_interval} ({Types::Int16le}),
169
+ # * {#cap} ({Types::Int16le}).
115
170
  # @author Sylvain Daubert
116
171
  class ProbeResp < SubMngt
117
172
  # @!attribute timestamp
@@ -128,6 +183,13 @@ module PacketGen
128
183
  Management.bind_header ProbeResp, op: :and, type: 0, subtype: 5
129
184
 
130
185
  # IEEE 802.11 Beacon frame
186
+ #
187
+ # Specialize {Dot11::Management} with +subtype+ set to 8.
188
+ #
189
+ # Add fields:
190
+ # * {#timestamp} ({Types::Int64le}),
191
+ # * {#interval} ({Types::Int16le}),
192
+ # * {#cap} ({Types::Int16le}).
131
193
  # @author Sylvain Daubert
132
194
  class Beacon < SubMngt
133
195
  # @!attribute timestamp
@@ -144,12 +206,21 @@ module PacketGen
144
206
  Management.bind_header Beacon, op: :and, type: 0, subtype: 8
145
207
 
146
208
  # IEEE 802.11 ATIM frame
209
+ #
210
+ # Specialize {Dot11::Management} with +subtype+ set to 9.
211
+ #
212
+ # This class defines no field.
147
213
  # @author Sylvain Daubert
148
214
  class ATIM < SubMngt; end
149
215
  Header.add_class ATIM
150
216
  Management.bind_header ATIM, op: :and, type: 0, subtype: 9
151
217
 
152
218
  # IEEE 802.11 Disassociation frame
219
+ #
220
+ # Specialize {Dot11::Management} with +subtype+ set to 10.
221
+ #
222
+ # Add fields:
223
+ # * {#reason} ({Types::Int16le}).
153
224
  # @author Sylvain Daubert
154
225
  class Disas < SubMngt
155
226
  # @!attribute reason
@@ -160,6 +231,13 @@ module PacketGen
160
231
  Management.bind_header Disas, op: :and, type: 0, subtype: 10
161
232
 
162
233
  # IEEE 802.11 Authentication frame
234
+ #
235
+ # Specialize {Dot11::Management} with +subtype+ set to 11.
236
+ #
237
+ # Add fields:
238
+ # * {#algo} ({Types::Int16le}),
239
+ # * {#seqnum} ({Types::Int16le}),
240
+ # * {#status} ({Types::Int16le}).
163
241
  # @author Sylvain Daubert
164
242
  class Auth < SubMngt
165
243
  # @!attribute algo
@@ -176,6 +254,11 @@ module PacketGen
176
254
  Management.bind_header Auth, op: :and, type: 0, subtype: 11
177
255
 
178
256
  # IEEE 802.11 Deauthentication frame
257
+ #
258
+ # Specialize {Dot11::Management} with +subtype+ set to 12.
259
+ #
260
+ # Add fields:
261
+ # * {#reason} ({Types::Int16le}).
179
262
  # @author Sylvain Daubert
180
263
  class DeAuth < SubMngt
181
264
  # @!attribute reason
@@ -26,19 +26,19 @@ module PacketGen
26
26
 
27
27
  # IEEE 802.1X packet types
28
28
  TYPES = {
29
- 0 => 'EAP Packet',
30
- 1 => 'Start',
31
- 2 => 'Logoff',
32
- 3 => 'Key',
33
- 4 => 'Encap-ASF-Alert'
34
- }
29
+ 'EAP Packet' => 0,
30
+ 'Start' => 1,
31
+ 'Logoff' => 2,
32
+ 'Key' => 3,
33
+ 'Encap-ASF-Alert' => 4
34
+ }.freeze
35
35
 
36
36
  # @!attribute version
37
37
  # @return [Integer] 8-bit Protocol Version
38
38
  define_field :version, Types::Int8, default: 1
39
39
  # @!attribute type
40
40
  # @return [Integer] 8-bit Packet Type
41
- define_field :type, Types::Int8
41
+ define_field :type, Types::Int8Enum, enum: TYPES
42
42
  # @!attribute length
43
43
  # @return [Integer] 16-bit body length
44
44
  define_field :length, Types::Int16
@@ -46,29 +46,10 @@ module PacketGen
46
46
  # @return [Types::String,Header::Base]
47
47
  define_field :body, Types::String
48
48
 
49
- # @private
50
- alias old_type= type=
51
-
52
- # Set type attribute
53
- # @param [String,Integer] type
54
- # @return [Integer]
55
- def type=(type)
56
- case type
57
- when Integer
58
- self.old_type = type
59
- else
60
- v = TYPES.key(type.to_s)
61
- raise ArgumentError, "unknown type #{type}" if v.nil?
62
- self.old_type = v
63
- end
64
- end
65
-
66
49
  # Get human readable type
67
50
  # @return [String]
68
51
  def human_type
69
- v = TYPES[self.type]
70
- v = self.type if v.nil?
71
- v.to_s
52
+ self[:type].to_human
72
53
  end
73
54
  end
74
55
 
@@ -78,19 +78,21 @@ module PacketGen
78
78
  PROTO_AH = 2
79
79
  PROTO_ESP = 3
80
80
 
81
- TYPE_IKE_SA_INIT = 34
82
- TYPE_IKE_AUTH = 35
83
- TYPE_CREATE_CHILD_SA = 36
84
- TYPE_INFORMATIONAL = 37
81
+ EXCHANGE_TYPES = {
82
+ 'IKE_SA_INIT' => 34,
83
+ 'IKE_AUTH' => 35,
84
+ 'CREATE_CHILD_SA' => 36,
85
+ 'INFORMATIONAL' => 37
86
+ }.freeze
85
87
 
86
88
  # @!attribute init_spi
87
89
  # 64-bit initiator SPI
88
90
  # @return [Integer]
89
- define_field :init_spi, Types::Int64
91
+ define_field :init_spi, Types::Int64
90
92
  # @!attribute resp_spi
91
93
  # 64-bit responder SPI
92
94
  # @return [Integer]
93
- define_field :resp_spi, Types::Int64
95
+ define_field :resp_spi, Types::Int64
94
96
  # @!attribute next
95
97
  # 8-bit next payload type
96
98
  # @return [Integer]
@@ -102,7 +104,7 @@ module PacketGen
102
104
  # @!attribute [r] exchange_type
103
105
  # 8-bit exchange type
104
106
  # @return [Integer]
105
- define_field :exchange_type, Types::Int8
107
+ define_field :exchange_type, Types::Int8Enum, enum: EXCHANGE_TYPES
106
108
  # @!attribute flags
107
109
  # 8-bit flags
108
110
  # @return [Integer]
@@ -152,30 +154,13 @@ module PacketGen
152
154
  self.type = options[:exchange_type] if options[:exchange_type]
153
155
  end
154
156
 
155
- # Set exchange type
156
- # @param [Integer,String] value
157
- # @return [Integer]
158
- def exchange_type=(value)
159
- type = case value
160
- when Integer
161
- value
162
- else
163
- c = self.class.constants.grep(/TYPE_#{value}/).first
164
- c ? self.class.const_get(c) : nil
165
- end
166
- raise ArgumentError, "unknown exchange type #{value.inspect}" unless type
167
- self[:exchange_type].value = type
168
- end
169
157
  alias type exchange_type
170
158
  alias type= exchange_type=
171
159
 
172
160
  # Get exchange type name
173
161
  # @return [String
174
162
  def human_exchange_type
175
- name = self.class.constants.grep(/TYPE_/).
176
- select { |c| self.class.const_get(c) == type }.
177
- first || "type #{type}"
178
- name.to_s.sub(/TYPE_/, '')
163
+ self[:exchange_type].to_human
179
164
  end
180
165
  alias human_type human_exchange_type
181
166
 
@@ -39,50 +39,34 @@ module PacketGen
39
39
  # Payload type number
40
40
  PAYLOAD_TYPE = 37
41
41
 
42
- ENCODING_PKCS7_WRAPPED_X509 = 1
43
- ENCODING_PGP = 2
44
- ENCODING_DNS_SIGNED_KEY = 3
45
- ENCODING_X509_CERT_SIG = 4
46
- ENCODING_KERBEROS_TOKEN = 6
47
- ENCODING_X509_CRL = 7
48
- ENCODING_X509_ARL = 8
49
- ENCODING_SPKI_CERT = 9
50
- ENCODING_X509_CERT_ATTR = 10
51
- ENCODING_HASH_URL_X509_CERT = 12
52
- ENCODING_HASH_URL_X509_BUNDLE = 13
42
+ ENCODINGS = {
43
+ 'PKCS7_WRAPPED_X509' => 1,
44
+ 'PGP' => 2,
45
+ 'DNS_SIGNED_KEY' => 3,
46
+ 'X509_CERT_SIG' => 4,
47
+ 'KERBEROS_TOKEN' => 6,
48
+ 'X509_CRL' => 7,
49
+ 'X509_ARL' => 8,
50
+ 'SPKI_CERT' => 9,
51
+ 'X509_CERT_ATTR' => 10,
52
+ 'HASH_URL_X509_CERT' => 12,
53
+ 'HASH_URL_X509_BUNDLE' => 13
54
+ }.freeze
53
55
 
54
56
  # @attribute encoding
55
57
  # 8-bit certificate encoding
56
58
  # @return [Integer]
57
- define_field_before :content, :encoding, Types::Int8
59
+ define_field_before :content, :encoding, Types::Int8Enum, enum: ENCODINGS
58
60
 
59
61
  def initialize(options={})
60
62
  super
61
63
  self.encoding = options[:encoding] if options[:encoding]
62
64
  end
63
65
 
64
- # Set encoding
65
- # @param [Integer,String] value
66
- # @return [Integer]
67
- def encoding=(value)
68
- encoding = case value
69
- when Integer
70
- value
71
- else
72
- c = self.class.constants.grep(/ENCODING_#{value}/).first
73
- c ? self.class.const_get(c) : nil
74
- end
75
- raise ArgumentError, "unknown ID encoding #{value.inspect}" unless encoding
76
- self[:encoding].value = encoding
77
- end
78
-
79
66
  # Get encoding name
80
67
  # @return [String]
81
68
  def human_encoding
82
- name = self.class.constants.grep(/ENCODING_/).
83
- select { |c| self.class.const_get(c) == encoding }.
84
- first || "encoding #{encoding}"
85
- name.to_s.sub(/ENCODING_/, '')
69
+ self[:encoding].to_human
86
70
  end
87
71
 
88
72
  # @return [String]