packetgen 1.2.0 → 1.3.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/packetgen/header/arp.rb +54 -125
  4. data/lib/packetgen/header/base.rb +175 -0
  5. data/lib/packetgen/header/dns/name.rb +110 -0
  6. data/lib/packetgen/header/dns/opt.rb +137 -0
  7. data/lib/packetgen/header/dns/option.rb +17 -0
  8. data/lib/packetgen/header/dns/qdsection.rb +39 -0
  9. data/lib/packetgen/header/dns/question.rb +129 -0
  10. data/lib/packetgen/header/dns/rr.rb +89 -0
  11. data/lib/packetgen/header/dns/rrsection.rb +72 -0
  12. data/lib/packetgen/header/dns.rb +276 -0
  13. data/lib/packetgen/header/esp.rb +38 -70
  14. data/lib/packetgen/header/eth.rb +35 -106
  15. data/lib/packetgen/header/icmp.rb +19 -70
  16. data/lib/packetgen/header/icmpv6.rb +3 -3
  17. data/lib/packetgen/header/ip.rb +54 -210
  18. data/lib/packetgen/header/ipv6.rb +73 -164
  19. data/lib/packetgen/header/tcp/option.rb +34 -50
  20. data/lib/packetgen/header/tcp/options.rb +19 -20
  21. data/lib/packetgen/header/tcp.rb +66 -129
  22. data/lib/packetgen/header/udp.rb +31 -88
  23. data/lib/packetgen/header.rb +5 -10
  24. data/lib/packetgen/inspect.rb +5 -4
  25. data/lib/packetgen/packet.rb +74 -57
  26. data/lib/packetgen/pcapng/block.rb +49 -7
  27. data/lib/packetgen/pcapng/epb.rb +36 -34
  28. data/lib/packetgen/pcapng/file.rb +24 -8
  29. data/lib/packetgen/pcapng/idb.rb +28 -33
  30. data/lib/packetgen/pcapng/shb.rb +35 -39
  31. data/lib/packetgen/pcapng/spb.rb +18 -27
  32. data/lib/packetgen/pcapng/unknown_block.rb +11 -21
  33. data/lib/packetgen/pcapng.rb +9 -7
  34. data/lib/packetgen/types/array.rb +56 -0
  35. data/lib/packetgen/types/fields.rb +325 -0
  36. data/lib/packetgen/types/int.rb +164 -0
  37. data/lib/packetgen/types/int_string.rb +69 -0
  38. data/lib/packetgen/types/string.rb +36 -0
  39. data/lib/packetgen/types/tlv.rb +41 -0
  40. data/lib/packetgen/types.rb +13 -0
  41. data/lib/packetgen/version.rb +1 -1
  42. data/lib/packetgen.rb +1 -1
  43. metadata +19 -6
  44. data/lib/packetgen/header/header_class_methods.rb +0 -106
  45. data/lib/packetgen/header/header_methods.rb +0 -73
  46. data/lib/packetgen/structfu.rb +0 -363
@@ -8,10 +8,10 @@ module PacketGen
8
8
  module Header
9
9
 
10
10
  # A IP header consists of:
11
- # * a first byte ({#u8} of {Int8} type) composed of:
11
+ # * a first byte ({#u8} of {Types::Int8} type) composed of:
12
12
  # * a 4-bit {#version} field,
13
13
  # * a 4-bit IP header length ({#ihl}) field,
14
- # * a total length ({#length}, {Int16} type),
14
+ # * a total length ({#length}, {Types::Int16} type),
15
15
  # * a ID ({#id}, +Int16+ type),
16
16
  # * a {#frag} worg (+Int16+) composed of:
17
17
  # * 3 1-bit flags ({#flag_rsv}, {#flag_df} and {#flag_mf}),
@@ -21,7 +21,7 @@ module PacketGen
21
21
  # * a {#checksum} field (+Int16+),
22
22
  # * a source IP address ({#src}, {Addr} type),
23
23
  # * a destination IP ddress ({#dst}, +Addr+ type),
24
- # * and a {#body} ({String} type).
24
+ # * and a {#body} ({Types::String} type).
25
25
  #
26
26
  # == Create a IP header
27
27
  # # standalone
@@ -58,32 +58,26 @@ module PacketGen
58
58
  # ip.dst = '127.0.0.2'
