packetgen 3.3.0 → 3.3.2

Sign up to get free protection for your applications and to get access to all the features.
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