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