59
59
  # ip.body.read 'this is a body'
60
60
  # @author Sylvain Daubert
61
- class IP < Struct.new(:u8, :tos, :length, :id, :frag, :ttl,
62
- :protocol, :checksum, :src, :dst, :body)
63
- include StructFu
64
- include HeaderMethods
65
- extend HeaderClassMethods
61
+ class IP < Base
66
62
 
67
63
  # IP address, as a group of 4 bytes
68
64
  # @author Sylvain Daubert
69
- class Addr < Struct.new(:a1, :a2, :a3, :a4)
70
- include StructFu
65
+ class Addr < Base
66
+ # @!attribute a1
67
+ # @return [Integer] IP address first byte
68
+ define_field :a1, Types::Int8
69
+ # @!attribute a2
70
+ # @return [Integer] IP address seconf byte
71
+ define_field :a2, Types::Int8
72
+ # @!attribute a3
73
+ # @return [Integer] IP address third byte
74
+ define_field :a3, Types::Int8
75
+ # @!attribute a4
76
+ # @return [Integer] IP address fourth byte
77
+ define_field :a4, Types::Int8
71
78
 
72
79
  IPV4_ADDR_REGEX = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
73
80
 
74
- # @param [Hash] options
75
- # @option options [Integer] :a1
76
- # @option options [Integer] :a2
77
- # @option options [Integer] :a3
78
- # @option options [Integer] :a4
79
- def initialize(options={})
80
- super Int8.new(options[:a1]),
81
- Int8.new(options[:a2]),
82
- Int8.new(options[:a3]),
83
- Int8.new(options[:a4])
84
-
85
- end
86
-
87
81
  # Read a dotted address
88
82
  # @param [String] str
89
83
  # @return [self]
@@ -99,27 +93,10 @@ module PacketGen
99
93
  self
100
94
  end
101
95
 
102
- # Read a Addr from a string
103
- # @param [String] str binary string
104
- # @return [self]
105
- def read(str)
106
- return self if str.nil?
107
- raise ParseError, 'string too short for IP::Addr' if str.size < self.sz
108
- force_binary str
109
- [:a1, :a2, :a3, :a4].each_with_index do |byte, i|
110
- self[byte].read str[i, 1]
111
- end
112
- end
113
-
114
- [:a1, :a2, :a3, :a4].each do |sym|
115
- class_eval "def #{sym}; self[:#{sym}].to_i; end\n" \
116
- "def #{sym}=(v); self[:#{sym}].read v; end"
117
- end
118
-
119
96
  # Addr in human readable form (dotted format)
120
97
  # @return [String]
121
98
  def to_human
122
- members.map { |m| "#{self[m].to_i}" }.join('.')
99
+ fields.map { |f| "#{self[f].to_i}" }.join('.')
123
100
  end
124
101
 
125
102
  # Addr as an integer
@@ -130,32 +107,41 @@ module PacketGen
130
107
  end
131
108
  end
132
109
 
