Home | History | Annotate | Download | only in tcpdump
      1 /* Copyright (c) 2001 NETLAB, Temple University
      2  * Copyright (c) 2001 Protocol Engineering Lab, University of Delaware
      3  *
      4  * Jerry Heinz <gheinz (at) astro.temple.edu>
      5  * John Fiore <jfiore (at) joda.cis.temple.edu>
      6  * Armando L. Caro Jr. <acaro (at) 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 #ifndef lint
     37 static const char rcsid[] _U_ =
     38 "@(#) $Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.16.2.5 2007/09/13 18:04:58 guy Exp $ (NETLAB/PEL)";
     39 #endif
     40 
     41 #ifdef HAVE_CONFIG_H
     42 #include "config.h"
     43 #endif
     44 
     45 #include <tcpdump-stdinc.h>
     46 
     47 #include "sctpHeader.h"
     48 #include "sctpConstants.h"
     49 #include <assert.h>
     50 
     51 #include <stdio.h>
     52 #include <string.h>
     53 
     54 #include "interface.h"
     55 #include "addrtoname.h"
     56 #include "extract.h"			/* must come after interface.h */
     57 #include "ip.h"
     58 #ifdef INET6
     59 #include "ip6.h"
     60 #endif
     61 
     62 void sctp_print(const u_char *bp,        /* beginning of sctp packet */
     63 		const u_char *bp2,       /* beginning of enclosing */
     64 		u_int sctpPacketLength)  /* ip packet */
     65 {
     66   const struct sctpHeader *sctpPktHdr;
     67   const struct ip *ip;
     68 #ifdef INET6
     69   const struct ip6_hdr *ip6;
     70 #endif
     71   const void *endPacketPtr;
     72   u_short sourcePort, destPort;
     73   int chunkCount;
     74   const struct sctpChunkDesc *chunkDescPtr;
     75   const void *nextChunk;
     76   const char *sep;
     77 
     78   sctpPktHdr = (const struct sctpHeader*) bp;
     79   endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength;
     80 
     81   if( (u_long) endPacketPtr > (u_long) snapend)
     82     endPacketPtr = (const void *) snapend;
     83   ip = (struct ip *)bp2;
     84 #ifdef INET6
     85   if (IP_V(ip) == 6)
     86     ip6 = (const struct ip6_hdr *)bp2;
     87   else
     88     ip6 = NULL;
     89 #endif /*INET6*/
     90   TCHECK(*sctpPktHdr);
     91 
     92   if (sctpPacketLength < sizeof(struct sctpHeader))
     93     {
     94       (void)printf("truncated-sctp - %ld bytes missing!",
     95 		   (long)sctpPacketLength-sizeof(struct sctpHeader));
     96       return;
     97     }
     98 
     99   /*    sctpPacketLength -= sizeof(struct sctpHeader);  packet length  */
    100   /*  			      is now only as long as the payload  */
    101 
    102   sourcePort = EXTRACT_16BITS(&sctpPktHdr->source);
    103   destPort = EXTRACT_16BITS(&sctpPktHdr->destination);
    104 
    105 #ifdef INET6
    106   if (ip6) {
    107     (void)printf("%s.%d > %s.%d: sctp",
    108       ip6addr_string(&ip6->ip6_src),
    109       sourcePort,
    110       ip6addr_string(&ip6->ip6_dst),
    111       destPort);
    112   } else
    113 #endif /*INET6*/
    114   {
    115     (void)printf("%s.%d > %s.%d: sctp",
    116       ipaddr_string(&ip->ip_src),
    117       sourcePort,
    118       ipaddr_string(&ip->ip_dst),
    119       destPort);
    120   }
    121   fflush(stdout);
    122 
    123   if (vflag >= 2)
    124     sep = "\n\t";
    125   else
    126     sep = " (";
    127   /* cycle through all chunks, printing information on each one */
    128   for (chunkCount = 0,
    129 	 chunkDescPtr = (const struct sctpChunkDesc *)
    130 	    ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader));
    131        chunkDescPtr != NULL &&
    132 	 ( (const void *)
    133 	    ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc))
    134 	   <= endPacketPtr);
    135 
    136        chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++)
    137     {
    138       u_int16_t chunkLength;
    139       const u_char *chunkEnd;
    140       u_int16_t align;
    141 
    142       TCHECK(*chunkDescPtr);
    143       chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength);
    144       if (chunkLength < sizeof(*chunkDescPtr)) {
    145       	printf("%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength);
    146       	break;
    147       }
    148 
    149       TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength);
    150       chunkEnd = ((const u_char*)chunkDescPtr + chunkLength);
    151 
    152       align=chunkLength % 4;
    153       if (align != 0)
    154 	align = 4 - align;
    155 
    156       nextChunk = (const void *) (chunkEnd + align);
    157 
    158       printf("%s%d) ", sep, chunkCount+1);
    159       switch (chunkDescPtr->chunkID)
    160 	{
    161 	case SCTP_DATA :
    162 	  {
    163 	    const struct sctpDataPart *dataHdrPtr;
    164 
    165 	    printf("[DATA] ");
    166 
    167 	    if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
    168 		== SCTP_DATA_UNORDERED)
    169 	      printf("(U)");
    170 
    171 	    if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
    172 		== SCTP_DATA_FIRST_FRAG)
    173 	      printf("(B)");
    174 
    175 	    if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
    176 		== SCTP_DATA_LAST_FRAG)
    177 	      printf("(E)");
    178 
    179 	    if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
    180 		 == SCTP_DATA_UNORDERED)
    181 		||
    182 		((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
    183 		 == SCTP_DATA_FIRST_FRAG)
    184 		||
    185 		((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
    186 		 == SCTP_DATA_LAST_FRAG) )
    187 	      printf(" ");
    188 
    189 	    dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1);
    190 
    191 	    printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN));
    192 	    printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId));
    193 	    printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence));
    194 	    printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr->payloadtype));
    195 	    fflush(stdout);
    196 
    197 	    if (vflag >= 2)	   /* if verbose output is specified */
    198 	      {		           /* at the command line */
    199 		const u_char *payloadPtr;
    200 
    201 		printf("[Payload");
    202 
    203 		if (!suppress_default_print) {
    204 			payloadPtr = (const u_char *) (++dataHdrPtr);
    205 			printf(":");
    206 			if (htons(chunkDescPtr->chunkLength) <
    207 			    sizeof(struct sctpDataPart)+
    208 			    sizeof(struct sctpChunkDesc)+1) {
    209 				/* Less than 1 byte of chunk payload */
    210 				printf("bogus chunk length %u]",
    211 				    htons(chunkDescPtr->chunkLength));
    212 				return;
    213 			}
    214 			default_print(payloadPtr,
    215 			      htons(chunkDescPtr->chunkLength) -
    216 			      (sizeof(struct sctpDataPart)+
    217 			      sizeof(struct sctpChunkDesc)));
    218 		} else
    219 			printf("]");
    220 	      }
    221 	    break;
    222 	  }
    223 	case SCTP_INITIATION :
    224 	  {
    225 	    const struct sctpInitiation *init;
    226 
    227 	    printf("[INIT] ");
    228 	    init=(const struct sctpInitiation*)(chunkDescPtr+1);
    229 	    printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag));
    230 	    printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit));
    231 	    printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams));
    232 	    printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams));
    233 	    printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN));
    234 
    235 #if(0) /* ALC you can add code for optional params here */
    236 	    if( (init+1) < chunkEnd )
    237 	      printf(" @@@@@ UNFINISHED @@@@@@%s\n",
    238 		     "Optional params present, but not printed.");
    239 #endif
    240 	    break;
    241 	  }
    242 	case SCTP_INITIATION_ACK :
    243 	  {
    244 	    const struct sctpInitiation *init;
    245 
    246 	    printf("[INIT ACK] ");
    247 	    init=(const struct sctpInitiation*)(chunkDescPtr+1);
    248 	    printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag));
    249 	    printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit));
    250 	    printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams));
    251 	    printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams));
    252 	    printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN));
    253 
    254 #if(0) /* ALC you can add code for optional params here */
    255 	    if( (init+1) < chunkEnd )
    256 	      printf(" @@@@@ UNFINISHED @@@@@@%s\n",
    257 		     "Optional params present, but not printed.");
    258 #endif
    259 	    break;
    260 	  }
    261 	case SCTP_SELECTIVE_ACK:
    262 	  {
    263 	    const struct sctpSelectiveAck *sack;
    264 	    const struct sctpSelectiveFrag *frag;
    265 	    int fragNo, tsnNo;
    266 	    const u_char *dupTSN;
    267 
    268 	    printf("[SACK] ");
    269 	    sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1);
    270 	    printf("[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN));
    271 	    printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd));
    272 	    printf("[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc));
    273 	    printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns));
    274 
    275 
    276 	    /* print gaps */
    277 	    for (frag = ( (const struct sctpSelectiveFrag *)
    278 			  ((const struct sctpSelectiveAck *) sack+1)),
    279 		   fragNo=0;
    280 		 (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc);
    281 		 frag++, fragNo++)
    282 	      printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ",
    283 		     fragNo+1,
    284 		     EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart),
    285 		     EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd));
    286 
    287 
    288 	    /* print duplicate TSNs */
    289 	    for (dupTSN = (const u_char *)frag, tsnNo=0;
    290 		 (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns);
    291 		 dupTSN += 4, tsnNo++)
    292 	      printf("\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
    293 	          EXTRACT_32BITS(dupTSN));
    294 
    295 	    break;
    296 	  }
    297 	case SCTP_HEARTBEAT_REQUEST :
    298 	  {
    299 	    const struct sctpHBsender *hb;
    300 
    301 	    hb=(const struct sctpHBsender*)chunkDescPtr;
    302 
    303 	    printf("[HB REQ] ");
    304 
    305 	    break;
    306 	  }
    307 	case SCTP_HEARTBEAT_ACK :
    308 	  printf("[HB ACK] ");
    309 	  break;
    310 	case SCTP_ABORT_ASSOCIATION :
    311 	  printf("[ABORT] ");
    312 	  break;
    313 	case SCTP_SHUTDOWN :
    314 	  printf("[SHUTDOWN] ");
    315 	  break;
    316 	case SCTP_SHUTDOWN_ACK :
    317 	  printf("[SHUTDOWN ACK] ");
    318 	  break;
    319 	case SCTP_OPERATION_ERR :
    320 	  printf("[OP ERR] ");
    321 	  break;
    322 	case SCTP_COOKIE_ECHO :
    323 	  printf("[COOKIE ECHO] ");
    324 	  break;
    325 	case SCTP_COOKIE_ACK :
    326 	  printf("[COOKIE ACK] ");
    327 	  break;
    328 	case SCTP_ECN_ECHO :
    329 	  printf("[ECN ECHO] ");
    330 	  break;
    331 	case SCTP_ECN_CWR :
    332 	  printf("[ECN CWR] ");
    333 	  break;
    334 	case SCTP_SHUTDOWN_COMPLETE :
    335 	  printf("[SHUTDOWN COMPLETE] ");
    336 	  break;
    337 	case SCTP_FORWARD_CUM_TSN :
    338 	  printf("[FOR CUM TSN] ");
    339 	  break;
    340 	case SCTP_RELIABLE_CNTL :
    341 	  printf("[REL CTRL] ");
    342 	  break;
    343 	case SCTP_RELIABLE_CNTL_ACK :
    344 	  printf("[REL CTRL ACK] ");
    345 	  break;
    346 	default :
    347 	  printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID);
    348 	  return;
    349 	}
    350 
    351 	if (vflag < 2)
    352 	  sep = ", (";
    353     }
    354     return;
    355 
    356 trunc:
    357     printf("[|sctp]");
    358     return;
    359 }
    360