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