1/* Copyright (c) 2001 NETLAB, Temple University
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/* \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@email.mot.com
88 * kmorneau@cisco.com
89 * qxie1@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
117static 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
155struct sctpHeader{
156  uint16_t source;
157  uint16_t destination;
158  uint32_t verificationTag;
159  uint32_t adler32;
160};
161
162/* various descriptor parsers */
163
164struct sctpChunkDesc{
165  uint8_t chunkID;
166  uint8_t chunkFlg;
167  uint16_t chunkLength;
168};
169
170struct sctpParamDesc{
171  uint16_t paramType;
172  uint16_t paramLength;
173};
174
175
176struct sctpRelChunkDesc{
177  struct sctpChunkDesc chk;
178  uint32_t serialNumber;
179};
180
181struct 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 */
196struct 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
205struct sctpV4IpAddress{
206  struct sctpParamDesc p;	/* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */
207  uint32_t  ipAddress;
208};
209
210
211struct sctpV6IpAddress{
212  struct sctpParamDesc p;	/* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */
213  uint8_t  ipAddress[16];
214};
215
216struct sctpDNSName{
217  struct sctpParamDesc param;
218  uint8_t name[1];
219};
220
221
222struct sctpCookiePreserve{
223  struct sctpParamDesc p;	/* type is set to SCTP_COOKIE_PRESERVE, len=8 */
224  uint32_t extraTime;
225};
226
227
228struct sctpTimeStamp{
229  uint32_t ts_sec;
230  uint32_t ts_usec;
231};
232
233/* wire structure of my cookie */
234struct 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 */
256struct sctpUnifiedInit{
257  struct sctpChunkDesc uh;
258  struct sctpInitiation initm;
259};
260
261struct 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
274struct sctpSelectiveAck{
275  uint32_t highestConseqTSN;
276  uint32_t updatedRwnd;
277  uint16_t numberOfdesc;
278  uint16_t numDupTsns;
279};
280
281struct sctpSelectiveFrag{
282  uint16_t fragmentStart;
283  uint16_t fragmentEnd;
284};
285
286
287struct sctpUnifiedSack{
288  struct sctpChunkDesc uh;
289  struct sctpSelectiveAck sack;
290};
291
292/* for both RTT request/response the
293 * following is sent
294 */
295
296struct 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. */
302struct sctpHBunified{
303  struct sctpChunkDesc hdr;
304  struct sctpParamDesc hb;
305};
306
307
308/* here is what I send */
309struct 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 */
323struct sctpUnifiedAbort{
324  struct sctpChunkDesc uh;
325};
326
327struct sctpUnifiedAbortLight{
328  struct sctpHeader mh;
329  struct sctpChunkDesc uh;
330};
331
332struct 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 */
342struct sctpShutdown {
343  uint32_t TSN_Seen;
344};
345
346struct 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 */
355struct sctpOpErrorCause{
356  uint16_t cause;
357  uint16_t causeLen;
358};
359
360struct sctpUnifiedOpError{
361  struct sctpChunkDesc uh;
362  struct sctpOpErrorCause c;
363};
364
365struct sctpUnifiedStreamError{
366  struct sctpHeader mh;
367  struct sctpChunkDesc uh;
368  struct sctpOpErrorCause c;
369  uint16_t strmNum;
370  uint16_t reserved;
371};
372
373struct 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
384struct sctpUnifiedSingleMsg{
385  struct sctpHeader mh;
386  struct sctpChunkDesc uh;
387};
388
389struct sctpDataPart{
390  uint32_t TSN;
391  uint16_t streamId;
392  uint16_t sequence;
393  uint32_t payloadtype;
394};
395
396struct sctpUnifiedDatagram{
397  struct sctpChunkDesc uh;
398  struct sctpDataPart dp;
399};
400
401struct sctpECN_echo{
402  struct sctpChunkDesc uh;
403  uint32_t Lowest_TSN;
404};
405
406
407struct sctpCWR{
408  struct sctpChunkDesc uh;
409  uint32_t TSN_reduced_at;
410};
411
412static 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
449static 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
481static 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
493void 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
815trunc:
816    ND_PRINT((ndo, "[|sctp]"));
817}
818