Home | History | Annotate | Download | only in tcpdump
      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