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,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