packetgen 3.3.3 → 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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -22
  3. data/lib/packetgen/capture.rb +2 -2
  4. data/lib/packetgen/config.rb +0 -1
  5. data/lib/packetgen/deprecation.rb +14 -8
  6. data/lib/packetgen/header/arp.rb +17 -18
  7. data/lib/packetgen/header/asn1_base.rb +2 -1
  8. data/lib/packetgen/header/base.rb +42 -40
  9. data/lib/packetgen/header/bootp.rb +35 -37
  10. data/lib/packetgen/header/dhcp/option.rb +21 -21
  11. data/lib/packetgen/header/dhcp/options.rb +3 -3
  12. data/lib/packetgen/header/dhcp.rb +8 -9
  13. data/lib/packetgen/header/dhcpv6/duid.rb +16 -16
  14. data/lib/packetgen/header/dhcpv6/option.rb +83 -61
  15. data/lib/packetgen/header/dhcpv6/options.rb +4 -4
  16. data/lib/packetgen/header/dhcpv6/relay.rb +6 -5
  17. data/lib/packetgen/header/dhcpv6.rb +17 -18
  18. data/lib/packetgen/header/dns/name.rb +21 -16
  19. data/lib/packetgen/header/dns/opt.rb +5 -2
  20. data/lib/packetgen/header/dns/option.rb +14 -14
  21. data/lib/packetgen/header/dns/qdsection.rb +3 -3
  22. data/lib/packetgen/header/dns/question.rb +7 -8
  23. data/lib/packetgen/header/dns/rr.rb +56 -43
  24. data/lib/packetgen/header/dns/rrsection.rb +6 -6
  25. data/lib/packetgen/header/dns.rb +103 -90
  26. data/lib/packetgen/header/dot11/control.rb +12 -12
  27. data/lib/packetgen/header/dot11/data.rb +25 -24
  28. data/lib/packetgen/header/dot11/element.rb +4 -4
  29. data/lib/packetgen/header/dot11/management.rb +21 -18
  30. data/lib/packetgen/header/dot11/sub_mngt.rb +40 -53
  31. data/lib/packetgen/header/dot11.rb +117 -122
  32. data/lib/packetgen/header/dot1q.rb +12 -13
  33. data/lib/packetgen/header/dot1x.rb +13 -13
  34. data/lib/packetgen/header/eap/fast.rb +4 -4
  35. data/lib/packetgen/header/eap/md5.rb +16 -8
  36. data/lib/packetgen/header/eap/tls.rb +18 -19
  37. data/lib/packetgen/header/eap/ttls.rb +22 -21
  38. data/lib/packetgen/header/eap.rb +73 -48
  39. data/lib/packetgen/header/eth.rb +41 -27
  40. data/lib/packetgen/header/gre.rb +33 -11
  41. data/lib/packetgen/header/http/headers.rb +7 -6
  42. data/lib/packetgen/header/http/request.rb +38 -29
  43. data/lib/packetgen/header/http/response.rb +35 -27
  44. data/lib/packetgen/header/http/verbs.rb +1 -3
  45. data/lib/packetgen/header/icmp.rb +14 -14
  46. data/lib/packetgen/header/icmpv6.rb +10 -9
  47. data/lib/packetgen/header/igmp.rb +26 -15
  48. data/lib/packetgen/header/igmpv3/group_record.rb +18 -13
  49. data/lib/packetgen/header/igmpv3/mq.rb +16 -18
  50. data/lib/packetgen/header/igmpv3/mr.rb +5 -5
  51. data/lib/packetgen/header/igmpv3.rb +12 -11
  52. data/lib/packetgen/header/ip/addr.rb +19 -15
  53. data/lib/packetgen/header/ip/option.rb +47 -36
  54. data/lib/packetgen/header/ip/options.rb +1 -1
  55. data/lib/packetgen/header/ip.rb +77 -95
  56. data/lib/packetgen/header/ipv6/addr.rb +28 -27
  57. data/lib/packetgen/header/ipv6/extension.rb +13 -11
  58. data/lib/packetgen/header/ipv6/hop_by_hop.rb +32 -13
  59. data/lib/packetgen/header/ipv6.rb +42 -35
  60. data/lib/packetgen/header/llc.rb +28 -21
  61. data/lib/packetgen/header/mdns.rb +10 -3
  62. data/lib/packetgen/header/mld.rb +15 -13
  63. data/lib/packetgen/header/mldv2/mcast_address_record.rb +17 -12
  64. data/lib/packetgen/header/mldv2/mlq.rb +22 -24
  65. data/lib/packetgen/header/mldv2/mlr.rb +8 -8
  66. data/lib/packetgen/header/mldv2.rb +1 -1
  67. data/lib/packetgen/header/ospfv2/db_description.rb +17 -18
  68. data/lib/packetgen/header/ospfv2/hello.rb +18 -17
  69. data/lib/packetgen/header/ospfv2/ls_ack.rb +6 -7
  70. data/lib/packetgen/header/ospfv2/ls_request.rb +14 -13
  71. data/lib/packetgen/header/ospfv2/ls_update.rb +9 -9
  72. data/lib/packetgen/header/ospfv2/lsa.rb +79 -60
  73. data/lib/packetgen/header/ospfv2/lsa_header.rb +12 -11
  74. data/lib/packetgen/header/ospfv2.rb +49 -46
  75. data/lib/packetgen/header/ospfv3/db_description.rb +20 -22
  76. data/lib/packetgen/header/ospfv3/hello.rb +17 -16
  77. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +22 -20
  78. data/lib/packetgen/header/ospfv3/ls_ack.rb +7 -8
  79. data/lib/packetgen/header/ospfv3/ls_request.rb +18 -18
  80. data/lib/packetgen/header/ospfv3/ls_update.rb +10 -10
  81. data/lib/packetgen/header/ospfv3/lsa.rb +62 -51
  82. data/lib/packetgen/header/ospfv3/lsa_header.rb +12 -11
  83. data/lib/packetgen/header/ospfv3.rb +54 -52
  84. data/lib/packetgen/header/sctp/chunk.rb +80 -56
  85. data/lib/packetgen/header/sctp/error.rb +174 -202
  86. data/lib/packetgen/header/sctp/padded32.rb +3 -3
  87. data/lib/packetgen/header/sctp/parameter.rb +89 -136
  88. data/lib/packetgen/header/sctp.rb +19 -8
  89. data/lib/packetgen/header/snmp.rb +108 -7
  90. data/lib/packetgen/header/tcp/option.rb +52 -39
  91. data/lib/packetgen/header/tcp/options.rb +13 -5
  92. data/lib/packetgen/header/tcp.rb +83 -65
  93. data/lib/packetgen/header/tftp.rb +31 -25
  94. data/lib/packetgen/header/udp.rb +21 -19
  95. data/lib/packetgen/header.rb +23 -18
  96. data/lib/packetgen/headerable.rb +21 -5
  97. data/lib/packetgen/inspect.rb +3 -8
  98. data/lib/packetgen/packet.rb +146 -71
  99. data/lib/packetgen/pcap.rb +15 -4
  100. data/lib/packetgen/pcapng/block.rb +20 -18
  101. data/lib/packetgen/pcapng/epb.rb +13 -15
  102. data/lib/packetgen/pcapng/file.rb +44 -111
  103. data/lib/packetgen/pcapng/idb.rb +11 -12
  104. data/lib/packetgen/pcapng/shb.rb +15 -16
  105. data/lib/packetgen/pcapng/spb.rb +9 -11
  106. data/lib/packetgen/pcapng/unknown_block.rb +6 -17
  107. data/lib/packetgen/pcapng.rb +6 -4
  108. data/lib/packetgen/pcaprub_wrapper.rb +17 -1
  109. data/lib/packetgen/proto.rb +5 -1
  110. data/lib/packetgen/unknown_packet.rb +5 -5
  111. data/lib/packetgen/utils/arp_spoofer.rb +18 -19
  112. data/lib/packetgen/utils.rb +4 -3
  113. data/lib/packetgen/version.rb +1 -1
  114. data/lib/packetgen.rb +12 -5
  115. metadata +29 -38
  116. data/lib/packetgen/types/abstract_tlv.rb +0 -278
  117. data/lib/packetgen/types/array.rb +0 -287
  118. data/lib/packetgen/types/cstring.rb +0 -109
  119. data/lib/packetgen/types/enum.rb +0 -171
  120. data/lib/packetgen/types/fieldable.rb +0 -66
  121. data/lib/packetgen/types/fields.rb +0 -622
  122. data/lib/packetgen/types/int.rb +0 -473
  123. data/lib/packetgen/types/int_string.rb +0 -102
  124. data/lib/packetgen/types/length_from.rb +0 -54
  125. data/lib/packetgen/types/oui.rb +0 -52
  126. data/lib/packetgen/types/string.rb +0 -97
  127. data/lib/packetgen/types/tlv.rb +0 -161
  128. data/lib/packetgen/types.rb +0 -26
