Skip to content

Commit 29d158a

Browse files
author
Yuxuan Luo
committed
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]
1 parent 08b3357 commit 29d158a

File tree

1 file changed

+246
-0
lines changed

1 file changed

+246
-0
lines changed

print-sctp.c

+246
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
#define SCTP_ECN_CWR 0x0d
113113
#define SCTP_SHUTDOWN_COMPLETE 0x0e
114114
#define SCTP_I_DATA 0x40
115+
#define SCTP_RE_CONFIG 0x82
115116
#define SCTP_FORWARD_CUM_TSN 0xc0
116117
#define SCTP_RELIABLE_CNTL 0xc1
117118
#define SCTP_I_FORWARD_TSN 0xc2
@@ -133,6 +134,7 @@ static const struct tok sctp_chunkid_str[] = {
133134
{ SCTP_ECN_CWR, "ECN CWR" },
134135
{ SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" },
135136
{ SCTP_I_DATA, "I-DATA" },
137+
{ SCTP_RE_CONFIG, "RE-CONFIG" },
136138
{ SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" },
137139
{ SCTP_RELIABLE_CNTL, "REL CTRL" },
138140
{ SCTP_I_FORWARD_TSN, "I-FORWARD-FSN" },
@@ -151,6 +153,14 @@ static const struct tok sctp_chunkid_str[] = {
151153
/* I-Forward-TSN Specific Flag */
152154
#define SCTP_I_FORWARD_UNORDERED 0x01
153155

156+
/* RE-CONFIG Parameters */
157+
#define OUT_SSN_RESET 13
158+
#define IN_SSN_RESET 14
159+
#define SSN_TSN_RESET 15
160+
#define RE_CONFIG_RES 16
161+
#define ADD_OUT_STREAM_REQ 17
162+
#define ADD_IN_STREAM_REQ 18
163+
154164
#define SCTP_ADDRMAX 60
155165

156166
#define CHAN_HP 6704
@@ -374,6 +384,33 @@ struct sctpIForwardEntry{
374384
nd_uint32_t MID;
375385
};
376386

387+
/* RE-CONFIG Parameters */
388+
struct sctpReConfigHdr{
389+
nd_uint16_t param_type;
390+
nd_uint16_t param_len;
391+
};
392+
393+
struct outGoingSSNReset{
394+
nd_uint32_t re_config_req;
395+
nd_uint32_t re_config_res;
396+
nd_uint32_t last_assigned_TSN;
397+
};
398+
399+
struct inGoingSSNReset{
400+
nd_uint32_t re_config_req;
401+
};
402+
403+
struct reConfigRes{
404+
nd_uint32_t res_seq_num;
405+
nd_uint32_t result;
406+
};
407+
408+
struct addStreamReq{
409+
nd_uint32_t res_seq_num;
410+
nd_uint16_t num_new_stream;
411+
nd_uint16_t reserved;
412+
};
413+
377414
struct sctpUnifiedDatagram{
378415
struct sctpChunkDesc uh;
379416
struct sctpDataPart dp;
@@ -390,6 +427,27 @@ struct sctpCWR{
390427
nd_uint32_t TSN_reduced_at;
391428
};
392429

430+
/* RE-CONFIG Parameters */
431+
static const struct tok RE_CONFIG_parameters[] = {
432+
{ OUT_SSN_RESET, "OUT SSN RESET" },
433+
{ IN_SSN_RESET, "IN SSN RESET" },
434+
{ SSN_TSN_RESET, "SSN/TSN Reset" },
435+
{ RE_CONFIG_RES, "RESP" },
436+
{ ADD_OUT_STREAM_REQ, "ADD OUT STREAM"},
437+
{ ADD_IN_STREAM_REQ, "ADD IN STREAM" },
438+
{ 0, NULL }
439+
};
440+
441+
static const struct tok results[] = {
442+
{ 0, "Success - Nothing to do" },
443+
{ 1, "Success - Performed" },
444+
{ 2, "Denied" },
445+
{ 3, "Error - Wrong SSN" },
446+
{ 4, "Error - Request already in progress" },
447+
{ 5, "Error - Bad Sequence Number" },
448+
{ 6, "In progress" },
449+
};
450+
393451
static const struct tok ForCES_channels[] = {
394452
{ CHAN_HP, "ForCES HP" },
395453
{ CHAN_MP, "ForCES MP" },
@@ -869,6 +927,194 @@ sctp_print(netdissect_options *ndo,
869927
ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
870928
GET_BE_U_4(dupTSN));
871929
}
930+
break;
931+
}
932+
case SCTP_RE_CONFIG:
933+
{
934+
const struct sctpReConfigHdr *param;
935+
uint16_t param_len, type;
936+
uint8_t padding_len;
937+
938+
sctpPacketLengthRemaining -= chunkLengthRemaining;
939+
940+
while (0 != chunkLengthRemaining) {
941+
/* it's a padding if the remaining length is less than 4 */
942+
if (sizeof(uint32_t) >= chunkLengthRemaining) {
943+
chunkLengthRemaining = 0;
944+
break;
945+
}
946+
947+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*param));
948+
param = (const struct sctpReConfigHdr*)bp;
949+
param_len = GET_BE_U_2(param->param_len);
950+
type = GET_BE_U_2(param->param_type);
951+
padding_len = param_len % 4;
952+
953+
ND_PRINT("[%s", tok2str(RE_CONFIG_parameters, NULL, type));
954+
955+
param_len -= sizeof(*param);
956+
chunkLengthRemaining -= sizeof(*param);
957+
bp += sizeof(*param);
958+
if (ndo->ndo_vflag < 2) { /* if verbose level < 2, stop and skip */
959+
ND_PRINT("]");
960+
961+
ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_len);
962+
bp += param_len;
963+
chunkLengthRemaining -= param_len;
964+
/* it's a parameter padding if there are more parameters in the remaining length */
965+
if (chunkLengthRemaining > 4)
966+
bp += padding_len;
967+
968+
continue;
969+
}
970+
971+
switch (type) {
972+
case OUT_SSN_RESET:
973+
{
974+
uint16_t stream_num = 0;
975+
const struct outGoingSSNReset *content;
976+
977+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content));
978+
979+
content = (const struct outGoingSSNReset*) bp;
980+
ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->re_config_req));
981+
ND_PRINT("RES SEQ: %u, ", GET_BE_U_4(content->re_config_res));
982+
ND_PRINT("Last TSN: %u, ", GET_BE_U_4(content->last_assigned_TSN));
983+
984+
bp += sizeof(*content);
985+
param_len -= sizeof(*content);
986+
chunkLengthRemaining -= sizeof(*content);
987+
988+
ND_PRINT("SID");
989+
while (0 != param_len) {
990+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(stream_num));
991+
stream_num = GET_BE_U_2(bp);
992+
ND_PRINT(" %u", stream_num);
993+
994+
bp += sizeof(stream_num);
995+
param_len -= sizeof(stream_num);
996+
chunkLengthRemaining -= sizeof(stream_num);
997+
}
998+
ND_PRINT("]");
999+
1000+
break;
1001+
}
1002+
case IN_SSN_RESET:
1003+
{
1004+
uint16_t stream_num = 0;
1005+
const struct inGoingSSNReset *content;
1006+
1007+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content));
1008+
1009+
content = (const struct inGoingSSNReset*) bp;
1010+
ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->re_config_req));
1011+
1012+
bp += sizeof(*content);
1013+
param_len -= sizeof(*content);
1014+
chunkLengthRemaining -= sizeof(*content);
1015+
1016+
ND_PRINT("SID");
1017+
while (0 != param_len) {
1018+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(stream_num));
1019+
stream_num = GET_BE_U_2(bp);
1020+
ND_PRINT(" %u", stream_num);
1021+
1022+
bp += sizeof(stream_num);
1023+
param_len -= sizeof(stream_num);
1024+
chunkLengthRemaining -= sizeof(stream_num);
1025+
}
1026+
ND_PRINT("]");
1027+
1028+
break;
1029+
}
1030+
case SSN_TSN_RESET:
1031+
{
1032+
const struct inGoingSSNReset *content;
1033+
1034+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content));
1035+
1036+
content = (const struct inGoingSSNReset*) bp;
1037+
ND_PRINT(": REQ SEQ: %u]", GET_BE_U_4(content->re_config_req));
1038+
1039+
bp += sizeof(*content);
1040+
chunkLengthRemaining -= sizeof(*content);
1041+
1042+
break;
1043+
}
1044+
case RE_CONFIG_RES:
1045+
{
1046+
uint32_t optional = 0;
1047+
const size_t optional_size = sizeof(optional);
1048+
const struct reConfigRes *content;
1049+
1050+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content));
1051+
1052+
content = (const struct reConfigRes*) bp;
1053+
ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->res_seq_num));
1054+
ND_PRINT("REQ: %s", tok2str(results, NULL, GET_BE_U_4(content->result)));
1055+
1056+
bp += sizeof(*content);
1057+
param_len -= sizeof(*content);
1058+
chunkLengthRemaining -= sizeof(*content);
1059+
1060+
if (0 == param_len) {
1061+
ND_PRINT("]");
1062+
break;
1063+
}
1064+
1065+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, optional_size);
1066+
optional = GET_BE_U_4(bp);
1067+
ND_PRINT(", Sender's TSN: %u", optional);
1068+
1069+
bp += optional_size;
1070+
param_len -= optional_size;
1071+
chunkLengthRemaining -= optional_size;
1072+
1073+
if (0 == param_len) {
1074+
ND_PRINT("]");
1075+
break;
1076+
}
1077+
1078+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, optional_size);
1079+
optional = GET_BE_U_4(bp);
1080+
ND_PRINT(", Receiver's Next TSN: %u] ", optional);
1081+
1082+
bp += optional_size;
1083+
param_len -= optional_size;
1084+
chunkLengthRemaining -= optional_size;
1085+
1086+
break;
1087+
}
1088+
case ADD_OUT_STREAM_REQ:
1089+
case ADD_IN_STREAM_REQ:
1090+
{
1091+
const struct addStreamReq *content;
1092+
1093+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content));
1094+
1095+
content = (const struct addStreamReq*) bp;
1096+
ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->res_seq_num));
1097+
ND_PRINT("No. of new streams: %u] ", GET_BE_U_2(content->num_new_stream));
1098+
1099+
bp += sizeof(*content);
1100+
param_len -= sizeof(*content);
1101+
chunkLengthRemaining -= sizeof(*content);
1102+
1103+
break;
1104+
}
1105+
default:
1106+
{
1107+
bp += chunkLengthRemaining;
1108+
chunkLengthRemaining = 0;
1109+
break;
1110+
}
1111+
}
1112+
1113+
/* it's a parameter padding if there are more parameters in the remaining length */
1114+
if (chunkLengthRemaining > 4)
1115+
bp += padding_len;
1116+
}
1117+
8721118
break;
8731119
}
8741120
default :

0 commit comments

Comments
 (0)