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