packetgen 2.8.7 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -1
  3. data/README.md +5 -4
  4. data/lib/packetgen.rb +6 -12
  5. data/lib/packetgen/capture.rb +43 -39
  6. data/lib/packetgen/config.rb +0 -1
  7. data/lib/packetgen/deprecation.rb +1 -1
  8. data/lib/packetgen/header.rb +9 -9
  9. data/lib/packetgen/header/asn1_base.rb +10 -10
  10. data/lib/packetgen/header/base.rb +42 -101
  11. data/lib/packetgen/header/dhcp/option.rb +5 -11
  12. data/lib/packetgen/header/dhcpv6/duid.rb +2 -0
  13. data/lib/packetgen/header/dhcpv6/option.rb +2 -19
  14. data/lib/packetgen/header/dhcpv6/options.rb +7 -0
  15. data/lib/packetgen/header/dns.rb +5 -23
  16. data/lib/packetgen/header/dns/name.rb +1 -0
  17. data/lib/packetgen/header/dns/qdsection.rb +1 -0
  18. data/lib/packetgen/header/dns/question.rb +3 -7
  19. data/lib/packetgen/header/dns/rr.rb +3 -0
  20. data/lib/packetgen/header/dns/rrsection.rb +1 -0
  21. data/lib/packetgen/header/dot11.rb +1 -17
  22. data/lib/packetgen/header/dot1x.rb +1 -0
  23. data/lib/packetgen/header/eap.rb +4 -7
  24. data/lib/packetgen/header/eth.rb +2 -0
  25. data/lib/packetgen/header/http/headers.rb +3 -0
  26. data/lib/packetgen/header/http/request.rb +5 -4
  27. data/lib/packetgen/header/http/response.rb +5 -4
  28. data/lib/packetgen/header/icmp.rb +6 -0
  29. data/lib/packetgen/header/icmpv6.rb +6 -0
  30. data/lib/packetgen/header/igmpv3/mq.rb +2 -0
  31. data/lib/packetgen/header/ip.rb +32 -30
  32. data/lib/packetgen/header/ip/addr.rb +1 -0
  33. data/lib/packetgen/header/ip/option.rb +23 -20
  34. data/lib/packetgen/header/ip/options.rb +11 -24
  35. data/lib/packetgen/header/ipv6.rb +45 -34
  36. data/lib/packetgen/header/ipv6/addr.rb +2 -0
  37. data/lib/packetgen/header/ipv6/hop_by_hop.rb +7 -31
  38. data/lib/packetgen/header/mdns.rb +1 -0
  39. data/lib/packetgen/header/mldv2/mlq.rb +2 -0
  40. data/lib/packetgen/header/ospfv2/lsa.rb +15 -25
  41. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +1 -1
  42. data/lib/packetgen/header/ospfv3/lsa.rb +8 -25
  43. data/lib/packetgen/header/snmp.rb +2 -0
  44. data/lib/packetgen/header/tcp.rb +23 -2
  45. data/lib/packetgen/header/tcp/option.rb +51 -52
  46. data/lib/packetgen/header/tcp/options.rb +17 -52
  47. data/lib/packetgen/header/tftp.rb +3 -0
  48. data/lib/packetgen/header/udp.rb +8 -0
  49. data/lib/packetgen/packet.rb +119 -102
  50. data/lib/packetgen/pcapng/block.rb +4 -10
  51. data/lib/packetgen/pcapng/epb.rb +4 -4
  52. data/lib/packetgen/pcapng/file.rb +7 -3
  53. data/lib/packetgen/pcapng/idb.rb +2 -2
  54. data/lib/packetgen/pcapng/shb.rb +3 -3
  55. data/lib/packetgen/pcapng/spb.rb +1 -8
  56. data/lib/packetgen/pcapng/unknown_block.rb +0 -7
  57. data/lib/packetgen/types.rb +1 -0
  58. data/lib/packetgen/types/array.rb +73 -71
  59. data/lib/packetgen/types/cstring.rb +1 -1
  60. data/lib/packetgen/types/enum.rb +3 -3
  61. data/lib/packetgen/types/fields.rb +66 -106
  62. data/lib/packetgen/types/int.rb +9 -5
  63. data/lib/packetgen/types/length_from.rb +45 -0
  64. data/lib/packetgen/types/oui.rb +2 -0
  65. data/lib/packetgen/types/string.rb +10 -16
  66. data/lib/packetgen/types/tlv.rb +7 -15
  67. data/lib/packetgen/utils.rb +8 -8
  68. data/lib/packetgen/utils/arp_spoofer.rb +1 -2
  69. data/lib/packetgen/version.rb +1 -1
  70. metadata +3 -21
  71. data/lib/packetgen/header/crypto.rb +0 -62
  72. data/lib/packetgen/header/esp.rb +0 -413
  73. data/lib/packetgen/header/ike.rb +0 -243
  74. data/lib/packetgen/header/ike/auth.rb +0 -165
  75. data/lib/packetgen/header/ike/cert.rb +0 -76
  76. data/lib/packetgen/header/ike/certreq.rb +0 -66
  77. data/lib/packetgen/header/ike/id.rb +0 -99
  78. data/lib/packetgen/header/ike/ke.rb +0 -79
  79. data/lib/packetgen/header/ike/nonce.rb +0 -40
  80. data/lib/packetgen/header/ike/notify.rb +0 -176
  81. data/lib/packetgen/header/ike/payload.rb +0 -315
  82. data/lib/packetgen/header/ike/sa.rb +0 -561
  83. data/lib/packetgen/header/ike/sk.rb +0 -261
  84. data/lib/packetgen/header/ike/ts.rb +0 -270
  85. data/lib/packetgen/header/ike/vendor_id.rb +0 -39
  86. data/lib/packetgen/header/netbios.rb +0 -20
  87. data/lib/packetgen/header/netbios/datagram.rb +0 -105
  88. data/lib/packetgen/header/netbios/name.rb +0 -67
  89. data/lib/packetgen/header/netbios/session.rb +0 -64
