packetgen 4.0.0 → 4.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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/packetgen/deprecation.rb +7 -1
  4. data/lib/packetgen/header/arp.rb +6 -7
  5. data/lib/packetgen/header/asn1_base.rb +2 -1
  6. data/lib/packetgen/header/base.rb +27 -24
  7. data/lib/packetgen/header/bootp.rb +14 -14
  8. data/lib/packetgen/header/dhcp/option.rb +8 -8
  9. data/lib/packetgen/header/dhcp/options.rb +2 -2
  10. data/lib/packetgen/header/dhcp.rb +6 -7
  11. data/lib/packetgen/header/dhcpv6/duid.rb +1 -1
  12. data/lib/packetgen/header/dhcpv6/option.rb +37 -15
  13. data/lib/packetgen/header/dhcpv6/options.rb +3 -3
  14. data/lib/packetgen/header/dhcpv6/relay.rb +1 -0
  15. data/lib/packetgen/header/dhcpv6.rb +13 -14
  16. data/lib/packetgen/header/dns/name.rb +9 -8
  17. data/lib/packetgen/header/dns/opt.rb +3 -0
  18. data/lib/packetgen/header/dns/option.rb +7 -7
  19. data/lib/packetgen/header/dns/qdsection.rb +2 -2
  20. data/lib/packetgen/header/dns/question.rb +1 -0
  21. data/lib/packetgen/header/dns/rrsection.rb +2 -2
  22. data/lib/packetgen/header/dns.rb +76 -60
  23. data/lib/packetgen/header/dot11/control.rb +5 -5
  24. data/lib/packetgen/header/dot11/data.rb +11 -10
  25. data/lib/packetgen/header/dot11/element.rb +1 -1
  26. data/lib/packetgen/header/dot11/management.rb +18 -15
  27. data/lib/packetgen/header/dot11/sub_mngt.rb +22 -21
  28. data/lib/packetgen/header/dot11.rb +38 -38
  29. data/lib/packetgen/header/dot1q.rb +5 -4
  30. data/lib/packetgen/header/dot1x.rb +8 -8
  31. data/lib/packetgen/header/eap/fast.rb +3 -3
  32. data/lib/packetgen/header/eap/md5.rb +11 -3
  33. data/lib/packetgen/header/eap/tls.rb +9 -8
  34. data/lib/packetgen/header/eap/ttls.rb +13 -10
  35. data/lib/packetgen/header/eap.rb +58 -33
  36. data/lib/packetgen/header/eth.rb +26 -12
  37. data/lib/packetgen/header/gre.rb +26 -2
  38. data/lib/packetgen/header/http/headers.rb +6 -5
  39. data/lib/packetgen/header/http/request.rb +24 -16
  40. data/lib/packetgen/header/http/response.rb +22 -15
  41. data/lib/packetgen/header/icmp.rb +10 -10
  42. data/lib/packetgen/header/icmpv6.rb +10 -9
  43. data/lib/packetgen/header/igmp.rb +21 -10
  44. data/lib/packetgen/header/igmpv3/group_record.rb +7 -2
  45. data/lib/packetgen/header/igmpv3/mq.rb +1 -1
  46. data/lib/packetgen/header/igmpv3/mr.rb +1 -1
  47. data/lib/packetgen/header/igmpv3.rb +11 -10
  48. data/lib/packetgen/header/ip/addr.rb +6 -2
  49. data/lib/packetgen/header/ip/option.rb +18 -5
  50. data/lib/packetgen/header/ip.rb +52 -35
  51. data/lib/packetgen/header/ipv6/addr.rb +14 -13
  52. data/lib/packetgen/header/ipv6/extension.rb +9 -7
  53. data/lib/packetgen/header/ipv6/hop_by_hop.rb +26 -7
  54. data/lib/packetgen/header/ipv6.rb +31 -22
  55. data/lib/packetgen/header/llc.rb +20 -13
  56. data/lib/packetgen/header/mdns.rb +9 -2
  57. data/lib/packetgen/header/mld.rb +11 -9
  58. data/lib/packetgen/header/mldv2/mcast_address_record.rb +6 -1
  59. data/lib/packetgen/header/mldv2/mlq.rb +8 -8
  60. data/lib/packetgen/header/mldv2/mlr.rb +4 -4
  61. data/lib/packetgen/header/mldv2.rb +1 -1
  62. data/lib/packetgen/header/ospfv2/db_description.rb +10 -10
  63. data/lib/packetgen/header/ospfv2/hello.rb +11 -10
  64. data/lib/packetgen/header/ospfv2/ls_ack.rb +5 -6
  65. data/lib/packetgen/header/ospfv2/ls_request.rb +7 -6
  66. data/lib/packetgen/header/ospfv2/ls_update.rb +7 -7
  67. data/lib/packetgen/header/ospfv2/lsa.rb +33 -10
  68. data/lib/packetgen/header/ospfv2/lsa_header.rb +3 -2
  69. data/lib/packetgen/header/ospfv2.rb +31 -26
  70. data/lib/packetgen/header/ospfv3/db_description.rb +12 -13
  71. data/lib/packetgen/header/ospfv3/hello.rb +10 -9
  72. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +6 -2
  73. data/lib/packetgen/header/ospfv3/ls_ack.rb +5 -6
  74. data/lib/packetgen/header/ospfv3/ls_request.rb +10 -10
  75. data/lib/packetgen/header/ospfv3/ls_update.rb +7 -7
  76. data/lib/packetgen/header/ospfv3/lsa.rb +23 -9
  77. data/lib/packetgen/header/ospfv3/lsa_header.rb +3 -2
  78. data/lib/packetgen/header/ospfv3.rb +38 -34
  79. data/lib/packetgen/header/sctp/chunk.rb +38 -17
  80. data/lib/packetgen/header/sctp/error.rb +169 -197
  81. data/lib/packetgen/header/sctp/padded32.rb +3 -3
  82. data/lib/packetgen/header/sctp/parameter.rb +85 -132
  83. data/lib/packetgen/header/sctp.rb +14 -3
  84. data/lib/packetgen/header/snmp.rb +108 -7
  85. data/lib/packetgen/header/tcp/option.rb +7 -0
  86. data/lib/packetgen/header/tcp/options.rb +11 -3
  87. data/lib/packetgen/header/tcp.rb +33 -26
  88. data/lib/packetgen/header/tftp.rb +16 -10
  89. data/lib/packetgen/header/udp.rb +15 -13
  90. data/lib/packetgen/header.rb +19 -13
  91. data/lib/packetgen/headerable.rb +9 -3
  92. data/lib/packetgen/inspect.rb +2 -7
  93. data/lib/packetgen/packet.rb +94 -36
  94. data/lib/packetgen/pcapng/block.rb +2 -1
  95. data/lib/packetgen/pcapng/file.rb +41 -14
  96. data/lib/packetgen/pcapng/idb.rb +2 -1
  97. data/lib/packetgen/pcapng/shb.rb +2 -1
  98. data/lib/packetgen/pcapng/spb.rb +1 -1
  99. data/lib/packetgen/pcapng.rb +2 -0
  100. data/lib/packetgen/proto.rb +4 -0
  101. data/lib/packetgen/unknown_packet.rb +3 -3
  102. data/lib/packetgen/utils.rb +2 -1
  103. data/lib/packetgen/version.rb +1 -1
  104. data/lib/packetgen.rb +8 -2
  105. metadata +4 -4
