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