@@ -13,31 +13,32 @@ module PacketGen
13
13
  # {https://tools.ietf.org/html/rfc5281 RFC 5281}
14
14
  #
15
15
  # {EAP::TTLS} has following fields:
16
- # * {#flags} ({Types::Int8}),
17
- # * optionally {#message_length} ({Types::Int32}), if +#l?+ is +true+,
18
- # * {#body} ({Types::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
- update_field :type, default: 21
22
+ update_attr :type, default: 21
23
23
  # @!attribute flags
24
- # @return [Integer] 8-bit flags
25
- define_field_before :body, :flags, Types::Int8
26
-
27
- # @!attribute l
28
- # Say if length field is included. Defined on {#flags} field.
29
- # @return [Boolean]
30
- # @!attribute m
31
- # Say if there are more fragments. Defined on {#flags} field.
32
- # @return [Boolean]
33
- # @!attribute s
34
- # If set, this message is a TLS-Start. Defined on {#flags} field.
35
- # @return [Boolean]
24
+ # 8-bit flags
25
+ # @return [Integer]
26
+ # @!attribute l?
27
+ # Say if {#message_length} field is included
28
+ # @return [Integer]
29
+ # @!attribute m?
30
+ # Say if there are more fragments
31
+ # @return [Integer]
32
+ # @!attribute s?
33
+ # If set, this message is a TLS-Start
34
+ # @return [Integer]
36
35
  # @!attribute reserved
