Move tcpdump-3.9/ to tcpdump/. No need for a versioned dir.
[dragonfly.git] / contrib / tcpdump / print-sctp.c
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 #ifndef lint
37 static const char rcsid[] _U_ =
38 "@(#) $Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.16.2.5 2007/09/13 18:04:58 guy Exp $ (NETLAB/PEL)";
39 #endif
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include <tcpdump-stdinc.h>
46
47 #include "sctpHeader.h"
48 #include "sctpConstants.h"
49 #include <assert.h>
50
51 #include <stdio.h>
52 #include <string.h>
53
54 #include "interface.h"
55 #include "addrtoname.h"
56 #include "extract.h"                    /* must come after interface.h */
57 #include "ip.h"
58 #ifdef INET6
59 #include "ip6.h"
60 #endif
61
62 void sctp_print(const u_char *bp,        /* beginning of sctp packet */
63                 const u_char *bp2,       /* beginning of enclosing */
64                 u_int sctpPacketLength)  /* ip packet */
65 {
66   const struct sctpHeader *sctpPktHdr;
67   const struct ip *ip;
68 #ifdef INET6
69   const struct ip6_hdr *ip6;
70 #endif
71   const void *endPacketPtr;
72   u_short sourcePort, destPort;
73   int chunkCount;
74   const struct sctpChunkDesc *chunkDescPtr;
75   const void *nextChunk;
76   const char *sep;
77
78   sctpPktHdr = (const struct sctpHeader*) bp;
79   endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength;
80
81   if( (u_long) endPacketPtr > (u_long) snapend)
82     endPacketPtr = (const void *) snapend;
83   ip = (struct ip *)bp2;
84 #ifdef INET6
85   if (IP_V(ip) == 6)
86     ip6 = (const struct ip6_hdr *)bp2;
87   else
88     ip6 = NULL;
89 #endif /*INET6*/
90   TCHECK(*sctpPktHdr);
91
92   if (sctpPacketLength < sizeof(struct sctpHeader))
93     {
94       (void)printf("truncated-sctp - %ld bytes missing!",
95                    (long)sctpPacketLength-sizeof(struct sctpHeader));
96       return;
97     }
98
99   /*    sctpPacketLength -= sizeof(struct sctpHeader);  packet length  */
100   /*                          is now only as long as the payload  */
101
102   sourcePort = EXTRACT_16BITS(&sctpPktHdr->source);
103   destPort = EXTRACT_16BITS(&sctpPktHdr->destination);
104
105 #ifdef INET6
106   if (ip6) {
107     (void)printf("%s.%d > %s.%d: sctp",
108       ip6addr_string(&ip6->ip6_src),
109       sourcePort,
110       ip6addr_string(&ip6->ip6_dst),
111       destPort);
112   } else
113 #endif /*INET6*/
114   {
115     (void)printf("%s.%d > %s.%d: sctp",
116       ipaddr_string(&ip->ip_src),
117       sourcePort,
118       ipaddr_string(&ip->ip_dst),
119       destPort);
120   }
121   fflush(stdout);
122
123   if (vflag >= 2)
124     sep = "\n\t";
125   else
126     sep = " (";
127   /* cycle through all chunks, printing information on each one */
128   for (chunkCount = 0,
129          chunkDescPtr = (const struct sctpChunkDesc *)
130             ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader));
131        chunkDescPtr != NULL &&
132          ( (const void *)
133             ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc))
134            <= endPacketPtr);
135
136        chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++)
137     {
138       u_int16_t chunkLength;
139       const u_char *chunkEnd;
140       u_int16_t align;
141
142       TCHECK(*chunkDescPtr);
143       chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength);
144       if (chunkLength < sizeof(*chunkDescPtr)) {
145         printf("%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength);
146         break;
147       }
148
149       TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength);
150       chunkEnd = ((const u_char*)chunkDescPtr + chunkLength);
151
152       align=chunkLength % 4;
153       if (align != 0)
154         align = 4 - align;
155
156       nextChunk = (const void *) (chunkEnd + align);
157
158       printf("%s%d) ", sep, chunkCount+1);
159       switch (chunkDescPtr->chunkID)
160         {
161         case SCTP_DATA :
162           {
163             const struct sctpDataPart *dataHdrPtr;
164
165             printf("[DATA] ");
166
167             if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
168                 == SCTP_DATA_UNORDERED)
169               printf("(U)");
170
171             if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
172                 == SCTP_DATA_FIRST_FRAG)
173               printf("(B)");
174
175             if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
176                 == SCTP_DATA_LAST_FRAG)
177               printf("(E)");
178
179             if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
180                  == SCTP_DATA_UNORDERED)
181                 ||
182                 ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
183                  == SCTP_DATA_FIRST_FRAG)
184                 ||
185                 ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
186                  == SCTP_DATA_LAST_FRAG) )
187               printf(" ");
188
189             dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1);
190
191             printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN));
192             printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId));
193             printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence));
194             printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr->payloadtype));
195             fflush(stdout);
196
197             if (vflag >= 2)        /* if verbose output is specified */
198               {                    /* at the command line */
199                 const u_char *payloadPtr;
200
201                 printf("[Payload");
202
203                 if (!suppress_default_print) {
204                         payloadPtr = (const u_char *) (++dataHdrPtr);
205                         printf(":");
206                         if (htons(chunkDescPtr->chunkLength) <
207                             sizeof(struct sctpDataPart)+
208                             sizeof(struct sctpChunkDesc)+1) {
209                                 /* Less than 1 byte of chunk payload */
210                                 printf("bogus chunk length %u]",
211                                     htons(chunkDescPtr->chunkLength));
212                                 return;
213                         }
214                         default_print(payloadPtr,
215                               htons(chunkDescPtr->chunkLength) -
216                               (sizeof(struct sctpDataPart)+
217                               sizeof(struct sctpChunkDesc)));
218                 } else
219                         printf("]");
220               }
221             break;
222           }
223         case SCTP_INITIATION :
224           {
225             const struct sctpInitiation *init;
226
227             printf("[INIT] ");
228             init=(const struct sctpInitiation*)(chunkDescPtr+1);
229             printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag));
230             printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit));
231             printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams));
232             printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams));
233             printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN));
234
235 #if(0) /* ALC you can add code for optional params here */
236             if( (init+1) < chunkEnd )
237               printf(" @@@@@ UNFINISHED @@@@@@%s\n",
238                      "Optional params present, but not printed.");
239 #endif
240             break;
241           }
242         case SCTP_INITIATION_ACK :
243           {
244             const struct sctpInitiation *init;
245
246             printf("[INIT ACK] ");
247             init=(const struct sctpInitiation*)(chunkDescPtr+1);
248             printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag));
249             printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit));
250             printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams));
251             printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams));
252             printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN));
253
254 #if(0) /* ALC you can add code for optional params here */
255             if( (init+1) < chunkEnd )
256               printf(" @@@@@ UNFINISHED @@@@@@%s\n",
257                      "Optional params present, but not printed.");
258 #endif
259             break;
260           }
261         case SCTP_SELECTIVE_ACK:
262           {
263             const struct sctpSelectiveAck *sack;
264             const struct sctpSelectiveFrag *frag;
265             int fragNo, tsnNo;
266             const u_char *dupTSN;
267
268             printf("[SACK] ");
269             sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1);
270             printf("[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN));
271             printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd));
272             printf("[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc));
273             printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns));
274
275
276             /* print gaps */
277             for (frag = ( (const struct sctpSelectiveFrag *)
278                           ((const struct sctpSelectiveAck *) sack+1)),
279                    fragNo=0;
280                  (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc);
281                  frag++, fragNo++)
282               printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ",
283                      fragNo+1,
284                      EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart),
285                      EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd));
286
287
288             /* print duplicate TSNs */
289             for (dupTSN = (const u_char *)frag, tsnNo=0;
290                  (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns);
291                  dupTSN += 4, tsnNo++)
292               printf("\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
293                   EXTRACT_32BITS(dupTSN));
294
295             break;
296           }
297         case SCTP_HEARTBEAT_REQUEST :
298           {
299             const struct sctpHBsender *hb;
300
301             hb=(const struct sctpHBsender*)chunkDescPtr;
302
303             printf("[HB REQ] ");
304
305             break;
306           }
307         case SCTP_HEARTBEAT_ACK :
308           printf("[HB ACK] ");
309           break;
310         case SCTP_ABORT_ASSOCIATION :
311           printf("[ABORT] ");
312           break;
313         case SCTP_SHUTDOWN :
314           printf("[SHUTDOWN] ");
315           break;
316         case SCTP_SHUTDOWN_ACK :
317           printf("[SHUTDOWN ACK] ");
318           break;
319         case SCTP_OPERATION_ERR :
320           printf("[OP ERR] ");
321           break;
322         case SCTP_COOKIE_ECHO :
323           printf("[COOKIE ECHO] ");
324           break;
325         case SCTP_COOKIE_ACK :
326           printf("[COOKIE ACK] ");
327           break;
328         case SCTP_ECN_ECHO :
329           printf("[ECN ECHO] ");
330           break;
331         case SCTP_ECN_CWR :
332           printf("[ECN CWR] ");
333           break;
334         case SCTP_SHUTDOWN_COMPLETE :
335           printf("[SHUTDOWN COMPLETE] ");
336           break;
337         case SCTP_FORWARD_CUM_TSN :
338           printf("[FOR CUM TSN] ");
339           break;
340         case SCTP_RELIABLE_CNTL :
341           printf("[REL CTRL] ");
342           break;
343         case SCTP_RELIABLE_CNTL_ACK :
344           printf("[REL CTRL ACK] ");
345           break;
346         default :
347           printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID);
348           return;
349         }
350
351         if (vflag < 2)
352           sep = ", (";
353     }
354     return;
355
356 trunc:
357     printf("[|sctp]");
358     return;
359 }