Skip to content

Commit f124842

Browse files
author
Yuxuan Luo
committed
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. Example: `-v`: [ASCONF] [SEQ: .., ADDR: 192...] [DEL ADDR] `-vv`:[ASCONF] [SEQ: .., ADDR: 192...] [DEL ADDR: C-ID: 0, ADDR: 192...] [ASCONF-ACK] [SEQ: 4161214189]
1 parent 29d158a commit f124842

File tree

1 file changed

+217
-2
lines changed

1 file changed

+217
-2
lines changed

print-sctp.c

+217-2
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,10 @@
112112
#define SCTP_ECN_CWR 0x0d
113113
#define SCTP_SHUTDOWN_COMPLETE 0x0e
114114
#define SCTP_I_DATA 0x40
115+
#define SCTP_ASCONF_ACK 0x80
115116
#define SCTP_RE_CONFIG 0x82
116117
#define SCTP_FORWARD_CUM_TSN 0xc0
117-
#define SCTP_RELIABLE_CNTL 0xc1
118+
#define SCTP_ASCONF 0xc1
118119
#define SCTP_I_FORWARD_TSN 0xc2
119120

120121
static const struct tok sctp_chunkid_str[] = {
@@ -136,7 +137,8 @@ static const struct tok sctp_chunkid_str[] = {
136137
{ SCTP_I_DATA, "I-DATA" },
137138
{ SCTP_RE_CONFIG, "RE-CONFIG" },
138139
{ SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" },
139-
{ SCTP_RELIABLE_CNTL, "REL CTRL" },
140+
{ SCTP_ASCONF, "ASCONF" },
141+
{ SCTP_ASCONF_ACK, "ASCONF-ACK" },
140142
{ SCTP_I_FORWARD_TSN, "I-FORWARD-FSN" },
141143
{ 0, NULL }
142144
};
@@ -163,6 +165,18 @@ static const struct tok sctp_chunkid_str[] = {
163165

164166
#define SCTP_ADDRMAX 60
165167

168+
/* ASCONF Parameters*/
169+
/* - used in INIT/ACK chunk */
170+
#define SET_PRI_ADDR 0xC004
171+
#define ADAPT_LAYER_INDIC 0xC006
172+
#define SUPPORTED_EXT 0x8008
173+
/* - used in ASCONF param */
174+
#define ADD_IP_ADDR 0xC001
175+
#define DEL_IP_ADDR 0xC002
176+
/* - used in ASCONF response */
177+
#define ERR_CAUSE_INDIC 0xC003
178+
#define SUCCESS_INDIC 0xC005
179+
166180
#define CHAN_HP 6704
167181
#define CHAN_MP 6705
168182
#define CHAN_LP 6706
@@ -411,6 +425,35 @@ struct addStreamReq{
411425
nd_uint16_t reserved;
412426
};
413427

428+
/* ASCONF parameters */
429+
struct sctpAsconfParam{
430+
nd_uint16_t type;
431+
nd_uint16_t length;
432+
nd_uint32_t CID;
433+
union {
434+
struct sctpV4IpAddress ipv4;
435+
struct sctpV6IpAddress ipv6;
436+
} addr;
437+
};
438+
439+
struct sctpASCONF{
440+
nd_uint32_t seq_num;
441+
union {
442+
struct sctpV4IpAddress ipv4;
443+
struct sctpV6IpAddress ipv6;
444+
} addr;
445+
};
446+
447+
struct sctpASCONF_ACK{
448+
nd_uint32_t seq_num;
449+
};
450+
451+
struct sctpErrParam{
452+
nd_uint8_t type;
453+
nd_uint8_t flags;
454+
nd_uint16_t length;
455+
};
456+
414457
struct sctpUnifiedDatagram{
415458
struct sctpChunkDesc uh;
416459
struct sctpDataPart dp;
@@ -448,6 +491,34 @@ static const struct tok results[] = {
448491
{ 6, "In progress" },
449492
};
450493

494+
/* ASCONF tokens */
495+
static const struct tok asconfigParams[] = {
496+
{ SET_PRI_ADDR, "SET PRIM ADDR" },
497+
{ ADAPT_LAYER_INDIC, "Adaptation Layer Indication" },
498+
{ SUPPORTED_EXT, "Supported Extensions" },
499+
{ ADD_IP_ADDR, "ADD ADDR" },
500+
{ DEL_IP_ADDR, "DEL ADDR" },
501+
{ ERR_CAUSE_INDIC, "ERR" },
502+
{ SUCCESS_INDIC, "SUCCESS" },
503+
};
504+
505+
static const struct tok causeCode[] = {
506+
{ 1, "Invalid Stream Identifier" },
507+
{ 2, "Missing Mandatory Parameter" },
508+
{ 3, "Stale Cookie Error" },
509+
{ 4, "Out of Resource" },
510+
{ 5, "Unresolvable Address" },
511+
{ 6, "Unrecognized Chunk Type" },
512+
{ 7, "Invalid Mandatory Parameter" },
513+
{ 8, "Unrecognized Parameters" },
514+
{ 9, "No User Data" },
515+
{ 10, "Cookie Received While Shutting Down" },
516+
{ 11, "Restart of an Association with New Addresses" },
517+
{ 12, "User Initiated Abort" },
518+
{ 13, "Protocol Violation" },
519+
{ 0, NULL }
520+
};
521+
451522
static const struct tok ForCES_channels[] = {
452523
{ CHAN_HP, "ForCES HP" },
453524
{ CHAN_MP, "ForCES MP" },
@@ -1115,6 +1186,150 @@ sctp_print(netdissect_options *ndo,
11151186
bp += padding_len;
11161187
}
11171188

1189+
break;
1190+
}
1191+
case SCTP_ASCONF:
1192+
{
1193+
const struct sctpASCONF *content;
1194+
const struct sctpAsconfParam *param;
1195+
size_t length;
1196+
uint16_t param_len;
1197+
1198+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content));
1199+
content = (const struct sctpASCONF*) bp;
1200+
ND_PRINT("[SEQ: %u, ", GET_BE_U_4(content->seq_num));
1201+
1202+
if (GET_BE_U_2(content->addr.ipv4.p.paramType) == 5) { /* IPv4 */
1203+
length = sizeof(nd_uint32_t) + sizeof(struct sctpV4IpAddress);
1204+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, length);
1205+
ND_PRINT("ADDR: %s] ", GET_IPADDR_STRING(content->addr.ipv4.ipAddress));
1206+
} else if (GET_BE_U_2(content->addr.ipv6.p.paramType) == 6) { /* IPv6 */
1207+
length = sizeof(nd_uint32_t) + sizeof(struct sctpV6IpAddress);
1208+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, length);
1209+
ND_PRINT("ADDR: %s] ", GET_IP6ADDR_STRING(content->addr.ipv4.ipAddress));
1210+
} else {
1211+
length = sizeof(nd_uint32_t) + GET_BE_U_2(content->addr.ipv4.p.paramLength);
1212+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, length);
1213+
ND_PRINT("ADDR: bogus address type]");
1214+
}
1215+
bp += length;
1216+
chunkLengthRemaining -= length;
1217+
sctpPacketLengthRemaining -= length;
1218+
1219+
while (0 != chunkLengthRemaining) {
1220+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(uint32_t)); /* ensure param_len can be extracted */
1221+
param = (const struct sctpAsconfParam*) bp;
1222+
param_len = GET_BE_U_2(param->length);
1223+
1224+
ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_len);
1225+
bp += param_len;
1226+
chunkLengthRemaining -= param_len;
1227+
sctpPacketLengthRemaining -= param_len;
1228+
1229+
ND_PRINT("[%s", tok2str(asconfigParams, NULL, GET_BE_U_2(param->type)));
1230+
1231+
if (ndo->ndo_vflag >= 2) {
1232+
ND_PRINT(": C-ID: %u, ", GET_BE_U_4(param->CID));
1233+
if (GET_BE_U_2(param->addr.ipv4.p.paramType) == 5) { /* IPv4 */
1234+
length = sizeof(nd_uint32_t) + sizeof(struct sctpV4IpAddress);
1235+
ND_ICHECKMSG_ZU("param length", param_len, <, length);
1236+
ND_PRINT("ADDR: %s] ", GET_IPADDR_STRING(param->addr.ipv4.ipAddress));
1237+
} else if (GET_BE_U_2(param->addr.ipv4.p.paramType) == 6) { /* IPv6 */
1238+
length = sizeof(nd_uint32_t) + sizeof(struct sctpV6IpAddress);
1239+
ND_ICHECKMSG_ZU("param length", param_len, <, length);
1240+
ND_PRINT("ADDR: %s] ", GET_IP6ADDR_STRING(param->addr.ipv6.ipAddress));
1241+
} else {
1242+
ND_PRINT("ADDR: bogus address type]");
1243+
}
1244+
} else {
1245+
ND_PRINT("]");
1246+
}
1247+
}
1248+
break;
1249+
}
1250+
case SCTP_ASCONF_ACK:
1251+
{
1252+
const struct sctpASCONF_ACK *content;
1253+
const struct sctpAsconfParam *header;
1254+
uint16_t param_len;
1255+
1256+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content));
1257+
content = (const struct sctpASCONF_ACK*) bp;
1258+
ND_PRINT("[SEQ: %u] ", GET_BE_U_4(content->seq_num));
1259+
1260+
bp += sizeof(*content);
1261+
chunkLengthRemaining -= sizeof(*content);
1262+
sctpPacketLengthRemaining -= sizeof(*content);
1263+
1264+
while (0 != chunkLengthRemaining) {
1265+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*header));
1266+
header = (const struct sctpAsconfParam*) bp;
1267+
param_len = GET_BE_U_2(header->length);
1268+
ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_len);
1269+
1270+
ND_PRINT("[%s", tok2str(asconfigParams, NULL, GET_BE_U_2(header->type)));
1271+
1272+
/* print payload only when vflag >= 2 */
1273+
if (ndo->ndo_vflag < 2) {
1274+
ND_PRINT("] ");
1275+
bp += param_len;
1276+
chunkLengthRemaining -= param_len;
1277+
sctpPacketLengthRemaining -= param_len;
1278+
continue;
1279+
}
1280+
1281+
bp += sizeof(*header);
1282+
chunkLengthRemaining -= sizeof(*header);
1283+
sctpPacketLengthRemaining -= sizeof(*header);
1284+
1285+
switch (GET_BE_U_2(header->type)) {
1286+
case ERR_CAUSE_INDIC:
1287+
{
1288+
const struct sctpErrParam *errHdr;
1289+
const struct sctpOpErrorCause *err_cause;
1290+
uint16_t param_remaining;
1291+
uint16_t cause_len;
1292+
1293+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(struct sctpErrParam));
1294+
errHdr = (const struct sctpErrParam*) bp;
1295+
param_remaining = GET_BE_U_2(errHdr->length);
1296+
ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_remaining);
1297+
1298+
bp += sizeof(*errHdr);
1299+
chunkLengthRemaining -= sizeof(*errHdr);
1300+
sctpPacketLengthRemaining -= sizeof(*errHdr);
1301+
1302+
ND_PRINT(": ");
1303+
while (0 != param_remaining) {
1304+
ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*err_cause));
1305+
err_cause = (const struct sctpOpErrorCause*) bp;
1306+
ND_PRINT(" %s, ", tok2str(causeCode, NULL, GET_BE_U_2(err_cause->cause)));
1307+
1308+
cause_len = GET_BE_U_2(err_cause->causeLen);
1309+
ND_ICHECKMSG_ZU("cause length", cause_len, <, sizeof(*err_cause));
1310+
ND_ICHECKMSG_U("param length", param_remaining, <, cause_len);
1311+
bp += cause_len;
1312+
param_remaining -= cause_len;
1313+
chunkLengthRemaining -= cause_len;
1314+
sctpPacketLengthRemaining -= cause_len;
1315+
}
1316+
ND_PRINT("] ");
1317+
break;
1318+
}
1319+
case SUCCESS_INDIC:
1320+
{
1321+
ND_PRINT(": C-ID %u] ", GET_BE_U_4(bp));
1322+
bp += sizeof(uint32_t);
1323+
break;
1324+
}
1325+
default:
1326+
{
1327+
ND_PRINT("Unknown parameter] ");
1328+
bp += (param_len - sizeof(*header));
1329+
break;
1330+
}
1331+
}
1332+
}
11181333
break;
11191334
}
11201335
default :

0 commit comments

Comments
 (0)