37
- # @return [Integer] 2-bit reserved integer
36
+ # 2-bit reserved integer
37
+ # @return [Integer]
38
38
  # @!attribute version
39
- # @return [Integer] 3-bit version
40
- define_bit_fields_on :flags, :l, :m, :s, :reserved, 2, :version, 3
39
+ # 3-bit version
40
+ # @return [Integer]
41
+ define_bit_attr_before :body, :flags, l: 1, m: 1, s: 1, reserved: 2, version: 3
41
42
  alias length_present? l?
42
43
  alias more_fragments? m?
43
44
  alias tls_start? s?
@@ -47,8 +48,8 @@ module PacketGen
47
48
  # raw data message sequence prior to fragmentation. So, it
48
49
  # cannot be automatically calculated (no +#calc_length+ method).
49
50
  # @return [Integer] 32-bit message length
50
- define_field_before :body, :message_length, Types::Int32,
51
- optional: ->(h) { h.l? }
51
+ define_attr_before :body, :message_length, BinStruct::Int32,
52
+ optional: lambda(&:l?)
52
53
 
53
54
  # @return [String]
54
55
  def inspect
@@ -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 ({Types::Int8Enum}),
16
- # * a {#id} field ({Types::Int8}),
17
- # * a {#length} field ({Types::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
- # * a {#type} field (+Types::Int8Enum+).
19
+ # * a {#type} field (+BinStruct::Int8Enum+).
20
20
  # And Expanded Types (type 254) packets also have:
21
- # * a {#vendor_id} field ({Types::Int24}),
22
- # * a {#vendor_type} field ({Types::Int32}).
23
- # Finally, all packets have a {#body} ({Types::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,42 +91,49 @@ module PacketGen
81
91
  }.freeze
