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.9 2020/02/24 18:39:47 kamil 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 incorperated 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 uint16_t source; 162 uint16_t destination; 163 uint32_t verificationTag; 164 uint32_t adler32; 165 }; 166 167 /* various descriptor parsers */ 168 169 struct sctpChunkDesc{ 170 uint8_t chunkID; 171 uint8_t chunkFlg; 172 uint16_t chunkLength; 173 }; 174 175 struct sctpParamDesc{ 176 uint16_t paramType; 177 uint16_t paramLength; 178 }; 179 180 181 struct sctpRelChunkDesc{ 182 struct sctpChunkDesc chk; 183 uint32_t serialNumber; 184 }; 185 186 struct sctpVendorSpecificParam { 187 struct sctpParamDesc p; /* type must be 0xfffe */ 188 uint32_t vendorId; /* vendor ID from RFC 1700 */ 189 uint16_t vendorSpecificType; 190 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 uint32_t initTag; /* tag of mine */ 203 uint32_t rcvWindowCredit; /* rwnd */ 204 uint16_t NumPreopenStreams; /* OS */ 205 uint16_t MaxInboundStreams; /* MIS */ 206 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 uint32_t ipAddress; 213 }; 214 215 216 struct sctpV6IpAddress{ 217 struct sctpParamDesc p; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */ 218 uint8_t ipAddress[16]; 219 }; 220 221 struct sctpDNSName{ 222 struct sctpParamDesc param; 223 uint8_t name[1]; 224 }; 225 226 227 struct sctpCookiePreserve{ 228 struct sctpParamDesc p; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */ 229 uint32_t extraTime; 230 }; 231 232 233 struct sctpTimeStamp{ 234 uint32_t ts_sec; 235 uint32_t ts_usec; 236 }; 237 238 /* wire structure of my cookie */ 239 struct cookieMessage{ 240 uint32_t TieTag_curTag; /* copied from assoc if present */ 241 uint32_t TieTag_hisTag; /* copied from assoc if present */ 242 int32_t cookieLife; /* life I will award this cookie */ 243 struct sctpTimeStamp timeEnteringState; /* the time I built cookie */ 244 struct sctpInitiation initAckISent; /* the INIT-ACK that I sent to my peer */ 245 uint32_t addressWhereISent[4]; /* I make this 4 ints so I get 128bits for future */ 246 int32_t addrtype; /* address type */ 247 uint16_t locScope; /* V6 local scope flag */ 248 uint16_t siteScope; /* V6 site scope flag */ 249 /* at the end is tacked on the INIT chunk sent in 250 * its entirety and of course our 251 * signature. 252 */ 253 }; 254 255 256 /* this guy is for use when 257 * I have a initiate message gloming the 258 * things together. 259 260 */ 261 struct sctpUnifiedInit{ 262 struct sctpChunkDesc uh; 263 struct sctpInitiation initm; 264 }; 265 266 struct sctpSendableInit{ 267 struct sctpHeader mh; 268 struct sctpUnifiedInit msg; 269 }; 270 271 272 /* Selective Acknowledgement 273 * has the following structure with 274 * a optional ammount of trailing int's 275 * on the last part (based on the numberOfDesc 276 * field). 277 */ 278 279 struct sctpSelectiveAck{ 280 uint32_t highestConseqTSN; 281 uint32_t updatedRwnd; 282 uint16_t numberOfdesc; 283 uint16_t numDupTsns; 284 }; 285 286 struct sctpSelectiveFrag{ 287 uint16_t fragmentStart; 288 uint16_t fragmentEnd; 289 }; 290 291 292 struct sctpUnifiedSack{ 293 struct sctpChunkDesc uh; 294 struct sctpSelectiveAck sack; 295 }; 296 297 /* for both RTT request/response the 298 * following is sent 299 */ 300 301 struct sctpHBrequest { 302 uint32_t time_value_1; 303 uint32_t time_value_2; 304 }; 305 306 /* here is what I read and respond with to. */ 307 struct sctpHBunified{ 308 struct sctpChunkDesc hdr; 309 struct sctpParamDesc hb; 310 }; 311 312 313 /* here is what I send */ 314 struct sctpHBsender{ 315 struct sctpChunkDesc hdr; 316 struct sctpParamDesc hb; 317 struct sctpHBrequest rtt; 318 int8_t addrFmt[SCTP_ADDRMAX]; 319 uint16_t userreq; 320 }; 321 322 323 324 /* for the abort and shutdown ACK 325 * we must carry the init tag in the common header. Just the 326 * common header is all that is needed with a chunk descriptor. 327 */ 328 struct sctpUnifiedAbort{ 329 struct sctpChunkDesc uh; 330 }; 331 332 struct sctpUnifiedAbortLight{ 333 struct sctpHeader mh; 334 struct sctpChunkDesc uh; 335 }; 336 337 struct sctpUnifiedAbortHeavy{ 338 struct sctpHeader mh; 339 struct sctpChunkDesc uh; 340 uint16_t causeCode; 341 uint16_t causeLen; 342 }; 343 344 /* For the graceful shutdown we must carry 345 * the tag (in common header) and the highest consequitive acking value 346 */ 347 struct sctpShutdown { 348 uint32_t TSN_Seen; 349 }; 350 351 struct sctpUnifiedShutdown{ 352 struct sctpChunkDesc uh; 353 struct sctpShutdown shut; 354 }; 355 356 /* in the unified message we add the trailing 357 * stream id since it is the only message 358 * that is defined as a operation error. 359 */ 360 struct sctpOpErrorCause{ 361 uint16_t cause; 362 uint16_t causeLen; 363 }; 364 365 struct sctpUnifiedOpError{ 366 struct sctpChunkDesc uh; 367 struct sctpOpErrorCause c; 368 }; 369 370 struct sctpUnifiedStreamError{ 371 struct sctpHeader mh; 372 struct sctpChunkDesc uh; 373 struct sctpOpErrorCause c; 374 uint16_t strmNum; 375 uint16_t reserved; 376 }; 377 378 struct staleCookieMsg{ 379 struct sctpHeader mh; 380 struct sctpChunkDesc uh; 381 struct sctpOpErrorCause c; 382 uint32_t moretime; 383 }; 384 385 /* the following is used in all sends 386 * where nothing is needed except the 387 * chunk/type i.e. shutdownAck Abort */ 388 389 struct sctpUnifiedSingleMsg{ 390 struct sctpHeader mh; 391 struct sctpChunkDesc uh; 392 }; 393 394 struct sctpDataPart{ 395 uint32_t TSN; 396 uint16_t streamId; 397 uint16_t sequence; 398 uint32_t payloadtype; 399 }; 400 401 struct sctpUnifiedDatagram{ 402 struct sctpChunkDesc uh; 403 struct sctpDataPart dp; 404 }; 405 406 struct sctpECN_echo{ 407 struct sctpChunkDesc uh; 408 uint32_t Lowest_TSN; 409 }; 410 411 412 struct sctpCWR{ 413 struct sctpChunkDesc uh; 414 uint32_t TSN_reduced_at; 415 }; 416 417 static const struct tok ForCES_channels[] = { 418 { CHAN_HP, "ForCES HP" }, 419 { CHAN_MP, "ForCES MP" }, 420 { CHAN_LP, "ForCES LP" }, 421 { 0, NULL } 422 }; 423 424 /* data chunk's payload protocol identifiers */ 425 426 #define SCTP_PPID_IUA 1 427 #define SCTP_PPID_M2UA 2 428 #define SCTP_PPID_M3UA 3 429 #define SCTP_PPID_SUA 4 430 #define SCTP_PPID_M2PA 5 431 #define SCTP_PPID_V5UA 6 432 #define SCTP_PPID_H248 7 433 #define SCTP_PPID_BICC 8 434 #define SCTP_PPID_TALI 9 435 #define SCTP_PPID_DUA 10 436 #define SCTP_PPID_ASAP 11 437 #define SCTP_PPID_ENRP 12 438 #define SCTP_PPID_H323 13 439 #define SCTP_PPID_QIPC 14 440 #define SCTP_PPID_SIMCO 15 441 #define SCTP_PPID_DDPSC 16 442 #define SCTP_PPID_DDPSSC 17 443 #define SCTP_PPID_S1AP 18 444 #define SCTP_PPID_RUA 19 445 #define SCTP_PPID_HNBAP 20 446 #define SCTP_PPID_FORCES_HP 21 447 #define SCTP_PPID_FORCES_MP 22 448 #define SCTP_PPID_FORCES_LP 23 449 #define SCTP_PPID_SBC_AP 24 450 #define SCTP_PPID_NBAP 25 451 /* 26 */ 452 #define SCTP_PPID_X2AP 27 453 454 static const struct tok PayloadProto_idents[] = { 455 { SCTP_PPID_IUA, "ISDN Q.921" }, 456 { SCTP_PPID_M2UA, "M2UA" }, 457 { SCTP_PPID_M3UA, "M3UA" }, 458 { SCTP_PPID_SUA, "SUA" }, 459 { SCTP_PPID_M2PA, "M2PA" }, 460 { SCTP_PPID_V5UA, "V5.2" }, 461 { SCTP_PPID_H248, "H.248" }, 462 { SCTP_PPID_BICC, "BICC" }, 463 { SCTP_PPID_TALI, "TALI" }, 464 { SCTP_PPID_DUA, "DUA" }, 465 { SCTP_PPID_ASAP, "ASAP" }, 466 { SCTP_PPID_ENRP, "ENRP" }, 467 { SCTP_PPID_H323, "H.323" }, 468 { SCTP_PPID_QIPC, "Q.IPC" }, 469 { SCTP_PPID_SIMCO, "SIMCO" }, 470 { SCTP_PPID_DDPSC, "DDPSC" }, 471 { SCTP_PPID_DDPSSC, "DDPSSC" }, 472 { SCTP_PPID_S1AP, "S1AP" }, 473 { SCTP_PPID_RUA, "RUA" }, 474 { SCTP_PPID_HNBAP, "HNBAP" }, 475 { SCTP_PPID_FORCES_HP, "ForCES HP" }, 476 { SCTP_PPID_FORCES_MP, "ForCES MP" }, 477 { SCTP_PPID_FORCES_LP, "ForCES LP" }, 478 { SCTP_PPID_SBC_AP, "SBc-AP" }, 479 { SCTP_PPID_NBAP, "NBAP" }, 480 /* 26 */ 481 { SCTP_PPID_X2AP, "X2AP" }, 482 { 0, NULL } 483 }; 484 485 486 static inline int isForCES_port(u_short Port) 487 { 488 if (Port == CHAN_HP) 489 return 1; 490 if (Port == CHAN_MP) 491 return 1; 492 if (Port == CHAN_LP) 493 return 1; 494 495 return 0; 496 } 497 498 UNALIGNED_OK 499 void sctp_print(netdissect_options *ndo, 500 const u_char *bp, /* beginning of sctp packet */ 501 const u_char *bp2, /* beginning of enclosing */ 502 u_int sctpPacketLength) /* ip packet */ 503 { 504 u_int sctpPacketLengthRemaining; 505 const struct sctpHeader *sctpPktHdr; 506 const struct ip *ip; 507 const struct ip6_hdr *ip6; 508 u_short sourcePort, destPort; 509 int chunkCount; 510 const struct sctpChunkDesc *chunkDescPtr; 511 const char *sep; 512 int isforces = 0; 513 514 if (sctpPacketLength < sizeof(struct sctpHeader)) 515 { 516 ND_PRINT((ndo, "truncated-sctp - %ld bytes missing!", 517 (long)(sizeof(struct sctpHeader) - sctpPacketLength))); 518 return; 519 } 520 sctpPktHdr = (const struct sctpHeader*) bp; 521 ND_TCHECK(*sctpPktHdr); 522 sctpPacketLengthRemaining = sctpPacketLength; 523 524 sourcePort = EXTRACT_16BITS(&sctpPktHdr->source); 525 destPort = EXTRACT_16BITS(&sctpPktHdr->destination); 526 527 ip = (const struct ip *)bp2; 528 if (IP_V(ip) == 6) 529 ip6 = (const struct ip6_hdr *)bp2; 530 else 531 ip6 = NULL; 532 533 if (ip6) { 534 ND_PRINT((ndo, "%s.%d > %s.%d: sctp", 535 ip6addr_string(ndo, &ip6->ip6_src), 536 sourcePort, 537 ip6addr_string(ndo, &ip6->ip6_dst), 538 destPort)); 539 } else 540 { 541 ND_PRINT((ndo, "%s.%d > %s.%d: sctp", 542 ipaddr_string(ndo, &ip->ip_src), 543 sourcePort, 544 ipaddr_string(ndo, &ip->ip_dst), 545 destPort)); 546 } 547 548 if (isForCES_port(sourcePort)) { 549 ND_PRINT((ndo, "[%s]", tok2str(ForCES_channels, NULL, sourcePort))); 550 isforces = 1; 551 } 552 if (isForCES_port(destPort)) { 553 ND_PRINT((ndo, "[%s]", tok2str(ForCES_channels, NULL, destPort))); 554 isforces = 1; 555 } 556 557 bp += sizeof(struct sctpHeader); 558 sctpPacketLengthRemaining -= sizeof(struct sctpHeader); 559 560 if (ndo->ndo_vflag >= 2) 561 sep = "\n\t"; 562 else 563 sep = " ("; 564 /* cycle through all chunks, printing information on each one */ 565 for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *)bp; 566 sctpPacketLengthRemaining != 0; 567 chunkCount++) 568 { 569 uint16_t chunkLength, chunkLengthRemaining; 570 uint16_t align; 571 572 chunkDescPtr = (const struct sctpChunkDesc *)bp; 573 if (sctpPacketLengthRemaining < sizeof(*chunkDescPtr)) { 574 ND_PRINT((ndo, "%s%d) [chunk descriptor cut off at end of packet]", sep, chunkCount+1)); 575 break; 576 } 577 ND_TCHECK(*chunkDescPtr); 578 chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength); 579 if (chunkLength < sizeof(*chunkDescPtr)) { 580 ND_PRINT((ndo, "%s%d) [Bad chunk length %u, < size of chunk descriptor]", sep, chunkCount+1, chunkLength)); 581 break; 582 } 583 chunkLengthRemaining = chunkLength; 584 585 align = chunkLength % 4; 586 if (align != 0) 587 align = 4 - align; 588 589 if (sctpPacketLengthRemaining < align) { 590 ND_PRINT((ndo, "%s%d) [Bad chunk length %u, > remaining data in packet]", sep, chunkCount+1, chunkLength)); 591 break; 592 } 593 594 ND_TCHECK2(*bp, chunkLength); 595 596 bp += sizeof(*chunkDescPtr); 597 sctpPacketLengthRemaining -= sizeof(*chunkDescPtr); 598 chunkLengthRemaining -= sizeof(*chunkDescPtr); 599 600 ND_PRINT((ndo, "%s%d) ", sep, chunkCount+1)); 601 ND_PRINT((ndo, "[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x", 602 chunkDescPtr->chunkID))); 603 switch (chunkDescPtr->chunkID) 604 { 605 case SCTP_DATA : 606 { 607 const struct sctpDataPart *dataHdrPtr; 608 uint32_t ppid; 609 u_int payload_size; 610 611 if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) 612 == SCTP_DATA_UNORDERED) 613 ND_PRINT((ndo, "(U)")); 614 615 if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) 616 == SCTP_DATA_FIRST_FRAG) 617 ND_PRINT((ndo, "(B)")); 618 619 if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) 620 == SCTP_DATA_LAST_FRAG) 621 ND_PRINT((ndo, "(E)")); 622 623 if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) 624 == SCTP_DATA_UNORDERED) 625 || 626 ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) 627 == SCTP_DATA_FIRST_FRAG) 628 || 629 ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) 630 == SCTP_DATA_LAST_FRAG) ) 631 ND_PRINT((ndo, " ")); 632 633 if (chunkLengthRemaining < sizeof(*dataHdrPtr)) { 634 ND_PRINT((ndo, "bogus chunk length %u]", chunkLength)); 635 return; 636 } 637 dataHdrPtr=(const struct sctpDataPart*)bp; 638 639 ppid = EXTRACT_32BITS(&dataHdrPtr->payloadtype); 640 ND_PRINT((ndo, "[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN))); 641 ND_PRINT((ndo, "[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId))); 642 ND_PRINT((ndo, "[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence))); 643 ND_PRINT((ndo, "[PPID %s] ", 644 tok2str(PayloadProto_idents, "0x%x", ppid))); 645 646 if (!isforces) { 647 isforces = (ppid == SCTP_PPID_FORCES_HP) || 648 (ppid == SCTP_PPID_FORCES_MP) || 649 (ppid == SCTP_PPID_FORCES_LP); 650 } 651 652 bp += sizeof(*dataHdrPtr); 653 sctpPacketLengthRemaining -= sizeof(*dataHdrPtr); 654 chunkLengthRemaining -= sizeof(*dataHdrPtr); 655 payload_size = chunkLengthRemaining; 656 if (payload_size == 0) { 657 ND_PRINT((ndo, "bogus chunk length %u]", chunkLength)); 658 return; 659 } 660 661 if (isforces) { 662 forces_print(ndo, bp, payload_size); 663 } else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */ 664 /* at the command line */ 665 switch (ppid) { 666 case SCTP_PPID_M3UA : 667 m3ua_print(ndo, bp, payload_size); 668 break; 669 default: 670 ND_PRINT((ndo, "[Payload")); 671 if (!ndo->ndo_suppress_default_print) { 672 ND_PRINT((ndo, ":")); 673 ND_DEFAULTPRINT(bp, payload_size); 674 } 675 ND_PRINT((ndo, "]")); 676 break; 677 } 678 } 679 bp += payload_size; 680 sctpPacketLengthRemaining -= payload_size; 681 chunkLengthRemaining -= payload_size; 682 break; 683 } 684 case SCTP_INITIATION : 685 { 686 const struct sctpInitiation *init; 687 688 if (chunkLengthRemaining < sizeof(*init)) { 689 ND_PRINT((ndo, "bogus chunk length %u]", chunkLength)); 690 return; 691 } 692 init=(const struct sctpInitiation*)bp; 693 ND_PRINT((ndo, "[init tag: %u] ", EXTRACT_32BITS(&init->initTag))); 694 ND_PRINT((ndo, "[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit))); 695 ND_PRINT((ndo, "[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams))); 696 ND_PRINT((ndo, "[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams))); 697 ND_PRINT((ndo, "[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN))); 698 bp += sizeof(*init); 699 sctpPacketLengthRemaining -= sizeof(*init); 700 chunkLengthRemaining -= sizeof(*init); 701 702 #if 0 /* ALC you can add code for optional params here */ 703 if( chunkLengthRemaining != 0 ) 704 ND_PRINT((ndo, " @@@@@ UNFINISHED @@@@@@%s\n", 705 "Optional params present, but not printed.")); 706 #endif 707 bp += chunkLengthRemaining; 708 sctpPacketLengthRemaining -= chunkLengthRemaining; 709 chunkLengthRemaining = 0; 710 break; 711 } 712 case SCTP_INITIATION_ACK : 713 { 714 const struct sctpInitiation *init; 715 716 if (chunkLengthRemaining < sizeof(*init)) { 717 ND_PRINT((ndo, "bogus chunk length %u]", chunkLength)); 718 return; 719 } 720 init=(const struct sctpInitiation*)bp; 721 ND_PRINT((ndo, "[init tag: %u] ", EXTRACT_32BITS(&init->initTag))); 722 ND_PRINT((ndo, "[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit))); 723 ND_PRINT((ndo, "[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams))); 724 ND_PRINT((ndo, "[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams))); 725 ND_PRINT((ndo, "[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN))); 726 bp += sizeof(*init); 727 sctpPacketLengthRemaining -= sizeof(*init); 728 chunkLengthRemaining -= sizeof(*init); 729 730 #if 0 /* ALC you can add code for optional params here */ 731 if( chunkLengthRemaining != 0 ) 732 ND_PRINT((ndo, " @@@@@ UNFINISHED @@@@@@%s\n", 733 "Optional params present, but not printed.")); 734 #endif 735 bp += chunkLengthRemaining; 736 sctpPacketLengthRemaining -= chunkLengthRemaining; 737 chunkLengthRemaining = 0; 738 break; 739 } 740 case SCTP_SELECTIVE_ACK: 741 { 742 const struct sctpSelectiveAck *sack; 743 const struct sctpSelectiveFrag *frag; 744 int fragNo, tsnNo; 745 const u_char *dupTSN; 746 747 if (chunkLengthRemaining < sizeof(*sack)) { 748 ND_PRINT((ndo, "bogus chunk length %u]", chunkLength)); 749 return; 750 } 751 sack=(const struct sctpSelectiveAck*)bp; 752 ND_PRINT((ndo, "[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN))); 753 ND_PRINT((ndo, "[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd))); 754 ND_PRINT((ndo, "[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc))); 755 ND_PRINT((ndo, "[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns))); 756 bp += sizeof(*sack); 757 sctpPacketLengthRemaining -= sizeof(*sack); 758 chunkLengthRemaining -= sizeof(*sack); 759 760 761 /* print gaps */ 762 for (fragNo=0; 763 chunkLengthRemaining != 0 && fragNo < EXTRACT_16BITS(&sack->numberOfdesc); 764 bp += sizeof(*frag), sctpPacketLengthRemaining -= sizeof(*frag), chunkLengthRemaining -= sizeof(*frag), fragNo++) { 765 if (chunkLengthRemaining < sizeof(*frag)) { 766 ND_PRINT((ndo, "bogus chunk length %u]", chunkLength)); 767 return; 768 } 769 frag = (const struct sctpSelectiveFrag *)bp; 770 ND_PRINT((ndo, "\n\t\t[gap ack block #%d: start = %u, end = %u] ", 771 fragNo+1, 772 EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart), 773 EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd))); 774 } 775 776 /* print duplicate TSNs */ 777 for (tsnNo=0; 778 chunkLengthRemaining != 0 && tsnNo<EXTRACT_16BITS(&sack->numDupTsns); 779 bp += 4, sctpPacketLengthRemaining -= 4, chunkLengthRemaining -= 4, tsnNo++) { 780 if (chunkLengthRemaining < 4) { 781 ND_PRINT((ndo, "bogus chunk length %u]", chunkLength)); 782 return; 783 } 784 dupTSN = (const u_char *)bp; 785 ND_PRINT((ndo, "\n\t\t[dup TSN #%u: %u] ", tsnNo+1, 786 EXTRACT_32BITS(dupTSN))); 787 } 788 break; 789 } 790 default : 791 { 792 bp += chunkLengthRemaining; 793 sctpPacketLengthRemaining -= chunkLengthRemaining; 794 chunkLengthRemaining = 0; 795 break; 796 } 797 } 798 799 /* 800 * Any extra stuff at the end of the chunk? 801 * XXX - report this? 802 */ 803 bp += chunkLengthRemaining; 804 sctpPacketLengthRemaining -= chunkLengthRemaining; 805 806 if (ndo->ndo_vflag < 2) 807 sep = ", ("; 808 809 if (align != 0) { 810 /* 811 * Fail if the alignment padding isn't in the captured data. 812 * Otherwise, skip it. 813 */ 814 ND_TCHECK2(*bp, align); 815 bp += align; 816 sctpPacketLengthRemaining -= align; 817 } 818 } 819 return; 820 821 trunc: 822 ND_PRINT((ndo, "[|sctp]")); 823 } 824