]> The Tcpdump Group git mirrors - tcpdump/blob - print-sctp.c
When parsing information elements, check for the full length beforehand.
[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 #define NETDISSECT_REWORKED
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include <tcpdump-stdinc.h>
42
43 #include "interface.h"
44 #include "addrtoname.h"
45 #include "extract.h" /* must come after interface.h */
46 #include "ip.h"
47 #ifdef INET6
48 #include "ip6.h"
49 #endif
50
51 /* Definitions from:
52 *
53 * SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola
54 *
55 * Redistribution and use in source and binary forms, with or without
56 * modification, are permitted provided that the following conditions
57 * are met:
58 *
59 * 1. Redistributions of source code must retain the above copyright
60 * notice, this list of conditions and the following disclaimer.
61 *
62 * 2. Redistributions in binary form must reproduce the above copyright
63 * notice, this list of conditions and the following disclaimer in the
64 * documentation and/or other materials provided with the distribution.
65 *
66 * 3. Neither the name of Cisco nor of Motorola may be used
67 * to endorse or promote products derived from this software without
68 * specific prior written permission.
69 *
70 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
71 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
72 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
73 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
74 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
75 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
76 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
77 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
78 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
79 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
80 * SUCH DAMAGE.
81 *
82 * This file is part of the SCTP reference Implementation
83 *
84 *
85 * Please send any bug reports or fixes you make to one of the following email
86 * addresses:
87 *
88 * rstewar1@email.mot.com
89 * kmorneau@cisco.com
90 * qxie1@email.mot.com
91 *
92 * Any bugs reported given to us we will try to fix... any fixes shared will
93 * be incorperated into the next SCTP release.
94 */
95
96 /* The valid defines for all message
97 * types know to SCTP. 0 is reserved
98 */
99 #define SCTP_DATA 0x00
100 #define SCTP_INITIATION 0x01
101 #define SCTP_INITIATION_ACK 0x02
102 #define SCTP_SELECTIVE_ACK 0x03
103 #define SCTP_HEARTBEAT_REQUEST 0x04
104 #define SCTP_HEARTBEAT_ACK 0x05
105 #define SCTP_ABORT_ASSOCIATION 0x06
106 #define SCTP_SHUTDOWN 0x07
107 #define SCTP_SHUTDOWN_ACK 0x08
108 #define SCTP_OPERATION_ERR 0x09
109 #define SCTP_COOKIE_ECHO 0x0a
110 #define SCTP_COOKIE_ACK 0x0b
111 #define SCTP_ECN_ECHO 0x0c
112 #define SCTP_ECN_CWR 0x0d
113 #define SCTP_SHUTDOWN_COMPLETE 0x0e
114 #define SCTP_FORWARD_CUM_TSN 0xc0
115 #define SCTP_RELIABLE_CNTL 0xc1
116 #define SCTP_RELIABLE_CNTL_ACK 0xc2
117
118 static const struct tok sctp_chunkid_str[] = {
119 { SCTP_DATA, "DATA" },
120 { SCTP_INITIATION, "INIT" },
121 { SCTP_INITIATION_ACK, "INIT ACK" },
122 { SCTP_SELECTIVE_ACK, "SACK" },
123 { SCTP_HEARTBEAT_REQUEST, "HB REQ" },
124 { SCTP_HEARTBEAT_ACK, "HB ACK" },
125 { SCTP_ABORT_ASSOCIATION, "ABORT" },
126 { SCTP_SHUTDOWN, "SHUTDOWN" },
127 { SCTP_SHUTDOWN_ACK, "SHUTDOWN ACK" },
128 { SCTP_OPERATION_ERR, "OP ERR" },
129 { SCTP_COOKIE_ECHO, "COOKIE ECHO" },
130 { SCTP_COOKIE_ACK, "COOKIE ACK" },
131 { SCTP_ECN_ECHO, "ECN ECHO" },
132 { SCTP_ECN_CWR, "ECN CWR" },
133 { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" },
134 { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" },
135 { SCTP_RELIABLE_CNTL, "REL CTRL" },
136 { SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" },
137 { 0, NULL }
138 };
139
140 /* Data Chuck Specific Flags */
141 #define SCTP_DATA_FRAG_MASK 0x03
142 #define SCTP_DATA_MIDDLE_FRAG 0x00
143 #define SCTP_DATA_LAST_FRAG 0x01
144 #define SCTP_DATA_FIRST_FRAG 0x02
145 #define SCTP_DATA_NOT_FRAG 0x03
146 #define SCTP_DATA_UNORDERED 0x04
147
148 #define SCTP_ADDRMAX 60
149
150 #define CHAN_HP 6704
151 #define CHAN_MP 6705
152 #define CHAN_LP 6706
153
154 /* the sctp common header */
155
156 struct sctpHeader{
157 u_int16_t source;
158 u_int16_t destination;
159 u_int32_t verificationTag;
160 u_int32_t adler32;
161 };
162
163 /* various descriptor parsers */
164
165 struct sctpChunkDesc{
166 u_int8_t chunkID;
167 u_int8_t chunkFlg;
168 u_int16_t chunkLength;
169 };
170
171 struct sctpParamDesc{
172 u_int16_t paramType;
173 u_int16_t paramLength;
174 };
175
176
177 struct sctpRelChunkDesc{
178 struct sctpChunkDesc chk;
179 u_int32_t serialNumber;
180 };
181
182 struct sctpVendorSpecificParam {
183 struct sctpParamDesc p; /* type must be 0xfffe */
184 u_int32_t vendorId; /* vendor ID from RFC 1700 */
185 u_int16_t vendorSpecificType;
186 u_int16_t vendorSpecificLen;
187 };
188
189
190 /* Structures for the control parts */
191
192
193
194 /* Sctp association init request/ack */
195
196 /* this is used for init ack, too */
197 struct sctpInitiation{
198 u_int32_t initTag; /* tag of mine */
199 u_int32_t rcvWindowCredit; /* rwnd */
200 u_int16_t NumPreopenStreams; /* OS */
201 u_int16_t MaxInboundStreams; /* MIS */
202 u_int32_t initialTSN;
203 /* optional param's follow in sctpParamDesc form */
204 };
205
206 struct sctpV4IpAddress{
207 struct sctpParamDesc p; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */
208 u_int32_t ipAddress;
209 };
210
211
212 struct sctpV6IpAddress{
213 struct sctpParamDesc p; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */
214 u_int8_t ipAddress[16];
215 };
216
217 struct sctpDNSName{
218 struct sctpParamDesc param;
219 u_int8_t name[1];
220 };
221
222
223 struct sctpCookiePreserve{
224 struct sctpParamDesc p; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */
225 u_int32_t extraTime;
226 };
227
228
229 struct sctpTimeStamp{
230 u_int32_t ts_sec;
231 u_int32_t ts_usec;
232 };
233
234 /* wire structure of my cookie */
235 struct cookieMessage{
236 u_int32_t TieTag_curTag; /* copied from assoc if present */
237 u_int32_t TieTag_hisTag; /* copied from assoc if present */
238 int32_t cookieLife; /* life I will award this cookie */
239 struct sctpTimeStamp timeEnteringState; /* the time I built cookie */
240 struct sctpInitiation initAckISent; /* the INIT-ACK that I sent to my peer */
241 u_int32_t addressWhereISent[4]; /* I make this 4 ints so I get 128bits for future */
242 int32_t addrtype; /* address type */
243 u_int16_t locScope; /* V6 local scope flag */
244 u_int16_t siteScope; /* V6 site scope flag */
245 /* at the end is tacked on the INIT chunk sent in
246 * its entirety and of course our
247 * signature.
248 */
249 };
250
251
252 /* this guy is for use when
253 * I have a initiate message gloming the
254 * things together.
255
256 */
257 struct sctpUnifiedInit{
258 struct sctpChunkDesc uh;
259 struct sctpInitiation initm;
260 };
261
262 struct sctpSendableInit{
263 struct sctpHeader mh;
264 struct sctpUnifiedInit msg;
265 };
266
267
268 /* Selective Acknowledgement
269 * has the following structure with
270 * a optional ammount of trailing int's
271 * on the last part (based on the numberOfDesc
272 * field).
273 */
274
275 struct sctpSelectiveAck{
276 u_int32_t highestConseqTSN;
277 u_int32_t updatedRwnd;
278 u_int16_t numberOfdesc;
279 u_int16_t numDupTsns;
280 };
281
282 struct sctpSelectiveFrag{
283 u_int16_t fragmentStart;
284 u_int16_t fragmentEnd;
285 };
286
287
288 struct sctpUnifiedSack{
289 struct sctpChunkDesc uh;
290 struct sctpSelectiveAck sack;
291 };
292
293 /* for both RTT request/response the
294 * following is sent
295 */
296
297 struct sctpHBrequest {
298 u_int32_t time_value_1;
299 u_int32_t time_value_2;
300 };
301
302 /* here is what I read and respond with to. */
303 struct sctpHBunified{
304 struct sctpChunkDesc hdr;
305 struct sctpParamDesc hb;
306 };
307
308
309 /* here is what I send */
310 struct sctpHBsender{
311 struct sctpChunkDesc hdr;
312 struct sctpParamDesc hb;
313 struct sctpHBrequest rtt;
314 int8_t addrFmt[SCTP_ADDRMAX];
315 u_int16_t userreq;
316 };
317
318
319
320 /* for the abort and shutdown ACK
321 * we must carry the init tag in the common header. Just the
322 * common header is all that is needed with a chunk descriptor.
323 */
324 struct sctpUnifiedAbort{
325 struct sctpChunkDesc uh;
326 };
327
328 struct sctpUnifiedAbortLight{
329 struct sctpHeader mh;
330 struct sctpChunkDesc uh;
331 };
332
333 struct sctpUnifiedAbortHeavy{
334 struct sctpHeader mh;
335 struct sctpChunkDesc uh;
336 u_int16_t causeCode;
337 u_int16_t causeLen;
338 };
339
340 /* For the graceful shutdown we must carry
341 * the tag (in common header) and the highest consequitive acking value
342 */
343 struct sctpShutdown {
344 u_int32_t TSN_Seen;
345 };
346
347 struct sctpUnifiedShutdown{
348 struct sctpChunkDesc uh;
349 struct sctpShutdown shut;
350 };
351
352 /* in the unified message we add the trailing
353 * stream id since it is the only message
354 * that is defined as a operation error.
355 */
356 struct sctpOpErrorCause{
357 u_int16_t cause;
358 u_int16_t causeLen;
359 };
360
361 struct sctpUnifiedOpError{
362 struct sctpChunkDesc uh;
363 struct sctpOpErrorCause c;
364 };
365
366 struct sctpUnifiedStreamError{
367 struct sctpHeader mh;
368 struct sctpChunkDesc uh;
369 struct sctpOpErrorCause c;
370 u_int16_t strmNum;
371 u_int16_t reserved;
372 };
373
374 struct staleCookieMsg{
375 struct sctpHeader mh;
376 struct sctpChunkDesc uh;
377 struct sctpOpErrorCause c;
378 u_int32_t moretime;
379 };
380
381 /* the following is used in all sends
382 * where nothing is needed except the
383 * chunk/type i.e. shutdownAck Abort */
384
385 struct sctpUnifiedSingleMsg{
386 struct sctpHeader mh;
387 struct sctpChunkDesc uh;
388 };
389
390 struct sctpDataPart{
391 u_int32_t TSN;
392 u_int16_t streamId;
393 u_int16_t sequence;
394 u_int32_t payloadtype;
395 };
396
397 struct sctpUnifiedDatagram{
398 struct sctpChunkDesc uh;
399 struct sctpDataPart dp;
400 };
401
402 struct sctpECN_echo{
403 struct sctpChunkDesc uh;
404 u_int32_t Lowest_TSN;
405 };
406
407
408 struct sctpCWR{
409 struct sctpChunkDesc uh;
410 u_int32_t TSN_reduced_at;
411 };
412
413 static const struct tok ForCES_channels[] = {
414 { CHAN_HP, "ForCES HP" },
415 { CHAN_MP, "ForCES MP" },
416 { CHAN_LP, "ForCES LP" },
417 { 0, NULL }
418 };
419
420 static inline int isForCES_port(u_short Port)
421 {
422 if (Port == CHAN_HP)
423 return 1;
424 if (Port == CHAN_MP)
425 return 1;
426 if (Port == CHAN_LP)
427 return 1;
428
429 return 0;
430 }
431
432 void sctp_print(netdissect_options *ndo,
433 const u_char *bp, /* beginning of sctp packet */
434 const u_char *bp2, /* beginning of enclosing */
435 u_int sctpPacketLength) /* ip packet */
436 {
437 const struct sctpHeader *sctpPktHdr;
438 const struct ip *ip;
439 #ifdef INET6
440 const struct ip6_hdr *ip6;
441 #endif
442 const void *endPacketPtr;
443 u_short sourcePort, destPort;
444 int chunkCount;
445 const struct sctpChunkDesc *chunkDescPtr;
446 const void *nextChunk;
447 const char *sep;
448 int isforces = 0;
449
450
451 sctpPktHdr = (const struct sctpHeader*) bp;
452 endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength;
453
454 if( (u_long) endPacketPtr > (u_long) ndo->ndo_snapend)
455 endPacketPtr = (const void *) ndo->ndo_snapend;
456 ip = (struct ip *)bp2;
457 #ifdef INET6
458 if (IP_V(ip) == 6)
459 ip6 = (const struct ip6_hdr *)bp2;
460 else
461 ip6 = NULL;
462 #endif /*INET6*/
463 ND_TCHECK(*sctpPktHdr);
464
465 if (sctpPacketLength < sizeof(struct sctpHeader))
466 {
467 ND_PRINT((ndo, "truncated-sctp - %ld bytes missing!",
468 (long)sctpPacketLength-sizeof(struct sctpHeader)));
469 return;
470 }
471
472 /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */
473 /* is now only as long as the payload */
474
475 sourcePort = EXTRACT_16BITS(&sctpPktHdr->source);
476 destPort = EXTRACT_16BITS(&sctpPktHdr->destination);
477
478 #ifdef INET6
479 if (ip6) {
480 ND_PRINT((ndo, "%s.%d > %s.%d: sctp",
481 ip6addr_string(ndo, &ip6->ip6_src),
482 sourcePort,
483 ip6addr_string(ndo, &ip6->ip6_dst),
484 destPort));
485 } else
486 #endif /*INET6*/
487 {
488 ND_PRINT((ndo, "%s.%d > %s.%d: sctp",
489 ipaddr_string(ndo, &ip->ip_src),
490 sourcePort,
491 ipaddr_string(ndo, &ip->ip_dst),
492 destPort));
493 }
494
495 if (isForCES_port(sourcePort)) {
496 ND_PRINT((ndo, "[%s]", tok2str(ForCES_channels, NULL, sourcePort)));
497 isforces = 1;
498 }
499 if (isForCES_port(destPort)) {
500 ND_PRINT((ndo, "[%s]", tok2str(ForCES_channels, NULL, destPort)));
501 isforces = 1;
502 }
503
504 if (ndo->ndo_vflag >= 2)
505 sep = "\n\t";
506 else
507 sep = " (";
508 /* cycle through all chunks, printing information on each one */
509 for (chunkCount = 0,
510 chunkDescPtr = (const struct sctpChunkDesc *)
511 ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader));
512 chunkDescPtr != NULL &&
513 ( (const void *)
514 ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc))
515 <= endPacketPtr);
516
517 chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++)
518 {
519 u_int16_t chunkLength;
520 const u_char *chunkEnd;
521 u_int16_t align;
522
523 ND_TCHECK(*chunkDescPtr);
524 chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength);
525 if (chunkLength < sizeof(*chunkDescPtr)) {
526 ND_PRINT((ndo, "%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength));
527 break;
528 }
529
530 ND_TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength);
531 chunkEnd = ((const u_char*)chunkDescPtr + chunkLength);
532
533 align=chunkLength % 4;
534 if (align != 0)
535 align = 4 - align;
536
537 nextChunk = (const void *) (chunkEnd + align);
538
539 ND_PRINT((ndo, "%s%d) ", sep, chunkCount+1));
540 ND_PRINT((ndo, "[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x",
541 chunkDescPtr->chunkID)));
542 switch (chunkDescPtr->chunkID)
543 {
544 case SCTP_DATA :
545 {
546 const struct sctpDataPart *dataHdrPtr;
547
548 if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
549 == SCTP_DATA_UNORDERED)
550 ND_PRINT((ndo, "(U)"));
551
552 if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
553 == SCTP_DATA_FIRST_FRAG)
554 ND_PRINT((ndo, "(B)"));
555
556 if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
557 == SCTP_DATA_LAST_FRAG)
558 ND_PRINT((ndo, "(E)"));
559
560 if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
561 == SCTP_DATA_UNORDERED)
562 ||
563 ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
564 == SCTP_DATA_FIRST_FRAG)
565 ||
566 ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
567 == SCTP_DATA_LAST_FRAG) )
568 ND_PRINT((ndo, " "));
569
570 dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1);
571
572 ND_PRINT((ndo, "[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN)));
573 ND_PRINT((ndo, "[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId)));
574 ND_PRINT((ndo, "[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence)));
575 ND_PRINT((ndo, "[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr->payloadtype)));
576 if (isforces) {
577 const u_char *payloadPtr;
578 u_int chunksize = sizeof(struct sctpDataPart)+
579 sizeof(struct sctpChunkDesc);
580 payloadPtr = (const u_char *) (dataHdrPtr + 1);
581 if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) <
582 sizeof(struct sctpDataPart)+
583 sizeof(struct sctpChunkDesc)+1) {
584 /* Less than 1 byte of chunk payload */
585 ND_PRINT((ndo, "bogus ForCES chunk length %u]",
586 EXTRACT_16BITS(&chunkDescPtr->chunkLength)));
587 return;
588 }
589
590 forces_print(ndo, payloadPtr, EXTRACT_16BITS(&chunkDescPtr->chunkLength)- chunksize);
591 } else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */
592 /* at the command line */
593 const u_char *payloadPtr;
594
595 ND_PRINT((ndo, "[Payload"));
596
597 if (!ndo->ndo_suppress_default_print) {
598 payloadPtr = (const u_char *) (++dataHdrPtr);
599 ND_PRINT((ndo, ":"));
600 if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) <
601 sizeof(struct sctpDataPart)+
602 sizeof(struct sctpChunkDesc)+1) {
603 /* Less than 1 byte of chunk payload */
604 ND_PRINT((ndo, "bogus chunk length %u]",
605 EXTRACT_16BITS(&chunkDescPtr->chunkLength)));
606 return;
607 }
608 ND_DEFAULTPRINT(payloadPtr,
609 EXTRACT_16BITS(&chunkDescPtr->chunkLength) -
610 (sizeof(struct sctpDataPart)+
611 sizeof(struct sctpChunkDesc)));
612 } else
613 ND_PRINT((ndo, "]"));
614 }
615 break;
616 }
617 case SCTP_INITIATION :
618 {
619 const struct sctpInitiation *init;
620
621 init=(const struct sctpInitiation*)(chunkDescPtr+1);
622 ND_PRINT((ndo, "[init tag: %u] ", EXTRACT_32BITS(&init->initTag)));
623 ND_PRINT((ndo, "[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)));
624 ND_PRINT((ndo, "[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)));
625 ND_PRINT((ndo, "[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)));
626 ND_PRINT((ndo, "[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)));
627
628 #if(0) /* ALC you can add code for optional params here */
629 if( (init+1) < chunkEnd )
630 ND_PRINT((ndo, " @@@@@ UNFINISHED @@@@@@%s\n",
631 "Optional params present, but not printed."));
632 #endif
633 break;
634 }
635 case SCTP_INITIATION_ACK :
636 {
637 const struct sctpInitiation *init;
638
639 init=(const struct sctpInitiation*)(chunkDescPtr+1);
640 ND_PRINT((ndo, "[init tag: %u] ", EXTRACT_32BITS(&init->initTag)));
641 ND_PRINT((ndo, "[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)));
642 ND_PRINT((ndo, "[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)));
643 ND_PRINT((ndo, "[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)));
644 ND_PRINT((ndo, "[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)));
645
646 #if(0) /* ALC you can add code for optional params here */
647 if( (init+1) < chunkEnd )
648 ND_PRINT((ndo, " @@@@@ UNFINISHED @@@@@@%s\n",
649 "Optional params present, but not printed."));
650 #endif
651 break;
652 }
653 case SCTP_SELECTIVE_ACK:
654 {
655 const struct sctpSelectiveAck *sack;
656 const struct sctpSelectiveFrag *frag;
657 int fragNo, tsnNo;
658 const u_char *dupTSN;
659
660 sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1);
661 ND_PRINT((ndo, "[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN)));
662 ND_PRINT((ndo, "[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd)));
663 ND_PRINT((ndo, "[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc)));
664 ND_PRINT((ndo, "[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns)));
665
666
667 /* print gaps */
668 for (frag = ( (const struct sctpSelectiveFrag *)
669 ((const struct sctpSelectiveAck *) sack+1)),
670 fragNo=0;
671 (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc);
672 frag++, fragNo++)
673 ND_PRINT((ndo, "\n\t\t[gap ack block #%d: start = %u, end = %u] ",
674 fragNo+1,
675 EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart),
676 EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd)));
677
678
679 /* print duplicate TSNs */
680 for (dupTSN = (const u_char *)frag, tsnNo=0;
681 (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns);
682 dupTSN += 4, tsnNo++)
683 ND_PRINT((ndo, "\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
684 EXTRACT_32BITS(dupTSN)));
685
686 break;
687 }
688 }
689
690 if (ndo->ndo_vflag < 2)
691 sep = ", (";
692 }
693 return;
694
695 trunc:
696 ND_PRINT((ndo, "[|sctp]"));
697 }