Explicitly request literal mode after .Xr.
[netbsd-mini2440.git] / dist / tcpdump / print-sctp.c
blob95795388d5a577626780323dfafd2ba3ed83ee7d
1 /* $NetBSD$ */
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
12 * are met:
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
35 * SUCH DAMAGE.
38 #include <sys/cdefs.h>
39 #ifndef lint
40 #if 0
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)";
43 #else
44 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
45 #endif
46 #endif
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif
52 #include <tcpdump-stdinc.h>
54 #include "sctpHeader.h"
55 #include "sctpConstants.h"
56 #include <assert.h>
58 #include <stdio.h>
59 #include <string.h>
61 #include "interface.h"
62 #include "addrtoname.h"
63 #include "extract.h" /* must come after interface.h */
64 #include "ip.h"
65 #ifdef INET6
66 #include "ip6.h"
67 #endif
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;
74 const struct ip *ip;
75 #ifdef INET6
76 const struct ip6_hdr *ip6;
77 #endif
78 const void *endPacketPtr;
79 u_short sourcePort, destPort;
80 int chunkCount;
81 const struct sctpChunkDesc *chunkDescPtr;
82 const void *nextChunk;
83 const char *sep;
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;
91 #ifdef INET6
92 if (IP_V(ip) == 6)
93 ip6 = (const struct ip6_hdr *)bp2;
94 else
95 ip6 = NULL;
96 #endif /*INET6*/
97 TCHECK(*sctpPktHdr);
99 if (sctpPacketLength < sizeof(struct sctpHeader))
101 (void)printf("truncated-sctp - %ld bytes missing!",
102 (long)sctpPacketLength-sizeof(struct sctpHeader));
103 return;
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);
112 #ifdef INET6
113 if (ip6) {
114 (void)printf("%s.%d > %s.%d: sctp",
115 ip6addr_string(&ip6->ip6_src),
116 sourcePort,
117 ip6addr_string(&ip6->ip6_dst),
118 destPort);
119 } else
120 #endif /*INET6*/
122 (void)printf("%s.%d > %s.%d: sctp",
123 ipaddr_string(&ip->ip_src),
124 sourcePort,
125 ipaddr_string(&ip->ip_dst),
126 destPort);
128 fflush(stdout);
130 if (vflag >= 2)
131 sep = "\n\t";
132 else
133 sep = " (";
134 /* cycle through all chunks, printing information on each one */
135 for (chunkCount = 0,
136 chunkDescPtr = (const struct sctpChunkDesc *)
137 ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader));
138 chunkDescPtr != NULL &&
139 ( (const void *)
140 ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc))
141 <= endPacketPtr);
143 chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++)
145 u_int16_t chunkLength;
146 const u_char *chunkEnd;
147 u_int16_t align;
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);
153 break;
156 TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength);
157 chunkEnd = ((const u_char*)chunkDescPtr + chunkLength);
159 align=chunkLength % 4;
160 if (align != 0)
161 align = 4 - align;
163 nextChunk = (const void *) (chunkEnd + align);
165 printf("%s%d) ", sep, chunkCount+1);
166 switch (chunkDescPtr->chunkID)
168 case SCTP_DATA :
170 const struct sctpDataPart *dataHdrPtr;
172 printf("[DATA] ");
174 if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
175 == SCTP_DATA_UNORDERED)
176 printf("(U)");
178 if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
179 == SCTP_DATA_FIRST_FRAG)
180 printf("(B)");
182 if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
183 == SCTP_DATA_LAST_FRAG)
184 printf("(E)");
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) )
194 printf(" ");
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));
202 fflush(stdout);
204 if (vflag >= 2) /* if verbose output is specified */
205 { /* at the command line */
206 const u_char *payloadPtr;
208 printf("[Payload");
210 if (!suppress_default_print) {
211 payloadPtr = (const u_char *) (++dataHdrPtr);
212 printf(":");
213 if (htons(chunkDescPtr->chunkLength) <
214 sizeof(struct sctpDataPart)+
215 sizeof(struct sctpChunkDesc)+1) {
216 printf("bogus chunk length %u]",
217 htons(chunkDescPtr->chunkLength));
218 return;
220 default_print(payloadPtr,
221 htons(chunkDescPtr->chunkLength) -
222 (sizeof(struct sctpDataPart)+
223 sizeof(struct sctpChunkDesc)+1));
224 } else
225 printf("]");
227 break;
229 case SCTP_INITIATION :
231 const struct sctpInitiation *init;
233 printf("[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.");
245 #endif
246 break;
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.");
264 #endif
265 break;
267 case SCTP_SELECTIVE_ACK:
269 const struct sctpSelectiveAck *sack;
270 const struct sctpSelectiveFrag *frag;
271 int fragNo, tsnNo;
272 const u_char *dupTSN;
274 printf("[SACK] ");
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));
282 /* print gaps */
283 for (frag = ( (const struct sctpSelectiveFrag *)
284 ((const struct sctpSelectiveAck *) sack+1)),
285 fragNo=0;
286 (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc);
287 frag++, fragNo++)
288 printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ",
289 fragNo+1,
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));
301 break;
303 case SCTP_HEARTBEAT_REQUEST :
305 const struct sctpHBsender *hb;
307 hb=(const struct sctpHBsender*)chunkDescPtr;
309 printf("[HB REQ] ");
311 break;
313 case SCTP_HEARTBEAT_ACK :
314 printf("[HB ACK] ");
315 break;
316 case SCTP_ABORT_ASSOCIATION :
317 printf("[ABORT] ");
318 break;
319 case SCTP_SHUTDOWN :
320 printf("[SHUTDOWN] ");
321 break;
322 case SCTP_SHUTDOWN_ACK :
323 printf("[SHUTDOWN ACK] ");
324 break;
325 case SCTP_OPERATION_ERR :
326 printf("[OP ERR] ");
327 break;
328 case SCTP_COOKIE_ECHO :
329 printf("[COOKIE ECHO] ");
330 break;
331 case SCTP_COOKIE_ACK :
332 printf("[COOKIE ACK] ");
333 break;
334 case SCTP_ECN_ECHO :
335 printf("[ECN ECHO] ");
336 break;
337 case SCTP_ECN_CWR :
338 printf("[ECN CWR] ");
339 break;
340 case SCTP_SHUTDOWN_COMPLETE :
341 printf("[SHUTDOWN COMPLETE] ");
342 break;
343 case SCTP_FORWARD_CUM_TSN :
344 printf("[FOR CUM TSN] ");
345 break;
346 case SCTP_RELIABLE_CNTL :
347 printf("[REL CTRL] ");
348 break;
349 case SCTP_RELIABLE_CNTL_ACK :
350 printf("[REL CTRL ACK] ");
351 break;
352 default :
353 printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID);
354 return;
357 if (vflag < 2)
358 sep = ", (";
360 return;
362 trunc:
363 printf("[|sctp]");
364 return;