@@ -70,6 +70,7 @@ module PacketGen
70
70
  packet.instance_eval "def mdnsize() @headers[#{mdns_idx}].mdnsize; end"
71
71
  return unless packet.is? 'UDP'
72
72
  return unless packet.udp.sport.zero?
73
+
73
74
  packet.udp.sport = UDP_PORT
74
75
  end
75
76
  end
@@ -121,6 +121,8 @@ module PacketGen
121
121
  self[:max_resp_delay].value = MLDv2.encode(value)
122
122
  end
123
123
 
124
+ undef qqic, qqic=
125
+
124
126
  # Get QQIC value
125
127
  # @note May return a different value from value previously set, as a
126
128
  # float encoding is used to encode big values. See {IGMPv3.decode}.
@@ -74,7 +74,7 @@ module PacketGen
74
74
 
75
75
  # @return [String]
76
76
  def to_human
77
- "Link<type:#{type},metric:#{metric},id:#{id},data:#{data}>"
77
+ "<type:#{type},metric:#{metric},id:#{id},data:#{data}>"
78
78
  end
79
79
  end
80
80
 
@@ -129,7 +129,8 @@ module PacketGen
129
129
  # @!attribute routers
130
130
  # List of routers in network
131
131
  # @return [IP::ArrayOfAddr]
132
- define_field :routers, IP::ArrayOfAddr
132
+ define_field :routers, IP::ArrayOfAddr,
133
+ builder: ->(h, t) { t.new(length_from: -> { h.length - 24 }) }
133
134
  end
134
135
 
135
136
  # This class handles external links in {LSAASExternal LSA AS-External payloads}.
@@ -153,6 +154,11 @@ module PacketGen
153
154
  # @!attribute tos
154
155
  # @return [Integer]
155
156
  define_bit_fields_on :u8, :e_flag, :tos, 7
157
+
158
+ # @return [String]
159
+ def to_human
160
+ "<type:#{e_flag? ? 2 : 1},tos:#{tos},metric:#{metric},fwaddr:#{forwarding_addr},tag:#{ext_route_tag}>"
161
+ end
156
162
  end
157
163
 
158
164
  # This class defines a specialized {Types::Array array} to handle series
@@ -176,14 +182,15 @@ module PacketGen
176
182
  # @!attribute externals