@@ -103,58 +103,54 @@ module PacketGen
103
103
  end
104
104
  self.add_class RadioTap
105
105
 
106
- # IEEE 802.11 header
107
106
  # @abstract This is a base class to demultiplex different IEEE 802.11 frames when
108
107
  # parsing.
109
108
  # A IEEE 802.11 header may consist of at least:
110
- # * a {#frame_ctrl} ({BinStruct::Int16}),
111
- # * a {#id}/duration ({BinStruct::Int16le}),
109
+ # * a {#frame_ctrl} (+BinStruct::Int16+),
110
+ # * a {#id}/duration (+BinStruct::Int16le+),
112
111
  # * and a {#mac1} ({Eth::MacAddr}).
113
112
  # Depending on frame type and subtype, it may also contains:
114
113
  # * a {#mac2} ({Eth::MacAddr}),
115
114
  # * a {#mac3} ({Eth::MacAddr}),
116
- # * a {#sequence_ctrl} ({BinStruct::Int16}),
115
+ # * a {#sequence_ctrl} (+BinStruct::Int16+),
117
116
  # * a {#mac4} ({Eth::MacAddr}),
118
- # * a {#qos_ctrl} ({BinStruct::Int16}),
119
- # * a {#ht_ctrl} ({BinStruct::Int32}),
120
- # * a {#body} (a {BinStruct::String} or another {Base} class),
121
- # * a Frame check sequence ({#fcs}, of type {BinStruct::Int32le})
117
+ # * a {#qos_ctrl} (+BinStruct::Int16+),
118
+ # * a {#ht_ctrl} (+BinStruct::Int32+),
119
+ # * a {#body} (a +BinStruct::String+ or another {Headerable} class),
120
+ # * a Frame check sequence ({#fcs}, of type +BinStruct::Int32le+)
122
121
  #
123
122
  # == Header accessors
124
123
  # As Dot11 header types are defined under Dot11 namespace, Dot11 header accessors
125
- # have a specific name. By example, to access to a {Dot11::Beacon} header,
124
+ # have a specific name. For example, to access to a {Dot11::Beacon} header,
126
125
  # accessor is +#dot11_beacon+.
127
126
  #
128
127
  # == Create Dot11 packets
129
128
  # As {Dot11} is an abstract class, you have to use one of its subclasses to
130
- # instanciate a IEEE802.11 header.
129
+ # instanciate a IEEE802.11 header (see examples below).
131
130
  #
132
- # === IEEE802.11 control frames
133
- # Control frames may be created this way:
131
+ # @example Create IEEE802.11 control frames
134
132
  # pkt = PacketGen.gen('Dot11::Control', subtype: 13) # Ack control frame
