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
@@ -11,23 +11,27 @@ module PacketGen
11
11
  class IP
12
12
  # Class to handle series of IP addresses
13
13
  # @author Sylvain Daubert
14
- class ArrayOfAddr < Types::Array
14
+ class ArrayOfAddr < BinStruct::Array
15
15
  set_of IP::Addr
16
16
 
17
17
  # Push a IP address to the array
18
18
  # @param [String,Addr] addr
19
19
  # @return [self]
20
+ # @example
21
+ # array = PacketGen::Header::IP::ArrayOfAddr.new
22
+ # # #<< uses #push internally
20
23
  # array << '192.168.1.12'
24
+ # array.push(PacketGen::Header::IP::Addr.new.from_human('192.18.1.13'))
21
25
  def push(addr)
22
26
  addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
23
- super(addr)
27
+ super
24
28
  end
25
29
  end
26
30
 
27
31
  # Base class for IP options
28
32
  # @author Sylvain Daubert
29
- class Option < Types::Fields
30
- include Types::Fieldable
33
+ class Option < BinStruct::Struct
34
+ include BinStruct::Structable
31
35
 
32
36
  # EOL option type
33
37
  EOL_TYPE = 0x00
@@ -46,21 +50,10 @@ module PacketGen
46
50
 
47
51
  # @!attribute type
48
52
  # 8-bit option type
49
- # @return [Integer]
50
- define_field :type, Types::Int8
51
- # @!attribute length
52
- # 8-bit option length. If 0, there is no +length+ field in option
53
- # @return [Integer]
54
- define_field :length, Types::Int8, default: 0, optional: ->(h) { h.type > 1 }
55
- # @!attribute data
56
- # option data
57
- # @return [String]
58
- define_field :data, Types::String, optional: ->(h) { h.length > 2 },
59
- builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
60
-
53
+ # @return [Integer]
61
54
  # @!attribute copied
62
55
  # 1-bit copied flag from {#type} field
63
- # @return [Boolean]
56
+ # @return [Integer]
64
57
  # @!attribute option_class
65
58
  # 2-bit option class (0: control, 2: debug and measurement, 1 and 3:
66
59
  # reserved) from {#type} field
@@ -68,15 +61,26 @@ module PacketGen
68
61
  # !@attribute number
69
62
  # 5-bit option number from {#type} field
70
63
  # @return [Integer]
71
- define_bit_fields_on :type, :copied, :option_class, 2, :number, 5
64
+ define_bit_attr :type, copied: 1, option_class: 2, number: 5
65
+ # @!attribute length
66
+ # 8-bit option length. If 0, there is no +length+ field in option
67
+ # @return [Integer]
68
+ define_attr :length, BinStruct::Int8, default: 0, optional: ->(h) { h.type > 1 }
69
+ # @!attribute data
70
+ # option data
71
+ # @return [String]
72
+ define_attr :data, BinStruct::String, optional: ->(h) { h.length > 2 },
73
+ builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
72
74
 
73
- # @return [Hash]
75
+ # @private
76
+ # Return a cached hash associating type name to its value.
77
+ # @return [Hash{String => Integer}]
74
78
  def self.types
75
79
  return @types if defined? @types
76
80
 
77
81
  @types = {}
78
82
  Option.constants.each do |cst|
79
- next unless cst.to_s.end_with? '_TYPE'
83
+ next unless cst.to_s.end_with?('_TYPE')
80
84
 
81
85
  optname = cst.to_s.sub('_TYPE', '')
82
86
  @types[optname] = Option.const_get(cst)
@@ -85,6 +89,7 @@ module PacketGen
85
89
  end
86
90
 
87
91
  # Factory to build an option from its type
92
+ # @param [Hash] options
88
93
  # @return [Option]
89
94
  def self.build(options={})
90
95
  type = options[:type]
@@ -98,6 +103,8 @@ module PacketGen
98
103
  klass.new(options)
99
104
  end
100
105
 
106
+ # Force type value for subclasses, if not specified
107
+ # @return [Option]
101
108
  def initialize(options={})
102
109
  options[:type] = class2type unless options[:type]
103
110
 
@@ -109,14 +116,14 @@ module PacketGen
109
116
  # Get binary string. Set {#length} field.
110
117
  # @return [String]