177
183
  # List of external destinations
178
184
  # @return [ArrayOfExternal]
179
- define_field :externals, ArrayOfExternal
185
+ define_field :externals, ArrayOfExternal,
186
+ builder: ->(h, t) { t.new(length_from: -> { h.length - 24 }) }
180
187
  end
181
188
 
182
189
  # This class defines a specialized {Types::Array array} to handle series
183
190
  # of {LSA LSAs}. It recognizes known LSA types and infers correct type.
184
191
  # @author Sylvain Daubert
185
192
  class ArrayOfLSA < Types::Array
186
- set_of LSA
193
+ set_of LSAHeader
187
194
 
188
195
  # @param [Hash] options
189
196
  # @option options [Types::Int] counter Int object used as a counter for this set
@@ -194,27 +201,6 @@ module PacketGen
194
201
  @only_headers = options[:only_headers] || false
195
202
  end
196
203
 
197
- # Populate object from a string
198
- # @param [String] str
199
- # @return [self]
200
- def read(str)
201
- clear
202
- return self if str.nil?
203
- return self if @counter && @counter.to_i.zero?
204
- force_binary str
205
- until str.empty?
206
- lsa = LSAHeader.new.read(str)
207
- unless @only_headers
208
- klass = get_lsa_class_by_human_type(lsa.human_type)
209
- lsa = klass.new.read(str[0...lsa.length])
210
- end
211
- self.push lsa
212
- str.slice!(0, lsa.sz)
213
- break if @counter && (self.size == @counter.to_i)
214
- end
215
- self
216
- end
217
-
218
204
  private
219
205
 
220
206
  def record_from_hash(hsh)
@@ -245,6 +231,10 @@ module PacketGen
245
231
  LSA
246
232
  end
247
233
  end
234
+
235
+ def real_type(lsah)
236
+ @only_headers ? lsah.class : get_lsa_class_by_human_type(lsah.human_type)
237
+ end
248
238
  end
249
239
  end
250
240
  end
@@ -33,7 +33,7 @@ module PacketGen
33
33
  # @!attribute prefix
34
34
  # IPv6 Prefix as an array of 32-bit words
35
35
  # @return [Prefix]
36
- define_field :prefix, Types::ArrayOfInt32
36
+ define_field :prefix, Types::ArrayOfInt32, builder: ->(h, t) { t.new(length_from: -> { h.length / 8 }) }
37
37
 
38
38
  # @!attribute dn_opt
39
39
  # This bit controls an inter-area-prefix-LSAs or AS-external-LSAs
@@ -72,7 +72,7 @@ module PacketGen
72
72
  OSPFv3.define_options(self)
73
73
  # @attribute links
74
74
  # @return [ArrayOfLink]
75
- define_field :links, ArrayOfLink
75
+ define_field :links, ArrayOfLink, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:links) }) }
76
76
 
77
77
  # @!attribute nt_flag
78
78
  # @return [Boolean]
@@ -103,7 +103,7 @@ module PacketGen
103
103
  # @!attribute routers
104
104
  # List of routers attached to the link.
105
105
  # @return [IP::ArrayOfAddr]
106
- define_field :routers, IP::ArrayOfAddr
106
+ define_field :routers, IP::ArrayOfAddr, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:routers) }) }
107
107
  end
108
108
 
109
109
  # This class handles OSPFv3 LSA Intra-Area-Prefix payloads.
@@ -175,7 +175,7 @@ module PacketGen
175
175
  # @!attribute prefixes
176
176
  # List of IPv6 prefixes to be associated with the link.
177
177
  # @return [ArrayOfIPv6Prefix]
178
- define_field :prefixes, ArrayOfIPv6Prefix
178
+ define_field :prefixes, ArrayOfIPv6Prefix, builder: ->(h, t) { t.new(counter: h[:prefix_count]) }
179
179
  end
180
180
 
181
181
  # This class defines a specialized {Types::Array array} to handle series
@@ -183,7 +183,7 @@ module PacketGen
183
183
  # and infers correct type.
184
184
  # @author Sylvain Daubert
185
185
  class ArrayOfLSA < Types::Array
