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