133
- # @param [Hash] options
134
- # @option options [Integer] :version
135
- # @option options [Integer] :ihl this header size in 4-byte words
136
- # @option options [Integer] :tos
137
- # @option options [Integer] :length IP packet length, including this header
138
- # @option options [Integer] :id
139
- # @option options [Integer] :frag
140
- # @option options [Integer] :ttl
141
- # @option options [Integer] :protocol
142
- # @option options [Integer] :checksum IP header checksum
143
- # @option options [String] :src IP source dotted address
144
- # @option options [String] :dst IP destination dotted address
145
- def initialize(options={})
146
- super Int8.new(((options[:version] || 4) << 4) | (options[:ihl] || 5)),
147
- Int8.new(options[:tos] || 0),
148
- Int16.new(options[:length] || 20),
149
- Int16.new(options[:id] || rand(65535)),
150
- Int16.new(options[:frag] || 0),
151
- Int8.new(options[:ttl] || 64),
152
- Int8.new(options[:protocol]),
153
- Int16.new(options[:checksum] || 0),
154
- Addr.new.from_human(options[:src] || '127.0.0.1'),
155
- Addr.new.from_human(options[:dst] || '127.0.0.1'),
156
- StructFu::String.new.read(options[:body])
157
- end
158
-
110
+ # @!attribute u8
111
+ # First byte of IP header. May be accessed through {#version} and {#ihl}.
112
+ # @return [Integer] first byte of IP header.
113
+ define_field :u8, Types::Int8, default: 0x45
114
+ # @!attribute tos
115
+ # @return [Integer] 8-bit Type of Service value
116
+ define_field :tos, Types::Int8, default: 0
117
+ # @!attribute length
118
+ # @return [Integer] 16-bit IP total length
119
+ define_field :length, Types::Int16, default: 20
120
+ # @!attribute id
121
+ # @return [Integer] 16-bit ID
122
+ define_field :id, Types::Int16, default: -> { rand(65535) }
123
+ # @!attribute frag
124
+ # @return [Integer] 16-bit frag word
125
+ define_field :frag, Types::Int16, default: 0
126
+ # @!attribute ttl
127
+ # @return [Integer] 8-bit Time To Live value
128
+ define_field :ttl, Types::Int8, default: 64
129
+ # @!attribute protocol
130
+ # @return [Integer] 8-bit upper protocol value
131
+ define_field :protocol, Types::Int8
132
+ # @!attribute checksum
133
+ # @return [Integer] 16-bit IP header checksum
134
+ define_field :checksum, Types::Int16, default: 0
135
+ # @!attribute src
136
+ # @return [Addr] source IP address
137
+ define_field :src, Addr, default: '127.0.0.1'
138
+ # @!attribute dst
139
+ # @return [Addr] destination IP address
140
+ define_field :dst, Addr, default: '127.0.0.1'
141
+ # @!attribute body
142
+ # @return [Types::String,Header::Base]
143
+ define_field :body, Types::String
144
+
159
145
  # @!attribute version
160
146
  # @return [Integer] 4-bit version attribute
161
147
  # @!attribute ihl
@@ -172,28 +158,7 @@ module PacketGen
172
158
  # @return [Integer] 13-bit fragment offset
173
159
  define_bit_fields_on :frag, :flag_rsv, :flag_df, :flag_mf, :fragment_offset, 13
174
160
 
175
- # Read a IP header from a string
176
- # @param [String] str binary string
177
- # @return [self]
178
- def read(str)
179
- return self if str.nil?
180
- raise ParseError, 'string too short for IP' if str.size < self.sz
181
- force_binary str
182
- self[:u8].read str[0, 1]
183
- self[:tos].read str[1, 1]
184
- self[:length].read str[2, 2]
185
- self[:id].read str[4, 2]
186
- self[:frag].read str[6, 2]
187
- self[:ttl].read str[8, 1]
188
- self[:protocol].read str[9, 1]
189
- self[:checksum].read str[10, 2]
190
- self[:src].read str[12, 4]
191
- self[:dst].read str[16, 4]
192
- self[:body].read str[20..-1]
193
- self
194
- end
195
-
196
- # Compute checksum and set +checksum+ field
161
+ # Compute checksum and set +checksum+ field
197
162
  # @return [Integer]
198
163
  def calc_checksum
199
164
  checksum = (self[:u8].to_i << 8) | self.tos
@@ -216,127 +181,6 @@ module PacketGen
216
181
  self[:length].value = self.sz
217
182
  end
218
183
 