186
- set_of LSA
186
+ set_of LSAHeader
187
187
 
188
188
  # @param [Hash] options
189
189
  # @option options [Types::Int] counter Int object used as a counter for this set
@@ -194,27 +194,6 @@ module PacketGen
194
194
  @only_headers = options[:only_headers] || false
195
195
  end
196
196
 
197
- # Populate object from a string
198
- # @param [String] str
199
- # @return [self]
200
- def read(str)
201
- clear
202
- return self if str.nil?
203
- return self if @counter && @counter.to_i.zero?
204
- force_binary str
205
- until str.empty?
206
- lsa = LSAHeader.new.read(str)
207
- unless @only_headers
208
- klass = get_lsa_class_by_human_type(lsa.human_type)
209
- lsa = klass.new.read(str[0...lsa.length])
210
- end
211
- self.push lsa
212
- str.slice!(0, lsa.sz)
213
- break if @counter && (self.size == @counter.to_i)
214
- end
215
- self
216
- end
217
-
218
197
  private
219
198
 
220
199
  def record_from_hash(hsh)
@@ -245,6 +224,10 @@ module PacketGen
245
224
  LSA
246
225
  end
247
226
  end
227
+
228
+ def real_type(lsah)
229
+ @only_headers ? lsah.class : get_lsa_class_by_human_type(lsah.human_type)
230
+ end
248
231
  end
249
232
  end
250
233
  end
@@ -259,6 +259,7 @@ module PacketGen
259
259
  super
260
260
  data.chosen = options[:chosen_pdu] if options[:chosen_pdu]
261
261
  return unless options[:pdu]
262
+
262
263
  data.root.value[data.chosen] = data.root.chosen_value.class.new(options[:pdu])
263
264
  end
264
265
 
@@ -307,6 +308,7 @@ module PacketGen
307
308
  def added_to_packet(packet)
308
309
  return unless packet.is? 'UDP'
309
310
  return unless packet.udp.sport.zero?
311
+
310
312
  packet.udp.sport = packet.udp.dport
311
313
  end
312
314
  end
@@ -7,6 +7,26 @@
7
7
 
8
8
  module PacketGen
9
9
  module Header
10
+ # TCP header ({https://tools.ietf.org/html/rfc793 RFC 793})
11
+ # 0 1 2 3
12
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
13
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14
+ # | Source Port | Destination Port |
15
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16
+ # | Sequence Number |
17
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18
+ # | Acknowledgment Number |
19
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20
+ # | Data | |U|A|P|R|S|F| |
21
+ # | Offset| Reserved |R|C|S|S|Y|I| Window |
22
+ # | | |G|K|H|T|N|N| |
23
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24
+ # | Checksum | Urgent Pointer |
25
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
26
+ # | Options | Padding |
27
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28
+ # | data |
29
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
10
30
  # A TCP header consists of:
11
31
  # * a source port ({#sport}, {Types::Int16} type),
12
32
  # * a destination port ({#dport}, +Int16+ type),
@@ -78,7 +98,7 @@ module PacketGen
78
98
  # @!attribute seqnum
79
99
  # 32-bit TCP sequence number
80
100
  # @return [Integer]
81
- define_field :seqnum, Types::Int32, default: ->(h) { rand(2**32) }
101
+ define_field :seqnum, Types::Int32, default: ->(_) { rand(2**32) }
82
102
  # @!attribute acknum
83
103
  # 32-bit TCP acknowledgement number
84
104
  # @return [Integer]
@@ -174,6 +194,7 @@ module PacketGen
174
194
  # @return [self]
175
195
  def read(str)
176
196
  return self if str.nil?
197
+
177
198
  force_binary str
178
199
  self[:sport].read str[0, 2]
179
200
  self[:dport].read str[2, 2]
@@ -212,7 +233,7 @@ module PacketGen
212
233
  shift = Inspect.shift_level
213
234
  str = Inspect.inspect_attribute(attr, self[attr])
214
235
  doff = Inspect.int_dec_hex(data_offset, 1)
215
- str<< shift << Inspect::FMT_ATTR % ['', 'data_offset', doff]
236
+ str << shift << Inspect::FMT_ATTR % ['', 'data_offset', doff]
216
237
  str << shift << Inspect::FMT_ATTR % ['', 'reserved', reserved]
