]> The Tcpdump Group git mirrors - tcpdump/blob - print-sctp.c
351a02c718925749d3baf1017027b9e5d61d018a
[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 /* Data Chuck Specific Flags */
119 #define SCTP_DATA_FRAG_MASK 0x03
120 #define SCTP_DATA_MIDDLE_FRAG 0x00
121 #define SCTP_DATA_LAST_FRAG 0x01
122 #define SCTP_DATA_FIRST_FRAG 0x02
123 #define SCTP_DATA_NOT_FRAG 0x03
124 #define SCTP_DATA_UNORDERED 0x04
125
126 #define SCTP_ADDRMAX 60
127
128 #define CHAN_HP 6704
129 #define CHAN_MP 6705
130 #define CHAN_LP 6706
131
132 /* the sctp common header */
133
134 struct sctpHeader{
135 u_int16_t source;
136 u_int16_t destination;
137 u_int32_t verificationTag;
138 u_int32_t adler32;
139 };
140
141 /* various descriptor parsers */
142
143 struct sctpChunkDesc{
144 u_int8_t chunkID;
145 u_int8_t chunkFlg;
146 u_int16_t chunkLength;
147 };
148
149 struct sctpParamDesc{
150 u_int16_t paramType;
151 u_int16_t paramLength;
152 };
153
154
155 struct sctpRelChunkDesc{
156 struct sctpChunkDesc chk;
157 u_int32_t serialNumber;
158 };
159
160 struct sctpVendorSpecificParam {
161 struct sctpParamDesc p; /* type must be 0xfffe */
162 u_int32_t vendorId; /* vendor ID from RFC 1700 */
163 u_int16_t vendorSpecificType;
164 u_int16_t vendorSpecificLen;
165 };
166
167
168 /* Structures for the control parts */
169
170
171
172 /* Sctp association init request/ack */
173
174 /* this is used for init ack, too */
175 struct sctpInitiation{
176 u_int32_t initTag; /* tag of mine */
177 u_int32_t rcvWindowCredit; /* rwnd */
178 u_int16_t NumPreopenStreams; /* OS */
179 u_int16_t MaxInboundStreams; /* MIS */
180 u_int32_t initialTSN;
181 /* optional param's follow in sctpParamDesc form */
182 };
183
184 struct sctpV4IpAddress{
185 struct sctpParamDesc p; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */
186 u_int32_t ipAddress;
187 };
188
189
190 struct sctpV6IpAddress{
191 struct sctpParamDesc p; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */
192 u_int8_t ipAddress[16];
193 };
194
195 struct sctpDNSName{
196 struct sctpParamDesc param;
197 u_int8_t name[1];
198 };
199
200
201 struct sctpCookiePreserve{
202 struct sctpParamDesc p; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */
203 u_int32_t extraTime;
204 };
205
206
207 struct sctpTimeStamp{
208 u_int32_t ts_sec;
209 u_int32_t ts_usec;
210 };
211
212 /* wire structure of my cookie */
213 struct cookieMessage{
214 u_int32_t TieTag_curTag; /* copied from assoc if present */
215 u_int32_t TieTag_hisTag; /* copied from assoc if present */
216 int32_t cookieLife; /* life I will award this cookie */
217 struct sctpTimeStamp timeEnteringState; /* the time I built cookie */
218 struct sctpInitiation initAckISent; /* the INIT-ACK that I sent to my peer */
219 u_int32_t addressWhereISent[4]; /* I make this 4 ints so I get 128bits for future */
220 int32_t addrtype; /* address type */
221 u_int16_t locScope; /* V6 local scope flag */
222 u_int16_t siteScope; /* V6 site scope flag */
223 /* at the end is tacked on the INIT chunk sent in
224 * its entirety and of course our
225 * signature.
226 */
227 };
228
229
230 /* this guy is for use when
231 * I have a initiate message gloming the
232 * things together.
233
234 */
235 struct sctpUnifiedInit{
236 struct sctpChunkDesc uh;
237 struct sctpInitiation initm;
238 };
239
240 struct sctpSendableInit{
241 struct sctpHeader mh;
242 struct sctpUnifiedInit msg;
243 };
244
245
246 /* Selective Acknowledgement
247 * has the following structure with
248 * a optional ammount of trailing int's
249 * on the last part (based on the numberOfDesc
250 * field).
251 */
252
253 struct sctpSelectiveAck{
254 u_int32_t highestConseqTSN;
255 u_int32_t updatedRwnd;
256 u_int16_t numberOfdesc;
257 u_int16_t numDupTsns;
258 };
259
260 struct sctpSelectiveFrag{
261 u_int16_t fragmentStart;
262 u_int16_t fragmentEnd;
263 };
264
265
266 struct sctpUnifiedSack{
267 struct sctpChunkDesc uh;
268 struct sctpSelectiveAck sack;
269 };
270
271 /* for both RTT request/response the
272 * following is sent
273 */
274
275 struct sctpHBrequest {
276 u_int32_t time_value_1;
277 u_int32_t time_value_2;
278 };
279
280 /* here is what I read and respond with to. */
281 struct sctpHBunified{
282 struct sctpChunkDesc hdr;
283 struct sctpParamDesc hb;
284 };
285
286
287 /* here is what I send */
288 struct sctpHBsender{
289 struct sctpChunkDesc hdr;
290 struct sctpParamDesc hb;
291 struct sctpHBrequest rtt;
292 int8_t addrFmt[SCTP_ADDRMAX];
293 u_int16_t userreq;
294 };
295
296
297
298 /* for the abort and shutdown ACK
299 * we must carry the init tag in the common header. Just the
300 * common header is all that is needed with a chunk descriptor.
301 */
302 struct sctpUnifiedAbort{
303 struct sctpChunkDesc uh;
304 };
305
306 struct sctpUnifiedAbortLight{
307 struct sctpHeader mh;
308 struct sctpChunkDesc uh;
309 };
310
311 struct sctpUnifiedAbortHeavy{
312 struct sctpHeader mh;
313 struct sctpChunkDesc uh;
314 u_int16_t causeCode;
315 u_int16_t causeLen;
316 };
317
318 /* For the graceful shutdown we must carry
319 * the tag (in common header) and the highest consequitive acking value
320 */
321 struct sctpShutdown {
322 u_int32_t TSN_Seen;
323 };
324
325 struct sctpUnifiedShutdown{
326 struct sctpChunkDesc uh;
327 struct sctpShutdown shut;
328 };
329
330 /* in the unified message we add the trailing
331 * stream id since it is the only message
332 * that is defined as a operation error.
333 */
334 struct sctpOpErrorCause{
335 u_int16_t cause;
336 u_int16_t causeLen;
337 };
338
339 struct sctpUnifiedOpError{
340 struct sctpChunkDesc uh;
341 struct sctpOpErrorCause c;
342 };
343
344 struct sctpUnifiedStreamError{
345 struct sctpHeader mh;
346 struct sctpChunkDesc uh;
347 struct sctpOpErrorCause c;
348 u_int16_t strmNum;
349 u_int16_t reserved;
350 };
351
352 struct staleCookieMsg{
353 struct sctpHeader mh;
354 struct sctpChunkDesc uh;
355 struct sctpOpErrorCause c;
356 u_int32_t moretime;
357 };
358
359 /* the following is used in all sends
360 * where nothing is needed except the
361 * chunk/type i.e. shutdownAck Abort */
362
363 struct sctpUnifiedSingleMsg{
364 struct sctpHeader mh;
365 struct sctpChunkDesc uh;
366 };
367
368 struct sctpDataPart{
369 u_int32_t TSN;
370 u_int16_t streamId;
371 u_int16_t sequence;
372 u_int32_t payloadtype;
373 };
374
375 struct sctpUnifiedDatagram{
376 struct sctpChunkDesc uh;
377 struct sctpDataPart dp;
378 };
379
380 struct sctpECN_echo{
381 struct sctpChunkDesc uh;
382 u_int32_t Lowest_TSN;
383 };
384
385
386 struct sctpCWR{
387 struct sctpChunkDesc uh;
388 u_int32_t TSN_reduced_at;
389 };
390
391 static const struct tok ForCES_channels[] = {
392 { CHAN_HP, "ForCES HP" },
393 { CHAN_MP, "ForCES MP" },
394 { CHAN_LP, "ForCES LP" },
395 { 0, NULL }
396 };
397
398 static inline int isForCES_port(u_short Port)
399 {
400 if (Port == CHAN_HP)
401 return 1;
402 if (Port == CHAN_MP)
403 return 1;
404 if (Port == CHAN_LP)
405 return 1;
406
407 return 0;
408 }
409
410 void sctp_print(netdissect_options *ndo,
411 const u_char *bp, /* beginning of sctp packet */
412 const u_char *bp2, /* beginning of enclosing */
413 u_int sctpPacketLength) /* ip packet */
414 {
415 const struct sctpHeader *sctpPktHdr;
416 const struct ip *ip;
417 #ifdef INET6
418 const struct ip6_hdr *ip6;
419 #endif
420 const void *endPacketPtr;
421 u_short sourcePort, destPort;
422 int chunkCount;
423 const struct sctpChunkDesc *chunkDescPtr;
424 const void *nextChunk;
425 const char *sep;
426 int isforces = 0;
427
428
429 sctpPktHdr = (const struct sctpHeader*) bp;
430 endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength;
431
432 if( (u_long) endPacketPtr > (u_long) ndo->ndo_snapend)
433 endPacketPtr = (const void *) ndo->ndo_snapend;
434 ip = (struct ip *)bp2;
435 #ifdef INET6
436 if (IP_V(ip) == 6)
437 ip6 = (const struct ip6_hdr *)bp2;
438 else
439 ip6 = NULL;
440 #endif /*INET6*/
441 ND_TCHECK(*sctpPktHdr);
442
443 if (sctpPacketLength < sizeof(struct sctpHeader))
444 {
445 ND_PRINT((ndo, "truncated-sctp - %ld bytes missing!",
446 (long)sctpPacketLength-sizeof(struct sctpHeader)));
447 return;
448 }
449
450 /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */
451 /* is now only as long as the payload */
452
453 sourcePort = EXTRACT_16BITS(&sctpPktHdr->source);
454 destPort = EXTRACT_16BITS(&sctpPktHdr->destination);
455
456 #ifdef INET6
457 if (ip6) {
458 ND_PRINT((ndo, "%s.%d > %s.%d: sctp",
459 ip6addr_string(&ip6->ip6_src),
460 sourcePort,
461 ip6addr_string(&ip6->ip6_dst),
462 destPort));
463 } else
464 #endif /*INET6*/
465 {
466 ND_PRINT((ndo, "%s.%d > %s.%d: sctp",
467 ipaddr_string(&ip->ip_src),
468 sourcePort,
469 ipaddr_string(&ip->ip_dst),
470 destPort));
471 }
472 fflush(stdout);
473
474 if (isForCES_port(sourcePort)) {
475 ND_PRINT((ndo, "[%s]", tok2str(ForCES_channels, NULL, sourcePort)));
476 isforces = 1;
477 }
478 if (isForCES_port(destPort)) {
479 ND_PRINT((ndo, "[%s]", tok2str(ForCES_channels, NULL, destPort)));
480 isforces = 1;
481 }
482
483 if (ndo->ndo_vflag >= 2)
484 sep = "\n\t";
485 else
486 sep = " (";
487 /* cycle through all chunks, printing information on each one */
488 for (chunkCount = 0,
489 chunkDescPtr = (const struct sctpChunkDesc *)
490 ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader));
491 chunkDescPtr != NULL &&
492 ( (const void *)
493 ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc))
494 <= endPacketPtr);
495
496 chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++)
497 {
498 u_int16_t chunkLength;
499 const u_char *chunkEnd;
500 u_int16_t align;
501
502 ND_TCHECK(*chunkDescPtr);
503 chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength);
504 if (chunkLength < sizeof(*chunkDescPtr)) {
505 ND_PRINT((ndo, "%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength));
506 break;
507 }
508
509 ND_TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength);
510 chunkEnd = ((const u_char*)chunkDescPtr + chunkLength);
511
512 align=chunkLength % 4;
513 if (align != 0)
514 align = 4 - align;
515
516 nextChunk = (const void *) (chunkEnd + align);
517
518 ND_PRINT((ndo, "%s%d) ", sep, chunkCount+1));
519 switch (chunkDescPtr->chunkID)
520 {
521 case SCTP_DATA :
522 {
523 const struct sctpDataPart *dataHdrPtr;
524
525 ND_PRINT((ndo, "[DATA] "));
526
527 if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
528 == SCTP_DATA_UNORDERED)
529 ND_PRINT((ndo, "(U)"));
530
531 if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
532 == SCTP_DATA_FIRST_FRAG)
533 ND_PRINT((ndo, "(B)"));
534
535 if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
536 == SCTP_DATA_LAST_FRAG)
537 ND_PRINT((ndo, "(E)"));
538
539 if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
540 == SCTP_DATA_UNORDERED)
541 ||
542 ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
543 == SCTP_DATA_FIRST_FRAG)
544 ||
545 ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
546 == SCTP_DATA_LAST_FRAG) )
547 ND_PRINT((ndo, " "));
548
549 dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1);
550
551 ND_PRINT((ndo, "[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN)));
552 ND_PRINT((ndo, "[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId)));
553 ND_PRINT((ndo, "[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence)));
554 ND_PRINT((ndo, "[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr->payloadtype)));
555 fflush(stdout);
556 if (isforces) {
557 const u_char *payloadPtr;
558 u_int chunksize = sizeof(struct sctpDataPart)+
559 sizeof(struct sctpChunkDesc);
560 payloadPtr = (const u_char *) (dataHdrPtr + 1);
561 if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) <
562 sizeof(struct sctpDataPart)+
563 sizeof(struct sctpChunkDesc)+1) {
564 /* Less than 1 byte of chunk payload */
565 ND_PRINT((ndo, "bogus ForCES chunk length %u]",
566 EXTRACT_16BITS(&chunkDescPtr->chunkLength)));
567 return;
568 }
569
570 forces_print(ndo, payloadPtr, EXTRACT_16BITS(&chunkDescPtr->chunkLength)- chunksize);
571 } else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */
572 /* at the command line */
573 const u_char *payloadPtr;
574
575 ND_PRINT((ndo, "[Payload"));
576
577 if (!ndo->ndo_suppress_default_print) {
578 payloadPtr = (const u_char *) (++dataHdrPtr);
579 ND_PRINT((ndo, ":"));
580 if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) <
581 sizeof(struct sctpDataPart)+
582 sizeof(struct sctpChunkDesc)+1) {
583 /* Less than 1 byte of chunk payload */
584 ND_PRINT((ndo, "bogus chunk length %u]",
585 EXTRACT_16BITS(&chunkDescPtr->chunkLength)));
586 return;
587 }
588 default_print(payloadPtr,
589 EXTRACT_16BITS(&chunkDescPtr->chunkLength) -
590 (sizeof(struct sctpDataPart)+
591 sizeof(struct sctpChunkDesc)));
592 } else
593 ND_PRINT((ndo, "]"));
594 }
595 break;
596 }
597 case SCTP_INITIATION :
598 {
599 const struct sctpInitiation *init;
600
601 ND_PRINT((ndo, "[INIT] "));
602 init=(const struct sctpInitiation*)(chunkDescPtr+1);
603 ND_PRINT((ndo, "[init tag: %u] ", EXTRACT_32BITS(&init->initTag)));
604 ND_PRINT((ndo, "[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)));
605 ND_PRINT((ndo, "[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)));
606 ND_PRINT((ndo, "[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)));
607 ND_PRINT((ndo, "[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)));
608
609 #if(0) /* ALC you can add code for optional params here */
610 if( (init+1) < chunkEnd )
611 ND_PRINT((ndo, " @@@@@ UNFINISHED @@@@@@%s\n",
612 "Optional params present, but not printed."));
613 #endif
614 break;
615 }
616 case SCTP_INITIATION_ACK :
617 {
618 const struct sctpInitiation *init;
619
620 ND_PRINT((ndo, "[INIT ACK] "));
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_SELECTIVE_ACK:
636 {
637 const struct sctpSelectiveAck *sack;
638 const struct sctpSelectiveFrag *frag;
639 int fragNo, tsnNo;
640 const u_char *dupTSN;
641
642 ND_PRINT((ndo, "[SACK] "));
643 sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1);
644 ND_PRINT((ndo, "[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN)));
645 ND_PRINT((ndo, "[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd)));
646 ND_PRINT((ndo, "[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc)));
647 ND_PRINT((ndo, "[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns)));
648
649
650 /* print gaps */
651 for (frag = ( (const struct sctpSelectiveFrag *)
652 ((const struct sctpSelectiveAck *) sack+1)),
653 fragNo=0;
654 (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc);
655 frag++, fragNo++)
656 ND_PRINT((ndo, "\n\t\t[gap ack block #%d: start = %u, end = %u] ",
657 fragNo+1,
658 EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart),
659 EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd)));
660
661
662 /* print duplicate TSNs */
663 for (dupTSN = (const u_char *)frag, tsnNo=0;
664 (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns);
665 dupTSN += 4, tsnNo++)
666 ND_PRINT((ndo, "\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
667 EXTRACT_32BITS(dupTSN)));
668
669 break;
670 }
671 case SCTP_HEARTBEAT_REQUEST :
672 ND_PRINT((ndo, "[HB REQ] "));
673 break;
674 case SCTP_HEARTBEAT_ACK :
675 ND_PRINT((ndo, "[HB ACK] "));
676 break;
677 case SCTP_ABORT_ASSOCIATION :
678 ND_PRINT((ndo, "[ABORT] "));
679 break;
680 case SCTP_SHUTDOWN :
681 ND_PRINT((ndo, "[SHUTDOWN] "));
682 break;
683 case SCTP_SHUTDOWN_ACK :
684 ND_PRINT((ndo, "[SHUTDOWN ACK] "));
685 break;
686 case SCTP_OPERATION_ERR :
687 ND_PRINT((ndo, "[OP ERR] "));
688 break;
689 case SCTP_COOKIE_ECHO :
690 ND_PRINT((ndo, "[COOKIE ECHO] "));
691 break;
692 case SCTP_COOKIE_ACK :
693 ND_PRINT((ndo, "[COOKIE ACK] "));
694 break;
695 case SCTP_ECN_ECHO :
696 ND_PRINT((ndo, "[ECN ECHO] "));
697 break;
698 case SCTP_ECN_CWR :
699 ND_PRINT((ndo, "[ECN CWR] "));
700 break;
701 case SCTP_SHUTDOWN_COMPLETE :
702 ND_PRINT((ndo, "[SHUTDOWN COMPLETE] "));
703 break;
704 case SCTP_FORWARD_CUM_TSN :
705 ND_PRINT((ndo, "[FOR CUM TSN] "));
706 break;
707 case SCTP_RELIABLE_CNTL :
708 ND_PRINT((ndo, "[REL CTRL] "));
709 break;
710 case SCTP_RELIABLE_CNTL_ACK :
711 ND_PRINT((ndo, "[REL CTRL ACK] "));
712 break;
713 default :
714 ND_PRINT((ndo, "[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID));
715 return;
716 }
717
718 if (ndo->ndo_vflag < 2)
719 sep = ", (";
720 }
721 return;
722
723 trunc:
724 ND_PRINT((ndo, "[|sctp]"));
725 }