219
- # Getter for TOS attribute
220
- # @return [Integer]
221
- def tos
222
- self[:tos].to_i
223
- end
224
-
225
- # Setter for TOS attribute
226
- # @param [Integer] tos
227
- # @return [Integer]
228
- def tos=(tos)
229
- self[:tos].value = tos
230
- end
231
-
232
- # Getter for length attribute
233
- # @return [Integer]
234
- def length
235
- self[:length].to_i
236
- end
237
-
238
- # Setter for length attribute
239
- # @param [Integer] length
240
- # @return [Integer]
241
- def length=(length)
242
- self[:length].value = length
243
- end
244
-
245
- # Getter for id attribute
246
- # @return [Integer]
247
- def id
248
- self[:id].to_i
249
- end
250
-
251
- # Setter for id attribute
252
- # @param [Integer] id
253
- # @return [Integer]
254
- def id=(id)
255
- self[:id].value = id
256
- end
257
-
258
- # Getter for frag attribute
259
- # @return [Integer]
260
- def frag
261
- self[:frag].to_i
262
- end
263
-
264
- # Setter for frag attribute
265
- # @param [Integer] frag
266
- # @return [Integer]
267
- def frag=(frag)
268
- self[:frag].value = frag
269
- end
270
-
271
- # Getter for ttl attribute
272
- # @return [Integer]
273
- def ttl
274
- self[:ttl].to_i
275
- end
276
-
277
- # Setter for ttl attribute
278
- # @param [Integer] ttl
279
- # @return [Integer]
280
- def ttl=(ttl)
281
- self[:ttl].value = ttl
282
- end
283
-
284
- # Getter for protocol attribute
285
- # @return [Integer]
286
- def protocol
287
- self[:protocol].to_i
288
- end
289
-
290
- # Setter for protocol attribute
291
- # @param [Integer] protocol
292
- # @return [Integer]
293
- def protocol=(protocol)
294
- self[:protocol].value = protocol
295
- end
296
-
297
- # Getter for checksum attribute
298
- # @return [Integer]
299
- def checksum
300
- self[:checksum].to_i
301
- end
302
-
303
- # Setter for checksum attribute
304
- # @param [Integer] checksum
305
- # @return [Integer]
306
- def checksum=(checksum)
307
- self[:checksum].value = checksum
308
- end
309
-
310
- # Get IP source address
311
- # @return [String] dotted address
312
- def src
313
- self[:src].to_human
314
- end
315
- alias :source :src
316
-
317
- # Set IP source address
318
- # @param [String] addr dotted IP address
319
- # @return [String]
320
- def src=(addr)
321
- self[:src].from_human addr
322
- end
323
- alias :source= :src=
324
-
325
- # Get IP destination address
326
- # @return [String] dotted address
327
- def dst
328
- self[:dst].to_human
329
- end
330
- alias :destination :dst
331
-
332
- # Set IP destination address
333
- # @param [String] addr dotted IP address
334
- # @return [String]
335
- def dst=(addr)
336
- self[:dst].from_human addr
337
- end
338
- alias :destination= :dst=
339
-
340
184
  # Get IP part of pseudo header checksum.
341
185
  # @return [Integer]
342
186
  def pseudo_header_checksum
@@ -9,12 +9,12 @@ module PacketGen
9
9
  module Header
10
10
 
11
11
  # A IPv6 header consists of:
12
- # * a first 32-bit word ({#u32}, of {Int32} type) composoed of:
12
+ # * a first 32-bit word ({#u32}, of {Types::Int32} type) composoed of:
13
13
  # * a 4-bit {#version} field,
14
14
  # * a 8-bit {#traffic_class} field,
15
15
  # * a 20-bit {#flow_label} field,
16
- # * a payload length field ({#length}, {Int16} type}),
17
- # * a next header field ({#next}, {Int8} type),
16
+ # * a payload length field ({#length}, {Types::Int16} type}),
17
+ # * a next header field ({#next}, {Types::Int8} type),
18
18
  # * a hop-limit field ({#hop}, +Int8+ type),
19
19
  # * a source address field ({#src}, {IPv6::Addr} type),
20
20
  # * a destination address field ({#dst}, +IPv6::Addr+ type),
@@ -43,35 +43,44 @@ module PacketGen
43
43
  # ipv6.dst = '2001:1234:5678:abcd::123'
44
44
  # ipv6.body.read 'this is a body'
45
45
  # @author Sylvain Daubert
46
- class IPv6 < Struct.new(:u32, :length, :next, :hop, :src, :dst, :body)
47
- include StructFu
48
- include HeaderMethods
49
- extend HeaderClassMethods
46
+ class IPv6 < Base
50
47
 
51
48
  # IPv6 address, as a group of 8 2-byte words
52
49
  # @author Sylvain Daubert
