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