111
118
  def to_s
112
- self.length = super.size if respond_to? :length
119
+ self.length = super.size if respond_to?(:length)
113
120
  super
114
121
  end
115
122
 
116
123
  # Get a human readable string
117
124
  # @return [String]
118
125
  def to_human
119
- str = self.instance_of?(Option) ? +"unk-#{type}" : self.class.to_s.sub(/.*::/, '')
126
+ str = self.instance_of?(Option) ? "unk-#{type}" : self.class.to_s.sub(/.*::/, '')
120
127
  str << ":#{self[:data].to_s.inspect}" if respond_to?(:length) && (length > 2) && !self[:data].to_s.empty?
121
128
  str
122
129
  end
@@ -124,8 +131,8 @@ module PacketGen
124
131
  private
125
132
 
126
133
  def class2type
127
- opt_name = self.class.to_s.gsub(/.*::/, '')
128
- Option.const_get(:"#{opt_name}_TYPE") if Option.const_defined? :"#{opt_name}_TYPE"
134
+ opt_sym = :"#{self.class.to_s.gsub(/.*::/, '')}_TYPE"
135
+ Option.const_get(opt_sym) if Option.const_defined?(opt_sym)
129
136
  end
130
137
 
131
138
  def initialize_length_if_needed(options)
@@ -133,7 +140,7 @@ module PacketGen
133
140
  end
134
141
 
135
142
  def initialize_data_if_needed(options)
136
- return unless fields.include?(:data) && self[:data].respond_to?(:from_human) && options.key?(:data)
143
+ return unless attributes.include?(:data) && self[:data].respond_to?(:from_human) && options.key?(:data)
137
144
 
138
145
  # Force data if data is set in options but not length
139
146
  self.length += options[:data].size
@@ -143,8 +150,8 @@ module PacketGen
143
150
 
144
151
  # End-of-option-List IP option
145
152
  class EOL < Option
146
- remove_field :length
147
- remove_field :data
153
+ remove_attr :length
154
+ remove_attr :data
148
155
  end
149
156
 
150
157
  # No OPeration IP option
@@ -152,16 +159,16 @@ module PacketGen
152
159
 
153
160
  # Loose Source and Record Route IP option
154
161
  class LSRR < Option
155
- remove_field :data
162
+ remove_attr :data
156
163
 
157
164
  # @!attribute pointer
158
- # 8-bit pointer on next address
165
+ # 8-bit po+++inter on next address
159
166
  # @return [Integer]
160
- define_field :pointer, Types::Int8, default: 4
167
+ define_attr :pointer, BinStruct::Int8, default: 4
161
168
  # @!attribute data
162
169
  # Array of IP addresses
163
- # @return [Types::Array<IP::Addr>]
164
- define_field :data, ArrayOfAddr, builder: ->(h, t) { t.new(length_from: -> { h.length - 3 }) }
170
+ # @return [BinStruct::Array<IP::Addr>]
171
+ define_attr :data, ArrayOfAddr, builder: ->(h, t) { t.new(length_from: -> { h.length - 3 }) }
165
172
 
166
173
  # Get IP address pointer by {#pointer}
167
174
  # @return [Addr]
@@ -185,13 +192,15 @@ module PacketGen
185
192
 
186
193
  # Stream Identifier IP option
187
194
  class SI < Option
188
- remove_field :data
195
+ remove_attr :data
189
196
 
190
197
  # @!attribute id
191
198
  # 16-bit stream ID
192
199
  # @return [Integer]
193
- define_field :id, Types::Int16
200
+ define_attr :id, BinStruct::Int16
194
201
 
202
+ # Return a human-readable string
203
+ # @return [String]
195
204
  def to_human
196
205
  super << ":#{self.id}"
197
206
  end
@@ -199,13 +208,15 @@ module PacketGen
199
208
 
200
209
  # Router Alert IP option
201
210
  class RA < Option
202
- remove_field :data
211
+ remove_attr :data
203
212
 
204
213
  # @!attribute value
205
214
  # 16-bit value. Should be 0.
206
215
  # @return [Integer]
207
- define_field :value, Types::Int16, default: 0
216
+ define_attr :value, BinStruct::Int16, default: 0
208
217
 
218
+ # Return a human-readable string
219
+ # @return [String]
209
220
  def to_human