135
- # pkt.dot11_control # => PacketGen::Header::Dot11::Control
133
+ # pkt.dot11_control.class # => PacketGen::Header::Dot11::Control
136
134
  # # #dot11 is a shortcut for #dot11_control
137
- # pkt.dot11 # => PacketGen::Header::Dot11::Control
135
+ # pkt.dot11.class # => PacketGen::Header::Dot11::Control
138
136
  #
139
- # === IEEE802.11 management frames
140
- # Management frames may be created this way:
137
+ # @example Create IEEE802.11 management frames
141
138
  # pkt = PacketGen.gen('Dot11::Management')
142
- # pkt.dot11_management # => PacketGen::Header::Dot11::Management
139
+ # pkt.dot11_management.class # => PacketGen::Header::Dot11::Management
143
140
  # # #dot11 is a shortcut for #dot11_management
144
- # pkt.dot11 # => PacketGen::Header::Dot11::Management
145
- # Management frames are usually specialized, AssociationRequest by example:
141
+ # pkt.dot11.class # => PacketGen::Header::Dot11::Management
142
+ # # Management frames are usually specialized, AssociationRequest by example
146
143
  # pkt.add('Dot11::AssoReq')
147
- # pkt.dot11_assoreq # => PacketGen::Header::Dot11::AssoReq
148
- # Management frames also may contain some elements (see IEEE 802.11 standard):
149
- # pkt.dot11_assoreq.add_elements(type: 'SSID', value: "My SSID")
150
- # pkt.dot11_assoreq.add_elements(type: 'Rates', value: supported_rates)
144
+ # pkt.dot11_assoreq .class # => PacketGen::Header::Dot11::AssoReq
145
+ # # Management frames also may contain some elements (see IEEE 802.11 standard)
146
+ # pkt.dot11_assoreq.elements << { type: 'SSID', value: "My SSID" }
147
+ # pkt.dot11_assoreq.elements << { type: 'Rates', value: "\x8c\x12\x98\x24\xb0" }
151
148
  #
152
- # === IEEE802.11 data frames
153
- # Data frames may be created this way:
149
+ # @example Create IEEE802.11 data frames
154
150
  # pkt = PacketGen.gen('Dot11::Data')
155
- # pkt.dot11_data # => PacketGen::Header::Dot11::Data
151
+ # pkt.dot11_data.class # => PacketGen::Header::Dot11::Data
156
152
  # # #dot11 is a shortcut for #dot11_data
157
- # pkt.dot11 # => PacketGen::Header::Dot11::Data
153
+ # pkt.dot11.class # => PacketGen::Header::Dot11::Data
158
154
  #
159
155
  # == Parse Dot11 packets
160
156
  # When parsing a Dot11 packet, Dot11 subclass is created from +type+ value.
@@ -163,13 +159,12 @@ module PacketGen
163
159
  # for a control frame, +Packet#dot11_control+ may also be used.
164
160
  #
165
161
  # == Send Dot11 packets
166
- # To send a Dot11 packet, a RadioTap header is needed:
162
+ # To send a Dot11 packet, a RadioTap or PPI header is needed (depending on your hardware):
167
163
  # pkt = PacketGen.gen('RadioTap')
168
164
  # pkt.add('Dot11::Management', mac1: client, mac2: bssid, mac3: bssid)
169
165
  # pkt.add('Dot11::Beacon')
170
- # pkt.dot11_beacon.add_element(type: 'SSID', value: 'My SSID')
171
- # pkt.dot11_beacon.add_element(type: 'Rates', value: "\x85\x0c")
172
- # pkt.calc
166
+ # pkt.dot11_management.add_element(type: 'SSID', value: 'My SSID')
167
+ # pkt.dot11_management.add_element(type: 'Rates', value: "\x85\x0c")
173
168
  # pkt.to_w('wlan0')
174
169
  # @author Sylvain Daubert
175
170
  # @since 1.4.0
@@ -226,10 +221,12 @@ module PacketGen
226
221
  define_attr :mac3, Eth::MacAddr
227
222
  # @!attribute sequence_ctrl
228
223
  # @return [Integer] 16-bit sequence control word
229
- # @!attribute sequence_number (12-bit field from {#sequence_ctrl})
224
+ # @!attribute sequence_number
225
+ # 12-bit field from {#sequence_ctrl}
230
226
  # @return [Integer]
231
227
  # @since 2.1.3
232
- # @!attribute fragment_number (4-bit field from {#sequence_ctrl})
228
+ # @!attribute fragment_number
229
+ # 4-bit attribute from {#sequence_ctrl}
233
230
  # @return [Integer]
234
231
  # @since 2.1.3
235
232
  define_bit_attr :sequence_ctrl, sequence_number: 12, fragment_number: 4
@@ -243,9 +240,11 @@ module PacketGen
243
240
  # @return [Integer] 16-bit HT control word
244
241
  define_attr :ht_ctrl, BinStruct::Int32
245
242
  # @!attribute body
243
+ # Dot11 body, if any
246
244
  # @return [BinStruct::String]
247
245
  define_attr :body, BinStruct::String
248
246
  # @!attribute fcs
247
+ # Checksum of the Dot11 frame.
249
248
  # @return [BinStruct::Int32le]
