packetgen 3.3.0 → 3.3.2

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -0
  3. data/README.md +7 -7
  4. data/lib/packetgen/capture.rb +2 -1
  5. data/lib/packetgen/config.rb +2 -1
  6. data/lib/packetgen/header/arp.rb +2 -1
  7. data/lib/packetgen/header/asn1_base.rb +2 -1
  8. data/lib/packetgen/header/base.rb +4 -3
  9. data/lib/packetgen/header/bootp.rb +2 -1
  10. data/lib/packetgen/header/dhcp/option.rb +2 -1
  11. data/lib/packetgen/header/dhcp/options.rb +2 -1
  12. data/lib/packetgen/header/dhcp.rb +2 -1
  13. data/lib/packetgen/header/dhcpv6/duid.rb +2 -1
  14. data/lib/packetgen/header/dhcpv6/option.rb +2 -1
  15. data/lib/packetgen/header/dhcpv6/options.rb +2 -1
  16. data/lib/packetgen/header/dhcpv6/relay.rb +2 -1
  17. data/lib/packetgen/header/dhcpv6.rb +2 -1
  18. data/lib/packetgen/header/dns/name.rb +2 -1
  19. data/lib/packetgen/header/dns/opt.rb +3 -2
  20. data/lib/packetgen/header/dns/option.rb +3 -2
  21. data/lib/packetgen/header/dns/qdsection.rb +2 -1
  22. data/lib/packetgen/header/dns/question.rb +2 -1
  23. data/lib/packetgen/header/dns/rr.rb +2 -1
  24. data/lib/packetgen/header/dns/rrsection.rb +2 -1
  25. data/lib/packetgen/header/dns.rb +3 -2
  26. data/lib/packetgen/header/dot11/control.rb +2 -1
  27. data/lib/packetgen/header/dot11/data.rb +4 -3
  28. data/lib/packetgen/header/dot11/element.rb +2 -1
  29. data/lib/packetgen/header/dot11/management.rb +2 -1
  30. data/lib/packetgen/header/dot11/sub_mngt.rb +2 -1
  31. data/lib/packetgen/header/dot11.rb +2 -1
  32. data/lib/packetgen/header/dot1q.rb +2 -1
  33. data/lib/packetgen/header/dot1x.rb +2 -1
  34. data/lib/packetgen/header/eap/fast.rb +2 -1
  35. data/lib/packetgen/header/eap/md5.rb +2 -1
  36. data/lib/packetgen/header/eap/tls.rb +3 -2
  37. data/lib/packetgen/header/eap/ttls.rb +3 -2
  38. data/lib/packetgen/header/eap.rb +3 -2
  39. data/lib/packetgen/header/eth.rb +3 -2
  40. data/lib/packetgen/header/gre.rb +2 -1
  41. data/lib/packetgen/header/http/headers.rb +4 -3
  42. data/lib/packetgen/header/http/request.rb +2 -1
  43. data/lib/packetgen/header/http/response.rb +2 -1
  44. data/lib/packetgen/header/http/verbs.rb +2 -1
  45. data/lib/packetgen/header/http.rb +2 -1
  46. data/lib/packetgen/header/icmp.rb +2 -1
  47. data/lib/packetgen/header/icmpv6.rb +2 -1
  48. data/lib/packetgen/header/igmp.rb +2 -1
  49. data/lib/packetgen/header/igmpv3/group_record.rb +2 -1
  50. data/lib/packetgen/header/igmpv3/mq.rb +2 -1
  51. data/lib/packetgen/header/igmpv3/mr.rb +2 -1
  52. data/lib/packetgen/header/igmpv3.rb +2 -1
  53. data/lib/packetgen/header/ip/addr.rb +2 -1
  54. data/lib/packetgen/header/ip/option.rb +3 -2
  55. data/lib/packetgen/header/ip/options.rb +2 -1
  56. data/lib/packetgen/header/ip.rb +3 -2
  57. data/lib/packetgen/header/ipv6/addr.rb +2 -1
  58. data/lib/packetgen/header/ipv6/extension.rb +2 -1
  59. data/lib/packetgen/header/ipv6/hop_by_hop.rb +2 -1
  60. data/lib/packetgen/header/ipv6.rb +2 -1
  61. data/lib/packetgen/header/llc.rb +2 -1
  62. data/lib/packetgen/header/mdns.rb +2 -1
  63. data/lib/packetgen/header/mld.rb +2 -1
  64. data/lib/packetgen/header/mldv2/mcast_address_record.rb +2 -1
  65. data/lib/packetgen/header/mldv2/mlq.rb +2 -1
  66. data/lib/packetgen/header/mldv2/mlr.rb +2 -1
  67. data/lib/packetgen/header/mldv2.rb +2 -1
  68. data/lib/packetgen/header/ospfv2/db_description.rb +2 -1
  69. data/lib/packetgen/header/ospfv2/hello.rb +2 -1
  70. data/lib/packetgen/header/ospfv2/ls_ack.rb +2 -1
  71. data/lib/packetgen/header/ospfv2/ls_request.rb +2 -1
  72. data/lib/packetgen/header/ospfv2/ls_update.rb +2 -1
  73. data/lib/packetgen/header/ospfv2/lsa.rb +2 -1
  74. data/lib/packetgen/header/ospfv2/lsa_header.rb +2 -1
  75. data/lib/packetgen/header/ospfv2.rb +2 -1
  76. data/lib/packetgen/header/ospfv3/db_description.rb +2 -1
  77. data/lib/packetgen/header/ospfv3/hello.rb +2 -1
  78. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +2 -1
  79. data/lib/packetgen/header/ospfv3/ls_ack.rb +2 -1
  80. data/lib/packetgen/header/ospfv3/ls_request.rb +2 -1
  81. data/lib/packetgen/header/ospfv3/ls_update.rb +2 -1
  82. data/lib/packetgen/header/ospfv3/lsa.rb +2 -1
  83. data/lib/packetgen/header/ospfv3/lsa_header.rb +2 -1
  84. data/lib/packetgen/header/ospfv3.rb +2 -1
  85. data/lib/packetgen/header/sctp/chunk.rb +547 -0
  86. data/lib/packetgen/header/sctp/error.rb +347 -0
  87. data/lib/packetgen/header/sctp/padded32.rb +34 -0
  88. data/lib/packetgen/header/sctp/parameter.rb +229 -0
  89. data/lib/packetgen/header/sctp.rb +96 -0
  90. data/lib/packetgen/header/snmp.rb +3 -2
  91. data/lib/packetgen/header/tcp/option.rb +2 -1
  92. data/lib/packetgen/header/tcp/options.rb +2 -1
  93. data/lib/packetgen/header/tcp.rb +3 -2
  94. data/lib/packetgen/header/tftp.rb +2 -1
  95. data/lib/packetgen/header/udp.rb +2 -1
  96. data/lib/packetgen/header.rb +4 -2
  97. data/lib/packetgen/headerable.rb +2 -1
  98. data/lib/packetgen/inject.rb +2 -1
  99. data/lib/packetgen/inspect.rb +2 -1
  100. data/lib/packetgen/packet.rb +4 -3
  101. data/lib/packetgen/pcap.rb +2 -1
  102. data/lib/packetgen/pcapng/block.rb +3 -2
  103. data/lib/packetgen/pcapng/epb.rb +2 -1
  104. data/lib/packetgen/pcapng/file.rb +2 -1
  105. data/lib/packetgen/pcapng/idb.rb +2 -1
  106. data/lib/packetgen/pcapng/shb.rb +2 -1
  107. data/lib/packetgen/pcapng/spb.rb +2 -1
  108. data/lib/packetgen/pcapng/unknown_block.rb +2 -1
  109. data/lib/packetgen/pcapng.rb +2 -1
  110. data/lib/packetgen/pcaprub_wrapper.rb +2 -1
  111. data/lib/packetgen/proto.rb +2 -1
  112. data/lib/packetgen/types/abstract_tlv.rb +146 -56
  113. data/lib/packetgen/types/array.rb +20 -3
  114. data/lib/packetgen/types/cstring.rb +2 -1
  115. data/lib/packetgen/types/enum.rb +3 -2
  116. data/lib/packetgen/types/fieldable.rb +3 -2
  117. data/lib/packetgen/types/fields.rb +8 -7
  118. data/lib/packetgen/types/int.rb +114 -13
  119. data/lib/packetgen/types/int_string.rb +2 -1
  120. data/lib/packetgen/types/length_from.rb +2 -1
  121. data/lib/packetgen/types/oui.rb +2 -1
  122. data/lib/packetgen/types/string.rb +2 -1
  123. data/lib/packetgen/types/tlv.rb +2 -1
  124. data/lib/packetgen/types.rb +2 -1
  125. data/lib/packetgen/unknown_packet.rb +3 -2
  126. data/lib/packetgen/utils/arp_spoofer.rb +4 -3
  127. data/lib/packetgen/utils.rb +2 -1
  128. data/lib/packetgen/version.rb +3 -2
  129. data/lib/packetgen.rb +2 -1
  130. metadata +27 -16