210
221
  super << ":#{self.value}"
211
222
  end
@@ -11,7 +11,7 @@ module PacketGen
11
11
  class IP
12
12
  # Class to handle IP options
13
13
  # @author Sylvain Daubert
14
- class Options < Types::Array
14
+ class Options < BinStruct::Array
15
15
  set_of Option
16
16
 
17
17
  HUMAN_SEPARATOR = ';'
@@ -27,32 +27,33 @@ module PacketGen
27
27
  # | Options | Padding |
28
28
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29
29
  # A IP header consists of:
30
- # * a first byte ({#u8} of {Types::Int8} type) composed of:
30
+ # * a first byte ({#u8} of +BinStruct::Int8+ type) composed of:
31
31
  # * a 4-bit {#version} field,
32
32
  # * a 4-bit IP header length ({#ihl}) field,
33
- # * a Type of Service field ({#tos}, {Types::Int8} type),
34
- # * a total length ({#length}, {Types::Int16} type),
35
- # * a ID ({#id}, +Int16+ type),
36
- # * a {#frag} worg (+Int16+) composed of:
33
+ # * a Type of Service field ({#tos}, +BinStruct::Int8+ type),
34
+ # * a total length ({#length}, +BinStruct::Int16+ type),
35
+ # * a ID ({#id}, +BinStruct::Int16+ type),
36
+ # * a {#frag} worg (+BinStruct::Int16+) composed of:
37
37
  # * 3 1-bit flags ({#flag_rsv}, {#flag_df} and {#flag_mf}),
38
38
  # * a 13-bit {#fragment_offset} field,
39
39
  # * a Time-to-Live ({#ttl}) field (+Int8+),
40
- # * a {#protocol} field (+Int8+),
41
- # * a {#checksum} field (+Int16+),
40
+ # * a {#protocol} field (+BinStruct::Int8+),
41
+ # * a {#checksum} field (+BinStruct::Int16+),
42
42
  # * a source IP address ({#src}, {Addr} type),
43
- # * a destination IP address ({#dst}, +Addr+ type),
43
+ # * a destination IP address ({#dst}, {Addr} type),
44
44
  # * an optional {#options} field ({Options} type),
45
- # * and a {#body} ({Types::String} type).
45
+ # * and a {#body} (+BinStruct::String+ type).
46
46
  #
47
- # == Create a IP header
47
+ # @example Create a IP header
48
48
  # # standalone
49
49
  # ip = PacketGen::Header::IP.new
50
50
  # # in a packet
51
51
  # pkt = PacketGen.gen('IP')
52
52
  # # access to IP header
53
- # pkt.ip # => PacketGen::Header::IP
53
+ # pkt.ip.class # => PacketGen::Header::IP
54
54
  #
55
- # == IP attributes
55
+ # @example IP attributes
56
+ # ip = PacketGen::Header::IP.new
56
57
  # ip.u8 = 0x45
57
58
  # # the same as
58
59
  # ip.version = 4
@@ -66,21 +67,20 @@ module PacketGen
66
67
  # ip.flag_mf = true
67
68
  # ip.fragment_offset = 0x31
68
69
  #
69
- # ip.flag_rsv? # => Boolean
70
- # ip.flag_df? # => Boolean
71
- # ip.flag_mf? # => Boolean
70
+ # ip.flag_rsv? # => false
71
+ # ip.flag_df? # => false
72
+ # ip.flag_mf? # => true
72
73
  #
73
74
  # ip.ttl = 0x40
74
75
  # ip.protocol = 6
75
76
  # ip.checksum = 0xffff
76
77
  # ip.src = '127.0.0.1'
77
78
  # ip.src # => "127.0.0.1"
78
- # ip[:src] # => PacketGen::Header::IP::Addr
79
+ # ip[:src].class # => PacketGen::Header::IP::Addr
79
80
  # ip.dst = '127.0.0.2'
80
- # ip.body.read 'this is a body'
81
+ # ip.body = 'this is a body'
81
82
  #
82
- # == Add IP options
83
- # IP has an {#options} attribute used to store datagram options.
83
+ # @example Add IP options
84
84
  # pkt = PacketGen.gen('IP')
85
85
  # # add option from class
86
86
  # pkt.ip.options << PacketGen::Header::IP::RA.new
