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