250
249
  define_attr :fcs, BinStruct::Int32le
251
250
 
@@ -260,7 +259,7 @@ module PacketGen
260
259
  @applicable_attributes = old_attributes
261
260
  end
262
261
 
263
- # Get all used field names
262
+ # Get all used attribute names
264
263
  # @return [Array<Symbol>]
265
264
  def attributes
266
265
  @applicable_attributes
@@ -279,7 +278,7 @@ module PacketGen
279
278
  if self.instance_of?(Dot11)
280
279
  return self if str.nil?
281
280
 
282
- force_binary str
281
+ str = str.b unless str.encoding == Encoding::BINARY
283
282
  self[:frame_ctrl].read(str[0, 2])
284
283
 
285
284
  case type
@@ -305,10 +304,11 @@ module PacketGen
305
304
  fcs
306
305
  end
307
306
 
307
+ # Generate binary string
308
308
  # @return [String]
309
309
  def to_s
310
310
  define_applicable_attributes
311
- @applicable_attributes.map { |f| force_binary @attributes[f].to_s }.join
311
+ @applicable_attributes.map { |f| @attributes[f].to_s.b }.join
312
312
  end
313
313
 
314
314
  # Get human readable type
@@ -343,7 +343,7 @@ module PacketGen
343
343
  Inject.inject(iface: iface, data: self)
344
344
  end
345
345
 
346
- # Callback called when a Dot11 header is added to a packet
346
+ # Callback called when a Dot11 header is added to a packet.
347
347
  # Here, add +#dot11+ method as a shortcut to existing
348
348
  # +#dot11_(control|management|data)+.
349
349
  # @param [Packet] packet
@@ -357,7 +357,7 @@ module PacketGen
357
357
  private
358
358
 
359
359
  def remove_from_applicable_attributes(attributes)
360
- attributes = [attributes] unless attributes.is_a? Array
360
+ attributes = [attributes] unless attributes.is_a?(Array)
361
361
  @applicable_attributes -= attributes
362
362
  end
363
363
 
@@ -11,13 +11,14 @@ module PacketGen
11
11
  # IEEE 802.1Q VLAN tagging
12
12
  #
13
13
  # A VLAN tag consists of:
14
- # * a {#tci Tag Control Information} ({BinStruct::Int16}),
15
- # * a {#ethertype} ({BinStruct::Int16}),
16
- # * and a body (a {BinStruct::String} or another Header class).
14
+ # * a {#tci Tag Control Information} (+BinStruct::Int16+),
15
+ # * a {#ethertype} (+BinStruct::Int16+),
16
+ # * and a body (a +BinStruct::String+ or another {Headerable} class).
17
17
  #
18
- # == Create a Dot1q header
18
+ # @example Create a Dot1q header
19
19
  # # Create a IP packet in VLAN #43
20
20
  # pkt = PacketGen.gen('Eth').add('Dot1q', vid: 43).add('IP')
21
+ # pkt.is?('Dot1q') #=> true
21
22
  # @author Sylvain Daubert
22
23
  # @since 1.4.0
23
24
  class Dot1q < Base
@@ -11,15 +11,15 @@ module PacketGen
11
11
  # IEEE 802.1X / EAPOL
12
12
  #
13
13
  # A IEEE 802.1X header consists of:
14
- # * a {#version} ({BinStruct::Int8}),
15
- # * a packet {#type} ({BinStruct::Int8}),
16
- # * a {#length} ({BinStruct::Int16}),
17
- # * and a body (a {BinStruct::String} or another Header class).
18
- # == Create a Dot1x header
14
+ # * a {#version} (+BinStruct::Int8+),
15
+ # * a packet {#type} (+BinStruct::Int8+),
16
+ # * a {#length} (+BinStruct::Int16+),
17
+ # * and a body (a +BinStruct::String+ or another {Headerable} class).
18
+ # @example Create a Dot1x header
19
+ # # Create with integer type
19
20
  # pkt1 = PacketGen.gen('Eth').add('Dot1x', type: 1)
20
- # pkt2 = PacketGen.gen('Eth').add('Dot1x')
21
- # pkt2.dot1x.type = 'EAP Packet'
22
- # pkt2.dot1x.body.read 'body'
21
+ # # Create with human-readable type
22
+ # pkt2 = PacketGen.gen('Eth').add('Dot1x', type: 'EAP Packet')
23
23
  # @author Sylvain Daubert
24
24
  # @since 1.4.0
25
25
  class Dot1x < Base
@@ -13,9 +13,9 @@ module PacketGen
13
13
  # Secure Tunneling, {https://tools.ietf.org/html/rfc4851 RFC 4851}
14
14
  #
15
15
  # {EAP::FAST} has following fields:
16
- # * {#flags} ({BinStruct::Int8}),
17
- # * optionally {#message_length} ({BinStruct::Int32}), if +#l?+ is +true+,
18
- # * {#body} ({BinStruct::String}).
16
+ # * {#flags} (+BinStruct::Int8+),
17
+ # * optionally {#message_length} (+BinStruct::Int32+), if +#l?+ is +true+,
18
+ # * {#body} (+BinStruct::String+).
19
19
  # @author Sylvain Daubert