@@ -100,58 +100,70 @@ module PacketGen
100
100
  # @!attribute u8
101
101
  # First byte of IP header. May be accessed through {#version} and {#ihl}.
102
102
  # @return [Integer] first byte of IP header.
103
- define_field :u8, Types::Int8, default: 0x45
103
+ # @!attribute version
104
+ # 4-bit version attribute
105
+ # @return [Integer]
106
+ # @!attribute ihl
107
+ # 4-bit IP header length attribute, as 32-bit word count.
108
+ # Default to 5 (IP header without option).
109
+ # @return [Integer]
110
+ define_bit_attr :u8, default: 0x45, version: 4, ihl: 4
104
111
  # @!attribute tos
105
112
  # @return [Integer] 8-bit Type of Service self[attr]
106
- define_field :tos, Types::Int8, default: 0
113
+ define_attr :tos, BinStruct::Int8, default: 0
107
114
  # @!attribute length
108
- # @return [Integer] 16-bit IP total length
109
- define_field :length, Types::Int16, default: 20
115
+ # 16-bit IP total length, including this header.
116
+ # @return [Integer]
117
+ define_attr :length, BinStruct::Int16, default: 20
110
118
  # @!attribute id
111
119
  # @return [Integer] 16-bit ID
112
- define_field :id, Types::Int16, default: ->(_) { rand(65_535) }
120
+ define_attr :id, BinStruct::Int16, default: ->(_) { rand(65_535) }
113
121
  # @!attribute frag
114
- # @return [Integer] 16-bit frag word
115
- define_field :frag, Types::Int16, default: 0
122
+ # 16-bit frag word
123
+ # @return [Integer]
124
+ # @!attribute flag_rsv
125
+ # reserved bit from flags
126
+ # @return [Boolean]
127
+ # @!attribute flag_df
128
+ # Don't Fragment flag
129
+ # @return [Boolean]
130
+ # @!attribute flag_mf
131
+ # More Fragment flags
132
+ # @return [Boolean]
133
+ # @!attribute fragment_offset
134
+ # 13-bit fragment offset
135
+ # @return [Integer]
136
+ define_bit_attr :frag, flag_rsv: 1, flag_df: 1, flag_mf: 1, fragment_offset: 13
116
137
  # @!attribute ttl
117
- # @return [Integer] 8-bit Time To Live self[attr]
118
- define_field :ttl, Types::Int8, default: 64
138
+ # 8-bit Time To Live
139
+ # @return [Integer]
140
+ define_attr :ttl, BinStruct::Int8, default: 64
119
141
  # @!attribute protocol
120
- # @return [Integer] 8-bit upper protocol self[attr]
121
- define_field :protocol, Types::Int8
142
+ # 8-bit upper protocol
143
+ # @return [Integer]
144
+ define_attr :protocol, BinStruct::Int8
122
145
  # @!attribute checksum
123
- # @return [Integer] 16-bit IP header checksum
124
- define_field :checksum, Types::Int16, default: 0
146
+ # 16-bit IP header checksum
147
+ # @return [Integer]
148
+ define_attr :checksum, BinStruct::Int16, default: 0
125
149
  # @!attribute src
126
- # @return [Addr] source IP address
127
- define_field :src, Addr, default: '127.0.0.1'
150
+ # source IP address
151
+ # @return [Addr]
152
+ define_attr :src, Addr, default: '127.0.0.1'
128
153
  # @!attribute dst
129
- # @return [Addr] destination IP address
130
- define_field :dst, Addr, default: '127.0.0.1'
154
+ # destination IP address
155
+ # @return [Addr]
156
+ define_attr :dst, Addr, default: '127.0.0.1'
131
157
  # @!attribute options
158
+ # IP options
132
159
  # @since 2.2.0
133
- # @return [Types::String]
134
- define_field :options, Options, optional: ->(h) { h.ihl > 5 },
135
- builder: ->(h, t) { t.new(length_from: -> { (h.ihl - 5) * 4 }) }
160
+ # @return [Options]
161
+ define_attr :options, Options, optional: ->(h) { h.ihl > 5 },
162
+ builder: ->(h, t) { t.new(length_from: -> { (h.ihl - 5) * 4 }) }
136
163
  # @!attribute body
