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