20
20
  # @since 2.1.4
21
21
  class FAST < TTLS
@@ -18,15 +18,23 @@ module PacketGen
18
18
  remove_attr :body
19
19
 
20
20
  # @!attribute value_size
21
- # @return [Integer] 8-bit value size
21
+ # 8-bit size of the {#value} attribute.
22
+ # @return [Integer]
22
23
  define_attr :value_size, BinStruct::Int8
23
24
  # @!attribute value
25
+ # MD5 challenge value, as an octet stream, as per {https://datatracker.ietf.org/doc/html/rfc1994#section-4 RFC1994}
24
26
  # @return [::String]
25
27
  define_attr :value, BinStruct::String,
26
28
  builder: ->(h, t) { t.new(length_from: h[:value_size]) }
27
- # @!attribute optional_name
29
+ # @!attribute name
30
+ # Name identifying the system sending the packet. It is or or more octets. Its size is
31
+ # determined from the {#length} attribute.
28
32
  # @return [::String]
29
- define_attr :optional_name, BinStruct::String
33
+ # @since 4.1.0 Attribute renamed from +optioanl_name+ to +name+
34
+ define_attr :name, BinStruct::String
35
+
36
+ # @deprecated
37
+ alias optional_name name
30
38
  end
31
39
  end
32
40
  end
@@ -13,22 +13,23 @@ module PacketGen
13
13
  # {https://tools.ietf.org/html/rfc5216 RFC 5216}
14
14
  #
15
15
  # {EAP::TLS} has following fields:
16
- # * {#flags} ({BinStruct::Int8}),
17
- # * optionally {#tls_length} ({BinStruct::Int32}), if +#l?+ is +true+,
18
- # * {#body} ({BinStruct::String}).
16
+ # * {#flags} (+BinStruct::Int8+),
17
+ # * optionally {#tls_length} (+BinStruct::Int32+), if +#l?+ is +true+,
18
+ # * {#body} (+BinStruct::String+).
19
19
  # @author Sylvain Daubert
20
20
  # @since 2.1.4
21
21
  class TLS < EAP
22
22
  update_attr :type, default: 13
23
23
  # @!attribute flags
24
- # @return [Integer] 8-bit flags
25
- # @!attribute l
26
- # Say if length field is included
24
+ # 8-bit flags
27
25
  # @return [Integer]
28
- # @!attribute m
26
+ # @!attribute l?
27
+ # Say if {#tls_length 32-bit TLS length attribute} is included.
28
+ # @return [Integer]
29
+ # @!attribute m?
29
30
  # Say if there are more fragments
30
31
  # @return [Integer]
31
- # @!attribute s
32
+ # @!attribute s?
32
33
  # If set, this message is a TLS-Start
33
34
  # @return [Integer]
34
35
  define_bit_attr_before :body, :flags, l: 1, m: 1, s: 1, reserved: 5
@@ -13,28 +13,31 @@ module PacketGen
13
13
  # {https://tools.ietf.org/html/rfc5281 RFC 5281}
14
14
  #
15
15
  # {EAP::TTLS} has following fields:
16
- # * {#flags} ({BinStruct::Int8}),
17
- # * optionally {#message_length} ({BinStruct::Int32}), if +#l?+ is +true+,
18
- # * {#body} ({BinStruct::String}).
16
+ # * {#flags} (+BinStruct::Int8+),
17
+ # * optionally {#message_length} (+BinStruct::Int32+), if +#l?+ is +true+,
18
+ # * {#body} (+BinStruct::String+).
19
19
  # @author Sylvain Daubert
20
20
  # @since 2.1.4
21
21
  class TTLS < EAP
22
22
  update_attr :type, default: 21
23
23
  # @!attribute flags
24
- # @return [Integer] 8-bit flags
25
- # @!attribute l
26
- # Say if length field is included
24
+ # 8-bit flags
27
25
  # @return [Integer]
28
- # @!attribute m
26
+ # @!attribute l?
27
+ # Say if {#message_length} field is included
28
+ # @return [Integer]
29
+ # @!attribute m?
29
30
  # Say if there are more fragments
30
31
  # @return [Integer]
31
- # @!attribute s
32
+ # @!attribute s?
32
33
  # If set, this message is a TLS-Start
33
34
  # @return [Integer]
34
35
  # @!attribute reserved
35
- # @return [Integer] 2-bit reserved integer
36
+ # 2-bit reserved integer
37
+ # @return [Integer]
36
38
  # @!attribute version
37
- # @return [Integer] 3-bit version
39
+ # 3-bit version
40
+ # @return [Integer]
38
41
  define_bit_attr_before :body, :flags, l: 1, m: 1, s: 1, reserved: 2, version: 3
39
42
  alias length_present? l?
40
43
  alias more_fragments? m?
@@ -12,34 +12,22 @@ module PacketGen
12
12
  # {https://tools.ietf.org/html/rfc3748 RFC 3748}
13
13
  #
14
14
  # A EAP header has:
15
- # * a {#code} field ({BinStruct::Int8Enum}),
16
- # * a {#id} field ({BinStruct::Int8}),
17
- # * a {#length} field ({BinStruct::Int16}).
15
+ # * a {#code} field (+BinStruct::Int8Enum+),
16
+ # * a {#id} field (+BinStruct::Int8+),
17
+ # * a {#length} field (+BinStruct::Int16+).
18
18
  # Request (code 1) and Response (code 2) packets also have:
19
19
  # * a {#type} field (+BinStruct::Int8Enum+).
20
20
  # And Expanded Types (type 254) packets also have:
21
- # * a {#vendor_id} field ({BinStruct::Int24}),
22
- # * a {#vendor_type} field ({BinStruct::Int32}).
23
- # Finally, all packets have a {#body} ({BinStruct::String}).
24
- #
25
- # == Create EAP headers
26
- # An EAP header may be created this way:
27
- # # create a request header with default type (1)
28
- # eap = EAP.new(code: 1) # => PacketGen::Header::EAP
29
- # # the same
30
- # eap = EAP.new(code: 'Request') # => PacketGen::Header::EAP
31
- # # create a Response header of type Nak
32
- # nak = EAP.new(code: 'Response', type: 'Nak')
21
+ # * a {#vendor_id} field (+BinStruct::Int24+),
22
+ # * a {#vendor_type} field (+BinStruct::Int32+).
23
+ # Finally, all packets have a {#body} (+BinStruct::String+).
33
24
  #
34
25
  # === Specialized headers
35
26
  # Some EAP has a specialized class:
36
- # * EAP-MD5,
37
- # * EAP-TLS,
38
- # * EAP-TTLS,
39
- # * EAP-FAST.
40
- # Creating such a header is fairly simple:
41
- # # Generate a EAP-TLS Response (type is forced to 13)
42
- # eap = EAP::TLS.new(code: 2) # => PacketGen::Header::EAP::TLS
27
+ # * EAP-MD5 ({EAP::MD5}),
28
+ # * EAP-TLS ({EAP::TLS}),
29
+ # * EAP-TTLS ({EAP::TTLS}),
30
+ # * EAP-FAST ({EAP::FAST}).
43
31
  #
44
32
  # == Header accessors
45
33
  # EAP headers may be accessed through +Packet#eap+ accessor.
@@ -54,7 +42,29 @@ module PacketGen
54
42
  # So result of parsing a EAP header may be a {EAP}, {EAP::MD5}, {EAP::TLS},
55
43
  # {EAP::TTLS} or {EAP::FAST} instance. But this instance is still accessible
56
44
  # through +Packet#eap+.
45
+ #
46
+ # @example Create EAP headers
47
+ # # create a request header with default type (1)
48
+ # eap = PacketGen::Header::EAP.new(code: 1)
49
+ # eap.human_code #=> 'Request'
50
+ # # the same
51
+ # eap = PacketGen::Header::EAP.new(code: 'Request')
52
+ # eap.code #=> 1
53
+ # # create a Response header of type Nak
54
+ # nak = PacketGen::Header::EAP.new(code: 'Response', type: 'Nak')
55
+ # nak.code #=> 2
56
+ # nak.type #=> 3
57
+ #
58
+ # @example Create a specialized EAP header
59
+ # eap = PacketGen::Header::EAP::TLS.new(code: 2)
60
+ # eap.class #=> PacketGen::Header::EAP::TLS
61
+ #
62
+ # @example Parse a specialized class from a binary string
63
+ # pkt = PacketGen.parse("\x01\x00\x00\x0e\x04\x04\x00\x01\x02\x03name", first_header: 'EAP')
64
+ # pkt.eap.class # => PacketGen::Header::EAP::MD5
65
+ #
57
66
  # @author Sylvain Daubert
67
+ # @author LemonTree55
58
68
  # @since 2.1.4
59
69
  class EAP < Base
60
70
  # EAP known codes
@@ -81,41 +91,48 @@ module PacketGen
81
91
  }.freeze
82
92
 
83
93
  # @!attribute code
84
- # @return [Integer] 8-bit EAP code
94
+ # 8-bit EAP code. See {CODES known EAP codes}
95
+ # @return [Integer]
85
96
  define_attr :code, BinStruct::Int8Enum, enum: CODES
86
97
 
87
98
  # @!attribute id
88
- # @return [Integer] 8-bit identifier
99
+ # 8-bit identifier
100
+ # @return [Integer]
89
101
  define_attr :id, BinStruct::Int8
90
102
 
91
103
  # @!attribute length
92
- # @return [Integer] 16-bit length of EAP packet
104
+ # 16-bit length of EAP packet
105
+ # @return [Integer]
93
106
  define_attr :length, BinStruct::Int16, default: 4
94
107
 
95
108
  # @!attribute type
96
- # This field is present only for Request or Response packets,
97
- # with type different from Expanded Types (254).
98
- # @return [Integer] 8-bit request or response type
109
+ # 8-bit request or response type.
110
+ # This field is present only for Request or Response packets.
111
+ # See {TYPES known EAP types}.
112
+ # @return [Integer]
99
113
  define_attr :type, BinStruct::Int8Enum,
