installer - Several improvements
[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.21 2007-09-13 18:03:49 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 #define CHAN_HP 6704
63 #define CHAN_MP 6705
64 #define CHAN_LP 6706
65
66 struct tok ForCES_channels[] = {
67         { CHAN_HP, "ForCES HP" },
68         { CHAN_MP, "ForCES MP" },
69         { CHAN_LP, "ForCES LP" },
70         { 0, NULL }
71 };
72
73 static inline int isForCES_port(u_short Port)
74 {
75         if (Port == CHAN_HP)
76                 return 1;
77         if (Port == CHAN_MP)
78                 return 1;
79         if (Port == CHAN_LP)
80                 return 1;
81
82         return 0;
83 }
84
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 */
88 {
89   const struct sctpHeader *sctpPktHdr;
90   const struct ip *ip;
91 #ifdef INET6
92   const struct ip6_hdr *ip6;
93 #endif
94   const void *endPacketPtr;
95   u_short sourcePort, destPort;
96   int chunkCount;
97   const struct sctpChunkDesc *chunkDescPtr;
98   const void *nextChunk;
99   const char *sep;
100   int isforces = 0;
101
102
103   sctpPktHdr = (const struct sctpHeader*) bp;
104   endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength;
105
106   if( (u_long) endPacketPtr > (u_long) snapend)
107     endPacketPtr = (const void *) snapend;
108   ip = (struct ip *)bp2;
109 #ifdef INET6
110   if (IP_V(ip) == 6)
111     ip6 = (const struct ip6_hdr *)bp2;
112   else
113     ip6 = NULL;
114 #endif /*INET6*/
115   TCHECK(*sctpPktHdr);
116
117   if (sctpPacketLength < sizeof(struct sctpHeader))
118     {
119       (void)printf("truncated-sctp - %ld bytes missing!",
120                    (long)sctpPacketLength-sizeof(struct sctpHeader));
121       return;
122     }
123
124   /*    sctpPacketLength -= sizeof(struct sctpHeader);  packet length  */
125   /*                          is now only as long as the payload  */
126
127   sourcePort = EXTRACT_16BITS(&sctpPktHdr->source);
128   destPort = EXTRACT_16BITS(&sctpPktHdr->destination);
129
130 #ifdef INET6
131   if (ip6) {
132     (void)printf("%s.%d > %s.%d: sctp",
133       ip6addr_string(&ip6->ip6_src),
134       sourcePort,
135       ip6addr_string(&ip6->ip6_dst),
136       destPort);
137   } else
138 #endif /*INET6*/
139   {
140     (void)printf("%s.%d > %s.%d: sctp",
141       ipaddr_string(&ip->ip_src),
142       sourcePort,
143       ipaddr_string(&ip->ip_dst),
144       destPort);
145   }
146   fflush(stdout);
147
148   if (isForCES_port(sourcePort)) {
149          printf("[%s]", tok2str(ForCES_channels, NULL, sourcePort));
150          isforces = 1;
151   }
152   if (isForCES_port(destPort)) {
153          printf("[%s]", tok2str(ForCES_channels, NULL, destPort));
154          isforces = 1;
155   }
156
157   if (vflag >= 2)
158     sep = "\n\t";
159   else
160     sep = " (";
161   /* cycle through all chunks, printing information on each one */
162   for (chunkCount = 0,
163          chunkDescPtr = (const struct sctpChunkDesc *)
164             ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader));
165        chunkDescPtr != NULL &&
166          ( (const void *)
167             ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc))
168            <= endPacketPtr);
169
170        chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++)
171     {
172       u_int16_t chunkLength;
173       const u_char *chunkEnd;
174       u_int16_t align;
175
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);
180         break;
181       }
182
183       TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength);
184       chunkEnd = ((const u_char*)chunkDescPtr + chunkLength);
185
186       align=chunkLength % 4;
187       if (align != 0)
188         align = 4 - align;
189
190       nextChunk = (const void *) (chunkEnd + align);
191
192       printf("%s%d) ", sep, chunkCount+1);
193       switch (chunkDescPtr->chunkID)
194         {
195         case SCTP_DATA :
196           {
197             const struct sctpDataPart *dataHdrPtr;
198
199             printf("[DATA] ");
200
201             if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
202                 == SCTP_DATA_UNORDERED)
203               printf("(U)");
204
205             if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
206                 == SCTP_DATA_FIRST_FRAG)
207               printf("(B)");
208
209             if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
210                 == SCTP_DATA_LAST_FRAG)
211               printf("(E)");
212
213             if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
214                  == SCTP_DATA_UNORDERED)
215                 ||
216                 ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
217                  == SCTP_DATA_FIRST_FRAG)
218                 ||
219                 ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
220                  == SCTP_DATA_LAST_FRAG) )
221               printf(" ");
222
223             dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1);
224
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));
229             fflush(stdout);
230             if (isforces) {
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));
241                         return;
242                 }
243
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;
248
249                 printf("[Payload");
250
251                 if (!suppress_default_print) {
252                         payloadPtr = (const u_char *) (++dataHdrPtr);
253                         printf(":");
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));
260                                 return;
261                         }
262                         default_print(payloadPtr,
263                               EXTRACT_16BITS(&chunkDescPtr->chunkLength) -
264                               (sizeof(struct sctpDataPart)+
265                               sizeof(struct sctpChunkDesc)));
266                 } else
267                         printf("]");
268               }
269             break;
270           }
271         case SCTP_INITIATION :
272           {
273             const struct sctpInitiation *init;
274
275             printf("[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));
282
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.");
287 #endif
288             break;
289           }
290         case SCTP_INITIATION_ACK :
291           {
292             const struct sctpInitiation *init;
293
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));
301
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.");
306 #endif
307             break;
308           }
309         case SCTP_SELECTIVE_ACK:
310           {
311             const struct sctpSelectiveAck *sack;
312             const struct sctpSelectiveFrag *frag;
313             int fragNo, tsnNo;
314             const u_char *dupTSN;
315
316             printf("[SACK] ");
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));
322
323
324             /* print gaps */
325             for (frag = ( (const struct sctpSelectiveFrag *)
326                           ((const struct sctpSelectiveAck *) sack+1)),
327                    fragNo=0;
328                  (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc);
329                  frag++, fragNo++)
330               printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ",
331                      fragNo+1,
332                      EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart),
333                      EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd));
334
335
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));
342
343             break;
344           }
345         case SCTP_HEARTBEAT_REQUEST :
346           {
347             const struct sctpHBsender *hb;
348
349             hb=(const struct sctpHBsender*)chunkDescPtr;
350
351             printf("[HB REQ] ");
352
353             break;
354           }
355         case SCTP_HEARTBEAT_ACK :
356           printf("[HB ACK] ");
357           break;
358         case SCTP_ABORT_ASSOCIATION :
359           printf("[ABORT] ");
360           break;
361         case SCTP_SHUTDOWN :
362           printf("[SHUTDOWN] ");
363           break;
364         case SCTP_SHUTDOWN_ACK :
365           printf("[SHUTDOWN ACK] ");
366           break;
367         case SCTP_OPERATION_ERR :
368           printf("[OP ERR] ");
369           break;
370         case SCTP_COOKIE_ECHO :
371           printf("[COOKIE ECHO] ");
372           break;
373         case SCTP_COOKIE_ACK :
374           printf("[COOKIE ACK] ");
375           break;
376         case SCTP_ECN_ECHO :
377           printf("[ECN ECHO] ");
378           break;
379         case SCTP_ECN_CWR :
380           printf("[ECN CWR] ");
381           break;
382         case SCTP_SHUTDOWN_COMPLETE :
383           printf("[SHUTDOWN COMPLETE] ");
384           break;
385         case SCTP_FORWARD_CUM_TSN :
386           printf("[FOR CUM TSN] ");
387           break;
388         case SCTP_RELIABLE_CNTL :
389           printf("[REL CTRL] ");
390           break;
391         case SCTP_RELIABLE_CNTL_ACK :
392           printf("[REL CTRL ACK] ");
393           break;
394         default :
395           printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID);
396           return;
397         }
398
399         if (vflag < 2)
400           sep = ", (";
401     }
402     return;
403
404 trunc:
405     printf("[|sctp]");
406     return;
407 }