137
- # @return [Types::String,Header::Base]
138
- define_field :body, Types::String
139
-
140
- # @!attribute version
141
- # @return [Integer] 4-bit version attribute
142
- # @!attribute ihl
143
- # @return [Integer] 4-bit IP header length attribute
144
- define_bit_fields_on :u8, :version, 4, :ihl, 4
145
-
146
- # @!attribute flag_rsv
147
- # @return [Boolean] reserved bit from flags
148
- # @!attribute flag_df
149
- # @return [Boolean] Don't Fragment flag
150
- # @!attribute flag_mf
151
- # @return [Boolean] More Fragment flags
152
- # @!attribute fragment_offset
153
- # @return [Integer] 13-bit fragment offset
154
- define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13
164
+ # IP body
165
+ # @return [BinStruct::String,Headerable]
166
+ define_attr :body, BinStruct::String
155
167
 
156
168
  # Helper method to compute sum of 16-bit words. Used to compute IP-style
157
169
  # checksums.
@@ -160,7 +172,7 @@ module PacketGen
160
172
  # @return [Integer]
161
173
  def self.sum16(hdr)
162
174
  old_checksum = nil
163
- if hdr.respond_to? :checksum=
175
+ if hdr.respond_to?(:checksum)
164
176
  old_checksum = hdr.checksum
165
177
  hdr.checksum = 0
166
178
  end
@@ -178,8 +190,8 @@ module PacketGen
178
190
  # This method:
179
191
  # * checks a checksum is not greater than 0xffff. If it is,
180
192
  # reduces it.
181
- # * inverts reduced self[attr].
182
- # * forces self[attr] to 0xffff if computed self[attr] is 0.
193
+ # * inverts reduced checksum.
194
+ # * forces checksum to 0xffff if computed checksum is 0.
183
195
  # @param [Integer] checksum checksum to reduce
184
196
  # @return [Integer] reduced checksum
185
197
  def self.reduce_checksum(checksum)
@@ -203,7 +215,7 @@ module PacketGen
203
215
  # @return [Integer]
204
216
  # @since 3.0.0 add +ihl+ calculation
205
217
  def calc_length
206
- Base.calculate_and_set_length self
218
+ Base.calculate_and_set_length(self)
207
219
  self.ihl = 5 + self[:options].sz / 4
208
220
  end
209
221
 
@@ -216,31 +228,20 @@ module PacketGen
216
228
 
217
229
  # Send IP packet on wire.
218
230
  #
219
- # When sending packet at IP level, +checksum+ and +length+ fields are set by
231
+ # When sending packet at IP level, +checksum+ and +length+ attributes are set by
220
232
  # kernel, so bad IP packets cannot be sent this way. To do so, use {Eth#to_w}.
221
233
  # @param [String,nil] _iface interface name. Not used
222
234
  # @return [void]
223
235
  def to_w(_iface=nil)
