From 6324e3876a82b2b8f3b53823f6738639a7bb7e15 Mon Sep 17 00:00:00 2001 From: Yuxuan Luo Date: Tue, 5 Jul 2022 14:29:04 -0400 Subject: [PATCH 1/5] SCTP: support I-DATA chunk Add support for printing SCTP I-DATA chunk based on RFC8260 section 2.1 Prints payload when vflag leve is greater than 1. --- print-sctp.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/print-sctp.c b/print-sctp.c index cc5bee4ff..99ed5b9c0 100644 --- a/print-sctp.c +++ b/print-sctp.c @@ -111,6 +111,7 @@ #define SCTP_ECN_ECHO 0x0c #define SCTP_ECN_CWR 0x0d #define SCTP_SHUTDOWN_COMPLETE 0x0e +#define SCTP_I_DATA 0x40 #define SCTP_FORWARD_CUM_TSN 0xc0 #define SCTP_RELIABLE_CNTL 0xc1 #define SCTP_RELIABLE_CNTL_ACK 0xc2 @@ -131,6 +132,7 @@ static const struct tok sctp_chunkid_str[] = { { SCTP_ECN_ECHO, "ECN ECHO" }, { SCTP_ECN_CWR, "ECN CWR" }, { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" }, + { SCTP_I_DATA, "I-DATA" }, { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, { SCTP_RELIABLE_CNTL, "REL CTRL" }, { SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" }, @@ -144,6 +146,7 @@ static const struct tok sctp_chunkid_str[] = { #define SCTP_DATA_FIRST_FRAG 0x02 #define SCTP_DATA_NOT_FRAG 0x03 #define SCTP_DATA_UNORDERED 0x04 +#define SCTP_DATA_SACK_IMM 0x08 #define SCTP_ADDRMAX 60 @@ -350,6 +353,14 @@ struct sctpDataPart{ nd_uint32_t payloadtype; }; +struct sctpIData{ + nd_uint32_t TSN; + nd_uint16_t streamId; + nd_uint16_t reserved; + nd_uint32_t MID; + nd_uint32_t PPID_FSN; +}; + struct sctpUnifiedDatagram{ struct sctpChunkDesc uh; struct sctpDataPart dp; @@ -619,6 +630,100 @@ sctp_print(netdissect_options *ndo, break; } } + bp += payload_size; + sctpPacketLengthRemaining -= payload_size; + chunkLengthRemaining -= payload_size; + break; + } + case SCTP_I_DATA : + { + const struct sctpIData *dataHdrPtr; + u_int8_t Bbit = FALSE; + uint8_t chunkFlg; + uint32_t ppid_fsn; + uint16_t payload_size; + + chunkFlg = GET_U_1(chunkDescPtr->chunkFlg); + if ((chunkFlg & SCTP_DATA_SACK_IMM) == SCTP_DATA_SACK_IMM) + ND_PRINT("(I)"); + + if ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) + ND_PRINT("(U)"); + + if ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) { + ND_PRINT("(B)"); + Bbit = TRUE; + } + + if ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) + ND_PRINT("(E)"); + + if (((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) || + ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) || + ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ) + ND_PRINT(" "); + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*dataHdrPtr)); + dataHdrPtr=(const struct sctpIData*)bp; + + ppid_fsn = GET_BE_U_4(dataHdrPtr->PPID_FSN); + ND_PRINT("[TSN: %u] ", GET_BE_U_4(dataHdrPtr->TSN)); + ND_PRINT("[SID: %u] ", GET_BE_U_2(dataHdrPtr->streamId)); + ND_PRINT("[MID: %u] ", GET_BE_U_4(dataHdrPtr->MID)); + if (FALSE == Bbit) { /* print FSN if B bit is NOT set */ + ND_PRINT("[FSN: %u] ", ppid_fsn); + } else { /* print PPID if B bit is set */ + ND_PRINT("[PPID %s] ", tok2str(PayloadProto_idents, "0x%x", ppid_fsn)); + } + + bp += sizeof(*dataHdrPtr); + sctpPacketLengthRemaining -= sizeof(*dataHdrPtr); + chunkLengthRemaining -= sizeof(*dataHdrPtr); + ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, ==, 0) + payload_size = chunkLengthRemaining; + + if (FALSE == Bbit) { + if (ndo->ndo_vflag >= 2) { + ND_PRINT("[Payload"); + if (!ndo->ndo_suppress_default_print) { + ND_PRINT(": "); + ND_DEFAULTPRINT(bp, payload_size); + } + ND_PRINT("]"); + } + + bp += payload_size; + sctpPacketLengthRemaining -= payload_size; + chunkLengthRemaining -= payload_size; + break; /* do not parse ppid and check for CES when B bit is set */ + } + + if (!isforces) { + isforces = (ppid_fsn == SCTP_PPID_FORCES_HP) || + (ppid_fsn == SCTP_PPID_FORCES_MP) || + (ppid_fsn == SCTP_PPID_FORCES_LP); + } + + if (isforces) { + forces_print(ndo, bp, payload_size); + ndo->ndo_protocol = "sctp"; + } else if (ndo->ndo_vflag >= 2) { + switch (ppid_fsn) { + case SCTP_PPID_M3UA: + m3ua_print(ndo, bp, payload_size); + ndo->ndo_protocol = "sctp"; + break; + default: + ND_PRINT("[Payload"); + if (!ndo->ndo_suppress_default_print) { + ND_PRINT(":"); + ND_DEFAULTPRINT(bp, payload_size); + } + ND_PRINT("]"); + break; + } + } + bp += payload_size; sctpPacketLengthRemaining -= payload_size; chunkLengthRemaining -= payload_size; From f4b6fb349daebcc7a4b584d7129ac4fdaaf23ffb Mon Sep 17 00:00:00 2001 From: Yuxuan Luo Date: Tue, 5 Jul 2022 14:29:54 -0400 Subject: [PATCH 2/5] SCTP: Support I-FORWARD chunk Add support for printing I-FORWARD chunk based on RFC8260 section 2.3. Remove REL_CTL (RFC3758) since it is obsolete and it uses the value '0xc2' of I-FORWARD for CNTL_ACK. Print stream IDs and message IDs with `-vv` set. --- print-sctp.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/print-sctp.c b/print-sctp.c index 99ed5b9c0..a1e1e13dc 100644 --- a/print-sctp.c +++ b/print-sctp.c @@ -114,7 +114,7 @@ #define SCTP_I_DATA 0x40 #define SCTP_FORWARD_CUM_TSN 0xc0 #define SCTP_RELIABLE_CNTL 0xc1 -#define SCTP_RELIABLE_CNTL_ACK 0xc2 +#define SCTP_I_FORWARD_TSN 0xc2 static const struct tok sctp_chunkid_str[] = { { SCTP_DATA, "DATA" }, @@ -135,7 +135,7 @@ static const struct tok sctp_chunkid_str[] = { { SCTP_I_DATA, "I-DATA" }, { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, { SCTP_RELIABLE_CNTL, "REL CTRL" }, - { SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" }, + { SCTP_I_FORWARD_TSN, "I-FORWARD-FSN" }, { 0, NULL } }; @@ -148,6 +148,9 @@ static const struct tok sctp_chunkid_str[] = { #define SCTP_DATA_UNORDERED 0x04 #define SCTP_DATA_SACK_IMM 0x08 +/* I-Forward-TSN Specific Flag */ +#define SCTP_I_FORWARD_UNORDERED 0x01 + #define SCTP_ADDRMAX 60 #define CHAN_HP 6704 @@ -361,6 +364,16 @@ struct sctpIData{ nd_uint32_t PPID_FSN; }; +struct sctpIForward{ + nd_uint32_t new_cum_TSN; +}; + +struct sctpIForwardEntry{ + nd_uint16_t streamId; + nd_uint16_t flag; + nd_uint32_t MID; +}; + struct sctpUnifiedDatagram{ struct sctpChunkDesc uh; struct sctpDataPart dp; @@ -729,6 +742,40 @@ sctp_print(netdissect_options *ndo, chunkLengthRemaining -= payload_size; break; } + case SCTP_I_FORWARD_TSN: + { + const struct sctpIForward *dataHdrPtr; + const struct sctpIForwardEntry *entry; + const size_t entry_len = sizeof(struct sctpIForwardEntry); + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*dataHdrPtr)); + dataHdrPtr=(const struct sctpIForward*)bp; + ND_PRINT("[TSN: %u] ", GET_BE_U_4(dataHdrPtr->new_cum_TSN)); + + bp += sizeof(*dataHdrPtr); + sctpPacketLengthRemaining -= sizeof(*dataHdrPtr); + chunkLengthRemaining -= sizeof(*dataHdrPtr); + + if (ndo->ndo_vflag >= 2) { + while (entry_len <= chunkLengthRemaining) { + entry = (const struct sctpIForwardEntry*)bp; + + ND_PRINT("[SID: %u] ", GET_BE_U_2(entry->streamId)); + if ((GET_BE_U_2(entry->flag) & SCTP_I_FORWARD_UNORDERED)) + ND_PRINT("(U)"); /* if U bit is set */ + ND_PRINT("[MID: %u] ", GET_BE_U_4(entry->MID)); + + chunkLengthRemaining -= entry_len; + sctpPacketLengthRemaining -= entry_len; + bp += entry_len; + } + } + + bp += chunkLengthRemaining; + sctpPacketLengthRemaining -= chunkLengthRemaining; + chunkLengthRemaining = 0; + break; + } case SCTP_INITIATION : { const struct sctpInitiation *init; From 5817b44eafaf86ac666c44300edf53f490978103 Mon Sep 17 00:00:00 2001 From: Yuxuan Luo Date: Tue, 5 Jul 2022 14:31:49 -0400 Subject: [PATCH 3/5] SCTP: Support RE-CONFIG chunk Add support for printing RE-CONFIG chunk based on RFC6525 section3.1. Prints all optional parameters when `-vv` is set. Example: [RE-CONFIG] [OUT SSN RESET: REQ SEQ:, RES SEQ:, Last TSN:, SID 0 1] --- print-sctp.c | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/print-sctp.c b/print-sctp.c index a1e1e13dc..0f7e7c1f1 100644 --- a/print-sctp.c +++ b/print-sctp.c @@ -112,6 +112,7 @@ #define SCTP_ECN_CWR 0x0d #define SCTP_SHUTDOWN_COMPLETE 0x0e #define SCTP_I_DATA 0x40 +#define SCTP_RE_CONFIG 0x82 #define SCTP_FORWARD_CUM_TSN 0xc0 #define SCTP_RELIABLE_CNTL 0xc1 #define SCTP_I_FORWARD_TSN 0xc2 @@ -133,6 +134,7 @@ static const struct tok sctp_chunkid_str[] = { { SCTP_ECN_CWR, "ECN CWR" }, { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" }, { SCTP_I_DATA, "I-DATA" }, + { SCTP_RE_CONFIG, "RE-CONFIG" }, { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, { SCTP_RELIABLE_CNTL, "REL CTRL" }, { SCTP_I_FORWARD_TSN, "I-FORWARD-FSN" }, @@ -151,6 +153,14 @@ static const struct tok sctp_chunkid_str[] = { /* I-Forward-TSN Specific Flag */ #define SCTP_I_FORWARD_UNORDERED 0x01 +/* RE-CONFIG Parameters */ +#define OUT_SSN_RESET 13 +#define IN_SSN_RESET 14 +#define SSN_TSN_RESET 15 +#define RE_CONFIG_RES 16 +#define ADD_OUT_STREAM_REQ 17 +#define ADD_IN_STREAM_REQ 18 + #define SCTP_ADDRMAX 60 #define CHAN_HP 6704 @@ -374,6 +384,33 @@ struct sctpIForwardEntry{ nd_uint32_t MID; }; +/* RE-CONFIG Parameters */ +struct sctpReConfigHdr{ + nd_uint16_t param_type; + nd_uint16_t param_len; +}; + +struct outGoingSSNReset{ + nd_uint32_t re_config_req; + nd_uint32_t re_config_res; + nd_uint32_t last_assigned_TSN; +}; + +struct inGoingSSNReset{ + nd_uint32_t re_config_req; +}; + +struct reConfigRes{ + nd_uint32_t res_seq_num; + nd_uint32_t result; +}; + +struct addStreamReq{ + nd_uint32_t res_seq_num; + nd_uint16_t num_new_stream; + nd_uint16_t reserved; +}; + struct sctpUnifiedDatagram{ struct sctpChunkDesc uh; struct sctpDataPart dp; @@ -390,6 +427,27 @@ struct sctpCWR{ nd_uint32_t TSN_reduced_at; }; +/* RE-CONFIG Parameters */ +static const struct tok RE_CONFIG_parameters[] = { + { OUT_SSN_RESET, "OUT SSN RESET" }, + { IN_SSN_RESET, "IN SSN RESET" }, + { SSN_TSN_RESET, "SSN/TSN Reset" }, + { RE_CONFIG_RES, "RESP" }, + { ADD_OUT_STREAM_REQ, "ADD OUT STREAM"}, + { ADD_IN_STREAM_REQ, "ADD IN STREAM" }, + { 0, NULL } +}; + +static const struct tok results[] = { + { 0, "Success - Nothing to do" }, + { 1, "Success - Performed" }, + { 2, "Denied" }, + { 3, "Error - Wrong SSN" }, + { 4, "Error - Request already in progress" }, + { 5, "Error - Bad Sequence Number" }, + { 6, "In progress" }, +}; + static const struct tok ForCES_channels[] = { { CHAN_HP, "ForCES HP" }, { CHAN_MP, "ForCES MP" }, @@ -869,6 +927,194 @@ sctp_print(netdissect_options *ndo, ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, GET_BE_U_4(dupTSN)); } + break; + } + case SCTP_RE_CONFIG: + { + const struct sctpReConfigHdr *param; + uint16_t param_len, type; + uint8_t padding_len; + + sctpPacketLengthRemaining -= chunkLengthRemaining; + + while (0 != chunkLengthRemaining) { + /* it's a padding if the remaining length is less than 4 */ + if (sizeof(uint32_t) >= chunkLengthRemaining) { + chunkLengthRemaining = 0; + break; + } + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*param)); + param = (const struct sctpReConfigHdr*)bp; + param_len = GET_BE_U_2(param->param_len); + type = GET_BE_U_2(param->param_type); + padding_len = param_len % 4; + + ND_PRINT("[%s", tok2str(RE_CONFIG_parameters, NULL, type)); + + param_len -= sizeof(*param); + chunkLengthRemaining -= sizeof(*param); + bp += sizeof(*param); + if (ndo->ndo_vflag < 2) { /* if verbose level < 2, stop and skip */ + ND_PRINT("]"); + + ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_len); + bp += param_len; + chunkLengthRemaining -= param_len; + /* it's a parameter padding if there are more parameters in the remaining length */ + if (chunkLengthRemaining > 4) + bp += padding_len; + + continue; + } + + switch (type) { + case OUT_SSN_RESET: + { + uint16_t stream_num = 0; + const struct outGoingSSNReset *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct outGoingSSNReset*) bp; + ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->re_config_req)); + ND_PRINT("RES SEQ: %u, ", GET_BE_U_4(content->re_config_res)); + ND_PRINT("Last TSN: %u, ", GET_BE_U_4(content->last_assigned_TSN)); + + bp += sizeof(*content); + param_len -= sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + ND_PRINT("SID"); + while (0 != param_len) { + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(stream_num)); + stream_num = GET_BE_U_2(bp); + ND_PRINT(" %u", stream_num); + + bp += sizeof(stream_num); + param_len -= sizeof(stream_num); + chunkLengthRemaining -= sizeof(stream_num); + } + ND_PRINT("]"); + + break; + } + case IN_SSN_RESET: + { + uint16_t stream_num = 0; + const struct inGoingSSNReset *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct inGoingSSNReset*) bp; + ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->re_config_req)); + + bp += sizeof(*content); + param_len -= sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + ND_PRINT("SID"); + while (0 != param_len) { + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(stream_num)); + stream_num = GET_BE_U_2(bp); + ND_PRINT(" %u", stream_num); + + bp += sizeof(stream_num); + param_len -= sizeof(stream_num); + chunkLengthRemaining -= sizeof(stream_num); + } + ND_PRINT("]"); + + break; + } + case SSN_TSN_RESET: + { + const struct inGoingSSNReset *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct inGoingSSNReset*) bp; + ND_PRINT(": REQ SEQ: %u]", GET_BE_U_4(content->re_config_req)); + + bp += sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + break; + } + case RE_CONFIG_RES: + { + uint32_t optional = 0; + const size_t optional_size = sizeof(optional); + const struct reConfigRes *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct reConfigRes*) bp; + ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->res_seq_num)); + ND_PRINT("REQ: %s", tok2str(results, NULL, GET_BE_U_4(content->result))); + + bp += sizeof(*content); + param_len -= sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + if (0 == param_len) { + ND_PRINT("]"); + break; + } + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, optional_size); + optional = GET_BE_U_4(bp); + ND_PRINT(", Sender's TSN: %u", optional); + + bp += optional_size; + param_len -= optional_size; + chunkLengthRemaining -= optional_size; + + if (0 == param_len) { + ND_PRINT("]"); + break; + } + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, optional_size); + optional = GET_BE_U_4(bp); + ND_PRINT(", Receiver's Next TSN: %u] ", optional); + + bp += optional_size; + param_len -= optional_size; + chunkLengthRemaining -= optional_size; + + break; + } + case ADD_OUT_STREAM_REQ: + case ADD_IN_STREAM_REQ: + { + const struct addStreamReq *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct addStreamReq*) bp; + ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->res_seq_num)); + ND_PRINT("No. of new streams: %u] ", GET_BE_U_2(content->num_new_stream)); + + bp += sizeof(*content); + param_len -= sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + break; + } + default: + { + bp += chunkLengthRemaining; + chunkLengthRemaining = 0; + break; + } + } + + /* it's a parameter padding if there are more parameters in the remaining length */ + if (chunkLengthRemaining > 4) + bp += padding_len; + } + break; } default : From 943f5f3db067ca518792ec750275c675f54a21f1 Mon Sep 17 00:00:00 2001 From: Yuxuan Luo Date: Tue, 5 Jul 2022 14:34:15 -0400 Subject: [PATCH 4/5] SCTP: Support ASCONF/-ACK chunk Add support for printing ASCONF and ASCONF-ACK chunk based on RFC5061. Remove REL_CNTL(0xc1) because it's obsolete and conflicts with ASCONF. Prints all ASCONF parameters with `-vv` set. `-vv` Example: [ASCONF] [SEQ: .., ADDR: 192...] [DEL ADDR: C-ID: 0, ADDR: 192...] [ASCONF-ACK] [SEQ: 4161214189] `-v` Example: [ASCONF] [SEQ: .., ADDR: 192...] [DEL ADDR] --- print-sctp.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 217 insertions(+), 2 deletions(-) diff --git a/print-sctp.c b/print-sctp.c index 0f7e7c1f1..f861deb98 100644 --- a/print-sctp.c +++ b/print-sctp.c @@ -112,9 +112,10 @@ #define SCTP_ECN_CWR 0x0d #define SCTP_SHUTDOWN_COMPLETE 0x0e #define SCTP_I_DATA 0x40 +#define SCTP_ASCONF_ACK 0x80 #define SCTP_RE_CONFIG 0x82 #define SCTP_FORWARD_CUM_TSN 0xc0 -#define SCTP_RELIABLE_CNTL 0xc1 +#define SCTP_ASCONF 0xc1 #define SCTP_I_FORWARD_TSN 0xc2 static const struct tok sctp_chunkid_str[] = { @@ -136,7 +137,8 @@ static const struct tok sctp_chunkid_str[] = { { SCTP_I_DATA, "I-DATA" }, { SCTP_RE_CONFIG, "RE-CONFIG" }, { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, - { SCTP_RELIABLE_CNTL, "REL CTRL" }, + { SCTP_ASCONF, "ASCONF" }, + { SCTP_ASCONF_ACK, "ASCONF-ACK" }, { SCTP_I_FORWARD_TSN, "I-FORWARD-FSN" }, { 0, NULL } }; @@ -163,6 +165,18 @@ static const struct tok sctp_chunkid_str[] = { #define SCTP_ADDRMAX 60 +/* ASCONF Parameters*/ +/* - used in INIT/ACK chunk */ +#define SET_PRI_ADDR 0xC004 +#define ADAPT_LAYER_INDIC 0xC006 +#define SUPPORTED_EXT 0x8008 +/* - used in ASCONF param */ +#define ADD_IP_ADDR 0xC001 +#define DEL_IP_ADDR 0xC002 +/* - used in ASCONF response */ +#define ERR_CAUSE_INDIC 0xC003 +#define SUCCESS_INDIC 0xC005 + #define CHAN_HP 6704 #define CHAN_MP 6705 #define CHAN_LP 6706 @@ -411,6 +425,35 @@ struct addStreamReq{ nd_uint16_t reserved; }; +/* ASCONF parameters */ +struct sctpAsconfParam{ + nd_uint16_t type; + nd_uint16_t length; + nd_uint32_t CID; + union { + struct sctpV4IpAddress ipv4; + struct sctpV6IpAddress ipv6; + } addr; +}; + +struct sctpASCONF{ + nd_uint32_t seq_num; + union { + struct sctpV4IpAddress ipv4; + struct sctpV6IpAddress ipv6; + } addr; +}; + +struct sctpASCONF_ACK{ + nd_uint32_t seq_num; +}; + +struct sctpErrParam{ + nd_uint8_t type; + nd_uint8_t flags; + nd_uint16_t length; +}; + struct sctpUnifiedDatagram{ struct sctpChunkDesc uh; struct sctpDataPart dp; @@ -448,6 +491,34 @@ static const struct tok results[] = { { 6, "In progress" }, }; +/* ASCONF tokens */ +static const struct tok asconfigParams[] = { + { SET_PRI_ADDR, "SET PRIM ADDR" }, + { ADAPT_LAYER_INDIC, "Adaptation Layer Indication" }, + { SUPPORTED_EXT, "Supported Extensions" }, + { ADD_IP_ADDR, "ADD ADDR" }, + { DEL_IP_ADDR, "DEL ADDR" }, + { ERR_CAUSE_INDIC, "ERR" }, + { SUCCESS_INDIC, "SUCCESS" }, +}; + +static const struct tok causeCode[] = { + { 1, "Invalid Stream Identifier" }, + { 2, "Missing Mandatory Parameter" }, + { 3, "Stale Cookie Error" }, + { 4, "Out of Resource" }, + { 5, "Unresolvable Address" }, + { 6, "Unrecognized Chunk Type" }, + { 7, "Invalid Mandatory Parameter" }, + { 8, "Unrecognized Parameters" }, + { 9, "No User Data" }, + { 10, "Cookie Received While Shutting Down" }, + { 11, "Restart of an Association with New Addresses" }, + { 12, "User Initiated Abort" }, + { 13, "Protocol Violation" }, + { 0, NULL } +}; + static const struct tok ForCES_channels[] = { { CHAN_HP, "ForCES HP" }, { CHAN_MP, "ForCES MP" }, @@ -1115,6 +1186,150 @@ sctp_print(netdissect_options *ndo, bp += padding_len; } + break; + } + case SCTP_ASCONF: + { + const struct sctpASCONF *content; + const struct sctpAsconfParam *param; + size_t length; + uint16_t param_len; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + content = (const struct sctpASCONF*) bp; + ND_PRINT("[SEQ: %u, ", GET_BE_U_4(content->seq_num)); + + if (GET_BE_U_2(content->addr.ipv4.p.paramType) == 5) { /* IPv4 */ + length = sizeof(nd_uint32_t) + sizeof(struct sctpV4IpAddress); + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, length); + ND_PRINT("ADDR: %s] ", GET_IPADDR_STRING(content->addr.ipv4.ipAddress)); + } else if (GET_BE_U_2(content->addr.ipv6.p.paramType) == 6) { /* IPv6 */ + length = sizeof(nd_uint32_t) + sizeof(struct sctpV6IpAddress); + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, length); + ND_PRINT("ADDR: %s] ", GET_IP6ADDR_STRING(content->addr.ipv4.ipAddress)); + } else { + length = sizeof(nd_uint32_t) + GET_BE_U_2(content->addr.ipv4.p.paramLength); + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, length); + ND_PRINT("ADDR: bogus address type]"); + } + bp += length; + chunkLengthRemaining -= length; + sctpPacketLengthRemaining -= length; + + while (0 != chunkLengthRemaining) { + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(uint32_t)); /* ensure param_len can be extracted */ + param = (const struct sctpAsconfParam*) bp; + param_len = GET_BE_U_2(param->length); + + ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_len); + bp += param_len; + chunkLengthRemaining -= param_len; + sctpPacketLengthRemaining -= param_len; + + ND_PRINT("[%s", tok2str(asconfigParams, NULL, GET_BE_U_2(param->type))); + + if (ndo->ndo_vflag >= 2) { + ND_PRINT(": C-ID: %u, ", GET_BE_U_4(param->CID)); + if (GET_BE_U_2(param->addr.ipv4.p.paramType) == 5) { /* IPv4 */ + length = sizeof(nd_uint32_t) + sizeof(struct sctpV4IpAddress); + ND_ICHECKMSG_ZU("param length", param_len, <, length); + ND_PRINT("ADDR: %s] ", GET_IPADDR_STRING(param->addr.ipv4.ipAddress)); + } else if (GET_BE_U_2(param->addr.ipv4.p.paramType) == 6) { /* IPv6 */ + length = sizeof(nd_uint32_t) + sizeof(struct sctpV6IpAddress); + ND_ICHECKMSG_ZU("param length", param_len, <, length); + ND_PRINT("ADDR: %s] ", GET_IP6ADDR_STRING(param->addr.ipv6.ipAddress)); + } else { + ND_PRINT("ADDR: bogus address type]"); + } + } else { + ND_PRINT("]"); + } + } + break; + } + case SCTP_ASCONF_ACK: + { + const struct sctpASCONF_ACK *content; + const struct sctpAsconfParam *header; + uint16_t param_len; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + content = (const struct sctpASCONF_ACK*) bp; + ND_PRINT("[SEQ: %u] ", GET_BE_U_4(content->seq_num)); + + bp += sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + sctpPacketLengthRemaining -= sizeof(*content); + + while (0 != chunkLengthRemaining) { + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*header)); + header = (const struct sctpAsconfParam*) bp; + param_len = GET_BE_U_2(header->length); + ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_len); + + ND_PRINT("[%s", tok2str(asconfigParams, NULL, GET_BE_U_2(header->type))); + + /* print payload only when vflag >= 2 */ + if (ndo->ndo_vflag < 2) { + ND_PRINT("] "); + bp += param_len; + chunkLengthRemaining -= param_len; + sctpPacketLengthRemaining -= param_len; + continue; + } + + bp += sizeof(*header); + chunkLengthRemaining -= sizeof(*header); + sctpPacketLengthRemaining -= sizeof(*header); + + switch (GET_BE_U_2(header->type)) { + case ERR_CAUSE_INDIC: + { + const struct sctpErrParam *errHdr; + const struct sctpOpErrorCause *err_cause; + uint16_t param_remaining; + uint16_t cause_len; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(struct sctpErrParam)); + errHdr = (const struct sctpErrParam*) bp; + param_remaining = GET_BE_U_2(errHdr->length); + ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_remaining); + + bp += sizeof(*errHdr); + chunkLengthRemaining -= sizeof(*errHdr); + sctpPacketLengthRemaining -= sizeof(*errHdr); + + ND_PRINT(": "); + while (0 != param_remaining) { + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*err_cause)); + err_cause = (const struct sctpOpErrorCause*) bp; + ND_PRINT(" %s, ", tok2str(causeCode, NULL, GET_BE_U_2(err_cause->cause))); + + cause_len = GET_BE_U_2(err_cause->causeLen); + ND_ICHECKMSG_ZU("cause length", cause_len, <, sizeof(*err_cause)); + ND_ICHECKMSG_U("param length", param_remaining, <, cause_len); + bp += cause_len; + param_remaining -= cause_len; + chunkLengthRemaining -= cause_len; + sctpPacketLengthRemaining -= cause_len; + } + ND_PRINT("] "); + break; + } + case SUCCESS_INDIC: + { + ND_PRINT(": C-ID %u] ", GET_BE_U_4(bp)); + bp += sizeof(uint32_t); + break; + } + default: + { + ND_PRINT("Unknown parameter] "); + bp += (param_len - sizeof(*header)); + break; + } + } + } break; } default : From cd471b8eccf0a46e17c72d286521813a20518c13 Mon Sep 17 00:00:00 2001 From: Yuxuan Luo Date: Tue, 5 Jul 2022 14:35:40 -0400 Subject: [PATCH 5/5] SCTP: Support PAD chunk Add support for printing PAD chunk based on RFC4820 section3. Example: [PAD] --- print-sctp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/print-sctp.c b/print-sctp.c index f861deb98..01988cc35 100644 --- a/print-sctp.c +++ b/print-sctp.c @@ -114,6 +114,7 @@ #define SCTP_I_DATA 0x40 #define SCTP_ASCONF_ACK 0x80 #define SCTP_RE_CONFIG 0x82 +#define SCTP_PAD_CHUNK 0x84 #define SCTP_FORWARD_CUM_TSN 0xc0 #define SCTP_ASCONF 0xc1 #define SCTP_I_FORWARD_TSN 0xc2 @@ -136,6 +137,7 @@ static const struct tok sctp_chunkid_str[] = { { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" }, { SCTP_I_DATA, "I-DATA" }, { SCTP_RE_CONFIG, "RE-CONFIG" }, + { SCTP_PAD_CHUNK, "PAD" }, { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, { SCTP_ASCONF, "ASCONF" }, { SCTP_ASCONF_ACK, "ASCONF-ACK" },