53
- class Addr < Struct.new(:a1, :a2, :a3, :a4, :a5, :a6, :a7, :a8)
54
- include StructFu
55
-
56
- # @param [Hash] options
57
- # @option options [Integer] :a1
58
- # @option options [Integer] :a2
59
- # @option options [Integer] :a3
60
- # @option options [Integer] :a4
61
- # @option options [Integer] :a5
62
- # @option options [Integer] :a6
63
- # @option options [Integer] :a7
64
- # @option options [Integer] :a8
65
- def initialize(options={})
66
- super Int16.new(options[:a1]),
67
- Int16.new(options[:a2]),
68
- Int16.new(options[:a3]),
69
- Int16.new(options[:a4]),
70
- Int16.new(options[:a5]),
71
- Int16.new(options[:a6]),
72
- Int16.new(options[:a7]),
73
- Int16.new(options[:a8])
74
- end
50
+ class Addr < Base
51
+
52
+ # @!attribute a1
53
+ # 1st 2-byte word of IPv6 address
54
+ # @return [Integer]
55
+ define_field :a1, Types::Int16
56
+ # @!attribute a2
57
+ # 2nd 2-byte word of IPv6 address
58
+ # @return [Integer]
59
+ define_field :a2, Types::Int16
60
+ # @!attribute a3
61
+ # 3rd 2-byte word of IPv6 address
62
+ # @return [Integer]
63
+ define_field :a3, Types::Int16
64
+ # @!attribute a4
65
+ # 4th 2-byte word of IPv6 address
66
+ # @return [Integer]
67
+ define_field :a4, Types::Int16
68
+ # @!attribute a5
69
+ # 5th 2-byte word of IPv6 address
70
+ # @return [Integer]
71
+ define_field :a5, Types::Int16
72
+ # @!attribute a6
73
+ # 6th 2-byte word of IPv6 address
74
+ # @return [Integer]
75
+ define_field :a6, Types::Int16
76
+ # @!attribute a7
77
+ # 7th 2-byte word of IPv6 address
78
+ # @return [Integer]
79
+ define_field :a7, Types::Int16
80
+ # @!attribute a8
81
+ # 8th 2-byte word of IPv6 address
82
+ # @return [Integer]
83
+ define_field :a8, Types::Int16
75
84
 
76
85
  # Read a colon-delimited address
77
86
  # @param [String] str
@@ -92,57 +101,47 @@ module PacketGen
92
101
  self
93
102
  end
94
103
 
95
- # Read a Addr6 from a binary string
96
- # @param [String] str
97
- # @return [self]
98
- def read(str)
99
- force_binary str
100
- self[:a1].read str[0, 2]
101
- self[:a2].read str[2, 2]
102
- self[:a3].read str[4, 2]
103
- self[:a4].read str[6, 2]
104
- self[:a5].read str[8, 2]
105
- self[:a6].read str[10, 2]
106
- self[:a7].read str[12, 2]
107
- self[:a8].read str[14, 2]
108
- self
109
- end
110
-
111
- %i(a1 a2 a3 a4 a5 a6 a7 a8).each do |sym|
112
- class_eval "def #{sym}; self[:#{sym}].to_i; end\n" \
113
- "def #{sym}=(v); self[:#{sym}].read v; end"
114
- end
115
-
116
104
  # Addr6 in human readable form (colon-delimited hex string)
117
105
  # @return [String]
118
106
  def to_human
119
107
  IPAddr.new(to_a.map { |a| a.to_i.to_s(16) }.join(':')).to_s
120
108
  end
121
- end
122
109
 
123
- # @param [Hash] options
124
- # @option options [Integer] :version
125
- # @option options [Integer] :traffic_class
126
- # @option options [Integer] :flow_label
127
- # @option options [Integer] :length payload length
128
- # @option options [Integer] :next
129
- # @option options [Integer] :hop
130
- # @option options [String] :src colon-delimited source address
131
- # @option options [String] :dst colon-delimited destination address
132
- # @option options [String] :body binary string
133
- def initialize(options={})
134
- super Int32.new(0x60000000),
135
- Int16.new(options[:length]),
136
- Int8.new(options[:next]),
137
- Int8.new(options[:hop] || 64),
138
- Addr.new.from_human(options[:src] || '::1'),
139
- Addr.new.from_human(options[:dst] || '::1'),
140
- StructFu::String.new.read(options[:body])
141
- self.version = options[:version] if options[:version]
142
- self.traffic_class = options[:traffic_class] if options[:traffic_class]
143
- self.flow_label = options[:flow_label] if options[:flow_label]
110
+ # Return an array of address 16-bit words
111
+ # @return [Array<Integer>]
112
+ def to_a
113
+ @fields.values
114
+ end
144
115
  end
145
116
 
