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,547 @@
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
+ require_relative 'padded32'
10
+
11
+ module PacketGen
12
+ module Header
13
+ class SCTP
14
+ # BaseChunk class, defining SCTP chunk common fields
15
+ # 0 1 2 3
16
+ # 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
17
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18
+ # | Chunk Type | Chunk Flags | Chunk Length |
19
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20
+ # @abstract Subclass and add more fields
21
+ # @author Sylvain Daubert
22
+ class BaseChunk < Base
23
+ include Padded32
24
+
25
+ # SCTP chunk types, as per RFC9260
26
+ TYPES = {
27
+ 'DATA' => 0,
28
+ 'INIT' => 1,
29
+ 'INIT_ACK' => 2,
30
+ 'SACK' => 3,
31
+ 'HEARTBEAT' => 4,
32
+ 'HEARTBEAT_ACK' => 5,
33
+ 'ABORT' => 6,
34
+ 'SHUTDOWN' => 7,
35
+ 'SHUTDOWN_ACK' => 8,
36
+ 'ERROR' => 9,
37
+ 'COOKIE_ECHO' => 10,
38
+ 'COOKIE_ACK' => 11,
39
+ 'SHUTDOWN_COMPLETE' => 14,
40
+ }.freeze
41
+
42
+ # @!attribute type
43
+ # 8-bit SCTP chunk type
44
+ # @return [Integer]
45
+ define_field :type, Types::Int8Enum, enum: TYPES
46
+ # @!attribute type
47
+ # 8-bit SCTP chunk flags
48
+ # @return [Integer]
49
+ define_field :flags, Types::Int8
50
+ # @!attribute length
51
+ # 16-bit SCTP chunk length
52
+ # @return [Integer]
53
+ define_field :length, Types::Int16
54
+
55
+ # Get human-redable chunk
56
+ # @return [::String]
57
+ def to_human
58
+ str = +"<chunk:#{human_type}"
59
+ flags_str = flags_to_human
60
+ str << ",flags:#{flags_str}" unless flags_str.empty?
61
+ str << '>'
62
+ end
63
+
64
+ # @return [::String,Integer]
65
+ def human_type
66
+ self[:type].to_human
67
+ end
68
+
69
+ # Calculate and set chunk length
70
+ # @todo do not count last parameter padding
71
+ # @return [Integer]
72
+ def calc_length
73
+ self.length = to_s(no_padding: true).size
74
+ end
75
+
76
+ private
77
+
78
+ def flags_to_human
79
+ ''
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ require_relative 'parameter'
87
+ require_relative 'error'
88
+
89
+ module PacketGen
90
+ module Header
91
+ class SCTP
92
+ # Embed chunks for a given {SCTP} packet.
93
+ # @author Sylvain Daubert
94
+ class ArrayOfChunk < Types::Array
95
+ set_of BaseChunk
96
+
97
+ private
98
+
99
+ # Get real type from Chunk type
100
+ def real_type(opt)
101
+ type_name = BaseChunk::TYPES.key(opt.type)
102
+ return opt.class if type_name.nil?
103
+
104
+ klass_name = type_name.split('_').map(&:capitalize).join << 'Chunk'
105
+ SCTP.const_get(klass_name) || UnknownChunk
106
+ end
107
+ end
108
+
109
+ # UnknownChunk, used when type cannot be decoded
110
+ # 0 1 2 3
111
+ # 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
112
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
113
+ # | Chunk Type | Chunk Flags | Chunk Length |
114
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115
+ # \ \
116
+ # / Chunk Value /
117
+ # \ \
118
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119
+ # @author Sylvain Daubert
120
+ class UnknownChunk < BaseChunk
121
+ # @!attribute body
122
+ # SCTP chunk value
123
+ # @return [String]
124
+ define_field :body, Types::String, builder: ->(h, t) { t.new(length_from: -> { h.length - 4 }) }
125
+ end
126
+
127
+ # Data chunk
128
+ # 0 1 2 3
129
+ # 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
130
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131
+ # | Type = 0 | Res |I|U|B|E| Length |
132
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133
+ # | TSN |
134
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135
+ # | Stream Identifier S | Stream Sequence Number n |
136
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137
+ # | Payload Protocol Identifier |
138
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139
+ # \ \
140
+ # / User Data (seq n of Stream S) /
141
+ # \ \
142
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143
+ # @author Sylvain Daubert
144
+ class DataChunk < BaseChunk
145
+ # @!attribute tsn
146
+ # 32-bit TSN for this DATA chunk
147
+ # @return [Integer]
148
+ define_field :tsn, Types::Int32
149
+ # @!attribute stream_id
150
+ # 16-bit stream identifier
151
+ # @return [Integer]
152
+ define_field :stream_id, Types::Int16
153
+ # @!attribute stream_sn
154
+ # 16-bit stream sequence number
155
+ # @return [Integer]
156
+ define_field :stream_sn, Types::Int16
157
+ # @!attribute ppid
158
+ # 32-bit payload protocol identifier
159
+ # @return [Integer]
160
+ define_field :ppid, Types::Int32
161
+ # @!attribute body
162
+ # SCTP chunk value
163
+ # @return [String]
164
+ define_field :body, Types::String, builder: ->(h, t) { t.new(length_from: -> { h.length - 4 }) }
165
+
166
+ # @!attribute flag_i
167
+ # IMMEDIATE flag
168
+ # @return [Boolean]
169
+ # @!attribute flag_u
170
+ # UNORDERED flag
171
+ # @return [Boolean]
172
+ # @!attribute flag_b
173
+ # BEGINNING fragment flag
174
+ # @return [Boolean]
175
+ # @!attribute flag_e
176
+ # ENDING fragment flag
177
+ # @return [Boolean]
178
+ define_bit_fields_on :flags, :flag_res, 4, :flag_i, :flag_u, :flag_b, :flag_e
179
+
180
+ private
181
+
182
+ def flags_to_human
183
+ flags = +'....'
184
+ flags[0] = 'i' if flag_i?
185
+ flags[1] = 'u' if flag_u?
186
+ flags[2] = 'b' if flag_b?
187
+ flags[3] = 'e' if flag_e?
188
+ flags
189
+ end
190
+ end
191
+
192
+ # Init Chunk
193
+ # 0 1 2 3
194
+ # 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
195
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
196
+ # | Type = 1 | Chunk Flags | Chunk Length |
197
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
198
+ # | Initiate Tag |
199
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
200
+ # | Advertised Receiver Window Credit (a_rwnd) |
201
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202
+ # | Number of Outbound Streams | Number of Inbound Streams |
203
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204
+ # | Initial TSN |
205
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206
+ # \ \
207
+ # / Optional/Variable-Length Parameters /
208
+ # \ \
209
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210
+ # @author Sylvain Daubert
211
+ class InitChunk < BaseChunk
212
+ # @!attribute initiate_tag
213
+ # 32-bit Initiate Tag
214
+ # @return [Integer]
215
+ define_field :initiate_tag, Types::Int32
216
+ # @!attribute a_wrnd
217
+ # 32-bit Advertised Receiver Window Credit (a_rwnd)
218
+ # @return [Integer]
219
+ define_field :a_rwnd, Types::Int32
220
+ # @!attribute nos
221
+ # 16-bit Number of Outbound Streams
222
+ # @return [Integer]
223
+ define_field :nos, Types::Int16
224
+ # @!attribute nis
225
+ # 16-bit Number of Inbound Streams
226
+ # @return [Integer]
227
+ define_field :nis, Types::Int16
228
+ # @!attribute initial_tsn
229
+ # 32-bit Initial TSN
230
+ # @return [Integer]
231
+ define_field :initial_tsn, Types::Int32
232
+ # @!attribute parameters
233
+ # List of parameters
234
+ # @return [ArrayOfParameter]
235
+ define_field :parameters, ArrayOfParameter
236
+
237
+ def initialize(options={})
238
+ options[:type] = BaseChunk::TYPES['INIT'] unless options.key?(:type)
239
+ super
240
+ end
241
+
242
+ # Calculate lengths, including parameters ones.
243
+ # @return [void]
244
+ def calc_length
245
+ parameters.each(&:calc_length)
246
+ super
247
+ end
248
+
249
+ # @return [::String]
250
+ def to_human
251
+ str = +"<chunk:#{human_type}"
252
+ flags_str = flags_to_human
253
+ str << ",flags:#{flags_str}" unless flags_str.empty?
254
+ str << ",param:#{parameters.map(&:to_human).join(',')}" unless parameters.empty?
255
+ str << '>'
256
+ end
257
+ end
258
+
259
+ # InitAck Chunk
260
+ # 0 1 2 3
261
+ # 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
262
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263
+ # | Type = 1 | Chunk Flags | Chunk Length |
264
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265
+ # | Initiate Tag |
266
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
267
+ # | Advertised Receiver Window Credit (a_rwnd) |
268
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269
+ # | Number of Outbound Streams | Number of Inbound Streams |
270
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
271
+ # | Initial TSN |
272
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
273
+ # \ \
274
+ # / Optional/Variable-Length Parameters /
275
+ # \ \
276
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277
+ # @author Sylvain Daubert
278
+ class InitAckChunk < InitChunk
279
+ def initialize(options={})
280
+ options[:type] = BaseChunk::TYPES['INIT_ACK'] unless options.key?(:type)
281
+ super
282
+ end
283
+ end
284
+
285
+ # Selective Acknowledge Chunk
286
+ # 0 1 2 3
287
+ # 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
288
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
289
+ # | Type = 3 | Chunk Flags | Chunk Length |
290
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
291
+ # | Cumulative TSN Ack |
292
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
293
+ # | Advertised Receiver Window Credit (a_rwnd) |
294
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
295
+ # | Number of Gap Ack Blocks = N | Number of Duplicate TSNs = M |
296
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
297
+ # | Gap Ack Block #1 Start | Gap Ack Block #1 End |
298
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
299
+ # / /
300
+ # \ ... \
301
+ # / /
302
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
303
+ # | Gap Ack Block #N Start | Gap Ack Block #N End |
304
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
305
+ # | Duplicate TSN 1 |
306
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307
+ # / /
308
+ # \ ... \
309
+ # / /
310
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311
+ # | Duplicate TSN M |
312
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
313
+ # @author Sylvain Daubert
314
+ class SackChunk < BaseChunk
315
+ # @!attribute ctsn_ack
316
+ # 32-bit Cumulative TSN Ack
317
+ # @return [Integer]
318
+ define_field :ctsn_ack, Types::Int32
319
+ # @!attribute a_rwnd
320
+ # 32-bit Advertised Receiver Window Credit
321
+ # @return [Integer]
322
+ define_field :a_rwnd, Types::Int32
323
+ # @!attribute num_gap
324
+ # 16-bit Number of Gap Ack Blocks
325
+ # @return [Integer]
326
+ define_field :num_gap, Types::Int32
327
+ # @!attribute num_dup_tsn
328
+ # 16-bit Number of Duplicate TSNs
329
+ # @return [Integer]
330
+ define_field :num_dup_tsn, Types::Int32
331
+ # @!attribute gaps
332
+ # Array of 32-bit Integers, encoding boudaries of a Gap Ack Block.
333
+ # 16 most significant bits encode block start. 16 least significant bits encode block end.
334
+ # @return [Types::ArrayOfInt32]
335
+ define_field :gaps, Types::ArrayOfInt32
336
+ # @!attribute dup_tsns
337
+ # Array of 32-bit Duplicate TSNs.
338
+ # @return [Types::ArrayOfInt32]
339
+ define_field :dup_tsns, Types::ArrayOfInt32
340
+
341
+ def initialize(options={})
342
+ options[:type] = BaseChunk::TYPES['SACK'] unless options.key?(:type)
343
+ super
344
+ end
345
+ end
346
+
347
+ # Heartbeat Request Chunk
348
+ # 0 1 2 3
349
+ # 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
350
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
351
+ # | Type = 4 | Chunk Flags | Heartbeat Length |
352
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
353
+ # \ \
354
+ # / Heartbeat Information TLV (Variable-Length) /
355
+ # \ \
356
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
357
+ # @author Sylvain Daubert
358
+ class HeartbeatChunk < BaseChunk
359
+ # @!attribute info
360
+ # Array of Heartbeat information TLV.
361
+ # @return [Types::ArrayOfInt32]
362
+ define_field :info, HearbeatInfoParameter
363
+
364
+ def initialize(options={})
365
+ options[:type] = BaseChunk::TYPES['HEARTBEAT'] unless options.key?(:type)
366
+ super
367
+ end
368
+ end
369
+
370
+ # Heartbeat Acknoledgement Chunk
371
+ # 0 1 2 3
372
+ # 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
373
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
374
+ # | Type = 4 | Chunk Flags | Heartbeat Length |
375
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
376
+ # \ \
377
+ # / Heartbeat Information TLV (Variable-Length) /
378
+ # \ \
379
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
380
+ # @author Sylvain Daubert
381
+ class HeartbeatAckChunk < HeartbeatChunk
382
+ def initialize(options={})
383
+ options[:type] = BaseChunk::TYPES['HEARTBEAT_ACK'] unless options.key?(:type)
384
+ super
385
+ end
386
+ end
387
+
388
+ # Operation Error Chunk
389
+ # 0 1 2 3
390
+ # 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
391
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
392
+ # | Type = 9 | Chunk Flags | Length |
393
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
394
+ # \ \
395
+ # / zero or more Error Causes /
396
+ # \ \
397
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
398
+ # @author Sylvain Daubert
399
+ class ErrorChunk < BaseChunk
400
+ # @!attribute error_causes
401
+ # @return [ArrayofError]
402
+ define_field :error_causes, ArrayOfError
403
+
404
+ def initialize(options={})
405
+ options[:type] = BaseChunk::TYPES['ERROR'] unless options.key?(:type)
406
+ super
407
+ end
408
+
409
+ # Calculate lengths, including parameters ones.
410
+ # @return [void]
411
+ def calc_length
412
+ error_causes.each(&:calc_length)
413
+ super
414
+ end
415
+
416
+ # @return [::String]
417
+ def to_human
418
+ str = +"<chunk:#{human_type}"
419
+ flags_str = flags_to_human
420
+ str << ",flags:#{flags_str}" unless flags_str.empty?
421
+ str << ",causes:#{error_causes.map(&:to_human).join(',')}" unless error_causes.empty?
422
+ str << '>'
423
+ end
424
+ end
425
+
426
+ # Abort Association Chunk
427
+ # 0 1 2 3
428
+ # 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
429
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
430
+ # | Type = 6 | Reserved |T| Length |
431
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
432
+ # \ \
433
+ # / zero or more Error Causes /
434
+ # \ \
435
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
436
+ # @author Sylvain Daubert
437
+ class AbortChunk < ErrorChunk
438
+ # @!attribute flag_t
439
+ # @return [Boolean]
440
+ define_bit_fields_on :flags, :flag_res, 7, :flag_t
441
+
442
+ def initialize(options={})
443
+ options[:type] = BaseChunk::TYPES['ABORT'] unless options.key?(:type)
444
+ super
445
+ end
446
+
447
+ private
448
+
449
+ def flags_to_human
450
+ flag_t? ? 't' : '.'
451
+ end
452
+ end
453
+
454
+ # Shutdown association Chunk
455
+ # 0 1 2 3
456
+ # 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
457
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
458
+ # | Type = 7 | Chunk Flags | Length = 8 |
459
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
460
+ # | Cumulative TSN Ack |
461
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
462
+ # @author Sylvain Daubert
463
+ class ShutdownChunk < BaseChunk
464
+ # @!attribute cstn_ack
465
+ # 32-bit cumulative TSN ack
466
+ # @return [Integer]
467
+ define_field :ctsn_ack, Types::Int32
468
+
469
+ def initialize(options={})
470
+ options[:type] = BaseChunk::TYPES['SHUTDOWN'] unless options.key?(:type)
471
+ options[:length] = 8 unless options.key?(:length)
472
+ super
473
+ end
474
+ end
475
+
476
+ # Shutdown acknowledgement Chunk
477
+ # 0 1 2 3
478
+ # 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
479
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
480
+ # | Type = 8 | Chunk Flags | Length = 4 |
481
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
482
+ # @author Sylvain Daubert
483
+ class ShutdownAckChunk < BaseChunk
484
+ def initialize(options={})
485
+ options[:type] = BaseChunk::TYPES['SHUTDOWN_ACK'] unless options.key?(:type)
486
+ options[:length] = 4 unless options.key?(:length)
487
+ super
488
+ end
489
+ end
490
+
491
+ # Cookie Echo Chunk
492
+ # 0 1 2 3
493
+ # 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
494
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
495
+ # | Type = 10 | Chunk Flags | Length |
496
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
497
+ # / Cookie /
498
+ # \ \
499
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
500
+ # @author Sylvain Daubert
501
+ class CookieEchoChunk < BaseChunk
502
+ # @!attribute cookie
503
+ # @return [String]
504
+ define_field :cookie, Types::String
505
+
506
+ def initialize(options={})
507
+ options[:type] = BaseChunk::TYPES['COOKIE_ECHO'] unless options.key?(:type)
508
+ super
509
+ end
510
+ end
511
+
512
+ # Cookie Acknownledgement Chunk
513
+ # 0 1 2 3
514
+ # 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
515
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
516
+ # | Type = 11 | Chunk Flags | Length |
517
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
518
+ # @author Sylvain Daubert
519
+ class CookieAckChunk < BaseChunk
520
+ def initialize(options={})
521
+ options[:type] = BaseChunk::TYPES['COOKIE_ACK'] unless options.key?(:type)
522
+ options[:length] = 4 unless options.key?(:length)
523
+ super
524
+ end
525
+ end
526
+
527
+ # Shutdown Complete Chunk
528
+ # 0 1 2 3
529
+ # 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
530
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
531
+ # | Type = 14 | Reserved |T| Length = 4 |
532
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
533
+ # @author Sylvain Daubert
534
+ class ShutdownCompleteChunk < BaseChunk
535
+ # @!attribute flag_t
536
+ # @return [Boolean]
537
+ define_bit_fields_on :flags, :flag_res, 7, :flag_t
538
+
539
+ def initialize(options={})
540
+ options[:type] = BaseChunk::TYPES['SHUTDOWN_COMPLETE'] unless options.key?(:type)
541
+ options[:length] = 4 unless options.key?(:length)
542
+ super
543
+ end
544
+ end
545
+ end
546
+ end
547
+ end