1 /* 2 * Copyright (c) 2001 Protocol Engineering Lab, University of Delaware 3 * 4 * Jerry Heinz <gheinz@astro.temple.edu> 5 * John Fiore <jfiore@joda.cis.temple.edu> 6 * Armando L. Caro Jr. <acaro@cis.udel.edu> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the University nor of the Laboratory may be used 20 * to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 __RCSID("$NetBSD: print-sctp.c,v 1.10 2023/08/17 20:19:40 christos Exp $"); 39 #endif 40 41 /* \summary: Stream Control Transmission Protocol (SCTP) printer */ 42 43 #ifdef HAVE_CONFIG_H 44 #include <config.h> 45 #endif 46 47 #include "netdissect-stdinc.h" 48 49 #include "netdissect.h" 50 #include "addrtoname.h" 51 #include "extract.h" 52 #include "ip.h" 53 #include "ip6.h" 54 55 /* Definitions from: 56 * 57 * SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola 58 * 59 * Redistribution and use in source and binary forms, with or without 60 * modification, are permitted provided that the following conditions 61 * are met: 62 * 63 * 1. Redistributions of source code must retain the above copyright 64 * notice, this list of conditions and the following disclaimer. 65 * 66 * 2. Redistributions in binary form must reproduce the above copyright 67 * notice, this list of conditions and the following disclaimer in the 68 * documentation and/or other materials provided with the distribution. 69 * 70 * 3. Neither the name of Cisco nor of Motorola may be used 71 * to endorse or promote products derived from this software without 72 * specific prior written permission. 73 * 74 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 75 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 76 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 77 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 78 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 79 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 80 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 81 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 82 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 83 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 84 * SUCH DAMAGE. 85 * 86 * This file is part of the SCTP reference Implementation 87 * 88 * 89 * Please send any bug reports or fixes you make to one of the following email 90 * addresses: 91 * 92 * rstewar1@email.mot.com 93 * kmorneau@cisco.com 94 * qxie1@email.mot.com 95 * 96 * Any bugs reported given to us we will try to fix... any fixes shared will 97 * be incorporated into the next SCTP release. 98 */ 99 100 /* The valid defines for all message 101 * types know to SCTP. 0 is reserved 102 */ 103 #define SCTP_DATA 0x00 104 #define SCTP_INITIATION 0x01 105 #define SCTP_INITIATION_ACK 0x02 106 #define SCTP_SELECTIVE_ACK 0x03 107 #define SCTP_HEARTBEAT_REQUEST 0x04 108 #define SCTP_HEARTBEAT_ACK 0x05 109 #define SCTP_ABORT_ASSOCIATION 0x06 110 #define SCTP_SHUTDOWN 0x07 111 #define SCTP_SHUTDOWN_ACK 0x08 112 #define SCTP_OPERATION_ERR 0x09 113 #define SCTP_COOKIE_ECHO 0x0a 114 #define SCTP_COOKIE_ACK 0x0b 115 #define SCTP_ECN_ECHO 0x0c 116 #define SCTP_ECN_CWR 0x0d 117 #define SCTP_SHUTDOWN_COMPLETE 0x0e 118 #define SCTP_FORWARD_CUM_TSN 0xc0 119 #define SCTP_RELIABLE_CNTL 0xc1 120 #define SCTP_RELIABLE_CNTL_ACK 0xc2 121 122 static const struct tok sctp_chunkid_str[] = { 123 { SCTP_DATA, "DATA" }, 124 { SCTP_INITIATION, "INIT" }, 125 { SCTP_INITIATION_ACK, "INIT ACK" }, 126 { SCTP_SELECTIVE_ACK, "SACK" }, 127 { SCTP_HEARTBEAT_REQUEST, "HB REQ" }, 128 { SCTP_HEARTBEAT_ACK, "HB ACK" }, 129 { SCTP_ABORT_ASSOCIATION, "ABORT" }, 130 { SCTP_SHUTDOWN, "SHUTDOWN" }, 131 { SCTP_SHUTDOWN_ACK, "SHUTDOWN ACK" }, 132 { SCTP_OPERATION_ERR, "OP ERR" }, 133 { SCTP_COOKIE_ECHO, "COOKIE ECHO" }, 134 { SCTP_COOKIE_ACK, "COOKIE ACK" }, 135 { SCTP_ECN_ECHO, "ECN ECHO" }, 136 { SCTP_ECN_CWR, "ECN CWR" }, 137 { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" }, 138 { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, 139 { SCTP_RELIABLE_CNTL, "REL CTRL" }, 140 { SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" }, 141 { 0, NULL } 142 }; 143 144 /* Data Chuck Specific Flags */ 145 #define SCTP_DATA_FRAG_MASK 0x03 146 #define SCTP_DATA_MIDDLE_FRAG 0x00 147 #define SCTP_DATA_LAST_FRAG 0x01 148 #define SCTP_DATA_FIRST_FRAG 0x02 149 #define SCTP_DATA_NOT_FRAG 0x03 150 #define SCTP_DATA_UNORDERED 0x04 151 152 #define SCTP_ADDRMAX 60 153 154 #define CHAN_HP 6704 155 #define CHAN_MP 6705 156 #define CHAN_LP 6706 157 158 /* the sctp common header */ 159 160 struct sctpHeader{ 161 nd_uint16_t source; 162 nd_uint16_t destination; 163 nd_uint32_t verificationTag; 164 nd_uint32_t adler32; 165 }; 166 167 /* various descriptor parsers */ 168 169 struct sctpChunkDesc{ 170 nd_uint8_t chunkID; 171 nd_uint8_t chunkFlg; 172 nd_uint16_t chunkLength; 173 }; 174 175 struct sctpParamDesc{ 176 nd_uint16_t paramType; 177 nd_uint16_t paramLength; 178 }; 179 180 181 struct sctpRelChunkDesc{ 182 struct sctpChunkDesc chk; 183 nd_uint32_t serialNumber; 184 }; 185 186 struct sctpVendorSpecificParam { 187 struct sctpParamDesc p; /* type must be 0xfffe */ 188 nd_uint32_t vendorId; /* vendor ID from RFC 1700 */ 189 nd_uint16_t vendorSpecificType; 190 nd_uint16_t vendorSpecificLen; 191 }; 192 193 194 /* Structures for the control parts */ 195 196 197 198 /* Sctp association init request/ack */ 199 200 /* this is used for init ack, too */ 201 struct sctpInitiation{ 202 nd_uint32_t initTag; /* tag of mine */ 203 nd_uint32_t rcvWindowCredit; /* rwnd */ 204 nd_uint16_t NumPreopenStreams; /* OS */ 205 nd_uint16_t MaxInboundStreams; /* MIS */ 206 nd_uint32_t initialTSN; 207 /* optional param's follow in sctpParamDesc form */ 208 }; 209 210 struct sctpV4IpAddress{ 211 struct sctpParamDesc p; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */ 212 nd_ipv4 ipAddress; 213 }; 214 215 216 struct sctpV6IpAddress{ 217 struct sctpParamDesc p; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */ 218 nd_ipv6 ipAddress; 219 }; 220 221 struct sctpDNSName{ 222 struct sctpParamDesc param; 223 nd_byte name[1]; 224 }; 225 226 227 struct sctpCookiePreserve{ 228 struct sctpParamDesc p; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */ 229 nd_uint32_t extraTime; 230 }; 231 232 233 struct sctpTimeStamp{ 234 nd_uint32_t ts_sec; 235 nd_uint32_t ts_usec; 236 }; 237 238 239 /* this guy is for use when 240 * I have a initiate message gloming the 241 * things together. 242 243 */ 244 struct sctpUnifiedInit{ 245 struct sctpChunkDesc uh; 246 struct sctpInitiation initm; 247 }; 248 249 struct sctpSendableInit{ 250 struct sctpHeader mh; 251 struct sctpUnifiedInit msg; 252 }; 253 254 255 /* Selective Acknowledgement 256 * has the following structure with 257 * a optional amount of trailing int's 258 * on the last part (based on the numberOfDesc 259 * field). 260 */ 261 262 struct sctpSelectiveAck{ 263 nd_uint32_t highestConseqTSN; 264 nd_uint32_t updatedRwnd; 265 nd_uint16_t numberOfdesc; 266 nd_uint16_t numDupTsns; 267 }; 268 269 struct sctpSelectiveFrag{ 270 nd_uint16_t fragmentStart; 271 nd_uint16_t fragmentEnd; 272 }; 273 274 275 struct sctpUnifiedSack{ 276 struct sctpChunkDesc uh; 277 struct sctpSelectiveAck sack; 278 }; 279 280 /* for the abort and shutdown ACK 281 * we must carry the init tag in the common header. Just the 282 * common header is all that is needed with a chunk descriptor. 283 */ 284 struct sctpUnifiedAbort{ 285 struct sctpChunkDesc uh; 286 }; 287 288 struct sctpUnifiedAbortLight{ 289 struct sctpHeader mh; 290 struct sctpChunkDesc uh; 291 }; 292 293 struct sctpUnifiedAbortHeavy{ 294 struct sctpHeader mh; 295 struct sctpChunkDesc uh; 296 nd_uint16_t causeCode; 297 nd_uint16_t causeLen; 298 }; 299 300 /* For the graceful shutdown we must carry 301 * the tag (in common header) and the highest consequitive acking value 302 */ 303 struct sctpShutdown { 304 nd_uint32_t TSN_Seen; 305 }; 306 307 struct sctpUnifiedShutdown{ 308 struct sctpChunkDesc uh; 309 struct sctpShutdown shut; 310 }; 311 312 /* in the unified message we add the trailing 313 * stream id since it is the only message 314 * that is defined as a operation error. 315 */ 316 struct sctpOpErrorCause{ 317 nd_uint16_t cause; 318 nd_uint16_t causeLen; 319 }; 320 321 struct sctpUnifiedOpError{ 322 struct sctpChunkDesc uh; 323 struct sctpOpErrorCause c; 324 }; 325 326 struct sctpUnifiedStreamError{ 327 struct sctpHeader mh; 328 struct sctpChunkDesc uh; 329 struct sctpOpErrorCause c; 330 nd_uint16_t strmNum; 331 nd_uint16_t reserved; 332 }; 333 334 struct staleCookieMsg{ 335 struct sctpHeader mh; 336 struct sctpChunkDesc uh; 337 struct sctpOpErrorCause c; 338 nd_uint32_t moretime; 339 }; 340 341 /* the following is used in all sends 342 * where nothing is needed except the 343 * chunk/type i.e. shutdownAck Abort */ 344 345 struct sctpUnifiedSingleMsg{ 346 struct sctpHeader mh; 347 struct sctpChunkDesc uh; 348 }; 349 350 struct sctpDataPart{ 351 nd_uint32_t TSN; 352 nd_uint16_t streamId; 353 nd_uint16_t sequence; 354 nd_uint32_t payloadtype; 355 }; 356 357 struct sctpUnifiedDatagram{ 358 struct sctpChunkDesc uh; 359 struct sctpDataPart dp; 360 }; 361 362 struct sctpECN_echo{ 363 struct sctpChunkDesc uh; 364 nd_uint32_t Lowest_TSN; 365 }; 366 367 368 struct sctpCWR{ 369 struct sctpChunkDesc uh; 370 nd_uint32_t TSN_reduced_at; 371 }; 372 373 static const struct tok ForCES_channels[] = { 374 { CHAN_HP, "ForCES HP" }, 375 { CHAN_MP, "ForCES MP" }, 376 { CHAN_LP, "ForCES LP" }, 377 { 0, NULL } 378 }; 379 380 /* data chunk's payload protocol identifiers */ 381 382 #define SCTP_PPID_IUA 1 383 #define SCTP_PPID_M2UA 2 384 #define SCTP_PPID_M3UA 3 385 #define SCTP_PPID_SUA 4 386 #define SCTP_PPID_M2PA 5 387 #define SCTP_PPID_V5UA 6 388 #define SCTP_PPID_H248 7 389 #define SCTP_PPID_BICC 8 390 #define SCTP_PPID_TALI 9 391 #define SCTP_PPID_DUA 10 392 #define SCTP_PPID_ASAP 11 393 #define SCTP_PPID_ENRP 12 394 #define SCTP_PPID_H323 13 395 #define SCTP_PPID_QIPC 14 396 #define SCTP_PPID_SIMCO 15 397 #define SCTP_PPID_DDPSC 16 398 #define SCTP_PPID_DDPSSC 17 399 #define SCTP_PPID_S1AP 18 400 #define SCTP_PPID_RUA 19 401 #define SCTP_PPID_HNBAP 20 402 #define SCTP_PPID_FORCES_HP 21 403 #define SCTP_PPID_FORCES_MP 22 404 #define SCTP_PPID_FORCES_LP 23 405 #define SCTP_PPID_SBC_AP 24 406 #define SCTP_PPID_NBAP 25 407 /* 26 */ 408 #define SCTP_PPID_X2AP 27 409 410 static const struct tok PayloadProto_idents[] = { 411 { SCTP_PPID_IUA, "ISDN Q.921" }, 412 { SCTP_PPID_M2UA, "M2UA" }, 413 { SCTP_PPID_M3UA, "M3UA" }, 414 { SCTP_PPID_SUA, "SUA" }, 415 { SCTP_PPID_M2PA, "M2PA" }, 416 { SCTP_PPID_V5UA, "V5.2" }, 417 { SCTP_PPID_H248, "H.248" }, 418 { SCTP_PPID_BICC, "BICC" }, 419 { SCTP_PPID_TALI, "TALI" }, 420 { SCTP_PPID_DUA, "DUA" }, 421 { SCTP_PPID_ASAP, "ASAP" }, 422 { SCTP_PPID_ENRP, "ENRP" }, 423 { SCTP_PPID_H323, "H.323" }, 424 { SCTP_PPID_QIPC, "Q.IPC" }, 425 { SCTP_PPID_SIMCO, "SIMCO" }, 426 { SCTP_PPID_DDPSC, "DDPSC" }, 427 { SCTP_PPID_DDPSSC, "DDPSSC" }, 428 { SCTP_PPID_S1AP, "S1AP" }, 429 { SCTP_PPID_RUA, "RUA" }, 430 { SCTP_PPID_HNBAP, "HNBAP" }, 431 { SCTP_PPID_FORCES_HP, "ForCES HP" }, 432 { SCTP_PPID_FORCES_MP, "ForCES MP" }, 433 { SCTP_PPID_FORCES_LP, "ForCES LP" }, 434 { SCTP_PPID_SBC_AP, "SBc-AP" }, 435 { SCTP_PPID_NBAP, "NBAP" }, 436 /* 26 */ 437 { SCTP_PPID_X2AP, "X2AP" }, 438 { 0, NULL } 439 }; 440 441 442 static int 443 isForCES_port(u_short Port) 444 { 445 if (Port == CHAN_HP) 446 return 1; 447 if (Port == CHAN_MP) 448 return 1; 449 if (Port == CHAN_LP) 450 return 1; 451 452 return 0; 453 } 454 455 void 456 sctp_print(netdissect_options *ndo, 457 const u_char *bp, /* beginning of sctp packet */ 458 const u_char *bp2, /* beginning of enclosing */ 459 u_int sctpPacketLength) /* ip packet */ 460 { 461 u_int sctpPacketLengthRemaining; 462 const struct sctpHeader *sctpPktHdr; 463 const struct ip *ip; 464 const struct ip6_hdr *ip6; 465 uint8_t chunkID; 466 u_short sourcePort, destPort; 467 u_int chunkCount; 468 const struct sctpChunkDesc *chunkDescPtr; 469 const char *sep; 470 int isforces = 0; 471 472 ndo->ndo_protocol = "sctp"; 473 if (sctpPacketLength < sizeof(struct sctpHeader)) 474 { 475 ND_PRINT("truncated-sctp - %zu bytes missing!", 476 sizeof(struct sctpHeader) - sctpPacketLength); 477 return; 478 } 479 sctpPktHdr = (const struct sctpHeader*) bp; 480 ND_TCHECK_SIZE(sctpPktHdr); 481 sctpPacketLengthRemaining = sctpPacketLength; 482 483 sourcePort = GET_BE_U_2(sctpPktHdr->source); 484 destPort = GET_BE_U_2(sctpPktHdr->destination); 485 486 ip = (const struct ip *)bp2; 487 if (IP_V(ip) == 6) 488 ip6 = (const struct ip6_hdr *)bp2; 489 else 490 ip6 = NULL; 491 492 if (ip6) { 493 ND_PRINT("%s.%u > %s.%u: sctp", 494 GET_IP6ADDR_STRING(ip6->ip6_src), 495 sourcePort, 496 GET_IP6ADDR_STRING(ip6->ip6_dst), 497 destPort); 498 } else { 499 ND_PRINT("%s.%u > %s.%u: sctp", 500 GET_IPADDR_STRING(ip->ip_src), 501 sourcePort, 502 GET_IPADDR_STRING(ip->ip_dst), 503 destPort); 504 } 505 506 if (isForCES_port(sourcePort)) { 507 ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, sourcePort)); 508 isforces = 1; 509 } 510 if (isForCES_port(destPort)) { 511 ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, destPort)); 512 isforces = 1; 513 } 514 515 bp += sizeof(struct sctpHeader); 516 sctpPacketLengthRemaining -= sizeof(struct sctpHeader); 517 518 if (ndo->ndo_vflag >= 2) 519 sep = "\n\t"; 520 else 521 sep = " ("; 522 /* cycle through all chunks, printing information on each one */ 523 for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *)bp; 524 sctpPacketLengthRemaining != 0; 525 chunkCount++) 526 { 527 uint16_t chunkLength, chunkLengthRemaining; 528 uint16_t align; 529 530 chunkDescPtr = (const struct sctpChunkDesc *)bp; 531 if (sctpPacketLengthRemaining < sizeof(*chunkDescPtr)) { 532 ND_PRINT("%s%u) [chunk descriptor cut off at end of packet]", sep, chunkCount+1); 533 break; 534 } 535 ND_TCHECK_SIZE(chunkDescPtr); 536 chunkLength = GET_BE_U_2(chunkDescPtr->chunkLength); 537 if (chunkLength < sizeof(*chunkDescPtr)) { 538 ND_PRINT("%s%u) [Bad chunk length %u, < size of chunk descriptor]", sep, chunkCount+1, chunkLength); 539 break; 540 } 541 chunkLengthRemaining = chunkLength; 542 543 align = chunkLength % 4; 544 if (align != 0) 545 align = 4 - align; 546 547 if (sctpPacketLengthRemaining < align) { 548 ND_PRINT("%s%u) [Bad chunk length %u, > remaining data in packet]", sep, chunkCount+1, chunkLength); 549 break; 550 } 551 552 ND_TCHECK_LEN(bp, chunkLength); 553 554 bp += sizeof(*chunkDescPtr); 555 sctpPacketLengthRemaining -= sizeof(*chunkDescPtr); 556 chunkLengthRemaining -= sizeof(*chunkDescPtr); 557 558 ND_PRINT("%s%u) ", sep, chunkCount+1); 559 chunkID = GET_U_1(chunkDescPtr->chunkID); 560 ND_PRINT("[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x", 561 chunkID)); 562 switch (chunkID) 563 { 564 case SCTP_DATA : 565 { 566 const struct sctpDataPart *dataHdrPtr; 567 uint8_t chunkFlg; 568 uint32_t ppid; 569 uint16_t payload_size; 570 571 chunkFlg = GET_U_1(chunkDescPtr->chunkFlg); 572 if ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) 573 ND_PRINT("(U)"); 574 575 if ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) 576 ND_PRINT("(B)"); 577 578 if ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) 579 ND_PRINT("(E)"); 580 581 if( ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) || 582 ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) || 583 ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ) 584 ND_PRINT(" "); 585 586 if (chunkLengthRemaining < sizeof(*dataHdrPtr)) { 587 ND_PRINT("bogus chunk length %u]", chunkLength); 588 return; 589 } 590 dataHdrPtr=(const struct sctpDataPart*)bp; 591 592 ppid = GET_BE_U_4(dataHdrPtr->payloadtype); 593 ND_PRINT("[TSN: %u] ", GET_BE_U_4(dataHdrPtr->TSN)); 594 ND_PRINT("[SID: %u] ", GET_BE_U_2(dataHdrPtr->streamId)); 595 ND_PRINT("[SSEQ %u] ", GET_BE_U_2(dataHdrPtr->sequence)); 596 ND_PRINT("[PPID %s] ", 597 tok2str(PayloadProto_idents, "0x%x", ppid)); 598 599 if (!isforces) { 600 isforces = (ppid == SCTP_PPID_FORCES_HP) || 601 (ppid == SCTP_PPID_FORCES_MP) || 602 (ppid == SCTP_PPID_FORCES_LP); 603 } 604 605 bp += sizeof(*dataHdrPtr); 606 sctpPacketLengthRemaining -= sizeof(*dataHdrPtr); 607 chunkLengthRemaining -= sizeof(*dataHdrPtr); 608 payload_size = chunkLengthRemaining; 609 if (payload_size == 0) { 610 ND_PRINT("bogus chunk length %u]", chunkLength); 611 return; 612 } 613 614 if (isforces) { 615 forces_print(ndo, bp, payload_size); 616 /* ndo_protocol reassignment after forces_print() call */ 617 ndo->ndo_protocol = "sctp"; 618 } else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */ 619 /* at the command line */ 620 switch (ppid) { 621 case SCTP_PPID_M3UA : 622 m3ua_print(ndo, bp, payload_size); 623 /* ndo_protocol reassignment after m3ua_print() call */ 624 ndo->ndo_protocol = "sctp"; 625 break; 626 default: 627 ND_PRINT("[Payload"); 628 if (!ndo->ndo_suppress_default_print) { 629 ND_PRINT(":"); 630 ND_DEFAULTPRINT(bp, payload_size); 631 } 632 ND_PRINT("]"); 633 break; 634 } 635 } 636 bp += payload_size; 637 sctpPacketLengthRemaining -= payload_size; 638 chunkLengthRemaining -= payload_size; 639 break; 640 } 641 case SCTP_INITIATION : 642 { 643 const struct sctpInitiation *init; 644 645 if (chunkLengthRemaining < sizeof(*init)) { 646 ND_PRINT("bogus chunk length %u]", chunkLength); 647 return; 648 } 649 init=(const struct sctpInitiation*)bp; 650 ND_PRINT("[init tag: %u] ", GET_BE_U_4(init->initTag)); 651 ND_PRINT("[rwnd: %u] ", GET_BE_U_4(init->rcvWindowCredit)); 652 ND_PRINT("[OS: %u] ", GET_BE_U_2(init->NumPreopenStreams)); 653 ND_PRINT("[MIS: %u] ", GET_BE_U_2(init->MaxInboundStreams)); 654 ND_PRINT("[init TSN: %u] ", GET_BE_U_4(init->initialTSN)); 655 bp += sizeof(*init); 656 sctpPacketLengthRemaining -= sizeof(*init); 657 chunkLengthRemaining -= sizeof(*init); 658 659 #if 0 /* ALC you can add code for optional params here */ 660 if( chunkLengthRemaining != 0 ) 661 ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n", 662 "Optional params present, but not printed."); 663 #endif 664 bp += chunkLengthRemaining; 665 sctpPacketLengthRemaining -= chunkLengthRemaining; 666 chunkLengthRemaining = 0; 667 break; 668 } 669 case SCTP_INITIATION_ACK : 670 { 671 const struct sctpInitiation *init; 672 673 if (chunkLengthRemaining < sizeof(*init)) { 674 ND_PRINT("bogus chunk length %u]", chunkLength); 675 return; 676 } 677 init=(const struct sctpInitiation*)bp; 678 ND_PRINT("[init tag: %u] ", GET_BE_U_4(init->initTag)); 679 ND_PRINT("[rwnd: %u] ", GET_BE_U_4(init->rcvWindowCredit)); 680 ND_PRINT("[OS: %u] ", GET_BE_U_2(init->NumPreopenStreams)); 681 ND_PRINT("[MIS: %u] ", GET_BE_U_2(init->MaxInboundStreams)); 682 ND_PRINT("[init TSN: %u] ", GET_BE_U_4(init->initialTSN)); 683 bp += sizeof(*init); 684 sctpPacketLengthRemaining -= sizeof(*init); 685 chunkLengthRemaining -= sizeof(*init); 686 687 #if 0 /* ALC you can add code for optional params here */ 688 if( chunkLengthRemaining != 0 ) 689 ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n", 690 "Optional params present, but not printed."); 691 #endif 692 bp += chunkLengthRemaining; 693 sctpPacketLengthRemaining -= chunkLengthRemaining; 694 chunkLengthRemaining = 0; 695 break; 696 } 697 case SCTP_SELECTIVE_ACK: 698 { 699 const struct sctpSelectiveAck *sack; 700 const struct sctpSelectiveFrag *frag; 701 u_int fragNo, tsnNo; 702 const u_char *dupTSN; 703 704 if (chunkLengthRemaining < sizeof(*sack)) { 705 ND_PRINT("bogus chunk length %u]", chunkLength); 706 return; 707 } 708 sack=(const struct sctpSelectiveAck*)bp; 709 ND_PRINT("[cum ack %u] ", GET_BE_U_4(sack->highestConseqTSN)); 710 ND_PRINT("[a_rwnd %u] ", GET_BE_U_4(sack->updatedRwnd)); 711 ND_PRINT("[#gap acks %u] ", GET_BE_U_2(sack->numberOfdesc)); 712 ND_PRINT("[#dup tsns %u] ", GET_BE_U_2(sack->numDupTsns)); 713 bp += sizeof(*sack); 714 sctpPacketLengthRemaining -= sizeof(*sack); 715 chunkLengthRemaining -= sizeof(*sack); 716 717 718 /* print gaps */ 719 for (fragNo=0; 720 chunkLengthRemaining != 0 && fragNo < GET_BE_U_2(sack->numberOfdesc); 721 bp += sizeof(*frag), sctpPacketLengthRemaining -= sizeof(*frag), chunkLengthRemaining -= sizeof(*frag), fragNo++) { 722 if (chunkLengthRemaining < sizeof(*frag)) { 723 ND_PRINT("bogus chunk length %u]", chunkLength); 724 return; 725 } 726 frag = (const struct sctpSelectiveFrag *)bp; 727 ND_PRINT("\n\t\t[gap ack block #%u: start = %u, end = %u] ", 728 fragNo+1, 729 GET_BE_U_4(sack->highestConseqTSN) + GET_BE_U_2(frag->fragmentStart), 730 GET_BE_U_4(sack->highestConseqTSN) + GET_BE_U_2(frag->fragmentEnd)); 731 } 732 733 /* print duplicate TSNs */ 734 for (tsnNo=0; 735 chunkLengthRemaining != 0 && tsnNo<GET_BE_U_2(sack->numDupTsns); 736 bp += 4, sctpPacketLengthRemaining -= 4, chunkLengthRemaining -= 4, tsnNo++) { 737 if (chunkLengthRemaining < 4) { 738 ND_PRINT("bogus chunk length %u]", chunkLength); 739 return; 740 } 741 dupTSN = (const u_char *)bp; 742 ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, 743 GET_BE_U_4(dupTSN)); 744 } 745 break; 746 } 747 default : 748 { 749 bp += chunkLengthRemaining; 750 sctpPacketLengthRemaining -= chunkLengthRemaining; 751 chunkLengthRemaining = 0; 752 break; 753 } 754 } 755 756 /* 757 * Any extra stuff at the end of the chunk? 758 * XXX - report this? 759 */ 760 bp += chunkLengthRemaining; 761 sctpPacketLengthRemaining -= chunkLengthRemaining; 762 763 if (ndo->ndo_vflag < 2) 764 sep = ", ("; 765 766 if (align != 0) { 767 /* 768 * Fail if the alignment padding isn't in the captured data. 769 * Otherwise, skip it. 770 */ 771 ND_TCHECK_LEN(bp, align); 772 bp += align; 773 sctpPacketLengthRemaining -= align; 774 } 775 } 776 return; 777 778 trunc: 779 nd_print_trunc(ndo); 780 } 781