82
92
 
83
93
  # @!attribute code
84
- # @return [Integer] 8-bit EAP code
85
- define_field :code, Types::Int8Enum, enum: CODES
94
+ # 8-bit EAP code. See {CODES known EAP codes}
95
+ # @return [Integer]
96
+ define_attr :code, BinStruct::Int8Enum, enum: CODES
86
97
 
87
98
  # @!attribute id
88
- # @return [Integer] 8-bit identifier
89
- define_field :id, Types::Int8
99
+ # 8-bit identifier
100
+ # @return [Integer]
101
+ define_attr :id, BinStruct::Int8
90
102
 
91
103
  # @!attribute length
92
- # @return [Integer] 16-bit length of EAP packet
93
- define_field :length, Types::Int16, default: 4
104
+ # 16-bit length of EAP packet
105
+ # @return [Integer]
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
99
- define_field :type, Types::Int8Enum,
100
- enum: TYPES,
101
- optional: ->(eap) { eap.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]
113
+ define_attr :type, BinStruct::Int8Enum,
114
+ enum: TYPES,
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
107
- define_field :vendor_id, Types::Int24,
108
- optional: ->(eap) { eap.type? && (eap.type == 254) }
121
+ # @return [Integer]
122
+ define_attr :vendor_id, BinStruct::Int24,
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
114
- define_field :vendor_type, Types::Int32,
115
- optional: ->(eap) { eap.type? && (eap.type == 254) }
129
+ # @return [Integer]
130
+ define_attr :vendor_type, BinStruct::Int32,
131
+ optional: ->(eap) { eap.type? && (eap.type == 254) }
116
132
 
117
133
  # @!attribute body
118
- # @return [Types::String, Header::Base]
119
- define_field :body, Types::String
134
+ # EAP packet body
135
+ # @return [BinStruct::String, Headerable]
136
+ define_attr :body, BinStruct::String
120
137
 
121
138
  # @return [EAP]
122
139
  def initialize(options={})
@@ -129,10 +146,10 @@ 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
- super(str)
152
+ super
136
153
  return self unless self.instance_of?(EAP)
137
154
  return self unless type?
138
155
 
@@ -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
@@ -201,7 +226,7 @@ module PacketGen
201
226
  # Calculate length field from content
202
227
  # @return [Integer]
203
228
  def calc_length
204
- Base.calculate_and_set_length self
229
+ Base.calculate_and_set_length(self)
205
230
  end
206
231
 
207
232
  # Say is this EAP header has {#type} field
@@ -217,7 +242,7 @@ module PacketGen
217
242
  # @param [Packet] packet
218
243
  # @return [void]
219
244
  def added_to_packet(packet)
220
- return if packet.respond_to? :eap
245
+ return if packet.respond_to?(:eap)
221
246
 
222
247
  packet.instance_eval("def eap(arg=nil); header(#{self.class}, arg); end") # def eap(arg=nil); header(EAP, arg); end
223
248
  end
@@ -10,54 +10,64 @@ 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} ({Types::Int16}),
15
- # * and a body (a {Types::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
36
- class MacAddr < Types::Fields
37
- include Types::Fieldable
42
+ class MacAddr < BinStruct::Struct
43
+ include BinStruct::Structable
38
44
 
39
45
  # @!attribute a0
40
46
  # @return [Integer] first byte from MacAddr
41
- define_field :a0, Types::Int8
47
+ define_attr :a0, BinStruct::Int8
42
48
  # @!attribute a1
43
49
  # @return [Integer] second byte from MacAddr
44
- define_field :a1, Types::Int8
50
+ define_attr :a1, BinStruct::Int8
45
51
  # @!attribute a2
46
52
  # @return [Integer] third byte from MacAddr
47
- define_field :a2, Types::Int8
53
+ define_attr :a2, BinStruct::Int8
48
54
  # @!attribute a3
49
55
  # @return [Integer] fourth byte from MacAddr
50
- define_field :a3, Types::Int8
56
+ define_attr :a3, BinStruct::Int8
51
57
  # @!attribute a4
