1a90e161bSBill Fenner /* Copyright (c) 2001 NETLAB, Temple University
2a90e161bSBill Fenner * Copyright (c) 2001 Protocol Engineering Lab, University of Delaware
3a90e161bSBill Fenner *
4a90e161bSBill Fenner * Jerry Heinz <gheinz@astro.temple.edu>
5a90e161bSBill Fenner * John Fiore <jfiore@joda.cis.temple.edu>
6a90e161bSBill Fenner * Armando L. Caro Jr. <acaro@cis.udel.edu>
7a90e161bSBill Fenner *
8a90e161bSBill Fenner * Redistribution and use in source and binary forms, with or without
9a90e161bSBill Fenner * modification, are permitted provided that the following conditions
10a90e161bSBill Fenner * are met:
11a90e161bSBill Fenner *
12a90e161bSBill Fenner * 1. Redistributions of source code must retain the above copyright
13a90e161bSBill Fenner * notice, this list of conditions and the following disclaimer.
14a90e161bSBill Fenner *
15a90e161bSBill Fenner * 2. Redistributions in binary form must reproduce the above copyright
16a90e161bSBill Fenner * notice, this list of conditions and the following disclaimer in the
17a90e161bSBill Fenner * documentation and/or other materials provided with the distribution.
18a90e161bSBill Fenner *
19a90e161bSBill Fenner * 3. Neither the name of the University nor of the Laboratory may be used
20a90e161bSBill Fenner * to endorse or promote products derived from this software without
21a90e161bSBill Fenner * specific prior written permission.
22a90e161bSBill Fenner *
23a90e161bSBill Fenner * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24a90e161bSBill Fenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25a90e161bSBill Fenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26a90e161bSBill Fenner * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27a90e161bSBill Fenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28a90e161bSBill Fenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29a90e161bSBill Fenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30a90e161bSBill Fenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31a90e161bSBill Fenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32a90e161bSBill Fenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33a90e161bSBill Fenner * SUCH DAMAGE.
34a90e161bSBill Fenner */
35a90e161bSBill Fenner
363340d773SGleb Smirnoff /* \summary: Stream Control Transmission Protocol (SCTP) printer */
373340d773SGleb Smirnoff
38a90e161bSBill Fenner #ifdef HAVE_CONFIG_H
39ee67461eSJoseph Mingrone #include <config.h>
40a90e161bSBill Fenner #endif
41a90e161bSBill Fenner
42ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
43a90e161bSBill Fenner
443340d773SGleb Smirnoff #include "netdissect.h"
45a90e161bSBill Fenner #include "addrtoname.h"
463340d773SGleb Smirnoff #include "extract.h"
47a90e161bSBill Fenner #include "ip.h"
48a90e161bSBill Fenner #include "ip6.h"
49a90e161bSBill Fenner
503c602fabSXin LI /* Definitions from:
513c602fabSXin LI *
523c602fabSXin LI * SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola
533c602fabSXin LI *
543c602fabSXin LI * Redistribution and use in source and binary forms, with or without
553c602fabSXin LI * modification, are permitted provided that the following conditions
563c602fabSXin LI * are met:
573c602fabSXin LI *
583c602fabSXin LI * 1. Redistributions of source code must retain the above copyright
593c602fabSXin LI * notice, this list of conditions and the following disclaimer.
603c602fabSXin LI *
613c602fabSXin LI * 2. Redistributions in binary form must reproduce the above copyright
623c602fabSXin LI * notice, this list of conditions and the following disclaimer in the
633c602fabSXin LI * documentation and/or other materials provided with the distribution.
643c602fabSXin LI *
653c602fabSXin LI * 3. Neither the name of Cisco nor of Motorola may be used
663c602fabSXin LI * to endorse or promote products derived from this software without
673c602fabSXin LI * specific prior written permission.
683c602fabSXin LI *
693c602fabSXin LI * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
703c602fabSXin LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
713c602fabSXin LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
723c602fabSXin LI * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
733c602fabSXin LI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
743c602fabSXin LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
753c602fabSXin LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
763c602fabSXin LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
773c602fabSXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
783c602fabSXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
793c602fabSXin LI * SUCH DAMAGE.
803c602fabSXin LI *
813c602fabSXin LI * This file is part of the SCTP reference Implementation
823c602fabSXin LI *
833c602fabSXin LI *
843c602fabSXin LI * Please send any bug reports or fixes you make to one of the following email
853c602fabSXin LI * addresses:
863c602fabSXin LI *
873c602fabSXin LI * rstewar1@email.mot.com
883c602fabSXin LI * kmorneau@cisco.com
893c602fabSXin LI * qxie1@email.mot.com
903c602fabSXin LI *
913c602fabSXin LI * Any bugs reported given to us we will try to fix... any fixes shared will
92ee67461eSJoseph Mingrone * be incorporated into the next SCTP release.
933c602fabSXin LI */
943c602fabSXin LI
953c602fabSXin LI /* The valid defines for all message
963c602fabSXin LI * types know to SCTP. 0 is reserved
973c602fabSXin LI */
983c602fabSXin LI #define SCTP_DATA 0x00
993c602fabSXin LI #define SCTP_INITIATION 0x01
1003c602fabSXin LI #define SCTP_INITIATION_ACK 0x02
1013c602fabSXin LI #define SCTP_SELECTIVE_ACK 0x03
1023c602fabSXin LI #define SCTP_HEARTBEAT_REQUEST 0x04
1033c602fabSXin LI #define SCTP_HEARTBEAT_ACK 0x05
1043c602fabSXin LI #define SCTP_ABORT_ASSOCIATION 0x06
1053c602fabSXin LI #define SCTP_SHUTDOWN 0x07
1063c602fabSXin LI #define SCTP_SHUTDOWN_ACK 0x08
1073c602fabSXin LI #define SCTP_OPERATION_ERR 0x09
1083c602fabSXin LI #define SCTP_COOKIE_ECHO 0x0a
1093c602fabSXin LI #define SCTP_COOKIE_ACK 0x0b
1103c602fabSXin LI #define SCTP_ECN_ECHO 0x0c
1113c602fabSXin LI #define SCTP_ECN_CWR 0x0d
1123c602fabSXin LI #define SCTP_SHUTDOWN_COMPLETE 0x0e
1133c602fabSXin LI #define SCTP_FORWARD_CUM_TSN 0xc0
1143c602fabSXin LI #define SCTP_RELIABLE_CNTL 0xc1
1153c602fabSXin LI #define SCTP_RELIABLE_CNTL_ACK 0xc2
1163c602fabSXin LI
1173c602fabSXin LI static const struct tok sctp_chunkid_str[] = {
1183c602fabSXin LI { SCTP_DATA, "DATA" },
1193c602fabSXin LI { SCTP_INITIATION, "INIT" },
1203c602fabSXin LI { SCTP_INITIATION_ACK, "INIT ACK" },
1213c602fabSXin LI { SCTP_SELECTIVE_ACK, "SACK" },
1223c602fabSXin LI { SCTP_HEARTBEAT_REQUEST, "HB REQ" },
1233c602fabSXin LI { SCTP_HEARTBEAT_ACK, "HB ACK" },
1243c602fabSXin LI { SCTP_ABORT_ASSOCIATION, "ABORT" },
1253c602fabSXin LI { SCTP_SHUTDOWN, "SHUTDOWN" },
1263c602fabSXin LI { SCTP_SHUTDOWN_ACK, "SHUTDOWN ACK" },
1273c602fabSXin LI { SCTP_OPERATION_ERR, "OP ERR" },
1283c602fabSXin LI { SCTP_COOKIE_ECHO, "COOKIE ECHO" },
1293c602fabSXin LI { SCTP_COOKIE_ACK, "COOKIE ACK" },
1303c602fabSXin LI { SCTP_ECN_ECHO, "ECN ECHO" },
1313c602fabSXin LI { SCTP_ECN_CWR, "ECN CWR" },
1323c602fabSXin LI { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" },
1333c602fabSXin LI { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" },
1343c602fabSXin LI { SCTP_RELIABLE_CNTL, "REL CTRL" },
1353c602fabSXin LI { SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" },
1363c602fabSXin LI { 0, NULL }
1373c602fabSXin LI };
1383c602fabSXin LI
1393c602fabSXin LI /* Data Chuck Specific Flags */
1403c602fabSXin LI #define SCTP_DATA_FRAG_MASK 0x03
1413c602fabSXin LI #define SCTP_DATA_MIDDLE_FRAG 0x00
1423c602fabSXin LI #define SCTP_DATA_LAST_FRAG 0x01
1433c602fabSXin LI #define SCTP_DATA_FIRST_FRAG 0x02
1443c602fabSXin LI #define SCTP_DATA_NOT_FRAG 0x03
1453c602fabSXin LI #define SCTP_DATA_UNORDERED 0x04
1463c602fabSXin LI
1473c602fabSXin LI #define SCTP_ADDRMAX 60
1483c602fabSXin LI
149cac3dcd5SXin LI #define CHAN_HP 6704
150cac3dcd5SXin LI #define CHAN_MP 6705
151cac3dcd5SXin LI #define CHAN_LP 6706
15227df3f5dSRui Paulo
1533c602fabSXin LI /* the sctp common header */
1543c602fabSXin LI
1553c602fabSXin LI struct sctpHeader{
156ee67461eSJoseph Mingrone nd_uint16_t source;
157ee67461eSJoseph Mingrone nd_uint16_t destination;
158ee67461eSJoseph Mingrone nd_uint32_t verificationTag;
159ee67461eSJoseph Mingrone nd_uint32_t adler32;
1603c602fabSXin LI };
1613c602fabSXin LI
1623c602fabSXin LI /* various descriptor parsers */
1633c602fabSXin LI
1643c602fabSXin LI struct sctpChunkDesc{
165ee67461eSJoseph Mingrone nd_uint8_t chunkID;
166ee67461eSJoseph Mingrone nd_uint8_t chunkFlg;
167ee67461eSJoseph Mingrone nd_uint16_t chunkLength;
1683c602fabSXin LI };
1693c602fabSXin LI
1703c602fabSXin LI struct sctpParamDesc{
171ee67461eSJoseph Mingrone nd_uint16_t paramType;
172ee67461eSJoseph Mingrone nd_uint16_t paramLength;
1733c602fabSXin LI };
1743c602fabSXin LI
1753c602fabSXin LI
1763c602fabSXin LI struct sctpRelChunkDesc{
1773c602fabSXin LI struct sctpChunkDesc chk;
178ee67461eSJoseph Mingrone nd_uint32_t serialNumber;
1793c602fabSXin LI };
1803c602fabSXin LI
1813c602fabSXin LI struct sctpVendorSpecificParam {
1823c602fabSXin LI struct sctpParamDesc p; /* type must be 0xfffe */
183ee67461eSJoseph Mingrone nd_uint32_t vendorId; /* vendor ID from RFC 1700 */
184ee67461eSJoseph Mingrone nd_uint16_t vendorSpecificType;
185ee67461eSJoseph Mingrone nd_uint16_t vendorSpecificLen;
1863c602fabSXin LI };
1873c602fabSXin LI
1883c602fabSXin LI
1893c602fabSXin LI /* Structures for the control parts */
1903c602fabSXin LI
1913c602fabSXin LI
1923c602fabSXin LI
1933c602fabSXin LI /* Sctp association init request/ack */
1943c602fabSXin LI
1953c602fabSXin LI /* this is used for init ack, too */
1963c602fabSXin LI struct sctpInitiation{
197ee67461eSJoseph Mingrone nd_uint32_t initTag; /* tag of mine */
198ee67461eSJoseph Mingrone nd_uint32_t rcvWindowCredit; /* rwnd */
199ee67461eSJoseph Mingrone nd_uint16_t NumPreopenStreams; /* OS */
200ee67461eSJoseph Mingrone nd_uint16_t MaxInboundStreams; /* MIS */
201ee67461eSJoseph Mingrone nd_uint32_t initialTSN;
2023c602fabSXin LI /* optional param's follow in sctpParamDesc form */
2033c602fabSXin LI };
2043c602fabSXin LI
2053c602fabSXin LI struct sctpV4IpAddress{
2063c602fabSXin LI struct sctpParamDesc p; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */
207ee67461eSJoseph Mingrone nd_ipv4 ipAddress;
2083c602fabSXin LI };
2093c602fabSXin LI
2103c602fabSXin LI
2113c602fabSXin LI struct sctpV6IpAddress{
2123c602fabSXin LI struct sctpParamDesc p; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */
213ee67461eSJoseph Mingrone nd_ipv6 ipAddress;
2143c602fabSXin LI };
2153c602fabSXin LI
2163c602fabSXin LI struct sctpDNSName{
2173c602fabSXin LI struct sctpParamDesc param;
218ee67461eSJoseph Mingrone nd_byte name[1];
2193c602fabSXin LI };
2203c602fabSXin LI
2213c602fabSXin LI
2223c602fabSXin LI struct sctpCookiePreserve{
2233c602fabSXin LI struct sctpParamDesc p; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */
224ee67461eSJoseph Mingrone nd_uint32_t extraTime;
2253c602fabSXin LI };
2263c602fabSXin LI
2273c602fabSXin LI
2283c602fabSXin LI struct sctpTimeStamp{
229ee67461eSJoseph Mingrone nd_uint32_t ts_sec;
230ee67461eSJoseph Mingrone nd_uint32_t ts_usec;
2313c602fabSXin LI };
2323c602fabSXin LI
2333c602fabSXin LI
2343c602fabSXin LI /* this guy is for use when
2353c602fabSXin LI * I have a initiate message gloming the
2363c602fabSXin LI * things together.
2373c602fabSXin LI
2383c602fabSXin LI */
2393c602fabSXin LI struct sctpUnifiedInit{
2403c602fabSXin LI struct sctpChunkDesc uh;
2413c602fabSXin LI struct sctpInitiation initm;
2423c602fabSXin LI };
2433c602fabSXin LI
2443c602fabSXin LI struct sctpSendableInit{
2453c602fabSXin LI struct sctpHeader mh;
2463c602fabSXin LI struct sctpUnifiedInit msg;
2473c602fabSXin LI };
2483c602fabSXin LI
2493c602fabSXin LI
2503c602fabSXin LI /* Selective Acknowledgement
2513c602fabSXin LI * has the following structure with
252ee67461eSJoseph Mingrone * a optional amount of trailing int's
2533c602fabSXin LI * on the last part (based on the numberOfDesc
2543c602fabSXin LI * field).
2553c602fabSXin LI */
2563c602fabSXin LI
2573c602fabSXin LI struct sctpSelectiveAck{
258ee67461eSJoseph Mingrone nd_uint32_t highestConseqTSN;
259ee67461eSJoseph Mingrone nd_uint32_t updatedRwnd;
260ee67461eSJoseph Mingrone nd_uint16_t numberOfdesc;
261ee67461eSJoseph Mingrone nd_uint16_t numDupTsns;
2623c602fabSXin LI };
2633c602fabSXin LI
2643c602fabSXin LI struct sctpSelectiveFrag{
265ee67461eSJoseph Mingrone nd_uint16_t fragmentStart;
266ee67461eSJoseph Mingrone nd_uint16_t fragmentEnd;
2673c602fabSXin LI };
2683c602fabSXin LI
2693c602fabSXin LI
2703c602fabSXin LI struct sctpUnifiedSack{
2713c602fabSXin LI struct sctpChunkDesc uh;
2723c602fabSXin LI struct sctpSelectiveAck sack;
2733c602fabSXin LI };
2743c602fabSXin LI
2753c602fabSXin LI /* for the abort and shutdown ACK
2763c602fabSXin LI * we must carry the init tag in the common header. Just the
2773c602fabSXin LI * common header is all that is needed with a chunk descriptor.
2783c602fabSXin LI */
2793c602fabSXin LI struct sctpUnifiedAbort{
2803c602fabSXin LI struct sctpChunkDesc uh;
2813c602fabSXin LI };
2823c602fabSXin LI
2833c602fabSXin LI struct sctpUnifiedAbortLight{
2843c602fabSXin LI struct sctpHeader mh;
2853c602fabSXin LI struct sctpChunkDesc uh;
2863c602fabSXin LI };
2873c602fabSXin LI
2883c602fabSXin LI struct sctpUnifiedAbortHeavy{
2893c602fabSXin LI struct sctpHeader mh;
2903c602fabSXin LI struct sctpChunkDesc uh;
291ee67461eSJoseph Mingrone nd_uint16_t causeCode;
292ee67461eSJoseph Mingrone nd_uint16_t causeLen;
2933c602fabSXin LI };
2943c602fabSXin LI
2953c602fabSXin LI /* For the graceful shutdown we must carry
2963c602fabSXin LI * the tag (in common header) and the highest consequitive acking value
2973c602fabSXin LI */
2983c602fabSXin LI struct sctpShutdown {
299ee67461eSJoseph Mingrone nd_uint32_t TSN_Seen;
3003c602fabSXin LI };
3013c602fabSXin LI
3023c602fabSXin LI struct sctpUnifiedShutdown{
3033c602fabSXin LI struct sctpChunkDesc uh;
3043c602fabSXin LI struct sctpShutdown shut;
3053c602fabSXin LI };
3063c602fabSXin LI
3073c602fabSXin LI /* in the unified message we add the trailing
3083c602fabSXin LI * stream id since it is the only message
3093c602fabSXin LI * that is defined as a operation error.
3103c602fabSXin LI */
3113c602fabSXin LI struct sctpOpErrorCause{
312ee67461eSJoseph Mingrone nd_uint16_t cause;
313ee67461eSJoseph Mingrone nd_uint16_t causeLen;
3143c602fabSXin LI };
3153c602fabSXin LI
3163c602fabSXin LI struct sctpUnifiedOpError{
3173c602fabSXin LI struct sctpChunkDesc uh;
3183c602fabSXin LI struct sctpOpErrorCause c;
3193c602fabSXin LI };
3203c602fabSXin LI
3213c602fabSXin LI struct sctpUnifiedStreamError{
3223c602fabSXin LI struct sctpHeader mh;
3233c602fabSXin LI struct sctpChunkDesc uh;
3243c602fabSXin LI struct sctpOpErrorCause c;
325ee67461eSJoseph Mingrone nd_uint16_t strmNum;
326ee67461eSJoseph Mingrone nd_uint16_t reserved;
3273c602fabSXin LI };
3283c602fabSXin LI
3293c602fabSXin LI struct staleCookieMsg{
3303c602fabSXin LI struct sctpHeader mh;
3313c602fabSXin LI struct sctpChunkDesc uh;
3323c602fabSXin LI struct sctpOpErrorCause c;
333ee67461eSJoseph Mingrone nd_uint32_t moretime;
3343c602fabSXin LI };
3353c602fabSXin LI
3363c602fabSXin LI /* the following is used in all sends
3373c602fabSXin LI * where nothing is needed except the
3383c602fabSXin LI * chunk/type i.e. shutdownAck Abort */
3393c602fabSXin LI
3403c602fabSXin LI struct sctpUnifiedSingleMsg{
3413c602fabSXin LI struct sctpHeader mh;
3423c602fabSXin LI struct sctpChunkDesc uh;
3433c602fabSXin LI };
3443c602fabSXin LI
3453c602fabSXin LI struct sctpDataPart{
346ee67461eSJoseph Mingrone nd_uint32_t TSN;
347ee67461eSJoseph Mingrone nd_uint16_t streamId;
348ee67461eSJoseph Mingrone nd_uint16_t sequence;
349ee67461eSJoseph Mingrone nd_uint32_t payloadtype;
3503c602fabSXin LI };
3513c602fabSXin LI
3523c602fabSXin LI struct sctpUnifiedDatagram{
3533c602fabSXin LI struct sctpChunkDesc uh;
3543c602fabSXin LI struct sctpDataPart dp;
3553c602fabSXin LI };
3563c602fabSXin LI
3573c602fabSXin LI struct sctpECN_echo{
3583c602fabSXin LI struct sctpChunkDesc uh;
359ee67461eSJoseph Mingrone nd_uint32_t Lowest_TSN;
3603c602fabSXin LI };
3613c602fabSXin LI
3623c602fabSXin LI
3633c602fabSXin LI struct sctpCWR{
3643c602fabSXin LI struct sctpChunkDesc uh;
365ee67461eSJoseph Mingrone nd_uint32_t TSN_reduced_at;
3663c602fabSXin LI };
3673c602fabSXin LI
3683c602fabSXin LI static const struct tok ForCES_channels[] = {
36927df3f5dSRui Paulo { CHAN_HP, "ForCES HP" },
37027df3f5dSRui Paulo { CHAN_MP, "ForCES MP" },
37127df3f5dSRui Paulo { CHAN_LP, "ForCES LP" },
37227df3f5dSRui Paulo { 0, NULL }
37327df3f5dSRui Paulo };
37427df3f5dSRui Paulo
3753c602fabSXin LI /* data chunk's payload protocol identifiers */
3763c602fabSXin LI
3773c602fabSXin LI #define SCTP_PPID_IUA 1
3783c602fabSXin LI #define SCTP_PPID_M2UA 2
3793c602fabSXin LI #define SCTP_PPID_M3UA 3
3803c602fabSXin LI #define SCTP_PPID_SUA 4
3813c602fabSXin LI #define SCTP_PPID_M2PA 5
3823c602fabSXin LI #define SCTP_PPID_V5UA 6
3833c602fabSXin LI #define SCTP_PPID_H248 7
3843c602fabSXin LI #define SCTP_PPID_BICC 8
3853c602fabSXin LI #define SCTP_PPID_TALI 9
3863c602fabSXin LI #define SCTP_PPID_DUA 10
3873c602fabSXin LI #define SCTP_PPID_ASAP 11
3883c602fabSXin LI #define SCTP_PPID_ENRP 12
3893c602fabSXin LI #define SCTP_PPID_H323 13
3903c602fabSXin LI #define SCTP_PPID_QIPC 14
3913c602fabSXin LI #define SCTP_PPID_SIMCO 15
3923c602fabSXin LI #define SCTP_PPID_DDPSC 16
3933c602fabSXin LI #define SCTP_PPID_DDPSSC 17
3943c602fabSXin LI #define SCTP_PPID_S1AP 18
3953c602fabSXin LI #define SCTP_PPID_RUA 19
3963c602fabSXin LI #define SCTP_PPID_HNBAP 20
3973c602fabSXin LI #define SCTP_PPID_FORCES_HP 21
3983c602fabSXin LI #define SCTP_PPID_FORCES_MP 22
3993c602fabSXin LI #define SCTP_PPID_FORCES_LP 23
4003c602fabSXin LI #define SCTP_PPID_SBC_AP 24
4013c602fabSXin LI #define SCTP_PPID_NBAP 25
4023c602fabSXin LI /* 26 */
4033c602fabSXin LI #define SCTP_PPID_X2AP 27
4043c602fabSXin LI
4053c602fabSXin LI static const struct tok PayloadProto_idents[] = {
4063c602fabSXin LI { SCTP_PPID_IUA, "ISDN Q.921" },
4073c602fabSXin LI { SCTP_PPID_M2UA, "M2UA" },
4083c602fabSXin LI { SCTP_PPID_M3UA, "M3UA" },
4093c602fabSXin LI { SCTP_PPID_SUA, "SUA" },
4103c602fabSXin LI { SCTP_PPID_M2PA, "M2PA" },
4113c602fabSXin LI { SCTP_PPID_V5UA, "V5.2" },
4123c602fabSXin LI { SCTP_PPID_H248, "H.248" },
4133c602fabSXin LI { SCTP_PPID_BICC, "BICC" },
4143c602fabSXin LI { SCTP_PPID_TALI, "TALI" },
4153c602fabSXin LI { SCTP_PPID_DUA, "DUA" },
4163c602fabSXin LI { SCTP_PPID_ASAP, "ASAP" },
4173c602fabSXin LI { SCTP_PPID_ENRP, "ENRP" },
4183c602fabSXin LI { SCTP_PPID_H323, "H.323" },
4193c602fabSXin LI { SCTP_PPID_QIPC, "Q.IPC" },
4203c602fabSXin LI { SCTP_PPID_SIMCO, "SIMCO" },
4213c602fabSXin LI { SCTP_PPID_DDPSC, "DDPSC" },
4223c602fabSXin LI { SCTP_PPID_DDPSSC, "DDPSSC" },
4233c602fabSXin LI { SCTP_PPID_S1AP, "S1AP" },
4243c602fabSXin LI { SCTP_PPID_RUA, "RUA" },
4253c602fabSXin LI { SCTP_PPID_HNBAP, "HNBAP" },
4263c602fabSXin LI { SCTP_PPID_FORCES_HP, "ForCES HP" },
4273c602fabSXin LI { SCTP_PPID_FORCES_MP, "ForCES MP" },
4283c602fabSXin LI { SCTP_PPID_FORCES_LP, "ForCES LP" },
4293c602fabSXin LI { SCTP_PPID_SBC_AP, "SBc-AP" },
4303c602fabSXin LI { SCTP_PPID_NBAP, "NBAP" },
4313c602fabSXin LI /* 26 */
4323c602fabSXin LI { SCTP_PPID_X2AP, "X2AP" },
4333c602fabSXin LI { 0, NULL }
4343c602fabSXin LI };
4353c602fabSXin LI
4363c602fabSXin LI
437ee67461eSJoseph Mingrone static int
isForCES_port(u_short Port)438ee67461eSJoseph Mingrone isForCES_port(u_short Port)
43927df3f5dSRui Paulo {
44027df3f5dSRui Paulo if (Port == CHAN_HP)
44127df3f5dSRui Paulo return 1;
44227df3f5dSRui Paulo if (Port == CHAN_MP)
44327df3f5dSRui Paulo return 1;
44427df3f5dSRui Paulo if (Port == CHAN_LP)
44527df3f5dSRui Paulo return 1;
44627df3f5dSRui Paulo
44727df3f5dSRui Paulo return 0;
44827df3f5dSRui Paulo }
44927df3f5dSRui Paulo
450ee67461eSJoseph Mingrone void
sctp_print(netdissect_options * ndo,const u_char * bp,const u_char * bp2,u_int sctpPacketLength)451ee67461eSJoseph Mingrone sctp_print(netdissect_options *ndo,
4523c602fabSXin LI const u_char *bp, /* beginning of sctp packet */
453a90e161bSBill Fenner const u_char *bp2, /* beginning of enclosing */
454a90e161bSBill Fenner u_int sctpPacketLength) /* ip packet */
455a90e161bSBill Fenner {
4563340d773SGleb Smirnoff u_int sctpPacketLengthRemaining;
457a90e161bSBill Fenner const struct sctpHeader *sctpPktHdr;
458a90e161bSBill Fenner const struct ip *ip;
459a90e161bSBill Fenner const struct ip6_hdr *ip6;
460ee67461eSJoseph Mingrone uint8_t chunkID;
461a90e161bSBill Fenner u_short sourcePort, destPort;
462ee67461eSJoseph Mingrone u_int chunkCount;
4639afd0c29SBill Fenner const struct sctpChunkDesc *chunkDescPtr;
4641de50e9fSSam Leffler const char *sep;
46527df3f5dSRui Paulo int isforces = 0;
46627df3f5dSRui Paulo
467ee67461eSJoseph Mingrone ndo->ndo_protocol = "sctp";
468a90e161bSBill Fenner if (sctpPacketLength < sizeof(struct sctpHeader))
469a90e161bSBill Fenner {
470ee67461eSJoseph Mingrone ND_PRINT("truncated-sctp - %zu bytes missing!",
471ee67461eSJoseph Mingrone sizeof(struct sctpHeader) - sctpPacketLength);
472a90e161bSBill Fenner return;
473a90e161bSBill Fenner }
4743340d773SGleb Smirnoff sctpPktHdr = (const struct sctpHeader*) bp;
475ee67461eSJoseph Mingrone ND_TCHECK_SIZE(sctpPktHdr);
4763340d773SGleb Smirnoff sctpPacketLengthRemaining = sctpPacketLength;
477a90e161bSBill Fenner
478ee67461eSJoseph Mingrone sourcePort = GET_BE_U_2(sctpPktHdr->source);
479ee67461eSJoseph Mingrone destPort = GET_BE_U_2(sctpPktHdr->destination);
480a90e161bSBill Fenner
4813340d773SGleb Smirnoff ip = (const struct ip *)bp2;
4823340d773SGleb Smirnoff if (IP_V(ip) == 6)
4833340d773SGleb Smirnoff ip6 = (const struct ip6_hdr *)bp2;
4843340d773SGleb Smirnoff else
4853340d773SGleb Smirnoff ip6 = NULL;
4863340d773SGleb Smirnoff
487a90e161bSBill Fenner if (ip6) {
488ee67461eSJoseph Mingrone ND_PRINT("%s.%u > %s.%u: sctp",
489ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(ip6->ip6_src),
490a90e161bSBill Fenner sourcePort,
491ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(ip6->ip6_dst),
492ee67461eSJoseph Mingrone destPort);
493ee67461eSJoseph Mingrone } else {
494ee67461eSJoseph Mingrone ND_PRINT("%s.%u > %s.%u: sctp",
495ee67461eSJoseph Mingrone GET_IPADDR_STRING(ip->ip_src),
496a90e161bSBill Fenner sourcePort,
497ee67461eSJoseph Mingrone GET_IPADDR_STRING(ip->ip_dst),
498ee67461eSJoseph Mingrone destPort);
499a90e161bSBill Fenner }
500a90e161bSBill Fenner
50127df3f5dSRui Paulo if (isForCES_port(sourcePort)) {
502ee67461eSJoseph Mingrone ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, sourcePort));
50327df3f5dSRui Paulo isforces = 1;
50427df3f5dSRui Paulo }
50527df3f5dSRui Paulo if (isForCES_port(destPort)) {
506ee67461eSJoseph Mingrone ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, destPort));
50727df3f5dSRui Paulo isforces = 1;
50827df3f5dSRui Paulo }
50927df3f5dSRui Paulo
5103340d773SGleb Smirnoff bp += sizeof(struct sctpHeader);
5113340d773SGleb Smirnoff sctpPacketLengthRemaining -= sizeof(struct sctpHeader);
5123340d773SGleb Smirnoff
5133c602fabSXin LI if (ndo->ndo_vflag >= 2)
5141de50e9fSSam Leffler sep = "\n\t";
5151de50e9fSSam Leffler else
5161de50e9fSSam Leffler sep = " (";
517a90e161bSBill Fenner /* cycle through all chunks, printing information on each one */
5183340d773SGleb Smirnoff for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *)bp;
5193340d773SGleb Smirnoff sctpPacketLengthRemaining != 0;
5203340d773SGleb Smirnoff chunkCount++)
521a90e161bSBill Fenner {
5223340d773SGleb Smirnoff uint16_t chunkLength, chunkLengthRemaining;
5233c602fabSXin LI uint16_t align;
524a90e161bSBill Fenner
5253340d773SGleb Smirnoff chunkDescPtr = (const struct sctpChunkDesc *)bp;
5263340d773SGleb Smirnoff if (sctpPacketLengthRemaining < sizeof(*chunkDescPtr)) {
527ee67461eSJoseph Mingrone ND_PRINT("%s%u) [chunk descriptor cut off at end of packet]", sep, chunkCount+1);
5283340d773SGleb Smirnoff break;
5293340d773SGleb Smirnoff }
530ee67461eSJoseph Mingrone ND_TCHECK_SIZE(chunkDescPtr);
531ee67461eSJoseph Mingrone chunkLength = GET_BE_U_2(chunkDescPtr->chunkLength);
532f4d0c64aSSam Leffler if (chunkLength < sizeof(*chunkDescPtr)) {
533ee67461eSJoseph Mingrone ND_PRINT("%s%u) [Bad chunk length %u, < size of chunk descriptor]", sep, chunkCount+1, chunkLength);
534f4d0c64aSSam Leffler break;
535f4d0c64aSSam Leffler }
5363340d773SGleb Smirnoff chunkLengthRemaining = chunkLength;
537f4d0c64aSSam Leffler
538f4d0c64aSSam Leffler align = chunkLength % 4;
539a90e161bSBill Fenner if (align != 0)
540a90e161bSBill Fenner align = 4 - align;
541a90e161bSBill Fenner
5423340d773SGleb Smirnoff if (sctpPacketLengthRemaining < align) {
543ee67461eSJoseph Mingrone ND_PRINT("%s%u) [Bad chunk length %u, > remaining data in packet]", sep, chunkCount+1, chunkLength);
5443340d773SGleb Smirnoff break;
5453340d773SGleb Smirnoff }
5463340d773SGleb Smirnoff
547ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, chunkLength);
5483340d773SGleb Smirnoff
5493340d773SGleb Smirnoff bp += sizeof(*chunkDescPtr);
5503340d773SGleb Smirnoff sctpPacketLengthRemaining -= sizeof(*chunkDescPtr);
5513340d773SGleb Smirnoff chunkLengthRemaining -= sizeof(*chunkDescPtr);
552a90e161bSBill Fenner
553ee67461eSJoseph Mingrone ND_PRINT("%s%u) ", sep, chunkCount+1);
554ee67461eSJoseph Mingrone chunkID = GET_U_1(chunkDescPtr->chunkID);
555ee67461eSJoseph Mingrone ND_PRINT("[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x",
556ee67461eSJoseph Mingrone chunkID));
557ee67461eSJoseph Mingrone switch (chunkID)
558a90e161bSBill Fenner {
559a90e161bSBill Fenner case SCTP_DATA :
560a90e161bSBill Fenner {
5619afd0c29SBill Fenner const struct sctpDataPart *dataHdrPtr;
562ee67461eSJoseph Mingrone uint8_t chunkFlg;
5633c602fabSXin LI uint32_t ppid;
564ee67461eSJoseph Mingrone uint16_t payload_size;
565a90e161bSBill Fenner
566ee67461eSJoseph Mingrone chunkFlg = GET_U_1(chunkDescPtr->chunkFlg);
567ee67461eSJoseph Mingrone if ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)
568ee67461eSJoseph Mingrone ND_PRINT("(U)");
569a90e161bSBill Fenner
570ee67461eSJoseph Mingrone if ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG)
571ee67461eSJoseph Mingrone ND_PRINT("(B)");
572a90e161bSBill Fenner
573ee67461eSJoseph Mingrone if ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG)
574ee67461eSJoseph Mingrone ND_PRINT("(E)");
575a90e161bSBill Fenner
576ee67461eSJoseph Mingrone if( ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) ||
577ee67461eSJoseph Mingrone ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) ||
578ee67461eSJoseph Mingrone ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) )
579ee67461eSJoseph Mingrone ND_PRINT(" ");
580a90e161bSBill Fenner
5813340d773SGleb Smirnoff if (chunkLengthRemaining < sizeof(*dataHdrPtr)) {
582ee67461eSJoseph Mingrone ND_PRINT("bogus chunk length %u]", chunkLength);
5833340d773SGleb Smirnoff return;
5843340d773SGleb Smirnoff }
5853340d773SGleb Smirnoff dataHdrPtr=(const struct sctpDataPart*)bp;
586a90e161bSBill Fenner
587ee67461eSJoseph Mingrone ppid = GET_BE_U_4(dataHdrPtr->payloadtype);
588ee67461eSJoseph Mingrone ND_PRINT("[TSN: %u] ", GET_BE_U_4(dataHdrPtr->TSN));
589ee67461eSJoseph Mingrone ND_PRINT("[SID: %u] ", GET_BE_U_2(dataHdrPtr->streamId));
590ee67461eSJoseph Mingrone ND_PRINT("[SSEQ %u] ", GET_BE_U_2(dataHdrPtr->sequence));
591ee67461eSJoseph Mingrone ND_PRINT("[PPID %s] ",
592ee67461eSJoseph Mingrone tok2str(PayloadProto_idents, "0x%x", ppid));
5933c602fabSXin LI
5943c602fabSXin LI if (!isforces) {
5953c602fabSXin LI isforces = (ppid == SCTP_PPID_FORCES_HP) ||
5963c602fabSXin LI (ppid == SCTP_PPID_FORCES_MP) ||
5973c602fabSXin LI (ppid == SCTP_PPID_FORCES_LP);
5983c602fabSXin LI }
5993c602fabSXin LI
6003340d773SGleb Smirnoff bp += sizeof(*dataHdrPtr);
6013340d773SGleb Smirnoff sctpPacketLengthRemaining -= sizeof(*dataHdrPtr);
6023340d773SGleb Smirnoff chunkLengthRemaining -= sizeof(*dataHdrPtr);
6033340d773SGleb Smirnoff payload_size = chunkLengthRemaining;
6043340d773SGleb Smirnoff if (payload_size == 0) {
605ee67461eSJoseph Mingrone ND_PRINT("bogus chunk length %u]", chunkLength);
60627df3f5dSRui Paulo return;
60727df3f5dSRui Paulo }
608a90e161bSBill Fenner
6093c602fabSXin LI if (isforces) {
6103340d773SGleb Smirnoff forces_print(ndo, bp, payload_size);
611ee67461eSJoseph Mingrone /* ndo_protocol reassignment after forces_print() call */
612ee67461eSJoseph Mingrone ndo->ndo_protocol = "sctp";
6133c602fabSXin LI } else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */
61427df3f5dSRui Paulo /* at the command line */
6153c602fabSXin LI switch (ppid) {
6163c602fabSXin LI case SCTP_PPID_M3UA :
6173340d773SGleb Smirnoff m3ua_print(ndo, bp, payload_size);
618ee67461eSJoseph Mingrone /* ndo_protocol reassignment after m3ua_print() call */
619ee67461eSJoseph Mingrone ndo->ndo_protocol = "sctp";
6203c602fabSXin LI break;
6213c602fabSXin LI default:
622ee67461eSJoseph Mingrone ND_PRINT("[Payload");
6233c602fabSXin LI if (!ndo->ndo_suppress_default_print) {
624ee67461eSJoseph Mingrone ND_PRINT(":");
6253340d773SGleb Smirnoff ND_DEFAULTPRINT(bp, payload_size);
6265b0fe478SBruce M Simpson }
627ee67461eSJoseph Mingrone ND_PRINT("]");
6283c602fabSXin LI break;
6293c602fabSXin LI }
630a90e161bSBill Fenner }
6313340d773SGleb Smirnoff bp += payload_size;
6323340d773SGleb Smirnoff sctpPacketLengthRemaining -= payload_size;
6333340d773SGleb Smirnoff chunkLengthRemaining -= payload_size;
634a90e161bSBill Fenner break;
635a90e161bSBill Fenner }
636a90e161bSBill Fenner case SCTP_INITIATION :
637a90e161bSBill Fenner {
6389afd0c29SBill Fenner const struct sctpInitiation *init;
639a90e161bSBill Fenner
6403340d773SGleb Smirnoff if (chunkLengthRemaining < sizeof(*init)) {
641ee67461eSJoseph Mingrone ND_PRINT("bogus chunk length %u]", chunkLength);
6423340d773SGleb Smirnoff return;
6433340d773SGleb Smirnoff }
6443340d773SGleb Smirnoff init=(const struct sctpInitiation*)bp;
645ee67461eSJoseph Mingrone ND_PRINT("[init tag: %u] ", GET_BE_U_4(init->initTag));
646ee67461eSJoseph Mingrone ND_PRINT("[rwnd: %u] ", GET_BE_U_4(init->rcvWindowCredit));
647ee67461eSJoseph Mingrone ND_PRINT("[OS: %u] ", GET_BE_U_2(init->NumPreopenStreams));
648ee67461eSJoseph Mingrone ND_PRINT("[MIS: %u] ", GET_BE_U_2(init->MaxInboundStreams));
649ee67461eSJoseph Mingrone ND_PRINT("[init TSN: %u] ", GET_BE_U_4(init->initialTSN));
6503340d773SGleb Smirnoff bp += sizeof(*init);
6513340d773SGleb Smirnoff sctpPacketLengthRemaining -= sizeof(*init);
6523340d773SGleb Smirnoff chunkLengthRemaining -= sizeof(*init);
653a90e161bSBill Fenner
6543340d773SGleb Smirnoff #if 0 /* ALC you can add code for optional params here */
6553340d773SGleb Smirnoff if( chunkLengthRemaining != 0 )
656ee67461eSJoseph Mingrone ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n",
657ee67461eSJoseph Mingrone "Optional params present, but not printed.");
658a90e161bSBill Fenner #endif
6593340d773SGleb Smirnoff bp += chunkLengthRemaining;
6603340d773SGleb Smirnoff sctpPacketLengthRemaining -= chunkLengthRemaining;
6613340d773SGleb Smirnoff chunkLengthRemaining = 0;
662a90e161bSBill Fenner break;
663a90e161bSBill Fenner }
664a90e161bSBill Fenner case SCTP_INITIATION_ACK :
665a90e161bSBill Fenner {
6669afd0c29SBill Fenner const struct sctpInitiation *init;
667a90e161bSBill Fenner
6683340d773SGleb Smirnoff if (chunkLengthRemaining < sizeof(*init)) {
669ee67461eSJoseph Mingrone ND_PRINT("bogus chunk length %u]", chunkLength);
6703340d773SGleb Smirnoff return;
6713340d773SGleb Smirnoff }
6723340d773SGleb Smirnoff init=(const struct sctpInitiation*)bp;
673ee67461eSJoseph Mingrone ND_PRINT("[init tag: %u] ", GET_BE_U_4(init->initTag));
674ee67461eSJoseph Mingrone ND_PRINT("[rwnd: %u] ", GET_BE_U_4(init->rcvWindowCredit));
675ee67461eSJoseph Mingrone ND_PRINT("[OS: %u] ", GET_BE_U_2(init->NumPreopenStreams));
676ee67461eSJoseph Mingrone ND_PRINT("[MIS: %u] ", GET_BE_U_2(init->MaxInboundStreams));
677ee67461eSJoseph Mingrone ND_PRINT("[init TSN: %u] ", GET_BE_U_4(init->initialTSN));
6783340d773SGleb Smirnoff bp += sizeof(*init);
6793340d773SGleb Smirnoff sctpPacketLengthRemaining -= sizeof(*init);
6803340d773SGleb Smirnoff chunkLengthRemaining -= sizeof(*init);
681a90e161bSBill Fenner
6823340d773SGleb Smirnoff #if 0 /* ALC you can add code for optional params here */
6833340d773SGleb Smirnoff if( chunkLengthRemaining != 0 )
684ee67461eSJoseph Mingrone ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n",
685ee67461eSJoseph Mingrone "Optional params present, but not printed.");
686a90e161bSBill Fenner #endif
6873340d773SGleb Smirnoff bp += chunkLengthRemaining;
6883340d773SGleb Smirnoff sctpPacketLengthRemaining -= chunkLengthRemaining;
6893340d773SGleb Smirnoff chunkLengthRemaining = 0;
690a90e161bSBill Fenner break;
691a90e161bSBill Fenner }
692a90e161bSBill Fenner case SCTP_SELECTIVE_ACK:
693a90e161bSBill Fenner {
6949afd0c29SBill Fenner const struct sctpSelectiveAck *sack;
6959afd0c29SBill Fenner const struct sctpSelectiveFrag *frag;
696ee67461eSJoseph Mingrone u_int fragNo, tsnNo;
697f4d0c64aSSam Leffler const u_char *dupTSN;
698a90e161bSBill Fenner
6993340d773SGleb Smirnoff if (chunkLengthRemaining < sizeof(*sack)) {
700ee67461eSJoseph Mingrone ND_PRINT("bogus chunk length %u]", chunkLength);
7013340d773SGleb Smirnoff return;
7023340d773SGleb Smirnoff }
7033340d773SGleb Smirnoff sack=(const struct sctpSelectiveAck*)bp;
704ee67461eSJoseph Mingrone ND_PRINT("[cum ack %u] ", GET_BE_U_4(sack->highestConseqTSN));
705ee67461eSJoseph Mingrone ND_PRINT("[a_rwnd %u] ", GET_BE_U_4(sack->updatedRwnd));
706ee67461eSJoseph Mingrone ND_PRINT("[#gap acks %u] ", GET_BE_U_2(sack->numberOfdesc));
707ee67461eSJoseph Mingrone ND_PRINT("[#dup tsns %u] ", GET_BE_U_2(sack->numDupTsns));
7083340d773SGleb Smirnoff bp += sizeof(*sack);
7093340d773SGleb Smirnoff sctpPacketLengthRemaining -= sizeof(*sack);
7103340d773SGleb Smirnoff chunkLengthRemaining -= sizeof(*sack);
711a90e161bSBill Fenner
712a90e161bSBill Fenner
713a90e161bSBill Fenner /* print gaps */
7143340d773SGleb Smirnoff for (fragNo=0;
715ee67461eSJoseph Mingrone chunkLengthRemaining != 0 && fragNo < GET_BE_U_2(sack->numberOfdesc);
7163340d773SGleb Smirnoff bp += sizeof(*frag), sctpPacketLengthRemaining -= sizeof(*frag), chunkLengthRemaining -= sizeof(*frag), fragNo++) {
7173340d773SGleb Smirnoff if (chunkLengthRemaining < sizeof(*frag)) {
718ee67461eSJoseph Mingrone ND_PRINT("bogus chunk length %u]", chunkLength);
7193340d773SGleb Smirnoff return;
7203340d773SGleb Smirnoff }
7213340d773SGleb Smirnoff frag = (const struct sctpSelectiveFrag *)bp;
722ee67461eSJoseph Mingrone ND_PRINT("\n\t\t[gap ack block #%u: start = %u, end = %u] ",
723a90e161bSBill Fenner fragNo+1,
724ee67461eSJoseph Mingrone GET_BE_U_4(sack->highestConseqTSN) + GET_BE_U_2(frag->fragmentStart),
725ee67461eSJoseph Mingrone GET_BE_U_4(sack->highestConseqTSN) + GET_BE_U_2(frag->fragmentEnd));
7263340d773SGleb Smirnoff }
727a90e161bSBill Fenner
728a90e161bSBill Fenner /* print duplicate TSNs */
7293340d773SGleb Smirnoff for (tsnNo=0;
730ee67461eSJoseph Mingrone chunkLengthRemaining != 0 && tsnNo<GET_BE_U_2(sack->numDupTsns);
7313340d773SGleb Smirnoff bp += 4, sctpPacketLengthRemaining -= 4, chunkLengthRemaining -= 4, tsnNo++) {
7323340d773SGleb Smirnoff if (chunkLengthRemaining < 4) {
733ee67461eSJoseph Mingrone ND_PRINT("bogus chunk length %u]", chunkLength);
7343340d773SGleb Smirnoff return;
7353340d773SGleb Smirnoff }
7363340d773SGleb Smirnoff dupTSN = (const u_char *)bp;
737ee67461eSJoseph Mingrone ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
738ee67461eSJoseph Mingrone GET_BE_U_4(dupTSN));
7393340d773SGleb Smirnoff }
7403340d773SGleb Smirnoff break;
7413340d773SGleb Smirnoff }
7423340d773SGleb Smirnoff default :
7433340d773SGleb Smirnoff {
7443340d773SGleb Smirnoff bp += chunkLengthRemaining;
7453340d773SGleb Smirnoff sctpPacketLengthRemaining -= chunkLengthRemaining;
7463340d773SGleb Smirnoff chunkLengthRemaining = 0;
747a90e161bSBill Fenner break;
748a90e161bSBill Fenner }
749a90e161bSBill Fenner }
7501de50e9fSSam Leffler
7513340d773SGleb Smirnoff /*
7523340d773SGleb Smirnoff * Any extra stuff at the end of the chunk?
7533340d773SGleb Smirnoff * XXX - report this?
7543340d773SGleb Smirnoff */
7553340d773SGleb Smirnoff bp += chunkLengthRemaining;
7563340d773SGleb Smirnoff sctpPacketLengthRemaining -= chunkLengthRemaining;
7573340d773SGleb Smirnoff
7583c602fabSXin LI if (ndo->ndo_vflag < 2)
7591de50e9fSSam Leffler sep = ", (";
7603340d773SGleb Smirnoff
7613340d773SGleb Smirnoff if (align != 0) {
7623340d773SGleb Smirnoff /*
7633340d773SGleb Smirnoff * Fail if the alignment padding isn't in the captured data.
7643340d773SGleb Smirnoff * Otherwise, skip it.
7653340d773SGleb Smirnoff */
766ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, align);
7673340d773SGleb Smirnoff bp += align;
7683340d773SGleb Smirnoff sctpPacketLengthRemaining -= align;
7693340d773SGleb Smirnoff }
770a90e161bSBill Fenner }
771f4d0c64aSSam Leffler return;
772f4d0c64aSSam Leffler
773f4d0c64aSSam Leffler trunc:
774ee67461eSJoseph Mingrone nd_print_trunc(ndo);
775a90e161bSBill Fenner }
776