217
238
  flags = ''.dup
218
239
  %w[ns cwr ece urg ack psh rst syn fin].each do |fl|
@@ -10,7 +10,7 @@ module PacketGen
10
10
  class TCP
11
11
  # Base class to describe a TCP option
12
12
  # @author Sylvain Daubert
13
- class Option < Base
13
+ class Option < Types::Fields
14
14
  # EOL option value
15
15
  EOL_KIND = 0
16
16
  # NOP option value
@@ -37,10 +37,11 @@ module PacketGen
37
37
  # @!attribute length
38
38
  # Option length
39
39
  # @return [Integer] 8-bit option length
40
- define_field :length, Types::Int8
40
+ define_field :length, Types::Int8, optional: ->(h) { h.length? }
41
41
  # @!attribute value
42
42
  # @return [Integer,String] option value
43
- define_field :value, Types::String
43
+ define_field :value, Types::String, optional: ->(h) { h.length? && h.length > 2 },
44
+ builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
44
45
 
45
46
  # @param [hash] options
46
47
  # @option options [Integer] :kind
@@ -59,40 +60,21 @@ module PacketGen
59
60
  end
60
61
  self[:value] = klass.new(options[:value])
61
62
  when NilClass
62
- self[:value] = Types::String.new
63
+ # Nothing to do
63
64
  else
64
65
  self[:value] = Types::String.new.read(options[:value])
65
66
  self[:length].read(self[:value].sz + 2) unless options[:length]
66
67
  end
67
68
  end
68
69
 
69
- # Read a TCP option from a string
70
- # @param [String] str binary string
71
- # @return [self]
72
- def read(str)
73
- return self if str.nil?
74
- force_binary str
75
- self[:kind].read str[0, 1]
76
- if str[1, 1]
77
- self[:length].read str[1, 1]
78
- self[:value].read str[2, length - 2] if str[2, 1] && length > 2
79
- end
80
- self
81
- end
82
-
83
70
  # Say if given option has a length field.
84
71
  # @return [Boolean]
85
72
  # @since 2.7.0
86
73
  def length?
87
- self[:kind].value && kind >= 2
74
+ kind >= 2
88
75
  end
89
76
 
90
- # @deprecated Use {#length?}.
91
- # @return [Boolean]
92
- def has_length?
93
- Deprecation.deprecated(self.class, __method__, 'length?')
94
- length?
95
- end
77
+ undef value
96
78
 
97
79
  # Getter for value attribute
98
80
  # @return [String, Integer]
@@ -105,19 +87,32 @@ module PacketGen
105
87
  end
106
88
  end
107
89
 
90
+ alias old_set_value value=
91
+ # Setter for value attribute
92
+ # @param[String,Integer]
93
+ # @return [String, Integer]
94
+ def value=(v)
95
+ case self[:value]
96
+ when Types::Int
97
+ self.length = 2 + self[:value].sz
98
+ when String
99
+ self.length = 2 + Types::String.new.read(v).sz
100
+ end
101
+ self[:value].read v
102
+ v
103
+ end
104
+
108
105
  # Get binary string
109
106
  # @return [String]
110
107
  def to_s
111
- str = self[:kind].to_s
112
- str << self[:length].to_s unless self[:length].value.nil?
113
- str << self[:value].to_s if length > 2
114
- str
108
+ self.length = 2 + self[:value].sz if length?
109
+ super
115
110
  end
116
111
 
117
112
  # Get option as a human readable string
118
113
  # @return [String]
119
114
  def to_human
120
- str = self.class == Option ? "unk-#{kind}" : self.class.to_s.sub(/.*::/, '')
115
+ str = self.class == Option ? +"unk-#{kind}" : self.class.to_s.sub(/.*::/, '')
121
116
  if (length > 2) && !self[:value].to_s.empty?
122
117
  str << ":#{self[:value].to_s.inspect}"
123
118
  end
@@ -135,27 +130,25 @@ module PacketGen
135
130
  # End Of Option TCP option
136
131
  # @author Sylvain Daubert