52
58
  # @return [Integer] fifth byte from MacAddr
53
- define_field :a4, Types::Int8
59
+ define_attr :a4, BinStruct::Int8
54
60
  # @!attribute a5
55
61
  # @return [Integer] sixth byte from MacAddr
56
- define_field :a5, Types::Int8
62
+ define_attr :a5, BinStruct::Int8
57
63
 
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
 
@@ -65,7 +75,7 @@ module PacketGen
65
75
  raise ArgumentError, 'not a MAC address' unless bytes.size == 6
66
76
 
67
77
  6.times do |i|
68
- self[:"a#{i}"].read(bytes[i].to_i(16))
78
+ self[:"a#{i}"].from_human(bytes[i].to_i(16))
69
79
  end
70
80
  self
71
81
  end
@@ -73,27 +83,31 @@ module PacketGen
73
83
  # +MacAddr+ in human readable form (colon format)
74
84
  # @return [String]
75
85
  def to_human
76
- fields.map { |m| '%02x' % self[m] }.join(':')
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
- fields.all? { |attr| self[attr].value == other[attr].value }
93
+ attributes.all? { |attr| self[attr].value == other[attr].value }
82
94
  end
83
95
  end
84
96
 
85
97
  # @!attribute dst
86
- # @return [MacAddr] Destination MAC address
87
- define_field :dst, MacAddr, default: '00:00:00:00:00:00'
98
+ # Destination MAC address
99
+ # @return [::String]
100
+ define_attr :dst, MacAddr, default: '00:00:00:00:00:00'
88
101
  # @!attribute src
89
- # @return [MacAddr] Source MAC address
90
- define_field :src, MacAddr, default: '00:00:00:00:00:00'
102
+ # Source MAC address
103
+ # @return [::String]
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
- define_field :ethertype, Types::Int16, default: 0
107
+ define_attr :ethertype, BinStruct::Int16, default: 0
94
108
  # @!attribute body
95
- # @return [Types::String,Header::Base]
96
- define_field :body, Types::String
109
+ # @return [BinStruct::String,Headerable]
110
+ define_attr :body, BinStruct::String
97
111
 
98
112
  # send Eth packet on wire.
99
113
  # @param [String] iface interface name
@@ -20,44 +20,66 @@ 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
- define_field :u16, Types::Int16
30
-
31
44
  # @!attribute c
45
+ # Say if {#checksum} and {#reserved1} attributes are present
32
46
  # @return [Boolean]
33
47
  # @!attribute k
48
+ # Say if {#key} attribute is present
34
49
  # @return [Boolean]
35
50
  # @!attribute s
51
+ # Say if {#sequence_number} attribute is present
36
52
  # @return [Boolean]
37
53
  # @!attribute reserved0
38
54
  # @return [Integer]
39
55
  # @!attribute ver
56
+ # 3-bit GRE protocol version.
40
57
  # @return [Integer]
41
- define_bit_fields_on :u16, :c, :r, :k, :s, :reserved0, 9, :ver, 3
58
+ define_bit_attr :u16, c: 1, r: 1, k: 1, s: 1, reserved0: 9, ver: 3
42
59
 
43
60
  # @!attribute protocol_type
44
61
  # @return [Integer]
45
- define_field :protocol_type, Types::Int16
62
+ define_attr :protocol_type, BinStruct::Int16
46
63
  # @!attribute checksum
64
+ # IP checksum over all 16-bit words in GRE header and its body. Present only if {#c} is set.
47
65
  # @return [Integer]
48
- define_field :checksum, Types::Int16, default: 0, optional: ->(gre) { gre.c? }
66
+ define_attr :checksum, BinStruct::Int16, default: 0, optional: lambda(&:c?)
49
67
  # @!attribute reserved1
68
+ # Reserved field, present only if {#c} is set.
50
69
  # @return [Integer]
51
- define_field :reserved1, Types::Int16, default: 0, optional: ->(gre) { gre.c? }
70
+ define_attr :reserved1, BinStruct::Int16, default: 0, optional: lambda(&:c?)
52
71
  # @!attribute key
