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