@@ -0,0 +1,347 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of PacketGen
4
+ # See https://github.com/lemontree55/packetgen for more informations
5
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
+ # This program is published under MIT license.
8
+
9
+ module PacketGen
10
+ module Header
11
+ class SCTP
12
+ # Common methods to all error causes
13
+ # @author Sylvain Daubert
14
+ module ErrorMixin
15
+ include Padded32
16
+
17
+ # Get error name
18
+ # @return [String]
19
+ def error_name
20
+ self.class.name.split('::').last.delete_suffix('Error')
21
+ end
22
+
23
+ # @return [String]
24
+ def to_human
25
+ "<#{error_name}: #{value}>"
26
+ end
27
+ end
28
+
29
+ Error = Types::AbstractTLV.create(type_class: Types::Int16Enum,
30
+ length_class: Types::Int16,
31
+ field_in_length: 'TLV')
32
+
33
+ # Base class/factory for {AbortChunk} and {ErrorChunk} error causes
34
+ # @author Sylvain Daubert
35
+ class Error
36
+ include ErrorMixin
37
+
38
+ # Error Causes/Types
39
+ TYPES = {
40
+ 'InvalidStreamId' => 1,
41
+ 'MissingMandatoryParameter' => 2,
42
+ 'StaleCookie' => 3,
43
+ 'OutOfResource' => 4,
44
+ 'UnresolvableAddress' => 5,
45
+ 'UnrecognizedChunkType' => 6,
46
+ 'InvalidMandatoryParameter' => 7,
47
+ 'UnrecognizedParameters' => 8,
48
+ 'NoUserData' => 9,
49
+ 'CookieReceivedWhileShuttingDown' => 10,
50
+ 'RestartAssociationWithNewAddress' => 11,
51
+ 'UserInitiatedAbort' => 12,
52
+ 'ProtocolViolation' => 13
53
+ }.freeze
54
+
55
+ # @param [Object] value
56
+ def from_human(value)
57
+ if value.is_a?(self[:value].class)
58
+ self[:value] = value
59
+ else
60
+ self[:value].from_human(value)
61
+ end
62
+ end
63
+ end
64
+ Error.define_type_enum(Error::TYPES)
65
+
66
+ # Handle array of {Error} and {ErrorMixin} classes.
67
+ # @author Sylvain Daubert
68
+ class ArrayOfError < Types::Array
69
+ set_of Error
70
+
71
+ private
72
+
73
+ # @param [Error,ErrorMixin] error
74
+ def real_type(error)
75
+ type_name = Error::TYPES.key(error.type)
76
+ return error.class if type_name.nil?
77
+
78
+ SCTP.const_get(real_klass_name(type_name)) || error.class
79
+ end
80
+
81
+ def real_klass_name(type_name)
82
+ type_name + 'Error' # rubocop:disable Style/StringConcatenation
83
+ end
84
+ end
85
+
86
+ InvalidStreamIdError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
87
+ length_class: Types::Int16,
88
+ value_class: Types::Int32,
89
+ field_in_length: 'TLV')
90
+
91
+ # InvalidStreamIdentifier error
92
+ # @author Sylvain Daubert
93
+ class InvalidStreamIdError
94
+ include ErrorMixin
95
+
96
+ # Get stream Id value
97
+ # @return [Integer]
98
+ def stream_identifier
99
+ self.value >> 16
100
+ end
101
+
102
+ # Set stream Id value
103
+ # @param [Integer] stream_id
104
+ # @return [Integer]
105
+ def stream_identifier=(stream_id)
106
+ self.value = (stream_id & 0xffff) << 16
107
+ stream_id
108
+ end
109
+
110
+ # @return [::String]
111
+ def to_human
112
+ "<#{error_name}: #{stream_identifier}>"
113
+ end
114
+
115
+ # @param [Integer] val
116
+ def from_human(val)
117
+ super
118
+ self.value <<= 16 if self[:value] < Types::Int
119
+ end
120
+ end
121
+ InvalidStreamIdError.define_type_enum(Error::TYPES)
122
+ InvalidStreamIdError.define_type_default('InvalidStreamId')
123
+
124
+ MissingMandatoryParameterError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
125
+ length_class: Types::Int16,
126
+ value_class: Types::ArrayOfInt16,
127
+ field_in_length: 'TLV')
128
+
129
+ # MissingMandatoryParameter error. Indicate that one or more
130
+ # mandatory TLV parameters are missing in a received {InitChunk}
131
+ # or {InitAckChunk}.
132
+ # @author Sylvain Daubert
133
+ class MissingMandatoryParameterError
134
+ include ErrorMixin
135
+
136
+ # @return [::String]
137
+ def to_human
138
+ "<#{error_name}: #{self[:value].to_human}>"
139
+ end
140
+ end
141
+ MissingMandatoryParameterError.define_type_enum(Error::TYPES)
142
+ MissingMandatoryParameterError.define_type_default('MissingMandatoryParameter')
143
+
144
+ StaleCookieError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
145
+ length_class: Types::Int16,
146
+ value_class: Types::Int32,
147
+ field_in_length: 'TLV')
148
+
149
+ # StaleCookie error. Indicates the receipt of a valid State Cookie that
150
+ # has expired.
151
+ # @author Sylvain Daubert
152
+ class StaleCookieError
153
+ include ErrorMixin
154
+ end
155
+ StaleCookieError.define_type_enum(Error::TYPES)
156
+ StaleCookieError.define_type_default('StaleCookie')
157
+
158
+ OutOfResourceError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
159
+ length_class: Types::Int16,
160
+ field_in_length: 'TLV')
161
+
162
+ # Out of ressource error. Indicates that the sender is out of resource.
163
+ # @author Sylvain Daubert
164
+ class OutOfResourceError
165
+ include ErrorMixin
166
+
167
+ # @return [::String]
168
+ def to_human
169
+ "<#{error_name}>"
170
+ end
171
+ end
172
+ OutOfResourceError.define_type_enum(Error::TYPES)
173
+ OutOfResourceError.define_type_default('OutOfResource')
174
+
175
+ UnresolvableAddressError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
176
+ length_class: Types::Int16,
177
+ value_class: Parameter,
178
+ field_in_length: 'TLV')
179
+
180
+ # Out of ressource error. Indicates that the sender is out of resource.
181
+ # @author Sylvain Daubert
182
+ class UnresolvableAddressError
183
+ include ErrorMixin
184
+
185
+ # Set +value+ by accepting {ParameterMixin} classes.
186
+ # @param [ParameterMixin] val
187
+ # @return [ParameterMixin]
188
+ def value=(val)
189
+ if val.is_a?(ParameterMixin)
190
+ self[:value] = val
191
+ calc_length
192
+ val
193
+ else
194
+ super
195
+ end
196
+ end
197
+
198
+ # @return [::String]
199
+ def to_human
200
+ "<#{error_name}: #{self[:value].to_human}>"
201
+ end
202
+ end
203
+ UnresolvableAddressError.define_type_enum(Error::TYPES)
204
+ UnresolvableAddressError.define_type_default('UnresolvableAddress')
205
+
206
+ UnrecognizedChunkTypeError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
207
+ length_class: Types::Int16,
208
+ value_class: BaseChunk,
209
+ field_in_length: 'TLV')
210
+
211
+ # Unrecognized chunk type error. The receiver does not understand the chunk and the upper bits of the 'Chunk Type'
212
+ # are set to 01 or 11.
213
+ # @author Sylvain Daubert
214
+ class UnrecognizedChunkTypeError
215
+ include ErrorMixin
216
+
217
+ # @return [::String]
218
+ def to_human
219
+ "<#{error_name}: #{self[:value].to_human}>"
220
+ end
221
+ end
222
+ UnrecognizedChunkTypeError.define_type_enum(Error::TYPES)
223
+ UnrecognizedChunkTypeError.define_type_default('UnrecognizedChunkType')
224
+
225
+ InvalidMandatoryParameterError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
226
+ length_class: Types::Int16,
227
+ field_in_length: 'TLV')
228
+
229
+ # Invalid mandatory parameter error. Returned to the originator of an INIT or INIT ACK chunk when one of the
230
+ # mandatory parameters is set to an invalid value.
231
+ # @author Sylvain Daubert
232
+ class InvalidMandatoryParameterError
233
+ include ErrorMixin
234
+
235
+ # @return [::String]
236
+ def to_human
237
+ "<#{error_name}>"
238
+ end
239
+ end
240
+ InvalidMandatoryParameterError.define_type_enum(Error::TYPES)
241
+ InvalidMandatoryParameterError.define_type_default('InvalidMandatoryParameter')
242
+
243
+ UnrecognizedParametersError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
244
+ length_class: Types::Int16,
245
+ value_class: ArrayOfParameter,
246
+ field_in_length: 'TLV')
247
+
248
+ # Unrecognized parameters error. Returned to the originator of the INIT ACK chunk if the receiver does not
249
+ # recognize one or more Optional TLV parameters in the INIT ACK chunk.
250
+ # @author Sylvain Daubert
251
+ class UnrecognizedParametersError
252
+ include ErrorMixin
253
+
254
+ # @return [::String]
255
+ def to_human
256
+ "<#{error_name}: #{self[:value].to_human}>"
257
+ end
258
+ end
259
+ UnrecognizedParametersError.define_type_enum(Error::TYPES)
260
+ UnrecognizedParametersError.define_type_default('UnrecognizedParameters')
261
+
262
+ NoUserDataError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
263
+ length_class: Types::Int16,
264
+ value_class: Types::Int32,
265
+ field_in_length: 'TLV')
266
+
267
+ # No user data error. Returned when a received {DataChunk} was received with no data.
268
+ # @author Sylvain Daubert
269
+ class NoUserDataError
270
+ include ErrorMixin
271
+ end
272
+ NoUserDataError.define_type_enum(Error::TYPES)
273
+ NoUserDataError.define_type_default('NoUserData')
274
+
275
+ CookieReceivedWhileShuttingDownError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
276
+ length_class: Types::Int16,
277
+ field_in_length: 'TLV')
278
+
279
+ # Cookie received while shutting down error.
280
+ # A COOKIE ECHO chunk was received while the endpoint was in the SHUTDOWN-ACK-SENT state.
281
+ # @author Sylvain Daubert
282
+ class CookieReceivedWhileShuttingDownError
283
+ include ErrorMixin
284
+
285
+ # @return [::String]
286
+ def to_human
287
+ "<#{error_name}>"
288
+ end
289
+ end
290
+ CookieReceivedWhileShuttingDownError.define_type_enum(Error::TYPES)
291
+ CookieReceivedWhileShuttingDownError.define_type_default('CookieReceivedWhileShuttingDown')
292
+
293
+ RestartAssociationWithNewAddressError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
294
+ length_class: Types::Int16,
295
+ value_class: ArrayOfParameter,
296
+ field_in_length: 'TLV')
297
+
298
+ # Cookie received while shutting down error.
299
+ # A COOKIE ECHO chunk was received while the endpoint was in the SHUTDOWN-ACK-SENT state.
300
+ # @author Sylvain Daubert
301
+ class RestartAssociationWithNewAddressError
302
+ include ErrorMixin
303
+
304
+ # @return [::String]
305
+ def to_human
306
+ "<#{error_name}: #{self[:value].to_human}>"
307
+ end
308
+ end
309
+ RestartAssociationWithNewAddressError.define_type_enum(Error::TYPES)
310
+ RestartAssociationWithNewAddressError.define_type_default('RestartAssociationWithNewAddress')
311
+
312
+ UserInitiatedAbortError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
313
+ length_class: Types::Int16,
314
+ field_in_length: 'TLV')
315
+
316
+ # User-Initiated abort error.
317
+ # @author Sylvain Daubert
318
+ class UserInitiatedAbortError
319
+ include ErrorMixin
320
+
321
+ # @return [::String]
322
+ def to_human
323
+ "<#{error_name}>"
324
+ end
325
+ end
326
+ UserInitiatedAbortError.define_type_enum(Error::TYPES)
327
+ UserInitiatedAbortError.define_type_default('UserInitiatedAbort')
328
+
329
+ ProtocolViolationError = Types::AbstractTLV.create(type_class: Types::Int16Enum,
330
+ length_class: Types::Int16,
331
+ field_in_length: 'TLV')
332
+
333
+ # Protocol violation error.
334
+ # @author Sylvain Daubert
335
+ class ProtocolViolationError
336
+ include ErrorMixin
337
+
338
+ # @return [::String]
339
+ def to_human
340
+ "<#{error_name}>"
341
+ end
342
+ end
343
+ ProtocolViolationError.define_type_enum(Error::TYPES)
344
+ ProtocolViolationError.define_type_default('ProtocolViolation')
345
+ end
346
+ end
347
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of PacketGen
4
+ # See https://github.com/lemontree55/packetgen for more informations
5
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
+ # This program is published under MIT license.
8
+
9
+ module PacketGen
10
+ module Header
11
+ class SCTP
12
+ # Mixin to handle 32-bit padding in SCTP classes
13
+ module Padded32
14
+ # Handle padding
15
+ # @param [Bool] no_padding
16
+ # @return [::String]
17
+ def to_s(no_padding: false)
18
+ s = super()
19
+ return s if no_padding
20
+
21
+ padlen = -(s.size % -4)
22
+ s << force_binary("\x00" * padlen)
23
+ end
24
+
25
+ # Say if binary string is padded
26
+ # @return [bool]
27
+ def padded?
28
+ str = to_s(no_padding: true)
29
+ (str.size % 4).positive?
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,229 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is part of PacketGen
4
+ # See https://github.com/lemontree55/packetgen for more informations
5
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
6
+ # Copyright (C) 2024 LemonTree55 <lenontree@proton.me>
7
+ # This program is published under MIT license.
8
+
9
+ module PacketGen
10
+ module Header
11
+ class SCTP
12
+ # Common methods to Init and InitAck parameters
13
+ # @author Sylvain Daubert
14
+ module ParameterMixin
15
+ include Padded32
16
+
17
+ # Get parameter name
18
+ # @return [String]
19
+ def parameter_name
20
+ self.class.name.split('::').last.delete_suffix('Parameter')
21
+ end
22
+
23
+ # @return [String]
24
+ def to_human
25
+ "<#{parameter_name}: #{value}>"
26
+ end
27
+ end
28
+
29
+ Parameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
30
+ length_class: Types::Int16,
31
+ field_in_length: 'TLV')
32
+ # Base class/factory for {InitChunk} and {InitAckChunk} parameters
33
+ # @author Sylvain Daubert
34
+ class Parameter
35
+ include ParameterMixin
36
+
37
+ # Paramter Types
38
+ TYPES = {
39
+ 'IPv4' => 5,
40
+ 'IPv6' => 6,
41
+ 'StateCookie' => 7,
42
+ 'Unrecognized' => 8,
43
+ 'CookiePreservative' => 9,
44
+ 'Hostname' => 11,
45
+ 'SupportedAddrTypes' => 12,
46
+ 'ECN' => 32_768
47
+ }.freeze
48
+
49
+ # @return [::String]
50
+ def to_human
51
+ "<#{human_type}: #{self[:value].inspect}>"
52
+ end
53
+
54
+ # @param [Object] value
55
+ def from_human(value)
56
+ if value.is_a?(self[:value].class)
57
+ self[:value] = value
58
+ else
59
+ self[:value].from_human(value)
60
+ end
61
+ end
62
+ end
63
+ Parameter.define_type_enum(Parameter::TYPES)
64
+
65
+ IPv4Parameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
66
+ length_class: Types::Int16,
67
+ value_class: IP::Addr,
68
+ field_in_length: 'TLV')
69
+
70
+ # IPv4 address parameter
71
+ # @author Sylvain Daubert
72
+ class IPv4Parameter
73
+ include ParameterMixin
74
+ end
75
+ IPv4Parameter.define_type_enum(Parameter::TYPES)
76
+ IPv4Parameter.define_type_default('IPv4')
77
+
78
+ IPv6Parameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
79
+ length_class: Types::Int16,
80
+ value_class: IPv6::Addr,
81
+ field_in_length: 'TLV')
82
+
83
+ # IPv6 address parameter
84
+ # @author Sylvain Daubert
85
+ class IPv6Parameter
86
+ include ParameterMixin
87
+ end
88
+ IPv6Parameter.define_type_enum(Parameter::TYPES)
89
+ IPv6Parameter.define_type_default('IPv6')
90
+
91
+ StateCookieParameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
92
+ length_class: Types::Int16,
93
+ value_class: Types::String,
94
+ field_in_length: 'TLV')
95
+
96
+ # State Cookie parameter
97
+ # @author Sylvain Daubert
98
+ class StateCookieParameter
99
+ include ParameterMixin
100
+
101
+ # @return [::String]
102
+ def to_human
103
+ "<#{parameter_name}: #{self[:value].inspect}>"
104
+ end
105
+ end
106
+ StateCookieParameter.define_type_enum(Parameter::TYPES)
107
+ StateCookieParameter.define_type_default('StateCookie')
108
+
109
+ UnrecognizedParameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
110
+ length_class: Types::Int16,
111
+ value_class: Parameter,
112
+ field_in_length: 'TLV')
113
+
114
+ # Unrecognized parameter
115
+ # @author Sylvain Daubert
116
+ class UnrecognizedParameter
117
+ include ParameterMixin
118
+
119
+ # @return [::String]
120
+ def to_human
121
+ "<#{parameter_name}: #{self[:value].to_human}"
122
+ end
123
+ end
124
+ UnrecognizedParameter.define_type_enum(Parameter::TYPES)
125
+ UnrecognizedParameter.define_type_default('Unrecognized')
126
+
127
+ HostnameParameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
128
+ length_class: Types::Int16,
129
+ value_class: Types::CString,
130
+ field_in_length: 'TLV')
131
+
132
+ # Hostname address parameter
133
+ # @author Sylvain Daubert
134
+ class HostnameParameter
135
+ include ParameterMixin
136
+ end
137
+ HostnameParameter.define_type_enum(Parameter::TYPES)
138
+ HostnameParameter.define_type_default('Hostname')
139
+
140
+ SupportedAddrTypesParameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
141
+ length_class: Types::Int16,
142
+ value_class: Types::ArrayOfInt16,
143
+ field_in_length: 'TLV')
144
+
145
+ # Supported address types parameter
146
+ # @author Sylvain Daubert
147
+ class SupportedAddrTypesParameter
148
+ include ParameterMixin
149
+
150
+ # @return [::String]
151
+ def to_human
152
+ types = self[:value].map(&:to_i).map do |int16|
153
+ Parameter::TYPES.key(int16) || int16.to_s
154
+ end.join(',')
155
+ "<#{parameter_name}: #{types}>"
156
+ end
157
+ end
158
+ SupportedAddrTypesParameter.define_type_enum(Parameter::TYPES)
159
+ SupportedAddrTypesParameter.define_type_default('SupportedAddrTypes')
160
+
161
+ CookiePreservativeParameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
162
+ length_class: Types::Int16,
163
+ value_class: Types::Int32,
164
+ field_in_length: 'TLV')
165
+
166
+ # Cookie Preservative parameter
167
+ # @author Sylvain Daubert
168
+ class CookiePreservativeParameter
169
+ include ParameterMixin
170
+
171
+ # @return [::String]
172
+ def to_human
173
+ "<#{parameter_name}: #{value}>"
174
+ end
175
+ end
176
+ CookiePreservativeParameter.define_type_enum(Parameter::TYPES)
177
+ CookiePreservativeParameter.define_type_default('CookiePreservative')
178
+
179
+ ECNParameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
180
+ length_class: Types::Int16,
181
+ field_in_length: 'TLV')
182
+
183
+ # ECN parameter
184
+ # @author Sylvain Daubert
185
+ class ECNParameter
186
+ include ParameterMixin
187
+
188
+ # @return [::String]
189
+ def to_human
190
+ "<#{parameter_name}>"
191
+ end
192
+ end
193
+ ECNParameter.define_type_enum(Parameter::TYPES)
194
+ ECNParameter.define_type_default('ECN')
195
+
196
+ HearbeatInfoParameter = Types::AbstractTLV.create(type_class: Types::Int16Enum,
197
+ length_class: Types::Int16,
198
+ field_in_length: 'TLV')
199
+
200
+ # Heartbeat Information parameter
201
+ # @author Sylvain Daubert
202
+ class HearbeatInfoParameter
203
+ include ParameterMixin
204
+ end
205
+ HearbeatInfoParameter.define_type_enum({ 'HearbeatInfo' => 1 }.freeze)
206
+ HearbeatInfoParameter.define_type_default('HearbeatInfo')
207
+
208
+ # Array of {Parameter}s and {ParameterMixin}.
209
+ # @author Sylvain Daubert
210
+ class ArrayOfParameter < Types::Array
211
+ set_of Parameter
212
+
213
+ private
214
+
215
+ # Get real type from {Parameter} type
216
+ def real_type(param)
217
+ type_name = Parameter::TYPES.key(param.type)
218
+ return param.class if type_name.nil?
219
+
220
+ SCTP.const_get(real_klass_name(type_name)) || param.class
221
+ end
222
+
223
+ def real_klass_name(type_name)
224
+ type_name + 'Parameter' # rubocop:disable Style/StringConcatenation
225
+ end
226
+ end
227
+ end
228
+ end
229
+ end