1 /* Copyright (c) 2001 NETLAB, Temple University
2 * Copyright (c) 2001 Protocol Engineering Lab, University of Delaware
4 * Jerry Heinz <gheinz@astro.temple.edu>
5 * John Fiore <jfiore@joda.cis.temple.edu>
6 * Armando L. Caro Jr. <acaro@cis.udel.edu>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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
40 #include <tcpdump-stdinc.h>
42 #include "interface.h"
43 #include "addrtoname.h"
44 #include "extract.h" /* must come after interface.h */
52 * SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola
54 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions
58 * 1. Redistributions of source code must retain the above copyright
59 * notice, this list of conditions and the following disclaimer.
61 * 2. Redistributions in binary form must reproduce the above copyright
62 * notice, this list of conditions and the following disclaimer in the
63 * documentation and/or other materials provided with the distribution.
65 * 3. Neither the name of Cisco nor of Motorola may be used
66 * to endorse or promote products derived from this software without
67 * specific prior written permission.
69 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
81 * This file is part of the SCTP reference Implementation
84 * Please send any bug reports or fixes you make to one of the following email
87 * rstewar1@email.mot.com
91 * Any bugs reported given to us we will try to fix... any fixes shared will
92 * be incorperated into the next SCTP release.
95 /* The valid defines for all message
96 * types know to SCTP. 0 is reserved
98 #define SCTP_DATA 0x00
99 #define SCTP_INITIATION 0x01
100 #define SCTP_INITIATION_ACK 0x02
101 #define SCTP_SELECTIVE_ACK 0x03
102 #define SCTP_HEARTBEAT_REQUEST 0x04
103 #define SCTP_HEARTBEAT_ACK 0x05
104 #define SCTP_ABORT_ASSOCIATION 0x06
105 #define SCTP_SHUTDOWN 0x07
106 #define SCTP_SHUTDOWN_ACK 0x08
107 #define SCTP_OPERATION_ERR 0x09
108 #define SCTP_COOKIE_ECHO 0x0a
109 #define SCTP_COOKIE_ACK 0x0b
110 #define SCTP_ECN_ECHO 0x0c
111 #define SCTP_ECN_CWR 0x0d
112 #define SCTP_SHUTDOWN_COMPLETE 0x0e
113 #define SCTP_FORWARD_CUM_TSN 0xc0
114 #define SCTP_RELIABLE_CNTL 0xc1
115 #define SCTP_RELIABLE_CNTL_ACK 0xc2
117 static const struct tok sctp_chunkid_str
[] = {
118 { SCTP_DATA
, "DATA" },
119 { SCTP_INITIATION
, "INIT" },
120 { SCTP_INITIATION_ACK
, "INIT ACK" },
121 { SCTP_SELECTIVE_ACK
, "SACK" },
122 { SCTP_HEARTBEAT_REQUEST
, "HB REQ" },
123 { SCTP_HEARTBEAT_ACK
, "HB ACK" },
124 { SCTP_ABORT_ASSOCIATION
, "ABORT" },
125 { SCTP_SHUTDOWN
, "SHUTDOWN" },
126 { SCTP_SHUTDOWN_ACK
, "SHUTDOWN ACK" },
127 { SCTP_OPERATION_ERR
, "OP ERR" },
128 { SCTP_COOKIE_ECHO
, "COOKIE ECHO" },
129 { SCTP_COOKIE_ACK
, "COOKIE ACK" },
130 { SCTP_ECN_ECHO
, "ECN ECHO" },
131 { SCTP_ECN_CWR
, "ECN CWR" },
132 { SCTP_SHUTDOWN_COMPLETE
, "SHUTDOWN COMPLETE" },
133 { SCTP_FORWARD_CUM_TSN
, "FOR CUM TSN" },
134 { SCTP_RELIABLE_CNTL
, "REL CTRL" },
135 { SCTP_RELIABLE_CNTL_ACK
, "REL CTRL ACK" },
139 /* Data Chuck Specific Flags */
140 #define SCTP_DATA_FRAG_MASK 0x03
141 #define SCTP_DATA_MIDDLE_FRAG 0x00
142 #define SCTP_DATA_LAST_FRAG 0x01
143 #define SCTP_DATA_FIRST_FRAG 0x02
144 #define SCTP_DATA_NOT_FRAG 0x03
145 #define SCTP_DATA_UNORDERED 0x04
147 #define SCTP_ADDRMAX 60
153 /* the sctp common header */
157 uint16_t destination
;
158 uint32_t verificationTag
;
162 /* various descriptor parsers */
164 struct sctpChunkDesc
{
167 uint16_t chunkLength
;
170 struct sctpParamDesc
{
172 uint16_t paramLength
;
176 struct sctpRelChunkDesc
{
177 struct sctpChunkDesc chk
;
178 uint32_t serialNumber
;
181 struct sctpVendorSpecificParam
{
182 struct sctpParamDesc p
; /* type must be 0xfffe */
183 uint32_t vendorId
; /* vendor ID from RFC 1700 */
184 uint16_t vendorSpecificType
;
185 uint16_t vendorSpecificLen
;
189 /* Structures for the control parts */
193 /* Sctp association init request/ack */
195 /* this is used for init ack, too */
196 struct sctpInitiation
{
197 uint32_t initTag
; /* tag of mine */
198 uint32_t rcvWindowCredit
; /* rwnd */
199 uint16_t NumPreopenStreams
; /* OS */
200 uint16_t MaxInboundStreams
; /* MIS */
202 /* optional param's follow in sctpParamDesc form */
205 struct sctpV4IpAddress
{
206 struct sctpParamDesc p
; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */
211 struct sctpV6IpAddress
{
212 struct sctpParamDesc p
; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */
213 uint8_t ipAddress
[16];
217 struct sctpParamDesc param
;
222 struct sctpCookiePreserve
{
223 struct sctpParamDesc p
; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */
228 struct sctpTimeStamp
{
233 /* wire structure of my cookie */
234 struct cookieMessage
{
235 uint32_t TieTag_curTag
; /* copied from assoc if present */
236 uint32_t TieTag_hisTag
; /* copied from assoc if present */
237 int32_t cookieLife
; /* life I will award this cookie */
238 struct sctpTimeStamp timeEnteringState
; /* the time I built cookie */
239 struct sctpInitiation initAckISent
; /* the INIT-ACK that I sent to my peer */
240 uint32_t addressWhereISent
[4]; /* I make this 4 ints so I get 128bits for future */
241 int32_t addrtype
; /* address type */
242 uint16_t locScope
; /* V6 local scope flag */
243 uint16_t siteScope
; /* V6 site scope flag */
244 /* at the end is tacked on the INIT chunk sent in
245 * its entirety and of course our
251 /* this guy is for use when
252 * I have a initiate message gloming the
256 struct sctpUnifiedInit
{
257 struct sctpChunkDesc uh
;
258 struct sctpInitiation initm
;
261 struct sctpSendableInit
{
262 struct sctpHeader mh
;
263 struct sctpUnifiedInit msg
;
267 /* Selective Acknowledgement
268 * has the following structure with
269 * a optional ammount of trailing int's
270 * on the last part (based on the numberOfDesc
274 struct sctpSelectiveAck
{
275 uint32_t highestConseqTSN
;
276 uint32_t updatedRwnd
;
277 uint16_t numberOfdesc
;
281 struct sctpSelectiveFrag
{
282 uint16_t fragmentStart
;
283 uint16_t fragmentEnd
;
287 struct sctpUnifiedSack
{
288 struct sctpChunkDesc uh
;
289 struct sctpSelectiveAck sack
;
292 /* for both RTT request/response the
296 struct sctpHBrequest
{
297 uint32_t time_value_1
;
298 uint32_t time_value_2
;
301 /* here is what I read and respond with to. */
302 struct sctpHBunified
{
303 struct sctpChunkDesc hdr
;
304 struct sctpParamDesc hb
;
308 /* here is what I send */
310 struct sctpChunkDesc hdr
;
311 struct sctpParamDesc hb
;
312 struct sctpHBrequest rtt
;
313 int8_t addrFmt
[SCTP_ADDRMAX
];
319 /* for the abort and shutdown ACK
320 * we must carry the init tag in the common header. Just the
321 * common header is all that is needed with a chunk descriptor.
323 struct sctpUnifiedAbort
{
324 struct sctpChunkDesc uh
;
327 struct sctpUnifiedAbortLight
{
328 struct sctpHeader mh
;
329 struct sctpChunkDesc uh
;
332 struct sctpUnifiedAbortHeavy
{
333 struct sctpHeader mh
;
334 struct sctpChunkDesc uh
;
339 /* For the graceful shutdown we must carry
340 * the tag (in common header) and the highest consequitive acking value
342 struct sctpShutdown
{
346 struct sctpUnifiedShutdown
{
347 struct sctpChunkDesc uh
;
348 struct sctpShutdown shut
;
351 /* in the unified message we add the trailing
352 * stream id since it is the only message
353 * that is defined as a operation error.
355 struct sctpOpErrorCause
{
360 struct sctpUnifiedOpError
{
361 struct sctpChunkDesc uh
;
362 struct sctpOpErrorCause c
;
365 struct sctpUnifiedStreamError
{
366 struct sctpHeader mh
;
367 struct sctpChunkDesc uh
;
368 struct sctpOpErrorCause c
;
373 struct staleCookieMsg
{
374 struct sctpHeader mh
;
375 struct sctpChunkDesc uh
;
376 struct sctpOpErrorCause c
;
380 /* the following is used in all sends
381 * where nothing is needed except the
382 * chunk/type i.e. shutdownAck Abort */
384 struct sctpUnifiedSingleMsg
{
385 struct sctpHeader mh
;
386 struct sctpChunkDesc uh
;
393 uint32_t payloadtype
;
396 struct sctpUnifiedDatagram
{
397 struct sctpChunkDesc uh
;
398 struct sctpDataPart dp
;
402 struct sctpChunkDesc uh
;
408 struct sctpChunkDesc uh
;
409 uint32_t TSN_reduced_at
;
412 static const struct tok ForCES_channels
[] = {
413 { CHAN_HP
, "ForCES HP" },
414 { CHAN_MP
, "ForCES MP" },
415 { CHAN_LP
, "ForCES LP" },
419 /* data chunk's payload protocol identifiers */
421 #define SCTP_PPID_IUA 1
422 #define SCTP_PPID_M2UA 2
423 #define SCTP_PPID_M3UA 3
424 #define SCTP_PPID_SUA 4
425 #define SCTP_PPID_M2PA 5
426 #define SCTP_PPID_V5UA 6
427 #define SCTP_PPID_H248 7
428 #define SCTP_PPID_BICC 8
429 #define SCTP_PPID_TALI 9
430 #define SCTP_PPID_DUA 10
431 #define SCTP_PPID_ASAP 11
432 #define SCTP_PPID_ENRP 12
433 #define SCTP_PPID_H323 13
434 #define SCTP_PPID_QIPC 14
435 #define SCTP_PPID_SIMCO 15
436 #define SCTP_PPID_DDPSC 16
437 #define SCTP_PPID_DDPSSC 17
438 #define SCTP_PPID_S1AP 18
439 #define SCTP_PPID_RUA 19
440 #define SCTP_PPID_HNBAP 20
441 #define SCTP_PPID_FORCES_HP 21
442 #define SCTP_PPID_FORCES_MP 22
443 #define SCTP_PPID_FORCES_LP 23
444 #define SCTP_PPID_SBC_AP 24
445 #define SCTP_PPID_NBAP 25
447 #define SCTP_PPID_X2AP 27
449 static const struct tok PayloadProto_idents
[] = {
450 { SCTP_PPID_IUA
, "ISDN Q.921" },
451 { SCTP_PPID_M2UA
, "M2UA" },
452 { SCTP_PPID_M3UA
, "M3UA" },
453 { SCTP_PPID_SUA
, "SUA" },
454 { SCTP_PPID_M2PA
, "M2PA" },
455 { SCTP_PPID_V5UA
, "V5.2" },
456 { SCTP_PPID_H248
, "H.248" },
457 { SCTP_PPID_BICC
, "BICC" },
458 { SCTP_PPID_TALI
, "TALI" },
459 { SCTP_PPID_DUA
, "DUA" },
460 { SCTP_PPID_ASAP
, "ASAP" },
461 { SCTP_PPID_ENRP
, "ENRP" },
462 { SCTP_PPID_H323
, "H.323" },
463 { SCTP_PPID_QIPC
, "Q.IPC" },
464 { SCTP_PPID_SIMCO
, "SIMCO" },
465 { SCTP_PPID_DDPSC
, "DDPSC" },
466 { SCTP_PPID_DDPSSC
, "DDPSSC" },
467 { SCTP_PPID_S1AP
, "S1AP" },
468 { SCTP_PPID_RUA
, "RUA" },
469 { SCTP_PPID_HNBAP
, "HNBAP" },
470 { SCTP_PPID_FORCES_HP
, "ForCES HP" },
471 { SCTP_PPID_FORCES_MP
, "ForCES MP" },
472 { SCTP_PPID_FORCES_LP
, "ForCES LP" },
473 { SCTP_PPID_SBC_AP
, "SBc-AP" },
474 { SCTP_PPID_NBAP
, "NBAP" },
476 { SCTP_PPID_X2AP
, "X2AP" },
481 static inline int isForCES_port(u_short Port
)
493 void sctp_print(netdissect_options
*ndo
,
494 const u_char
*bp
, /* beginning of sctp packet */
495 const u_char
*bp2
, /* beginning of enclosing */
496 u_int sctpPacketLength
) /* ip packet */
498 const struct sctpHeader
*sctpPktHdr
;
501 const struct ip6_hdr
*ip6
;
503 const void *endPacketPtr
;
504 u_short sourcePort
, destPort
;
506 const struct sctpChunkDesc
*chunkDescPtr
;
507 const void *nextChunk
;
512 sctpPktHdr
= (const struct sctpHeader
*) bp
;
513 endPacketPtr
= (const u_char
*)sctpPktHdr
+sctpPacketLength
;
515 if( (u_long
) endPacketPtr
> (u_long
) ndo
->ndo_snapend
)
516 endPacketPtr
= (const void *) ndo
->ndo_snapend
;
517 ip
= (const struct ip
*)bp2
;
520 ip6
= (const struct ip6_hdr
*)bp2
;
524 ND_TCHECK(*sctpPktHdr
);
526 if (sctpPacketLength
< sizeof(struct sctpHeader
))
528 ND_PRINT((ndo
, "truncated-sctp - %ld bytes missing!",
529 (long)sctpPacketLength
-sizeof(struct sctpHeader
)));
533 /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */
534 /* is now only as long as the payload */
536 sourcePort
= EXTRACT_16BITS(&sctpPktHdr
->source
);
537 destPort
= EXTRACT_16BITS(&sctpPktHdr
->destination
);
541 ND_PRINT((ndo
, "%s.%d > %s.%d: sctp",
542 ip6addr_string(ndo
, &ip6
->ip6_src
),
544 ip6addr_string(ndo
, &ip6
->ip6_dst
),
549 ND_PRINT((ndo
, "%s.%d > %s.%d: sctp",
550 ipaddr_string(ndo
, &ip
->ip_src
),
552 ipaddr_string(ndo
, &ip
->ip_dst
),
556 if (isForCES_port(sourcePort
)) {
557 ND_PRINT((ndo
, "[%s]", tok2str(ForCES_channels
, NULL
, sourcePort
)));
560 if (isForCES_port(destPort
)) {
561 ND_PRINT((ndo
, "[%s]", tok2str(ForCES_channels
, NULL
, destPort
)));
565 if (ndo
->ndo_vflag
>= 2)
569 /* cycle through all chunks, printing information on each one */
571 chunkDescPtr
= (const struct sctpChunkDesc
*)
572 ((const u_char
*) sctpPktHdr
+ sizeof(struct sctpHeader
));
573 chunkDescPtr
!= NULL
&&
575 ((const u_char
*) chunkDescPtr
+ sizeof(struct sctpChunkDesc
))
578 chunkDescPtr
= (const struct sctpChunkDesc
*) nextChunk
, chunkCount
++)
580 uint16_t chunkLength
;
581 const u_char
*chunkEnd
;
584 ND_TCHECK(*chunkDescPtr
);
585 chunkLength
= EXTRACT_16BITS(&chunkDescPtr
->chunkLength
);
586 if (chunkLength
< sizeof(*chunkDescPtr
)) {
587 ND_PRINT((ndo
, "%s%d) [Bad chunk length %u]", sep
, chunkCount
+1, chunkLength
));
591 ND_TCHECK2(*((const uint8_t *)chunkDescPtr
), chunkLength
);
592 chunkEnd
= ((const u_char
*)chunkDescPtr
+ chunkLength
);
594 align
=chunkLength
% 4;
598 nextChunk
= (const void *) (chunkEnd
+ align
);
600 ND_PRINT((ndo
, "%s%d) ", sep
, chunkCount
+1));
601 ND_PRINT((ndo
, "[%s] ", tok2str(sctp_chunkid_str
, "Unknown chunk type: 0x%x",
602 chunkDescPtr
->chunkID
)));
603 switch (chunkDescPtr
->chunkID
)
607 const struct sctpDataPart
*dataHdrPtr
;
609 const u_char
*payloadPtr
;
612 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_UNORDERED
)
613 == SCTP_DATA_UNORDERED
)
614 ND_PRINT((ndo
, "(U)"));
616 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_FIRST_FRAG
)
617 == SCTP_DATA_FIRST_FRAG
)
618 ND_PRINT((ndo
, "(B)"));
620 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_LAST_FRAG
)
621 == SCTP_DATA_LAST_FRAG
)
622 ND_PRINT((ndo
, "(E)"));
624 if( ((chunkDescPtr
->chunkFlg
& SCTP_DATA_UNORDERED
)
625 == SCTP_DATA_UNORDERED
)
627 ((chunkDescPtr
->chunkFlg
& SCTP_DATA_FIRST_FRAG
)
628 == SCTP_DATA_FIRST_FRAG
)
630 ((chunkDescPtr
->chunkFlg
& SCTP_DATA_LAST_FRAG
)
631 == SCTP_DATA_LAST_FRAG
) )
632 ND_PRINT((ndo
, " "));
634 dataHdrPtr
=(const struct sctpDataPart
*)(chunkDescPtr
+1);
636 ppid
= EXTRACT_32BITS(&dataHdrPtr
->payloadtype
);
637 ND_PRINT((ndo
, "[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr
->TSN
)));
638 ND_PRINT((ndo
, "[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr
->streamId
)));
639 ND_PRINT((ndo
, "[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr
->sequence
)));
640 ND_PRINT((ndo
, "[PPID %s] ",
641 tok2str(PayloadProto_idents
, "0x%x", ppid
)));
644 isforces
= (ppid
== SCTP_PPID_FORCES_HP
) ||
645 (ppid
== SCTP_PPID_FORCES_MP
) ||
646 (ppid
== SCTP_PPID_FORCES_LP
);
649 payloadPtr
= (const u_char
*) (dataHdrPtr
+ 1);
650 if (EXTRACT_16BITS(&chunkDescPtr
->chunkLength
) <
651 sizeof(struct sctpDataPart
) + sizeof(struct sctpChunkDesc
) + 1) {
652 ND_PRINT((ndo
, "bogus chunk length %u]", EXTRACT_16BITS(&chunkDescPtr
->chunkLength
)));
656 payload_size
= EXTRACT_16BITS(&chunkDescPtr
->chunkLength
) -
657 (sizeof(struct sctpDataPart
) + sizeof(struct sctpChunkDesc
));
660 forces_print(ndo
, payloadPtr
, payload_size
);
661 } else if (ndo
->ndo_vflag
>= 2) { /* if verbose output is specified */
662 /* at the command line */
664 case SCTP_PPID_M3UA
:
665 m3ua_print(ndo
, payloadPtr
, payload_size
);
668 ND_PRINT((ndo
, "[Payload"));
669 if (!ndo
->ndo_suppress_default_print
) {
670 ND_PRINT((ndo
, ":"));
671 ND_DEFAULTPRINT(payloadPtr
, payload_size
);
673 ND_PRINT((ndo
, "]"));
679 case SCTP_INITIATION
:
681 const struct sctpInitiation
*init
;
683 init
=(const struct sctpInitiation
*)(chunkDescPtr
+1);
684 ND_PRINT((ndo
, "[init tag: %u] ", EXTRACT_32BITS(&init
->initTag
)));
685 ND_PRINT((ndo
, "[rwnd: %u] ", EXTRACT_32BITS(&init
->rcvWindowCredit
)));
686 ND_PRINT((ndo
, "[OS: %u] ", EXTRACT_16BITS(&init
->NumPreopenStreams
)));
687 ND_PRINT((ndo
, "[MIS: %u] ", EXTRACT_16BITS(&init
->MaxInboundStreams
)));
688 ND_PRINT((ndo
, "[init TSN: %u] ", EXTRACT_32BITS(&init
->initialTSN
)));
690 #if(0) /* ALC you can add code for optional params here */
691 if( (init
+1) < chunkEnd
)
692 ND_PRINT((ndo
, " @@@@@ UNFINISHED @@@@@@%s\n",
693 "Optional params present, but not printed."));
697 case SCTP_INITIATION_ACK
:
699 const struct sctpInitiation
*init
;
701 init
=(const struct sctpInitiation
*)(chunkDescPtr
+1);
702 ND_PRINT((ndo
, "[init tag: %u] ", EXTRACT_32BITS(&init
->initTag
)));
703 ND_PRINT((ndo
, "[rwnd: %u] ", EXTRACT_32BITS(&init
->rcvWindowCredit
)));
704 ND_PRINT((ndo
, "[OS: %u] ", EXTRACT_16BITS(&init
->NumPreopenStreams
)));
705 ND_PRINT((ndo
, "[MIS: %u] ", EXTRACT_16BITS(&init
->MaxInboundStreams
)));
706 ND_PRINT((ndo
, "[init TSN: %u] ", EXTRACT_32BITS(&init
->initialTSN
)));
708 #if(0) /* ALC you can add code for optional params here */
709 if( (init
+1) < chunkEnd
)
710 ND_PRINT((ndo
, " @@@@@ UNFINISHED @@@@@@%s\n",
711 "Optional params present, but not printed."));
715 case SCTP_SELECTIVE_ACK
:
717 const struct sctpSelectiveAck
*sack
;
718 const struct sctpSelectiveFrag
*frag
;
720 const u_char
*dupTSN
;
722 sack
=(const struct sctpSelectiveAck
*)(chunkDescPtr
+1);
723 ND_PRINT((ndo
, "[cum ack %u] ", EXTRACT_32BITS(&sack
->highestConseqTSN
)));
724 ND_PRINT((ndo
, "[a_rwnd %u] ", EXTRACT_32BITS(&sack
->updatedRwnd
)));
725 ND_PRINT((ndo
, "[#gap acks %u] ", EXTRACT_16BITS(&sack
->numberOfdesc
)));
726 ND_PRINT((ndo
, "[#dup tsns %u] ", EXTRACT_16BITS(&sack
->numDupTsns
)));
730 for (frag
= ( (const struct sctpSelectiveFrag
*)
731 ((const struct sctpSelectiveAck
*) sack
+1)),
733 (const void *)frag
< nextChunk
&& fragNo
< EXTRACT_16BITS(&sack
->numberOfdesc
);
735 ND_PRINT((ndo
, "\n\t\t[gap ack block #%d: start = %u, end = %u] ",
737 EXTRACT_32BITS(&sack
->highestConseqTSN
) + EXTRACT_16BITS(&frag
->fragmentStart
),
738 EXTRACT_32BITS(&sack
->highestConseqTSN
) + EXTRACT_16BITS(&frag
->fragmentEnd
)));
741 /* print duplicate TSNs */
742 for (dupTSN
= (const u_char
*)frag
, tsnNo
=0;
743 (const void *) dupTSN
< nextChunk
&& tsnNo
<EXTRACT_16BITS(&sack
->numDupTsns
);
744 dupTSN
+= 4, tsnNo
++)
745 ND_PRINT((ndo
, "\n\t\t[dup TSN #%u: %u] ", tsnNo
+1,
746 EXTRACT_32BITS(dupTSN
)));
752 if (ndo
->ndo_vflag
< 2)
758 ND_PRINT((ndo
, "[|sctp]"));