Skip to content

Commit

Permalink
SCTP: Support RE-CONFIG chunk
Browse files Browse the repository at this point in the history
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]
  • Loading branch information
Yuxuan Luo authored and CacheUseOnly committed May 13, 2023
1 parent eeea0e1 commit fb0b574
Show file tree
Hide file tree
Showing 5 changed files with 344 additions and 0 deletions.
246 changes: 246 additions & 0 deletions print-sctp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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" },
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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" },
Expand Down Expand Up @@ -868,6 +926,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 :
Expand Down
32 changes: 32 additions & 0 deletions tests/sctp-re-config-v.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
1 15:56:38.595332 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [INIT] [init tag: 2670115933] [rwnd: 106496] [OS: 10] [MIS: 65535] [init TSN: 1593007960]
2 15:56:38.595368 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 348)
192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [INIT ACK] [init tag: 2082750980] [rwnd: 106496] [OS: 5] [MIS: 5] [init TSN: 2238062072]
3 15:56:38.595379 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 296)
192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [COOKIE ECHO]
4 15:56:38.595392 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 36)
192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [COOKIE ACK]
5 15:56:38.595416 IP (tos 0x2,ECT(0), ttl 64, id 1, offset 0, flags [DF], proto SCTP (132), length 76)
192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [RE-CONFIG] [OUT SSN RESET][IN SSN RESET]
6 15:56:38.595421 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 76)
192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [RE-CONFIG] [RESP], (2) [RE-CONFIG] [OUT SSN RESET]
7 15:56:38.595426 IP (tos 0x2,ECT(0), ttl 64, id 2, offset 0, flags [DF], proto SCTP (132), length 48)
192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [RE-CONFIG] [RESP]
8 15:56:38.595434 IP (tos 0x2,ECT(0), ttl 64, id 3, offset 0, flags [DF], proto SCTP (132), length 60)
192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [DATA] (B)(E) [TSN: 1593007960] [SID: 0] [SSEQ 0] [PPID 0x0]
9 15:56:38.595440 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 48)
192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [SACK] [cum ack 1593007960] [a_rwnd 106486] [#gap acks 0] [#dup tsns 0]
10 15:56:40.359603 IP (tos 0x2,ECT(0), ttl 64, id 4, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.1.58384 > 192.168.5.4.36297: sctp (1) [HB REQ]
11 15:56:40.359631 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [HB ACK]
12 15:56:42.055670 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.2.36297 > 192.168.5.3.58384: sctp (1) [HB REQ]
13 15:56:42.055866 IP (tos 0x2,ECT(0), ttl 64, id 5, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [HB ACK]
14 15:56:51.811692 IP (tos 0x2,ECT(0), ttl 64, id 6, offset 0, flags [DF], proto SCTP (132), length 40)
192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [SHUTDOWN]
15 15:56:51.811707 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 36)
192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [SHUTDOWN ACK]
16 15:56:51.811712 IP (tos 0x2,ECT(0), ttl 64, id 7, offset 0, flags [DF], proto SCTP (132), length 36)
192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [SHUTDOWN COMPLETE]
50 changes: 50 additions & 0 deletions tests/sctp-re-config-vv.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
1 15:56:38.595332 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.1.58384 > 192.168.5.2.36297: sctp
1) [INIT] [init tag: 2670115933] [rwnd: 106496] [OS: 10] [MIS: 65535] [init TSN: 1593007960]
2 15:56:38.595368 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 348)
192.168.5.2.36297 > 192.168.5.1.58384: sctp
1) [INIT ACK] [init tag: 2082750980] [rwnd: 106496] [OS: 5] [MIS: 5] [init TSN: 2238062072]
3 15:56:38.595379 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 296)
192.168.5.1.58384 > 192.168.5.2.36297: sctp
1) [COOKIE ECHO]
4 15:56:38.595392 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 36)
192.168.5.2.36297 > 192.168.5.1.58384: sctp
1) [COOKIE ACK]
5 15:56:38.595416 IP (tos 0x2,ECT(0), ttl 64, id 1, offset 0, flags [DF], proto SCTP (132), length 76)
192.168.5.1.58384 > 192.168.5.2.36297: sctp
1) [RE-CONFIG] [OUT SSN RESET: REQ SEQ: 1593007960, RES SEQ: 2238062071, Last TSN: 1593007959, SID 0 1 2 3][IN SSN RESET: REQ SEQ: 1593007961, SID 0 1 2 3]
6 15:56:38.595421 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 76)
192.168.5.2.36297 > 192.168.5.1.58384: sctp
1) [RE-CONFIG] [RESP: REQ SEQ: 1593007960, REQ: Success - Performed]
2) [RE-CONFIG] [OUT SSN RESET: REQ SEQ: 2238062072, RES SEQ: 1593007961, Last TSN: 2238062071, SID 0 1 2 3]
7 15:56:38.595426 IP (tos 0x2,ECT(0), ttl 64, id 2, offset 0, flags [DF], proto SCTP (132), length 48)
192.168.5.1.58384 > 192.168.5.2.36297: sctp
1) [RE-CONFIG] [RESP: REQ SEQ: 2238062072, REQ: Success - Performed]
8 15:56:38.595434 IP (tos 0x2,ECT(0), ttl 64, id 3, offset 0, flags [DF], proto SCTP (132), length 60)
192.168.5.1.58384 > 192.168.5.2.36297: sctp
1) [DATA] (B)(E) [TSN: 1593007960] [SID: 0] [SSEQ 0] [PPID 0x0] [Payload:
0x0000: 7265 7365 7420 492f 4f00 reset.I/O.]
9 15:56:38.595440 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 48)
192.168.5.2.36297 > 192.168.5.1.58384: sctp
1) [SACK] [cum ack 1593007960] [a_rwnd 106486] [#gap acks 0] [#dup tsns 0]
10 15:56:40.359603 IP (tos 0x2,ECT(0), ttl 64, id 4, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.1.58384 > 192.168.5.4.36297: sctp
1) [HB REQ]
11 15:56:40.359631 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.2.36297 > 192.168.5.1.58384: sctp
1) [HB ACK]
12 15:56:42.055670 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.2.36297 > 192.168.5.3.58384: sctp
1) [HB REQ]
13 15:56:42.055866 IP (tos 0x2,ECT(0), ttl 64, id 5, offset 0, flags [DF], proto SCTP (132), length 92)
192.168.5.1.58384 > 192.168.5.2.36297: sctp
1) [HB ACK]
14 15:56:51.811692 IP (tos 0x2,ECT(0), ttl 64, id 6, offset 0, flags [DF], proto SCTP (132), length 40)
192.168.5.1.58384 > 192.168.5.2.36297: sctp
1) [SHUTDOWN]
15 15:56:51.811707 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 36)
192.168.5.2.36297 > 192.168.5.1.58384: sctp
1) [SHUTDOWN ACK]
16 15:56:51.811712 IP (tos 0x2,ECT(0), ttl 64, id 7, offset 0, flags [DF], proto SCTP (132), length 36)
192.168.5.1.58384 > 192.168.5.2.36297: sctp
1) [SHUTDOWN COMPLETE]
16 changes: 16 additions & 0 deletions tests/sctp-re-config.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
1 15:56:38.595332 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [INIT] [init tag: 2670115933] [rwnd: 106496] [OS: 10] [MIS: 65535] [init TSN: 1593007960]
2 15:56:38.595368 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [INIT ACK] [init tag: 2082750980] [rwnd: 106496] [OS: 5] [MIS: 5] [init TSN: 2238062072]
3 15:56:38.595379 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [COOKIE ECHO]
4 15:56:38.595392 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [COOKIE ACK]
5 15:56:38.595416 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [RE-CONFIG] [OUT SSN RESET][IN SSN RESET]
6 15:56:38.595421 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [RE-CONFIG] [RESP], (2) [RE-CONFIG] [OUT SSN RESET]
7 15:56:38.595426 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [RE-CONFIG] [RESP]
8 15:56:38.595434 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [DATA] (B)(E) [TSN: 1593007960] [SID: 0] [SSEQ 0] [PPID 0x0]
9 15:56:38.595440 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [SACK] [cum ack 1593007960] [a_rwnd 106486] [#gap acks 0] [#dup tsns 0]
10 15:56:40.359603 IP 192.168.5.1.58384 > 192.168.5.4.36297: sctp (1) [HB REQ]
11 15:56:40.359631 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [HB ACK]
12 15:56:42.055670 IP 192.168.5.2.36297 > 192.168.5.3.58384: sctp (1) [HB REQ]
13 15:56:42.055866 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [HB ACK]
14 15:56:51.811692 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [SHUTDOWN]
15 15:56:51.811707 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [SHUTDOWN ACK]
16 15:56:51.811712 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [SHUTDOWN COMPLETE]
Binary file added tests/sctp-re-config.pcap
Binary file not shown.

0 comments on commit fb0b574

Please sign in to comment.