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>
47 #include "interface.h"
48 #include "addrtoname.h"
49 #include "extract.h" /* must come after interface.h */
57 * SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola
59 * Redistribution and use in source and binary forms, with or without
60 * modification, are permitted provided that the following conditions
63 * 1. Redistributions of source code must retain the above copyright
64 * notice, this list of conditions and the following disclaimer.
66 * 2. Redistributions in binary form must reproduce the above copyright
67 * notice, this list of conditions and the following disclaimer in the
68 * documentation and/or other materials provided with the distribution.
70 * 3. Neither the name of Cisco nor of Motorola may be used
71 * to endorse or promote products derived from this software without
72 * specific prior written permission.
74 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
75 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
76 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
77 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
78 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
79 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
80 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
81 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
82 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
83 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
86 * This file is part of the SCTP reference Implementation
89 * Please send any bug reports or fixes you make to one of the following email
92 * rstewar1@email.mot.com
96 * Any bugs reported given to us we will try to fix... any fixes shared will
97 * be incorperated into the next SCTP release.
100 /* The valid defines for all message
101 * types know to SCTP. 0 is reserved
103 #define SCTP_DATA 0x00
104 #define SCTP_INITIATION 0x01
105 #define SCTP_INITIATION_ACK 0x02
106 #define SCTP_SELECTIVE_ACK 0x03
107 #define SCTP_HEARTBEAT_REQUEST 0x04
108 #define SCTP_HEARTBEAT_ACK 0x05
109 #define SCTP_ABORT_ASSOCIATION 0x06
110 #define SCTP_SHUTDOWN 0x07
111 #define SCTP_SHUTDOWN_ACK 0x08
112 #define SCTP_OPERATION_ERR 0x09
113 #define SCTP_COOKIE_ECHO 0x0a
114 #define SCTP_COOKIE_ACK 0x0b
115 #define SCTP_ECN_ECHO 0x0c
116 #define SCTP_ECN_CWR 0x0d
117 #define SCTP_SHUTDOWN_COMPLETE 0x0e
118 #define SCTP_FORWARD_CUM_TSN 0xc0
119 #define SCTP_RELIABLE_CNTL 0xc1
120 #define SCTP_RELIABLE_CNTL_ACK 0xc2
122 /* Data Chuck Specific Flags */
123 #define SCTP_DATA_FRAG_MASK 0x03
124 #define SCTP_DATA_MIDDLE_FRAG 0x00
125 #define SCTP_DATA_LAST_FRAG 0x01
126 #define SCTP_DATA_FIRST_FRAG 0x02
127 #define SCTP_DATA_NOT_FRAG 0x03
128 #define SCTP_DATA_UNORDERED 0x04
130 #define SCTP_ADDRMAX 60
136 /* the sctp common header */
140 u_int16_t destination
;
141 u_int32_t verificationTag
;
145 /* various descriptor parsers */
147 struct sctpChunkDesc
{
150 u_int16_t chunkLength
;
153 struct sctpParamDesc
{
155 u_int16_t paramLength
;
159 struct sctpRelChunkDesc
{
160 struct sctpChunkDesc chk
;
161 u_int32_t serialNumber
;
164 struct sctpVendorSpecificParam
{
165 struct sctpParamDesc p
; /* type must be 0xfffe */
166 u_int32_t vendorId
; /* vendor ID from RFC 1700 */
167 u_int16_t vendorSpecificType
;
168 u_int16_t vendorSpecificLen
;
172 /* Structures for the control parts */
176 /* Sctp association init request/ack */
178 /* this is used for init ack, too */
179 struct sctpInitiation
{
180 u_int32_t initTag
; /* tag of mine */
181 u_int32_t rcvWindowCredit
; /* rwnd */
182 u_int16_t NumPreopenStreams
; /* OS */
183 u_int16_t MaxInboundStreams
; /* MIS */
184 u_int32_t initialTSN
;
185 /* optional param's follow in sctpParamDesc form */
188 struct sctpV4IpAddress
{
189 struct sctpParamDesc p
; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */
194 struct sctpV6IpAddress
{
195 struct sctpParamDesc p
; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */
196 u_int8_t ipAddress
[16];
200 struct sctpParamDesc param
;
205 struct sctpCookiePreserve
{
206 struct sctpParamDesc p
; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */
211 struct sctpTimeStamp
{
216 /* wire structure of my cookie */
217 struct cookieMessage
{
218 u_int32_t TieTag_curTag
; /* copied from assoc if present */
219 u_int32_t TieTag_hisTag
; /* copied from assoc if present */
220 int32_t cookieLife
; /* life I will award this cookie */
221 struct sctpTimeStamp timeEnteringState
; /* the time I built cookie */
222 struct sctpInitiation initAckISent
; /* the INIT-ACK that I sent to my peer */
223 u_int32_t addressWhereISent
[4]; /* I make this 4 ints so I get 128bits for future */
224 int32_t addrtype
; /* address type */
225 u_int16_t locScope
; /* V6 local scope flag */
226 u_int16_t siteScope
; /* V6 site scope flag */
227 /* at the end is tacked on the INIT chunk sent in
228 * its entirety and of course our
234 /* this guy is for use when
235 * I have a initiate message gloming the
239 struct sctpUnifiedInit
{
240 struct sctpChunkDesc uh
;
241 struct sctpInitiation initm
;
244 struct sctpSendableInit
{
245 struct sctpHeader mh
;
246 struct sctpUnifiedInit msg
;
250 /* Selective Acknowledgement
251 * has the following structure with
252 * a optional ammount of trailing int's
253 * on the last part (based on the numberOfDesc
257 struct sctpSelectiveAck
{
258 u_int32_t highestConseqTSN
;
259 u_int32_t updatedRwnd
;
260 u_int16_t numberOfdesc
;
261 u_int16_t numDupTsns
;
264 struct sctpSelectiveFrag
{
265 u_int16_t fragmentStart
;
266 u_int16_t fragmentEnd
;
270 struct sctpUnifiedSack
{
271 struct sctpChunkDesc uh
;
272 struct sctpSelectiveAck sack
;
275 /* for both RTT request/response the
279 struct sctpHBrequest
{
280 u_int32_t time_value_1
;
281 u_int32_t time_value_2
;
284 /* here is what I read and respond with to. */
285 struct sctpHBunified
{
286 struct sctpChunkDesc hdr
;
287 struct sctpParamDesc hb
;
291 /* here is what I send */
293 struct sctpChunkDesc hdr
;
294 struct sctpParamDesc hb
;
295 struct sctpHBrequest rtt
;
296 int8_t addrFmt
[SCTP_ADDRMAX
];
302 /* for the abort and shutdown ACK
303 * we must carry the init tag in the common header. Just the
304 * common header is all that is needed with a chunk descriptor.
306 struct sctpUnifiedAbort
{
307 struct sctpChunkDesc uh
;
310 struct sctpUnifiedAbortLight
{
311 struct sctpHeader mh
;
312 struct sctpChunkDesc uh
;
315 struct sctpUnifiedAbortHeavy
{
316 struct sctpHeader mh
;
317 struct sctpChunkDesc uh
;
322 /* For the graceful shutdown we must carry
323 * the tag (in common header) and the highest consequitive acking value
325 struct sctpShutdown
{
329 struct sctpUnifiedShutdown
{
330 struct sctpChunkDesc uh
;
331 struct sctpShutdown shut
;
334 /* in the unified message we add the trailing
335 * stream id since it is the only message
336 * that is defined as a operation error.
338 struct sctpOpErrorCause
{
343 struct sctpUnifiedOpError
{
344 struct sctpChunkDesc uh
;
345 struct sctpOpErrorCause c
;
348 struct sctpUnifiedStreamError
{
349 struct sctpHeader mh
;
350 struct sctpChunkDesc uh
;
351 struct sctpOpErrorCause c
;
356 struct staleCookieMsg
{
357 struct sctpHeader mh
;
358 struct sctpChunkDesc uh
;
359 struct sctpOpErrorCause c
;
363 /* the following is used in all sends
364 * where nothing is needed except the
365 * chunk/type i.e. shutdownAck Abort */
367 struct sctpUnifiedSingleMsg
{
368 struct sctpHeader mh
;
369 struct sctpChunkDesc uh
;
376 u_int32_t payloadtype
;
379 struct sctpUnifiedDatagram
{
380 struct sctpChunkDesc uh
;
381 struct sctpDataPart dp
;
385 struct sctpChunkDesc uh
;
386 u_int32_t Lowest_TSN
;
391 struct sctpChunkDesc uh
;
392 u_int32_t TSN_reduced_at
;
395 static const struct tok ForCES_channels
[] = {
396 { CHAN_HP
, "ForCES HP" },
397 { CHAN_MP
, "ForCES MP" },
398 { CHAN_LP
, "ForCES LP" },
402 static inline int isForCES_port(u_short Port
)
414 void sctp_print(const u_char
*bp
, /* beginning of sctp packet */
415 const u_char
*bp2
, /* beginning of enclosing */
416 u_int sctpPacketLength
) /* ip packet */
418 const struct sctpHeader
*sctpPktHdr
;
421 const struct ip6_hdr
*ip6
;
423 const void *endPacketPtr
;
424 u_short sourcePort
, destPort
;
426 const struct sctpChunkDesc
*chunkDescPtr
;
427 const void *nextChunk
;
432 sctpPktHdr
= (const struct sctpHeader
*) bp
;
433 endPacketPtr
= (const u_char
*)sctpPktHdr
+sctpPacketLength
;
435 if( (u_long
) endPacketPtr
> (u_long
) snapend
)
436 endPacketPtr
= (const void *) snapend
;
437 ip
= (struct ip
*)bp2
;
440 ip6
= (const struct ip6_hdr
*)bp2
;
446 if (sctpPacketLength
< sizeof(struct sctpHeader
))
448 (void)printf("truncated-sctp - %ld bytes missing!",
449 (long)sctpPacketLength
-sizeof(struct sctpHeader
));
453 /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */
454 /* is now only as long as the payload */
456 sourcePort
= EXTRACT_16BITS(&sctpPktHdr
->source
);
457 destPort
= EXTRACT_16BITS(&sctpPktHdr
->destination
);
461 (void)printf("%s.%d > %s.%d: sctp",
462 ip6addr_string(&ip6
->ip6_src
),
464 ip6addr_string(&ip6
->ip6_dst
),
469 (void)printf("%s.%d > %s.%d: sctp",
470 ipaddr_string(&ip
->ip_src
),
472 ipaddr_string(&ip
->ip_dst
),
477 if (isForCES_port(sourcePort
)) {
478 printf("[%s]", tok2str(ForCES_channels
, NULL
, sourcePort
));
481 if (isForCES_port(destPort
)) {
482 printf("[%s]", tok2str(ForCES_channels
, NULL
, destPort
));
490 /* cycle through all chunks, printing information on each one */
492 chunkDescPtr
= (const struct sctpChunkDesc
*)
493 ((const u_char
*) sctpPktHdr
+ sizeof(struct sctpHeader
));
494 chunkDescPtr
!= NULL
&&
496 ((const u_char
*) chunkDescPtr
+ sizeof(struct sctpChunkDesc
))
499 chunkDescPtr
= (const struct sctpChunkDesc
*) nextChunk
, chunkCount
++)
501 u_int16_t chunkLength
;
502 const u_char
*chunkEnd
;
505 TCHECK(*chunkDescPtr
);
506 chunkLength
= EXTRACT_16BITS(&chunkDescPtr
->chunkLength
);
507 if (chunkLength
< sizeof(*chunkDescPtr
)) {
508 printf("%s%d) [Bad chunk length %u]", sep
, chunkCount
+1, chunkLength
);
512 TCHECK2(*((u_int8_t
*)chunkDescPtr
), chunkLength
);
513 chunkEnd
= ((const u_char
*)chunkDescPtr
+ chunkLength
);
515 align
=chunkLength
% 4;
519 nextChunk
= (const void *) (chunkEnd
+ align
);
521 printf("%s%d) ", sep
, chunkCount
+1);
522 switch (chunkDescPtr
->chunkID
)
526 const struct sctpDataPart
*dataHdrPtr
;
530 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_UNORDERED
)
531 == SCTP_DATA_UNORDERED
)
534 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_FIRST_FRAG
)
535 == SCTP_DATA_FIRST_FRAG
)
538 if ((chunkDescPtr
->chunkFlg
& SCTP_DATA_LAST_FRAG
)
539 == SCTP_DATA_LAST_FRAG
)
542 if( ((chunkDescPtr
->chunkFlg
& SCTP_DATA_UNORDERED
)
543 == SCTP_DATA_UNORDERED
)
545 ((chunkDescPtr
->chunkFlg
& SCTP_DATA_FIRST_FRAG
)
546 == SCTP_DATA_FIRST_FRAG
)
548 ((chunkDescPtr
->chunkFlg
& SCTP_DATA_LAST_FRAG
)
549 == SCTP_DATA_LAST_FRAG
) )
552 dataHdrPtr
=(const struct sctpDataPart
*)(chunkDescPtr
+1);
554 printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr
->TSN
));
555 printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr
->streamId
));
556 printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr
->sequence
));
557 printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr
->payloadtype
));
560 const u_char
*payloadPtr
;
561 u_int chunksize
= sizeof(struct sctpDataPart
)+
562 sizeof(struct sctpChunkDesc
);
563 payloadPtr
= (const u_char
*) (dataHdrPtr
+ 1);
564 if (EXTRACT_16BITS(&chunkDescPtr
->chunkLength
) <
565 sizeof(struct sctpDataPart
)+
566 sizeof(struct sctpChunkDesc
)+1) {
567 /* Less than 1 byte of chunk payload */
568 printf("bogus ForCES chunk length %u]",
569 EXTRACT_16BITS(&chunkDescPtr
->chunkLength
));
573 forces_print(payloadPtr
, EXTRACT_16BITS(&chunkDescPtr
->chunkLength
)- chunksize
);
574 } else if (vflag
>= 2) { /* if verbose output is specified */
575 /* at the command line */
576 const u_char
*payloadPtr
;
580 if (!suppress_default_print
) {
581 payloadPtr
= (const u_char
*) (++dataHdrPtr
);
583 if (EXTRACT_16BITS(&chunkDescPtr
->chunkLength
) <
584 sizeof(struct sctpDataPart
)+
585 sizeof(struct sctpChunkDesc
)+1) {
586 /* Less than 1 byte of chunk payload */
587 printf("bogus chunk length %u]",
588 EXTRACT_16BITS(&chunkDescPtr
->chunkLength
));
591 default_print(payloadPtr
,
592 EXTRACT_16BITS(&chunkDescPtr
->chunkLength
) -
593 (sizeof(struct sctpDataPart
)+
594 sizeof(struct sctpChunkDesc
)));
600 case SCTP_INITIATION
:
602 const struct sctpInitiation
*init
;
605 init
=(const struct sctpInitiation
*)(chunkDescPtr
+1);
606 printf("[init tag: %u] ", EXTRACT_32BITS(&init
->initTag
));
607 printf("[rwnd: %u] ", EXTRACT_32BITS(&init
->rcvWindowCredit
));
608 printf("[OS: %u] ", EXTRACT_16BITS(&init
->NumPreopenStreams
));
609 printf("[MIS: %u] ", EXTRACT_16BITS(&init
->MaxInboundStreams
));
610 printf("[init TSN: %u] ", EXTRACT_32BITS(&init
->initialTSN
));
612 #if(0) /* ALC you can add code for optional params here */
613 if( (init
+1) < chunkEnd
)
614 printf(" @@@@@ UNFINISHED @@@@@@%s\n",
615 "Optional params present, but not printed.");
619 case SCTP_INITIATION_ACK
:
621 const struct sctpInitiation
*init
;
623 printf("[INIT ACK] ");
624 init
=(const struct sctpInitiation
*)(chunkDescPtr
+1);
625 printf("[init tag: %u] ", EXTRACT_32BITS(&init
->initTag
));
626 printf("[rwnd: %u] ", EXTRACT_32BITS(&init
->rcvWindowCredit
));
627 printf("[OS: %u] ", EXTRACT_16BITS(&init
->NumPreopenStreams
));
628 printf("[MIS: %u] ", EXTRACT_16BITS(&init
->MaxInboundStreams
));
629 printf("[init TSN: %u] ", EXTRACT_32BITS(&init
->initialTSN
));
631 #if(0) /* ALC you can add code for optional params here */
632 if( (init
+1) < chunkEnd
)
633 printf(" @@@@@ UNFINISHED @@@@@@%s\n",
634 "Optional params present, but not printed.");
638 case SCTP_SELECTIVE_ACK
:
640 const struct sctpSelectiveAck
*sack
;
641 const struct sctpSelectiveFrag
*frag
;
643 const u_char
*dupTSN
;
646 sack
=(const struct sctpSelectiveAck
*)(chunkDescPtr
+1);
647 printf("[cum ack %u] ", EXTRACT_32BITS(&sack
->highestConseqTSN
));
648 printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack
->updatedRwnd
));
649 printf("[#gap acks %u] ", EXTRACT_16BITS(&sack
->numberOfdesc
));
650 printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack
->numDupTsns
));
654 for (frag
= ( (const struct sctpSelectiveFrag
*)
655 ((const struct sctpSelectiveAck
*) sack
+1)),
657 (const void *)frag
< nextChunk
&& fragNo
< EXTRACT_16BITS(&sack
->numberOfdesc
);
659 printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ",
661 EXTRACT_32BITS(&sack
->highestConseqTSN
) + EXTRACT_16BITS(&frag
->fragmentStart
),
662 EXTRACT_32BITS(&sack
->highestConseqTSN
) + EXTRACT_16BITS(&frag
->fragmentEnd
));
665 /* print duplicate TSNs */
666 for (dupTSN
= (const u_char
*)frag
, tsnNo
=0;
667 (const void *) dupTSN
< nextChunk
&& tsnNo
<EXTRACT_16BITS(&sack
->numDupTsns
);
668 dupTSN
+= 4, tsnNo
++)
669 printf("\n\t\t[dup TSN #%u: %u] ", tsnNo
+1,
670 EXTRACT_32BITS(dupTSN
));
674 case SCTP_HEARTBEAT_REQUEST
:
677 case SCTP_HEARTBEAT_ACK
:
680 case SCTP_ABORT_ASSOCIATION
:
684 printf("[SHUTDOWN] ");
686 case SCTP_SHUTDOWN_ACK
:
687 printf("[SHUTDOWN ACK] ");
689 case SCTP_OPERATION_ERR
:
692 case SCTP_COOKIE_ECHO
:
693 printf("[COOKIE ECHO] ");
695 case SCTP_COOKIE_ACK
:
696 printf("[COOKIE ACK] ");
699 printf("[ECN ECHO] ");
702 printf("[ECN CWR] ");
704 case SCTP_SHUTDOWN_COMPLETE
:
705 printf("[SHUTDOWN COMPLETE] ");
707 case SCTP_FORWARD_CUM_TSN
:
708 printf("[FOR CUM TSN] ");
710 case SCTP_RELIABLE_CNTL
:
711 printf("[REL CTRL] ");
713 case SCTP_RELIABLE_CNTL_ACK
:
714 printf("[REL CTRL ACK] ");
717 printf("[Unknown chunk type: 0x%x]", chunkDescPtr
->chunkID
);