224
236
  sock = Socket.new(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
225
237
  sockaddrin = Socket.sockaddr_in(0, dst)
226
- sock.send to_s, 0, sockaddrin
238
+ sock.send(to_s, 0, sockaddrin)
227
239
  sock.close
228
240
  end
229
241
 
230
- # @return [String]
231
- def inspect
232
- super do |attr|
233
- case attr
234
- when :u8
235
- inspect_u8
236
- when :frag
237
- inspect_frag
238
- end
239
- end
240
- end
241
-
242
242
  # Check version field
243
- # @see [Base#parse?]
243
+ # @see Base#parse?
244
+ # @return [Boolean]
244
245
  def parse?
245
246
  (version == 4) && (ihl >= 5)
246
247
  end
@@ -259,25 +260,6 @@ module PacketGen
259
260
  self[:src], self[:dst] = self[:dst], self[:src]
260
261
  self
261
262
  end
262
-
263
- private
264
-
265
- def inspect_u8
266
- shift = Inspect.shift_level
267
- str = Inspect.inspect_attribute(:u8, self[:u8])
268
- str << shift << Inspect::FMT_ATTR % ['', 'version', version]
269
- str << shift << Inspect::FMT_ATTR % ['', 'ihl', ihl]
270
- end
271
-
272
- def inspect_frag
273
- shift = Inspect.shift_level
274
- str = Inspect.inspect_attribute(:frag, self[:frag])
275
- flags = %i[rsv df mf].select { |flag| send(:"flag_#{flag}?") }.map(&:upcase)
276
- flags_str = flags.empty? ? 'none' : flags.join(',')
277
- str << shift << Inspect::FMT_ATTR % ['', 'flags', flags_str]
278
- foff = Inspect.int_dec_hex(fragment_offset, 4)
279
- str << shift << Inspect::FMT_ATTR % ['', 'frag_offset', foff]
280
- end
281
263
  end
282
264
 
283
265
  self.add_class IP
@@ -14,47 +14,47 @@ module PacketGen
14
14
  class IPv6
15
15
  # IPv6 address, as a group of 8 2-byte words
16
16
  # @author Sylvain Daubert
17
- class Addr < Types::Fields
18
- include Types::Fieldable
17
+ # @author LemonTree55
18
+ class Addr < BinStruct::Struct
19
+ include BinStruct::Structable
19
20
 
20
21
  # @!attribute a1
21
22
  # 1st 2-byte word of IPv6 address
22
23
  # @return [Integer]
23
- define_field :a1, Types::Int16
24
+ define_attr :a1, BinStruct::Int16
24
25
  # @!attribute a2
25
26
  # 2nd 2-byte word of IPv6 address
26
27
  # @return [Integer]
27
- define_field :a2, Types::Int16
28
+ define_attr :a2, BinStruct::Int16
28
29
  # @!attribute a3
29
30
  # 3rd 2-byte word of IPv6 address
30
31
  # @return [Integer]
31
- define_field :a3, Types::Int16
32
+ define_attr :a3, BinStruct::Int16
32
33
  # @!attribute a4
33
34
  # 4th 2-byte word of IPv6 address
34
35
  # @return [Integer]
35
- define_field :a4, Types::Int16
36
+ define_attr :a4, BinStruct::Int16
36
37
  # @!attribute a5
37
38
  # 5th 2-byte word of IPv6 address
38
39
  # @return [Integer]
39
- define_field :a5, Types::Int16
40
+ define_attr :a5, BinStruct::Int16
40
41
  # @!attribute a6
41
42
  # 6th 2-byte word of IPv6 address
42
43
  # @return [Integer]
43
- define_field :a6, Types::Int16
44
+ define_attr :a6, BinStruct::Int16
44
45
  # @!attribute a7
45
46
  # 7th 2-byte word of IPv6 address
46
47
  # @return [Integer]
47
- define_field :a7, Types::Int16
48
+ define_attr :a7, BinStruct::Int16
48
49
  # @!attribute a8
49
50
  # 8th 2-byte word of IPv6 address
50
51
  # @return [Integer]
51
- define_field :a8, Types::Int16
52
-
53
- # rubocop:disable Metrics/AbcSize
52
+ define_attr :a8, BinStruct::Int16
54
53
 
55
54
  # Read a colon-delimited address
56
55
  # @param [String] str
57
56
  # @return [self]
57
+ # @raise [ArgumentError] not a colon-delimited IPv6 address
58
58
  def from_human(str)
59
59
  return self if str.nil?
60
60
 
@@ -62,19 +62,13 @@ module PacketGen
62
62
  raise ArgumentError, 'string is not a IPv6 address' unless addr.ipv6?
63
63
 
64
64
  addri = addr.to_i
65
- self.a1 = addri >> 112
66
- self.a2 = addri >> 96 & 0xffff
67
- self.a3 = addri >> 80 & 0xffff
68
- self.a4 = addri >> 64 & 0xffff
69
- self.a5 = addri >> 48 & 0xffff
70
- self.a6 = addri >> 32 & 0xffff
71
- self.a7 = addri >> 16 & 0xffff
72
- self.a8 = addri & 0xffff
65
+ 8.times do |i|
66
+ self.send(:"a#{i + 1}=", addri >> (16 * (7 - i)) & 0xffff)
67
+ end
73
68
  self
74
69
  end
75
- # rubocop:enable Metrics/AbcSize
76
70
 
77
- # Addr6 in human readable form (colon-delimited hex string)
71
+ # Return IPv6 address in human readable form (colon-delimited hex string)
78
72
  # @return [String]
79
73
  def to_human
80
74
  IPAddr.new(to_a.map { |a| a.to_i.to_s(16) }.join(':')).to_s
@@ -83,7 +77,7 @@ module PacketGen
83
77
  # Return an array of address 16-bit words
84
78
  # @return [Array<Integer>]
85
79
  def to_a
86
- @fields.values
80
+ @attributes.values
87
81
  end
88
82
 
89
83
  # Return true if this address is a multicast one
@@ -92,24 +86,31 @@ module PacketGen
92
86
  self.a1 & 0xff00 == 0xff00
93
87
  end
94
88
 
89
+ # Check equaliy to +other+.
90
+ # Equal if other has the same class, and all attributes are equal
91
+ # @return [Boolean]
95
92
  def ==(other)
96
93
  other.is_a?(self.class) &&
97
- fields.all? { |attr| self[attr].value == other[attr].value }
94
+ attributes.all? { |attr| self[attr].value == other[attr].value }
98
95
  end
99
96
  end
100
97
 
101
98
  # Class to handle series of IPv6 addresses
102
99
  # @author Sylvain Daubert
103
- class ArrayOfAddr < Types::Array
100
+ class ArrayOfAddr < BinStruct::Array
104
101
  set_of IPv6::Addr
105
102
 
106
103
  # Push a IPv6 address to the array
107
104
  # @param [String,Addr] addr
108
105
  # @return [self]
109
- # array << '2001:1234::125'
106
+ # @example
107
+ # array = PacketGen::Header::IPv6::ArrayOfAddr.new
108
+ # # #<< uses #push internally
109
+ # array << '2001::1'
110
+ # array.push(PacketGen::Header::IPv6::Addr.new.from_human('1:2:3:abcd::1'))
110
111
  def push(addr)
111
112
  addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
112
- super(addr)
113
+ super
113
114
  end
114
115
  end
115
116
  end
@@ -9,7 +9,7 @@
9
9
  module PacketGen
10
10
  module Header
11
11
  class IPv6
12
- # Base class to handle IPv6 extensions
12
+ # Base class to handle IPv6 extensions.
13
13
  # @abstract You should not use this class but its subclasses.
14
14
  # A IPv6 extension header has the following format:
15
15
  # 0 1 2 3
@@ -25,29 +25,31 @@ module PacketGen
25
25
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26
26
  #
27
27
  # Such a header consists of:
28
- # * a {#next} header field ({Types::Int8}),
29
- # * a {#length} field ({Types::Int8}),
30
- # * an {#options} field ({Types::String}),
28
+ # * a {#next} header field (+BinStruct::Int8+),
29
+ # * a {#length} field (+BinStruct::Int8+),
30
+ # * an {#options} field (+BinStruct::String+),
31
31
  # * and a {#body}, containing next header.
32
32
  # @author Sylvain Daubert
33
+ # @since 2.4.0
33
34
  class Extension < Base
34
35
  # @!attribute next
35
36
  # 8-bit Next header field
36
37
  # @return [Integer]
37
- define_field :next, Types::Int8
38
+ define_attr :next, BinStruct::Int8
38
39
  # @!attribute length
39
40
  # 8-bit extension length, in 8-octets units, not including the
40
41
  # first 8 octets.
41
42
  # @return [Integer]
42
- define_field :length, Types::Int8
43
+ define_attr :length, BinStruct::Int8
43
44
  # @!attribute options
44
45
  # Specific options of extension header
45
46
  # @return [String]
46
- define_field :options, Types::String,
47
- builder: ->(h, t) { t.new(length_from: -> { h.real_length }) }
47
+ define_attr :options, BinStruct::String,
48
+ builder: ->(h, t) { t.new(length_from: -> { h.real_length - 2}) }
48
49
  # @!attribute body
49
- # @return [String,Base]
50
- define_field :body, Types::String
50
+ # Next header in IPv6 packet
51
+ # @return [String,Headerable]
52
+ define_attr :body, BinStruct::String
51
53
 
52
54
  # Get real extension header length
53
55
  # @return [Integer]
@@ -55,7 +57,7 @@ module PacketGen
55
57
  (length + 1) * 8
56
58
  end
57
59
 
58
- # Compute length and set +len+ field
60
+ # Compute length and set {#length}+ attribute
59
61
  # @return [Integer]
60
62
  def calc_length
61
63
  self.length = (options.sz + 2) / 8 - 1