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