117
+ # @!attribute u32
118
+ # First 32-bit word of IPv6 header
119
+ # @return [Integer]
120
+ define_field :u32, Types::Int32, default: 0x6000_0000
121
+ # @!attribute length
122
+ # 16-bit word of IPv6 payload length
123
+ # @return [Integer]
124
+ define_field :length, Types::Int16
125
+ # @!attribute next
126
+ # 8-bit IPv6 next payload value
127
+ # @return [Integer]
128
+ define_field :next, Types::Int8
129
+ # @!attribute hop
130
+ # 8-bit IPv6 hop limit
131
+ # @return [Integer]
132
+ define_field :hop, Types::Int8, default: 64
133
+ # @!attribute src
134
+ # IPv6 source address
135
+ # @return [Addr]
136
+ define_field :src, Addr, default: '::1'
137
+ # @!attribute dst
138
+ # IPv6 destination address
139
+ # @return [Addr]
140
+ define_field :dst, Addr, default: '::1'
141
+ # @!attribute body
142
+ # @return [Types::String,Header::Base]
143
+ define_field :body, Types::String
144
+
146
145
  # @!attribute version
147
146
  # @return [Integer] 4-bit version attribute
148
147
  # @!attribute traffic_class
@@ -151,108 +150,18 @@ module PacketGen
151
150
  # @return [Integer] 20-bit flow_label attribute
152
151
  define_bit_fields_on :u32, :version, 4, :traffic_class, 8, :flow_label, 20
153
152
 
154
- # Read a IP header from a string
155
- # @param [String] str binary string
156
- # @return [self]
157
- def read(str)
158
- return self if str.nil?
159
- raise ParseError, 'string too short for IPv6' if str.size < self.sz
160
- force_binary str
161
- first32 = str[0, 4].unpack('N').first
162
- self.version = first32 >> 28
163
- self.traffic_class = (first32 >> 20) & 0xff
164
- self.flow_label = first32 & 0xfffff
165
-
166
- self[:length].read str[4, 2]
167
- self[:next].read str[6, 1]
168
- self[:hop].read str[7, 1]
169
- self[:src].read str[8, 16]
170
- self[:dst].read str[24, 16]
171
- self[:body].read str[40..-1]
172
- self
173
- end
174
-
175
153
  # Compute length and set +len+ field
176
154
  # @return [Integer]
177
155
  def calc_length
178
156
  self.length = body.sz
179
157
  end
180
158
 
181
- # @!attribute length
182
- # 16-bit payload length attribute
183
- # @return [Integer]
184
- def length
185
- self[:length].to_i
186
- end
187
-
188
- # @param [Integer] i
189
- # @return [Integer]
190
- def length=(i)
191
- self[:length].read i
192
- end
193
-
194
- # Getter for next attribute
195
- # @return [Integer]
196
- def next
197
- self[:next].to_i
198
- end
199
-
200
- # Setter for next attribute
201
- # @param [Integer] i
202
- # @return [Integer]
203
- def next=(i)
204
- self[:next].read i
205
- end
206
-
207
- # Getter for hop attribute
208
- # @return [Integer]
209
- def hop
210
- self[:hop].to_i
211
- end
212
-
213
- # Setter for hop attribute
214
- # @param [Integer] i
215
- # @return [Integer]
216
- def hop=(i)
217
- self[:hop].read i
218
- end
219
-
220
- # Getter for src attribute
221
- # @return [String]
222
- def src
223
- self[:src].to_human
224
- end
225
- alias :source :src
226
-
227
- # Setter for src attribute
228
- # @param [String] addr
229
- # @return [Integer]
230
- def src=(addr)
231
- self[:src].from_human addr
232
- end
233
- alias :source= :src=
234
-
235
- # Getter for dst attribute
236
- # @return [String]
237
- def dst
238
- self[:dst].to_human
239
- end
240
- alias :destination :dst
241
-
242
- # Setter for dst attribute
243
- # @param [String] addr
244
- # @return [Integer]
245
- def dst=(addr)
246
- self[:dst].from_human addr
247
- end
248
- alias :destination= :dst=
249
-
250
159
  # Get IPv6 part of pseudo header checksum.
251
160
  # @return [Integer]
252
161
  def pseudo_header_checksum
253
162
  sum = 0
254
- self[:src].each { |word| sum += word.to_i }
255
- self[:dst].each { |word| sum += word.to_i }
163
+ self[:src].to_a.each { |word| sum += word.to_i }
164
+ self[:dst].to_a.each { |word| sum += word.to_i }
256
165
  sum
257
166
  end
258
167