100
114
  enum: TYPES,
101
115
  optional: lambda(&:type?)
102
116
 
103
117
  # @!attribute vendor_id
118
+ # 24-bit vendor ID.
104
119
  # This field is present only for Request or Response packets,
105
120
  # with type equal to +Expanded Types+ (254).
106
- # @return [Integer] 24-bit vendor ID
121
+ # @return [Integer]
107
122
  define_attr :vendor_id, BinStruct::Int24,
108
123
  optional: ->(eap) { eap.type? && (eap.type == 254) }
109
124
 
110
125
  # @!attribute vendor_type
126
+ # 32-bit vendor type.
111
127
  # This field is present only for Request or Response packets,
112
128
  # with type equal to +Expanded Types+ (254).
113
- # @return [Integer] 32-bit vendor type
129
+ # @return [Integer]
114
130
  define_attr :vendor_type, BinStruct::Int32,
115
131
  optional: ->(eap) { eap.type? && (eap.type == 254) }
116
132
 
117
133
  # @!attribute body
118
- # @return [BinStruct::String, Header::Base]
134
+ # EAP packet body
135
+ # @return [BinStruct::String, Headerable]
119
136
  define_attr :body, BinStruct::String
120
137
 
121
138
  # @return [EAP]
@@ -129,7 +146,7 @@ module PacketGen
129
146
 
130
147
  # Populate object from a binary string
131
148
  # @param [String] str
132
- # @return [Dot11] may return a subclass object if a more specific class
149
+ # @return [EAP] may return a subclass object if a more specific class
133
150
  # may be determined
134
151
  def read(str)
135
152
  super
@@ -189,11 +206,19 @@ module PacketGen
189
206
  code == CODES['Failure']
190
207
  end
191
208
 
209
+ # Is packet a NAK?
210
+ # @return [Boolean]
211
+ # @since 4.1.0
212
+ # @author LemonTree55
213
+ def nak?
214
+ (code == 2) && (type == 3)
215
+ end
216
+
192
217
  # Return an array of desired authentication types from a Nak packet
193
218
  # @return [Array<Integer>]
194
219
  # @raise [ParseError] not a Nak packet
195
220
  def desired_auth_type
196
- raise ParseError, 'not a Nak response' if (code != 2) && (type != 3)
221
+ raise ParseError, 'not a Nak response' unless nak?
197
222
 
198
223
  body.to_s.unpack('C*')
199
224
  end
@@ -10,26 +10,32 @@ module PacketGen
10
10
  module Header
11
11
  # An Ethernet header consists of:
12
12
  # * a destination MAC address ({MacAddr}),
13
- # * a source MAC address (MacAddr),
14
- # * a {#ethertype} ({BinStruct::Int16}),
15
- # * and a body (a {BinStruct::String} or another Header class).
13
+ # * a source MAC address ({MacAddr}),
14
+ # * a {#ethertype} (+BinStruct::Int16+),
15
+ # * and a body (a +BinStruct::String+ or another {Headerable} class).
16
16
  #
17
- # == Create a Ethernet header
17
+ # @example Create a Ethernet header
18
18
  # # standalone
19
19
  # eth = PacketGen::Header::Eth.new
20
20
  # # in a packet
21
21
  # pkt = PacketGen.gen('Eth')
22
22
  # # access to Ethernet header
23
- # pkt.eth # => PacketGen::Header::Eth
23
+ # pkt.eth.class # => PacketGen::Header::Eth
24
24
  #
25
- # == Ethernet attributes
25
+ # @example Access to Ethernet attributes
26
+ # eth = PacketGen::Header::Eth.new(src: '00:01:01:01:01:01', ethertype: 0x1234)
27
+ # # Set destination MAC address
26
28
  # eth.dst = "00:01:02:03:04:05"
27
- # eth.src # => "00:01:01:01:01:01"
28
- # eth[:src] # => PacketGen::Header::Eth::MacAddr
29
- # eth.ethertype # => 16-bit Integer
29
+ # # Access source MAC address, human-redable
30
+ # eth.src # => "00:01:01:01:01:01"
31
+ # # Access to MacAddr object
32
+ # eth[:src].class # => PacketGen::Header::Eth::MacAddr
33
+ # eth.ethertype # => 0x1234
34
+ # # Set Ethernet body
30
35
  # eth.body = "This is a body"
31
36
  #
32
37
  # @author Sylvain Daubert
38
+ # @author LemonTree55
33
39
  class Eth < Base
34
40
  # Ethernet MAC address, as a group of 6 bytes
35
41
  # @author Sylvain Daubert
@@ -58,6 +64,10 @@ module PacketGen
58
64
  # Read a human-readable string to populate +MacAddr+
59
65
  # @param [String] str
60
66
  # @return [self]
67
+ # @example
68
+ # mac = PacketGen::Header::Eth::MacAddr.new
69
+ # mac.from_human('01:02:03:04:05:06')
70
+ # mac.a5 # => 6
61
71
  def from_human(str)
62
72
  return self if str.nil?
63
73
 
@@ -76,6 +86,8 @@ module PacketGen
76
86
  attributes.map { |m| '%02x' % self[m] }.join(':')