72
+ # 32-bit integer used to identify an individual traffic flow within a tunnel.
73
+ # Present only if {#k} is set.
53
74
  # @return [Integer]
54
- define_field :key, Types::Int32, optional: ->(gre) { gre.k? }
75
+ define_attr :key, BinStruct::Int32, optional: lambda(&:k?)
55
76
  # @!attribute sequence_number
77
+ # 32-bit integer. Present only if {#s} is set.
56
78
  # @return [Integer]
57
- define_field :sequence_number, Types::Int32, optional: ->(gre) { gre.s? }
79
+ define_attr :sequence_number, BinStruct::Int32, optional: lambda(&:s?)
58
80
  # @!attribute body
59
- # @return [Types::String,Header::Base]
60
- define_field :body, Types::String
81
+ # @return [BinStruct::String,Headerable]
82
+ define_attr :body, BinStruct::String
61
83
 
62
84
  alias seqnum sequence_number
63
85
  alias seqnum= sequence_number=
@@ -67,7 +89,7 @@ module PacketGen
67
89
  super(opts)
68
90
  end
69
91
 
70
- # Compute checksum and set +checksum+ field
92
+ # Compute checksum and set +checksum+ attribute.
71
93
  # @return [Integer]
72
94
  def calc_checksum
73
95
  sum = IP.sum16(self)
@@ -9,14 +9,15 @@
9
9
  module PacketGen
10
10
  module Header
11
11
  # @since 2.2.0
12
+ # @author Kent 'picat' Gruber
12
13
  module HTTP
13
14
  # @abstract Base class for HTTP headers.
14
15
  # @author Kent 'picat' Gruber
15
16
  class Headers
16
- include Types::Fieldable
17
+ include BinStruct::Structable
17
18
 
18
- # Underlying Headers data (or nil).
19
- # @return [Hash, nil]
19
+ # Underlying Headers data.
20
+ # @return [Hash{String => String}, nil]
20
21
  attr_reader :data
21
22
  alias to_h data
22
23
 
@@ -25,7 +26,7 @@ module PacketGen
25
26
  end
26
27
 
27
28
  # Populate object from a string or directly from a hash.
28
- # @param [String, Hash] s_or_h
29
+ # @param [String, Hash{String=>String}] s_or_h
29
30
  # @return [self]
30
31
  def read(s_or_h)
31
32
  case s_or_h
@@ -69,14 +70,14 @@ module PacketGen
69
70
  d.join("\r\n") << "\r\n\r\n"
70
71
  end
71
72
 
72
- # Get a human readable string.
73
+ # Get a human readable hash.
73
74
  # @return [Hash]
74
75
  def to_human
75
76
  @data
76
77
  end
77
78
 
78
79
  # Read human-readable data to populate header data.
79
- # @param [String, Hash] data
80
+ # @param [Hash{String=>String}] data
80
81
  # @return [self]
81
82
  def from_human(data)
82
83
  read(data)
@@ -10,50 +10,57 @@ module PacketGen
10
10
  module Header
11
11
  module HTTP
12
12
  # An HTTP/1.1 Request packet consists of:
13
- # * the http verb ({Types::String}).
14
- # * the path ({Types::String}).
15
- # * the version ({Types::String}).
13
+ # * the http verb (+BinStruct::String+).
14
+ # * the path (+BinStruct::String+).
15
+ # * the version (+BinStruct::String+).
16
16
  # * associated http headers ({HTTP::Headers}).
17
+ # * and a {#body} (+BinStruct::String+).
17
18
  #
18
- # == Create a HTTP Request header
19
+ # Note: When creating a HTTP Request packet, {TCP#sport} and {TCP#dport}
20
+ # attributes are not set.
21
+ #
22
+ # @example Create a HTTP Request header
19
23
  # # standalone
20
- # http_rqst = PacketGen::Header::HTTP::Request.new
24
+ # http_request = PacketGen::Header::HTTP::Request.new
21
25
  # # in a packet
22
26
  # pkt = PacketGen.gen("IP").add("TCP").add("HTTP::Request")