137
132
  class EOL < Option
138
- # @see Option#initialize
139
- def initialize(options={})
140
- super options.merge!(kind: EOL_KIND)
141
- end
133
+ update_field :kind, default: EOL_KIND
142
134
  end
143
135
 
144
136
  # No OPeration TCP option
145
137
  # @author Sylvain Daubert
146
138
  class NOP < Option
147
139
  # @see Option#initialize
148
- def initialize(options={})
149
- super options.merge!(kind: NOP_KIND)
150
- end
140
+ update_field :kind, default: NOP_KIND
151
141
  end
152
142
 
153
143
  # Maximum Segment Size TCP option
154
144
  # @author Sylvain Daubert
155
145
  class MSS < Option
146
+ update_field :kind, default: MSS_KIND
147
+ update_field :length, default: 4
148
+
156
149
  # @see Option#initialize
157
150
  def initialize(options={})
158
- super options.merge!(kind: MSS_KIND, length: 4)
151
+ super
159
152
  self[:value] = Types::Int16.new(options[:value])
160
153
  end
161
154
 
@@ -168,9 +161,12 @@ module PacketGen
168
161
  # Window Size TCP option
169
162
  # @author Sylvain Daubert
170
163
  class WS < Option
164
+ update_field :kind, default: WS_KIND
165
+ update_field :length, default: 3
166
+
171
167
  # @see Option#initialize
172
168
  def initialize(options={})
173
- super options.merge!(kind: WS_KIND, length: 3)
169
+ super
174
170
  self[:value] = Types::Int8.new(options[:value])
175
171
  end
176
172
 
@@ -183,28 +179,25 @@ module PacketGen
183
179
  # Selective Acknowledgment OK TCP option
184
180
  # @author Sylvain Daubert
185
181
  class SACKOK < Option
186
- # @see Option#initialize
187
- def initialize(options={})
188
- super options.merge!(kind: SACKOK_KIND, length: 2)
189
- end
182
+ update_field :kind, default: SACKOK_KIND
183
+ update_field :length, default: 2
190
184
  end
191
185
 
192
186
  # Selective Acknowledgment TCP option
193
187
  # @author Sylvain Daubert
194
188
  class SACK < Option
195
- # @see Option#initialize
196
- def initialize(options={})
197
- super options.merge!(kind: SACK_KIND)
198
- self[:length].read(2) if self[:value].to_s == ''
199
- end
189
+ update_field :kind, default: SACK_KIND
200
190
  end
201
191
 
202
192
  # Echo TCP option
203
193
  # @author Sylvain Daubert
204
194
  class ECHO < Option
195
+ update_field :kind, default: ECHO_KIND
196
+ update_field :length, default: 6
197
+
205
198
  # @see Option#initialize
206
199
  def initialize(options={})
207
- super options.merge!(kind: ECHO_KIND, length: 6)
200
+ super
208
201
  self[:value] = Types::Int32.new(options[:value])
209
202
  end
210
203
 
@@ -217,9 +210,12 @@ module PacketGen
217
210
  # Echo Reply TCP option
218
211
  # @author Sylvain Daubert
219
212
  class ECHOREPLY < Option
213
+ update_field :kind, default: ECHOREPLY_KIND
214
+ update_field :length, default: 6
215
+
220
216
  # @see Option#initialize
221
217
  def initialize(options={})
222
- super options.merge!(kind: ECHOREPLY_KIND, length: 6)
218
+ super
223
219
  self[:value] = Types::Int32.new(options[:value])
224
220
  end
225
221
 
@@ -232,10 +228,13 @@ module PacketGen
232
228
  # Timestamp TCP option
233
229
  # @author Sylvain Daubert
234
230
  class TS < Option
231
+ update_field :kind, default: TS_KIND
232
+ update_field :length, default: 10
233
+
235
234
  # @see Option#initialize
236
235
  def initialize(options={})
237
- super options.merge!(kind: TS_KIND, length: 10)
238
- self[:value] = Types::String.new.read(options[:value] || "\0" * 8)
236
+ super
237
+ self[:value].read(options[:value] || "\0" * 8)
239
238
  end
240
239
 
241
240
  # @return [String]