77
87
  end
78
88
 
89
+ # Equality check. +true+ only if +other+ is a MacAddr, and each address byte is the same.
90
+ # @return [Boolean]
79
91
  def ==(other)
80
92
  other.is_a?(self.class) &&
81
93
  attributes.all? { |attr| self[attr].value == other[attr].value }
@@ -83,16 +95,18 @@ module PacketGen
83
95
  end
84
96
 
85
97
  # @!attribute dst
86
- # @return [MacAddr] Destination MAC address
98
+ # Destination MAC address
99
+ # @return [::String]
87
100
  define_attr :dst, MacAddr, default: '00:00:00:00:00:00'
88
101
  # @!attribute src
89
- # @return [MacAddr] Source MAC address
102
+ # Source MAC address
103
+ # @return [::String]
90
104
  define_attr :src, MacAddr, default: '00:00:00:00:00:00'
91
105
  # @!attribute ethertype
92
106
  # @return [Integer] 16-bit integer to determine payload type
93
107
  define_attr :ethertype, BinStruct::Int16, default: 0
94
108
  # @!attribute body
95
- # @return [BinStruct::String,Header::Base]
109
+ # @return [BinStruct::String,Headerable]
96
110
  define_attr :body, BinStruct::String
97
111
 
98
112
  # send Eth packet on wire.
@@ -20,21 +20,40 @@ module PacketGen
20
20
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
21
  # | Sequence Number (Optional) |
22
22
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
+ #
24
+ # A GRE header is composed of:
25
+ # * A first 16-bit attribute containing given flags:
26
+ # * {#c} indicates if {#checksum} and {#reserved1} attributes are present.
27
+ # * {#k} indicates if {#key} attribute is present.
28
+ # * {#s} indicatesid {#sequence_number} attribute is present.
29
+ # * {#ver} 3-bit version number.
30
+ # * {#protocol_type} (+BinStruct::Int16+).
31
+ # * optional {#checksum} and {#reserved1} attribute (both +BinStruct::Int16+).
32
+ # * optional {#key} attribute (+BinStruct::Int32+).
33
+ # * optional {#sequence_number} attribute (+BinStruct::Int32+).
34
+ # * and a {#body} (+BinStruct::String or {Headerable}).
35
+ #
36
+ # Current implementation supports tunneling {IP} and {IPv6} packets in GRE.
23
37
  # @author Sylvain Daubert
38
+ # @author LemonTree55
24
39
  # @since 2.1.0
25
40
  class GRE < Base
26
41
  # IP protocol number for GRE
27
42
  IP_PROTOCOL = 47
28
43
 
29
44
  # @!attribute c
45
+ # Say if {#checksum} and {#reserved1} attributes are present
30
46
  # @return [Boolean]
31
47
  # @!attribute k
48
+ # Say if {#key} attribute is present
32
49
  # @return [Boolean]
33
50
  # @!attribute s
51
+ # Say if {#sequence_number} attribute is present
34
52
  # @return [Boolean]
35
53
  # @!attribute reserved0
36
54
  # @return [Integer]
37
55
  # @!attribute ver
56
+ # 3-bit GRE protocol version.
38
57
  # @return [Integer]
39
58
  define_bit_attr :u16, c: 1, r: 1, k: 1, s: 1, reserved0: 9, ver: 3
40
59
 
@@ -42,19 +61,24 @@ module PacketGen
42
61
  # @return [Integer]
43
62
  define_attr :protocol_type, BinStruct::Int16
44
63
  # @!attribute checksum
64
+ # IP checksum over all 16-bit words in GRE header and its body. Present only if {#c} is set.
45
65
  # @return [Integer]
46
66
  define_attr :checksum, BinStruct::Int16, default: 0, optional: lambda(&:c?)
47
67
  # @!attribute reserved1
68
+ # Reserved field, present only if {#c} is set.
48
69
  # @return [Integer]
49
70
  define_attr :reserved1, BinStruct::Int16, default: 0, optional: lambda(&:c?)
50
71
  # @!attribute key
72
+ # 32-bit integer used to identify an individual traffic flow within a tunnel.
73
+ # Present only if {#k} is set.
51
74
  # @return [Integer]
52
75
  define_attr :key, BinStruct::Int32, optional: lambda(&:k?)
53
76
  # @!attribute sequence_number
77
+ # 32-bit integer. Present only if {#s} is set.
54
78
  # @return [Integer]
55
79
  define_attr :sequence_number, BinStruct::Int32, optional: lambda(&:s?)
56
80
  # @!attribute body
57
- # @return [BinStruct::String,Header::Base]
81
+ # @return [BinStruct::String,Headerable]
58
82
  define_attr :body, BinStruct::String
59
83
 
60
84
  alias seqnum sequence_number
@@ -65,7 +89,7 @@ module PacketGen
65
89
  super(opts)
66
90
  end
67
91
 
68
- # Compute checksum and set +checksum+ field
92
+ # Compute checksum and set +checksum+ attribute.
69
93
  # @return [Integer]
70
94
  def calc_checksum
71
95
  sum = IP.sum16(self)