23
27
  # # access to HTTP Request header
24
- # pkt.http_request # => PacketGen::Header::HTTP::Request
25
- #
26
- # Note: When creating a HTTP Request packet, +sport+ and +dport+
27
- # attributes of TCP header are not set.
28
+ # pkt.http_request.class # => PacketGen::Header::HTTP::Request
28
29
  #
29
- # == HTTP Request attributes
30
- # http_rqst.version = "HTTP/1.1"
31
- # http_rqst.verb = "GET"
32
- # http_rqst.path = "/meow.html"
33
- # http_rqst.headers = "Host: tcpdump.org" # string or
34
- # http_rqst.headers = { "Host": "tcpdump.org" } # even a hash
30
+ # @example HTTP Request attributes
31
+ # http_request = PacketGen::Header::HTTP::Request.new
32
+ # http_request.version #=> "HTTP/1.1"
33
+ # http_request.verb = "GET"
34
+ # http_request.path = "/meow.html"
35
+ # http_request.headers = "Host: tcpdump.org" # string or
36
+ # http_request.headers = { "Host": "tcpdump.org" } # even a hash
35
37
  #
36
38
  # @author Kent 'picat' Gruber
37
39
  # @author Sylvain Daubert
40
+ # @author LemonTree55
38
41
  # @since 3.1.0 Rename +#method+ into {#verb} to not mask +Object#method+.
39
42
  class Request < Base
40
43
  # @!attribute verb
41
- # @return [Types::String]
44
+ # HTTP verb (method)
45
+ # @return [BinStruct::String]
42
46
  # @since 3.1.0
43
- define_field :verb, Types::String
47
+ define_attr :verb, BinStruct::String
44
48
  # @!attribute path
45
- # @return [Types::String]
46
- define_field :path, Types::String
49
+ # Requested path
50
+ # @return [BinStruct::String]
51
+ define_attr :path, BinStruct::String
47
52
  # @!attribute version
48
- # @return [Types::String]
49
- define_field :version, Types::String, default: 'HTTP/1.1'
53
+ # HTTP version
54
+ # @return [BinStruct::String]
55
+ define_attr :version, BinStruct::String, default: 'HTTP/1.1'
50
56
  # @!attribute headers
51
57
  # associated http/1.1 headers
52
58
  # @return [HTTP::Headers]
53
- define_field :headers, HTTP::Headers
59
+ define_attr :headers, HTTP::Headers
54
60
  # @!attribute body
55
- # @return [Types::String]
56
- define_field :body, Types::String
61
+ # HTTP request body, if any
62
+ # @return [BinStruct::String]
63
+ define_attr :body, BinStruct::String
57
64
 
58
65
  # @param [Hash] options
59
66
  # @option options [String] :verb
@@ -61,18 +68,18 @@ module PacketGen
61
68
  # @option options [String] :version
62
69
  # @option options [Hash] :headers
63
70
  def initialize(options={})
64
- super(options)
71
+ super
65
72
  self.headers ||= options[:headers]
66
73
  end
67
74
 
68
75
  # Read in the HTTP portion of the packet, and parse it.
69
- # @return [PacketGen::HTTP::Request]
76
+ # @return [self]
70
77
  def read(str)
71
78
  lines = lines(str)
72
79
  first_line_words = lines.shift.split
73
- self[:verb].read first_line_words[0]
74
- self[:path].read first_line_words[1]
75
- self[:version].read first_line_words[2]
80
+ self[:verb].read(first_line_words[0])
81
+ self[:path].read(first_line_words[1])
82
+ self[:version].read(first_line_words[2])
76
83
 
77
84
  # requests can sometimes have a payload
78
85
  headers, data = headers_and_payload_from_lines(lines)
@@ -82,6 +89,8 @@ module PacketGen
82
89
  self
83
90
  end
84
91
 
92
+ # May be parsed as a HTTP request if verb is known, and if version is +HTTP/1.x+.
93
+ # @return [Boolean]
85
94
  def parse?
86
95
  VERBS.include?(self.verb) && self.version.start_with?('HTTP/1.')
87
96
  end