3 /* Copyright (c) 2001 NETLAB, Temple University
4 * Copyright (c) 2001 Protocol Engineering Lab, University of Delaware
6 * Jerry Heinz <gheinz@astro.temple.edu>
7 * John Fiore <jfiore@joda.cis.temple.edu>
8 * Armando L. Caro Jr. <acaro@cis.udel.edu>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor of the Laboratory may be used
22 * to endorse or promote products derived from this software without
23 * specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <sys/cdefs.h>
41 static const char rcsid
[] _U_
=
42 "@(#) Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.16.2.4 2005/07/07 01:24:38 guy Exp (NETLAB/PEL)";
44 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
52 #include <tcpdump-stdinc.h>
54 #include "sctpHeader.h"
55 #include "sctpConstants.h"
61 #include "interface.h"
62 #include "addrtoname.h"
63 #include "extract.h" /* must come after interface.h */
69 void sctp_print(const u_char
*bp
, /* beginning of sctp packet */
70 const u_char
*bp2
, /* beginning of enclosing */
71 u_int sctpPacketLength
) /* ip packet */
73 const struct sctpHeader
*sctpPktHdr
;
76 const struct ip6_hdr
*ip6
;
78 const void *endPacketPtr
;
79 u_short sourcePort
, destPort
;
81 const struct sctpChunkDesc
*chunkDescPtr
;
82 const void *nextChunk
;
85 sctpPktHdr
= (const struct sctpHeader
*) bp
;
86 endPacketPtr
= (const u_char
*)sctpPktHdr
+sctpPacketLength
;
88 if( (u_long
) endPacketPtr
> (u_long
) snapend
)
89 endPacketPtr
= (const void *) snapend
;
90 ip
= (struct ip
*)bp2
;
93 ip6
= (const struct ip6_hdr
*)bp2
;
99 if (sctpPacketLength
< sizeof(struct sctpHeader
))
101 (void)printf("truncated-sctp - %ld bytes missing!",
102 (long)sctpPacketLength
-sizeof(struct sctpHeader
));
106 /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */
107 /* is now only as long as the payload */
109 sourcePort
= EXTRACT_16BITS(&sctpPktHdr
->source
);
110 destPort
= EXTRACT_16BITS(&sctpPktHdr
->destination
);
114 (void)printf("%s.%d > %s.%d: sctp",
115 ip6addr_string(&ip6
->ip6_src
),
117 ip6addr_string(&ip6
->ip6_dst
),
122 (void)printf("%s.%d > %s.%d: sctp",
123 ipaddr_string(&ip
->ip_src
),
125 ipaddr_string(&ip
->ip_dst
),
134 /* cycle through all chunks, printing information on each one */
136 chunkDescPtr
= (const struct sctpChunkDesc
*)
137 ((const u_char
*) sctpPktHdr
+ sizeof(struct sctpHeader
));
138 chunkDescPtr
!= NULL
&&
140 ((const u_char
*) chunkDescPtr
+ sizeof(struct sctpChunkDesc
))
143 chunkDescPtr
= (const struct sctpChunkDesc
*) nextChunk
, chunkCount
++)
145 u_int16_t chunkLength
;
146 const u_char
*chunkEnd
;
149 TCHECK(*chunkDescPtr
);
150 chunkLength
= EXTRACT_16BITS(&chunkDescPtr
->chunkLength
);
151 if (chunkLength
< sizeof(*chunkDescPtr
)) {
152 printf("%s%d) [Bad chunk length %u]", sep
, chunkCount
+1, chunkLength
);
156 TCHECK2(*((u_int8_t
*)chunkDescPtr
), chunkLength
);
157 chunkEnd
= ((const u_char
*)chunkDescPtr
+ chunkLength
);
159 align
=chunkLength
% 4;
163 nextChunk
= (const void *) (chunkEnd
+ align
);
165 printf("%s%d) ", sep
, chunkCount
+1);
166 switch (chunkDescPtr
->chunkID
)
170 const struct sctpDataPart
*dataHdrPtr
;
174 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_UNORDERED
)
175 == SCTP_DATA_UNORDERED
)
178 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_FIRST_FRAG
)
179 == SCTP_DATA_FIRST_FRAG
)
182 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_LAST_FRAG
)
183 == SCTP_DATA_LAST_FRAG
)
186 if( ((chunkDescPtr
->chunkFlg
& SCTP_DATA_UNORDERED
)
187 == SCTP_DATA_UNORDERED
)
189 ((chunkDescPtr
->chunkFlg
& SCTP_DATA_FIRST_FRAG
)
190 == SCTP_DATA_FIRST_FRAG
)
192 ((chunkDescPtr
->chunkFlg
& SCTP_DATA_LAST_FRAG
)
193 == SCTP_DATA_LAST_FRAG
) )
196 dataHdrPtr
=(const struct sctpDataPart
*)(chunkDescPtr
+1);
198 printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr
->TSN
));
199 printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr
->streamId
));
200 printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr
->sequence
));
201 printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr
->payloadtype
));
204 if (vflag
>= 2) /* if verbose output is specified */
205 { /* at the command line */
206 const u_char
*payloadPtr
;
210 if (!suppress_default_print
) {
211 payloadPtr
= (const u_char
*) (++dataHdrPtr
);
213 if (htons(chunkDescPtr
->chunkLength
) <
214 sizeof(struct sctpDataPart
)+
215 sizeof(struct sctpChunkDesc
)+1) {
216 printf("bogus chunk length %u]",
217 htons(chunkDescPtr
->chunkLength
));
220 default_print(payloadPtr
,
221 htons(chunkDescPtr
->chunkLength
) -
222 (sizeof(struct sctpDataPart
)+
223 sizeof(struct sctpChunkDesc
)+1));
229 case SCTP_INITIATION
:
231 const struct sctpInitiation
*init
;
234 init
=(const struct sctpInitiation
*)(chunkDescPtr
+1);
235 printf("[init tag: %u] ", EXTRACT_32BITS(&init
->initTag
));
236 printf("[rwnd: %u] ", EXTRACT_32BITS(&init
->rcvWindowCredit
));
237 printf("[OS: %u] ", EXTRACT_16BITS(&init
->NumPreopenStreams
));
238 printf("[MIS: %u] ", EXTRACT_16BITS(&init
->MaxInboundStreams
));
239 printf("[init TSN: %u] ", EXTRACT_32BITS(&init
->initialTSN
));
241 #if(0) /* ALC you can add code for optional params here */
242 if( (init
+1) < chunkEnd
)
243 printf(" @@@@@ UNFINISHED @@@@@@%s\n",
244 "Optional params present, but not printed.");
248 case SCTP_INITIATION_ACK
:
250 const struct sctpInitiation
*init
;
252 printf("[INIT ACK] ");
253 init
=(const struct sctpInitiation
*)(chunkDescPtr
+1);
254 printf("[init tag: %u] ", EXTRACT_32BITS(&init
->initTag
));
255 printf("[rwnd: %u] ", EXTRACT_32BITS(&init
->rcvWindowCredit
));
256 printf("[OS: %u] ", EXTRACT_16BITS(&init
->NumPreopenStreams
));
257 printf("[MIS: %u] ", EXTRACT_16BITS(&init
->MaxInboundStreams
));
258 printf("[init TSN: %u] ", EXTRACT_32BITS(&init
->initialTSN
));
260 #if(0) /* ALC you can add code for optional params here */
261 if( (init
+1) < chunkEnd
)
262 printf(" @@@@@ UNFINISHED @@@@@@%s\n",
263 "Optional params present, but not printed.");
267 case SCTP_SELECTIVE_ACK
:
269 const struct sctpSelectiveAck
*sack
;
270 const struct sctpSelectiveFrag
*frag
;
272 const u_char
*dupTSN
;
275 sack
=(const struct sctpSelectiveAck
*)(chunkDescPtr
+1);
276 printf("[cum ack %u] ", EXTRACT_32BITS(&sack
->highestConseqTSN
));
277 printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack
->updatedRwnd
));
278 printf("[#gap acks %u] ", EXTRACT_16BITS(&sack
->numberOfdesc
));
279 printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack
->numDupTsns
));
283 for (frag
= ( (const struct sctpSelectiveFrag
*)
284 ((const struct sctpSelectiveAck
*) sack
+1)),
286 (const void *)frag
< nextChunk
&& fragNo
< EXTRACT_16BITS(&sack
->numberOfdesc
);
288 printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ",
290 EXTRACT_32BITS(&sack
->highestConseqTSN
) + EXTRACT_16BITS(&frag
->fragmentStart
),
291 EXTRACT_32BITS(&sack
->highestConseqTSN
) + EXTRACT_16BITS(&frag
->fragmentEnd
));
294 /* print duplicate TSNs */
295 for (dupTSN
= (const u_char
*)frag
, tsnNo
=0;
296 (const void *) dupTSN
< nextChunk
&& tsnNo
<EXTRACT_16BITS(&sack
->numDupTsns
);
297 dupTSN
+= 4, tsnNo
++)
298 printf("\n\t\t[dup TSN #%u: %u] ", tsnNo
+1,
299 EXTRACT_32BITS(dupTSN
));
303 case SCTP_HEARTBEAT_REQUEST
:
305 const struct sctpHBsender
*hb
;
307 hb
=(const struct sctpHBsender
*)chunkDescPtr
;
313 case SCTP_HEARTBEAT_ACK
:
316 case SCTP_ABORT_ASSOCIATION
:
320 printf("[SHUTDOWN] ");
322 case SCTP_SHUTDOWN_ACK
:
323 printf("[SHUTDOWN ACK] ");
325 case SCTP_OPERATION_ERR
:
328 case SCTP_COOKIE_ECHO
:
329 printf("[COOKIE ECHO] ");
331 case SCTP_COOKIE_ACK
:
332 printf("[COOKIE ACK] ");
335 printf("[ECN ECHO] ");
338 printf("[ECN CWR] ");
340 case SCTP_SHUTDOWN_COMPLETE
:
341 printf("[SHUTDOWN COMPLETE] ");
343 case SCTP_FORWARD_CUM_TSN
:
344 printf("[FOR CUM TSN] ");
346 case SCTP_RELIABLE_CNTL
:
347 printf("[REL CTRL] ");
349 case SCTP_RELIABLE_CNTL_ACK
:
350 printf("[REL CTRL ACK] ");
353 printf("[Unknown chunk type: 0x%x]", chunkDescPtr
->chunkID
);