Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-sctp.c
Line
Count
Source
1
/* packet-sctp.c
2
 * Routines for Stream Control Transmission Protocol dissection
3
 * Copyright 2000-2012 Michael Tuexen <tuexen [AT] fh-muenster.de>
4
 * Copyright 2011-2021 Thomas Dreibholz <dreibh [AT] iem.uni-due.de>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
/*
13
 * It should be compliant to
14
 * - RFC 2960
15
 * - RFC 3309
16
 * - RFC 3758
17
 * - RFC 4460
18
 * - RFC 4895
19
 * - RFC 4960
20
 * - RFC 5061
21
 * - RFC 6525
22
 * - RFC 7053
23
 * - https://tools.ietf.org/html/draft-stewart-sctp-pktdrprep-02
24
 * - https://www.ietf.org/archive/id/draft-ietf-tsvwg-sctp-zero-checksum-01.html
25
 * - https://www.ietf.org/archive/id/draft-ietf-tsvwg-sctp-dtls-chunk-03.html
26
 *
27
 * Still to do (so stay tuned)
28
 * - error checking mode
29
 *   * padding errors
30
 *   * length errors
31
 *   * bundling errors
32
 *   * value errors
33
 *
34
 * Reassembly added 2006 by Robin Seggelmann
35
 * TSN Tracking by Luis E. G. Ontanon (Feb 2007)
36
 * Copyright 2009, Varun Notibala <nbvarun [AT] gmail.com>
37
 *
38
 * PPID types updated by Thomas Dreibholz (Feb 2011)
39
 */
40
41
#include "config.h"
42
0
#define WS_LOG_DOMAIN "sctp"
43
44
#include <wireshark.h>
45
46
#include <epan/packet.h>
47
#include <epan/capture_dissectors.h>
48
#include <epan/prefs.h>
49
#include <epan/exceptions.h>
50
#include <epan/exported_pdu.h>
51
#include <epan/addr_resolv.h>
52
#include <epan/uat.h>
53
#include <epan/expert.h>
54
#include <epan/conversation_table.h>
55
#include <epan/show_exception.h>
56
#include <epan/decode_as.h>
57
#include <epan/proto_data.h>
58
#include <epan/tfs.h>
59
#include <epan/iana-info.h>
60
#include <wsutil/array.h>
61
62
#include <wsutil/crc32.h>
63
#include <wsutil/adler32.h>
64
#include <wsutil/utf8_entities.h>
65
#include <wsutil/str_util.h>
66
#include <wsutil/ws_roundup.h>
67
68
#include "packet-sctp.h"
69
70
 /*
71
  * Based on https://www.iana.org/assignments/sctp-parameters/sctp-parameters.xhtml
72
  * as of February 22, 2021
73
  */
74
static const value_string sctp_payload_proto_id_values[] = {
75
  { NOT_SPECIFIED_PROTOCOL_ID,                      "not specified" },
76
  { IUA_PAYLOAD_PROTOCOL_ID,                        "IUA" },
77
  { M2UA_PAYLOAD_PROTOCOL_ID,                       "M2UA" },
78
  { M3UA_PAYLOAD_PROTOCOL_ID,                       "M3UA" },
79
  { SUA_PAYLOAD_PROTOCOL_ID,                        "SUA" },
80
  { M2PA_PAYLOAD_PROTOCOL_ID,                       "M2PA" },
81
  { V5UA_PAYLOAD_PROTOCOL_ID,                       "V5UA" },
82
  { H248_PAYLOAD_PROTOCOL_ID,                       "H.248/MEGACO" },
83
  { BICC_PAYLOAD_PROTOCOL_ID,                       "BICC/Q.2150.3" },
84
  { TALI_PAYLOAD_PROTOCOL_ID,                       "TALI" },
85
  { DUA_PAYLOAD_PROTOCOL_ID,                        "DUA" },
86
  { ASAP_PAYLOAD_PROTOCOL_ID,                       "ASAP" },
87
  { ENRP_PAYLOAD_PROTOCOL_ID,                       "ENRP" },
88
  { H323_PAYLOAD_PROTOCOL_ID,                       "H.323" },
89
  { QIPC_PAYLOAD_PROTOCOL_ID,                       "Q.IPC/Q.2150.3" },
90
  { SIMCO_PAYLOAD_PROTOCOL_ID,                      "SIMCO" },
91
  { DDP_SEG_CHUNK_PROTOCOL_ID,                      "DDP Segment Chunk" },
92
  { DDP_STREAM_SES_CTRL_PROTOCOL_ID,                "DDP Stream Session Control" },
93
  { S1AP_PAYLOAD_PROTOCOL_ID,                       "S1 Application Protocol (S1AP)" },
94
  { RUA_PAYLOAD_PROTOCOL_ID,                        "RUA" },
95
  { HNBAP_PAYLOAD_PROTOCOL_ID,                      "HNBAP" },
96
  { FORCES_HP_PAYLOAD_PROTOCOL_ID,                  "ForCES-HP" },
97
  { FORCES_MP_PAYLOAD_PROTOCOL_ID,                  "ForCES-MP" },
98
  { FORCES_LP_PAYLOAD_PROTOCOL_ID,                  "ForCES-LP" },
99
  { SBC_AP_PAYLOAD_PROTOCOL_ID,                     "SBc-AP" },
100
  { NBAP_PAYLOAD_PROTOCOL_ID,                       "NBAP" },
101
  { 26,                                             "Unassigned" },     /* Unassigned 26 */
102
  { X2AP_PAYLOAD_PROTOCOL_ID,                       "X2AP" },
103
  { IRCP_PAYLOAD_PROTOCOL_ID,                       "IRCP" },
104
  { LCS_AP_PAYLOAD_PROTOCOL_ID,                     "LCS-AP" },
105
  { MPICH2_PAYLOAD_PROTOCOL_ID,                     "MPICH2" },
106
  { SABP_PAYLOAD_PROTOCOL_ID,                       "SABP" },
107
  { FGP_PAYLOAD_PROTOCOL_ID,                        "Fractal Generator Protocol" },
108
  { PPP_PAYLOAD_PROTOCOL_ID,                        "Ping Pong Protocol" },
109
  { CALCAPP_PAYLOAD_PROTOCOL_ID,                    "CalcApp Protocol" },
110
  { SSP_PAYLOAD_PROTOCOL_ID,                        "Scripting Service Protocol" },
111
  { NPMP_CTRL_PAYLOAD_PROTOCOL_ID,                  "NetPerfMeter Control" },
112
  { NPMP_DATA_PAYLOAD_PROTOCOL_ID,                  "NetPerfMeter Data" },
113
  { ECHO_PAYLOAD_PROTOCOL_ID,                       "Echo" },
114
  { DISCARD_PAYLOAD_PROTOCOL_ID,                    "Discard" },
115
  { DAYTIME_PAYLOAD_PROTOCOL_ID,                    "Daytime" },
116
  { CHARGEN_PAYLOAD_PROTOCOL_ID,                    "Character Generator" },
117
  { PROTO_3GPP_RNA_PROTOCOL_ID,                     "3GPP RNA" },
118
  { PROTO_3GPP_M2AP_PROTOCOL_ID,                    "3GPP M2AP" },
119
  { PROTO_3GPP_M3AP_PROTOCOL_ID,                    "3GPP M3AP" },
120
  { SSH_PAYLOAD_PROTOCOL_ID,                        "SSH" },
121
  { DIAMETER_PROTOCOL_ID,                           "DIAMETER" },
122
  { DIAMETER_DTLS_PROTOCOL_ID,                      "DIAMETER over DTLS" },
123
  { R14P_BER_PROTOCOL_ID,                           "R14P" },
124
  { GDT_PROTOCOL_ID,                                "Generic Data Transfer Protocol (GDT)" },
125
  { WEBRTC_DCEP_PROTOCOL_ID,                        "WebRTC Control" },
126
  { WEBRTC_STRING_PAYLOAD_PROTOCOL_ID,              "WebRTC String" },
127
  { WEBRTC_BINARY_PARTIAL_PAYLOAD_PROTOCOL_ID,      "WebRTC Binary Partial (Deprecated)" },
128
  { WEBRTC_BINARY_PAYLOAD_PROTOCOL_ID,              "WebRTC Binary" },
129
  { WEBRTC_STRING_PARTIAL_PAYLOAD_PROTOCOL_ID,      "WebRTC String Partial (Deprecated)" },
130
  { PROTO_3GPP_PUA_PAYLOAD_PROTOCOL_ID,             "3GPP PUA" },
131
  { WEBRTC_STRING_EMPTY_PAYLOAD_PROTOCOL_ID,        "WebRTC String Empty" },
132
  { WEBRTC_BINARY_EMPTY_PAYLOAD_PROTOCOL_ID,        "WebRTC Binary Empty" },
133
  { XWAP_PROTOCOL_ID,                               "XwAP" },
134
  { XW_CONTROL_PLANE_PROTOCOL_ID,                   "Xw - Control Plane" },
135
  { NGAP_PROTOCOL_ID,                               "NGAP" },
136
  { XNAP_PROTOCOL_ID,                               "XnAP" },
137
  { F1AP_PROTOCOL_ID,                               "F1 AP" },
138
  { ELE2_PROTOCOL_ID,                               "ELE2 Lawful Interception" },
139
  { NGAP_OVER_DTLS_PROTOCOL_ID,                     "NGAP over DTLS" },
140
  { XNAP_OVER_DTLS_PROTOCOL_ID,                     "XnAP over DTLS" },
141
  { F1AP_OVER_DTLS_PROTOCOL_ID,                     "F1AP over DTLS" },
142
  { E1AP_OVER_DTLS_PROTOCOL_ID,                     "E1AP over DTLS" },
143
  { E2_CP_PROTOCOL_ID,                              "E2-CP" },
144
  { E2_UP_PROTOCOL_ID,                              "E2-UP" },
145
  { E2_DU_PROTOCOL_ID,                              "E2-DU" },
146
  { W1AP_PROTOCOL_ID,                               "W1AP" },
147
  { DTLS_CHUNK_KM_MESSAGES_PAYLOAD_PROTOCOL_ID,     "DTLS chunk KM" },
148
149
  { 0,                                              NULL } };
150
151
152
value_string_ext sctpppid_val_ext = VALUE_STRING_EXT_INIT(sctp_payload_proto_id_values);
153
154
#define LT(x, y) ((int32_t)((x) - (y)) < 0)
155
156
32
#define UDP_TUNNELING_PORT 9899
157
158
99.1k
#define MAX_NUMBER_OF_PPIDS     2
159
/** This is a valid PPID, but we use it to mark the end of the list */
160
39.0k
#define LAST_PPID 0xffffffff
161
162
void proto_register_sctp(void);
163
void proto_reg_handoff_sctp(void);
164
165
/* Initialize the protocol and registered fields */
166
static int proto_sctp;
167
static int hf_port;
168
static int hf_source_port;
169
static int hf_destination_port;
170
static int hf_verification_tag;
171
static int hf_checksum;
172
static int hf_checksum_adler;
173
static int hf_checksum_crc32c;
174
static int hf_checksum_status;
175
176
static int hf_chunk;
177
static int hf_chunk_type;
178
static int hf_chunk_flags;
179
static int hf_chunk_bit_1;
180
static int hf_chunk_bit_2;
181
static int hf_chunk_length;
182
static int hf_chunk_padding;
183
static int hf_chunk_value;
184
185
static int hf_initiate_tag;
186
static int hf_init_chunk_initiate_tag;
187
static int hf_init_chunk_adv_rec_window_credit;
188
static int hf_init_chunk_number_of_outbound_streams;
189
static int hf_init_chunk_number_of_inbound_streams;
190
static int hf_init_chunk_initial_tsn;
191
192
static int hf_initack_chunk_initiate_tag;
193
static int hf_initack_chunk_adv_rec_window_credit;
194
static int hf_initack_chunk_number_of_outbound_streams;
195
static int hf_initack_chunk_number_of_inbound_streams;
196
static int hf_initack_chunk_initial_tsn;
197
198
static int hf_data_chunk_tsn;
199
static int hf_data_chunk_tsn_raw;
200
static int hf_data_chunk_stream_id;
201
static int hf_data_chunk_stream_seq_number;
202
static int hf_data_chunk_payload_proto_id;
203
static int hf_idata_chunk_reserved;
204
static int hf_idata_chunk_mid;
205
static int hf_idata_chunk_fsn;
206
207
static int hf_data_chunk_e_bit;
208
static int hf_data_chunk_b_bit;
209
static int hf_data_chunk_u_bit;
210
static int hf_data_chunk_i_bit;
211
212
static int hf_sack_chunk_ns;
213
static int hf_sack_chunk_cumulative_tsn_ack;
214
static int hf_sack_chunk_cumulative_tsn_ack_raw;
215
static int hf_sack_chunk_adv_rec_window_credit;
216
static int hf_sack_chunk_number_of_gap_blocks;
217
static int hf_sack_chunk_number_of_dup_tsns;
218
static int hf_sack_chunk_gap_block_start;
219
static int hf_sack_chunk_gap_block_end;
220
static int hf_sack_chunk_gap_block_start_tsn;
221
static int hf_sack_chunk_gap_block_end_tsn;
222
static int hf_sack_chunk_number_tsns_gap_acked;
223
static int hf_sack_chunk_duplicate_tsn;
224
225
static int hf_nr_sack_chunk_ns;
226
static int hf_nr_sack_chunk_cumulative_tsn_ack;
227
static int hf_nr_sack_chunk_adv_rec_window_credit;
228
static int hf_nr_sack_chunk_number_of_gap_blocks;
229
static int hf_nr_sack_chunk_number_of_nr_gap_blocks;
230
static int hf_nr_sack_chunk_number_of_dup_tsns;
231
static int hf_nr_sack_chunk_reserved;
232
static int hf_nr_sack_chunk_gap_block_start;
233
static int hf_nr_sack_chunk_gap_block_end;
234
static int hf_nr_sack_chunk_gap_block_start_tsn;
235
static int hf_nr_sack_chunk_gap_block_end_tsn;
236
static int hf_nr_sack_chunk_number_tsns_gap_acked;
237
static int hf_nr_sack_chunk_nr_gap_block_start;
238
static int hf_nr_sack_chunk_nr_gap_block_end;
239
static int hf_nr_sack_chunk_nr_gap_block_start_tsn;
240
static int hf_nr_sack_chunk_nr_gap_block_end_tsn;
241
static int hf_nr_sack_chunk_number_tsns_nr_gap_acked;
242
static int hf_nr_sack_chunk_duplicate_tsn;
243
244
static int hf_shutdown_chunk_cumulative_tsn_ack;
245
static int hf_cookie;
246
static int hf_cwr_chunk_lowest_tsn;
247
248
static int hf_ecne_chunk_lowest_tsn;
249
static int hf_abort_chunk_t_bit;
250
static int hf_shutdown_complete_chunk_t_bit;
251
252
static int hf_parameter_type;
253
static int hf_parameter_length;
254
static int hf_parameter_value;
255
static int hf_parameter_padding;
256
static int hf_parameter_bit_1;
257
static int hf_parameter_bit_2;
258
static int hf_ipv4_address;
259
static int hf_ipv6_address;
260
static int hf_heartbeat_info;
261
static int hf_state_cookie;
262
static int hf_cookie_preservative_increment;
263
static int hf_hostname;
264
static int hf_supported_address_type;
265
static int hf_stream_reset_req_seq_nr;
266
static int hf_stream_reset_rsp_seq_nr;
267
static int hf_senders_last_assigned_tsn;
268
static int hf_senders_next_tsn;
269
static int hf_receivers_next_tsn;
270
static int hf_stream_reset_rsp_result;
271
static int hf_stream_reset_sid;
272
static int hf_add_outgoing_streams_number_streams;
273
static int hf_add_outgoing_streams_reserved;
274
static int hf_add_incoming_streams_number_streams;
275
static int hf_add_incoming_streams_reserved;
276
277
static int hf_zero_checksum_edmid;
278
279
static int hf_random_number;
280
static int hf_chunks_to_auth;
281
static int hf_hmac_id;
282
static int hf_hmac;
283
static int hf_shared_key_id;
284
static int hf_supported_chunk_type;
285
286
static int hf_dtls_km_tiebreaker;
287
static int hf_dtls_km_flags;
288
static int hf_dtls_km_c_bit;
289
static int hf_dtls_km_s_bit;
290
static int hf_dtls_km_r_bit;
291
static int hf_dtls_km_id;
292
293
static int hf_cause_code;
294
static int hf_cause_length;
295
static int hf_cause_padding;
296
static int hf_cause_info;
297
298
static int hf_cause_stream_identifier;
299
static int hf_cause_reserved;
300
301
static int hf_cause_number_of_missing_parameters;
302
static int hf_cause_missing_parameter_type;
303
304
static int hf_cause_measure_of_staleness;
305
306
static int hf_cause_tsn;
307
308
static int hf_forward_tsn_chunk_tsn;
309
static int hf_forward_tsn_chunk_sid;
310
static int hf_forward_tsn_chunk_ssn;
311
312
static int hf_i_forward_tsn_chunk_tsn;
313
static int hf_i_forward_tsn_chunk_sid;
314
static int hf_i_forward_tsn_chunk_flags;
315
static int hf_i_forward_tsn_chunk_res;
316
static int hf_i_forward_tsn_chunk_u_bit;
317
static int hf_i_forward_tsn_chunk_mid;
318
319
static int hf_asconf_ack_seq_nr;
320
static int hf_asconf_seq_nr;
321
static int hf_correlation_id;
322
323
static int hf_dtls_chunk_r_bit;
324
325
static int hf_adap_indication;
326
327
static int hf_pktdrop_chunk_m_bit;
328
static int hf_pktdrop_chunk_b_bit;
329
static int hf_pktdrop_chunk_t_bit;
330
static int hf_pktdrop_chunk_bandwidth;
331
static int hf_pktdrop_chunk_queuesize;
332
static int hf_pktdrop_chunk_truncated_length;
333
static int hf_pktdrop_chunk_reserved;
334
static int hf_pktdrop_chunk_data_field;
335
336
static int hf_pad_chunk_padding_data;
337
338
static int hf_sctp_reassembled_in;
339
static int hf_sctp_duplicate;
340
static int hf_sctp_fragments;
341
static int hf_sctp_fragment;
342
343
static int hf_sctp_retransmission;
344
static int hf_sctp_retransmitted;
345
static int hf_sctp_retransmitted_count;
346
static int hf_sctp_data_rtt;
347
static int hf_sctp_sack_rtt;
348
static int hf_sctp_rto;
349
static int hf_sctp_ack_tsn;
350
static int hf_sctp_ack_frame;
351
static int hf_sctp_acked;
352
static int hf_sctp_retransmitted_after_ack;
353
354
static int hf_sctp_assoc_index;
355
356
static dissector_table_t sctp_port_dissector_table;
357
static dissector_table_t sctp_ppi_dissector_table;
358
static heur_dissector_list_t sctp_heur_subdissector_list;
359
static int sctp_tap;
360
static int exported_pdu_tap;
361
362
/* Initialize the subtree pointers */
363
static int ett_sctp;
364
static int ett_sctp_chunk;
365
static int ett_sctp_chunk_parameter;
366
static int ett_sctp_chunk_cause;
367
static int ett_sctp_chunk_type;
368
static int ett_sctp_data_chunk_flags;
369
static int ett_sctp_sack_chunk_flags;
370
static int ett_sctp_nr_sack_chunk_flags;
371
static int ett_sctp_abort_chunk_flags;
372
static int ett_sctp_shutdown_complete_chunk_flags;
373
static int ett_sctp_pktdrop_chunk_flags;
374
static int ett_sctp_parameter_type;
375
static int ett_sctp_sack_chunk_gap_block;
376
static int ett_sctp_sack_chunk_gap_block_start;
377
static int ett_sctp_sack_chunk_gap_block_end;
378
static int ett_sctp_nr_sack_chunk_gap_block;
379
static int ett_sctp_nr_sack_chunk_gap_block_start;
380
static int ett_sctp_nr_sack_chunk_gap_block_end;
381
static int ett_sctp_nr_sack_chunk_nr_gap_block;
382
static int ett_sctp_nr_sack_chunk_nr_gap_block_start;
383
static int ett_sctp_nr_sack_chunk_nr_gap_block_end;
384
static int ett_sctp_unrecognized_parameter_parameter;
385
static int ett_sctp_i_forward_tsn_chunk_flags;
386
static int ett_sctp_dtls_chunk_flags;
387
388
static int ett_sctp_fragments;
389
static int ett_sctp_fragment;
390
391
static int ett_sctp_tsn;
392
static int ett_sctp_ack;
393
static int ett_sctp_acked;
394
static int ett_sctp_tsn_retransmission;
395
static int ett_sctp_tsn_retransmitted_count;
396
static int ett_sctp_tsn_retransmitted;
397
398
static int ett_sctp_dtls_km_flags;
399
static expert_field ei_sctp_sack_chunk_adv_rec_window_credit;
400
static expert_field ei_sctp_nr_sack_chunk_number_tsns_gap_acked_100;
401
static expert_field ei_sctp_parameter_length;
402
static expert_field ei_sctp_bad_sctp_checksum;
403
static expert_field ei_sctp_tsn_retransmitted_more_than_twice;
404
static expert_field ei_sctp_parameter_padding;
405
static expert_field ei_sctp_retransmitted_after_ack;
406
static expert_field ei_sctp_nr_sack_chunk_number_tsns_nr_gap_acked_100;
407
static expert_field ei_sctp_sack_chunk_gap_block_out_of_order;
408
static expert_field ei_sctp_chunk_length_bad;
409
static expert_field ei_sctp_tsn_retransmitted;
410
static expert_field ei_sctp_sack_chunk_gap_block_malformed;
411
static expert_field ei_sctp_sack_chunk_number_tsns_gap_acked_100;
412
static expert_field ei_sctp_illegal_parameter_occurrence;
413
static expert_field ei_sctp_dtls_km_illegal_number_of_ids;
414
415
static const value_string chunk_type_values[] = {
416
  { SCTP_DATA_CHUNK_ID,              "DATA" },
417
  { SCTP_INIT_CHUNK_ID,              "INIT" },
418
  { SCTP_INIT_ACK_CHUNK_ID,          "INIT_ACK" },
419
  { SCTP_SACK_CHUNK_ID,              "SACK" },
420
  { SCTP_HEARTBEAT_CHUNK_ID,         "HEARTBEAT" },
421
  { SCTP_HEARTBEAT_ACK_CHUNK_ID,     "HEARTBEAT_ACK" },
422
  { SCTP_ABORT_CHUNK_ID,             "ABORT" },
423
  { SCTP_SHUTDOWN_CHUNK_ID,          "SHUTDOWN" },
424
  { SCTP_SHUTDOWN_ACK_CHUNK_ID,      "SHUTDOWN_ACK" },
425
  { SCTP_ERROR_CHUNK_ID,             "ERROR" },
426
  { SCTP_COOKIE_ECHO_CHUNK_ID,       "COOKIE_ECHO" },
427
  { SCTP_COOKIE_ACK_CHUNK_ID,        "COOKIE_ACK" },
428
  { SCTP_ECNE_CHUNK_ID,              "ECNE" },
429
  { SCTP_CWR_CHUNK_ID,               "CWR" },
430
  { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" },
431
  { SCTP_AUTH_CHUNK_ID,              "AUTH" },
432
  { SCTP_NR_SACK_CHUNK_ID,           "NR_SACK" },
433
  { SCTP_I_DATA_CHUNK_ID,            "I_DATA" },
434
  { SCTP_DTLS_CHUNK_ID,              "DTLS" },
435
  { SCTP_ASCONF_ACK_CHUNK_ID,        "ASCONF_ACK" },
436
  { SCTP_PKTDROP_CHUNK_ID,           "PKTDROP" },
437
  { SCTP_RE_CONFIG_CHUNK_ID,         "RE_CONFIG" },
438
  { SCTP_PAD_CHUNK_ID,               "PAD" },
439
  { SCTP_FORWARD_TSN_CHUNK_ID,       "FORWARD_TSN" },
440
  { SCTP_ASCONF_CHUNK_ID,            "ASCONF" },
441
  { SCTP_I_FORWARD_TSN_CHUNK_ID,     "I_FORWARD_TSN" },
442
  { SCTP_IETF_EXT,                   "IETF_EXTENSION" },
443
  { 0,                               NULL } };
444
445
446
774k
#define CHUNK_TYPE_LENGTH             1U
447
622k
#define CHUNK_FLAGS_LENGTH            1U
448
445k
#define CHUNK_LENGTH_LENGTH           2U
449
147k
#define CHUNK_HEADER_LENGTH           (CHUNK_TYPE_LENGTH + \
450
147k
                                       CHUNK_FLAGS_LENGTH + \
451
147k
                                       CHUNK_LENGTH_LENGTH)
452
711k
#define CHUNK_HEADER_OFFSET           0
453
655k
#define CHUNK_TYPE_OFFSET             CHUNK_HEADER_OFFSET
454
509k
#define CHUNK_FLAGS_OFFSET            (CHUNK_TYPE_OFFSET + CHUNK_TYPE_LENGTH)
455
371k
#define CHUNK_LENGTH_OFFSET           (CHUNK_FLAGS_OFFSET + CHUNK_FLAGS_LENGTH)
456
261k
#define CHUNK_VALUE_OFFSET            (CHUNK_LENGTH_OFFSET + CHUNK_LENGTH_LENGTH)
457
458
2.91k
#define PARAMETER_TYPE_LENGTH            2
459
1.07k
#define PARAMETER_LENGTH_LENGTH          2
460
310
#define PARAMETER_HEADER_LENGTH          (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH)
461
462
3.50k
#define PARAMETER_HEADER_OFFSET          0
463
3.09k
#define PARAMETER_TYPE_OFFSET            PARAMETER_HEADER_OFFSET
464
1.65k
#define PARAMETER_LENGTH_OFFSET          (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH)
465
445
#define PARAMETER_VALUE_OFFSET           (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH)
466
467
432k
#define SOURCE_PORT_LENGTH      2
468
305k
#define DESTINATION_PORT_LENGTH 2
469
178k
#define VERIFICATION_TAG_LENGTH 4
470
71.3k
#define CHECKSUM_LENGTH         4
471
71.3k
#define COMMON_HEADER_LENGTH    (SOURCE_PORT_LENGTH + \
472
71.3k
                                 DESTINATION_PORT_LENGTH + \
473
71.3k
                                 VERIFICATION_TAG_LENGTH + \
474
71.3k
                                 CHECKSUM_LENGTH)
475
416k
#define SOURCE_PORT_OFFSET      0
476
289k
#define DESTINATION_PORT_OFFSET (SOURCE_PORT_OFFSET + SOURCE_PORT_LENGTH)
477
162k
#define VERIFICATION_TAG_OFFSET (DESTINATION_PORT_OFFSET + DESTINATION_PORT_LENGTH)
478
71.3k
#define CHECKSUM_OFFSET         (VERIFICATION_TAG_OFFSET + VERIFICATION_TAG_LENGTH)
479
480
71.3k
#define SCTP_CHECKSUM_NONE      0
481
16
#define SCTP_CHECKSUM_ADLER32   1
482
16
#define SCTP_CHECKSUM_CRC32C    2
483
16
#define SCTP_CHECKSUM_AUTOMATIC 3
484
485
#define FORWARD_STREAM                     0
486
#define BACKWARD_STREAM                    1
487
#define FORWARD_ADD_FORWARD_VTAG           2
488
#define BACKWARD_ADD_FORWARD_VTAG          3
489
#define BACKWARD_ADD_BACKWARD_VTAG         4
490
19.9k
#define ASSOC_NOT_FOUND                    5
491
492
/* Default values for preferences */
493
static bool show_port_numbers           = true;
494
static int sctp_checksum               = SCTP_CHECKSUM_NONE;
495
static bool enable_tsn_analysis         = true;
496
static bool enable_association_indexing;
497
static bool enable_ulp_dissection       = true;
498
static bool use_reassembly              = true;
499
static bool show_always_control_chunks  = true;
500
static bool show_relative_tsns          = true;
501
502
/* Data types and functions for generation/handling of chunk types for chunk statistics */
503
504
static const value_string chunk_enabled[] = {
505
  {0,"Show"},
506
  {1,"Hide"},
507
  {0, NULL}
508
};
509
typedef struct _type_field_t {
510
  unsigned type_id;
511
  char* type_name;
512
  unsigned type_enable;
513
} type_field_t;
514
515
static type_field_t* type_fields;
516
static unsigned num_type_fields;
517
518
typedef struct _assoc_info_t {
519
  uint16_t assoc_index;
520
  uint16_t direction;
521
  address saddr;
522
  address daddr;
523
  uint16_t sport;
524
  uint16_t dport;
525
  uint32_t verification_tag1;
526
  uint32_t verification_tag2;
527
} assoc_info_t;
528
529
typedef struct _infodata_t {
530
  uint16_t assoc_index;
531
  uint16_t direction;
532
} infodata_t;
533
534
static wmem_map_t *assoc_info_half_map;
535
static wmem_map_t *assoc_info_map;
536
static unsigned num_assocs;
537
538
0
UAT_CSTRING_CB_DEF(type_fields, type_name, type_field_t)
539
0
UAT_VS_DEF(type_fields, type_enable, type_field_t, unsigned, 0, "Show")
Unexecuted instantiation: packet-sctp.c:type_fields_type_enable_set_cb
Unexecuted instantiation: packet-sctp.c:type_fields_type_enable_tostr_cb
540
0
UAT_DEC_CB_DEF(type_fields, type_id, type_field_t)
Unexecuted instantiation: packet-sctp.c:type_fields_type_id_set_cb
Unexecuted instantiation: packet-sctp.c:type_fields_type_id_tostr_cb
541
542
static void *sctp_chunk_type_copy_cb(void* n, const void* o, size_t siz _U_)
543
0
{
544
0
  type_field_t* new_rec = (type_field_t*)n;
545
0
  const type_field_t* old_rec = (const type_field_t*)o;
546
0
  new_rec->type_name = g_strdup(old_rec->type_name);
547
548
0
  return new_rec;
549
0
}
550
551
static void
552
sctp_chunk_type_free_cb(void* r)
553
0
{
554
0
  type_field_t* rec = (type_field_t*)r;
555
0
  g_free(rec->type_name);
556
0
}
557
558
static bool
559
sctp_chunk_type_update_cb(void *r, char **err)
560
0
{
561
0
  type_field_t *rec = (type_field_t *)r;
562
0
  char c;
563
0
  if (rec->type_name == NULL) {
564
0
    *err = g_strdup("Header name can't be empty");
565
0
    return false;
566
0
  }
567
568
0
  g_strstrip(rec->type_name);
569
0
  if (rec->type_name[0] == 0) {
570
0
    *err = g_strdup("Header name can't be empty");
571
0
    return false;
572
0
  }
573
574
  /* Check for invalid characters (to avoid asserting out when
575
  * registering the field).
576
  */
577
0
  c = proto_check_field_name(rec->type_name);
578
0
  if (c) {
579
0
    *err = ws_strdup_printf("Header name can't contain '%c'", c);
580
0
    return false;
581
0
  }
582
583
0
  *err = NULL;
584
0
  return true;
585
0
}
586
587
static dissector_handle_t sctp_handle;
588
589
static struct _sctp_info sctp_info;
590
591
static bool
592
sctp_vtag_match(uint32_t vtag1, uint32_t vtag2)
593
0
{
594
  /* If zero (unknown) tags match anything. Nonzero tags must be the same. */
595
0
  if (vtag1 != 0) {
596
0
    return (vtag1 == vtag2 || vtag2 == 0);
597
0
  }
598
0
  return true;
599
0
}
600
601
static assoc_info_t*
602
sctp_assoc_reverse(wmem_allocator_t *scope, const assoc_info_t *assoc)
603
0
{
604
0
  assoc_info_t *new_assoc;
605
606
0
  new_assoc = wmem_new(scope, assoc_info_t);
607
0
  new_assoc->assoc_index = assoc->assoc_index;
608
0
  new_assoc->direction = (assoc->direction == 1) ? 2 : 1;
609
0
  copy_address_shallow(&new_assoc->saddr, &assoc->daddr);
610
0
  copy_address_shallow(&new_assoc->daddr, &assoc->saddr);
611
0
  new_assoc->sport = assoc->dport;
612
0
  new_assoc->dport = assoc->sport;
613
0
  new_assoc->verification_tag1 = assoc->verification_tag2;
614
0
  new_assoc->verification_tag2 = assoc->verification_tag1;
615
616
0
  return new_assoc;
617
0
}
618
619
static unsigned
620
sctp_assoc_half_hash(const void *key)
621
0
{
622
0
  const assoc_info_t *k = (const assoc_info_t *)key;
623
624
  /* Add the ports so that the hash is the same regardless of direction */
625
0
  return g_direct_hash(GUINT_TO_POINTER(k->sport + k->dport));
626
0
}
627
628
static unsigned
629
sctp_assoc_hash(const void *key)
630
0
{
631
0
  const assoc_info_t *k = (const assoc_info_t *)key;
632
633
  // When inserting in this map, we know we have both vtags.
634
  // Hash via the first one (we expect vtag collisions will be low.)
635
  // When looking up with a entry from a packet that only has one vtag,
636
  // we'll reverse the temporary key as necessary.
637
0
  return g_int_hash(&k->verification_tag1);
638
0
}
639
640
/* Association comparison strategy:
641
 * 1. Ports MUST match.
642
 * 2. Assume vtag collisions are rare compared to multihoming. Thus:
643
 * 3. If we have already discovered the vtags on both sides (e.g., with an
644
 *    INIT ACK, which contains both sides) and the ports match, don't require
645
 *    address matches.
646
 * 4. If we have two keys each with 1 matching vtag in the same direction (and
647
 *    the other vtag 0), don't require address matches; if there are new addresses
648
 *    assume it's multihoming.
649
 * 5. However, if we have two keys each with 1 vtag (and the other tag 0)
650
 *    that are different but could be the two vtags of one association
651
 *    (e.g., two unmatched DATA chunks in the opposite direction, or an INIT
652
 *    and a DATA in the same direction) require address matching. Otherwise
653
 *    we'll make likely spurious matches.
654
 * 6. Don't worry about odd possibilities like both sides of an association
655
 *    choosing the same vtag.
656
 * 7. We ought to track additional addresses given in INIT, INIT ACK, ASCONF.
657
 *    If we do, we could have an option of more strict association matching
658
 *    that uses the addresses in all cases and is more similar to what SCTP
659
 *    stacks actually do. We'd have to store a list/map/set of known source
660
 *    and destination addresses instead of just one each. This would fail in
661
 *    the case of multihoming and where we missed the configuration messages
662
 *    setting up multihoming.
663
 */
664
665
static gboolean
666
sctp_assoc_half_equal(const void *key1, const void *key2)
667
0
{
668
0
  const assoc_info_t *a = (const assoc_info_t *)key1;
669
0
  const assoc_info_t *b = (const assoc_info_t *)key2;
670
671
  /* Matching for associations where for the entries already in the table
672
   * only have one vtag, and have zero for the other direction. (For an
673
   * new INIT ACK, we know both directions.)
674
   */
675
676
0
  if (a->sport == b->sport && a->dport == b->dport) {
677
    // Forward match
678
0
    if ((a->verification_tag1 == 0 || b->verification_tag1 == 0) &&
679
0
        (a->verification_tag2 == 0 || b->verification_tag2 == 0)) {
680
      // Possible INIT and DATA in the same direction, where we didn't get
681
      // the INIT ACK. Call it a match if the addresses match.
682
0
      if (addresses_equal(&a->saddr, &b->saddr) && addresses_equal(&a->daddr, &b->daddr)) {
683
0
          return TRUE;
684
0
      }
685
0
    } else if (sctp_vtag_match(a->verification_tag1, b->verification_tag1) &&
686
0
        sctp_vtag_match(a->verification_tag2, b->verification_tag2)) {
687
0
      return TRUE;
688
0
    }
689
0
  }
690
0
  if (a->sport == b->dport && a->dport == b->sport) {
691
    // Reverse direction (not an else so we can handle identical ports)
692
0
    if ((a->verification_tag1 == 0 || b->verification_tag2 == 0) &&
693
0
        (a->verification_tag2 == 0 || b->verification_tag1 == 0)) {
694
      // Possible two DATAs chunks in the opposite direction, where we
695
      // didn't get the INIT ACK. Call it a match if the addresses match.
696
0
      if (addresses_equal(&a->saddr, &b->daddr) && addresses_equal(&a->daddr, &b->saddr)) {
697
0
          return TRUE;
698
0
      }
699
0
    } else if (sctp_vtag_match(a->verification_tag1, b->verification_tag2) &&
700
0
        sctp_vtag_match(a->verification_tag2, b->verification_tag1)) {
701
0
      return TRUE;
702
0
    }
703
0
  }
704
705
0
  return FALSE;
706
0
}
707
708
static gboolean
709
sctp_assoc_equal(const void *key1, const void *key2)
710
0
{
711
0
  const assoc_info_t *a = (const assoc_info_t *)key1;
712
0
  const assoc_info_t *b = (const assoc_info_t *)key2;
713
714
  /*
715
   * Matching for associations where for the entries already in the map
716
   * we know the vtags in each direction.
717
   * We will not check addresses.
718
   */
719
720
0
  if (a->sport == b->sport && a->dport == b->dport) {
721
    // Forward match
722
    // ASSERTION: at least one of the verification tags must be nonzero.
723
0
    if (sctp_vtag_match(a->verification_tag1, b->verification_tag1) &&
724
0
        sctp_vtag_match(a->verification_tag2, b->verification_tag2)) {
725
0
      return TRUE;
726
0
    }
727
0
  }
728
0
  if (a->sport == b->dport && a->dport == b->sport) {
729
    // Reverse direction (not an else so we can handle identical ports)
730
0
    if (sctp_vtag_match(a->verification_tag1, b->verification_tag2) &&
731
0
        sctp_vtag_match(a->verification_tag2, b->verification_tag1)) {
732
0
      return TRUE;
733
0
    }
734
0
  }
735
736
0
  return FALSE;
737
0
}
738
739
static infodata_t
740
find_assoc_index(assoc_info_t* tmpinfo, packet_info *pinfo)
741
0
{
742
0
  assoc_info_t *info = NULL;
743
0
  infodata_t inf;
744
0
  inf.assoc_index = -1;
745
0
  inf.direction = 1;
746
747
  /* At least one of tmpinfo's vtag1 must be nonzero (both might be, if
748
   * it's an INIT ACK.) Lookup in the proper direction(s).
749
   */
750
0
  if (tmpinfo->verification_tag1 != 0) {
751
0
    info = (assoc_info_t*)wmem_map_lookup(assoc_info_map, tmpinfo);
752
0
    if (info) {
753
0
      inf.assoc_index = info->assoc_index;
754
0
      inf.direction = info->direction;
755
0
      return inf;
756
0
    }
757
0
  }
758
759
0
  if (tmpinfo->verification_tag2 != 0) {
760
0
    info = sctp_assoc_reverse(pinfo->pool, tmpinfo);
761
0
    info = (assoc_info_t*)wmem_map_lookup(assoc_info_map, info);
762
0
    if (info) {
763
0
      inf.assoc_index = info->assoc_index;
764
0
      inf.direction = info->direction == 1 ? 2 : 1;
765
0
      return inf;
766
0
    }
767
0
  }
768
769
0
  info = (assoc_info_t*)wmem_map_lookup(assoc_info_half_map, tmpinfo);
770
0
  if (info == NULL) {
771
0
    if (!PINFO_FD_VISITED(pinfo)) {
772
0
      info = wmem_new(wmem_file_scope(), assoc_info_t);
773
0
      *info = *tmpinfo;
774
0
      copy_address_wmem(wmem_file_scope(), &info->saddr, &tmpinfo->saddr);
775
0
      copy_address_wmem(wmem_file_scope(), &info->daddr, &tmpinfo->daddr);
776
0
      info->assoc_index = num_assocs++;
777
0
      info->direction = 1;
778
0
      inf.assoc_index = info->assoc_index;
779
0
      if (info->verification_tag1 == 0 || info->verification_tag2 == 0) {
780
0
        wmem_map_insert(assoc_info_half_map, info, info);
781
0
      } else {
782
0
        info->direction = 1;
783
0
        wmem_map_insert(assoc_info_map, info, info);
784
0
        info = sctp_assoc_reverse(wmem_file_scope(), info);
785
0
        wmem_map_insert(assoc_info_map, info, info);
786
0
      }
787
0
    } else {
788
0
      ws_info("association not found on second pass");
789
0
    }
790
0
  } else {
791
0
    inf.assoc_index = info->assoc_index;
792
    /* Now figure out why we matched and fill in new information. */
793
0
    if (info->sport == tmpinfo->dport &&
794
0
        sctp_vtag_match(info->verification_tag1, tmpinfo->verification_tag1) &&
795
0
        sctp_vtag_match(info->verification_tag2, tmpinfo->verification_tag2)) {
796
      /* We already checked the addresses if needed when looking up in the map. */
797
0
      if (info->verification_tag1 == 0) {
798
0
        info->verification_tag1 = tmpinfo->verification_tag1;
799
0
      }
800
0
      if (info->verification_tag2 == 0) {
801
0
        info->verification_tag2 = tmpinfo->verification_tag2;
802
0
      }
803
0
    } else if (sctp_vtag_match(info->verification_tag1, tmpinfo->verification_tag2) &&
804
0
        sctp_vtag_match(info->verification_tag2, tmpinfo->verification_tag1)) {
805
      /* We already checked the addresses if needed when looking up in the map. */
806
0
      inf.direction = 2;
807
0
      if (info->verification_tag1 == 0) {
808
0
        info->verification_tag1 = tmpinfo->verification_tag2;
809
0
      }
810
0
      if (info->verification_tag2 == 0) {
811
0
        info->verification_tag2 = tmpinfo->verification_tag1;
812
0
      }
813
0
    }
814
0
    if (info->verification_tag1 != 0 && info->verification_tag2 != 0) {
815
0
      DISSECTOR_ASSERT(wmem_map_remove(assoc_info_half_map, info) != NULL);
816
0
      wmem_map_insert(assoc_info_map, info, info);
817
0
      info = sctp_assoc_reverse(wmem_file_scope(), info);
818
0
      wmem_map_insert(assoc_info_map, info, info);
819
0
    }
820
0
  }
821
822
0
  return inf;
823
0
}
824
825
static void
826
sctp_src_prompt(packet_info *pinfo, char *result)
827
0
{
828
0
    uint32_t port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_source_port, pinfo->curr_layer_num));
829
830
0
    snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "source (%s%u)", UTF8_RIGHTWARDS_ARROW, port);
831
0
}
832
833
static void *
834
sctp_src_value(packet_info *pinfo)
835
0
{
836
0
    return p_get_proto_data(pinfo->pool, pinfo, hf_source_port, pinfo->curr_layer_num);
837
0
}
838
839
static void
840
sctp_dst_prompt(packet_info *pinfo, char *result)
841
0
{
842
0
    uint32_t port = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_destination_port, pinfo->curr_layer_num));
843
844
0
    snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "destination (%s%u)", UTF8_RIGHTWARDS_ARROW, port);
845
0
}
846
847
static void *
848
sctp_dst_value(packet_info *pinfo)
849
0
{
850
0
    return p_get_proto_data(pinfo->pool, pinfo, hf_destination_port, pinfo->curr_layer_num);
851
0
}
852
853
static void
854
sctp_both_prompt(packet_info *pinfo, char *result)
855
0
{
856
0
    uint32_t srcport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_source_port, pinfo->curr_layer_num)),
857
0
            destport = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, hf_destination_port, pinfo->curr_layer_num));
858
859
0
    snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "both (%u%s%u)", srcport, UTF8_LEFT_RIGHT_ARROW, destport);
860
0
}
861
862
static void
863
sctp_ppi_prompt1(packet_info *pinfo _U_, char* result)
864
0
{
865
0
    uint32_t ppid = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_sctp, 0));
866
867
0
    if (ppid == LAST_PPID) {
868
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "PPID (none)");
869
0
    } else {
870
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "PPID (%d)", ppid);
871
0
    }
872
0
}
873
874
static void
875
sctp_ppi_prompt2(packet_info *pinfo _U_, char* result)
876
0
{
877
0
    uint32_t ppid = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_sctp, 1));
878
879
0
    if (ppid == LAST_PPID) {
880
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "PPID (none)");
881
0
    } else {
882
0
        snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "PPID (%d)", ppid);
883
0
    }
884
0
}
885
886
static void *
887
sctp_ppi_value1(packet_info *pinfo)
888
0
{
889
0
    return p_get_proto_data(pinfo->pool, pinfo, proto_sctp, 0);
890
0
}
891
892
static void *
893
sctp_ppi_value2(packet_info *pinfo)
894
0
{
895
0
    return p_get_proto_data(pinfo->pool, pinfo, proto_sctp, 1);
896
0
}
897
898
static const char* sctp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
899
0
{
900
0
    if (filter == CONV_FT_SRC_PORT)
901
0
        return "sctp.srcport";
902
903
0
    if (filter == CONV_FT_DST_PORT)
904
0
        return "sctp.dstport";
905
906
0
    if (filter == CONV_FT_ANY_PORT)
907
0
        return "sctp.port";
908
909
0
    if(!conv) {
910
0
        return CONV_FILTER_INVALID;
911
0
    }
912
913
0
    if (filter == CONV_FT_SRC_ADDRESS) {
914
0
        if (conv->src_address.type == AT_IPv4)
915
0
            return "ip.src";
916
0
        if (conv->src_address.type == AT_IPv6)
917
0
            return "ipv6.src";
918
0
    }
919
920
0
    if (filter == CONV_FT_DST_ADDRESS) {
921
0
        if (conv->dst_address.type == AT_IPv4)
922
0
            return "ip.dst";
923
0
        if (conv->dst_address.type == AT_IPv6)
924
0
            return "ipv6.dst";
925
0
    }
926
927
0
    if (filter == CONV_FT_ANY_ADDRESS) {
928
0
        if (conv->src_address.type == AT_IPv4)
929
0
            return "ip.addr";
930
0
        if (conv->src_address.type == AT_IPv6)
931
0
            return "ipv6.addr";
932
0
    }
933
934
0
    return CONV_FILTER_INVALID;
935
0
}
936
937
static ct_dissector_info_t sctp_ct_dissector_info = {&sctp_conv_get_filter_type};
938
939
static tap_packet_status
940
sctp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
941
0
{
942
0
  conv_hash_t *hash = (conv_hash_t*) pct;
943
0
  hash->flags = flags;
944
945
0
  const struct _sctp_info *sctphdr=(const struct _sctp_info *)vip;
946
947
0
  add_conversation_table_data(hash, &sctphdr->ip_src, &sctphdr->ip_dst,
948
0
        sctphdr->sport, sctphdr->dport, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &sctp_ct_dissector_info, CONVERSATION_SCTP);
949
950
951
0
  return TAP_PACKET_REDRAW;
952
0
}
953
954
static const char* sctp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter)
955
0
{
956
0
    if (filter == CONV_FT_SRC_PORT)
957
0
        return "sctp.srcport";
958
959
0
    if (filter == CONV_FT_DST_PORT)
960
0
        return "sctp.dstport";
961
962
0
    if (filter == CONV_FT_ANY_PORT)
963
0
        return "sctp.port";
964
965
0
    if(!endpoint) {
966
0
        return CONV_FILTER_INVALID;
967
0
    }
968
969
0
    if (filter == CONV_FT_SRC_ADDRESS) {
970
0
        if (endpoint->myaddress.type == AT_IPv4)
971
0
            return "ip.src";
972
0
        if (endpoint->myaddress.type == AT_IPv6)
973
0
            return "ipv6.src";
974
0
    }
975
976
0
    if (filter == CONV_FT_DST_ADDRESS) {
977
0
        if (endpoint->myaddress.type == AT_IPv4)
978
0
            return "ip.dst";
979
0
        if (endpoint->myaddress.type == AT_IPv6)
980
0
            return "ipv6.dst";
981
0
    }
982
983
0
    if (filter == CONV_FT_ANY_ADDRESS) {
984
0
        if (endpoint->myaddress.type == AT_IPv4)
985
0
            return "ip.addr";
986
0
        if (endpoint->myaddress.type == AT_IPv6)
987
0
            return "ipv6.addr";
988
0
    }
989
990
0
    return CONV_FILTER_INVALID;
991
0
}
992
993
static et_dissector_info_t sctp_endpoint_dissector_info = {&sctp_endpoint_get_filter_type};
994
995
static tap_packet_status
996
sctp_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
997
0
{
998
0
  conv_hash_t *hash = (conv_hash_t*) pit;
999
0
  hash->flags = flags;
1000
1001
0
  const struct _sctp_info *sctphdr=(const struct _sctp_info *)vip;
1002
1003
  /* Take two "add" passes per packet, adding for each direction, ensures that all
1004
  packets are counted properly (even if address is sending to itself)
1005
  XXX - this could probably be done more efficiently inside endpoint_table */
1006
0
  add_endpoint_table_data(hash, &sctphdr->ip_src, sctphdr->sport, true, 1, pinfo->fd->pkt_len, &sctp_endpoint_dissector_info, ENDPOINT_SCTP);
1007
0
  add_endpoint_table_data(hash, &sctphdr->ip_dst, sctphdr->dport, false, 1, pinfo->fd->pkt_len, &sctp_endpoint_dissector_info, ENDPOINT_SCTP);
1008
1009
0
  return TAP_PACKET_REDRAW;
1010
0
}
1011
1012
static unsigned int
1013
sctp_adler32(tvbuff_t *tvb, unsigned int len)
1014
0
{
1015
0
  const uint8_t *buf = tvb_get_ptr(tvb, 0, len);
1016
0
  uint32_t result = 1;
1017
1018
0
  result = update_adler32(result, buf, SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH);
1019
  /* handle four 0 bytes as checksum */
1020
0
  result = update_adler32(result, (const uint8_t*)"\0\0\0\0", 4);
1021
0
  result = update_adler32(result, buf+COMMON_HEADER_LENGTH, len-COMMON_HEADER_LENGTH);
1022
1023
0
  return result;
1024
0
}
1025
1026
static uint32_t
1027
sctp_crc32c(tvbuff_t *tvb, unsigned int len)
1028
0
{
1029
0
  const uint8_t *buf = tvb_get_ptr(tvb, 0, len);
1030
0
  uint32_t crc32,
1031
0
          zero = 0;
1032
0
  uint32_t result;
1033
1034
  /* CRC for header */
1035
0
  crc32 = crc32c_calculate_no_swap(buf, SOURCE_PORT_LENGTH + DESTINATION_PORT_LENGTH + VERIFICATION_TAG_LENGTH, CRC32C_PRELOAD);
1036
1037
  /* handle four 0 bytes as checksum */
1038
0
  crc32 = crc32c_calculate_no_swap(&zero, 4, crc32);
1039
1040
  /* CRC for the rest of the packet */
1041
0
  crc32 = crc32c_calculate_no_swap(&buf[COMMON_HEADER_LENGTH], len-COMMON_HEADER_LENGTH, crc32);
1042
1043
0
  result = CRC32C_SWAP(crc32);
1044
1045
0
  return ( ~result );
1046
0
}
1047
1048
/*
1049
 * Routines for dissecting parameters
1050
 */
1051
1052
typedef struct _sctp_half_assoc_t sctp_half_assoc_t;
1053
1054
static void dissect_parameter(tvbuff_t *, packet_info *, proto_tree *, proto_item *, bool, bool, bool);
1055
1056
static void dissect_parameters(tvbuff_t *, packet_info *, proto_tree *, proto_item *, bool, bool);
1057
1058
static void dissect_error_cause(tvbuff_t *, packet_info *, proto_tree *);
1059
1060
static void dissect_error_causes(tvbuff_t *, packet_info *, proto_tree *);
1061
1062
static bool dissect_data_chunk(tvbuff_t*, uint16_t, packet_info*, proto_tree*, proto_tree*, proto_item*, proto_item*, sctp_half_assoc_t*, bool);
1063
1064
static void dissect_sctp_packet(tvbuff_t *, packet_info *, proto_tree *, bool);
1065
1066
1067
/* TSN ANALYSIS CODE */
1068
1069
struct _sctp_half_assoc_t {
1070
  uint32_t spt;
1071
  uint32_t dpt;
1072
  uint32_t vtag;
1073
1074
  bool started;
1075
1076
  uint32_t first_tsn; /* start */
1077
  uint32_t cumm_ack; /* rel */
1078
  wmem_tree_t *tsns; /* sctp_tsn_t* by rel_tsn */
1079
  wmem_tree_t *tsn_acks; /* sctp_tsn_t* by ctsn_frame */
1080
1081
  struct _sctp_half_assoc_t *peer;
1082
};
1083
1084
1085
typedef struct _retransmit_t {
1086
  uint32_t framenum;
1087
  nstime_t ts;
1088
  struct _retransmit_t *next;
1089
} retransmit_t;
1090
1091
typedef struct _sctp_tsn_t {
1092
  uint32_t tsn;
1093
  struct {
1094
    uint32_t framenum;
1095
    nstime_t ts;
1096
  } first_transmit;
1097
  struct {
1098
    uint32_t framenum;
1099
    nstime_t ts;
1100
  } ack;
1101
  retransmit_t *retransmit;
1102
  uint32_t retransmit_count;
1103
  struct _sctp_tsn_t *next;
1104
} sctp_tsn_t;
1105
1106
1107
static wmem_tree_key_t*
1108
make_address_key(wmem_allocator_t *pool, uint32_t spt, uint32_t dpt, address *addr)
1109
30.2k
{
1110
30.2k
  wmem_tree_key_t *k = (wmem_tree_key_t *)wmem_alloc(pool, sizeof(wmem_tree_key_t)*6);
1111
1112
30.2k
  k[0].length = 1;    k[0].key = (uint32_t*)wmem_memdup(pool, &spt,sizeof(spt));
1113
30.2k
  k[1].length = 1;    k[1].key = (uint32_t*)wmem_memdup(pool, &dpt,sizeof(dpt));
1114
30.2k
  k[2].length = 1;    k[2].key = (uint32_t*)(void *)&(addr->type);
1115
30.2k
  k[3].length = 1;    k[3].key = (uint32_t*)(void *)&(addr->len);
1116
1117
30.2k
  k[4].length = ((addr->len/4)+1);
1118
30.2k
  k[4].key = (uint32_t*)wmem_alloc0(pool, ((addr->len/4)+1)*4);
1119
30.2k
  if (addr->len) memcpy(k[4].key, addr->data, addr->len);
1120
1121
30.2k
  k[5].length = 0;    k[5].key = NULL;
1122
1123
30.2k
  return k;
1124
30.2k
}
1125
1126
static wmem_tree_key_t *
1127
make_dir_key(wmem_allocator_t *pool, uint32_t spt, uint32_t dpt, uint32_t vtag)
1128
15.5k
{
1129
15.5k
  wmem_tree_key_t *k =  (wmem_tree_key_t *)wmem_alloc(pool, sizeof(wmem_tree_key_t)*4);
1130
1131
15.5k
  k[0].length = 1;    k[0].key = (uint32_t*)wmem_memdup(pool, &spt,sizeof(spt));
1132
15.5k
  k[1].length = 1;    k[1].key = (uint32_t*)wmem_memdup(pool, &dpt,sizeof(dpt));
1133
15.5k
  k[2].length = 1;    k[2].key = (uint32_t*)wmem_memdup(pool, &vtag,sizeof(vtag));
1134
15.5k
  k[3].length = 0;    k[3].key = NULL;
1135
1136
15.5k
  return k;
1137
15.5k
}
1138
1139
1140
1141
static wmem_tree_t *dirs_by_ptvtag; /* sctp_half_assoc_t*  */
1142
static wmem_tree_t *dirs_by_ptaddr; /* sctp_half_assoc_t**, it may contain a null pointer */
1143
1144
static sctp_half_assoc_t *
1145
get_half_assoc(packet_info *pinfo, uint32_t spt, uint32_t dpt, uint32_t vtag)
1146
35.6k
{
1147
35.6k
  sctp_half_assoc_t *ha;
1148
35.6k
  sctp_half_assoc_t **hb;
1149
35.6k
  wmem_tree_key_t *k;
1150
1151
35.6k
  if (!enable_tsn_analysis || !vtag || pinfo->flags.in_error_pkt)
1152
20.1k
    return NULL;
1153
1154
  /* look for the current half_assoc by spt, dpt and vtag */
1155
1156
15.5k
  k = make_dir_key(pinfo->pool, spt, dpt, vtag);
1157
15.5k
  if (( ha = (sctp_half_assoc_t *)wmem_tree_lookup32_array(dirs_by_ptvtag, k)  )) {
1158
    /* found, if it has been already matched we're done */
1159
12.6k
    if (ha->peer) return ha;
1160
12.6k
  } else {
1161
    /* not found, make a new one and add it to the table */
1162
2.93k
    ha = wmem_new0(wmem_file_scope(), sctp_half_assoc_t);
1163
2.93k
    ha->spt = spt;
1164
2.93k
    ha->dpt = dpt;
1165
2.93k
    ha->vtag = vtag;
1166
2.93k
    ha->tsns = wmem_tree_new(wmem_file_scope());
1167
2.93k
    ha->tsn_acks = wmem_tree_new(wmem_file_scope());
1168
2.93k
    ha->started = false;
1169
2.93k
    ha->first_tsn= 0;
1170
2.93k
    ha->cumm_ack= 0;
1171
1172
    /* add this half to the table indexed by ports and vtag */
1173
2.93k
    wmem_tree_insert32_array(dirs_by_ptvtag, k, ha);
1174
2.93k
  }
1175
1176
  /* at this point we have an unmatched half, look for its other half using the ports and IP address */
1177
15.1k
  k = make_address_key(pinfo->pool, dpt, spt, &(pinfo->dst));
1178
1179
15.1k
  if (( hb = (sctp_half_assoc_t **)wmem_tree_lookup32_array(dirs_by_ptaddr, k) )) {
1180
    /*the table contains a pointer to a pointer to a half */
1181
140
    if (! *hb) {
1182
      /* if there is no half pointed by this, add the current half to the table */
1183
62
      *hb = ha;
1184
78
    } else {
1185
      /* there's a half pointed by this, assume it's our peer and clear the table's pointer */
1186
78
      ha->peer = *hb;
1187
78
      (*hb)->peer = ha;
1188
78
      *hb = NULL;
1189
78
    }
1190
15.0k
  } else {
1191
    /* we found no entry in the table: add one (using reversed ports and src addresses) so that it can be matched later */
1192
15.0k
    *(hb = (sctp_half_assoc_t **)wmem_alloc(wmem_file_scope(), sizeof(void*))) = ha;
1193
15.0k
    k = make_address_key(pinfo->pool, spt, dpt, &(pinfo->src));
1194
15.0k
    wmem_tree_insert32_array(dirs_by_ptaddr, k, hb);
1195
15.0k
  }
1196
1197
15.1k
  return ha;
1198
15.5k
}
1199
1200
/*  Limit the number of retransmissions we track (to limit memory usage--and
1201
 *  tree size--in pathological cases, for example zero window probing forever).
1202
 */
1203
1.53k
#define MAX_RETRANS_TRACKED_PER_TSN 100
1204
1205
static void
1206
tsn_tree(sctp_tsn_t *t, proto_item *tsn_item, packet_info *pinfo,
1207
         tvbuff_t *tvb, uint32_t framenum)
1208
609
{
1209
609
  proto_item *pi;
1210
609
  proto_tree *pt;
1211
609
  proto_tree *tsn_tree_pt = proto_item_add_subtree(tsn_item, ett_sctp_tsn);
1212
1213
609
  if (t->first_transmit.framenum != framenum) {
1214
216
    nstime_t rto;
1215
1216
216
    pi = proto_tree_add_uint(tsn_tree_pt, hf_sctp_retransmission, tvb, 0, 0, t->first_transmit.framenum);
1217
216
    pt = proto_item_add_subtree(pi, ett_sctp_tsn_retransmission);
1218
216
    proto_item_set_generated(pi);
1219
216
    expert_add_info(pinfo, pi, &ei_sctp_tsn_retransmitted);
1220
1221
216
    nstime_delta( &rto, &pinfo->abs_ts, &(t->first_transmit.ts) );
1222
216
    pi = proto_tree_add_time(pt, hf_sctp_rto, tvb, 0, 0, &rto);
1223
216
    proto_item_set_generated(pi);
1224
1225
    /* Detect reneged acks */
1226
    /* XXX what if the frames aren't sorted by time? */
1227
216
    if (t->ack.framenum && t->ack.framenum < framenum)
1228
0
    {
1229
0
      pi = proto_tree_add_uint_format(pt, hf_sctp_retransmitted_after_ack, tvb, 0, 0, t->ack.framenum,
1230
0
                                      "This TSN was acked (in frame %u) prior to this retransmission (reneged ack?)",
1231
0
                                      t->ack.framenum);
1232
0
      proto_item_set_generated(pi);
1233
0
      expert_add_info(pinfo, pi, &ei_sctp_retransmitted_after_ack);
1234
0
    }
1235
393
  } else if (t->retransmit) {
1236
0
    retransmit_t **r;
1237
0
    nstime_t rto;
1238
0
    char ds[64];
1239
1240
0
    if (t->retransmit_count > MAX_RETRANS_TRACKED_PER_TSN)
1241
0
      snprintf(ds, sizeof(ds), " (only %d displayed)", MAX_RETRANS_TRACKED_PER_TSN);
1242
0
    else
1243
0
      ds[0] = 0;
1244
1245
0
    pi = proto_tree_add_uint_format(tsn_tree_pt,
1246
0
                                    hf_sctp_retransmitted_count,
1247
0
                                    tvb, 0, 0, t->retransmit_count,
1248
0
                                    "This TSN was retransmitted %u time%s%s",
1249
0
                                    t->retransmit_count,
1250
0
                                    plurality(t->retransmit_count, "", "s"),
1251
0
                                    ds);
1252
0
    proto_item_set_generated(pi);
1253
1254
0
    if (t->retransmit_count > 2)
1255
0
      expert_add_info(pinfo, pi, &ei_sctp_tsn_retransmitted_more_than_twice);
1256
1257
0
    pt = proto_item_add_subtree(pi, ett_sctp_tsn_retransmitted_count);
1258
1259
0
    r = &t->retransmit;
1260
0
    while (*r) {
1261
0
      nstime_delta(&rto, &((*r)->ts), &pinfo->abs_ts);
1262
0
      pi = proto_tree_add_uint_format(pt,
1263
0
                                      hf_sctp_retransmitted,
1264
0
                                      tvb, 0, 0,
1265
0
                                      (*r)->framenum,
1266
0
                                      "This TSN was retransmitted in frame %u (%s seconds after this frame)",
1267
0
                                      (*r)->framenum,
1268
0
                                      rel_time_to_secs_str(pinfo->pool, &rto));
1269
0
      proto_item_set_generated(pi);
1270
0
      r = &(*r)->next;
1271
0
    }
1272
0
  }
1273
1274
609
  if (t->ack.framenum) {
1275
0
    nstime_t rtt;
1276
1277
0
    pi = proto_tree_add_uint(tsn_tree_pt, hf_sctp_acked, tvb, 0 , 0, t->ack.framenum);
1278
0
    proto_item_set_generated(pi);
1279
0
    pt = proto_item_add_subtree(pi, ett_sctp_ack);
1280
1281
0
    nstime_delta( &rtt, &(t->ack.ts), &(t->first_transmit.ts) );
1282
0
    pi = proto_tree_add_time(pt, hf_sctp_data_rtt, tvb, 0, 0, &rtt);
1283
0
    proto_item_set_generated(pi);
1284
0
  }
1285
609
}
1286
1287
609
#define RELTSN(tsn) (((tsn) < h->first_tsn) ? (tsn + (0xffffffff - (h->first_tsn)) + 1) : (tsn - h->first_tsn))
1288
1289
/* Returns true if the tsn is a retransmission (we've seen it before), false
1290
 * otherwise.
1291
 */
1292
static bool
1293
sctp_tsn(packet_info *pinfo,  tvbuff_t *tvb, proto_item *tsn_item,
1294
         sctp_half_assoc_t *h, uint32_t tsn)
1295
19.4k
{
1296
19.4k
  sctp_tsn_t *t;
1297
19.4k
  uint32_t framenum;
1298
19.4k
  uint32_t reltsn;
1299
19.4k
  bool is_retransmission = false;
1300
1301
  /* no half assoc? nothing to do!*/
1302
19.4k
  if (!h)
1303
18.8k
    return is_retransmission;
1304
1305
1306
609
  framenum = pinfo->num;
1307
1308
  /*  If we're dissecting for a read filter in the GUI [tshark assigns
1309
   *  frame numbers before running the read filter], don't do the TSN
1310
   *  analysis.  (We can't anyway because we don't have a valid frame
1311
   *  number...)
1312
   *
1313
   *  Without this check if you load a capture file in the
1314
   *  GUI while using a read filter, every SCTP TSN is marked as a
1315
   *  retransmission of that in frame 0.
1316
   */
1317
609
  if (framenum == 0)
1318
0
    return is_retransmission;
1319
1320
  /* we have not seen any tsn yet in this half assoc set the ground */
1321
609
  if (! h->started) {
1322
0
    h->first_tsn = tsn;
1323
0
    h->started = true;
1324
0
  }
1325
1326
1327
609
  reltsn = RELTSN(tsn);
1328
1329
  /* printf("%.3d REL TSN: %p->%p [%u] %u \n",framenum,h,h->peer,tsn,reltsn); */
1330
1331
  /* look for this tsn in this half's tsn table */
1332
609
  if (! (t = (sctp_tsn_t *)wmem_tree_lookup32(h->tsns,reltsn) )) {
1333
    /* no tsn found, create a new one */
1334
356
    t = wmem_new0(wmem_file_scope(), sctp_tsn_t);
1335
356
    t->tsn = tsn;
1336
1337
356
    t->first_transmit.framenum = framenum;
1338
356
    t->first_transmit.ts = pinfo->abs_ts;
1339
1340
356
    wmem_tree_insert32(h->tsns,reltsn,t);
1341
356
  }
1342
1343
609
  is_retransmission = (t->first_transmit.framenum != framenum);
1344
1345
609
  if ( (! pinfo->fd->visited ) && is_retransmission ) {
1346
216
    retransmit_t **r;
1347
216
    int i;
1348
1349
216
    t->retransmit_count++;
1350
216
    r = &t->retransmit;
1351
216
    i = 0;
1352
1.53k
    while (*r && i < MAX_RETRANS_TRACKED_PER_TSN) {
1353
1.32k
      r = &(*r)->next;
1354
1.32k
      i++;
1355
1.32k
    }
1356
1357
216
    if (i <= MAX_RETRANS_TRACKED_PER_TSN) {
1358
216
      *r = wmem_new0(wmem_file_scope(), retransmit_t);
1359
216
      (*r)->framenum = framenum;
1360
216
      (*r)->ts = pinfo->abs_ts;
1361
216
    }
1362
216
  }
1363
1364
609
  tsn_tree(t, tsn_item, pinfo, tvb, framenum);
1365
1366
609
  return is_retransmission;
1367
609
}
1368
1369
static void
1370
ack_tree(sctp_tsn_t *t, proto_tree *acks_tree,
1371
         tvbuff_t *tvb, packet_info *pinfo)
1372
0
{
1373
0
  proto_item *pi;
1374
0
  proto_tree *pt;
1375
0
  nstime_t rtt;
1376
0
  unsigned framenum =  pinfo->num;
1377
1378
0
  if ( t->ack.framenum == framenum ) {
1379
0
    nstime_delta( &rtt, &(t->ack.ts), &(t->first_transmit.ts) );
1380
1381
0
    pi = proto_tree_add_uint(acks_tree, hf_sctp_ack_tsn, tvb, 0 , 0, t->tsn);
1382
0
    proto_item_set_generated(pi);
1383
1384
0
    pt = proto_item_add_subtree(pi, ett_sctp_acked);
1385
1386
0
    pi = proto_tree_add_uint(pt, hf_sctp_ack_frame, tvb, 0 , 0, t->first_transmit.framenum);
1387
0
    proto_item_set_generated(pi);
1388
1389
0
    pi = proto_tree_add_time(pt, hf_sctp_sack_rtt, tvb, 0, 0, &rtt);
1390
0
    proto_item_set_generated(pi);
1391
0
  }
1392
0
}
1393
1394
static void
1395
sctp_ack(packet_info *pinfo, tvbuff_t *tvb,  proto_tree *acks_tree,
1396
         sctp_half_assoc_t *h, uint32_t reltsn)
1397
132k
{
1398
132k
  sctp_tsn_t *t;
1399
132k
  uint32_t framenum;
1400
1401
1402
132k
  if (!h || !h->peer)
1403
0
    return;
1404
1405
132k
  framenum = pinfo->num;
1406
1407
  /* printf("%.6d ACK: %p->%p [%u] \n",framenum,h,h->peer,reltsn); */
1408
1409
132k
  t = (sctp_tsn_t *)wmem_tree_lookup32(h->peer->tsns,reltsn);
1410
1411
132k
  if (t) {
1412
0
    if (! t->ack.framenum) {
1413
0
      sctp_tsn_t *t2;
1414
1415
0
      t->ack.framenum = framenum;
1416
0
      t->ack.ts = pinfo->abs_ts;
1417
1418
0
      if (( t2 = (sctp_tsn_t *)wmem_tree_lookup32(h->peer->tsn_acks, framenum) )) {
1419
0
        for(;t2->next;t2 = t2->next)
1420
0
          ;
1421
1422
0
        t2->next = t;
1423
0
      } else {
1424
0
        wmem_tree_insert32(h->peer->tsn_acks, framenum,t);
1425
0
      }
1426
0
    }
1427
1428
0
    if ( t->ack.framenum == framenum)
1429
0
      ack_tree(t, acks_tree, tvb, pinfo);
1430
1431
0
  } /* else {
1432
       proto_tree_add_debug_text(acks_tree, tvb, 0 , 0, "Assoc: %p vs %p ?? %ld",h,h->peer,tsn);
1433
       } */
1434
132k
}
1435
1436
2.23k
#define RELTSNACK(tsn) (((tsn) < h->peer->first_tsn) ? ((tsn) + (0xffffffff - (h->peer->first_tsn)) + 1) : ((tsn) - h->peer->first_tsn))
1437
static void
1438
sctp_ack_block(packet_info *pinfo, sctp_half_assoc_t *h, tvbuff_t *tvb,
1439
               proto_item *acks_tree, const uint32_t *tsn_start_ptr,
1440
               uint32_t tsn_end)
1441
5.52k
{
1442
5.52k
  sctp_tsn_t *t;
1443
5.52k
  uint32_t framenum;
1444
5.52k
  uint32_t rel_start;
1445
5.52k
  uint32_t rel_end;
1446
1447
1448
5.52k
  if ( !h || !h->peer || ! h->peer->started )
1449
4.40k
    return;
1450
1451
1.12k
  framenum =  pinfo->num;
1452
1.12k
  rel_end = RELTSNACK(tsn_end);
1453
1454
1.12k
  if (tsn_start_ptr) {
1455
1.10k
    rel_start = RELTSNACK(*tsn_start_ptr);
1456
    /* printf("%.3d BACK: %p->%p [%u-%u]\n",framenum,h,h->peer,rel_start,rel_end); */
1457
1.10k
  }  else {
1458
22
    rel_start = h->peer->cumm_ack;
1459
    /* printf("%.3d CACK: %p->%p  [%u-%u]\n",framenum,h,h->peer,rel_start,rel_end); */
1460
22
  }
1461
1462
1463
1.12k
  if ((t = (sctp_tsn_t *)wmem_tree_lookup32(h->peer->tsn_acks, framenum))) {
1464
0
    for(;t;t = t->next) {
1465
0
      uint32_t tsn = t->tsn;
1466
1467
0
      tsn -= h->peer->first_tsn;
1468
1469
0
      if (t->ack.framenum == framenum && ( (!tsn_start_ptr) || rel_start <= tsn) && tsn <= rel_end)
1470
0
        ack_tree(t, acks_tree, tvb, pinfo);
1471
0
    }
1472
1473
0
    return;
1474
0
  }
1475
1476
1.12k
  if (PINFO_FD_VISITED(pinfo) || rel_end < rel_start || rel_end - rel_start > 0xffff0000 ) return;
1477
1478
784
  if (! tsn_start_ptr )
1479
5
    h->peer->cumm_ack = rel_end + 1;
1480
1481
784
  if (rel_start <= rel_end && rel_end - rel_start < 5000 ) {
1482
541
    uint32_t rel_tsn, i;
1483
132k
    for (i=0; i <= rel_end-rel_start; i++) {
1484
132k
      rel_tsn = (uint32_t) (i+rel_start);
1485
132k
      sctp_ack(pinfo, tvb,  acks_tree, h, rel_tsn);
1486
132k
    }
1487
541
  }
1488
784
}
1489
1490
/* END TSN ANALYSIS CODE */
1491
1492
1493
1494
1495
9
#define HEARTBEAT_INFO_PARAMETER_INFO_OFFSET PARAMETER_VALUE_OFFSET
1496
1497
static void
1498
dissect_heartbeat_info_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1499
9
{
1500
9
  uint16_t heartbeat_info_length;
1501
1502
9
  heartbeat_info_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1503
9
  if (heartbeat_info_length > 0)
1504
9
    proto_tree_add_item(parameter_tree, hf_heartbeat_info, parameter_tvb, HEARTBEAT_INFO_PARAMETER_INFO_OFFSET, heartbeat_info_length, ENC_NA);
1505
9
  proto_item_append_text(parameter_item, " (Information: %u byte%s)", heartbeat_info_length, plurality(heartbeat_info_length, "", "s"));
1506
9
}
1507
1508
8
#define IPV4_ADDRESS_LENGTH 4
1509
8
#define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1510
1511
static void
1512
dissect_ipv4_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, bool dissecting_init_init_ack_chunk)
1513
8
{
1514
8
  if (parameter_tree) {
1515
8
    proto_tree_add_item(parameter_tree, hf_ipv4_address, parameter_tvb, IPV4_ADDRESS_OFFSET, IPV4_ADDRESS_LENGTH, ENC_BIG_ENDIAN);
1516
8
    proto_item_append_text(parameter_item, " (Address: %s)", tvb_ip_to_str(pinfo->pool, parameter_tvb, IPV4_ADDRESS_OFFSET));
1517
8
    if (additional_item)
1518
0
        proto_item_append_text(additional_item, "%s", tvb_ip_to_str(pinfo->pool, parameter_tvb, IPV4_ADDRESS_OFFSET));
1519
8
  }
1520
8
  if (dissecting_init_init_ack_chunk) {
1521
4
    if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
1522
4
      sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
1523
0
    else
1524
0
      sctp_info.incomplete = true;
1525
4
  }
1526
8
}
1527
1528
5
#define IPV6_ADDRESS_LENGTH 16
1529
5
#define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET
1530
1531
static void
1532
dissect_ipv6_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item, bool dissecting_init_init_ack_chunk)
1533
5
{
1534
5
  if (parameter_tree) {
1535
5
    proto_tree_add_item(parameter_tree, hf_ipv6_address, parameter_tvb, IPV6_ADDRESS_OFFSET, IPV6_ADDRESS_LENGTH, ENC_NA);
1536
5
    proto_item_append_text(parameter_item, " (Address: %s)", tvb_ip6_to_str(pinfo->pool, parameter_tvb, IPV6_ADDRESS_OFFSET));
1537
5
    if (additional_item)
1538
0
      proto_item_append_text(additional_item, "%s", tvb_ip6_to_str(pinfo->pool, parameter_tvb, IPV6_ADDRESS_OFFSET));
1539
5
  }
1540
5
  if (dissecting_init_init_ack_chunk) {
1541
2
    if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
1542
2
      sctp_info.tvb[sctp_info.number_of_tvbs++] = parameter_tvb;
1543
0
    else
1544
0
      sctp_info.incomplete = true;
1545
2
  }
1546
5
}
1547
1548
2
#define STATE_COOKIE_PARAMETER_COOKIE_OFFSET   PARAMETER_VALUE_OFFSET
1549
1550
static void
1551
dissect_state_cookie_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1552
3
{
1553
3
  uint16_t state_cookie_length;
1554
1555
3
  state_cookie_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1556
3
  if (state_cookie_length > 0)
1557
2
    proto_tree_add_item(parameter_tree, hf_state_cookie, parameter_tvb, STATE_COOKIE_PARAMETER_COOKIE_OFFSET, state_cookie_length, ENC_NA);
1558
3
  proto_item_append_text(parameter_item, " (Cookie length: %u byte%s)", state_cookie_length, plurality(state_cookie_length, "", "s"));
1559
3
}
1560
1561
static void
1562
// NOLINTNEXTLINE(misc-no-recursion)
1563
dissect_unrecognized_parameters_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1564
3
{
1565
  /* FIXME: Does it contain one or more parameters? */
1566
3
  dissect_parameter(tvb_new_subset_remaining(parameter_tvb, PARAMETER_VALUE_OFFSET), pinfo, parameter_tree, NULL, false, false, false);
1567
3
}
1568
1569
2
#define COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH 4
1570
4
#define COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET PARAMETER_VALUE_OFFSET
1571
1572
static void
1573
dissect_cookie_preservative_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1574
2
{
1575
2
  proto_tree_add_item(parameter_tree, hf_cookie_preservative_increment, parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET, COOKIE_PRESERVATIVE_PARAMETER_INCR_LENGTH, ENC_BIG_ENDIAN);
1576
2
  proto_item_append_text(parameter_item, " (Increment :%u msec)", tvb_get_ntohl(parameter_tvb, COOKIE_PRESERVATIVE_PARAMETER_INCR_OFFSET));
1577
2
}
1578
1579
3
#define HOSTNAME_OFFSET PARAMETER_VALUE_OFFSET
1580
1581
static void
1582
dissect_hostname_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item, proto_item *additional_item)
1583
3
{
1584
3
  char *hostname;
1585
3
  uint16_t hostname_length;
1586
1587
3
  hostname_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1588
3
  proto_tree_add_item_ret_display_string(parameter_tree, hf_hostname, parameter_tvb, HOSTNAME_OFFSET, hostname_length, ENC_ASCII, pinfo->pool, &hostname);
1589
3
  if (hostname_length > 1) {
1590
1
    proto_item_append_text(parameter_item, " (Hostname: %s)", hostname);
1591
1
    if (additional_item != NULL) {
1592
0
      proto_item_append_text(additional_item, " (Hostname: %s)", hostname);
1593
0
    }
1594
1
  }
1595
3
}
1596
1597
22
#define IPv4_ADDRESS_TYPE      5
1598
33
#define IPv6_ADDRESS_TYPE      6
1599
12
#define HOSTNAME_ADDRESS_TYPE 11
1600
1601
static const value_string address_types_values[] = {
1602
  { IPv4_ADDRESS_TYPE,     "IPv4 address"     },
1603
  { IPv6_ADDRESS_TYPE,     "IPv6 address"     },
1604
  { HOSTNAME_ADDRESS_TYPE, "Hostname address" },
1605
  { 0,                     NULL               }
1606
};
1607
1608
9.81k
#define SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH 2
1609
1610
static void
1611
dissect_supported_address_types_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1612
38
{
1613
38
  uint16_t addr_type, number_of_addr_types, addr_type_number;
1614
38
  unsigned offset;
1615
1616
38
  number_of_addr_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH)
1617
38
                            / SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
1618
1619
38
  offset = PARAMETER_VALUE_OFFSET;
1620
38
  proto_item_append_text(parameter_item, " (Supported types: ");
1621
4.91k
  for(addr_type_number = 0; addr_type_number < number_of_addr_types; addr_type_number++) {
1622
4.90k
    proto_tree_add_item(parameter_tree, hf_supported_address_type, parameter_tvb, offset, SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH, ENC_BIG_ENDIAN);
1623
4.90k
    addr_type = tvb_get_ntohs(parameter_tvb, offset);
1624
4.90k
    switch (addr_type) {
1625
22
    case IPv4_ADDRESS_TYPE:
1626
22
      proto_item_append_text(parameter_item, "IPv4");
1627
22
      break;
1628
33
    case IPv6_ADDRESS_TYPE:
1629
33
      proto_item_append_text(parameter_item, "IPv6");
1630
33
      break;
1631
12
    case HOSTNAME_ADDRESS_TYPE:
1632
12
      proto_item_append_text(parameter_item, "hostname");
1633
12
      break;
1634
4.80k
    default:
1635
4.80k
      proto_item_append_text(parameter_item, "%u", addr_type);
1636
4.90k
    }
1637
4.87k
    if (addr_type_number < (number_of_addr_types-1))
1638
4.86k
      proto_item_append_text(parameter_item, ", ");
1639
4.87k
    offset += SUPPORTED_ADDRESS_TYPE_PARAMETER_ADDRESS_TYPE_LENGTH;
1640
4.87k
  }
1641
5
  proto_item_append_text(parameter_item, ")");
1642
5
}
1643
1644
266
#define STREAM_RESET_SEQ_NR_LENGTH       4
1645
72
#define SENDERS_LAST_ASSIGNED_TSN_LENGTH 4
1646
3.15k
#define SID_LENGTH                       2
1647
1648
42
#define STREAM_RESET_REQ_SEQ_NR_OFFSET     PARAMETER_VALUE_OFFSET
1649
54
#define STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET (PARAMETER_VALUE_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1650
36
#define SENDERS_LAST_ASSIGNED_TSN_OFFSET   (STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1651
1652
static void
1653
dissect_outgoing_ssn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1654
18
{
1655
18
  unsigned length, number_of_sids, sid_number, sid_offset;
1656
1657
18
  proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr,   parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET,     STREAM_RESET_SEQ_NR_LENGTH,       ENC_BIG_ENDIAN);
1658
18
  proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_seq_nr,   parameter_tvb, STREAM_RESET_REQ_RSP_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH,       ENC_BIG_ENDIAN);
1659
18
  proto_tree_add_item(parameter_tree, hf_senders_last_assigned_tsn, parameter_tvb, SENDERS_LAST_ASSIGNED_TSN_OFFSET,   SENDERS_LAST_ASSIGNED_TSN_LENGTH, ENC_BIG_ENDIAN);
1660
1661
18
  length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1662
18
  sid_offset = SENDERS_LAST_ASSIGNED_TSN_OFFSET + SENDERS_LAST_ASSIGNED_TSN_LENGTH;
1663
18
  if (length > PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + SENDERS_LAST_ASSIGNED_TSN_LENGTH) {
1664
18
    number_of_sids = (length - (PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + SENDERS_LAST_ASSIGNED_TSN_LENGTH)) / SID_LENGTH;
1665
1.13k
    for(sid_number = 0; sid_number < number_of_sids; sid_number++) {
1666
1.11k
      proto_tree_add_item(parameter_tree, hf_stream_reset_sid, parameter_tvb, sid_offset, SID_LENGTH, ENC_BIG_ENDIAN);
1667
1.11k
      sid_offset += SID_LENGTH;
1668
1.11k
    }
1669
18
  }
1670
18
}
1671
1672
static void
1673
dissect_incoming_ssn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1674
12
{
1675
12
  unsigned length, number_of_sids, sid_number, sid_offset;
1676
1677
12
  proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr, parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, ENC_BIG_ENDIAN);
1678
1679
12
  length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1680
12
  sid_offset = STREAM_RESET_REQ_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH;
1681
12
  if (length > PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH) {
1682
11
    number_of_sids = (length - (PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH)) / SID_LENGTH;
1683
458
    for(sid_number = 0; sid_number < number_of_sids; sid_number++) {
1684
447
      proto_tree_add_item(parameter_tree, hf_stream_reset_sid, parameter_tvb, sid_offset, SID_LENGTH, ENC_BIG_ENDIAN);
1685
447
      sid_offset += SID_LENGTH;
1686
447
    }
1687
11
  }
1688
12
}
1689
1690
3
#define STREAM_RESET_REQ_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1691
1692
static void
1693
dissect_ssn_tsn_reset_request_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1694
3
{
1695
3
  proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr, parameter_tvb, STREAM_RESET_REQ_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH, ENC_BIG_ENDIAN);
1696
3
}
1697
1698
15
#define STREAM_RESET_RSP_RESULT_LENGTH 4
1699
12
#define SENDERS_NEXT_TSN_LENGTH        4
1700
6
#define RECEIVERS_NEXT_TSN_LENGTH      4
1701
1702
12
#define STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET PARAMETER_VALUE_OFFSET
1703
9
#define STREAM_RESET_RSP_RESULT_OFFSET     (STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET + STREAM_RESET_SEQ_NR_LENGTH)
1704
6
#define SENDERS_NEXT_TSN_OFFSET            (STREAM_RESET_RSP_RESULT_OFFSET + STREAM_RESET_RSP_RESULT_LENGTH)
1705
3
#define RECEIVERS_NEXT_TSN_OFFSET          (SENDERS_NEXT_TSN_OFFSET + SENDERS_NEXT_TSN_LENGTH)
1706
1707
static const value_string stream_reset_result_values[] = {
1708
  { 0, "Nothing to do"                       },
1709
  { 1, "Performed"                           },
1710
  { 2, "Denied"                              },
1711
  { 3, "Error - Wrong SSN"                   },
1712
  { 4, "Error - Request already in progress" },
1713
  { 5, "Error - Bad sequence number"         },
1714
  { 6, "In progress"                         },
1715
  { 0, NULL                                  }
1716
};
1717
1718
1719
static void
1720
dissect_re_configuration_response_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1721
3
{
1722
3
  unsigned length;
1723
1724
3
  length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
1725
1726
3
  proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_seq_nr, parameter_tvb, STREAM_RESET_RSP_RSP_SEQ_NR_OFFSET, STREAM_RESET_SEQ_NR_LENGTH,     ENC_BIG_ENDIAN);
1727
3
  proto_tree_add_item(parameter_tree, hf_stream_reset_rsp_result, parameter_tvb, STREAM_RESET_RSP_RESULT_OFFSET,     STREAM_RESET_RSP_RESULT_LENGTH, ENC_BIG_ENDIAN);
1728
3
  if (length >= PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_RSP_RESULT_LENGTH + SENDERS_NEXT_TSN_LENGTH)
1729
3
    proto_tree_add_item(parameter_tree, hf_senders_next_tsn,   parameter_tvb, SENDERS_NEXT_TSN_OFFSET,   SENDERS_NEXT_TSN_LENGTH,   ENC_BIG_ENDIAN);
1730
3
  if (length >= PARAMETER_HEADER_LENGTH + STREAM_RESET_SEQ_NR_LENGTH + STREAM_RESET_RSP_RESULT_LENGTH + SENDERS_NEXT_TSN_LENGTH + RECEIVERS_NEXT_TSN_LENGTH)
1731
3
    proto_tree_add_item(parameter_tree, hf_receivers_next_tsn, parameter_tvb, RECEIVERS_NEXT_TSN_OFFSET, RECEIVERS_NEXT_TSN_LENGTH, ENC_BIG_ENDIAN);
1732
3
}
1733
1734
15
#define ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH      4
1735
7
#define ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_LENGTH 2
1736
2
#define ADD_OUTGOING_STREAM_REQ_RESERVED_LENGTH    2
1737
1738
6
#define ADD_OUTGOING_STREAM_REQ_SEQ_NR_OFFSET      PARAMETER_VALUE_OFFSET
1739
4
#define ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_OFFSET (ADD_OUTGOING_STREAM_REQ_SEQ_NR_OFFSET + ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH)
1740
2
#define ADD_OUTGOING_STREAM_REQ_RESERVED_OFFSET    (ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_OFFSET + ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_LENGTH)
1741
1742
static void
1743
dissect_add_outgoing_streams_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1744
2
{
1745
  /* unsigned length; */
1746
1747
  /* length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); */
1748
1749
2
  proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr,             parameter_tvb, ADD_OUTGOING_STREAM_REQ_SEQ_NR_OFFSET,      ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH,      ENC_BIG_ENDIAN);
1750
2
  proto_tree_add_item(parameter_tree, hf_add_outgoing_streams_number_streams, parameter_tvb, ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_OFFSET, ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_LENGTH, ENC_BIG_ENDIAN);
1751
2
  proto_tree_add_item(parameter_tree, hf_add_outgoing_streams_reserved,       parameter_tvb, ADD_OUTGOING_STREAM_REQ_RESERVED_OFFSET,    ADD_OUTGOING_STREAM_REQ_RESERVED_LENGTH,    ENC_BIG_ENDIAN);
1752
2
}
1753
1754
#define ADD_INCOMING_STREAM_REQ_SEQ_NR_LENGTH      4
1755
3
#define ADD_INCOMING_STREAM_REQ_NUM_STREAMS_LENGTH 2
1756
3
#define ADD_INCOMING_STREAM_REQ_RESERVED_LENGTH    2
1757
1758
9
#define ADD_INCOMING_STREAM_REQ_SEQ_NR_OFFSET      PARAMETER_VALUE_OFFSET
1759
6
#define ADD_INCOMING_STREAM_REQ_NUM_STREAMS_OFFSET (ADD_INCOMING_STREAM_REQ_SEQ_NR_OFFSET + ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH)
1760
3
#define ADD_INCOMING_STREAM_REQ_RESERVED_OFFSET    (ADD_INCOMING_STREAM_REQ_NUM_STREAMS_OFFSET + ADD_OUTGOING_STREAM_REQ_NUM_STREAMS_LENGTH)
1761
1762
static void
1763
dissect_add_incoming_streams_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item _U_)
1764
3
{
1765
  /* unsigned length; */
1766
1767
  /* length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET); */
1768
1769
3
  proto_tree_add_item(parameter_tree, hf_stream_reset_req_seq_nr,             parameter_tvb, ADD_INCOMING_STREAM_REQ_SEQ_NR_OFFSET,      ADD_OUTGOING_STREAM_REQ_SEQ_NR_LENGTH,    ENC_BIG_ENDIAN);
1770
3
  proto_tree_add_item(parameter_tree, hf_add_incoming_streams_number_streams, parameter_tvb, ADD_INCOMING_STREAM_REQ_NUM_STREAMS_OFFSET, ADD_INCOMING_STREAM_REQ_NUM_STREAMS_LENGTH, ENC_BIG_ENDIAN);
1771
3
  proto_tree_add_item(parameter_tree, hf_add_incoming_streams_reserved,       parameter_tvb, ADD_INCOMING_STREAM_REQ_RESERVED_OFFSET,    ADD_INCOMING_STREAM_REQ_RESERVED_LENGTH,    ENC_BIG_ENDIAN);
1772
3
}
1773
1774
static void
1775
dissect_ecn_parameter(tvbuff_t *parameter_tvb _U_)
1776
2
{
1777
2
}
1778
1779
2
#define ZERO_CHECKSUM_PARAMETER_EDMID_LENGTH 4
1780
4
#define ZERO_CHECKSUM_PARAMETER_EDMID_OFFSET PARAMETER_VALUE_OFFSET
1781
1782
static const value_string edmid_values[] = {
1783
  { 1, "SCTP over DTLS" },
1784
  { 0, NULL             }
1785
};
1786
1787
static void
1788
dissect_zero_checksum_acceptable_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1789
2
{
1790
2
  proto_tree_add_item(parameter_tree, hf_zero_checksum_edmid, parameter_tvb, ZERO_CHECKSUM_PARAMETER_EDMID_OFFSET, ZERO_CHECKSUM_PARAMETER_EDMID_LENGTH, ENC_BIG_ENDIAN);
1791
2
  proto_item_append_text(parameter_item, " (EDMID: %s)", val_to_str_const(tvb_get_ntohl(parameter_tvb, ZERO_CHECKSUM_PARAMETER_EDMID_OFFSET), edmid_values, "Unknown"));
1792
2
}
1793
1794
2
#define RANDOM_NUMBER_OFFSET PARAMETER_VALUE_OFFSET
1795
1796
static void
1797
dissect_random_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree)
1798
2
{
1799
2
  int32_t number_length;
1800
1801
2
  number_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1802
2
  if (number_length > 0)
1803
2
    proto_tree_add_item(parameter_tree, hf_random_number, parameter_tvb, RANDOM_NUMBER_OFFSET, number_length, ENC_NA);
1804
2
}
1805
1806
static void
1807
dissect_chunks_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1808
9
{
1809
9
  uint16_t number_of_chunks;
1810
9
  uint16_t chunk_number, offset;
1811
1812
9
  proto_item_append_text(parameter_item, " (Chunk types to be authenticated: ");
1813
9
  number_of_chunks = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
1814
1.58k
  for(chunk_number = 0, offset = PARAMETER_VALUE_OFFSET; chunk_number < number_of_chunks; chunk_number++, offset +=  CHUNK_TYPE_LENGTH) {
1815
1.57k
    proto_tree_add_item(parameter_tree, hf_chunks_to_auth, parameter_tvb, offset, CHUNK_TYPE_LENGTH, ENC_BIG_ENDIAN);
1816
1.57k
    proto_item_append_text(parameter_item, "%s", val_to_str_const(tvb_get_uint8(parameter_tvb, offset), chunk_type_values, "Unknown"));
1817
1.57k
    if (chunk_number < (number_of_chunks - 1))
1818
1.56k
      proto_item_append_text(parameter_item, ", ");
1819
1.57k
  }
1820
9
  proto_item_append_text(parameter_item, ")");
1821
9
}
1822
1823
static const value_string hmac_id_values[] = {
1824
  { 0x0000,         "Reserved" },
1825
  { 0x0001,         "SHA-1"    },
1826
  { 0x0002,         "Reserved" },
1827
  { 0x0003,         "SHA-256"  },
1828
  { 0,              NULL       } };
1829
1830
820
#define HMAC_ID_LENGTH 2
1831
1832
static void
1833
dissect_hmac_algo_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1834
9
{
1835
9
  uint16_t number_of_ids;
1836
9
  uint16_t id_number, offset;
1837
1838
9
  proto_item_append_text(parameter_item, " (Supported HMACs: ");
1839
9
  number_of_ids = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / HMAC_ID_LENGTH;
1840
410
  for(id_number = 0, offset = PARAMETER_VALUE_OFFSET; id_number < number_of_ids; id_number++, offset +=  HMAC_ID_LENGTH) {
1841
401
    proto_tree_add_item(parameter_tree, hf_hmac_id, parameter_tvb, offset, HMAC_ID_LENGTH, ENC_BIG_ENDIAN);
1842
401
    proto_item_append_text(parameter_item, "%s", val_to_str_const(tvb_get_ntohs(parameter_tvb, offset), hmac_id_values, "Unknown"));
1843
401
    if (id_number < (number_of_ids - 1))
1844
392
      proto_item_append_text(parameter_item, ", ");
1845
401
  }
1846
9
  proto_item_append_text(parameter_item, ")");
1847
9
}
1848
1849
static const value_string dtls_km_id_values[] = {
1850
  { 0x00, "Reserved"                  },
1851
  { 0x01, "Single DTLS connection"    },
1852
  { 0xC0, "Single TLS connection"     },
1853
  { 0,    NULL                        } };
1854
1855
42
#define DTLS_KM_PARAMETER_TIE_BREAKER_LENGTH 4
1856
28
#define DTLS_KM_PARAMETER_FLAGS_LENGTH       1
1857
6.66k
#define DTLS_KM_PARAMETER_KMID_LENGTH        1
1858
1859
42
#define DTLS_KM_PARAMETER_TIE_BREAKER_OFFSET PARAMETER_VALUE_OFFSET
1860
35
#define DTLS_KM_PARAMETER_FLAGS_OFFSET       (DTLS_KM_PARAMETER_TIE_BREAKER_OFFSET + DTLS_KM_PARAMETER_TIE_BREAKER_LENGTH)
1861
14
#define DTLS_KM_PARAMETER_KMID_OFFSET        (DTLS_KM_PARAMETER_FLAGS_OFFSET + DTLS_KM_PARAMETER_FLAGS_LENGTH)
1862
1863
23
#define DTLS_KM_PARAMETER_C_BIT 0x01
1864
23
#define DTLS_KM_PARAMETER_S_BIT 0x02
1865
23
#define DTLS_KM_PARAMETER_R_BIT 0x04
1866
1867
static const true_false_string sctp_dtls_km_parameter_c_bit_value = {
1868
  "Client role supported",
1869
  "Client role not supported"
1870
};
1871
1872
static const true_false_string sctp_dtls_km_parameter_s_bit_value = {
1873
  "Server role supported",
1874
  "Server role not supported"
1875
};
1876
1877
static const true_false_string sctp_dtls_km_parameter_r_bit_value = {
1878
  "Restart supported",
1879
  "Restart not supported"
1880
};
1881
1882
static void
1883
dissect_dtls_key_management_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item, bool dissecting_init_chunk, bool dissecting_init_ack_chunk)
1884
7
{
1885
7
  proto_item *flags_item;
1886
7
  proto_tree *flags_tree;
1887
7
  uint16_t number_of_ids;
1888
7
  uint16_t id_number, offset;
1889
7
  uint8_t flags, c_bit, s_bit, r_bit;
1890
7
  static int* const flag_list[] = {
1891
7
    &hf_dtls_km_c_bit,
1892
7
    &hf_dtls_km_s_bit,
1893
7
    &hf_dtls_km_r_bit,
1894
7
    NULL
1895
7
  };
1896
1897
7
  if (!dissecting_init_chunk && !dissecting_init_ack_chunk)
1898
2
    expert_add_info(pinfo, parameter_item, &ei_sctp_illegal_parameter_occurrence);
1899
1900
7
  proto_tree_add_item(parameter_tree, hf_dtls_km_tiebreaker, parameter_tvb, DTLS_KM_PARAMETER_TIE_BREAKER_OFFSET, DTLS_KM_PARAMETER_TIE_BREAKER_LENGTH, ENC_BIG_ENDIAN);
1901
7
  flags = tvb_get_uint8(parameter_tvb, DTLS_KM_PARAMETER_FLAGS_OFFSET);
1902
7
  c_bit = flags & DTLS_KM_PARAMETER_C_BIT;
1903
7
  s_bit = flags & DTLS_KM_PARAMETER_S_BIT;
1904
7
  r_bit = flags & DTLS_KM_PARAMETER_R_BIT;
1905
7
  proto_item_append_text(parameter_item, " (");
1906
7
  if (c_bit)
1907
2
    proto_item_append_text(parameter_item, "client%s", s_bit ? " and " : " ");
1908
7
  if (s_bit)
1909
5
    proto_item_append_text(parameter_item, "server");
1910
7
  if (c_bit || s_bit)
1911
5
    proto_item_append_text(parameter_item, " role, ");
1912
7
  proto_item_append_text(parameter_item, "restart%ssupported, ", r_bit ? " " : " not ");
1913
7
  flags_item = proto_tree_add_item(parameter_tree, hf_dtls_km_flags, parameter_tvb, DTLS_KM_PARAMETER_FLAGS_OFFSET, DTLS_KM_PARAMETER_FLAGS_LENGTH, ENC_BIG_ENDIAN);
1914
7
  flags_tree = proto_item_add_subtree(flags_item, ett_sctp_dtls_km_flags);
1915
7
  proto_tree_add_bitmask_list(flags_tree, parameter_tvb, DTLS_KM_PARAMETER_FLAGS_OFFSET, DTLS_KM_PARAMETER_FLAGS_LENGTH, flag_list, ENC_NA);
1916
7
  proto_item_append_text(parameter_item, "ids: ");
1917
7
  number_of_ids = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - DTLS_KM_PARAMETER_KMID_OFFSET) / DTLS_KM_PARAMETER_KMID_LENGTH;
1918
3.33k
  for(id_number = 0, offset = DTLS_KM_PARAMETER_KMID_OFFSET; id_number < number_of_ids; id_number++, offset +=  DTLS_KM_PARAMETER_KMID_LENGTH) {
1919
3.33k
    proto_tree_add_item(parameter_tree, hf_dtls_km_id, parameter_tvb, offset, DTLS_KM_PARAMETER_KMID_LENGTH, ENC_BIG_ENDIAN);
1920
3.33k
    proto_item_append_text(parameter_item, "%s", val_to_str_const(tvb_get_uint8(parameter_tvb, offset), dtls_km_id_values, "Unknown"));
1921
3.33k
    if (id_number < (number_of_ids - 1))
1922
3.32k
      proto_item_append_text(parameter_item, ", ");
1923
3.33k
  }
1924
7
  proto_item_append_text(parameter_item, ")");
1925
7
  if (number_of_ids == 0)
1926
0
    expert_add_info_format(pinfo, parameter_item, &ei_sctp_dtls_km_illegal_number_of_ids, "At least one identifier required.");
1927
7
}
1928
1929
static void
1930
dissect_supported_extensions_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
1931
12
{
1932
12
  uint16_t number_of_types;
1933
12
  uint16_t type_number, offset;
1934
1935
12
  proto_item_append_text(parameter_item, " (Supported types: ");
1936
12
  number_of_types = (tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH) / CHUNK_TYPE_LENGTH;
1937
2.23k
  for(type_number = 0, offset = PARAMETER_VALUE_OFFSET; type_number < number_of_types; type_number++, offset +=  CHUNK_TYPE_LENGTH) {
1938
2.22k
    proto_tree_add_item(parameter_tree, hf_supported_chunk_type, parameter_tvb, offset, CHUNK_TYPE_LENGTH, ENC_BIG_ENDIAN);
1939
2.22k
    proto_item_append_text(parameter_item, "%s", val_to_str_const(tvb_get_uint8(parameter_tvb, offset), chunk_type_values, "Unknown"));
1940
2.22k
    if (type_number < (number_of_types - 1))
1941
2.21k
      proto_item_append_text(parameter_item, ", ");
1942
2.22k
  }
1943
12
  proto_item_append_text(parameter_item, ")");
1944
12
}
1945
1946
static void
1947
dissect_forward_tsn_supported_parameter(tvbuff_t *parameter_tvb _U_)
1948
2
{
1949
2
}
1950
1951
9
#define CORRELATION_ID_LENGTH    4
1952
9
#define CORRELATION_ID_OFFSET    PARAMETER_VALUE_OFFSET
1953
3
#define ADDRESS_PARAMETER_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
1954
1955
static void
1956
// NOLINTNEXTLINE(misc-no-recursion)
1957
dissect_add_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1958
1
{
1959
1
  uint16_t address_length;
1960
1
  tvbuff_t *address_tvb;
1961
1962
1
  address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1963
1964
1
  proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
1965
1
  address_tvb =  tvb_new_subset_length(parameter_tvb, ADDRESS_PARAMETER_OFFSET,
1966
1
                                MIN(address_length, tvb_reported_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)));
1967
1
  proto_item_append_text(parameter_item, " (Address: ");
1968
1
  dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, false, false, false);
1969
1
  proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1970
1
}
1971
1972
static void
1973
// NOLINTNEXTLINE(misc-no-recursion)
1974
dissect_del_ip_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
1975
2
{
1976
2
  uint16_t address_length;
1977
2
  tvbuff_t *address_tvb;
1978
1979
2
  address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
1980
1981
2
  proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
1982
2
  address_tvb =  tvb_new_subset_length(parameter_tvb, ADDRESS_PARAMETER_OFFSET,
1983
2
                                MIN(address_length, tvb_reported_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)));
1984
2
  proto_item_append_text(parameter_item, " (Address: ");
1985
2
  dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, false, false, false);
1986
2
  proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
1987
2
}
1988
1989
0
#define ERROR_CAUSE_IND_CASUES_OFFSET (CORRELATION_ID_OFFSET + CORRELATION_ID_LENGTH)
1990
1991
static void
1992
// NOLINTNEXTLINE(misc-no-recursion)
1993
dissect_error_cause_indication_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree)
1994
0
{
1995
0
  uint16_t causes_length;
1996
0
  tvbuff_t *causes_tvb;
1997
1998
0
  proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
1999
0
  causes_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
2000
0
  causes_tvb    = tvb_new_subset_length(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET,
2001
0
                                 MIN(causes_length, tvb_reported_length_remaining(parameter_tvb, ERROR_CAUSE_IND_CASUES_OFFSET)));
2002
0
  dissect_error_causes(causes_tvb, pinfo,  parameter_tree);
2003
0
}
2004
2005
static void
2006
// NOLINTNEXTLINE(misc-no-recursion)
2007
dissect_set_primary_address_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo, proto_tree *parameter_tree, proto_item *parameter_item)
2008
0
{
2009
0
  uint16_t address_length;
2010
0
  tvbuff_t *address_tvb;
2011
2012
0
  address_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH - CORRELATION_ID_LENGTH;
2013
2014
0
  proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
2015
0
  address_tvb    =  tvb_new_subset_length(parameter_tvb, ADDRESS_PARAMETER_OFFSET,
2016
0
                                   MIN(address_length, tvb_reported_length_remaining(parameter_tvb, ADDRESS_PARAMETER_OFFSET)));
2017
0
  proto_item_append_text(parameter_item, " (Address: ");
2018
0
  dissect_parameter(address_tvb, pinfo, parameter_tree, parameter_item, false, false, false);
2019
0
  proto_item_append_text(parameter_item, ", correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
2020
0
}
2021
2022
static void
2023
dissect_success_report_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
2024
0
{
2025
0
  proto_tree_add_item(parameter_tree, hf_correlation_id, parameter_tvb, CORRELATION_ID_OFFSET, CORRELATION_ID_LENGTH, ENC_BIG_ENDIAN);
2026
0
  proto_item_append_text(parameter_item, " (Correlation ID: %u)", tvb_get_ntohl(parameter_tvb, CORRELATION_ID_OFFSET));
2027
0
}
2028
2029
0
#define ADAP_INDICATION_LENGTH 4
2030
0
#define ADAP_INDICATION_OFFSET PARAMETER_VALUE_OFFSET
2031
2032
static void
2033
dissect_adap_indication_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
2034
0
{
2035
0
  proto_tree_add_item(parameter_tree, hf_adap_indication, parameter_tvb, ADAP_INDICATION_OFFSET, ADAP_INDICATION_LENGTH, ENC_BIG_ENDIAN);
2036
0
  proto_item_append_text(parameter_item, " (Indication: %u)", tvb_get_ntohl(parameter_tvb, ADAP_INDICATION_OFFSET));
2037
0
}
2038
2039
static void
2040
dissect_unknown_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
2041
157
{
2042
157
  uint16_t type, parameter_value_length;
2043
2044
157
  type                   = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
2045
157
  parameter_value_length = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET) - PARAMETER_HEADER_LENGTH;
2046
2047
157
  if (parameter_value_length > 0)
2048
151
    proto_tree_add_item(parameter_tree, hf_parameter_value, parameter_tvb, PARAMETER_VALUE_OFFSET, parameter_value_length, ENC_NA);
2049
2050
157
  proto_item_append_text(parameter_item, " (Type %u, value length: %u byte%s)", type, parameter_value_length, plurality(parameter_value_length, "", "s"));
2051
157
}
2052
2053
9
#define HEARTBEAT_INFO_PARAMETER_ID               0x0001
2054
8
#define IPV4ADDRESS_PARAMETER_ID                  0x0005
2055
5
#define IPV6ADDRESS_PARAMETER_ID                  0x0006
2056
3
#define STATE_COOKIE_PARAMETER_ID                 0x0007
2057
3
#define UNREC_PARA_PARAMETER_ID                   0x0008
2058
2
#define COOKIE_PRESERVATIVE_PARAMETER_ID          0x0009
2059
3
#define HOSTNAME_ADDRESS_PARAMETER_ID             0x000b
2060
38
#define SUPPORTED_ADDRESS_TYPES_PARAMETER_ID      0x000c
2061
18
#define OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID   0x000d
2062
12
#define INCOMING_SSN_RESET_REQUEST_PARAMETER_ID   0x000e
2063
3
#define SSN_TSN_RESET_REQUEST_PARAMETER_ID        0x000f
2064
3
#define RE_CONFIGURATION_RESPONSE_PARAMETER_ID    0x0010
2065
2
#define ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_ID 0x0011
2066
3
#define ADD_INCOMING_STREAMS_REQUEST_PARAMETER_ID 0x0012
2067
2
#define ECN_PARAMETER_ID                          0x8000
2068
2
#define ZERO_CHECKSUM_ACCEPTABLE_PARAMETER_ID     0x8001
2069
2
#define RANDOM_PARAMETER_ID                       0x8002
2070
9
#define CHUNKS_PARAMETER_ID                       0x8003
2071
9
#define HMAC_ALGO_PARAMETER_ID                    0x8004
2072
7
#define DTLS_KEY_MANAGEMENT_PARAMETER_ID          0x8006
2073
12
#define SUPPORTED_EXTENSIONS_PARAMETER_ID         0x8008
2074
2
#define FORWARD_TSN_SUPPORTED_PARAMETER_ID        0xC000
2075
1
#define ADD_IP_ADDRESS_PARAMETER_ID               0xC001
2076
2
#define DEL_IP_ADDRESS_PARAMETER_ID               0xC002
2077
0
#define ERROR_CAUSE_INDICATION_PARAMETER_ID       0xC003
2078
0
#define SET_PRIMARY_ADDRESS_PARAMETER_ID          0xC004
2079
0
#define SUCCESS_REPORT_PARAMETER_ID               0xC005
2080
0
#define ADAP_LAYER_INDICATION_PARAMETER_ID        0xC006
2081
2082
static const value_string parameter_identifier_values[] = {
2083
  { HEARTBEAT_INFO_PARAMETER_ID,               "Heartbeat info"               },
2084
  { IPV4ADDRESS_PARAMETER_ID,                  "IPv4 address"                 },
2085
  { IPV6ADDRESS_PARAMETER_ID,                  "IPv6 address"                 },
2086
  { STATE_COOKIE_PARAMETER_ID,                 "State cookie"                 },
2087
  { UNREC_PARA_PARAMETER_ID,                   "Unrecognized parameter"       },
2088
  { COOKIE_PRESERVATIVE_PARAMETER_ID,          "Cookie preservative"          },
2089
  { HOSTNAME_ADDRESS_PARAMETER_ID,             "Hostname address"             },
2090
  { OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID,   "Outgoing SSN reset request"   },
2091
  { INCOMING_SSN_RESET_REQUEST_PARAMETER_ID,   "Incoming SSN reset request"   },
2092
  { SSN_TSN_RESET_REQUEST_PARAMETER_ID,        "SSN/TSN reset request"        },
2093
  { RE_CONFIGURATION_RESPONSE_PARAMETER_ID,    "Re-configuration response"    },
2094
  { ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_ID, "Add outgoing streams request" },
2095
  { ADD_INCOMING_STREAMS_REQUEST_PARAMETER_ID, "Add incoming streams request" },
2096
  { SUPPORTED_ADDRESS_TYPES_PARAMETER_ID,      "Supported address types"      },
2097
  { ECN_PARAMETER_ID,                          "ECN"                          },
2098
  { ZERO_CHECKSUM_ACCEPTABLE_PARAMETER_ID,     "Zero checksum acceptable"     },
2099
  { RANDOM_PARAMETER_ID,                       "Random"                       },
2100
  { CHUNKS_PARAMETER_ID,                       "Authenticated Chunk list"     },
2101
  { HMAC_ALGO_PARAMETER_ID,                    "Requested HMAC Algorithm"     },
2102
  { DTLS_KEY_MANAGEMENT_PARAMETER_ID,          "DTLS key management"          },
2103
  { SUPPORTED_EXTENSIONS_PARAMETER_ID,         "Supported Extensions"         },
2104
  { FORWARD_TSN_SUPPORTED_PARAMETER_ID,        "Forward TSN supported"        },
2105
  { ADD_IP_ADDRESS_PARAMETER_ID,               "Add IP address"               },
2106
  { DEL_IP_ADDRESS_PARAMETER_ID,               "Delete IP address"            },
2107
  { ERROR_CAUSE_INDICATION_PARAMETER_ID,       "Error cause indication"       },
2108
  { SET_PRIMARY_ADDRESS_PARAMETER_ID,          "Set primary address"          },
2109
  { SUCCESS_REPORT_PARAMETER_ID,               "Success report"               },
2110
  { ADAP_LAYER_INDICATION_PARAMETER_ID,        "Adaptation Layer Indication"  },
2111
  { 0,                                         NULL                           } };
2112
2113
16
#define SCTP_PARAMETER_BIT_1  0x8000
2114
16
#define SCTP_PARAMETER_BIT_2 0x4000
2115
2116
static const true_false_string sctp_parameter_bit_1_value = {
2117
  "Skip parameter and continue processing of the chunk",
2118
  "Stop processing of chunk"
2119
};
2120
2121
static const true_false_string sctp_parameter_bit_2_value = {
2122
  "Do report",
2123
  "Do not report"
2124
};
2125
2126
static void
2127
// NOLINTNEXTLINE(misc-no-recursion)
2128
dissect_parameter(tvbuff_t *parameter_tvb, packet_info *pinfo,
2129
                  proto_tree *chunk_tree, proto_item *additional_item,
2130
                  bool dissecting_init_chunk,
2131
                  bool dissecting_init_ack_chunk,
2132
                  bool final_parameter)
2133
331
{
2134
331
  uint16_t type, length, padding_length, reported_length;
2135
331
  proto_item *parameter_item, *type_item;
2136
331
  proto_tree *parameter_tree, *type_tree;
2137
331
  bool dissecting_init_init_ack_chunk;
2138
2139
331
  dissecting_init_init_ack_chunk = dissecting_init_chunk || dissecting_init_ack_chunk;
2140
2141
331
  type            = tvb_get_ntohs(parameter_tvb, PARAMETER_TYPE_OFFSET);
2142
331
  length          = tvb_get_ntohs(parameter_tvb, PARAMETER_LENGTH_OFFSET);
2143
331
  reported_length = tvb_reported_length(parameter_tvb);
2144
331
  padding_length  = reported_length - length;
2145
2146
331
  parameter_tree = proto_tree_add_subtree_format(chunk_tree, parameter_tvb, PARAMETER_HEADER_OFFSET, -1,
2147
331
            ett_sctp_chunk_parameter, &parameter_item, "%s parameter",
2148
331
            val_to_str_const(type, parameter_identifier_values, "Unknown"));
2149
331
  if (final_parameter) {
2150
219
    if (padding_length > 0) {
2151
216
      expert_add_info(pinfo, parameter_item, &ei_sctp_parameter_padding);
2152
216
    }
2153
219
  } else {
2154
112
    if (reported_length % 4) {
2155
5
      expert_add_info_format(pinfo, parameter_item, &ei_sctp_parameter_length, "Parameter length is not padded to a multiple of 4 bytes (length=%d)", reported_length);
2156
5
    }
2157
112
  }
2158
2159
331
  if (!(chunk_tree || (dissecting_init_init_ack_chunk && (type == IPV4ADDRESS_PARAMETER_ID || type == IPV6ADDRESS_PARAMETER_ID || type == DTLS_KEY_MANAGEMENT_PARAMETER_ID))))
2160
0
    return;
2161
2162
331
  if (chunk_tree) {
2163
317
    type_item = proto_tree_add_item(parameter_tree, hf_parameter_type,   parameter_tvb, PARAMETER_TYPE_OFFSET,   PARAMETER_TYPE_LENGTH,   ENC_BIG_ENDIAN);
2164
317
    type_tree = proto_item_add_subtree(type_item, ett_sctp_parameter_type);
2165
317
    proto_tree_add_item(type_tree, hf_parameter_bit_1,  parameter_tvb, PARAMETER_TYPE_OFFSET,  PARAMETER_TYPE_LENGTH,  ENC_BIG_ENDIAN);
2166
317
    proto_tree_add_item(type_tree, hf_parameter_bit_2,  parameter_tvb, PARAMETER_TYPE_OFFSET,  PARAMETER_TYPE_LENGTH,  ENC_BIG_ENDIAN);
2167
317
    proto_tree_add_item(parameter_tree, hf_parameter_length, parameter_tvb, PARAMETER_LENGTH_OFFSET, PARAMETER_LENGTH_LENGTH, ENC_BIG_ENDIAN);
2168
    /* XXX - add expert info if length is bogus? */
2169
317
  } else {
2170
14
    parameter_item = NULL;
2171
14
    parameter_tree = NULL;
2172
14
  }
2173
2174
331
  increment_dissection_depth(pinfo);
2175
331
  switch(type) {
2176
9
  case HEARTBEAT_INFO_PARAMETER_ID:
2177
9
    dissect_heartbeat_info_parameter(parameter_tvb, parameter_tree, parameter_item);
2178
9
    break;
2179
8
  case IPV4ADDRESS_PARAMETER_ID:
2180
8
    dissect_ipv4_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
2181
8
    break;
2182
5
  case IPV6ADDRESS_PARAMETER_ID:
2183
5
    dissect_ipv6_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item, additional_item, dissecting_init_init_ack_chunk);
2184
5
    break;
2185
3
  case STATE_COOKIE_PARAMETER_ID:
2186
3
    dissect_state_cookie_parameter(parameter_tvb, parameter_tree, parameter_item);
2187
3
    break;
2188
3
  case UNREC_PARA_PARAMETER_ID:
2189
3
    dissect_unrecognized_parameters_parameter(parameter_tvb, pinfo, parameter_tree);
2190
3
    break;
2191
2
  case COOKIE_PRESERVATIVE_PARAMETER_ID:
2192
2
    dissect_cookie_preservative_parameter(parameter_tvb, parameter_tree, parameter_item);
2193
2
    break;
2194
3
  case HOSTNAME_ADDRESS_PARAMETER_ID:
2195
3
    dissect_hostname_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item, additional_item);
2196
3
    break;
2197
38
  case SUPPORTED_ADDRESS_TYPES_PARAMETER_ID:
2198
38
    dissect_supported_address_types_parameter(parameter_tvb, parameter_tree, parameter_item);
2199
38
    break;
2200
18
  case OUTGOING_SSN_RESET_REQUEST_PARAMETER_ID:
2201
18
    dissect_outgoing_ssn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
2202
18
    break;
2203
12
  case INCOMING_SSN_RESET_REQUEST_PARAMETER_ID:
2204
12
    dissect_incoming_ssn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
2205
12
    break;
2206
3
  case SSN_TSN_RESET_REQUEST_PARAMETER_ID:
2207
3
    dissect_ssn_tsn_reset_request_parameter(parameter_tvb, parameter_tree, parameter_item);
2208
3
    break;
2209
3
  case RE_CONFIGURATION_RESPONSE_PARAMETER_ID:
2210
3
    dissect_re_configuration_response_parameter(parameter_tvb, parameter_tree, parameter_item);
2211
3
    break;
2212
2
  case ADD_OUTGOING_STREAMS_REQUEST_PARAMETER_ID:
2213
2
    dissect_add_outgoing_streams_parameter(parameter_tvb, parameter_tree, parameter_item);
2214
2
    break;
2215
3
  case ADD_INCOMING_STREAMS_REQUEST_PARAMETER_ID:
2216
3
    dissect_add_incoming_streams_parameter(parameter_tvb, parameter_tree, parameter_item);
2217
3
    break;
2218
2
  case ECN_PARAMETER_ID:
2219
2
    dissect_ecn_parameter(parameter_tvb);
2220
2
    break;
2221
2
  case ZERO_CHECKSUM_ACCEPTABLE_PARAMETER_ID:
2222
2
    dissect_zero_checksum_acceptable_parameter(parameter_tvb, parameter_tree, parameter_item);
2223
2
    break;
2224
2
  case RANDOM_PARAMETER_ID:
2225
2
    dissect_random_parameter(parameter_tvb, parameter_tree);
2226
2
    break;
2227
9
  case CHUNKS_PARAMETER_ID:
2228
9
    dissect_chunks_parameter(parameter_tvb, parameter_tree, parameter_item);
2229
9
    break;
2230
9
  case HMAC_ALGO_PARAMETER_ID:
2231
9
    dissect_hmac_algo_parameter(parameter_tvb, parameter_tree, parameter_item);
2232
9
    break;
2233
7
  case DTLS_KEY_MANAGEMENT_PARAMETER_ID:
2234
7
    dissect_dtls_key_management_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item, dissecting_init_chunk, dissecting_init_ack_chunk);
2235
7
    break;
2236
12
  case SUPPORTED_EXTENSIONS_PARAMETER_ID:
2237
12
    dissect_supported_extensions_parameter(parameter_tvb, parameter_tree, parameter_item);
2238
12
    break;
2239
2
  case FORWARD_TSN_SUPPORTED_PARAMETER_ID:
2240
2
    dissect_forward_tsn_supported_parameter(parameter_tvb);
2241
2
    break;
2242
1
  case ADD_IP_ADDRESS_PARAMETER_ID:
2243
1
    dissect_add_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
2244
1
    break;
2245
2
  case DEL_IP_ADDRESS_PARAMETER_ID:
2246
2
    dissect_del_ip_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
2247
2
    break;
2248
0
  case ERROR_CAUSE_INDICATION_PARAMETER_ID:
2249
0
    dissect_error_cause_indication_parameter(parameter_tvb, pinfo, parameter_tree);
2250
0
    break;
2251
0
  case SET_PRIMARY_ADDRESS_PARAMETER_ID:
2252
0
    dissect_set_primary_address_parameter(parameter_tvb, pinfo, parameter_tree, parameter_item);
2253
0
    break;
2254
0
  case SUCCESS_REPORT_PARAMETER_ID:
2255
0
    dissect_success_report_parameter(parameter_tvb, parameter_tree, parameter_item);
2256
0
    break;
2257
0
  case ADAP_LAYER_INDICATION_PARAMETER_ID:
2258
0
    dissect_adap_indication_parameter(parameter_tvb, parameter_tree, parameter_item);
2259
0
    break;
2260
157
  default:
2261
157
    dissect_unknown_parameter(parameter_tvb, parameter_tree, parameter_item);
2262
157
    break;
2263
331
  }
2264
118
  decrement_dissection_depth(pinfo);
2265
2266
118
  if (padding_length > 0) {
2267
81
    proto_tree_add_item(parameter_tree, hf_parameter_padding, parameter_tvb, PARAMETER_HEADER_OFFSET + length, padding_length, ENC_NA);
2268
81
  }
2269
118
}
2270
2271
static void
2272
// NOLINTNEXTLINE(misc-no-recursion)
2273
dissect_parameters(tvbuff_t *parameters_tvb, packet_info *pinfo, proto_tree *tree, proto_item *additional_item, bool dissecting_init_chunk, bool dissecting_init_ack_chunk)
2274
199
{
2275
199
  int offset, length, total_length, remaining_length;
2276
199
  tvbuff_t *parameter_tvb;
2277
199
  bool final_parameter;
2278
2279
199
  offset = 0;
2280
199
  remaining_length = tvb_reported_length_remaining(parameters_tvb, offset);
2281
476
  while (remaining_length > 0) {
2282
277
    if ((offset > 0) && additional_item)
2283
1
      proto_item_append_text(additional_item, " ");
2284
2285
277
    length       = tvb_get_ntohs(parameters_tvb, offset + PARAMETER_LENGTH_OFFSET);
2286
277
    total_length = WS_ROUNDUP_4(length);
2287
2288
    /*  If we have less bytes than we need, throw an exception while dissecting
2289
     *  the parameter--not when generating the parameter_tvb below.
2290
     */
2291
277
    total_length = MIN(total_length, remaining_length);
2292
2293
    /* create a tvb for the parameter including the padding bytes */
2294
277
    parameter_tvb  = tvb_new_subset_length(parameters_tvb, offset, total_length);
2295
    /* get rid of the handled parameter */
2296
277
    offset += total_length;
2297
277
    remaining_length = tvb_reported_length_remaining(parameters_tvb, offset);
2298
277
    if (remaining_length > 0) {
2299
100
      final_parameter = false;
2300
177
    } else {
2301
177
      final_parameter = true;
2302
177
    }
2303
277
    dissect_parameter(parameter_tvb, pinfo, tree, additional_item, dissecting_init_chunk, dissecting_init_ack_chunk, final_parameter);
2304
277
  }
2305
199
}
2306
2307
2308
/*
2309
 * Code to handle error causes for ABORT and ERROR chunks
2310
 */
2311
2312
2313
1.02k
#define CAUSE_CODE_LENGTH            2
2314
432
#define CAUSE_LENGTH_LENGTH          2
2315
112
#define CAUSE_HEADER_LENGTH          (CAUSE_CODE_LENGTH + CAUSE_LENGTH_LENGTH)
2316
2317
1.38k
#define CAUSE_HEADER_OFFSET          0
2318
1.16k
#define CAUSE_CODE_OFFSET            CAUSE_HEADER_OFFSET
2319
754
#define CAUSE_LENGTH_OFFSET          (CAUSE_CODE_OFFSET + CAUSE_CODE_LENGTH)
2320
161
#define CAUSE_INFO_OFFSET            (CAUSE_LENGTH_OFFSET + CAUSE_LENGTH_LENGTH)
2321
2322
2323
10
#define CAUSE_STREAM_IDENTIFIER_LENGTH 2
2324
5
#define CAUSE_RESERVED_LENGTH 2
2325
15
#define CAUSE_STREAM_IDENTIFIER_OFFSET CAUSE_INFO_OFFSET
2326
5
#define CAUSE_RESERVED_OFFSET          (CAUSE_STREAM_IDENTIFIER_OFFSET + CAUSE_STREAM_IDENTIFIER_LENGTH)
2327
2328
static void
2329
dissect_invalid_stream_identifier_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
2330
5
{
2331
5
  proto_tree_add_item(cause_tree, hf_cause_stream_identifier, cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET, CAUSE_STREAM_IDENTIFIER_LENGTH, ENC_BIG_ENDIAN);
2332
5
  proto_tree_add_item(cause_tree, hf_cause_reserved,          cause_tvb, CAUSE_RESERVED_OFFSET,          CAUSE_RESERVED_LENGTH,          ENC_BIG_ENDIAN);
2333
5
  proto_item_append_text(cause_item, " (SID: %u)", tvb_get_ntohs(cause_tvb, CAUSE_STREAM_IDENTIFIER_OFFSET));
2334
5
}
2335
2336
30
#define CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH 4
2337
3.51k
#define CAUSE_MISSING_PARAMETER_TYPE_LENGTH       2
2338
2339
30
#define CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET CAUSE_INFO_OFFSET
2340
15
#define CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET (CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET + \
2341
15
                                                   CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH )
2342
2343
static void
2344
dissect_missing_mandatory_parameters_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
2345
15
{
2346
15
  uint32_t number_of_missing_parameters, missing_parameter_number;
2347
15
  unsigned   offset;
2348
2349
15
  proto_tree_add_item_ret_uint(cause_tree, hf_cause_number_of_missing_parameters, cause_tvb, CAUSE_NUMBER_OF_MISSING_PARAMETERS_OFFSET,
2350
15
                               CAUSE_NUMBER_OF_MISSING_PARAMETERS_LENGTH, ENC_BIG_ENDIAN, &number_of_missing_parameters);
2351
15
  offset = CAUSE_FIRST_MISSING_PARAMETER_TYPE_OFFSET;
2352
1.77k
  for(missing_parameter_number = 0; missing_parameter_number < number_of_missing_parameters; missing_parameter_number++) {
2353
1.75k
    proto_tree_add_item(cause_tree, hf_cause_missing_parameter_type, cause_tvb, offset, CAUSE_MISSING_PARAMETER_TYPE_LENGTH, ENC_BIG_ENDIAN);
2354
1.75k
    offset +=  CAUSE_MISSING_PARAMETER_TYPE_LENGTH;
2355
1.75k
  }
2356
15
}
2357
2358
2
#define CAUSE_MEASURE_OF_STALENESS_LENGTH 4
2359
4
#define CAUSE_MEASURE_OF_STALENESS_OFFSET CAUSE_INFO_OFFSET
2360
2361
static void
2362
dissect_stale_cookie_error_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
2363
2
{
2364
2
  proto_tree_add_item(cause_tree, hf_cause_measure_of_staleness, cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET, CAUSE_MEASURE_OF_STALENESS_LENGTH, ENC_BIG_ENDIAN);
2365
2
  proto_item_append_text(cause_item, " (Measure: %u usec)", tvb_get_ntohl(cause_tvb, CAUSE_MEASURE_OF_STALENESS_OFFSET));
2366
2
}
2367
2368
static void
2369
dissect_out_of_resource_cause(tvbuff_t *cause_tvb _U_)
2370
2
{
2371
2
}
2372
2373
static void
2374
// NOLINTNEXTLINE(misc-no-recursion)
2375
dissect_unresolvable_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2376
4
{
2377
4
  uint16_t parameter_length;
2378
4
  tvbuff_t *parameter_tvb;
2379
2380
4
  parameter_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2381
4
  parameter_tvb    = tvb_new_subset_length(cause_tvb, CAUSE_INFO_OFFSET,
2382
4
                                    MIN(parameter_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2383
4
  dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, false, false, true);
2384
4
}
2385
2386
static bool
2387
dissect_sctp_chunk(tvbuff_t *chunk_tvb, packet_info *pinfo, proto_tree *tree, proto_tree *sctp_tree, sctp_half_assoc_t *assoc, bool useinfo);
2388
2389
static void
2390
// NOLINTNEXTLINE(misc-no-recursion)
2391
dissect_unrecognized_chunk_type_cause(tvbuff_t *cause_tvb,  packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2392
5
{
2393
5
  uint16_t chunk_length;
2394
5
  uint8_t unrecognized_type;
2395
5
  tvbuff_t *unrecognized_chunk_tvb;
2396
2397
5
  chunk_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2398
5
  unrecognized_chunk_tvb = tvb_new_subset_length(cause_tvb, CAUSE_INFO_OFFSET,
2399
5
                                          MIN(chunk_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2400
5
  dissect_sctp_chunk(unrecognized_chunk_tvb, pinfo, cause_tree,cause_tree, NULL, false);
2401
5
  unrecognized_type   = tvb_get_uint8(unrecognized_chunk_tvb, CHUNK_TYPE_OFFSET);
2402
5
  proto_item_append_text(cause_item, " (Type: %u (%s))", unrecognized_type, val_to_str_const(unrecognized_type, chunk_type_values, "unknown"));
2403
5
}
2404
2405
static void
2406
dissect_invalid_mandatory_parameter_cause(tvbuff_t *cause_tvb _U_)
2407
2
{
2408
2
}
2409
2410
static void
2411
// NOLINTNEXTLINE(misc-no-recursion)
2412
dissect_unrecognized_parameters_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
2413
2
{
2414
2
  uint16_t cause_info_length;
2415
2
  tvbuff_t *unrecognized_parameters_tvb;
2416
2417
2
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2418
2419
2
  unrecognized_parameters_tvb = tvb_new_subset_length(cause_tvb, CAUSE_INFO_OFFSET,
2420
2
                                               MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2421
2
  dissect_parameters(unrecognized_parameters_tvb, pinfo, cause_tree, NULL, false, false);
2422
2
}
2423
2424
3
#define CAUSE_TSN_LENGTH 4
2425
6
#define CAUSE_TSN_OFFSET CAUSE_INFO_OFFSET
2426
2427
static void
2428
dissect_no_user_data_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
2429
3
{
2430
3
  proto_tree_add_item(cause_tree, hf_cause_tsn, cause_tvb, CAUSE_TSN_OFFSET, CAUSE_TSN_LENGTH, ENC_BIG_ENDIAN);
2431
3
  proto_item_append_text(cause_item, " (TSN: %u)", tvb_get_ntohl(cause_tvb, CAUSE_TSN_OFFSET));
2432
3
}
2433
2434
static void
2435
dissect_cookie_received_while_shutting_down_cause(tvbuff_t *cause_tvb _U_)
2436
3
{
2437
3
}
2438
2439
static void
2440
// NOLINTNEXTLINE(misc-no-recursion)
2441
dissect_restart_with_new_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2442
2
{
2443
2
  uint16_t cause_info_length;
2444
2
  tvbuff_t *parameter_tvb;
2445
2446
2
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2447
2
  parameter_tvb     = tvb_new_subset_length(cause_tvb, CAUSE_INFO_OFFSET,
2448
2
                                     MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2449
2
  proto_item_append_text(cause_item, " (New addresses: ");
2450
2
  dissect_parameters(parameter_tvb, pinfo, cause_tree, cause_item, false, false);
2451
2
  proto_item_append_text(cause_item, ")");
2452
2
}
2453
2454
static void
2455
dissect_user_initiated_abort_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
2456
1
{
2457
1
  uint16_t cause_info_length;
2458
2459
1
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2460
1
  if (cause_info_length > 0)
2461
1
    proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, ENC_NA);
2462
1
}
2463
2464
static void
2465
dissect_protocol_violation_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree)
2466
2
{
2467
2
  uint16_t cause_info_length;
2468
2469
2
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2470
2
  if (cause_info_length > 0)
2471
2
    proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, ENC_NA);
2472
2
}
2473
2474
static void
2475
dissect_missing_dtls_chunk_support_cause(tvbuff_t *cause_tvb _U_, proto_tree *cause_tree _U_)
2476
2
{
2477
2
}
2478
2479
static void
2480
dissect_no_common_dtls_key_management_method_cause(tvbuff_t *cause_tvb _U_, proto_tree *cause_tree _U_)
2481
0
{
2482
0
}
2483
2484
static void
2485
dissect_dtls_key_management_tie_breaker_collision_cause(tvbuff_t *cause_tvb _U_, proto_tree *cause_tree _U_)
2486
0
{
2487
0
}
2488
2489
static void
2490
dissect_incompatible_dtls_key_management_roles_cause(tvbuff_t *cause_tvb _U_, proto_tree *cause_tree _U_)
2491
0
{
2492
0
}
2493
2494
static void
2495
// NOLINTNEXTLINE(misc-no-recursion)
2496
dissect_delete_last_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2497
1
{
2498
1
  uint16_t cause_info_length;
2499
1
  tvbuff_t *parameter_tvb;
2500
2501
1
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2502
1
  parameter_tvb     = tvb_new_subset_length(cause_tvb, CAUSE_INFO_OFFSET,
2503
1
                                     MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2504
1
  proto_item_append_text(cause_item, " (Last address: ");
2505
1
  dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, false, false, false);
2506
1
  proto_item_append_text(cause_item, ")");
2507
1
}
2508
2509
static void
2510
// NOLINTNEXTLINE(misc-no-recursion)
2511
dissect_resource_outage_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
2512
1
{
2513
1
  uint16_t cause_info_length;
2514
1
  tvbuff_t *parameter_tvb;
2515
2516
1
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2517
1
  parameter_tvb     = tvb_new_subset_length(cause_tvb, CAUSE_INFO_OFFSET,
2518
1
                                     MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2519
1
  dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, false, false, false);
2520
1
}
2521
2522
static void
2523
// NOLINTNEXTLINE(misc-no-recursion)
2524
dissect_delete_source_address_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree, proto_item *cause_item)
2525
0
{
2526
0
  uint16_t cause_info_length;
2527
0
  tvbuff_t *parameter_tvb;
2528
2529
0
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2530
0
  parameter_tvb     = tvb_new_subset_length(cause_tvb, CAUSE_INFO_OFFSET,
2531
0
                                     MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2532
0
  proto_item_append_text(cause_item, " (Deleted address: ");
2533
0
  dissect_parameter(parameter_tvb, pinfo, cause_tree, cause_item, false, false, false);
2534
0
  proto_item_append_text(cause_item, ")");
2535
0
}
2536
2537
static void
2538
// NOLINTNEXTLINE(misc-no-recursion)
2539
dissect_request_refused_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *cause_tree)
2540
1
{
2541
1
  uint16_t cause_info_length;
2542
1
  tvbuff_t *parameter_tvb;
2543
2544
1
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2545
1
  parameter_tvb     = tvb_new_subset_length(cause_tvb, CAUSE_INFO_OFFSET,
2546
1
                                     MIN(cause_info_length, tvb_reported_length_remaining(cause_tvb, CAUSE_INFO_OFFSET)));
2547
1
  dissect_parameter(parameter_tvb, pinfo, cause_tree, NULL, false, false, false);
2548
1
}
2549
2550
static void
2551
dissect_unsupported_hmac_id_cause(tvbuff_t *cause_tvb, packet_info *pinfo _U_, proto_tree *cause_tree)
2552
0
{
2553
0
  proto_tree_add_item(cause_tree, hf_hmac_id, cause_tvb, CAUSE_INFO_OFFSET, HMAC_ID_LENGTH, ENC_BIG_ENDIAN);
2554
0
}
2555
2556
static void
2557
dissect_unknown_cause(tvbuff_t *cause_tvb, proto_tree *cause_tree, proto_item *cause_item)
2558
93
{
2559
93
  uint16_t cause_info_length;
2560
2561
93
  cause_info_length = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET) - CAUSE_HEADER_LENGTH;
2562
93
  if (cause_info_length > 0)
2563
87
    proto_tree_add_item(cause_tree, hf_cause_info, cause_tvb, CAUSE_INFO_OFFSET, cause_info_length, ENC_NA);
2564
93
  proto_item_append_text(cause_item, " (Code: %u, information length: %u byte%s)", tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET), cause_info_length, plurality(cause_info_length, "", "s"));
2565
93
}
2566
2567
5
#define INVALID_STREAM_IDENTIFIER                  0x0001
2568
15
#define MISSING_MANDATORY_PARAMETERS               0x0002
2569
2
#define STALE_COOKIE_ERROR                         0x0003
2570
2
#define OUT_OF_RESOURCE                            0x0004
2571
4
#define UNRESOLVABLE_ADDRESS                       0x0005
2572
5
#define UNRECOGNIZED_CHUNK_TYPE                    0x0006
2573
2
#define INVALID_MANDATORY_PARAMETER                0x0007
2574
2
#define UNRECOGNIZED_PARAMETERS                    0x0008
2575
3
#define NO_USER_DATA                               0x0009
2576
3
#define COOKIE_RECEIVED_WHILE_SHUTTING_DOWN        0x000a
2577
2
#define RESTART_WITH_NEW_ADDRESSES                 0x000b
2578
1
#define USER_INITIATED_ABORT                       0x000c
2579
2
#define PROTOCOL_VIOLATION                         0x000d
2580
2
#define MISSING_DTLS_CHUNK_SUPPORT                 0x0064
2581
0
#define NO_COMMON_DTLS_KEY_MANAGEMENT_METHOD       0x0065
2582
0
#define DTLS_KEY_MANAGEMENT_TIE_BREAKER_COLLISION  0x0066
2583
0
#define INCOMPATIBLE_DTLS_KEY_MANAGEMENT_ROLES     0x0067
2584
1
#define REQUEST_TO_DELETE_LAST_ADDRESS             0x00a0
2585
1
#define OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE 0x00a1
2586
0
#define REQUEST_TO_DELETE_SOURCE_ADDRESS           0x00a2
2587
#define ABORT_DUE_TO_ILLEGAL_ASCONF                0x00a3
2588
1
#define REQUEST_REFUSED                            0x00a4
2589
0
#define UNSUPPORTED_HMAC_ID                        0x0105
2590
2591
static const value_string cause_code_values[] = {
2592
  { INVALID_STREAM_IDENTIFIER,                  "Invalid stream identifier" },
2593
  { MISSING_MANDATORY_PARAMETERS,               "Missing mandatory parameter" },
2594
  { STALE_COOKIE_ERROR,                         "Stale cookie error" },
2595
  { OUT_OF_RESOURCE,                            "Out of resource" },
2596
  { UNRESOLVABLE_ADDRESS,                       "Unresolvable address" },
2597
  { UNRECOGNIZED_CHUNK_TYPE,                    "Unrecognized chunk type" },
2598
  { INVALID_MANDATORY_PARAMETER,                "Invalid mandatory parameter" },
2599
  { UNRECOGNIZED_PARAMETERS,                    "Unrecognized parameters" },
2600
  { NO_USER_DATA,                               "No user data" },
2601
  { COOKIE_RECEIVED_WHILE_SHUTTING_DOWN,        "Cookie received while shutting down" },
2602
  { RESTART_WITH_NEW_ADDRESSES,                 "Restart of an association with new addresses" },
2603
  { USER_INITIATED_ABORT,                       "User initiated ABORT" },
2604
  { PROTOCOL_VIOLATION,                         "Protocol violation" },
2605
  { MISSING_DTLS_CHUNK_SUPPORT,                 "Missing DTLS chunk support" },
2606
  { NO_COMMON_DTLS_KEY_MANAGEMENT_METHOD,       "No common DTLS key management method" },
2607
  { DTLS_KEY_MANAGEMENT_TIE_BREAKER_COLLISION,  "DTLS key management tie breaker collision" },
2608
  { INCOMPATIBLE_DTLS_KEY_MANAGEMENT_ROLES,     "Incompatible DTLS key management roles" },
2609
  { REQUEST_TO_DELETE_LAST_ADDRESS,             "Request to delete last address" },
2610
  { OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE, "Operation refused due to resource shortage" },
2611
  { REQUEST_TO_DELETE_SOURCE_ADDRESS,           "Request to delete source address" },
2612
  { ABORT_DUE_TO_ILLEGAL_ASCONF,                "Association Aborted due to illegal ASCONF-ACK" },
2613
  { REQUEST_REFUSED,                            "Request refused - no authorization" },
2614
  { UNSUPPORTED_HMAC_ID,                        "Unsupported HMAC identifier" },
2615
  { 0,                                          NULL } };
2616
2617
2618
static void
2619
// NOLINTNEXTLINE(misc-no-recursion)
2620
dissect_error_cause(tvbuff_t *cause_tvb, packet_info *pinfo, proto_tree *chunk_tree)
2621
159
{
2622
159
  uint16_t code, length, padding_length;
2623
159
  proto_item *cause_item;
2624
159
  proto_tree *cause_tree;
2625
2626
159
  code           = tvb_get_ntohs(cause_tvb, CAUSE_CODE_OFFSET);
2627
159
  length         = tvb_get_ntohs(cause_tvb, CAUSE_LENGTH_OFFSET);
2628
159
  padding_length = tvb_reported_length(cause_tvb) - length;
2629
2630
159
  cause_tree = proto_tree_add_subtree_format(chunk_tree, cause_tvb, CAUSE_HEADER_OFFSET, -1,
2631
159
            ett_sctp_chunk_cause, &cause_item, "%s cause", val_to_str_const(code, cause_code_values, "Unknown"));
2632
2633
159
  proto_tree_add_item(cause_tree, hf_cause_code, cause_tvb,   CAUSE_CODE_OFFSET,   CAUSE_CODE_LENGTH,   ENC_BIG_ENDIAN);
2634
159
  proto_tree_add_item(cause_tree, hf_cause_length, cause_tvb, CAUSE_LENGTH_OFFSET, CAUSE_LENGTH_LENGTH, ENC_BIG_ENDIAN);
2635
  /* XXX - add expert info if length is bogus? */
2636
2637
159
  increment_dissection_depth(pinfo);
2638
159
  switch(code) {
2639
5
  case INVALID_STREAM_IDENTIFIER:
2640
5
    dissect_invalid_stream_identifier_cause(cause_tvb, cause_tree, cause_item);
2641
5
    break;
2642
15
  case MISSING_MANDATORY_PARAMETERS:
2643
15
    dissect_missing_mandatory_parameters_cause(cause_tvb, cause_tree);
2644
15
    break;
2645
2
  case STALE_COOKIE_ERROR:
2646
2
    dissect_stale_cookie_error_cause(cause_tvb, cause_tree, cause_item);
2647
2
    break;
2648
2
  case OUT_OF_RESOURCE:
2649
2
    dissect_out_of_resource_cause(cause_tvb);
2650
2
    break;
2651
4
  case UNRESOLVABLE_ADDRESS:
2652
4
    dissect_unresolvable_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
2653
4
    break;
2654
5
  case UNRECOGNIZED_CHUNK_TYPE:
2655
5
    dissect_unrecognized_chunk_type_cause(cause_tvb, pinfo, cause_tree, cause_item);
2656
5
    break;
2657
2
  case INVALID_MANDATORY_PARAMETER:
2658
2
    dissect_invalid_mandatory_parameter_cause(cause_tvb);
2659
2
    break;
2660
2
  case UNRECOGNIZED_PARAMETERS:
2661
2
    dissect_unrecognized_parameters_cause(cause_tvb, pinfo, cause_tree);
2662
2
    break;
2663
3
  case NO_USER_DATA:
2664
3
    dissect_no_user_data_cause(cause_tvb, cause_tree, cause_item);
2665
3
    break;
2666
3
  case COOKIE_RECEIVED_WHILE_SHUTTING_DOWN:
2667
3
    dissect_cookie_received_while_shutting_down_cause(cause_tvb);
2668
3
    break;
2669
2
  case RESTART_WITH_NEW_ADDRESSES:
2670
2
    dissect_restart_with_new_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
2671
2
    break;
2672
1
  case USER_INITIATED_ABORT:
2673
1
    dissect_user_initiated_abort_cause(cause_tvb, cause_tree);
2674
1
    break;
2675
2
  case PROTOCOL_VIOLATION:
2676
2
    dissect_protocol_violation_cause(cause_tvb, cause_tree);
2677
2
    break;
2678
2
  case MISSING_DTLS_CHUNK_SUPPORT:
2679
2
    dissect_missing_dtls_chunk_support_cause(cause_tvb, cause_tree);
2680
2
    break;
2681
0
  case NO_COMMON_DTLS_KEY_MANAGEMENT_METHOD:
2682
0
    dissect_no_common_dtls_key_management_method_cause(cause_tvb, cause_tree);
2683
0
    break;
2684
0
  case DTLS_KEY_MANAGEMENT_TIE_BREAKER_COLLISION:
2685
0
    dissect_dtls_key_management_tie_breaker_collision_cause(cause_tvb, cause_tree);
2686
0
    break;
2687
0
  case INCOMPATIBLE_DTLS_KEY_MANAGEMENT_ROLES:
2688
0
    dissect_incompatible_dtls_key_management_roles_cause(cause_tvb, cause_tree);
2689
0
    break;
2690
1
  case REQUEST_TO_DELETE_LAST_ADDRESS:
2691
1
    dissect_delete_last_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
2692
1
    break;
2693
1
  case OPERATION_REFUSED_DUE_TO_RESOURCE_SHORTAGE:
2694
1
    dissect_resource_outage_cause(cause_tvb, pinfo, cause_tree);
2695
1
    break;
2696
0
  case REQUEST_TO_DELETE_SOURCE_ADDRESS:
2697
0
    dissect_delete_source_address_cause(cause_tvb, pinfo, cause_tree, cause_item);
2698
0
    break;
2699
1
  case REQUEST_REFUSED:
2700
1
    dissect_request_refused_cause(cause_tvb, pinfo, cause_tree);
2701
1
    break;
2702
0
  case UNSUPPORTED_HMAC_ID:
2703
0
    dissect_unsupported_hmac_id_cause(cause_tvb, pinfo, cause_tree);
2704
0
    break;
2705
93
  default:
2706
93
    dissect_unknown_cause(cause_tvb, cause_tree, cause_item);
2707
93
    break;
2708
159
  }
2709
91
  decrement_dissection_depth(pinfo);
2710
2711
91
  if (padding_length > 0)
2712
61
    proto_tree_add_item(cause_tree, hf_cause_padding, cause_tvb, CAUSE_HEADER_OFFSET + length, padding_length, ENC_NA);
2713
91
}
2714
2715
static void
2716
// NOLINTNEXTLINE(misc-no-recursion)
2717
dissect_error_causes(tvbuff_t *causes_tvb, packet_info *pinfo, proto_tree *tree)
2718
98
{
2719
98
  int offset, length, total_length, remaining_length;
2720
98
  tvbuff_t *cause_tvb;
2721
2722
98
  offset = 0;
2723
261
  while((remaining_length = tvb_reported_length_remaining(causes_tvb, offset))) {
2724
163
    length       = tvb_get_ntohs(causes_tvb, offset + CAUSE_LENGTH_OFFSET);
2725
163
    total_length = WS_ROUNDUP_4(length);
2726
2727
    /*  If we have less bytes than we need, throw an exception while dissecting
2728
     *  the cause--not when generating the causes_tvb below.
2729
     */
2730
163
    total_length = MIN(total_length, remaining_length);
2731
2732
    /* create a tvb for the parameter including the padding bytes */
2733
163
    cause_tvb    = tvb_new_subset_length(causes_tvb, offset, total_length);
2734
2735
163
    dissect_error_cause(cause_tvb, pinfo, tree);
2736
2737
    /* get rid of the handled cause */
2738
163
    offset += total_length;
2739
163
  }
2740
98
}
2741
2742
2743
/*
2744
 * Code to actually dissect the packets
2745
*/
2746
2747
static bool try_heuristic_first;
2748
2749
static bool
2750
dissect_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, uint32_t ppi)
2751
18.8k
{
2752
18.8k
  uint32_t low_port, high_port;
2753
18.8k
  bool try_ppi, try_low_port, try_high_port;
2754
18.8k
  heur_dtbl_entry_t *hdtbl_entry;
2755
2756
18.8k
  if (enable_ulp_dissection) {
2757
2758
    /* XXX - we ignore port numbers of 0, as some dissectors use a port
2759
       number of 0 to disable the port. */
2760
18.8k
    if (pinfo->srcport > pinfo->destport) {
2761
8.91k
      low_port = pinfo->destport;
2762
8.91k
      high_port = pinfo->srcport;
2763
9.97k
    } else {
2764
9.97k
      low_port = pinfo->srcport;
2765
9.97k
      high_port = pinfo->destport;
2766
9.97k
    }
2767
2768
18.8k
    try_ppi = false;
2769
18.8k
    if (dissector_is_uint_changed(sctp_ppi_dissector_table, ppi)) {
2770
0
      if (dissector_try_uint_with_data(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree, true, GUINT_TO_POINTER(ppi))) {
2771
0
        return true;
2772
0
      }
2773
18.8k
    } else {
2774
      /* The default; try it later */
2775
18.8k
      try_ppi = true;
2776
18.8k
    }
2777
2778
18.8k
    try_low_port = false;
2779
18.8k
    if (low_port != 0) {
2780
15.4k
      if (dissector_is_uint_changed(sctp_port_dissector_table, low_port)) {
2781
0
        if (dissector_try_uint_with_data(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree, true, GUINT_TO_POINTER(ppi))) {
2782
0
          return true;
2783
0
        }
2784
15.4k
      } else {
2785
        /* The default; try it later */
2786
15.4k
        try_low_port = true;
2787
15.4k
      }
2788
15.4k
    }
2789
2790
18.8k
    try_high_port = false;
2791
18.8k
    if (high_port != 0) {
2792
18.0k
      if (dissector_is_uint_changed(sctp_port_dissector_table, high_port)) {
2793
0
        if (dissector_try_uint_with_data(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree, true, GUINT_TO_POINTER(ppi))) {
2794
0
          return true;
2795
0
        }
2796
18.0k
      } else {
2797
        /* The default; try it later */
2798
18.0k
        try_high_port = true;
2799
18.0k
      }
2800
18.0k
    }
2801
2802
18.8k
    if (try_heuristic_first) {
2803
      /* do lookup with the heuristic subdissector table */
2804
0
      if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, GUINT_TO_POINTER(ppi)))
2805
0
         return true;
2806
0
    }
2807
2808
    /* Do lookups with the subdissector table.
2809
       First try the PPI.
2810
2811
       When trying port numbers, we try the port number with the lower value
2812
       first, followed by the port number with the higher value.  This means
2813
       that, for packets where a dissector is registered for *both* port
2814
       numbers, and where there's no match on the PPI:
2815
2816
    1) we pick the same dissector for traffic going in both directions;
2817
2818
    2) we prefer the port number that's more likely to be the right
2819
       one (as that prefers well-known ports to reserved ports);
2820
2821
       although there is, of course, no guarantee that any such strategy
2822
       will always pick the right port number. */
2823
18.8k
    if (try_ppi &&
2824
18.8k
        dissector_try_uint_with_data(sctp_ppi_dissector_table, ppi, payload_tvb, pinfo, tree, true, GUINT_TO_POINTER(ppi)))
2825
15.7k
      return true;
2826
2827
3.12k
    if (try_low_port &&
2828
187
        dissector_try_uint_with_data(sctp_port_dissector_table, low_port, payload_tvb, pinfo, tree, true, GUINT_TO_POINTER(ppi)))
2829
5
      return true;
2830
3.11k
    if (try_high_port &&
2831
141
        dissector_try_uint_with_data(sctp_port_dissector_table, high_port, payload_tvb, pinfo, tree, true, GUINT_TO_POINTER(ppi)))
2832
10
      return true;
2833
2834
3.10k
    if (!try_heuristic_first) {
2835
      /* do lookup with the heuristic subdissector table */
2836
86
      if (dissector_try_heuristic(sctp_heur_subdissector_list, payload_tvb, pinfo, tree, &hdtbl_entry, GUINT_TO_POINTER(ppi)))
2837
5
         return true;
2838
86
    }
2839
3.10k
  }
2840
  /* Oh, well, we don't know this; dissect it as data. */
2841
3.10k
  call_data_dissector(payload_tvb, pinfo, tree);
2842
3.10k
  return true;
2843
18.8k
}
2844
2845
235k
#define DATA_CHUNK_TSN_LENGTH         4
2846
195k
#define DATA_CHUNK_STREAM_ID_LENGTH   2
2847
155k
#define DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH 2
2848
116k
#define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
2849
550
#define I_DATA_CHUNK_RESERVED_LENGTH 2
2850
432
#define I_DATA_CHUNK_MID_LENGTH 4
2851
272
#define I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH 4
2852
23
#define I_DATA_CHUNK_FSN_LENGTH 4
2853
2854
176k
#define DATA_CHUNK_TSN_OFFSET         (CHUNK_VALUE_OFFSET + 0)
2855
136k
#define DATA_CHUNK_STREAM_ID_OFFSET   (DATA_CHUNK_TSN_OFFSET + DATA_CHUNK_TSN_LENGTH)
2856
97.3k
#define DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET (DATA_CHUNK_STREAM_ID_OFFSET + \
2857
97.3k
                                             DATA_CHUNK_STREAM_ID_LENGTH)
2858
58.2k
#define DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET + \
2859
58.2k
                                               DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH)
2860
19.4k
#define DATA_CHUNK_PAYLOAD_OFFSET     (DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
2861
19.4k
                                       DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2862
351
#define I_DATA_CHUNK_RESERVED_OFFSET  (DATA_CHUNK_STREAM_ID_OFFSET + \
2863
351
                                       DATA_CHUNK_STREAM_ID_LENGTH)
2864
303
#define I_DATA_CHUNK_MID_OFFSET       (I_DATA_CHUNK_RESERVED_OFFSET + \
2865
303
                                       I_DATA_CHUNK_RESERVED_LENGTH)
2866
124
#define I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET (I_DATA_CHUNK_MID_OFFSET + \
2867
124
                                                 I_DATA_CHUNK_MID_LENGTH)
2868
61
#define I_DATA_CHUNK_FSN_OFFSET       (I_DATA_CHUNK_MID_OFFSET + \
2869
61
                                       I_DATA_CHUNK_MID_LENGTH)
2870
48
#define I_DATA_CHUNK_PAYLOAD_OFFSET   (I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET + \
2871
48
                                       I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2872
2873
78.1k
#define DATA_CHUNK_HEADER_LENGTH      (CHUNK_HEADER_LENGTH + \
2874
78.1k
                                       DATA_CHUNK_TSN_LENGTH + \
2875
78.1k
                                       DATA_CHUNK_STREAM_ID_LENGTH + \
2876
78.1k
                                       DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH + \
2877
78.1k
                                       DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2878
199
#define I_DATA_CHUNK_HEADER_LENGTH    (CHUNK_HEADER_LENGTH + \
2879
199
                                       DATA_CHUNK_TSN_LENGTH + \
2880
199
                                       DATA_CHUNK_STREAM_ID_LENGTH + \
2881
199
                                       I_DATA_CHUNK_RESERVED_LENGTH + \
2882
199
                                       I_DATA_CHUNK_MID_LENGTH +\
2883
199
                                       I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH)
2884
2885
19.4k
#define SCTP_DATA_CHUNK_E_BIT 0x01
2886
19.4k
#define SCTP_DATA_CHUNK_B_BIT 0x02
2887
19.4k
#define SCTP_DATA_CHUNK_U_BIT 0x04
2888
16
#define SCTP_DATA_CHUNK_I_BIT 0x08
2889
2890
/* table to hold fragmented SCTP messages */
2891
static GHashTable *frag_table;
2892
2893
2894
typedef struct _frag_key {
2895
  uint16_t sport;
2896
  uint16_t dport;
2897
  uint32_t verification_tag;
2898
  uint16_t stream_id;
2899
  uint32_t stream_seq_num;
2900
  uint8_t u_bit;
2901
} frag_key;
2902
2903
2904
static int
2905
frag_equal(const void *k1, const void *k2)
2906
926
{
2907
926
  const frag_key *key1 = (const frag_key *) k1;
2908
926
  const frag_key *key2 = (const frag_key *) k2;
2909
2910
926
  return ( (key1->sport == key2->sport) &&
2911
858
           (key1->dport == key2->dport) &&
2912
781
           (key1->verification_tag == key2->verification_tag) &&
2913
781
           (key1->stream_id == key2->stream_id) &&
2914
688
           (key1->stream_seq_num == key2->stream_seq_num) &&
2915
684
           (key1->u_bit == key2->u_bit)
2916
926
           ? true : false);
2917
926
}
2918
2919
2920
static unsigned
2921
frag_hash(const void *k)
2922
1.15k
{
2923
1.15k
  const frag_key *key = (const frag_key *) k;
2924
2925
1.15k
  return key->sport ^ key->dport ^ key->verification_tag ^
2926
1.15k
         key->stream_id ^ key->stream_seq_num ^ key->u_bit;
2927
1.15k
}
2928
2929
2930
static void
2931
frag_free_msgs(sctp_frag_msg *msg)
2932
0
{
2933
0
  sctp_frag_be *beginend;
2934
0
  sctp_fragment *fragment;
2935
2936
  /* free all begins */
2937
0
  while (msg->begins) {
2938
0
    beginend = msg->begins;
2939
0
    msg->begins = msg->begins->next;
2940
0
    g_free(beginend);
2941
0
  }
2942
2943
  /* free all ends */
2944
0
  while (msg->ends) {
2945
0
    beginend = msg->ends;
2946
0
    msg->ends = msg->ends->next;
2947
0
    g_free(beginend);
2948
0
  }
2949
2950
  /* free all fragments */
2951
0
  while (msg->fragments) {
2952
0
    fragment = msg->fragments;
2953
0
    msg->fragments = msg->fragments->next;
2954
0
    g_free(fragment->data);
2955
0
    g_free(fragment);
2956
0
  }
2957
2958
  /* msg->messages is wmem_ allocated, no need to free it */
2959
2960
0
  g_free(msg);
2961
0
}
2962
2963
static void
2964
sctp_init(void)
2965
16
{
2966
16
  frag_table = g_hash_table_new_full(frag_hash, frag_equal,
2967
16
      (GDestroyNotify)g_free, (GDestroyNotify)frag_free_msgs);
2968
16
  num_assocs = 0;
2969
16
}
2970
2971
static void
2972
sctp_cleanup(void)
2973
0
{
2974
0
  g_hash_table_destroy(frag_table);
2975
0
}
2976
2977
2978
static sctp_frag_msg*
2979
find_message(uint16_t stream_id, uint32_t stream_seq_num, uint8_t u_bit)
2980
918
{
2981
918
  frag_key key;
2982
2983
918
  key.sport = sctp_info.sport;
2984
918
  key.dport = sctp_info.dport;
2985
918
  key.verification_tag = sctp_info.verification_tag;
2986
918
  key.stream_id = stream_id;
2987
918
  key.stream_seq_num = stream_seq_num;
2988
918
  key.u_bit = u_bit;
2989
2990
918
  return (sctp_frag_msg *)g_hash_table_lookup(frag_table, &key);
2991
918
}
2992
2993
2994
static sctp_fragment*
2995
find_fragment(uint32_t tsn, uint16_t stream_id, uint32_t stream_seq_num, uint8_t u_bit)
2996
317
{
2997
317
  sctp_frag_msg *msg;
2998
317
  sctp_fragment *next_fragment;
2999
3000
317
  msg = find_message(stream_id, stream_seq_num, u_bit);
3001
3002
317
  if (msg) {
3003
317
    next_fragment = msg->fragments;
3004
398
    while (next_fragment) {
3005
116
      if (next_fragment->tsn == tsn)
3006
35
        return next_fragment;
3007
81
      next_fragment = next_fragment->next;
3008
81
    }
3009
317
  }
3010
3011
282
  return NULL;
3012
317
}
3013
3014
3015
static sctp_fragment *
3016
add_fragment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t tsn,
3017
             uint16_t stream_id, uint32_t stream_seq_num, uint8_t b_bit, uint8_t e_bit,
3018
             uint8_t u_bit, uint32_t ppi, bool is_idata)
3019
352
{
3020
352
  sctp_frag_msg *msg;
3021
352
  sctp_fragment *fragment, *last_fragment;
3022
352
  sctp_frag_be *beginend, *last_beginend;
3023
352
  frag_key *key;
3024
3025
  /* Don't try to do reassembly on error packets */
3026
352
  if (pinfo->flags.in_error_pkt)
3027
35
    return NULL;
3028
3029
  /* lookup message. if not found, create it */
3030
317
  msg = find_message(stream_id, stream_seq_num, u_bit);
3031
3032
317
  if (!msg) {
3033
234
    msg = g_new(sctp_frag_msg, 1);
3034
234
    msg->begins = NULL;
3035
234
    msg->ends = NULL;
3036
234
    msg->fragments = NULL;
3037
234
    msg->messages = NULL;
3038
234
    msg->next = NULL;
3039
234
    if (is_idata)
3040
17
      if (b_bit)
3041
4
        msg->ppi = ppi;
3042
13
      else
3043
13
        msg->ppi = 0;
3044
217
    else
3045
217
      msg->ppi = ppi;
3046
3047
234
    key = g_new(frag_key, 1);
3048
234
    key->sport = sctp_info.sport;
3049
234
    key->dport = sctp_info.dport;
3050
234
    key->verification_tag = sctp_info.verification_tag;
3051
234
    key->stream_id = stream_id;
3052
234
    key->stream_seq_num = stream_seq_num;
3053
234
    key->u_bit = u_bit;
3054
3055
234
    g_hash_table_insert(frag_table, key, msg);
3056
234
  } else {
3057
83
      if (b_bit)
3058
10
        msg->ppi = ppi;
3059
83
  }
3060
3061
  /* lookup segment. if not found, create it */
3062
317
  fragment = find_fragment(tsn, stream_id, stream_seq_num, u_bit);
3063
3064
317
  if (fragment) {
3065
    /* this fragment is already known.
3066
     * compare frame number to check if it's a duplicate
3067
     */
3068
35
    if (fragment->frame_num == pinfo->num) {
3069
28
      return fragment;
3070
28
    } else {
3071
      /* There already is a fragment having the same ports, v_tag,
3072
       * stream id, stream_seq_num and tsn but it appeared in a different
3073
       * frame, so it must be a duplicate fragment. Maybe a retransmission?
3074
       * Mark it as duplicate and return NULL.
3075
       *
3076
       * Note: This won't happen if TSN analysis is on: the caller will have
3077
       * detected the retransmission and not pass it to the reassembly code.
3078
       */
3079
7
      col_append_str(pinfo->cinfo, COL_INFO, "(Duplicate Message Fragment) ");
3080
3081
7
      proto_tree_add_uint(tree, hf_sctp_duplicate, tvb, 0, 0, fragment->frame_num);
3082
7
      return NULL;
3083
7
    }
3084
35
  }
3085
3086
  /* There is no point in storing a fragment with no data in it */
3087
282
  if (tvb_captured_length(tvb) == 0)
3088
26
    return NULL;
3089
3090
  /* create new fragment */
3091
256
  fragment = g_new(sctp_fragment, 1);
3092
256
  fragment->frame_num = pinfo->num;
3093
256
  fragment->tsn = tsn;
3094
256
  fragment->len = tvb_captured_length(tvb);
3095
256
  fragment->ppi = msg->ppi;
3096
256
  fragment->next = NULL;
3097
256
  fragment->data = (unsigned char *)g_malloc (fragment->len);
3098
256
  tvb_memcpy(tvb, fragment->data, 0, fragment->len);
3099
3100
  /* add new fragment to linked list. sort ascending by tsn */
3101
256
  if (!msg->fragments)
3102
211
    msg->fragments = fragment;
3103
45
  else {
3104
45
    if (msg->fragments->tsn > fragment->tsn) {
3105
7
      fragment->next = msg->fragments;
3106
7
      msg->fragments = fragment;
3107
38
    } else {
3108
38
        last_fragment = msg->fragments;
3109
60
        while (last_fragment->next &&
3110
31
               last_fragment->next->tsn < fragment->tsn)
3111
22
          last_fragment = last_fragment->next;
3112
3113
38
        fragment->next = last_fragment->next;
3114
38
        last_fragment->next = fragment;
3115
38
    }
3116
45
  }
3117
3118
3119
  /* save begin or end if necessary */
3120
256
  if (b_bit && !e_bit) {
3121
31
    beginend = g_new(sctp_frag_be, 1);
3122
31
    beginend->fragment = fragment;
3123
31
    beginend->next = NULL;
3124
3125
    /* add begin to linked list. sort descending by tsn */
3126
31
    if (!msg->begins)
3127
24
      msg->begins = beginend;
3128
7
    else {
3129
7
      if (msg->begins->fragment->tsn < beginend->fragment->tsn) {
3130
4
        beginend->next = msg->begins;
3131
4
        msg->begins = beginend;
3132
4
      } else {
3133
3
        last_beginend = msg->begins;
3134
3
        while (last_beginend->next &&
3135
2
               last_beginend->next->fragment->tsn > beginend->fragment->tsn)
3136
0
          last_beginend = last_beginend->next;
3137
3138
3
        beginend->next = last_beginend->next;
3139
3
       last_beginend->next = beginend;
3140
3
      }
3141
7
    }
3142
3143
31
  }
3144
3145
256
  if (!b_bit && e_bit) {
3146
57
    beginend = g_new(sctp_frag_be, 1);
3147
57
    beginend->fragment = fragment;
3148
57
    beginend->next = NULL;
3149
3150
    /* add end to linked list. sort ascending by tsn */
3151
57
    if (!msg->ends)
3152
51
      msg->ends = beginend;
3153
6
    else {
3154
6
      if (msg->ends->fragment->tsn > beginend->fragment->tsn) {
3155
1
        beginend->next = msg->ends;
3156
1
        msg->ends = beginend;
3157
5
      } else {
3158
5
        last_beginend = msg->ends;
3159
7
        while (last_beginend->next &&
3160
3
               last_beginend->next->fragment->tsn < beginend->fragment->tsn)
3161
2
          last_beginend = last_beginend->next;
3162
3163
5
        beginend->next = last_beginend->next;
3164
5
        last_beginend->next = beginend;
3165
5
      }
3166
6
    }
3167
3168
57
  }
3169
3170
256
  return fragment;
3171
282
}
3172
3173
static tvbuff_t*
3174
fragment_reassembly(tvbuff_t *tvb, sctp_fragment *fragment,
3175
                    packet_info *pinfo, proto_tree *tree, uint16_t stream_id,
3176
                    uint32_t stream_seq_num, uint8_t u_bit)
3177
284
{
3178
284
  sctp_frag_msg *msg;
3179
284
  sctp_complete_msg *message, *last_message;
3180
284
  sctp_fragment *frag_i, *last_frag, *first_frag;
3181
284
  sctp_frag_be *begin, *end, *beginend;
3182
284
  uint32_t len, offset = 0;
3183
284
  tvbuff_t *new_tvb = NULL;
3184
284
  proto_item *item;
3185
284
  proto_tree *ptree;
3186
3187
284
  msg = find_message(stream_id, stream_seq_num, u_bit);
3188
3189
284
  if (!msg) {
3190
    /* no message, we can't do anything */
3191
0
    return NULL;
3192
0
  }
3193
3194
  /* check if fragment is part of an already reassembled message */
3195
284
  for (message = msg->messages;
3196
284
       message &&
3197
0
       !(message->begin <= fragment->tsn && message->end >= fragment->tsn) &&
3198
0
       !(message->begin > message->end &&
3199
0
       (message->begin <= fragment->tsn || message->end >= fragment->tsn));
3200
284
         message = message->next);
3201
3202
284
  if (message) {
3203
    /* we found the reassembled message this fragment belongs to */
3204
0
    if (fragment == message->reassembled_in) {
3205
3206
      /* this is the last fragment, create data source */
3207
0
      new_tvb = tvb_new_child_real_data(tvb, message->data, message->len, message->len);
3208
0
      add_new_data_source(pinfo, new_tvb, "Reassembled SCTP Message");
3209
3210
      /* display reassembly info */
3211
0
      item = proto_tree_add_item(tree, hf_sctp_fragments, tvb, 0, -1, ENC_NA);
3212
0
      ptree = proto_item_add_subtree(item, ett_sctp_fragments);
3213
0
      proto_item_append_text(item, " (%u bytes, %u fragments): ",
3214
0
                             message->len, message->end - message->begin + 1);
3215
3216
0
      if (message->begin > message->end) {
3217
0
        for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
3218
0
             frag_i;
3219
0
             frag_i = frag_i->next) {
3220
3221
0
          proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3222
0
                                     frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3223
0
                                     frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3224
0
          offset += frag_i->len;
3225
3226
0
          mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
3227
0
        }
3228
3229
0
        for (frag_i = msg->fragments;
3230
0
             frag_i && frag_i->tsn <= message->end;
3231
0
             frag_i = frag_i->next) {
3232
3233
0
          proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3234
0
                                     frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3235
0
                                     frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3236
0
          offset += frag_i->len;
3237
3238
0
          mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
3239
0
        }
3240
0
      } else {
3241
0
        for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
3242
0
             frag_i && frag_i->tsn <= message->end;
3243
0
             frag_i = frag_i->next) {
3244
3245
0
          proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3246
0
                                     frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3247
0
                                     frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3248
0
          offset += frag_i->len;
3249
3250
0
          mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
3251
0
        }
3252
0
      }
3253
3254
0
      return new_tvb;
3255
0
    }
3256
3257
    /* this is not the last fragment,
3258
     * so let the user know the frame where the reassembly is
3259
     */
3260
0
    col_append_str(pinfo->cinfo, COL_INFO, "(Message Fragment) ");
3261
3262
0
    proto_tree_add_uint(tree, hf_sctp_reassembled_in, tvb, 0, 0, message->reassembled_in->frame_num);
3263
0
    return NULL;
3264
0
  }
3265
3266
  /* this fragment has not been reassembled, yet
3267
   * check now if we can reassemble it
3268
   * at first look for the first and last tsn of the msg
3269
   */
3270
284
  for (begin = msg->begins;
3271
288
       begin && begin->fragment->tsn > fragment->tsn;
3272
284
       begin = begin->next);
3273
3274
  /* in case begin still is null, set it to first (highest) begin
3275
   * maybe the message tsn restart at 0 in between
3276
   */
3277
284
  if (!begin)
3278
252
    begin = msg->begins;
3279
3280
284
  for (end = msg->ends;
3281
292
       end && end->fragment->tsn < fragment->tsn;
3282
284
       end = end->next);
3283
3284
  /* in case end still is null, set it to first (lowest) end
3285
   * maybe the message tsn restart at 0 in between
3286
   */
3287
284
  if (!end)
3288
219
    end = msg->ends;
3289
3290
284
  if (!begin || !end || !msg->fragments ||
3291
283
      (begin->fragment->tsn > end->fragment->tsn && msg->fragments->tsn)) {
3292
    /* begin and end have not been collected, yet
3293
     * or there might be a tsn restart but the first fragment hasn't a tsn of 0
3294
     * just mark as fragment
3295
     */
3296
3297
283
    col_append_str(pinfo->cinfo, COL_INFO, "(Message Fragment) ");
3298
3299
283
    return NULL;
3300
283
  }
3301
3302
  /* we found possible begin and end
3303
   * look for the first fragment and then try to get to the end
3304
   */
3305
1
  first_frag = begin->fragment;
3306
3307
  /* while looking if all fragments are there
3308
   * we can calculate the overall length that
3309
   * we need in case of success
3310
   */
3311
1
  len = first_frag->len;
3312
3313
  /* check if begin is past end
3314
   * this can happen if there has been a tsn restart
3315
   * or we just got the wrong begin and end
3316
   * so give it a try
3317
  */
3318
1
  if (begin->fragment->tsn > end->fragment->tsn) {
3319
1
    for (last_frag = first_frag, frag_i = first_frag->next;
3320
1
         frag_i && frag_i->tsn == (last_frag->tsn + 1);
3321
1
         last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
3322
3323
    /* check if we reached the last possible tsn
3324
     * if yes, restart and continue
3325
     */
3326
1
    if ((last_frag->tsn + 1)) {
3327
      /* there are just fragments missing */
3328
1
      col_append_str(pinfo->cinfo, COL_INFO, "(Message Fragment) ");
3329
3330
1
      return NULL;
3331
1
    }
3332
3333
    /* we got all fragments until the last possible tsn
3334
     * and the first is 0 if we got here
3335
     */
3336
3337
0
    len += msg->fragments->len;
3338
0
    for (last_frag = msg->fragments, frag_i = last_frag->next;
3339
0
         frag_i && frag_i->tsn < end->fragment->tsn && frag_i->tsn == (last_frag->tsn + 1);
3340
0
         last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
3341
3342
0
  } else {
3343
0
    for (last_frag = first_frag, frag_i = first_frag->next;
3344
0
         frag_i && frag_i->tsn < end->fragment->tsn && frag_i->tsn == (last_frag->tsn + 1);
3345
0
         last_frag = frag_i, frag_i = frag_i->next) len += frag_i->len;
3346
0
  }
3347
3348
0
  if (!frag_i || frag_i != end->fragment || frag_i->tsn != (last_frag->tsn + 1)) {
3349
    /* we need more fragments. just mark as fragment */
3350
0
    col_append_str(pinfo->cinfo, COL_INFO, "(Message Fragment) ");
3351
3352
0
    return NULL;
3353
0
  }
3354
3355
  /* ok, this message is complete, we can reassemble it
3356
   * but at first don't forget to add the length of the last fragment
3357
   */
3358
0
  len += frag_i->len;
3359
3360
0
  message = wmem_new(wmem_file_scope(), sctp_complete_msg);
3361
0
  message->begin = begin->fragment->tsn;
3362
0
  message->end = end->fragment->tsn;
3363
0
  message->reassembled_in = fragment;
3364
0
  message->len = len;
3365
0
  message->data = (unsigned char *)wmem_alloc(wmem_file_scope(), len);
3366
0
  message->next = NULL;
3367
3368
  /* now copy all fragments */
3369
0
  if (begin->fragment->tsn > end->fragment->tsn) {
3370
    /* a tsn restart has occurred */
3371
0
    for (frag_i = first_frag;
3372
0
         frag_i;
3373
0
         frag_i = frag_i->next) {
3374
3375
0
      if (frag_i->len && frag_i->data)
3376
0
        memcpy(message->data + offset, frag_i->data, frag_i->len);
3377
0
      offset += frag_i->len;
3378
3379
      /* release fragment data */
3380
0
      g_free(frag_i->data);
3381
0
      frag_i->data = NULL;
3382
0
    }
3383
3384
0
    for (frag_i = msg->fragments;
3385
0
         frag_i && frag_i->tsn <= end->fragment->tsn;
3386
0
         frag_i = frag_i->next) {
3387
3388
0
      if (frag_i->len && frag_i->data)
3389
0
        memcpy(message->data + offset, frag_i->data, frag_i->len);
3390
0
      offset += frag_i->len;
3391
3392
      /* release fragment data */
3393
0
      g_free(frag_i->data);
3394
0
      frag_i->data = NULL;
3395
0
    }
3396
3397
0
  } else {
3398
0
    for (frag_i = first_frag;
3399
0
         frag_i && frag_i->tsn <= end->fragment->tsn;
3400
0
         frag_i = frag_i->next) {
3401
3402
0
      if (frag_i->len && frag_i->data)
3403
0
        memcpy(message->data + offset, frag_i->data, frag_i->len);
3404
0
      offset += frag_i->len;
3405
3406
      /* release fragment data */
3407
0
      g_free(frag_i->data);
3408
0
      frag_i->data = NULL;
3409
0
    }
3410
0
  }
3411
3412
  /* save message */
3413
0
  if (!msg->messages) {
3414
0
    msg->messages = message;
3415
0
  } else {
3416
0
    for (last_message = msg->messages;
3417
0
         last_message->next;
3418
0
         last_message = last_message->next);
3419
0
    last_message->next = message;
3420
0
  }
3421
3422
  /* remove begin and end from list */
3423
0
  if (msg->begins == begin) {
3424
0
    msg->begins = begin->next;
3425
0
  } else {
3426
0
    for (beginend = msg->begins;
3427
0
         beginend && beginend->next != begin;
3428
0
         beginend = beginend->next);
3429
0
    if (beginend && beginend->next == begin)
3430
0
      beginend->next = begin->next;
3431
0
  }
3432
0
  g_free(begin);
3433
3434
0
  if (msg->ends == end) {
3435
0
    msg->ends = end->next;
3436
0
  } else {
3437
0
    for (beginend = msg->ends;
3438
0
         beginend && beginend->next != end;
3439
0
         beginend = beginend->next);
3440
0
    if (beginend && beginend->next == end)
3441
0
      beginend->next = end->next;
3442
0
  }
3443
0
   g_free(end);
3444
3445
  /* create data source */
3446
0
  new_tvb = tvb_new_child_real_data(tvb, message->data, len, len);
3447
0
  add_new_data_source(pinfo, new_tvb, "Reassembled SCTP Message");
3448
3449
  /* display reassembly info */
3450
0
  item = proto_tree_add_item(tree, hf_sctp_fragments, tvb, 0, -1, ENC_NA);
3451
0
  ptree = proto_item_add_subtree(item, ett_sctp_fragments);
3452
0
  proto_item_append_text(item, " (%u bytes, %u fragments): ",
3453
0
                         message->len, message->end - message->begin + 1);
3454
3455
0
  if (message->begin > message->end) {
3456
0
    for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
3457
0
         frag_i;
3458
0
         frag_i = frag_i->next) {
3459
3460
0
      proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3461
0
                                 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3462
0
                                 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3463
0
      offset += frag_i->len;
3464
3465
0
      mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
3466
0
    }
3467
3468
0
    for (frag_i = msg->fragments;
3469
0
         frag_i && frag_i->tsn <= message->end;
3470
0
         frag_i = frag_i->next) {
3471
3472
0
      proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3473
0
                                 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3474
0
                                 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3475
0
      offset += frag_i->len;
3476
3477
0
      mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
3478
0
    }
3479
0
  } else {
3480
0
    for (frag_i = find_fragment(message->begin, stream_id, stream_seq_num, u_bit);
3481
0
         frag_i && frag_i->tsn <= message->end;
3482
0
         frag_i = frag_i->next) {
3483
3484
0
      proto_tree_add_uint_format(ptree, hf_sctp_fragment, new_tvb, offset, frag_i->len,
3485
0
                                 frag_i->frame_num, "Frame: %u, payload: %u-%u (%u bytes)",
3486
0
                                 frag_i->frame_num, offset, offset + frag_i->len - 1, frag_i->len);
3487
0
      offset += frag_i->len;
3488
3489
0
      mark_frame_as_depended_upon(pinfo->fd, frag_i->frame_num);
3490
0
    }
3491
0
  }
3492
3493
  /* it's not fragmented anymore */
3494
0
  pinfo->fragmented = false;
3495
3496
0
  return new_tvb;
3497
0
}
3498
3499
static exp_pdu_data_t*
3500
create_exp_pdu_table(packet_info *pinfo, tvbuff_t *tvb, const char *table_name, uint32_t table_value)
3501
0
{
3502
0
  exp_pdu_data_item_t exp_pdu_data_table_value = {
3503
0
    exp_pdu_data_dissector_table_num_value_size,
3504
0
    exp_pdu_data_dissector_table_num_value_populate_data,
3505
0
    GUINT_TO_POINTER(table_value)
3506
0
  };
3507
3508
0
  const exp_pdu_data_item_t *sctp_exp_pdu_items[] = {
3509
0
    &exp_pdu_data_src_ip,
3510
0
    &exp_pdu_data_dst_ip,
3511
0
    &exp_pdu_data_port_type,
3512
0
    &exp_pdu_data_src_port,
3513
0
    &exp_pdu_data_dst_port,
3514
0
    &exp_pdu_data_orig_frame_num,
3515
0
    &exp_pdu_data_table_value,
3516
0
    NULL
3517
0
  };
3518
3519
0
  exp_pdu_data_t *exp_pdu_data = export_pdu_create_tags(pinfo, table_name, EXP_PDU_TAG_DISSECTOR_TABLE_NAME, sctp_exp_pdu_items);
3520
3521
0
  exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
3522
0
  exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
3523
0
  exp_pdu_data->pdu_tvb = tvb;
3524
3525
0
  return exp_pdu_data;
3526
0
}
3527
3528
static exp_pdu_data_t*
3529
create_exp_pdu_proto_name(packet_info *pinfo, tvbuff_t *tvb, const char *proto_name)
3530
0
{
3531
0
  exp_pdu_data_t *exp_pdu_data = export_pdu_create_common_tags(pinfo, proto_name, EXP_PDU_TAG_DISSECTOR_NAME);
3532
3533
0
  exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
3534
0
  exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
3535
0
  exp_pdu_data->pdu_tvb = tvb;
3536
3537
0
  return exp_pdu_data;
3538
0
}
3539
3540
static void
3541
export_sctp_data_chunk(packet_info *pinfo, tvbuff_t *tvb, uint32_t payload_proto_id,
3542
                       const wmem_list_frame_t *frame)
3543
18.8k
{
3544
18.8k
  const char *proto_name = NULL;
3545
18.8k
  exp_pdu_data_t *exp_pdu_data = NULL;
3546
3547
18.8k
  if (!have_tap_listener(exported_pdu_tap)) {
3548
    /* Do nothing when there is no export pdu tap listener */
3549
18.8k
    return;
3550
18.8k
  }
3551
3552
0
  if (enable_ulp_dissection && frame) {
3553
    /* get the proto_name of the next frame */
3554
0
    proto_name = proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame)));
3555
0
  }
3556
3557
0
  if (proto_name && (strcmp(proto_name, "data") != 0)) {
3558
    /* when we have proto_name and it is not "data" export using the proto_name */
3559
0
    exp_pdu_data = create_exp_pdu_proto_name(pinfo, tvb, proto_name);
3560
0
  } else if (payload_proto_id != 0) {
3561
0
    exp_pdu_data = create_exp_pdu_table(pinfo, tvb, "sctp.ppi", payload_proto_id);
3562
0
  } else if (pinfo->destport != 0) {
3563
0
    exp_pdu_data = create_exp_pdu_table(pinfo, tvb, "sctp.port", pinfo->destport);
3564
0
  } else if (pinfo->srcport != 0) {
3565
0
    exp_pdu_data = create_exp_pdu_table(pinfo, tvb, "sctp.port", pinfo->srcport);
3566
0
  } else {
3567
    /* do not export anything when none of the above fields are available */
3568
0
    return;
3569
0
  }
3570
3571
0
  tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
3572
0
}
3573
3574
static bool
3575
dissect_fragmented_payload(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree,
3576
                           proto_tree *chunk_tree, uint32_t tsn, uint32_t ppi, uint16_t stream_id,
3577
                           uint32_t stream_seq_num, uint8_t b_bit, uint8_t e_bit, uint8_t u_bit, bool is_idata)
3578
352
{
3579
352
  sctp_fragment *fragment;
3580
352
  tvbuff_t *new_tvb = NULL;
3581
3582
  /*
3583
   * If this is a short frame, then we can't, and don't, do
3584
   * reassembly on it.  We just give up.
3585
   */
3586
352
  if (tvb_reported_length(payload_tvb) > tvb_captured_length(payload_tvb))
3587
0
    return true;
3588
3589
  /* add fragment to list of known fragments. returns NULL if segment is a duplicate */
3590
352
  fragment = add_fragment(payload_tvb, pinfo, chunk_tree, tsn, stream_id, stream_seq_num, b_bit, e_bit, u_bit, ppi, is_idata);
3591
3592
352
  if (fragment)
3593
284
    new_tvb = fragment_reassembly(payload_tvb, fragment, pinfo, chunk_tree, stream_id, stream_seq_num, u_bit);
3594
3595
  /* pass reassembled data to next dissector, if possible */
3596
352
  if (new_tvb){
3597
0
    bool retval;
3598
0
    wmem_list_frame_t *cur = wmem_list_tail(pinfo->layers);
3599
3600
0
    retval = dissect_payload(new_tvb, pinfo, tree, ppi);
3601
0
    export_sctp_data_chunk(pinfo, new_tvb, ppi, wmem_list_frame_next(cur));
3602
0
    return retval;
3603
0
  }
3604
3605
  /* no reassembly done, do nothing */
3606
352
  return true;
3607
352
}
3608
3609
static const true_false_string sctp_data_chunk_e_bit_value = {
3610
  "Last segment",
3611
  "Not the last segment"
3612
};
3613
3614
static const true_false_string sctp_data_chunk_b_bit_value = {
3615
  "First segment",
3616
  "Subsequent segment"
3617
};
3618
3619
static const true_false_string sctp_data_chunk_u_bit_value = {
3620
  "Unordered delivery",
3621
  "Ordered delivery"
3622
};
3623
3624
static const true_false_string sctp_data_chunk_i_bit_value = {
3625
  "Send SACK immediately",
3626
  "Possibly delay SACK"
3627
};
3628
3629
static bool
3630
dissect_data_chunk(tvbuff_t *chunk_tvb,
3631
                   uint16_t chunk_length,
3632
                   packet_info *pinfo,
3633
                   proto_tree *tree,
3634
                   proto_tree *chunk_tree,
3635
                   proto_item *chunk_item,
3636
                   proto_item *flags_item,
3637
                   sctp_half_assoc_t *ha,
3638
                   bool is_idata)
3639
19.5k
{
3640
19.5k
  unsigned number_of_ppid;
3641
19.5k
  volatile uint32_t payload_proto_id;
3642
19.5k
  tvbuff_t *payload_tvb;
3643
19.5k
  proto_tree *flags_tree;
3644
19.5k
  uint8_t oct, e_bit, b_bit, u_bit;
3645
19.5k
  uint16_t stream_id;
3646
19.5k
  uint32_t tsn, rawtsn, ppid, stream_seq_num = 0;
3647
19.5k
  proto_item *tsn_item = NULL;
3648
19.5k
  bool call_subdissector = false;
3649
19.5k
  bool is_retransmission;
3650
19.5k
  uint32_t header_length;
3651
19.5k
  uint32_t payload_offset;
3652
3653
19.5k
  static int* const chunk_flags[] = {
3654
19.5k
    &hf_data_chunk_i_bit,
3655
19.5k
    &hf_data_chunk_u_bit,
3656
19.5k
    &hf_data_chunk_b_bit,
3657
19.5k
    &hf_data_chunk_e_bit,
3658
19.5k
    NULL
3659
19.5k
  };
3660
3661
19.5k
  if (is_idata) {
3662
53
    if (chunk_length < I_DATA_CHUNK_HEADER_LENGTH) {
3663
2
      proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)", chunk_length, I_DATA_CHUNK_HEADER_LENGTH);
3664
2
      return true;
3665
2
    }
3666
51
    payload_proto_id = tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
3667
19.4k
  } else {
3668
19.4k
    if (chunk_length < DATA_CHUNK_HEADER_LENGTH) {
3669
43
      proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)", chunk_length, DATA_CHUNK_HEADER_LENGTH);
3670
43
      return true;
3671
43
    }
3672
19.4k
    payload_proto_id = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET);
3673
19.4k
  }
3674
3675
  /* insert the PPID in the pinfo structure if it is not already there and there is still room */
3676
19.8k
  for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++) {
3677
19.7k
    void *tmp = p_get_proto_data(pinfo->pool, pinfo, proto_sctp, number_of_ppid);
3678
19.7k
    ppid = GPOINTER_TO_UINT(tmp);
3679
19.7k
    if ((ppid == LAST_PPID) || (ppid == payload_proto_id))
3680
19.3k
      break;
3681
19.7k
  }
3682
19.4k
  if ((number_of_ppid < MAX_NUMBER_OF_PPIDS) && (ppid == LAST_PPID))
3683
19.2k
    p_add_proto_data(pinfo->pool, pinfo, proto_sctp, number_of_ppid, GUINT_TO_POINTER(payload_proto_id));
3684
3685
19.4k
  oct = tvb_get_uint8(chunk_tvb, CHUNK_FLAGS_OFFSET);
3686
19.4k
  e_bit = oct & SCTP_DATA_CHUNK_E_BIT;
3687
19.4k
  b_bit = oct & SCTP_DATA_CHUNK_B_BIT;
3688
19.4k
  u_bit = oct & SCTP_DATA_CHUNK_U_BIT;
3689
3690
19.4k
  tsn = rawtsn = tvb_get_ntohl(chunk_tvb, DATA_CHUNK_TSN_OFFSET);
3691
19.4k
  if ((show_relative_tsns) && (ha)) {
3692
609
    if (!ha->started) {
3693
204
      ha->first_tsn = tsn;
3694
204
      ha->started = true;
3695
204
    }
3696
609
    tsn -= ha->first_tsn;
3697
609
  }
3698
3699
19.4k
  col_append_fstr(pinfo->cinfo, COL_INFO, "(TSN=%" PRIu32 ") ", tsn);
3700
3701
19.4k
  if (chunk_tree) {
3702
19.4k
    if (is_idata)
3703
48
      proto_item_set_len(chunk_item, I_DATA_CHUNK_HEADER_LENGTH);
3704
19.4k
    else
3705
19.4k
      proto_item_set_len(chunk_item, DATA_CHUNK_HEADER_LENGTH);
3706
3707
19.4k
    flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_data_chunk_flags);
3708
19.4k
    proto_tree_add_bitmask_list(flags_tree, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, chunk_flags, ENC_NA);
3709
19.4k
    if((show_relative_tsns) && (ha)) {
3710
609
       tsn_item = proto_tree_add_uint(chunk_tree, hf_data_chunk_tsn, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, tsn);
3711
609
       proto_tree_add_item(chunk_tree, hf_data_chunk_tsn_raw, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, ENC_BIG_ENDIAN);
3712
609
    }
3713
18.8k
    else {
3714
18.8k
       tsn_item = proto_tree_add_item(chunk_tree, hf_data_chunk_tsn_raw, chunk_tvb, DATA_CHUNK_TSN_OFFSET, DATA_CHUNK_TSN_LENGTH, ENC_BIG_ENDIAN);
3715
18.8k
    }
3716
19.4k
    proto_tree_add_item(chunk_tree, hf_data_chunk_stream_id,          chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET, DATA_CHUNK_STREAM_ID_LENGTH, ENC_BIG_ENDIAN);
3717
19.4k
    if (is_idata) {
3718
48
      proto_tree_add_item(chunk_tree, hf_idata_chunk_reserved, chunk_tvb, I_DATA_CHUNK_RESERVED_OFFSET, I_DATA_CHUNK_RESERVED_LENGTH, ENC_BIG_ENDIAN);
3719
48
      proto_tree_add_item(chunk_tree, hf_idata_chunk_mid, chunk_tvb, I_DATA_CHUNK_MID_OFFSET, I_DATA_CHUNK_MID_LENGTH, ENC_BIG_ENDIAN);
3720
48
      if (b_bit)
3721
25
        proto_tree_add_item(chunk_tree, hf_data_chunk_payload_proto_id, chunk_tvb, I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, I_DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH, ENC_BIG_ENDIAN);
3722
23
      else
3723
23
        proto_tree_add_item(chunk_tree, hf_idata_chunk_fsn, chunk_tvb, I_DATA_CHUNK_FSN_OFFSET, I_DATA_CHUNK_FSN_LENGTH, ENC_BIG_ENDIAN);
3724
19.4k
    } else {
3725
19.4k
      proto_tree_add_item(chunk_tree, hf_data_chunk_stream_seq_number, chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET,   DATA_CHUNK_STREAM_SEQ_NUMBER_LENGTH,   ENC_BIG_ENDIAN);
3726
19.4k
      proto_tree_add_item(chunk_tree, hf_data_chunk_payload_proto_id,  chunk_tvb, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_OFFSET, DATA_CHUNK_PAYLOAD_PROTOCOL_ID_LENGTH, ENC_BIG_ENDIAN);
3727
19.4k
    }
3728
19.4k
    proto_item_append_text(chunk_item, " (%s, ", (u_bit) ? "unordered" : "ordered");
3729
19.4k
    if (b_bit) {
3730
18.9k
      if (e_bit)
3731
18.9k
        proto_item_append_text(chunk_item, "complete");
3732
58
      else
3733
58
        proto_item_append_text(chunk_item, "first");
3734
18.9k
    } else {
3735
491
      if (e_bit)
3736
128
        proto_item_append_text(chunk_item, "last");
3737
363
      else
3738
363
        proto_item_append_text(chunk_item, "middle");
3739
491
    }
3740
3741
19.4k
    if (is_idata) {
3742
48
      if (b_bit)
3743
25
        proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, MID: %u, payload length: %u byte%s)",
3744
25
                               tsn,
3745
25
                               tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
3746
25
                               tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_MID_OFFSET),
3747
25
                               chunk_length - I_DATA_CHUNK_HEADER_LENGTH, plurality(chunk_length - I_DATA_CHUNK_HEADER_LENGTH, "", "s"));
3748
23
      else
3749
23
        proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, MID: %u, FSN: %u, payload length: %u byte%s)",
3750
23
                               tsn,
3751
23
                               tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
3752
23
                               tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_MID_OFFSET),
3753
23
                               tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_FSN_OFFSET),
3754
23
                               chunk_length - I_DATA_CHUNK_HEADER_LENGTH, plurality(chunk_length - I_DATA_CHUNK_HEADER_LENGTH, "", "s"));
3755
48
    } else
3756
19.4k
      proto_item_append_text(chunk_item, " segment, TSN: %u, SID: %u, SSN: %u, PPID: %u, payload length: %u byte%s)",
3757
19.4k
                             tsn,
3758
19.4k
                             tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET),
3759
19.4k
                             tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET),
3760
19.4k
                             payload_proto_id,
3761
19.4k
                             chunk_length - DATA_CHUNK_HEADER_LENGTH, plurality(chunk_length - DATA_CHUNK_HEADER_LENGTH, "", "s"));
3762
19.4k
  }
3763
3764
19.4k
  is_retransmission = sctp_tsn(pinfo, chunk_tvb, tsn_item, ha, rawtsn);
3765
3766
19.4k
  if (is_idata) {
3767
48
    header_length = I_DATA_CHUNK_HEADER_LENGTH;
3768
48
    payload_offset = I_DATA_CHUNK_PAYLOAD_OFFSET;
3769
19.4k
  } else {
3770
19.4k
    header_length = DATA_CHUNK_HEADER_LENGTH;
3771
19.4k
    payload_offset = DATA_CHUNK_PAYLOAD_OFFSET;
3772
19.4k
  }
3773
19.4k
  payload_tvb = tvb_new_subset_length(chunk_tvb, payload_offset,
3774
19.4k
                                 MIN(chunk_length - header_length, tvb_reported_length_remaining(chunk_tvb, payload_offset)));
3775
3776
  /* Is this a fragment? */
3777
19.4k
  if (b_bit && e_bit) {
3778
    /* No - just call the subdissector. */
3779
18.9k
    if (!is_retransmission)
3780
18.8k
      call_subdissector = true;
3781
18.9k
  } else {
3782
    /* Yes. */
3783
563
    pinfo->fragmented = true;
3784
3785
    /* if reassembly is off just mark as fragment for next dissector and proceed */
3786
563
    if (!use_reassembly)
3787
0
    {
3788
      /*  Don't pass on non-first fragments since the next dissector will
3789
       *  almost certainly not understand the data.
3790
       */
3791
0
      if (b_bit) {
3792
0
        if (!is_retransmission)
3793
0
          call_subdissector = true;
3794
0
      } else
3795
0
        return false;
3796
0
    }
3797
3798
563
  }
3799
3800
19.4k
  if (call_subdissector) {
3801
    /* This isn't a fragment or reassembly is off and it's the first fragment */
3802
3803
18.8k
    volatile bool retval = false;
3804
18.8k
    wmem_list_frame_t *cur = wmem_list_tail(pinfo->layers);
3805
3806
18.8k
    TRY {
3807
18.8k
      retval = dissect_payload(payload_tvb, pinfo, tree, payload_proto_id);
3808
18.8k
    }
3809
18.8k
    CATCH_NONFATAL_ERRORS {
3810
      /*
3811
       * Somebody threw an exception that means that there was a problem
3812
       * dissecting the payload; that means that a dissector was found,
3813
       * so we don't need to dissect the payload as data or update the
3814
       * protocol or info columns.
3815
       *
3816
       * Just show the exception and then continue dissecting chunks.
3817
       */
3818
2.98k
      show_exception(payload_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
3819
2.98k
    }
3820
18.8k
    ENDTRY;
3821
3822
18.8k
    export_sctp_data_chunk(pinfo, payload_tvb, payload_proto_id, wmem_list_frame_next(cur));
3823
18.8k
    return retval;
3824
3825
18.8k
  } else if (is_retransmission) {
3826
216
    col_append_str(pinfo->cinfo, COL_INFO, "(retransmission) ");
3827
216
    return false;
3828
366
  } else {
3829
3830
    /* The logic above should ensure this... */
3831
366
    DISSECTOR_ASSERT(use_reassembly);
3832
3833
366
    stream_id = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_ID_OFFSET);
3834
366
    if (is_idata) {
3835
      /* The stream_seq_num variable is used to hold the MID, the tsn variable holds the FSN*/
3836
22
      stream_seq_num = tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_MID_OFFSET);
3837
22
      if (b_bit) {
3838
7
        tsn = 0;
3839
15
      } else {
3840
15
        tsn = tvb_get_ntohl(chunk_tvb, I_DATA_CHUNK_FSN_OFFSET);
3841
15
        payload_proto_id = 0;
3842
15
      }
3843
344
    } else {
3844
      /* if unordered set stream_seq_num to 0 for easier handling */
3845
344
      if (u_bit)
3846
47
        stream_seq_num = 0;
3847
297
      else
3848
297
        stream_seq_num = tvb_get_ntohs(chunk_tvb, DATA_CHUNK_STREAM_SEQ_NUMBER_OFFSET);
3849
344
    }
3850
    /* start reassembly */
3851
366
    return dissect_fragmented_payload(payload_tvb, pinfo, tree, chunk_tree, tsn, payload_proto_id, stream_id, stream_seq_num, b_bit, e_bit, u_bit, is_idata);
3852
366
  }
3853
3854
19.4k
}
3855
3856
1.83k
#define INIT_CHUNK_INITIATE_TAG_LENGTH               4
3857
1.50k
#define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH      4
3858
1.17k
#define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH 2
3859
846
#define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH  2
3860
682
#define INIT_CHUNK_INITIAL_TSN_LENGTH                4
3861
354
#define INIT_CHUNK_FIXED_PARAMTERS_LENGTH            (CHUNK_HEADER_LENGTH + \
3862
354
                                                      INIT_CHUNK_INITIATE_TAG_LENGTH + \
3863
354
                                                      INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \
3864
354
                                                      INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \
3865
354
                                                      INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \
3866
354
                                                      INIT_CHUNK_INITIAL_TSN_LENGTH)
3867
3868
1.47k
#define INIT_CHUNK_INITIATE_TAG_OFFSET               CHUNK_VALUE_OFFSET
3869
1.14k
#define INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET      (INIT_CHUNK_INITIATE_TAG_OFFSET + \
3870
1.14k
                                                      INIT_CHUNK_INITIATE_TAG_LENGTH )
3871
984
#define INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET (INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
3872
984
                                                      INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH )
3873
656
#define INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET  (INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET + \
3874
656
                                                      INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH )
3875
328
#define INIT_CHUNK_INITIAL_TSN_OFFSET                (INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET + \
3876
328
                                                      INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH )
3877
164
#define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET  (INIT_CHUNK_INITIAL_TSN_OFFSET + \
3878
164
                                                      INIT_CHUNK_INITIAL_TSN_LENGTH )
3879
3880
static void
3881
// NOLINTNEXTLINE(misc-no-recursion)
3882
dissect_init_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3883
120
{
3884
120
  tvbuff_t *parameters_tvb;
3885
120
  proto_item *hidden_item;
3886
3887
120
  if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
3888
10
    proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)", chunk_length, INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
3889
10
    return;
3890
10
  }
3891
3892
110
  if (chunk_tree) {
3893
    /* handle fixed parameters */
3894
110
    proto_tree_add_item(chunk_tree, hf_init_chunk_initiate_tag,               chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               ENC_BIG_ENDIAN);
3895
110
    hidden_item = proto_tree_add_item(chunk_tree, hf_initiate_tag,            chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               ENC_BIG_ENDIAN);
3896
110
    proto_item_set_hidden(hidden_item);
3897
110
    proto_tree_add_item(chunk_tree, hf_init_chunk_adv_rec_window_credit,      chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET,      INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,      ENC_BIG_ENDIAN);
3898
110
    proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, ENC_BIG_ENDIAN);
3899
110
    proto_tree_add_item(chunk_tree, hf_init_chunk_number_of_inbound_streams,  chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET,  INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,  ENC_BIG_ENDIAN);
3900
110
    proto_tree_add_item(chunk_tree, hf_init_chunk_initial_tsn,                chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET,                INIT_CHUNK_INITIAL_TSN_LENGTH,                ENC_BIG_ENDIAN);
3901
3902
110
    proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
3903
110
                           tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
3904
110
                           tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
3905
110
  }
3906
3907
  /* handle variable parameters */
3908
110
  chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
3909
110
  parameters_tvb = tvb_new_subset_length(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET,
3910
110
                                  MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET)));
3911
110
  dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, true, false);
3912
110
}
3913
3914
static void
3915
// NOLINTNEXTLINE(misc-no-recursion)
3916
dissect_init_ack_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
3917
57
{
3918
57
  tvbuff_t *parameters_tvb;
3919
57
  proto_item *hidden_item;
3920
3921
57
  if (chunk_length < INIT_CHUNK_FIXED_PARAMTERS_LENGTH) {
3922
3
    proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
3923
3
                           chunk_length,
3924
3
                           INIT_CHUNK_FIXED_PARAMTERS_LENGTH);
3925
3
    return;
3926
3
  }
3927
54
  if (chunk_tree) {
3928
    /* handle fixed parameters */
3929
54
    proto_tree_add_item(chunk_tree, hf_initack_chunk_initiate_tag,               chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               ENC_BIG_ENDIAN);
3930
54
    hidden_item = proto_tree_add_item(chunk_tree, hf_initiate_tag,                      chunk_tvb, INIT_CHUNK_INITIATE_TAG_OFFSET,               INIT_CHUNK_INITIATE_TAG_LENGTH,               ENC_BIG_ENDIAN);
3931
54
    proto_item_set_hidden(hidden_item);
3932
54
    proto_tree_add_item(chunk_tree, hf_initack_chunk_adv_rec_window_credit,      chunk_tvb, INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET,      INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH,      ENC_BIG_ENDIAN);
3933
54
    proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_outbound_streams, chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH, ENC_BIG_ENDIAN);
3934
54
    proto_tree_add_item(chunk_tree, hf_initack_chunk_number_of_inbound_streams,  chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET,  INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH,  ENC_BIG_ENDIAN);
3935
54
    proto_tree_add_item(chunk_tree, hf_initack_chunk_initial_tsn,                chunk_tvb, INIT_CHUNK_INITIAL_TSN_OFFSET,                INIT_CHUNK_INITIAL_TSN_LENGTH,                ENC_BIG_ENDIAN);
3936
3937
54
    proto_item_append_text(chunk_item, " (Outbound streams: %u, inbound streams: %u)",
3938
54
                           tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET),
3939
54
                           tvb_get_ntohs(chunk_tvb, INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET));
3940
54
  }
3941
  /* handle variable parameters */
3942
54
  chunk_length -= INIT_CHUNK_FIXED_PARAMTERS_LENGTH;
3943
54
  parameters_tvb = tvb_new_subset_length(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET,
3944
54
                                  MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET)));
3945
54
  dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, false, true);
3946
54
}
3947
3948
16
#define SCTP_SACK_CHUNK_NS_BIT                  0x01
3949
1.32k
#define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH    4
3950
1.00k
#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4
3951
720
#define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH  2
3952
432
#define SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH    2
3953
6.61k
#define SACK_CHUNK_GAP_BLOCK_LENGTH             4
3954
16.1k
#define SACK_CHUNK_GAP_BLOCK_START_LENGTH       2
3955
6.47k
#define SACK_CHUNK_GAP_BLOCK_END_LENGTH         2
3956
1.03k
#define SACK_CHUNK_DUP_TSN_LENGTH               4
3957
3958
1.61k
#define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0)
3959
1.15k
#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
3960
1.15k
                                                 SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
3961
864
#define SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET (SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
3962
864
                                                SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
3963
576
#define SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET (SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
3964
576
                                              SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
3965
288
#define SACK_CHUNK_GAP_BLOCK_OFFSET (SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
3966
288
                                     SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
3967
3968
3969
static void
3970
dissect_sack_chunk(packet_info *pinfo, tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item, sctp_half_assoc_t *ha)
3971
144
{
3972
144
  uint16_t number_of_gap_blocks, number_of_dup_tsns;
3973
144
  uint16_t gap_block_number, dup_tsn_number, start, end;
3974
144
  int gap_block_offset, dup_tsn_offset;
3975
144
  uint32_t cum_tsn_ack;
3976
144
  proto_tree *block_tree;
3977
144
  proto_tree *flags_tree;
3978
144
  proto_item *ctsa_item;
3979
144
  proto_item *a_rwnd_item;
3980
144
  proto_tree *acks_tree;
3981
144
  uint32_t tsns_gap_acked = 0;
3982
144
  uint32_t a_rwnd;
3983
144
  uint16_t last_end;
3984
3985
144
  cum_tsn_ack = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
3986
144
  if((show_relative_tsns) && (ha) && (ha->peer)) {
3987
32
    cum_tsn_ack -= ha->peer->first_tsn;
3988
32
  }
3989
3990
144
  flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_sack_chunk_flags);
3991
144
  proto_tree_add_item(flags_tree, hf_sack_chunk_ns, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
3992
144
  if((show_relative_tsns) && (ha) && (ha->peer)) {
3993
32
     ctsa_item = proto_tree_add_uint(chunk_tree, hf_sack_chunk_cumulative_tsn_ack, chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, cum_tsn_ack);
3994
32
     proto_tree_add_item(chunk_tree, hf_sack_chunk_cumulative_tsn_ack_raw, chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, ENC_BIG_ENDIAN);
3995
32
  }
3996
112
  else {
3997
112
     ctsa_item = proto_tree_add_item(chunk_tree, hf_sack_chunk_cumulative_tsn_ack_raw, chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, ENC_BIG_ENDIAN);
3998
112
  }
3999
144
  a_rwnd_item = proto_tree_add_item(chunk_tree, hf_sack_chunk_adv_rec_window_credit,  chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, ENC_BIG_ENDIAN);
4000
144
  proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_gap_blocks, chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH, ENC_BIG_ENDIAN);
4001
144
  proto_tree_add_item(chunk_tree, hf_sack_chunk_number_of_dup_tsns,   chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET,   SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH,   ENC_BIG_ENDIAN);
4002
4003
144
  a_rwnd = tvb_get_ntohl(chunk_tvb, SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET);
4004
144
  if (a_rwnd == 0)
4005
11
      expert_add_info(pinfo, a_rwnd_item, &ei_sctp_sack_chunk_adv_rec_window_credit);
4006
4007
4008
  /* handle the gap acknowledgement blocks */
4009
144
  number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
4010
144
  gap_block_offset     = SACK_CHUNK_GAP_BLOCK_OFFSET;
4011
4012
144
  acks_tree = proto_item_add_subtree(ctsa_item,ett_sctp_ack);
4013
144
  sctp_ack_block(pinfo, ha, chunk_tvb, acks_tree, NULL, cum_tsn_ack);
4014
4015
144
  last_end = 0;
4016
3.37k
  for(gap_block_number = 0; gap_block_number < number_of_gap_blocks; gap_block_number++) {
4017
3.23k
    proto_item *pi;
4018
3.23k
    proto_tree *pt;
4019
3.23k
    uint32_t tsn_start;
4020
4021
3.23k
    start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
4022
3.23k
    end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH);
4023
3.23k
    tsn_start = cum_tsn_ack + start;
4024
4025
3.23k
    block_tree = proto_tree_add_subtree_format(chunk_tree, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_LENGTH,
4026
3.23k
                        ett_sctp_sack_chunk_gap_block, NULL, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
4027
4028
3.23k
    pi = proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset, SACK_CHUNK_GAP_BLOCK_START_LENGTH, ENC_BIG_ENDIAN);
4029
3.23k
    pt = proto_item_add_subtree(pi, ett_sctp_sack_chunk_gap_block_start);
4030
3.23k
    pi = proto_tree_add_uint(pt, hf_sack_chunk_gap_block_start_tsn,
4031
3.23k
                             chunk_tvb, gap_block_offset,SACK_CHUNK_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
4032
3.23k
    proto_item_set_generated(pi);
4033
4034
3.23k
    pi = proto_tree_add_item(block_tree, hf_sack_chunk_gap_block_end, chunk_tvb, gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH,   ENC_BIG_ENDIAN);
4035
3.23k
    pt = proto_item_add_subtree(pi, ett_sctp_sack_chunk_gap_block_end);
4036
3.23k
    pi = proto_tree_add_uint(pt, hf_sack_chunk_gap_block_end_tsn, chunk_tvb,
4037
3.23k
                             gap_block_offset + SACK_CHUNK_GAP_BLOCK_START_LENGTH, SACK_CHUNK_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
4038
3.23k
    proto_item_set_generated(pi);
4039
4040
3.23k
    sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end);
4041
3.23k
    gap_block_offset += SACK_CHUNK_GAP_BLOCK_LENGTH;
4042
4043
3.23k
    tsns_gap_acked += (end+1 - start);
4044
4045
    /* Check validity */
4046
3.23k
    if (start > end) {
4047
897
       expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_malformed);
4048
897
    }
4049
3.23k
    if (last_end > start) {
4050
884
       expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_out_of_order);
4051
884
    }
4052
3.23k
    last_end = end;
4053
3.23k
  }
4054
4055
144
  if(last_end == 0) {
4056
    /* No GapAck -> only show CumAck */
4057
29
    col_append_fstr(pinfo->cinfo, COL_INFO,
4058
29
                    "(Ack=%" PRIu32 ", Arwnd=%" PRIu32 ") ",
4059
29
                    cum_tsn_ack, a_rwnd);
4060
29
  }
4061
115
  else {
4062
    /* Show CumAck + highest GapAck */
4063
115
    col_append_fstr(pinfo->cinfo, COL_INFO,
4064
115
                    "(Ack=%" PRIu32 "+%" PRIu32 ", Arwnd=%" PRIu32 ") ",
4065
115
                    cum_tsn_ack, last_end, a_rwnd);
4066
115
  }
4067
4068
144
  if (tsns_gap_acked) {
4069
10
    proto_item *pi;
4070
4071
10
    pi = proto_tree_add_uint(chunk_tree, hf_sack_chunk_number_tsns_gap_acked, chunk_tvb, 0, 0, tsns_gap_acked);
4072
10
    proto_item_set_generated(pi);
4073
4074
    /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
4075
     *  number: it could be tuned.
4076
     */
4077
10
    if (tsns_gap_acked > 100)
4078
8
      expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_number_tsns_gap_acked_100);
4079
4080
10
  }
4081
4082
4083
  /* handle the duplicate TSNs */
4084
144
  number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
4085
144
  dup_tsn_offset     = SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * SACK_CHUNK_GAP_BLOCK_LENGTH;
4086
660
  for(dup_tsn_number = 0; dup_tsn_number < number_of_dup_tsns; dup_tsn_number++) {
4087
516
    proto_tree_add_item(chunk_tree, hf_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, SACK_CHUNK_DUP_TSN_LENGTH, ENC_BIG_ENDIAN);
4088
516
    dup_tsn_offset += SACK_CHUNK_DUP_TSN_LENGTH;
4089
516
  }
4090
4091
144
  proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, duplicate TSNs: %u)",
4092
144
                         tvb_get_ntohl(chunk_tvb, SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
4093
144
                         a_rwnd,
4094
144
                         number_of_gap_blocks, number_of_dup_tsns);
4095
144
}
4096
4097
/* NE: Dissect nr-sack chunk */
4098
16
#define SCTP_NR_SACK_CHUNK_NS_BIT                  0x01
4099
2.04k
#define NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH       4
4100
1.70k
#define NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH    4
4101
1.36k
#define NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH     2
4102
1.02k
#define NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH  2
4103
680
#define NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH       2
4104
510
#define NR_SACK_CHUNK_RESERVED_LENGTH                 2
4105
4.47k
#define NR_SACK_CHUNK_GAP_BLOCK_LENGTH                4
4106
10.7k
#define NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH          2
4107
4.30k
#define NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH            2
4108
4.38k
#define NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH             4
4109
10.5k
#define NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH       2
4110
4.21k
#define NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH         2
4111
1.12k
#define NR_SACK_CHUNK_DUP_TSN_LENGTH                  4
4112
4113
2.38k
#define NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET        (CHUNK_VALUE_OFFSET + 0)
4114
1.87k
#define NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET     (NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \
4115
1.87k
                                                        NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH)
4116
1.53k
#define NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET      (NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET + \
4117
1.53k
                                                        NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH)
4118
1.19k
#define NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET   (NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET + \
4119
1.19k
                                                        NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH)
4120
850
#define NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET        (NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET + \
4121
850
                                                        NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH)
4122
510
#define NR_SACK_CHUNK_RESERVED_OFFSET                  (NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET + \
4123
510
                                                        NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH)
4124
340
#define NR_SACK_CHUNK_GAP_BLOCK_OFFSET                 (NR_SACK_CHUNK_RESERVED_OFFSET + \
4125
340
                                                        NR_SACK_CHUNK_RESERVED_LENGTH)
4126
4127
static void
4128
dissect_nr_sack_chunk(packet_info *pinfo, tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item, sctp_half_assoc_t *ha)
4129
170
{
4130
170
  uint16_t number_of_gap_blocks, number_of_dup_tsns;
4131
170
  uint16_t number_of_nr_gap_blocks;
4132
170
  uint16_t gap_block_number, nr_gap_block_number, dup_tsn_number, start, end;
4133
170
  int gap_block_offset, nr_gap_block_offset, dup_tsn_offset;
4134
170
  uint32_t cum_tsn_ack;
4135
170
  proto_tree *block_tree;
4136
170
  proto_tree *flags_tree;
4137
170
  proto_item *ctsa_item;
4138
170
  proto_tree *acks_tree;
4139
170
  uint32_t tsns_gap_acked = 0;
4140
170
  uint32_t tsns_nr_gap_acked = 0;
4141
170
  uint16_t last_end;
4142
4143
170
  flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_nr_sack_chunk_flags);
4144
170
  proto_tree_add_item(flags_tree, hf_nr_sack_chunk_ns, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4145
4146
170
  ctsa_item = proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_cumulative_tsn_ack, chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, ENC_BIG_ENDIAN);
4147
170
  proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_adv_rec_window_credit, chunk_tvb, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH, ENC_BIG_ENDIAN);
4148
4149
170
  proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_gap_blocks, chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET,  NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_LENGTH, ENC_BIG_ENDIAN);
4150
4151
170
  proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_nr_gap_blocks,  chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_LENGTH, ENC_BIG_ENDIAN);
4152
170
  proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_number_of_dup_tsns, chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_LENGTH, ENC_BIG_ENDIAN);
4153
170
  proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_reserved, chunk_tvb, NR_SACK_CHUNK_RESERVED_OFFSET, NR_SACK_CHUNK_RESERVED_LENGTH, ENC_BIG_ENDIAN);
4154
4155
4156
170
  number_of_gap_blocks = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_GAP_BLOCKS_OFFSET);
4157
170
  gap_block_offset     = NR_SACK_CHUNK_GAP_BLOCK_OFFSET;
4158
170
  cum_tsn_ack          = tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET);
4159
4160
170
  acks_tree = proto_item_add_subtree(ctsa_item,ett_sctp_ack);
4161
170
  sctp_ack_block(pinfo, ha, chunk_tvb, acks_tree, NULL, cum_tsn_ack);
4162
4163
170
  last_end = 0;
4164
2.32k
  for(gap_block_number = 0; gap_block_number < number_of_gap_blocks; gap_block_number++) {
4165
2.15k
    proto_item *pi;
4166
2.15k
    proto_tree *pt;
4167
2.15k
    uint32_t tsn_start;
4168
4169
2.15k
    start = tvb_get_ntohs(chunk_tvb, gap_block_offset);
4170
2.15k
    end   = tvb_get_ntohs(chunk_tvb, gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH);
4171
2.15k
    tsn_start = cum_tsn_ack + start;
4172
4173
2.15k
    block_tree = proto_tree_add_subtree_format(chunk_tree, chunk_tvb, gap_block_offset, NR_SACK_CHUNK_GAP_BLOCK_LENGTH,
4174
2.15k
                        ett_sctp_nr_sack_chunk_gap_block, NULL, "Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
4175
4176
2.15k
    pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_gap_block_start, chunk_tvb, gap_block_offset, NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, ENC_BIG_ENDIAN);
4177
2.15k
    pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_gap_block_start);
4178
2.15k
    pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_gap_block_start_tsn,
4179
2.15k
                             chunk_tvb, gap_block_offset,NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
4180
2.15k
    proto_item_set_generated(pi);
4181
4182
2.15k
    pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_gap_block_end, chunk_tvb, gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH,   ENC_BIG_ENDIAN);
4183
2.15k
    pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_gap_block_end);
4184
2.15k
    pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_gap_block_end_tsn, chunk_tvb,
4185
2.15k
                               gap_block_offset + NR_SACK_CHUNK_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
4186
2.15k
    proto_item_set_generated(pi);
4187
4188
2.15k
    sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end);
4189
2.15k
    gap_block_offset += NR_SACK_CHUNK_GAP_BLOCK_LENGTH;
4190
2.15k
    tsns_gap_acked += (end - start) + 1;
4191
4192
    /* Check validity */
4193
2.15k
    if (start > end) {
4194
608
       expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_malformed);
4195
608
    }
4196
2.15k
    if (last_end > start) {
4197
581
       expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_out_of_order);
4198
581
    }
4199
2.15k
    last_end = end;
4200
2.15k
  }
4201
4202
170
  if (tsns_gap_acked) {
4203
18
    proto_item *pi;
4204
4205
18
    pi = proto_tree_add_uint(chunk_tree, hf_nr_sack_chunk_number_tsns_gap_acked, chunk_tvb, 0, 0, tsns_gap_acked);
4206
18
    proto_item_set_generated(pi);
4207
4208
    /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
4209
     *  number: it could be tuned.
4210
     */
4211
18
    if (tsns_gap_acked > 100)
4212
13
      expert_add_info(pinfo, pi, &ei_sctp_nr_sack_chunk_number_tsns_gap_acked_100);
4213
4214
18
  }
4215
4216
  /* NE: handle the nr-sack chunk's nr-gap blocks */
4217
170
  number_of_nr_gap_blocks = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_NR_GAP_BLOCKS_OFFSET);
4218
170
  nr_gap_block_offset     = gap_block_offset;
4219
4220
170
  last_end = 0;
4221
2.27k
  for(nr_gap_block_number = 0; nr_gap_block_number < number_of_nr_gap_blocks; nr_gap_block_number++) {
4222
2.10k
    proto_item *pi;
4223
2.10k
    proto_tree *pt;
4224
    /*uint32_t tsn_start;*/
4225
4226
2.10k
    start = tvb_get_ntohs(chunk_tvb, nr_gap_block_offset);
4227
2.10k
    end   = tvb_get_ntohs(chunk_tvb, nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH);
4228
    /*tsn_start = cum_tsn_ack + start;*/
4229
4230
2.10k
    block_tree = proto_tree_add_subtree_format(chunk_tree, chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH,
4231
2.10k
            ett_sctp_nr_sack_chunk_nr_gap_block, NULL, "NR-Gap Acknowledgement for TSN %u to %u", cum_tsn_ack + start, cum_tsn_ack + end);
4232
4233
2.10k
    pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_nr_gap_block_start, chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, ENC_BIG_ENDIAN);
4234
2.10k
    pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_nr_gap_block_start);
4235
2.10k
    pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_nr_gap_block_start_tsn,
4236
2.10k
                             chunk_tvb, nr_gap_block_offset, NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, cum_tsn_ack + start);
4237
2.10k
    proto_item_set_generated(pi);
4238
4239
2.10k
    pi = proto_tree_add_item(block_tree, hf_nr_sack_chunk_nr_gap_block_end, chunk_tvb, nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH,   ENC_BIG_ENDIAN);
4240
2.10k
    pt = proto_item_add_subtree(pi, ett_sctp_nr_sack_chunk_nr_gap_block_end);
4241
2.10k
    pi = proto_tree_add_uint(pt, hf_nr_sack_chunk_nr_gap_block_end_tsn, chunk_tvb,
4242
2.10k
                             nr_gap_block_offset + NR_SACK_CHUNK_NR_GAP_BLOCK_START_LENGTH, NR_SACK_CHUNK_NR_GAP_BLOCK_END_LENGTH, cum_tsn_ack + end);
4243
2.10k
    proto_item_set_generated(pi);
4244
4245
    /* sctp_ack_block(pinfo, ha, chunk_tvb, block_tree, &tsn_start, cum_tsn_ack + end); */
4246
2.10k
    nr_gap_block_offset += NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH;
4247
2.10k
    tsns_nr_gap_acked += (end - start) + 1;
4248
4249
    /* Check validity */
4250
2.10k
    if (start > end) {
4251
618
       expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_malformed);
4252
618
    }
4253
2.10k
    if (last_end > start) {
4254
599
       expert_add_info(pinfo, pi, &ei_sctp_sack_chunk_gap_block_out_of_order);
4255
599
    }
4256
2.10k
    last_end = end;
4257
2.10k
  }
4258
4259
170
  if (tsns_nr_gap_acked) {
4260
10
    proto_item *pi;
4261
4262
10
    pi = proto_tree_add_uint(chunk_tree, hf_nr_sack_chunk_number_tsns_nr_gap_acked, chunk_tvb, 0, 0, tsns_nr_gap_acked);
4263
10
    proto_item_set_generated(pi);
4264
4265
    /*  If there are a huge number of GAP ACKs, warn the user.  100 is a random
4266
     *  number: it could be tuned.
4267
     */
4268
10
    if (tsns_nr_gap_acked > 100)
4269
7
      expert_add_info(pinfo, pi, &ei_sctp_nr_sack_chunk_number_tsns_nr_gap_acked_100);
4270
10
  }
4271
4272
  /* handle the duplicate TSNs */
4273
170
  number_of_dup_tsns = tvb_get_ntohs(chunk_tvb, NR_SACK_CHUNK_NUMBER_OF_DUP_TSNS_OFFSET);
4274
170
  dup_tsn_offset     = NR_SACK_CHUNK_GAP_BLOCK_OFFSET + number_of_gap_blocks * NR_SACK_CHUNK_GAP_BLOCK_LENGTH
4275
170
    + number_of_nr_gap_blocks * NR_SACK_CHUNK_NR_GAP_BLOCK_LENGTH;
4276
4277
4278
730
  for(dup_tsn_number = 0; dup_tsn_number < number_of_dup_tsns; dup_tsn_number++) {
4279
560
    proto_tree_add_item(chunk_tree, hf_nr_sack_chunk_duplicate_tsn, chunk_tvb, dup_tsn_offset, NR_SACK_CHUNK_DUP_TSN_LENGTH, ENC_BIG_ENDIAN);
4280
560
    dup_tsn_offset += NR_SACK_CHUNK_DUP_TSN_LENGTH;
4281
560
  }
4282
4283
170
  proto_item_append_text(chunk_item, " (Cumulative TSN: %u, a_rwnd: %u, gaps: %u, nr-gaps: %u, duplicate TSNs: %u)",
4284
170
                         tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET),
4285
170
                         tvb_get_ntohl(chunk_tvb, NR_SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET),
4286
170
                         number_of_gap_blocks, number_of_nr_gap_blocks, number_of_dup_tsns);
4287
170
}
4288
4289
29
#define HEARTBEAT_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
4290
4291
static void
4292
// NOLINTNEXTLINE(misc-no-recursion)
4293
dissect_heartbeat_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
4294
29
{
4295
29
  tvbuff_t   *parameter_tvb;
4296
4297
29
  if (chunk_tree) {
4298
29
    proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
4299
29
    parameter_tvb  = tvb_new_subset_length(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET,
4300
29
                                    MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, HEARTBEAT_CHUNK_INFO_OFFSET)));
4301
    /* FIXME: Parameters or parameter? */
4302
29
    dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, false, false, true);
4303
29
  }
4304
29
}
4305
4306
16
#define HEARTBEAT_ACK_CHUNK_INFO_OFFSET CHUNK_VALUE_OFFSET
4307
4308
static void
4309
// NOLINTNEXTLINE(misc-no-recursion)
4310
dissect_heartbeat_ack_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
4311
16
{
4312
16
  tvbuff_t   *parameter_tvb;
4313
4314
16
  if (chunk_tree) {
4315
16
    proto_item_append_text(chunk_item, " (Information: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
4316
16
    parameter_tvb  = tvb_new_subset_length(chunk_tvb, HEARTBEAT_ACK_CHUNK_INFO_OFFSET,
4317
16
                                    MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, HEARTBEAT_ACK_CHUNK_INFO_OFFSET)));
4318
    /* FIXME: Parameters or parameter? */
4319
16
    dissect_parameter(parameter_tvb, pinfo, chunk_tree, NULL, false, false, true);
4320
16
  }
4321
16
}
4322
4323
#define ABORT_CHUNK_FIRST_ERROR_CAUSE_OFFSET 4
4324
72
#define SCTP_ABORT_CHUNK_T_BIT               0x01
4325
4326
static void
4327
// NOLINTNEXTLINE(misc-no-recursion)
4328
dissect_abort_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *flags_item)
4329
56
{
4330
56
  tvbuff_t *causes_tvb;
4331
56
  proto_tree *flags_tree;
4332
4333
56
  sctp_info.vtag_reflected =
4334
56
      (tvb_get_uint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_ABORT_CHUNK_T_BIT) != 0;
4335
4336
56
  if (chunk_tree) {
4337
56
    flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_abort_chunk_flags);
4338
56
    proto_tree_add_item(flags_tree, hf_abort_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4339
56
    causes_tvb  = tvb_new_subset_length(chunk_tvb, CHUNK_VALUE_OFFSET,
4340
56
                                 MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, CHUNK_VALUE_OFFSET)));
4341
56
    dissect_error_causes(causes_tvb, pinfo, chunk_tree);
4342
56
  }
4343
56
}
4344
4345
12
#define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET CHUNK_VALUE_OFFSET
4346
6
#define SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4
4347
4348
static void
4349
dissect_shutdown_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
4350
6
{
4351
6
  if (chunk_tree) {
4352
6
    proto_tree_add_item(chunk_tree, hf_shutdown_chunk_cumulative_tsn_ack, chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_LENGTH, ENC_BIG_ENDIAN);
4353
6
    proto_item_append_text(chunk_item, " (Cumulative TSN ack: %u)", tvb_get_ntohl(chunk_tvb, SHUTDOWN_CHUNK_CUMULATIVE_TSN_ACK_OFFSET));
4354
6
  }
4355
6
}
4356
4357
static void
4358
dissect_shutdown_ack_chunk(tvbuff_t *chunk_tvb _U_)
4359
13
{
4360
13
}
4361
4362
42
#define ERROR_CAUSE_IND_CAUSES_OFFSET CHUNK_VALUE_OFFSET
4363
4364
static void
4365
// NOLINTNEXTLINE(misc-no-recursion)
4366
dissect_error_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree)
4367
42
{
4368
42
  tvbuff_t *causes_tvb;
4369
4370
42
  if (chunk_tree) {
4371
42
    causes_tvb = tvb_new_subset_length(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET,
4372
42
                                MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, ERROR_CAUSE_IND_CAUSES_OFFSET)));
4373
42
    dissect_error_causes(causes_tvb, pinfo, chunk_tree);
4374
42
  }
4375
42
}
4376
4377
7
#define COOKIE_OFFSET CHUNK_VALUE_OFFSET
4378
4379
static void
4380
dissect_cookie_echo_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
4381
7
{
4382
7
  if (chunk_tree) {
4383
7
    proto_tree_add_item(chunk_tree, hf_cookie, chunk_tvb, COOKIE_OFFSET, chunk_length - CHUNK_HEADER_LENGTH, ENC_NA);
4384
7
    proto_item_append_text(chunk_item, " (Cookie length: %u byte%s)", chunk_length - CHUNK_HEADER_LENGTH, plurality(chunk_length - CHUNK_HEADER_LENGTH, "", "s"));
4385
7
  }
4386
7
}
4387
4388
static void
4389
dissect_cookie_ack_chunk(tvbuff_t *chunk_tvb _U_)
4390
8
{
4391
8
}
4392
4393
14
#define ECNE_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
4394
7
#define ECNE_CHUNK_LOWEST_TSN_LENGTH 4
4395
4396
static void
4397
dissect_ecne_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
4398
7
{
4399
7
    proto_tree_add_item(chunk_tree, hf_ecne_chunk_lowest_tsn, chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET, ECNE_CHUNK_LOWEST_TSN_LENGTH, ENC_BIG_ENDIAN);
4400
7
    proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, ECNE_CHUNK_LOWEST_TSN_OFFSET));
4401
7
}
4402
4403
16
#define CWR_CHUNK_LOWEST_TSN_OFFSET CHUNK_VALUE_OFFSET
4404
8
#define CWR_CHUNK_LOWEST_TSN_LENGTH 4
4405
4406
static void
4407
dissect_cwr_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *chunk_item)
4408
8
{
4409
8
    proto_tree_add_item(chunk_tree, hf_cwr_chunk_lowest_tsn, chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET, CWR_CHUNK_LOWEST_TSN_LENGTH, ENC_BIG_ENDIAN);
4410
8
    proto_item_append_text(chunk_item, " (Lowest TSN: %u)", tvb_get_ntohl(chunk_tvb, CWR_CHUNK_LOWEST_TSN_OFFSET));
4411
8
}
4412
4413
18
#define SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT 0x01
4414
4415
4416
static const true_false_string sctp_shutdown_complete_chunk_t_bit_value = {
4417
  "Tag reflected",
4418
  "Tag not reflected"
4419
};
4420
4421
4422
static void
4423
dissect_shutdown_complete_chunk(tvbuff_t *chunk_tvb, proto_tree *chunk_tree, proto_item *flags_item)
4424
2
{
4425
2
  proto_tree *flags_tree;
4426
4427
2
  sctp_info.vtag_reflected =
4428
2
      (tvb_get_uint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT) != 0;
4429
4430
2
  if (chunk_tree) {
4431
2
    flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_shutdown_complete_chunk_flags);
4432
2
    proto_tree_add_item(flags_tree, hf_shutdown_complete_chunk_t_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4433
2
  }
4434
2
}
4435
4436
108
#define FORWARD_TSN_CHUNK_TSN_LENGTH 4
4437
1.71k
#define FORWARD_TSN_CHUNK_SID_LENGTH 2
4438
1.15k
#define FORWARD_TSN_CHUNK_SSN_LENGTH 2
4439
54
#define FORWARD_TSN_CHUNK_TSN_OFFSET CHUNK_VALUE_OFFSET
4440
1.12k
#define FORWARD_TSN_CHUNK_SID_OFFSET 0
4441
562
#define FORWARD_TSN_CHUNK_SSN_OFFSET (FORWARD_TSN_CHUNK_SID_OFFSET + FORWARD_TSN_CHUNK_SID_LENGTH)
4442
4443
static void
4444
dissect_forward_tsn_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
4445
27
{
4446
27
  unsigned   offset;
4447
27
  uint16_t number_of_affected_streams, affected_stream;
4448
4449
  /* FIXME */
4450
27
  if (chunk_length < CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH) {
4451
0
    proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4452
0
                           chunk_length,
4453
0
                           CHUNK_HEADER_LENGTH + FORWARD_TSN_CHUNK_TSN_LENGTH);
4454
0
    return;
4455
0
  }
4456
27
  if (chunk_tree) {
4457
27
    proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_tsn, chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET, FORWARD_TSN_CHUNK_TSN_LENGTH, ENC_BIG_ENDIAN);
4458
27
    number_of_affected_streams = (chunk_length - CHUNK_HEADER_LENGTH - FORWARD_TSN_CHUNK_TSN_LENGTH) /
4459
27
                                 (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
4460
27
    offset = CHUNK_VALUE_OFFSET + FORWARD_TSN_CHUNK_TSN_LENGTH;
4461
4462
589
    for(affected_stream = 0;  affected_stream < number_of_affected_streams; affected_stream++) {
4463
562
        proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_sid, chunk_tvb, offset + FORWARD_TSN_CHUNK_SID_OFFSET, FORWARD_TSN_CHUNK_SID_LENGTH, ENC_BIG_ENDIAN);
4464
562
        proto_tree_add_item(chunk_tree, hf_forward_tsn_chunk_ssn, chunk_tvb, offset + FORWARD_TSN_CHUNK_SSN_OFFSET, FORWARD_TSN_CHUNK_SSN_LENGTH, ENC_BIG_ENDIAN);
4465
562
        offset = offset + (FORWARD_TSN_CHUNK_SID_LENGTH + FORWARD_TSN_CHUNK_SSN_LENGTH);
4466
562
    }
4467
27
    proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, FORWARD_TSN_CHUNK_TSN_OFFSET));
4468
27
  }
4469
27
}
4470
4471
114
#define I_FORWARD_TSN_CHUNK_TSN_LENGTH   4
4472
1.64k
#define I_FORWARD_TSN_CHUNK_SID_LENGTH   2
4473
1.37k
#define I_FORWARD_TSN_CHUNK_FLAGS_LENGTH 2
4474
568
#define I_FORWARD_TSN_CHUNK_MID_LENGTH   4
4475
56
#define I_FORWARD_TSN_CHUNK_TSN_OFFSET   CHUNK_VALUE_OFFSET
4476
1.35k
#define I_FORWARD_TSN_CHUNK_SID_OFFSET   0
4477
1.08k
#define I_FORWARD_TSN_CHUNK_FLAGS_OFFSET (I_FORWARD_TSN_CHUNK_SID_OFFSET + I_FORWARD_TSN_CHUNK_SID_LENGTH)
4478
270
#define I_FORWARD_TSN_CHUNK_MID_OFFSET   (I_FORWARD_TSN_CHUNK_FLAGS_OFFSET + I_FORWARD_TSN_CHUNK_FLAGS_LENGTH)
4479
4480
16
#define SCTP_I_FORWARD_TSN_CHUNK_U_BIT    0x0001
4481
16
#define SCTP_I_FORWARD_TSN_CHUNK_RES_MASK 0xfffe
4482
4483
static const true_false_string sctp_i_forward_tsn_chunk_u_bit_value = {
4484
  "Unordered messages",
4485
  "Ordered messages"
4486
};
4487
4488
static void
4489
dissect_i_forward_tsn_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
4490
29
{
4491
29
  unsigned   offset;
4492
29
  uint16_t number_of_affected_streams, affected_stream;
4493
29
  proto_tree *flags_tree;
4494
29
  proto_item *flags_item = NULL;
4495
4496
  /* FIXME */
4497
29
  if (chunk_length < CHUNK_HEADER_LENGTH + I_FORWARD_TSN_CHUNK_TSN_LENGTH) {
4498
1
    proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4499
1
                           chunk_length,
4500
1
                           CHUNK_HEADER_LENGTH + I_FORWARD_TSN_CHUNK_TSN_LENGTH);
4501
1
    return;
4502
1
  }
4503
28
  if (chunk_tree) {
4504
28
    proto_tree_add_item(chunk_tree, hf_i_forward_tsn_chunk_tsn, chunk_tvb, I_FORWARD_TSN_CHUNK_TSN_OFFSET, I_FORWARD_TSN_CHUNK_TSN_LENGTH, ENC_BIG_ENDIAN);
4505
28
    number_of_affected_streams = (chunk_length - CHUNK_HEADER_LENGTH - I_FORWARD_TSN_CHUNK_TSN_LENGTH) /
4506
28
                                 (I_FORWARD_TSN_CHUNK_SID_LENGTH + I_FORWARD_TSN_CHUNK_FLAGS_LENGTH + I_FORWARD_TSN_CHUNK_MID_LENGTH);
4507
28
    offset = CHUNK_VALUE_OFFSET + I_FORWARD_TSN_CHUNK_TSN_LENGTH;
4508
4509
298
    for(affected_stream = 0;  affected_stream < number_of_affected_streams; affected_stream++) {
4510
270
        proto_tree_add_item(chunk_tree, hf_i_forward_tsn_chunk_sid, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_SID_OFFSET, I_FORWARD_TSN_CHUNK_SID_LENGTH, ENC_BIG_ENDIAN);
4511
270
        flags_item = proto_tree_add_item(chunk_tree, hf_i_forward_tsn_chunk_flags, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_FLAGS_OFFSET, I_FORWARD_TSN_CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4512
270
        flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_i_forward_tsn_chunk_flags);
4513
270
        proto_tree_add_item(flags_tree, hf_i_forward_tsn_chunk_res, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_FLAGS_OFFSET, I_FORWARD_TSN_CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4514
270
        proto_tree_add_item(flags_tree, hf_i_forward_tsn_chunk_u_bit, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_FLAGS_OFFSET, I_FORWARD_TSN_CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4515
270
        proto_tree_add_item(chunk_tree, hf_i_forward_tsn_chunk_mid, chunk_tvb, offset + I_FORWARD_TSN_CHUNK_MID_OFFSET, I_FORWARD_TSN_CHUNK_MID_LENGTH, ENC_BIG_ENDIAN);
4516
270
        offset += (I_FORWARD_TSN_CHUNK_SID_LENGTH + I_FORWARD_TSN_CHUNK_FLAGS_LENGTH + I_FORWARD_TSN_CHUNK_MID_LENGTH);
4517
270
    }
4518
28
    proto_item_append_text(chunk_item, "(Cumulative TSN: %u)", tvb_get_ntohl(chunk_tvb, I_FORWARD_TSN_CHUNK_TSN_OFFSET));
4519
28
  }
4520
28
}
4521
4522
13
#define RE_CONFIG_PARAMETERS_OFFSET CHUNK_HEADER_LENGTH
4523
4524
static void
4525
// NOLINTNEXTLINE(misc-no-recursion)
4526
dissect_re_config_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item _U_)
4527
13
{
4528
13
  tvbuff_t *parameters_tvb;
4529
4530
13
  parameters_tvb = tvb_new_subset_length(chunk_tvb, RE_CONFIG_PARAMETERS_OFFSET,
4531
13
                                  MIN(chunk_length - CHUNK_HEADER_LENGTH, tvb_reported_length_remaining(chunk_tvb, RE_CONFIG_PARAMETERS_OFFSET)));
4532
13
  dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, false, false);
4533
13
}
4534
4535
12
#define SHARED_KEY_ID_LENGTH 2
4536
4537
9
#define SHARED_KEY_ID_OFFSET PARAMETER_VALUE_OFFSET
4538
6
#define HMAC_ID_OFFSET       (SHARED_KEY_ID_OFFSET + SHARED_KEY_ID_LENGTH)
4539
3
#define HMAC_OFFSET          (HMAC_ID_OFFSET + HMAC_ID_LENGTH)
4540
4541
static void
4542
dissect_auth_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, proto_tree *chunk_tree, proto_item *chunk_item _U_)
4543
3
{
4544
3
  unsigned hmac_length;
4545
4546
3
  hmac_length = chunk_length - CHUNK_HEADER_LENGTH - HMAC_ID_LENGTH - SHARED_KEY_ID_LENGTH;
4547
3
  proto_tree_add_item(chunk_tree, hf_shared_key_id, chunk_tvb, SHARED_KEY_ID_OFFSET, SHARED_KEY_ID_LENGTH, ENC_BIG_ENDIAN);
4548
3
  proto_tree_add_item(chunk_tree, hf_hmac_id,       chunk_tvb, HMAC_ID_OFFSET,       HMAC_ID_LENGTH,       ENC_BIG_ENDIAN);
4549
3
  if (hmac_length > 0)
4550
3
    proto_tree_add_item(chunk_tree, hf_hmac,    chunk_tvb, HMAC_OFFSET,    hmac_length,    ENC_NA);
4551
3
}
4552
4553
16
#define SCTP_DTLS_CHUNK_R_BIT 0x01
4554
4555
static const true_false_string sctp_dtls_chunk_r_bit_value = {
4556
  "Restart DTLS key context",
4557
  "Primary DTLS key context"
4558
};
4559
4560
static void
4561
dissect_dtls_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length _U_, proto_tree *chunk_tree, proto_item *flags_item)
4562
8
{
4563
8
  proto_tree *flags_tree;
4564
4565
8
  if (chunk_tree) {
4566
8
    flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_dtls_chunk_flags);
4567
8
    proto_tree_add_item(flags_tree, hf_dtls_chunk_r_bit, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4568
8
  }
4569
8
}
4570
4571
4572
120
#define SCTP_SEQUENCE_NUMBER_LENGTH    4
4573
56
#define SEQUENCE_NUMBER_OFFSET    CHUNK_VALUE_OFFSET
4574
7
#define ASCONF_CHUNK_PARAMETERS_OFFSET (SEQUENCE_NUMBER_OFFSET + SCTP_SEQUENCE_NUMBER_LENGTH)
4575
4576
static void
4577
// NOLINTNEXTLINE(misc-no-recursion)
4578
dissect_asconf_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
4579
8
{
4580
8
  tvbuff_t *parameters_tvb;
4581
4582
8
  if (chunk_length < CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH) {
4583
1
    proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4584
1
                           chunk_length,
4585
1
                           CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH);
4586
1
    return;
4587
1
  }
4588
7
  if (chunk_tree) {
4589
7
    proto_tree_add_item(chunk_tree, hf_asconf_seq_nr, chunk_tvb, SEQUENCE_NUMBER_OFFSET, SCTP_SEQUENCE_NUMBER_LENGTH, ENC_BIG_ENDIAN);
4590
7
  }
4591
7
  chunk_length -= CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH;
4592
7
  parameters_tvb = tvb_new_subset_length(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET,
4593
7
                                  MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, ASCONF_CHUNK_PARAMETERS_OFFSET)));
4594
7
  dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, false, false);
4595
7
}
4596
4597
21
#define ASCONF_ACK_CHUNK_PARAMETERS_OFFSET (SEQUENCE_NUMBER_OFFSET + SCTP_SEQUENCE_NUMBER_LENGTH)
4598
4599
static void
4600
// NOLINTNEXTLINE(misc-no-recursion)
4601
dissect_asconf_ack_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item)
4602
24
{
4603
24
  tvbuff_t *parameters_tvb;
4604
4605
24
  if (chunk_length < CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH) {
4606
3
    proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4607
3
                           chunk_length + CHUNK_HEADER_LENGTH,
4608
3
                           CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH);
4609
3
    return;
4610
3
  }
4611
21
  if (chunk_tree) {
4612
21
    proto_tree_add_item(chunk_tree, hf_asconf_ack_seq_nr, chunk_tvb, SEQUENCE_NUMBER_OFFSET, SCTP_SEQUENCE_NUMBER_LENGTH, ENC_BIG_ENDIAN);
4613
21
  }
4614
21
  chunk_length -= CHUNK_HEADER_LENGTH + SCTP_SEQUENCE_NUMBER_LENGTH;
4615
21
  parameters_tvb = tvb_new_subset_length(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET,
4616
21
                                  MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, ASCONF_ACK_CHUNK_PARAMETERS_OFFSET)));
4617
21
  dissect_parameters(parameters_tvb, pinfo, chunk_tree, NULL, false, false);
4618
21
}
4619
4620
110k
#define PKTDROP_CHUNK_BANDWIDTH_LENGTH      4
4621
94.7k
#define PKTDROP_CHUNK_QUEUESIZE_LENGTH      4
4622
78.9k
#define PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH 2
4623
63.1k
#define PKTDROP_CHUNK_RESERVED_SIZE_LENGTH  2
4624
4625
31.5k
#define PKTDROP_CHUNK_HEADER_LENGTH (CHUNK_HEADER_LENGTH + \
4626
31.5k
                   PKTDROP_CHUNK_BANDWIDTH_LENGTH + \
4627
31.5k
                   PKTDROP_CHUNK_QUEUESIZE_LENGTH + \
4628
31.5k
                   PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH + \
4629
31.5k
                   PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
4630
4631
78.9k
#define PKTDROP_CHUNK_BANDWIDTH_OFFSET      CHUNK_VALUE_OFFSET
4632
63.1k
#define PKTDROP_CHUNK_QUEUESIZE_OFFSET      (PKTDROP_CHUNK_BANDWIDTH_OFFSET + PKTDROP_CHUNK_BANDWIDTH_LENGTH)
4633
47.3k
#define PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET (PKTDROP_CHUNK_QUEUESIZE_OFFSET + PKTDROP_CHUNK_QUEUESIZE_LENGTH)
4634
31.5k
#define PKTDROP_CHUNK_RESERVED_SIZE_OFFSET  (PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET + PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH)
4635
15.7k
#define PKTDROP_CHUNK_DATA_FIELD_OFFSET     (PKTDROP_CHUNK_RESERVED_SIZE_OFFSET + PKTDROP_CHUNK_RESERVED_SIZE_LENGTH)
4636
4637
16
#define SCTP_PKTDROP_CHUNK_M_BIT 0x01
4638
16
#define SCTP_PKTDROP_CHUNK_B_BIT 0x02
4639
15.7k
#define SCTP_PKTDROP_CHUNK_T_BIT 0x04
4640
4641
static const true_false_string sctp_pktdropk_m_bit_value = {
4642
  "Source is a middlebox",
4643
  "Source is an endhost"
4644
};
4645
4646
static const true_false_string sctp_pktdropk_b_bit_value = {
4647
  "SCTP checksum was incorrect",
4648
  "SCTP checksum was correct"
4649
};
4650
4651
static const true_false_string sctp_pktdropk_t_bit_value = {
4652
  "Packet is truncated",
4653
  "Packet is not truncated"
4654
};
4655
4656
static void
4657
// NOLINTNEXTLINE(misc-no-recursion)
4658
dissect_pktdrop_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, packet_info *pinfo, proto_tree *chunk_tree, proto_item *chunk_item, proto_item *flags_item)
4659
15.7k
{
4660
15.7k
  tvbuff_t *data_field_tvb;
4661
15.7k
  proto_tree *flags_tree;
4662
4663
15.7k
  if (chunk_length < PKTDROP_CHUNK_HEADER_LENGTH) {
4664
2
    proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)",
4665
2
                           chunk_length,
4666
2
                           PKTDROP_CHUNK_HEADER_LENGTH);
4667
2
    return;
4668
2
  }
4669
15.7k
  chunk_length -= PKTDROP_CHUNK_HEADER_LENGTH;
4670
15.7k
  data_field_tvb = tvb_new_subset_length(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET,
4671
15.7k
                                  MIN(chunk_length, tvb_reported_length_remaining(chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET)));
4672
4673
15.7k
  if (chunk_tree) {
4674
15.7k
    flags_tree  = proto_item_add_subtree(flags_item, ett_sctp_pktdrop_chunk_flags);
4675
4676
15.7k
    proto_tree_add_item(flags_tree, hf_pktdrop_chunk_m_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  ENC_BIG_ENDIAN);
4677
15.7k
    proto_tree_add_item(flags_tree, hf_pktdrop_chunk_b_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  ENC_BIG_ENDIAN);
4678
15.7k
    proto_tree_add_item(flags_tree, hf_pktdrop_chunk_t_bit,            chunk_tvb, CHUNK_FLAGS_OFFSET,                  CHUNK_FLAGS_LENGTH,                  ENC_BIG_ENDIAN);
4679
15.7k
    proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_bandwidth,        chunk_tvb, PKTDROP_CHUNK_BANDWIDTH_OFFSET,      PKTDROP_CHUNK_BANDWIDTH_LENGTH,      ENC_BIG_ENDIAN);
4680
15.7k
    proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_queuesize,        chunk_tvb, PKTDROP_CHUNK_QUEUESIZE_OFFSET,      PKTDROP_CHUNK_QUEUESIZE_LENGTH,      ENC_BIG_ENDIAN);
4681
15.7k
    proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_truncated_length, chunk_tvb, PKTDROP_CHUNK_TRUNCATED_SIZE_OFFSET, PKTDROP_CHUNK_TRUNCATED_SIZE_LENGTH, ENC_BIG_ENDIAN);
4682
15.7k
    proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_reserved,         chunk_tvb, PKTDROP_CHUNK_RESERVED_SIZE_OFFSET,  PKTDROP_CHUNK_RESERVED_SIZE_LENGTH,  ENC_BIG_ENDIAN);
4683
4684
15.7k
    if (chunk_length > 0) {
4685
      /* XXX - We should dissect what we can and catch the BoundsError when we run out of bytes */
4686
15.7k
      if (tvb_get_uint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_PKTDROP_CHUNK_T_BIT)
4687
4
        proto_tree_add_item(chunk_tree, hf_pktdrop_chunk_data_field,   chunk_tvb, PKTDROP_CHUNK_DATA_FIELD_OFFSET,     chunk_length,                   ENC_NA);
4688
15.7k
      else {
4689
15.7k
        bool save_in_error_pkt = pinfo->flags.in_error_pkt;
4690
15.7k
        pinfo->flags.in_error_pkt = true;
4691
4692
15.7k
        dissect_sctp_packet(data_field_tvb, pinfo, chunk_tree, true);
4693
4694
15.7k
        pinfo->flags.in_error_pkt = save_in_error_pkt;
4695
15.7k
      }
4696
15.7k
    }
4697
15.7k
  }
4698
15.7k
}
4699
4700
static void
4701
dissect_pad_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, proto_tree *chunk_tree, proto_item *chunk_item)
4702
3
{
4703
3
  uint16_t value_length;
4704
4705
3
  if (chunk_tree) {
4706
3
    value_length = chunk_length - CHUNK_HEADER_LENGTH;
4707
3
    proto_tree_add_item(chunk_tree, hf_pad_chunk_padding_data, chunk_tvb, CHUNK_VALUE_OFFSET, value_length, ENC_NA);
4708
3
    proto_item_append_text(chunk_item, " (Padding data length: %u byte%s)", value_length, plurality(value_length, "", "s"));
4709
3
  }
4710
3
}
4711
4712
static void
4713
dissect_unknown_chunk(tvbuff_t *chunk_tvb, uint16_t chunk_length, uint8_t chunk_type, proto_tree *chunk_tree, proto_item *chunk_item)
4714
194
{
4715
194
  uint16_t value_length;
4716
4717
194
  if (chunk_tree) {
4718
194
    value_length = chunk_length - CHUNK_HEADER_LENGTH;
4719
194
    if (value_length > 0)
4720
189
      proto_tree_add_item(chunk_tree, hf_chunk_value, chunk_tvb, CHUNK_VALUE_OFFSET, value_length, ENC_NA);
4721
194
    proto_item_append_text(chunk_item, " (Type: %u, value length: %u byte%s)", chunk_type, value_length, plurality(value_length, "", "s"));
4722
194
  }
4723
194
}
4724
4725
16
#define SCTP_CHUNK_BIT_1 0x80
4726
16
#define SCTP_CHUNK_BIT_2 0x40
4727
4728
static const true_false_string sctp_chunk_bit_1_value = {
4729
  "Skip chunk and continue processing of the packet",
4730
  "Stop processing of the packet"
4731
};
4732
4733
static const true_false_string sctp_chunk_bit_2_value = {
4734
  "Do report",
4735
  "Do not report"
4736
};
4737
4738
4739
static bool
4740
// NOLINTNEXTLINE(misc-no-recursion)
4741
dissect_sctp_chunk(tvbuff_t *chunk_tvb,
4742
                   packet_info *pinfo,
4743
                   proto_tree *tree,
4744
                   proto_tree *sctp_tree,
4745
                   sctp_half_assoc_t *ha,
4746
                   bool useinfo)
4747
36.4k
{
4748
36.4k
  uint8_t type;
4749
36.4k
  uint16_t length, padding_length, reported_length;
4750
36.4k
  bool result;
4751
36.4k
  proto_item *flags_item, *chunk_item, *type_item, *length_item;
4752
36.4k
  proto_tree *chunk_tree, *type_tree;
4753
4754
36.4k
  result = false;
4755
4756
  /* first extract the chunk header */
4757
36.4k
  type            = tvb_get_uint8(chunk_tvb, CHUNK_TYPE_OFFSET);
4758
36.4k
  length          = tvb_get_ntohs(chunk_tvb, CHUNK_LENGTH_OFFSET);
4759
36.4k
  reported_length = tvb_reported_length(chunk_tvb);
4760
36.4k
  padding_length  = reported_length - length;
4761
4762
36.4k
  if (useinfo)
4763
20.5k
    col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(type, chunk_type_values, "RESERVED"));
4764
4765
  /* create proto_tree stuff */
4766
36.4k
  chunk_item = proto_tree_add_none_format(sctp_tree, hf_chunk, chunk_tvb, CHUNK_HEADER_OFFSET, reported_length,
4767
36.4k
                    "%s chunk", val_to_str_const(type, chunk_type_values, "RESERVED"));
4768
36.4k
  chunk_tree = proto_item_add_subtree(chunk_item, ett_sctp_chunk);
4769
4770
36.4k
  if (tree) {
4771
    /* then insert the chunk header components into the protocol tree */
4772
36.4k
    type_item  = proto_tree_add_item(chunk_tree, hf_chunk_type, chunk_tvb, CHUNK_TYPE_OFFSET, CHUNK_TYPE_LENGTH, ENC_BIG_ENDIAN);
4773
36.4k
    type_tree  = proto_item_add_subtree(type_item, ett_sctp_chunk_type);
4774
36.4k
    proto_tree_add_item(type_tree, hf_chunk_bit_1,  chunk_tvb, CHUNK_TYPE_OFFSET,  CHUNK_TYPE_LENGTH,  ENC_BIG_ENDIAN);
4775
36.4k
    proto_tree_add_item(type_tree, hf_chunk_bit_2,  chunk_tvb, CHUNK_TYPE_OFFSET,  CHUNK_TYPE_LENGTH,  ENC_BIG_ENDIAN);
4776
36.4k
    flags_item = proto_tree_add_item(chunk_tree, hf_chunk_flags, chunk_tvb, CHUNK_FLAGS_OFFSET, CHUNK_FLAGS_LENGTH, ENC_BIG_ENDIAN);
4777
36.4k
  } else {
4778
61
    chunk_tree = NULL;
4779
61
    chunk_item = NULL;
4780
61
    flags_item = NULL;
4781
61
  }
4782
4783
36.4k
  if (length < CHUNK_HEADER_LENGTH) {
4784
123
    if (tree) {
4785
123
      proto_tree_add_uint_format_value(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length,
4786
123
                                 "%u (invalid, should be >= %u)", length, CHUNK_HEADER_LENGTH);
4787
123
      proto_item_append_text(chunk_item, ", bogus chunk length %u < %u)", length, CHUNK_HEADER_LENGTH);
4788
123
    }
4789
4790
123
    if (type == SCTP_DATA_CHUNK_ID)
4791
76
      result = true;
4792
123
    return result;
4793
123
  }
4794
4795
36.3k
  length_item = proto_tree_add_uint(chunk_tree, hf_chunk_length, chunk_tvb, CHUNK_LENGTH_OFFSET, CHUNK_LENGTH_LENGTH, length);
4796
36.3k
  if (length > reported_length && !pinfo->flags.in_error_pkt) {
4797
19.7k
    expert_add_info_format(pinfo, length_item, &ei_sctp_chunk_length_bad, "Chunk length (%d) is longer than remaining data (%d) in the packet.", length, reported_length);
4798
    /* We'll almost certainly throw an exception shortly... */
4799
19.7k
  }
4800
4801
  /*
4802
  length -= CHUNK_HEADER_LENGTH;
4803
  */
4804
4805
  /* now dissect the chunk value */
4806
36.3k
  increment_dissection_depth(pinfo);
4807
36.3k
  switch(type) {
4808
19.4k
  case SCTP_DATA_CHUNK_ID:
4809
19.4k
    result = dissect_data_chunk(chunk_tvb, length, pinfo, tree, chunk_tree, chunk_item, flags_item, ha, false);
4810
19.4k
    break;
4811
53
  case SCTP_I_DATA_CHUNK_ID:
4812
53
    result = dissect_data_chunk(chunk_tvb, length, pinfo, tree, chunk_tree, chunk_item, flags_item, ha, true);
4813
53
    break;
4814
120
  case SCTP_INIT_CHUNK_ID:
4815
120
    dissect_init_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4816
120
    break;
4817
57
  case SCTP_INIT_ACK_CHUNK_ID:
4818
57
    dissect_init_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4819
57
    break;
4820
144
  case SCTP_SACK_CHUNK_ID:
4821
144
    dissect_sack_chunk(pinfo, chunk_tvb, chunk_tree, chunk_item, flags_item, ha);
4822
144
    break;
4823
29
  case SCTP_HEARTBEAT_CHUNK_ID:
4824
29
    dissect_heartbeat_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4825
29
    break;
4826
16
  case SCTP_HEARTBEAT_ACK_CHUNK_ID:
4827
16
    dissect_heartbeat_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4828
16
    break;
4829
56
  case SCTP_ABORT_CHUNK_ID:
4830
56
    dissect_abort_chunk(chunk_tvb, length, pinfo, chunk_tree, flags_item);
4831
56
    break;
4832
6
  case SCTP_SHUTDOWN_CHUNK_ID:
4833
6
    dissect_shutdown_chunk(chunk_tvb, chunk_tree, chunk_item);
4834
6
    break;
4835
13
  case SCTP_SHUTDOWN_ACK_CHUNK_ID:
4836
13
    dissect_shutdown_ack_chunk(chunk_tvb);
4837
13
    break;
4838
42
  case SCTP_ERROR_CHUNK_ID:
4839
42
    dissect_error_chunk(chunk_tvb, length, pinfo, chunk_tree);
4840
42
    break;
4841
7
  case SCTP_COOKIE_ECHO_CHUNK_ID:
4842
7
    dissect_cookie_echo_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4843
7
    break;
4844
8
  case SCTP_COOKIE_ACK_CHUNK_ID:
4845
8
    dissect_cookie_ack_chunk(chunk_tvb);
4846
8
    break;
4847
7
  case SCTP_ECNE_CHUNK_ID:
4848
7
    dissect_ecne_chunk(chunk_tvb, chunk_tree, chunk_item);
4849
7
    break;
4850
8
  case SCTP_CWR_CHUNK_ID:
4851
8
    dissect_cwr_chunk(chunk_tvb, chunk_tree, chunk_item);
4852
8
    break;
4853
2
  case SCTP_SHUTDOWN_COMPLETE_CHUNK_ID:
4854
2
    dissect_shutdown_complete_chunk(chunk_tvb, chunk_tree, flags_item);
4855
2
    break;
4856
27
  case SCTP_FORWARD_TSN_CHUNK_ID:
4857
27
    dissect_forward_tsn_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4858
27
    break;
4859
13
  case SCTP_RE_CONFIG_CHUNK_ID:
4860
13
    dissect_re_config_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4861
13
    break;
4862
3
  case SCTP_AUTH_CHUNK_ID:
4863
3
    dissect_auth_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4864
3
    break;
4865
170
  case SCTP_NR_SACK_CHUNK_ID:
4866
170
    dissect_nr_sack_chunk(pinfo, chunk_tvb, chunk_tree, chunk_item, flags_item, ha);
4867
170
    break;
4868
8
  case SCTP_DTLS_CHUNK_ID:
4869
8
    dissect_dtls_chunk(chunk_tvb, length, chunk_tree, flags_item);
4870
8
    break;
4871
24
  case SCTP_ASCONF_ACK_CHUNK_ID:
4872
24
    dissect_asconf_ack_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4873
24
    break;
4874
8
  case SCTP_ASCONF_CHUNK_ID:
4875
8
    dissect_asconf_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item);
4876
8
    break;
4877
29
  case SCTP_I_FORWARD_TSN_CHUNK_ID:
4878
29
    dissect_i_forward_tsn_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4879
29
    break;
4880
15.7k
  case SCTP_PKTDROP_CHUNK_ID:
4881
15.7k
    col_set_writable(pinfo->cinfo, -1, false);
4882
15.7k
    dissect_pktdrop_chunk(chunk_tvb, length, pinfo, chunk_tree, chunk_item, flags_item);
4883
15.7k
    col_set_writable(pinfo->cinfo, -1, true);
4884
15.7k
    break;
4885
3
  case SCTP_PAD_CHUNK_ID:
4886
3
    dissect_pad_chunk(chunk_tvb, length, chunk_tree, chunk_item);
4887
3
    break;
4888
194
  default:
4889
194
    dissect_unknown_chunk(chunk_tvb, length, type, chunk_tree, chunk_item);
4890
194
    break;
4891
36.3k
  }
4892
19.6k
  decrement_dissection_depth(pinfo);
4893
4894
19.6k
  if (padding_length > 0)
4895
19.3k
    proto_tree_add_item(chunk_tree, hf_chunk_padding, chunk_tvb, CHUNK_HEADER_OFFSET + length, padding_length, ENC_NA);
4896
4897
19.6k
  if (useinfo && ((type == SCTP_DATA_CHUNK_ID) || show_always_control_chunks))
4898
698
    col_set_fence(pinfo->cinfo, COL_INFO);
4899
4900
19.6k
  return result;
4901
36.3k
}
4902
4903
static void
4904
// NOLINTNEXTLINE(misc-no-recursion)
4905
dissect_sctp_chunks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *sctp_item, proto_tree *sctp_tree, sctp_half_assoc_t *ha, bool encapsulated, proto_item *vt)
4906
35.6k
{
4907
35.6k
  proto_item *pi;
4908
35.6k
  tvbuff_t *chunk_tvb;
4909
35.6k
  uint16_t length, total_length, remaining_length;
4910
35.6k
  int last_offset, offset;
4911
35.6k
  bool sctp_item_length_set;
4912
35.6k
  assoc_info_t tmpinfo;
4913
35.6k
  infodata_t id_dir;
4914
35.6k
  bool first_chunk = true;
4915
4916
  /* the common header of the datagram is already handled */
4917
35.6k
  last_offset = 0;
4918
35.6k
  offset = COMMON_HEADER_LENGTH;
4919
35.6k
  sctp_item_length_set = false;
4920
4921
72.2k
  while((remaining_length = tvb_reported_length_remaining(tvb, offset))) {
4922
    /* extract the chunk length and compute number of padding bytes */
4923
36.5k
    length         = tvb_get_ntohs(tvb, offset + CHUNK_LENGTH_OFFSET);
4924
36.5k
    total_length   = WS_ROUNDUP_4(length);
4925
4926
    /*  If we have less bytes than we need, throw an exception while dissecting
4927
     *  the chunk--not when generating the chunk_tvb below.
4928
     */
4929
36.5k
    total_length = MIN(total_length, remaining_length);
4930
4931
    /* create a tvb for the chunk including the padding bytes */
4932
36.5k
    chunk_tvb = tvb_new_subset_length(tvb, offset, total_length);
4933
4934
    /* save it in the sctp_info structure */
4935
36.5k
    if (!encapsulated) {
4936
20.6k
      if (sctp_info.number_of_tvbs < MAXIMUM_NUMBER_OF_TVBS)
4937
20.6k
        sctp_info.tvb[sctp_info.number_of_tvbs++] = chunk_tvb;
4938
0
      else
4939
0
        sctp_info.incomplete = true;
4940
20.6k
    }
4941
36.5k
    if (first_chunk) {
4942
35.6k
      first_chunk = false;
4943
35.6k
      if (enable_association_indexing) {
4944
0
        tmpinfo.assoc_index = -1;
4945
0
        tmpinfo.direction = 1;
4946
0
        copy_address_shallow(&tmpinfo.saddr, &pinfo->src);
4947
0
        copy_address_shallow(&tmpinfo.daddr, &pinfo->dst);
4948
0
        tmpinfo.sport = sctp_info.sport;
4949
0
        tmpinfo.dport = sctp_info.dport;
4950
0
        bool vtag_reflected = false;
4951
        /* Certain chunk types have exceptional Verification Tag handling
4952
         * ( see https://datatracker.ietf.org/doc/html/rfc9260#section-8.5.1 )
4953
         * XXX: Those chunk types shouldn't be bundled with other chunk types
4954
         * (ABORT can be bundled after other control types, but ABORT with the
4955
         * T bit set should not be) and there should be an expert info if so.
4956
         * Should we use the association from the first chunk or the last
4957
         * chunk in such a case?
4958
         */
4959
0
        if (tvb_get_uint8(chunk_tvb, CHUNK_TYPE_OFFSET) == SCTP_ABORT_CHUNK_ID) {
4960
0
          if ((tvb_get_uint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_ABORT_CHUNK_T_BIT) != 0) {
4961
0
            vtag_reflected = true;
4962
0
          }
4963
0
        }
4964
0
        if (tvb_get_uint8(chunk_tvb, CHUNK_TYPE_OFFSET) == SCTP_SHUTDOWN_COMPLETE_CHUNK_ID) {
4965
0
          if ((tvb_get_uint8(chunk_tvb, CHUNK_FLAGS_OFFSET) & SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT) != 0) {
4966
0
            vtag_reflected = true;
4967
0
          }
4968
0
        }
4969
0
        if (vtag_reflected) {
4970
0
          tmpinfo.verification_tag1 = 0;
4971
0
          tmpinfo.verification_tag2 = sctp_info.verification_tag;
4972
0
        }
4973
0
        else {
4974
0
          tmpinfo.verification_tag1 = sctp_info.verification_tag;
4975
0
          tmpinfo.verification_tag2 = 0;
4976
0
        }
4977
0
        if (tvb_get_uint8(chunk_tvb, CHUNK_TYPE_OFFSET) == SCTP_INIT_CHUNK_ID) {
4978
0
          tmpinfo.verification_tag1 = 0;
4979
0
          tmpinfo.verification_tag2 = tvb_get_ntohl(sctp_info.tvb[0], 4);
4980
0
        }
4981
0
        if (tvb_get_uint8(chunk_tvb, CHUNK_TYPE_OFFSET) == SCTP_INIT_ACK_CHUNK_ID) {
4982
0
          tmpinfo.verification_tag2 = tvb_get_ntohl(sctp_info.tvb[0], 4);
4983
0
        }
4984
4985
0
        id_dir = find_assoc_index(&tmpinfo, pinfo);
4986
0
        pi = proto_tree_add_uint(sctp_tree, hf_sctp_assoc_index, tvb, 0 , 0, id_dir.assoc_index);
4987
        /* XXX: Should we set these if encapsulated is true or not? */
4988
0
        sctp_info.assoc_index = id_dir.assoc_index;
4989
0
        sctp_info.direction = id_dir.direction;
4990
4991
35.6k
      } else {
4992
35.6k
          pi = proto_tree_add_uint_format_value(sctp_tree, hf_sctp_assoc_index, tvb, 0 , 0, sctp_info.assoc_index, "disabled (enable in preferences)");
4993
35.6k
      }
4994
4995
35.6k
      proto_item_set_generated(pi);
4996
35.6k
      proto_tree_move_item(sctp_tree, vt, pi);
4997
35.6k
    }
4998
4999
    /* call dissect_sctp_chunk for the actual work */
5000
36.5k
    if (dissect_sctp_chunk(chunk_tvb, pinfo, tree, sctp_tree, ha, !encapsulated) && (tree)) {
5001
410
      proto_item_set_len(sctp_item, offset - last_offset + DATA_CHUNK_HEADER_LENGTH);
5002
410
      sctp_item_length_set = true;
5003
410
      offset += total_length;
5004
410
      last_offset = offset;
5005
410
      if (tvb_reported_length_remaining(tvb, offset) > 0) {
5006
404
        sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, offset, -1, ENC_NA);
5007
404
        sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
5008
404
        sctp_item_length_set = false;
5009
404
      }
5010
36.1k
    } else {
5011
      /* get rid of the dissected chunk */
5012
36.1k
      offset += total_length;
5013
36.1k
    }
5014
36.5k
  }
5015
35.6k
  if (!sctp_item_length_set && (tree)) {
5016
54
    proto_item_set_len(sctp_item, offset - last_offset);
5017
54
  }
5018
35.6k
}
5019
5020
static void
5021
// NOLINTNEXTLINE(misc-no-recursion)
5022
dissect_sctp_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, bool encapsulated)
5023
35.6k
{
5024
35.6k
  uint32_t checksum = 0, calculated_crc32c = 0, calculated_adler32 = 0;
5025
35.6k
  uint16_t source_port, destination_port;
5026
35.6k
  unsigned captured_length, reported_length;
5027
35.6k
  bool crc32c_correct = false, adler32_correct = false;
5028
35.6k
  proto_item *sctp_item, *hidden_item;
5029
35.6k
  proto_tree *sctp_tree;
5030
35.6k
  uint32_t vtag;
5031
35.6k
  sctp_half_assoc_t *ha = NULL;
5032
35.6k
  proto_item *vt = NULL;
5033
5034
35.6k
  captured_length = tvb_captured_length(tvb);
5035
35.6k
  reported_length = tvb_reported_length(tvb);
5036
35.6k
  checksum        = tvb_get_ntohl(tvb, CHECKSUM_OFFSET);
5037
35.6k
  sctp_info.checksum_zero = (checksum == 0);
5038
5039
  /* Only try to checksum the packet if we have all of it */
5040
35.6k
  if ((captured_length == reported_length) &&
5041
35.6k
     (captured_length >= COMMON_HEADER_LENGTH)) {
5042
5043
35.6k
    switch(sctp_checksum) {
5044
35.6k
    case SCTP_CHECKSUM_NONE:
5045
35.6k
      break;
5046
0
    case SCTP_CHECKSUM_ADLER32:
5047
0
      calculated_adler32           = sctp_adler32(tvb, captured_length);
5048
0
      adler32_correct              = (checksum == calculated_adler32);
5049
0
      sctp_info.adler32_calculated = true;
5050
0
      sctp_info.adler32_correct    = adler32_correct;
5051
0
      break;
5052
0
    case SCTP_CHECKSUM_CRC32C:
5053
0
      calculated_crc32c            = sctp_crc32c(tvb, captured_length);
5054
0
      crc32c_correct               = (checksum == calculated_crc32c);
5055
0
      sctp_info.crc32c_calculated  = true;
5056
0
      sctp_info.crc32c_correct     = crc32c_correct;
5057
0
      break;
5058
0
    case SCTP_CHECKSUM_AUTOMATIC:
5059
0
      calculated_adler32           = sctp_adler32(tvb, captured_length);
5060
0
      adler32_correct              = (checksum == calculated_adler32);
5061
0
      calculated_crc32c            = sctp_crc32c(tvb, captured_length);
5062
0
      crc32c_correct               = (checksum == calculated_crc32c);
5063
0
      sctp_info.adler32_calculated = true;
5064
0
      sctp_info.adler32_correct    = adler32_correct;
5065
0
      sctp_info.crc32c_calculated  = true;
5066
0
      sctp_info.crc32c_correct     = crc32c_correct;
5067
0
      break;
5068
35.6k
    }
5069
35.6k
  }
5070
5071
35.6k
  source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
5072
35.6k
  destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
5073
35.6k
  vtag             = tvb_get_ntohl(tvb,VERIFICATION_TAG_OFFSET);
5074
5075
35.6k
  ha = get_half_assoc(pinfo, source_port, destination_port, vtag);
5076
5077
  /* In the interest of speed, if "tree" is NULL, don't do any work not
5078
     necessary to generate protocol tree items. */
5079
35.6k
  if (tree) {
5080
5081
    /* create the sctp protocol tree */
5082
35.6k
    if (show_port_numbers)
5083
35.6k
      sctp_item = proto_tree_add_protocol_format(tree, proto_sctp, tvb, 0, -1,
5084
35.6k
                                                 "Stream Control Transmission Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
5085
35.6k
                                                 sctp_port_to_display(pinfo->pool, source_port), source_port,
5086
35.6k
                                                 sctp_port_to_display(pinfo->pool, destination_port), destination_port);
5087
0
    else
5088
0
      sctp_item = proto_tree_add_item(tree, proto_sctp, tvb, 0, -1, ENC_NA);
5089
5090
35.6k
    sctp_tree = proto_item_add_subtree(sctp_item, ett_sctp);
5091
5092
    /* add the components of the common header to the protocol tree */
5093
35.6k
    proto_tree_add_item(sctp_tree, hf_source_port,      tvb, SOURCE_PORT_OFFSET,      SOURCE_PORT_LENGTH,      ENC_BIG_ENDIAN);
5094
35.6k
    proto_tree_add_item(sctp_tree, hf_destination_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, ENC_BIG_ENDIAN);
5095
35.6k
    vt = proto_tree_add_item(sctp_tree, hf_verification_tag, tvb, VERIFICATION_TAG_OFFSET, VERIFICATION_TAG_LENGTH, ENC_BIG_ENDIAN);
5096
35.6k
    hidden_item = proto_tree_add_item(sctp_tree, hf_port, tvb, SOURCE_PORT_OFFSET,      SOURCE_PORT_LENGTH,      ENC_BIG_ENDIAN);
5097
35.6k
    proto_item_set_hidden(hidden_item);
5098
35.6k
    hidden_item = proto_tree_add_item(sctp_tree, hf_port, tvb, DESTINATION_PORT_OFFSET, DESTINATION_PORT_LENGTH, ENC_BIG_ENDIAN);
5099
35.6k
    proto_item_set_hidden(hidden_item);
5100
35.6k
  } else {
5101
12
    sctp_tree = NULL;
5102
12
    sctp_item = NULL;
5103
12
  }
5104
5105
35.6k
  if (captured_length == reported_length) {
5106
    /* We have the whole packet */
5107
5108
35.6k
    switch(sctp_checksum) {
5109
35.6k
    case SCTP_CHECKSUM_NONE:
5110
35.6k
      proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, 0,
5111
35.6k
                              ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
5112
35.6k
      break;
5113
0
    case SCTP_CHECKSUM_ADLER32:
5114
0
      proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_adler, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_adler32,
5115
0
                              ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
5116
0
      break;
5117
0
    case SCTP_CHECKSUM_CRC32C:
5118
0
      proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_crc32c, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_crc32c,
5119
0
                              ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
5120
0
      break;
5121
0
    case SCTP_CHECKSUM_AUTOMATIC:
5122
0
      if ((adler32_correct) && !(crc32c_correct))
5123
0
        proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_adler, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_adler32,
5124
0
                              ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
5125
0
      else if ((!adler32_correct) && (crc32c_correct))
5126
0
        proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_crc32c, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_crc32c,
5127
0
                              ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
5128
0
      else {
5129
0
        proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_adler, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_adler32,
5130
0
                              ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
5131
0
        proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum_crc32c, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, calculated_crc32c,
5132
0
                              ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
5133
0
      }
5134
0
      break;
5135
35.6k
    }
5136
35.6k
  } else {
5137
    /* We don't have the whole packet so we can't verify the checksum */
5138
14
      proto_tree_add_checksum(sctp_tree, tvb, CHECKSUM_OFFSET, hf_checksum, hf_checksum_status, &ei_sctp_bad_sctp_checksum, pinfo, 0,
5139
14
                              ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
5140
14
  }
5141
5142
  /* add all chunks of the sctp datagram to the protocol tree */
5143
35.6k
  dissect_sctp_chunks(tvb, pinfo, tree, sctp_item, sctp_tree, ha, encapsulated, vt);
5144
5145
35.6k
}
5146
5147
static bool
5148
capture_sctp(const unsigned char *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
5149
0
{
5150
0
  capture_dissector_increment_count(cpinfo, proto_sctp);
5151
0
  return true;
5152
0
}
5153
5154
static int
5155
dissect_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5156
19.9k
{
5157
19.9k
  uint16_t source_port, destination_port;
5158
19.9k
  unsigned   number_of_ppid;
5159
5160
  /* Extract the common header */
5161
19.9k
  source_port      = tvb_get_ntohs(tvb, SOURCE_PORT_OFFSET);
5162
19.9k
  destination_port = tvb_get_ntohs(tvb, DESTINATION_PORT_OFFSET);
5163
5164
  /* update pi structure */
5165
19.9k
  pinfo->ptype    = PT_SCTP;
5166
19.9k
  pinfo->srcport  = source_port;
5167
19.9k
  pinfo->destport = destination_port;
5168
5169
  /* make entry in the Protocol column on summary display */
5170
19.9k
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTP");
5171
5172
  /* Clear entries in Info column on summary display */
5173
19.9k
  col_clear(pinfo->cinfo, COL_INFO);
5174
5175
5176
59.7k
  for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++) {
5177
39.8k
    p_add_proto_data(pinfo->pool, pinfo, proto_sctp, number_of_ppid, GUINT_TO_POINTER(LAST_PPID));
5178
39.8k
  }
5179
5180
  /*  The tvb array in struct _sctp_info is huge: currently 2k pointers.
5181
   *  We know (by the value of 'number_of_tvbs') which of these entries have
5182
   *  been used, so don't memset() the array.  This saves us from zeroing out
5183
   *  8k (4-byte pointers) or 16k (8-byte pointers) of memory every time we
5184
   *  dissect a packet (saving quite a bit of time!).
5185
   */
5186
19.9k
  sctp_info.incomplete = 0;
5187
19.9k
  sctp_info.adler32_calculated = 0;
5188
19.9k
  sctp_info.adler32_correct = 0;
5189
19.9k
  sctp_info.crc32c_calculated = 0;
5190
19.9k
  sctp_info.crc32c_correct = 0;
5191
19.9k
  sctp_info.vtag_reflected = 0;
5192
19.9k
  sctp_info.number_of_tvbs = 0;
5193
19.9k
  sctp_info.verification_tag = tvb_get_ntohl(tvb, VERIFICATION_TAG_OFFSET);
5194
  /* Initialize these to unknown */
5195
19.9k
  sctp_info.assoc_index = -1;
5196
19.9k
  sctp_info.direction = ASSOC_NOT_FOUND;
5197
5198
19.9k
  sctp_info.sport = pinfo->srcport;
5199
19.9k
  sctp_info.dport = pinfo->destport;
5200
19.9k
  set_address(&sctp_info.ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
5201
19.9k
  set_address(&sctp_info.ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
5202
5203
19.9k
  p_add_proto_data(pinfo->pool, pinfo, hf_source_port, pinfo->curr_layer_num, GUINT_TO_POINTER(pinfo->srcport));
5204
19.9k
  p_add_proto_data(pinfo->pool, pinfo, hf_destination_port, pinfo->curr_layer_num, GUINT_TO_POINTER(pinfo->destport));
5205
5206
19.9k
  TRY {
5207
19.9k
    dissect_sctp_packet(tvb, pinfo, tree, false);
5208
19.9k
  }
5209
5210
19.9k
  FINALLY {
5211
19.9k
    if (!pinfo->flags.in_error_pkt && sctp_info.number_of_tvbs > 0)
5212
      /* XXX: If a (only present in an expired Internet-Draft)
5213
       * PKTDROP chunk is present, that shouldn't stop us from
5214
       * tapping the information from the outer encapsulation,
5215
       * but we'd have to be careful about not updating sctp_info
5216
       * with information from the encapsulated packet.
5217
       */
5218
4.44k
      tap_queue_packet(sctp_tap, pinfo, &sctp_info);
5219
19.9k
  }
5220
5221
19.9k
  ENDTRY;
5222
5223
19.9k
  return tvb_captured_length(tvb);
5224
19.9k
}
5225
5226
/* Register the protocol with Wireshark */
5227
void
5228
proto_register_sctp(void)
5229
16
{
5230
5231
  /* Setup list of header fields */
5232
16
  static hf_register_info hf[] = {
5233
16
    { &hf_source_port,                              { "Source port",                                    "sctp.srcport",                                         FT_UINT16,  BASE_PT_SCTP, NULL,                                        0x0,                                NULL, HFILL } },
5234
16
    { &hf_destination_port,                         { "Destination port",                               "sctp.dstport",                                         FT_UINT16,  BASE_PT_SCTP, NULL,                                        0x0,                                NULL, HFILL } },
5235
16
    { &hf_port,                                     { "Port",                                           "sctp.port",                                            FT_UINT16,  BASE_PT_SCTP, NULL,                                        0x0,                                NULL, HFILL } },
5236
16
    { &hf_verification_tag,                         { "Verification tag",                               "sctp.verification_tag",                                FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5237
16
    { &hf_checksum,                                 { "Checksum",                                       "sctp.checksum",                                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5238
16
    { &hf_checksum_adler,                           { "Checksum (Adler)",                               "sctp.checksum",                                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5239
16
    { &hf_checksum_crc32c,                          { "Checksum (CRC32C)",                              "sctp.checksum",                                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5240
16
    { &hf_checksum_status,                          { "Checksum Status",                                "sctp.checksum.status",                                 FT_UINT8,   BASE_NONE, VALS(proto_checksum_vals),                      0x0,                                NULL, HFILL } },
5241
16
    { &hf_chunk,                                    { "Chunk",                                          "sctp.chunk",                                           FT_NONE,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5242
16
    { &hf_chunk_type,                               { "Chunk type",                                     "sctp.chunk_type",                                      FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
5243
16
    { &hf_chunk_flags,                              { "Chunk flags",                                    "sctp.chunk_flags",                                     FT_UINT8,   BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5244
16
    { &hf_chunk_bit_1,                              { "Bit",                                            "sctp.chunk_bit_1",                                     FT_BOOLEAN, 8,         TFS(&sctp_chunk_bit_1_value),                   SCTP_CHUNK_BIT_1,                   NULL, HFILL } },
5245
16
    { &hf_chunk_bit_2,                              { "Bit",                                            "sctp.chunk_bit_2",                                     FT_BOOLEAN, 8,         TFS(&sctp_chunk_bit_2_value),                   SCTP_CHUNK_BIT_2,                   NULL, HFILL } },
5246
16
    { &hf_chunk_length,                             { "Chunk length",                                   "sctp.chunk_length",                                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5247
16
    { &hf_chunk_padding,                            { "Chunk padding",                                  "sctp.chunk_padding",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5248
16
    { &hf_chunk_value,                              { "Chunk value",                                    "sctp.chunk_value",                                     FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5249
16
    { &hf_cookie,                                   { "Cookie",                                         "sctp.cookie",                                          FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5250
16
    { &hf_initiate_tag,                             { "Initiate tag",                                   "sctp.initiate_tag",                                    FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5251
16
    { &hf_init_chunk_initiate_tag,                  { "Initiate tag",                                   "sctp.init_initiate_tag",                               FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5252
16
    { &hf_init_chunk_adv_rec_window_credit,         { "Advertised receiver window credit (a_rwnd)",     "sctp.init_credit",                                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5253
16
    { &hf_init_chunk_number_of_outbound_streams,    { "Number of outbound streams",                     "sctp.init_nr_out_streams",                             FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5254
16
    { &hf_init_chunk_number_of_inbound_streams,     { "Number of inbound streams",                      "sctp.init_nr_in_streams",                              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5255
16
    { &hf_init_chunk_initial_tsn,                   { "Initial TSN",                                    "sctp.init_initial_tsn",                                FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5256
16
    { &hf_initack_chunk_initiate_tag,               { "Initiate tag",                                   "sctp.initack_initiate_tag",                            FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5257
16
    { &hf_initack_chunk_adv_rec_window_credit,      { "Advertised receiver window credit (a_rwnd)",     "sctp.initack_credit",                                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5258
16
    { &hf_initack_chunk_number_of_outbound_streams, { "Number of outbound streams",                     "sctp.initack_nr_out_streams",                          FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5259
16
    { &hf_initack_chunk_number_of_inbound_streams,  { "Number of inbound streams",                      "sctp.initack_nr_in_streams",                           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5260
16
    { &hf_initack_chunk_initial_tsn,                { "Initial TSN",                                    "sctp.initack_initial_tsn",                             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5261
16
    { &hf_data_chunk_tsn,                           { "Transmission sequence number (relative)",        "sctp.data_tsn",                                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5262
16
    { &hf_data_chunk_tsn_raw,                       { "Transmission sequence number (absolute)",        "sctp.data_tsn_raw",                                    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5263
16
    { &hf_data_chunk_stream_id,                     { "Stream identifier",                              "sctp.data_sid",                                        FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5264
16
    { &hf_data_chunk_stream_seq_number,             { "Stream sequence number",                         "sctp.data_ssn",                                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5265
16
    { &hf_data_chunk_payload_proto_id,              { "Payload protocol identifier",                    "sctp.data_payload_proto_id",                           FT_UINT32,  BASE_DEC|BASE_EXT_STRING, &sctpppid_val_ext,               0x0,                                NULL, HFILL } },
5266
16
    { &hf_idata_chunk_reserved,                     { "Reserved",                                       "sctp.data_reserved",                                   FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5267
16
    { &hf_idata_chunk_mid,                          { "Message identifier",                             "sctp.data_mid",                                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5268
16
    { &hf_idata_chunk_fsn,                          { "Fragment sequence number",                       "sctp.data_fsn",                                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5269
16
    { &hf_data_chunk_e_bit,                         { "E-Bit",                                          "sctp.data_e_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_e_bit_value),              SCTP_DATA_CHUNK_E_BIT,              NULL, HFILL } },
5270
16
    { &hf_data_chunk_b_bit,                         { "B-Bit",                                          "sctp.data_b_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_b_bit_value),              SCTP_DATA_CHUNK_B_BIT,              NULL, HFILL } },
5271
16
    { &hf_data_chunk_u_bit,                         { "U-Bit",                                          "sctp.data_u_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_u_bit_value),              SCTP_DATA_CHUNK_U_BIT,              NULL, HFILL } },
5272
16
    { &hf_data_chunk_i_bit,                         { "I-Bit",                                          "sctp.data_i_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_data_chunk_i_bit_value),              SCTP_DATA_CHUNK_I_BIT,              NULL, HFILL } },
5273
16
    { &hf_sack_chunk_ns,                            { "Nonce sum",                                      "sctp.sack_nonce_sum",                                  FT_UINT8,   BASE_DEC,  NULL,                                           SCTP_SACK_CHUNK_NS_BIT,             NULL, HFILL } },
5274
16
    { &hf_sack_chunk_cumulative_tsn_ack,            { "Cumulative TSN ACK (relative)",                  "sctp.sack_cumulative_tsn_ack",                         FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5275
16
    { &hf_sack_chunk_cumulative_tsn_ack_raw,        { "Cumulative TSN ACK (absolute)",                  "sctp.sack_cumulative_tsn_ack_raw",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5276
16
    { &hf_sack_chunk_adv_rec_window_credit,         { "Advertised receiver window credit (a_rwnd)",     "sctp.sack_a_rwnd",                                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5277
16
    { &hf_sack_chunk_number_of_gap_blocks,          { "Number of gap acknowledgement blocks",           "sctp.sack_number_of_gap_blocks",                       FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5278
16
    { &hf_sack_chunk_number_of_dup_tsns,            { "Number of duplicated TSNs",                      "sctp.sack_number_of_duplicated_tsns",                  FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5279
16
    { &hf_sack_chunk_gap_block_start,               { "Start",                                          "sctp.sack_gap_block_start",                            FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5280
16
    { &hf_sack_chunk_gap_block_start_tsn,           { "Start TSN",                                      "sctp.sack_gap_block_start_tsn",                        FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5281
16
    { &hf_sack_chunk_gap_block_end,                 { "End",                                            "sctp.sack_gap_block_end",                              FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5282
16
    { &hf_sack_chunk_gap_block_end_tsn,             { "End TSN",                                        "sctp.sack_gap_block_end_tsn",                          FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5283
16
    { &hf_sack_chunk_number_tsns_gap_acked,         { "Number of TSNs in gap acknowledgement blocks",   "sctp.sack_number_of_tsns_gap_acked",                   FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5284
16
    { &hf_sack_chunk_duplicate_tsn,                 { "Duplicate TSN",                                  "sctp.sack_duplicate_tsn",                              FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5285
16
    { &hf_nr_sack_chunk_ns,                         { "Nonce sum",                                      "sctp.nr_sack_nonce_sum",                               FT_UINT8,   BASE_DEC,  NULL,                                           SCTP_NR_SACK_CHUNK_NS_BIT,          NULL, HFILL } },
5286
16
    { &hf_nr_sack_chunk_cumulative_tsn_ack,         { "Cumulative TSN ACK",                             "sctp.nr_sack_cumulative_tsn_ack",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5287
16
    { &hf_nr_sack_chunk_adv_rec_window_credit,      { "Advertised receiver window credit (a_rwnd)",     "sctp.nr_sack_a_rwnd",                                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5288
16
    { &hf_nr_sack_chunk_number_of_gap_blocks,       { "Number of gap acknowledgement blocks",           "sctp.nr_sack_number_of_gap_blocks",                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5289
16
    { &hf_nr_sack_chunk_number_of_nr_gap_blocks,    { "Number of nr-gap acknowledgement blocks",        "sctp.nr_sack_number_of_nr_gap_blocks",                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5290
16
    { &hf_nr_sack_chunk_number_of_dup_tsns,         { "Number of duplicated TSNs",                      "sctp.nr_sack_number_of_duplicated_tsns",               FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5291
16
    { &hf_nr_sack_chunk_reserved,                   { "Reserved",                                       "sctp.nr_sack_reserved",                                FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5292
16
    { &hf_nr_sack_chunk_gap_block_start,            { "Start",                                          "sctp.nr_sack_gap_block_start",                         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5293
16
    { &hf_nr_sack_chunk_gap_block_start_tsn,        { "Start TSN",                                      "sctp.nr_sack_gap_block_start_tsn",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5294
16
    { &hf_nr_sack_chunk_gap_block_end,              { "End",                                            "sctp.nr_sack_gap_block_end",                           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5295
16
    { &hf_nr_sack_chunk_gap_block_end_tsn,          { "End TSN",                                        "sctp.nr_sack_gap_block_end_tsn",                       FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5296
16
    { &hf_nr_sack_chunk_number_tsns_gap_acked,      { "Number of TSNs in gap acknowledgement blocks",   "sctp.nr_sack_number_of_tsns_gap_acked",                FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5297
16
    { &hf_nr_sack_chunk_nr_gap_block_start,         { "Start",                                          "sctp.nr_sack_nr_gap_block_start",                      FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5298
16
    { &hf_nr_sack_chunk_nr_gap_block_start_tsn,     { "Start TSN",                                      "sctp.nr_sack_nr_gap_block_start_tsn",                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5299
16
    { &hf_nr_sack_chunk_nr_gap_block_end,           { "End",                                            "sctp.nr_sack_nr_gap_block_end",                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5300
16
    { &hf_nr_sack_chunk_nr_gap_block_end_tsn,       { "End TSN",                                        "sctp.nr_sack_nr_gap_block_end_tsn",                    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5301
16
    { &hf_nr_sack_chunk_number_tsns_nr_gap_acked,   { "Number of TSNs in nr-gap acknowledgement blocks","sctp.nr_sack_number_of_tsns_nr_gap_acked",             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5302
16
    { &hf_nr_sack_chunk_duplicate_tsn,              { "Duplicate TSN",                                  "sctp.nr_sack_duplicate_tsn",                           FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5303
16
    { &hf_shutdown_chunk_cumulative_tsn_ack,        { "Cumulative TSN Ack",                             "sctp.shutdown_cumulative_tsn_ack",                     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5304
16
    { &hf_ecne_chunk_lowest_tsn,                    { "Lowest TSN",                                     "sctp.ecne_lowest_tsn",                                 FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5305
16
    { &hf_cwr_chunk_lowest_tsn,                     { "Lowest TSN",                                     "sctp.cwr_lowest_tsn",                                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5306
16
    { &hf_shutdown_complete_chunk_t_bit,            { "T-Bit",                                          "sctp.shutdown_complete_t_bit",                         FT_BOOLEAN, 8,         TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_SHUTDOWN_COMPLETE_CHUNK_T_BIT, NULL, HFILL } },
5307
16
    { &hf_abort_chunk_t_bit,                        { "T-Bit",                                          "sctp.abort_t_bit",                                     FT_BOOLEAN, 8,         TFS(&sctp_shutdown_complete_chunk_t_bit_value), SCTP_ABORT_CHUNK_T_BIT,             NULL, HFILL } },
5308
16
    { &hf_forward_tsn_chunk_tsn,                    { "New cumulative TSN",                             "sctp.forward_tsn_tsn",                                 FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5309
16
    { &hf_forward_tsn_chunk_sid,                    { "Stream identifier",                              "sctp.forward_tsn_sid",                                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5310
16
    { &hf_forward_tsn_chunk_ssn,                    { "Stream sequence number",                         "sctp.forward_tsn_ssn",                                 FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5311
16
    { &hf_i_forward_tsn_chunk_tsn,                  { "New cumulative TSN",                             "sctp.i_forward_tsn_tsn",                               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5312
16
    { &hf_i_forward_tsn_chunk_sid,                  { "Stream identifier",                              "sctp.i_forward_tsn_sid",                               FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5313
16
    { &hf_i_forward_tsn_chunk_flags,                { "Flags",                                          "sctp.i_forward_tsn_flags",                             FT_UINT16,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5314
16
    { &hf_i_forward_tsn_chunk_res,                  { "Reserved",                                       "sctp.i_forward_tsn_res",                               FT_UINT16,  BASE_DEC,  NULL,                                           SCTP_I_FORWARD_TSN_CHUNK_RES_MASK,  NULL, HFILL } },
5315
16
    { &hf_i_forward_tsn_chunk_u_bit,                { "U-Bit",                                          "sctp.i_forward_tsn_u_bit",                             FT_BOOLEAN, 16,        TFS(&sctp_i_forward_tsn_chunk_u_bit_value),     SCTP_I_FORWARD_TSN_CHUNK_U_BIT,     NULL, HFILL } },
5316
16
    { &hf_i_forward_tsn_chunk_mid,                  { "Message identifier",                             "sctp.forward_tsn_mid",                                 FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5317
16
    { &hf_parameter_type,                           { "Parameter type",                                 "sctp.parameter_type",                                  FT_UINT16,  BASE_HEX,  VALS(parameter_identifier_values),              0x0,                                NULL, HFILL } },
5318
16
    { &hf_parameter_length,                         { "Parameter length",                               "sctp.parameter_length",                                FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5319
16
    { &hf_parameter_value,                          { "Parameter value",                                "sctp.parameter_value",                                 FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5320
16
    { &hf_parameter_padding,                        { "Parameter padding",                              "sctp.parameter_padding",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5321
16
    { &hf_parameter_bit_1,                          { "Bit",                                            "sctp.parameter_bit_1",                                 FT_BOOLEAN, 16,        TFS(&sctp_parameter_bit_1_value),               SCTP_PARAMETER_BIT_1,               NULL, HFILL } },
5322
16
    { &hf_parameter_bit_2,                          { "Bit",                                            "sctp.parameter_bit_2",                                 FT_BOOLEAN, 16,        TFS(&sctp_parameter_bit_2_value),               SCTP_PARAMETER_BIT_2,               NULL, HFILL } },
5323
16
    { &hf_ipv4_address,                             { "IP Version 4 address",                           "sctp.parameter_ipv4_address",                          FT_IPv4,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5324
16
    { &hf_ipv6_address,                             { "IP Version 6 address",                           "sctp.parameter_ipv6_address",                          FT_IPv6,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5325
16
    { &hf_heartbeat_info,                           { "Heartbeat information",                          "sctp.parameter_heartbeat_information",                 FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5326
16
    { &hf_state_cookie,                             { "State cookie",                                   "sctp.parameter_state_cookie",                          FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5327
16
    { &hf_cookie_preservative_increment,            { "Suggested Cookie life-span increment (msec)",    "sctp.parameter_cookie_preservative_incr",              FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5328
16
    { &hf_hostname,                                 { "Hostname",                                       "sctp.parameter_hostname",                              FT_STRINGZ,  BASE_NONE, NULL,                                           0x0,                               NULL, HFILL } },
5329
16
    { &hf_supported_address_type,                   { "Supported address type",                         "sctp.parameter_supported_address_type",                FT_UINT16,  BASE_DEC,  VALS(address_types_values),                     0x0,                                NULL, HFILL } },
5330
16
    { &hf_stream_reset_req_seq_nr,                  { "Re-configuration request sequence number",       "sctp.parameter_reconfig_request_sequence_number",      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5331
16
    { &hf_stream_reset_rsp_seq_nr,                  { "Re-configuration response sequence number",      "sctp.parameter_reconfig_response_sequence_number",     FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5332
16
    { &hf_senders_last_assigned_tsn,                { "Senders last assigned TSN",                      "sctp.parameter_senders_last_assigned_tsn",             FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5333
16
    { &hf_senders_next_tsn,                         { "Senders next TSN",                               "sctp.parameter_senders_next_tsn",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5334
16
    { &hf_receivers_next_tsn,                       { "Receivers next TSN",                             "sctp.parameter_receivers_next_tsn",                    FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5335
16
    { &hf_stream_reset_rsp_result,                  { "Result",                                         "sctp.parameter_reconfig_response_result",              FT_UINT32,  BASE_DEC,  VALS(stream_reset_result_values),               0x0,                                NULL, HFILL } },
5336
16
    { &hf_stream_reset_sid,                         { "Stream Identifier",                              "sctp.parameter_reconfig_sid",                          FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5337
16
    { &hf_add_outgoing_streams_number_streams,      { "Number of streams",                              "sctp.parameter_add_outgoing_streams_number",           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5338
16
    { &hf_add_outgoing_streams_reserved,            { "Reserved",                                       "sctp.parameter_add_outgoing_streams_reserved",         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5339
16
    { &hf_add_incoming_streams_number_streams,      { "Number of streams",                              "sctp.parameter_add_incoming_streams_number",           FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5340
16
    { &hf_add_incoming_streams_reserved,            { "Reserved",                                       "sctp.parameter_add_incoming_streams_reserved",         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5341
16
    { &hf_asconf_seq_nr,                            { "Sequence number",                                "sctp.asconf_seq_nr_number",                            FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5342
16
    { &hf_asconf_ack_seq_nr,                        { "Sequence number",                                "sctp.asconf_ack_seq_nr_number",                        FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5343
16
    { &hf_correlation_id,                           { "Correlation_id",                                 "sctp.correlation_id",                                  FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5344
16
    { &hf_adap_indication,                          { "Indication",                                     "sctp.adaptation_layer_indication",                     FT_UINT32,  BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5345
16
    { &hf_zero_checksum_edmid,                      { "Error Detection Method Identifier",              "sctp.edmid",                                           FT_UINT32,  BASE_DEC,  VALS(edmid_values),                             0x0,                                NULL, HFILL } },
5346
16
    { &hf_random_number,                            { "Random number",                                  "sctp.random_number",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5347
16
    { &hf_chunks_to_auth,                           { "Chunk type",                                     "sctp.chunk_type_to_auth",                              FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
5348
16
    { &hf_hmac_id,                                  { "HMAC identifier",                                "sctp.hmac_id",                                         FT_UINT16,  BASE_DEC,  VALS(hmac_id_values),                           0x0,                                NULL, HFILL } },
5349
16
    { &hf_hmac,                                     { "HMAC",                                           "sctp.hmac",                                            FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5350
16
    { &hf_dtls_km_tiebreaker,                       { "DTLS KM tiebreaker identifier",                  "sctp.dtls_km_tiebreaker",                              FT_UINT32,   BASE_DEC, NULL,                                           0x0,                                NULL, HFILL } },
5351
16
    { &hf_dtls_km_flags,                            { "DTLS KM flags",                                  "sctp.dtls_km_flags",                                   FT_UINT8,   BASE_HEX,  NULL,                                           0x0,                                NULL, HFILL } },
5352
16
    { &hf_dtls_km_c_bit,                            { "C-Bit",                                          "sctp.dtls_km_c_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_dtls_km_parameter_c_bit_value),       DTLS_KM_PARAMETER_C_BIT,            NULL, HFILL } },
5353
16
    { &hf_dtls_km_s_bit,                            { "S-Bit",                                          "sctp.dtls_km_s_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_dtls_km_parameter_s_bit_value),       DTLS_KM_PARAMETER_S_BIT,            NULL, HFILL } },
5354
16
    { &hf_dtls_km_r_bit,                            { "R-Bit",                                          "sctp.dtls_km_r_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_dtls_km_parameter_r_bit_value),       DTLS_KM_PARAMETER_R_BIT,            NULL, HFILL } },
5355
16
    { &hf_dtls_km_id,                               { "DTLS KM identifier",                             "sctp.dtls_km_id",                                      FT_UINT8,   BASE_DEC,  VALS(dtls_km_id_values),                        0x0,                                NULL, HFILL } },
5356
16
    { &hf_dtls_chunk_r_bit,                         { "R-Bit",                                          "sctp.dtls_r_bit",                                      FT_BOOLEAN, 8,         TFS(&sctp_dtls_chunk_r_bit_value),              SCTP_DTLS_CHUNK_R_BIT,              NULL, HFILL } },
5357
16
    { &hf_shared_key_id,                            { "Shared key identifier",                          "sctp.shared_key_id",                                   FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5358
16
    { &hf_supported_chunk_type,                     { "Supported chunk type",                           "sctp.supported_chunk_type",                            FT_UINT8,   BASE_DEC,  VALS(chunk_type_values),                        0x0,                                NULL, HFILL } },
5359
16
    { &hf_cause_code,                               { "Cause code",                                     "sctp.cause_code",                                      FT_UINT16,  BASE_HEX,  VALS(cause_code_values),                        0x0,                                NULL, HFILL } },
5360
16
    { &hf_cause_length,                             { "Cause length",                                   "sctp.cause_length",                                    FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5361
16
    { &hf_cause_info,                               { "Cause information",                              "sctp.cause_information",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5362
16
    { &hf_cause_padding,                            { "Cause padding",                                  "sctp.cause_padding",                                   FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5363
16
    { &hf_cause_stream_identifier,                  { "Stream identifier",                              "sctp.cause_stream_identifier",                         FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5364
16
    { &hf_cause_reserved,                           { "Reserved",                                       "sctp.cause_reserved",                                  FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5365
16
    { &hf_cause_number_of_missing_parameters,       { "Number of missing parameters",                   "sctp.cause_nr_of_missing_parameters",                  FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5366
16
    { &hf_cause_missing_parameter_type,             { "Missing parameter type",                         "sctp.cause_missing_parameter_type",                    FT_UINT16,  BASE_HEX,  VALS(parameter_identifier_values),              0x0,                                NULL, HFILL } },
5367
16
    { &hf_cause_measure_of_staleness,               { "Measure of staleness in usec",                   "sctp.cause_measure_of_staleness",                      FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5368
16
    { &hf_cause_tsn,                                { "TSN",                                            "sctp.cause_tsn",                                       FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5369
16
    { &hf_pktdrop_chunk_m_bit,                      { "M-Bit",                                          "sctp.pckdrop_m_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_m_bit_value),                SCTP_PKTDROP_CHUNK_M_BIT,           NULL, HFILL } },
5370
16
    { &hf_pktdrop_chunk_b_bit,                      { "B-Bit",                                          "sctp.pckdrop_b_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_b_bit_value),                SCTP_PKTDROP_CHUNK_B_BIT,           NULL, HFILL } },
5371
16
    { &hf_pktdrop_chunk_t_bit,                      { "T-Bit",                                          "sctp.pckdrop_t_bit",                                   FT_BOOLEAN, 8,         TFS(&sctp_pktdropk_t_bit_value),                SCTP_PKTDROP_CHUNK_T_BIT,           NULL, HFILL } },
5372
16
    { &hf_pktdrop_chunk_bandwidth,                  { "Bandwidth",                                      "sctp.pktdrop_bandwidth",                               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5373
16
    { &hf_pktdrop_chunk_queuesize,                  { "Queuesize",                                      "sctp.pktdrop_queuesize",                               FT_UINT32,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5374
16
    { &hf_pktdrop_chunk_truncated_length,           { "Truncated length",                               "sctp.pktdrop_truncated_length",                        FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5375
16
    { &hf_pktdrop_chunk_reserved,                   { "Reserved",                                       "sctp.pktdrop_reserved",                                FT_UINT16,  BASE_DEC,  NULL,                                           0x0,                                NULL, HFILL } },
5376
16
    { &hf_pktdrop_chunk_data_field,                 { "Data field",                                     "sctp.pktdrop_datafield",                               FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5377
16
    { &hf_pad_chunk_padding_data,                   { "Padding data",                                   "sctp.padding_data",                                    FT_BYTES,   BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5378
5379
16
    { &hf_sctp_fragment,                            { "SCTP Fragment",                                  "sctp.fragment",                                        FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
5380
16
    { &hf_sctp_fragments,                           { "Reassembled SCTP Fragments",                     "sctp.fragments",                                       FT_NONE,    BASE_NONE, NULL,                                           0x0,                                NULL, HFILL } },
5381
16
    { &hf_sctp_reassembled_in,                      { "Reassembled Message in frame",                   "sctp.reassembled_in",                                  FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
5382
16
    { &hf_sctp_duplicate,                           { "Fragment already seen in frame",                 "sctp.duplicate",                                       FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
5383
5384
16
    { &hf_sctp_data_rtt,                            { "The RTT to SACK was",                            "sctp.data_rtt",                                        FT_RELATIVE_TIME, BASE_NONE, NULL,                                     0x0,                                NULL, HFILL } },
5385
16
    { &hf_sctp_sack_rtt,                            { "The RTT since DATA was",                         "sctp.sack_rtt",                                        FT_RELATIVE_TIME, BASE_NONE, NULL,                                     0x0,                                NULL, HFILL } },
5386
16
    { &hf_sctp_rto,                                 { "Retransmitted after",                            "sctp.retransmission_time",                             FT_RELATIVE_TIME, BASE_NONE, NULL,                                     0x0,                                NULL, HFILL } },
5387
16
    { &hf_sctp_retransmission,                      { "This TSN is a retransmission of one in frame",   "sctp.retransmission",                                  FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
5388
16
    { &hf_sctp_retransmitted,                       { "This TSN is retransmitted in frame",             "sctp.retransmitted",                                   FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
5389
16
    { &hf_sctp_retransmitted_count,                 { "TSN was retransmitted this many times",          "sctp.retransmitted_count",                             FT_UINT32, BASE_DEC, NULL,                                             0x0,                                NULL, HFILL } },
5390
16
    { &hf_sctp_acked,                               { "This chunk is acked in frame",                   "sctp.acked",                                           FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
5391
16
    { &hf_sctp_ack_tsn,                             { "Acknowledges TSN",                               "sctp.ack",                                             FT_UINT32, BASE_DEC, NULL,                                             0x0,                                NULL, HFILL } },
5392
16
    { &hf_sctp_ack_frame,                           { "Acknowledges TSN in frame",                      "sctp.ack_frame",                                       FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_ACK),                0x0,                                NULL, HFILL } },
5393
16
    { &hf_sctp_retransmitted_after_ack,             { "Chunk was acked prior to retransmission",        "sctp.retransmitted_after_ack",                         FT_FRAMENUM, BASE_NONE, NULL,                                          0x0,                                NULL, HFILL } },
5394
16
    { &hf_sctp_assoc_index,                         { "Association index",                              "sctp.assoc_index",                                     FT_UINT16, BASE_DEC, NULL,                                             0x0,                                NULL, HFILL } }
5395
5396
16
 };
5397
5398
  /* Setup protocol subtree array */
5399
16
  static int *ett[] = {
5400
16
    &ett_sctp,
5401
16
    &ett_sctp_chunk,
5402
16
    &ett_sctp_chunk_parameter,
5403
16
    &ett_sctp_chunk_cause,
5404
16
    &ett_sctp_chunk_type,
5405
16
    &ett_sctp_data_chunk_flags,
5406
16
    &ett_sctp_sack_chunk_flags,
5407
16
    &ett_sctp_nr_sack_chunk_flags,
5408
16
    &ett_sctp_abort_chunk_flags,
5409
16
    &ett_sctp_shutdown_complete_chunk_flags,
5410
16
    &ett_sctp_pktdrop_chunk_flags,
5411
16
    &ett_sctp_parameter_type,
5412
16
    &ett_sctp_sack_chunk_gap_block,
5413
16
    &ett_sctp_sack_chunk_gap_block_start,
5414
16
    &ett_sctp_sack_chunk_gap_block_end,
5415
16
    &ett_sctp_nr_sack_chunk_gap_block,
5416
16
    &ett_sctp_nr_sack_chunk_gap_block_start,
5417
16
    &ett_sctp_nr_sack_chunk_gap_block_end,
5418
16
    &ett_sctp_nr_sack_chunk_nr_gap_block,
5419
16
    &ett_sctp_nr_sack_chunk_nr_gap_block_start,
5420
16
    &ett_sctp_nr_sack_chunk_nr_gap_block_end,
5421
16
    &ett_sctp_unrecognized_parameter_parameter,
5422
16
    &ett_sctp_i_forward_tsn_chunk_flags,
5423
16
    &ett_sctp_dtls_chunk_flags,
5424
16
    &ett_sctp_fragments,
5425
16
    &ett_sctp_fragment,
5426
16
    &ett_sctp_ack,
5427
16
    &ett_sctp_acked,
5428
16
    &ett_sctp_tsn,
5429
16
    &ett_sctp_tsn_retransmission,
5430
16
    &ett_sctp_tsn_retransmitted_count,
5431
16
    &ett_sctp_tsn_retransmitted,
5432
16
    &ett_sctp_dtls_km_flags
5433
16
  };
5434
5435
16
  static ei_register_info ei[] = {
5436
16
      { &ei_sctp_tsn_retransmitted, { "sctp.retransmission.expert", PI_SEQUENCE, PI_NOTE, "Retransmitted TSN", EXPFILL }},
5437
16
      { &ei_sctp_retransmitted_after_ack, { "sctp.retransmitted_after_ack.expert", PI_SEQUENCE, PI_WARN, "This TSN was acked prior to this retransmission (reneged ack?).", EXPFILL }},
5438
16
      { &ei_sctp_tsn_retransmitted_more_than_twice, { "sctp.retransmission.more_than_twice", PI_SEQUENCE, PI_WARN, "This TSN was retransmitted more than 2 times.", EXPFILL }},
5439
16
      { &ei_sctp_parameter_padding, { "sctp.parameter_padding.expert", PI_MALFORMED, PI_NOTE, "The padding of this final parameter should be the padding of the chunk.", EXPFILL }},
5440
16
      { &ei_sctp_parameter_length, { "sctp.parameter_length.bad", PI_MALFORMED, PI_ERROR, "Parameter length bad", EXPFILL }},
5441
16
      { &ei_sctp_sack_chunk_adv_rec_window_credit, { "sctp.sack_a_rwnd.expert", PI_SEQUENCE, PI_NOTE, "Zero Advertised Receiver Window Credit", EXPFILL }},
5442
16
      { &ei_sctp_sack_chunk_gap_block_malformed, { "sctp.sack_gap_block_malformed", PI_PROTOCOL, PI_ERROR, "Malformed gap block.", EXPFILL }},
5443
16
      { &ei_sctp_sack_chunk_gap_block_out_of_order, { "sctp.sack_gap_block_out_of_order", PI_PROTOCOL, PI_WARN, "Gap blocks not in strict order.", EXPFILL }},
5444
16
      { &ei_sctp_sack_chunk_number_tsns_gap_acked_100, { "sctp.sack_number_of_tsns_gap_acked.100", PI_SEQUENCE, PI_WARN, "More than 100 TSNs were gap-acknowledged in this SACK.", EXPFILL }},
5445
16
      { &ei_sctp_nr_sack_chunk_number_tsns_gap_acked_100, { "sctp.nr_sack_number_of_tsns_gap_acked.100", PI_SEQUENCE, PI_WARN, "More than 100 TSNs were gap-acknowledged in this NR-SACK.", EXPFILL }},
5446
16
      { &ei_sctp_nr_sack_chunk_number_tsns_nr_gap_acked_100, { "sctp.nr_sack_number_of_tsns_nr_gap_acked.100", PI_SEQUENCE, PI_WARN, "More than 100 TSNs were nr-gap-acknowledged in this NR-SACK.", EXPFILL }},
5447
16
      { &ei_sctp_chunk_length_bad, { "sctp.chunk_length.bad", PI_MALFORMED, PI_ERROR, "Chunk length bad", EXPFILL }},
5448
16
      { &ei_sctp_bad_sctp_checksum, { "sctp.checksum_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad SCTP checksum.", EXPFILL }},
5449
16
      { &ei_sctp_illegal_parameter_occurrence, { "sctp.illegal_parameter_occurrence.expert", PI_PROTOCOL, PI_ERROR, "Illegal parameter occurrence.", EXPFILL }},
5450
16
      { &ei_sctp_dtls_km_illegal_number_of_ids, { "sctp.dtls_km_illegal_number_of_ids.expert", PI_PROTOCOL, PI_ERROR, "Illegal number of IDs.", EXPFILL }},
5451
16
  };
5452
5453
16
  static const enum_val_t sctp_checksum_options[] = {
5454
16
    { "none",      "None",        SCTP_CHECKSUM_NONE },
5455
16
    { "adler-32",  "Adler 32",    SCTP_CHECKSUM_ADLER32 },
5456
16
    { "crc-32c",   "CRC 32c",     SCTP_CHECKSUM_CRC32C },
5457
16
    { "automatic", "Automatic",   SCTP_CHECKSUM_AUTOMATIC},
5458
16
    { NULL, NULL, 0 }
5459
16
  };
5460
5461
  /* Decode As handling */
5462
16
  static build_valid_func sctp_da_src_values[1] = {sctp_src_value};
5463
16
  static build_valid_func sctp_da_dst_values[1] = {sctp_dst_value};
5464
16
  static build_valid_func sctp_da_both_values[2] = {sctp_src_value, sctp_dst_value};
5465
16
  static decode_as_value_t sctp_da_port_values[3] = {{sctp_src_prompt, 1, sctp_da_src_values}, {sctp_dst_prompt, 1, sctp_da_dst_values}, {sctp_both_prompt, 2, sctp_da_both_values}};
5466
16
  static decode_as_t sctp_da_port = {"sctp", "sctp.port", 3, 2, sctp_da_port_values, "SCTP", "port(s) as",
5467
16
                                     decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL, NULL, NULL };
5468
5469
16
  static build_valid_func sctp_da_ppi_build_value1[1] = {sctp_ppi_value1};
5470
16
  static build_valid_func sctp_da_ppi_build_value2[1] = {sctp_ppi_value2};
5471
16
  static decode_as_value_t sctp_da_ppi_values[2] = {{sctp_ppi_prompt1, 1, sctp_da_ppi_build_value1}, {sctp_ppi_prompt2, 1, sctp_da_ppi_build_value2}};
5472
16
  static decode_as_t sctp_da_ppi = {"sctp", "sctp.ppi", 2, 0, sctp_da_ppi_values, "SCTP", NULL,
5473
16
                                    decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL, NULL, NULL };
5474
5475
  /* UAT for header fields */
5476
16
  static uat_field_t custom_types_uat_fields[] = {
5477
16
    UAT_FLD_NONE(type_fields, type_id, "Chunk ID", "IANA chunk type ID"),
5478
16
    UAT_FLD_CSTRING(type_fields, type_name, "Type name", "Chunk Type name"),
5479
16
    UAT_FLD_VS(type_fields, type_enable, "Visibility", chunk_enabled, "Hide or show the type in the chunk statistics"),
5480
16
    UAT_END_FIELDS
5481
16
  };
5482
5483
16
  module_t *sctp_module;
5484
16
  expert_module_t* expert_sctp;
5485
16
  uat_t* chunk_types_uat;
5486
5487
16
  chunk_types_uat = uat_new("Chunk types for the statistics dialog",
5488
16
                            sizeof(type_field_t),
5489
16
                            "statistics_chunk_types",
5490
16
                            true,
5491
16
                            &type_fields,
5492
16
                            &num_type_fields,
5493
16
                            0,
5494
16
                            NULL,
5495
16
                            sctp_chunk_type_copy_cb,
5496
16
                            sctp_chunk_type_update_cb,
5497
16
                            sctp_chunk_type_free_cb,
5498
16
                            NULL,
5499
16
                            NULL,
5500
16
                            custom_types_uat_fields
5501
16
);
5502
5503
  /* Register the protocol name and description */
5504
16
  proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp");
5505
16
  sctp_module = prefs_register_protocol(proto_sctp, NULL);
5506
16
  prefs_register_bool_preference(sctp_module, "show_port_numbers_in_tree",
5507
16
                         "Show port numbers in the protocol tree",
5508
16
                         "Show source and destination port numbers in the protocol tree",
5509
16
                         &show_port_numbers);
5510
16
  prefs_register_bool_preference(sctp_module, "relative_tsns", "Relative TSNs",
5511
16
                         "Use relative TSNs instead of absolute ones",
5512
16
                         &show_relative_tsns);
5513
16
  prefs_register_enum_preference(sctp_module, "checksum", "Checksum type",
5514
16
                         "The type of checksum used in SCTP packets",
5515
16
                         &sctp_checksum, sctp_checksum_options, false);
5516
16
  prefs_register_bool_preference(sctp_module, "show_always_control_chunks",
5517
16
                         "Show always control chunks",
5518
16
                         "Show always SCTP control chunks in the Info column",
5519
16
                         &show_always_control_chunks);
5520
16
  prefs_register_bool_preference(sctp_module, "try_heuristic_first",
5521
16
                         "Try heuristic sub-dissectors first",
5522
16
                         "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector registered to a specific port or PPI",
5523
16
                         &try_heuristic_first);
5524
16
  prefs_register_bool_preference(sctp_module, "reassembly",
5525
16
                         "Reassemble fragmented SCTP user messages",
5526
16
                         "Whether fragmented SCTP user messages should be reassembled",
5527
16
                         &use_reassembly);
5528
16
  prefs_register_bool_preference(sctp_module, "tsn_analysis",
5529
16
                         "Enable TSN analysis",
5530
16
                         "Match TSNs and their SACKs",
5531
16
                         &enable_tsn_analysis);
5532
16
  prefs_register_bool_preference(sctp_module, "association_index",
5533
16
                         "Enable Association indexing (Can be CPU intense)",
5534
16
                         "Match verification tags (CPU intense)",
5535
16
                         &enable_association_indexing);
5536
16
  prefs_register_bool_preference(sctp_module, "ulp_dissection",
5537
16
                         "Dissect upper layer protocols",
5538
16
                         "Dissect upper layer protocols",
5539
16
                         &enable_ulp_dissection);
5540
16
  prefs_register_uat_preference(sctp_module, "statistics_chunk_types",
5541
16
                         "Select the chunk types for the statistics dialog",
5542
16
                         "Select the chunk types for the statistics dialog",
5543
16
                         chunk_types_uat);
5544
5545
  /* Required function calls to register the header fields and subtrees used */
5546
16
  proto_register_field_array(proto_sctp, hf, array_length(hf));
5547
16
  proto_register_subtree_array(ett, array_length(ett));
5548
16
  expert_sctp = expert_register_protocol(proto_sctp);
5549
16
  expert_register_field_array(expert_sctp, ei, array_length(ei));
5550
5551
16
  sctp_tap = register_tap("sctp");
5552
16
  exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_3);
5553
  /* subdissector code */
5554
16
  sctp_port_dissector_table = register_dissector_table("sctp.port", "SCTP port", proto_sctp, FT_UINT16, BASE_DEC);
5555
16
  sctp_ppi_dissector_table  = register_dissector_table("sctp.ppi",  "SCTP payload protocol identifier", proto_sctp, FT_UINT32, BASE_HEX);
5556
5557
16
  sctp_handle = register_dissector("sctp", dissect_sctp, proto_sctp);
5558
16
  sctp_heur_subdissector_list = register_heur_dissector_list_with_description("sctp", "SCTP payload", proto_sctp);
5559
5560
16
  register_init_routine(sctp_init);
5561
16
  register_cleanup_routine(sctp_cleanup);
5562
5563
16
  dirs_by_ptvtag = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
5564
16
  dirs_by_ptaddr = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
5565
5566
16
  register_decode_as(&sctp_da_port);
5567
16
  register_decode_as(&sctp_da_ppi);
5568
5569
16
  register_conversation_table(proto_sctp, false, sctp_conversation_packet, sctp_endpoint_packet);
5570
5571
16
  assoc_info_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
5572
16
        sctp_assoc_hash, sctp_assoc_equal);
5573
16
  assoc_info_half_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
5574
16
        sctp_assoc_half_hash, sctp_assoc_half_equal);
5575
5576
16
  register_external_value_string("chunk_type_values", chunk_type_values);
5577
16
}
5578
5579
void
5580
proto_reg_handoff_sctp(void)
5581
16
{
5582
16
  capture_dissector_handle_t sctp_cap_handle;
5583
5584
16
  dissector_add_uint("wtap_encap", WTAP_ENCAP_SCTP, sctp_handle);
5585
16
  dissector_add_uint("ip.proto", IP_PROTO_SCTP, sctp_handle);
5586
16
  dissector_add_uint_with_preference("udp.port", UDP_TUNNELING_PORT, sctp_handle);
5587
16
  dissector_add_uint_with_preference("dtls.port", UDP_TUNNELING_PORT, sctp_handle);
5588
16
  sctp_cap_handle = create_capture_dissector_handle(capture_sctp, proto_sctp);
5589
16
  capture_dissector_add_uint("ip.proto", IP_PROTO_SCTP, sctp_cap_handle);
5590
16
}
5591
5592
/*
5593
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
5594
 *
5595
 * Local variables:
5596
 * c-basic-offset: 2
5597
 * tab-width: 8
5598
 * indent-tabs-mode: nil
5599
 * End:
5600
 *
5601
 * vi: set shiftwidth=2 tabstop=8 expandtab:
5602
 * :indentSize=2:tabSize=8:noTabs=true:
5603
 */