1 /* Copyright (c) 2001 NETLAB, Temple University
2 * Copyright (c) 2001 Protocol Engineering Lab, University of Delaware
4 * Jerry Heinz <gheinz@astro.temple.edu>
5 * John Fiore <jfiore@joda.cis.temple.edu>
6 * Armando L. Caro Jr. <acaro@cis.udel.edu>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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
37 static const char rcsid
[] _U_
=
38 "@(#) $Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.21 2007-09-13 18:03:49 guy Exp $ (NETLAB/PEL)";
45 #include <tcpdump-stdinc.h>
47 #include "sctpHeader.h"
48 #include "sctpConstants.h"
54 #include "interface.h"
55 #include "addrtoname.h"
56 #include "extract.h" /* must come after interface.h */
66 struct tok ForCES_channels
[] = {
67 { CHAN_HP
, "ForCES HP" },
68 { CHAN_MP
, "ForCES MP" },
69 { CHAN_LP
, "ForCES LP" },
73 static inline int isForCES_port(u_short Port
)
85 void sctp_print(const u_char
*bp
, /* beginning of sctp packet */
86 const u_char
*bp2
, /* beginning of enclosing */
87 u_int sctpPacketLength
) /* ip packet */
89 const struct sctpHeader
*sctpPktHdr
;
92 const struct ip6_hdr
*ip6
;
94 const void *endPacketPtr
;
95 u_short sourcePort
, destPort
;
97 const struct sctpChunkDesc
*chunkDescPtr
;
98 const void *nextChunk
;
103 sctpPktHdr
= (const struct sctpHeader
*) bp
;
104 endPacketPtr
= (const u_char
*)sctpPktHdr
+sctpPacketLength
;
106 if( (u_long
) endPacketPtr
> (u_long
) snapend
)
107 endPacketPtr
= (const void *) snapend
;
108 ip
= (struct ip
*)bp2
;
111 ip6
= (const struct ip6_hdr
*)bp2
;
117 if (sctpPacketLength
< sizeof(struct sctpHeader
))
119 (void)printf("truncated-sctp - %ld bytes missing!",
120 (long)sctpPacketLength
-sizeof(struct sctpHeader
));
124 /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */
125 /* is now only as long as the payload */
127 sourcePort
= EXTRACT_16BITS(&sctpPktHdr
->source
);
128 destPort
= EXTRACT_16BITS(&sctpPktHdr
->destination
);
132 (void)printf("%s.%d > %s.%d: sctp",
133 ip6addr_string(&ip6
->ip6_src
),
135 ip6addr_string(&ip6
->ip6_dst
),
140 (void)printf("%s.%d > %s.%d: sctp",
141 ipaddr_string(&ip
->ip_src
),
143 ipaddr_string(&ip
->ip_dst
),
148 if (isForCES_port(sourcePort
)) {
149 printf("[%s]", tok2str(ForCES_channels
, NULL
, sourcePort
));
152 if (isForCES_port(destPort
)) {
153 printf("[%s]", tok2str(ForCES_channels
, NULL
, destPort
));
161 /* cycle through all chunks, printing information on each one */
163 chunkDescPtr
= (const struct sctpChunkDesc
*)
164 ((const u_char
*) sctpPktHdr
+ sizeof(struct sctpHeader
));
165 chunkDescPtr
!= NULL
&&
167 ((const u_char
*) chunkDescPtr
+ sizeof(struct sctpChunkDesc
))
170 chunkDescPtr
= (const struct sctpChunkDesc
*) nextChunk
, chunkCount
++)
172 u_int16_t chunkLength
;
173 const u_char
*chunkEnd
;
176 TCHECK(*chunkDescPtr
);
177 chunkLength
= EXTRACT_16BITS(&chunkDescPtr
->chunkLength
);
178 if (chunkLength
< sizeof(*chunkDescPtr
)) {
179 printf("%s%d) [Bad chunk length %u]", sep
, chunkCount
+1, chunkLength
);
183 TCHECK2(*((u_int8_t
*)chunkDescPtr
), chunkLength
);
184 chunkEnd
= ((const u_char
*)chunkDescPtr
+ chunkLength
);
186 align
=chunkLength
% 4;
190 nextChunk
= (const void *) (chunkEnd
+ align
);
192 printf("%s%d) ", sep
, chunkCount
+1);
193 switch (chunkDescPtr
->chunkID
)
197 const struct sctpDataPart
*dataHdrPtr
;
201 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_UNORDERED
)
202 == SCTP_DATA_UNORDERED
)
205 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_FIRST_FRAG
)
206 == SCTP_DATA_FIRST_FRAG
)
209 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_LAST_FRAG
)
210 == SCTP_DATA_LAST_FRAG
)
213 if( ((chunkDescPtr
->chunkFlg
& SCTP_DATA_UNORDERED
)
214 == SCTP_DATA_UNORDERED
)
216 ((chunkDescPtr
->chunkFlg
& SCTP_DATA_FIRST_FRAG
)
217 == SCTP_DATA_FIRST_FRAG
)
219 ((chunkDescPtr
->chunkFlg
& SCTP_DATA_LAST_FRAG
)
220 == SCTP_DATA_LAST_FRAG
) )
223 dataHdrPtr
=(const struct sctpDataPart
*)(chunkDescPtr
+1);
225 printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr
->TSN
));
226 printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr
->streamId
));
227 printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr
->sequence
));
228 printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr
->payloadtype
));
231 const u_char
*payloadPtr
;
232 u_int chunksize
= sizeof(struct sctpDataPart
)+
233 sizeof(struct sctpChunkDesc
);
234 payloadPtr
= (const u_char
*) (dataHdrPtr
+ 1);
235 if (EXTRACT_16BITS(&chunkDescPtr
->chunkLength
) <
236 sizeof(struct sctpDataPart
)+
237 sizeof(struct sctpChunkDesc
)+1) {
238 /* Less than 1 byte of chunk payload */
239 printf("bogus ForCES chunk length %u]",
240 EXTRACT_16BITS(&chunkDescPtr
->chunkLength
));
244 forces_print(payloadPtr
, EXTRACT_16BITS(&chunkDescPtr
->chunkLength
)- chunksize
);
245 } else if (vflag
>= 2) { /* if verbose output is specified */
246 /* at the command line */
247 const u_char
*payloadPtr
;
251 if (!suppress_default_print
) {
252 payloadPtr
= (const u_char
*) (++dataHdrPtr
);
254 if (EXTRACT_16BITS(&chunkDescPtr
->chunkLength
) <
255 sizeof(struct sctpDataPart
)+
256 sizeof(struct sctpChunkDesc
)+1) {
257 /* Less than 1 byte of chunk payload */
258 printf("bogus chunk length %u]",
259 EXTRACT_16BITS(&chunkDescPtr
->chunkLength
));
262 default_print(payloadPtr
,
263 EXTRACT_16BITS(&chunkDescPtr
->chunkLength
) -
264 (sizeof(struct sctpDataPart
)+
265 sizeof(struct sctpChunkDesc
)));
271 case SCTP_INITIATION
:
273 const struct sctpInitiation
*init
;
276 init
=(const struct sctpInitiation
*)(chunkDescPtr
+1);
277 printf("[init tag: %u] ", EXTRACT_32BITS(&init
->initTag
));
278 printf("[rwnd: %u] ", EXTRACT_32BITS(&init
->rcvWindowCredit
));
279 printf("[OS: %u] ", EXTRACT_16BITS(&init
->NumPreopenStreams
));
280 printf("[MIS: %u] ", EXTRACT_16BITS(&init
->MaxInboundStreams
));
281 printf("[init TSN: %u] ", EXTRACT_32BITS(&init
->initialTSN
));
283 #if(0) /* ALC you can add code for optional params here */
284 if( (init
+1) < chunkEnd
)
285 printf(" @@@@@ UNFINISHED @@@@@@%s\n",
286 "Optional params present, but not printed.");
290 case SCTP_INITIATION_ACK
:
292 const struct sctpInitiation
*init
;
294 printf("[INIT ACK] ");
295 init
=(const struct sctpInitiation
*)(chunkDescPtr
+1);
296 printf("[init tag: %u] ", EXTRACT_32BITS(&init
->initTag
));
297 printf("[rwnd: %u] ", EXTRACT_32BITS(&init
->rcvWindowCredit
));
298 printf("[OS: %u] ", EXTRACT_16BITS(&init
->NumPreopenStreams
));
299 printf("[MIS: %u] ", EXTRACT_16BITS(&init
->MaxInboundStreams
));
300 printf("[init TSN: %u] ", EXTRACT_32BITS(&init
->initialTSN
));
302 #if(0) /* ALC you can add code for optional params here */
303 if( (init
+1) < chunkEnd
)
304 printf(" @@@@@ UNFINISHED @@@@@@%s\n",
305 "Optional params present, but not printed.");
309 case SCTP_SELECTIVE_ACK
:
311 const struct sctpSelectiveAck
*sack
;
312 const struct sctpSelectiveFrag
*frag
;
314 const u_char
*dupTSN
;
317 sack
=(const struct sctpSelectiveAck
*)(chunkDescPtr
+1);
318 printf("[cum ack %u] ", EXTRACT_32BITS(&sack
->highestConseqTSN
));
319 printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack
->updatedRwnd
));
320 printf("[#gap acks %u] ", EXTRACT_16BITS(&sack
->numberOfdesc
));
321 printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack
->numDupTsns
));
325 for (frag
= ( (const struct sctpSelectiveFrag
*)
326 ((const struct sctpSelectiveAck
*) sack
+1)),
328 (const void *)frag
< nextChunk
&& fragNo
< EXTRACT_16BITS(&sack
->numberOfdesc
);
330 printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ",
332 EXTRACT_32BITS(&sack
->highestConseqTSN
) + EXTRACT_16BITS(&frag
->fragmentStart
),
333 EXTRACT_32BITS(&sack
->highestConseqTSN
) + EXTRACT_16BITS(&frag
->fragmentEnd
));
336 /* print duplicate TSNs */
337 for (dupTSN
= (const u_char
*)frag
, tsnNo
=0;
338 (const void *) dupTSN
< nextChunk
&& tsnNo
<EXTRACT_16BITS(&sack
->numDupTsns
);
339 dupTSN
+= 4, tsnNo
++)
340 printf("\n\t\t[dup TSN #%u: %u] ", tsnNo
+1,
341 EXTRACT_32BITS(dupTSN
));
345 case SCTP_HEARTBEAT_REQUEST
:
347 const struct sctpHBsender
*hb
;
349 hb
=(const struct sctpHBsender
*)chunkDescPtr
;
355 case SCTP_HEARTBEAT_ACK
:
358 case SCTP_ABORT_ASSOCIATION
:
362 printf("[SHUTDOWN] ");
364 case SCTP_SHUTDOWN_ACK
:
365 printf("[SHUTDOWN ACK] ");
367 case SCTP_OPERATION_ERR
:
370 case SCTP_COOKIE_ECHO
:
371 printf("[COOKIE ECHO] ");
373 case SCTP_COOKIE_ACK
:
374 printf("[COOKIE ACK] ");
377 printf("[ECN ECHO] ");
380 printf("[ECN CWR] ");
382 case SCTP_SHUTDOWN_COMPLETE
:
383 printf("[SHUTDOWN COMPLETE] ");
385 case SCTP_FORWARD_CUM_TSN
:
386 printf("[FOR CUM TSN] ");
388 case SCTP_RELIABLE_CNTL
:
389 printf("[REL CTRL] ");
391 case SCTP_RELIABLE_CNTL_ACK
:
392 printf("[REL CTRL ACK] ");
395 printf("[Unknown chunk type: 0x%x]", chunkDescPtr
->chunkID
);