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.21 2007-09-13 18:03:49 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 #define CHAN_HP 6704
     63 #define CHAN_MP 6705
     64 #define CHAN_LP 6706
     65 
     66 static const struct tok ForCES_channels[] = {
     67 	{ CHAN_HP, "ForCES HP" },
     68 	{ CHAN_MP, "ForCES MP" },
     69 	{ CHAN_LP, "ForCES LP" },
     70 	{ 0, NULL }
     71 };
     72 
     73 static inline int isForCES_port(u_short Port)
     74 {
     75 	if (Port == CHAN_HP)
     76 		return 1;
     77 	if (Port == CHAN_MP)
     78 		return 1;
     79 	if (Port == CHAN_LP)
     80 		return 1;
     81 
     82 	return 0;
     83 }
     84 
     85 void sctp_print(const u_char *bp,        /* beginning of sctp packet */
     86 		const u_char *bp2,       /* beginning of enclosing */
     87 		u_int sctpPacketLength)  /* ip packet */
     88 {
     89   const struct sctpHeader *sctpPktHdr;
     90   const struct ip *ip;
     91 #ifdef INET6
     92   const struct ip6_hdr *ip6;
     93 #endif
     94   const void *endPacketPtr;
     95   u_short sourcePort, destPort;
     96   int chunkCount;
     97   const struct sctpChunkDesc *chunkDescPtr;
     98   const void *nextChunk;
     99   const char *sep;
    100   int isforces = 0;
    101 
    102 
    103   sctpPktHdr = (const struct sctpHeader*) bp;
    104   endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength;
    105 
    106   if( (u_long) endPacketPtr > (u_long) snapend)
    107     endPacketPtr = (const void *) snapend;
    108   ip = (struct ip *)bp2;
    109 #ifdef INET6
    110   if (IP_V(ip) == 6)
    111     ip6 = (const struct ip6_hdr *)bp2;
    112   else
    113     ip6 = NULL;
    114 #endif /*INET6*/
    115   TCHECK(*sctpPktHdr);
    116 
    117   if (sctpPacketLength < sizeof(struct sctpHeader))
    118     {
    119       (void)printf("truncated-sctp - %ld bytes missing!",
    120 		   (long)sctpPacketLength-sizeof(struct sctpHeader));
    121       return;
    122     }
    123 
    124   /*    sctpPacketLength -= sizeof(struct sctpHeader);  packet length  */
    125   /*  			      is now only as long as the payload  */
    126 
    127   sourcePort = EXTRACT_16BITS(&sctpPktHdr->source);
    128   destPort = EXTRACT_16BITS(&sctpPktHdr->destination);
    129 
    130 #ifdef INET6
    131   if (ip6) {
    132     (void)printf("%s.%d > %s.%d: sctp",
    133       ip6addr_string(&ip6->ip6_src),
    134       sourcePort,
    135       ip6addr_string(&ip6->ip6_dst),
    136       destPort);
    137   } else
    138 #endif /*INET6*/
    139   {
    140     (void)printf("%s.%d > %s.%d: sctp",
    141       ipaddr_string(&ip->ip_src),
    142       sourcePort,
    143       ipaddr_string(&ip->ip_dst),
    144       destPort);
    145   }
    146   fflush(stdout);
    147 
    148   if (isForCES_port(sourcePort)) {
    149          printf("[%s]", tok2str(ForCES_channels, NULL, sourcePort));
    150          isforces = 1;
    151   }
    152   if (isForCES_port(destPort)) {
    153          printf("[%s]", tok2str(ForCES_channels, NULL, destPort));
    154          isforces = 1;
    155   }
    156 
    157   if (vflag >= 2)
    158     sep = "\n\t";
    159   else
    160     sep = " (";
    161   /* cycle through all chunks, printing information on each one */
    162   for (chunkCount = 0,
    163 	 chunkDescPtr = (const struct sctpChunkDesc *)
    164 	    ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader));
    165        chunkDescPtr != NULL &&
    166 	 ( (const void *)
    167 	    ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc))
    168 	   <= endPacketPtr);
    169 
    170        chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++)
    171     {
    172       u_int16_t chunkLength;
    173       const u_char *chunkEnd;
    174       u_int16_t align;
    175 
    176       TCHECK(*chunkDescPtr);
    177       chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength);
    178       if (chunkLength < sizeof(*chunkDescPtr)) {
    179       	printf("%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength);
    180       	break;
    181       }
    182 
    183       TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength);
    184       chunkEnd = ((const u_char*)chunkDescPtr + chunkLength);
    185 
    186       align=chunkLength % 4;
    187       if (align != 0)
    188 	align = 4 - align;
    189 
    190       nextChunk = (const void *) (chunkEnd + align);
    191 
    192       printf("%s%d) ", sep, chunkCount+1);
    193       switch (chunkDescPtr->chunkID)
    194 	{
    195 	case SCTP_DATA :
    196 	  {
    197 	    const struct sctpDataPart *dataHdrPtr;
    198 
    199 	    printf("[DATA] ");
    200 
    201 	    if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
    202 		== SCTP_DATA_UNORDERED)
    203 	      printf("(U)");
    204 
    205 	    if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
    206 		== SCTP_DATA_FIRST_FRAG)
    207 	      printf("(B)");
    208 
    209 	    if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
    210 		== SCTP_DATA_LAST_FRAG)
    211 	      printf("(E)");
    212 
    213 	    if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED)
    214 		 == SCTP_DATA_UNORDERED)
    215 		||
    216 		((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG)
    217 		 == SCTP_DATA_FIRST_FRAG)
    218 		||
    219 		((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG)
    220 		 == SCTP_DATA_LAST_FRAG) )
    221 	      printf(" ");
    222 
    223 	    dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1);
    224 
    225 	    printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN));
    226 	    printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId));
    227 	    printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence));
    228 	    printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr->payloadtype));
    229 	    fflush(stdout);
    230 	    if (isforces) {
    231 		const u_char *payloadPtr;
    232 		u_int chunksize = sizeof(struct sctpDataPart)+
    233 			          sizeof(struct sctpChunkDesc);
    234 		payloadPtr = (const u_char *) (dataHdrPtr + 1);
    235 		if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) <
    236 			sizeof(struct sctpDataPart)+
    237 			sizeof(struct sctpChunkDesc)+1) {
    238 		/* Less than 1 byte of chunk payload */
    239 			printf("bogus ForCES chunk length %u]",
    240 			    EXTRACT_16BITS(&chunkDescPtr->chunkLength));
    241 			return;
    242 		}
    243 
    244 		forces_print(payloadPtr, EXTRACT_16BITS(&chunkDescPtr->chunkLength)- chunksize);
    245 	   } else if (vflag >= 2) {	/* if verbose output is specified */
    246 					/* at the command line */
    247 		const u_char *payloadPtr;
    248 
    249 		printf("[Payload");
    250 
    251 		if (!suppress_default_print) {
    252 			payloadPtr = (const u_char *) (++dataHdrPtr);
    253 			printf(":");
    254 			if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) <
    255 			    sizeof(struct sctpDataPart)+
    256 			    sizeof(struct sctpChunkDesc)+1) {
    257 				/* Less than 1 byte of chunk payload */
    258 				printf("bogus chunk length %u]",
    259 				    EXTRACT_16BITS(&chunkDescPtr->chunkLength));
    260 				return;
    261 			}
    262 			default_print(payloadPtr,
    263 			      EXTRACT_16BITS(&chunkDescPtr->chunkLength) -
    264 			      (sizeof(struct sctpDataPart)+
    265 			      sizeof(struct sctpChunkDesc)));
    266 		} else
    267 			printf("]");
    268 	      }
    269 	    break;
    270 	  }
    271 	case SCTP_INITIATION :
    272 	  {
    273 	    const struct sctpInitiation *init;
    274 
    275 	    printf("[INIT] ");
    276 	    init=(const struct sctpInitiation*)(chunkDescPtr+1);
    277 	    printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag));
    278 	    printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit));
    279 	    printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams));
    280 	    printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams));
    281 	    printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN));
    282 
    283 #if(0) /* ALC you can add code for optional params here */
    284 	    if( (init+1) < chunkEnd )
    285 	      printf(" @@@@@ UNFINISHED @@@@@@%s\n",
    286 		     "Optional params present, but not printed.");
    287 #endif
    288 	    break;
    289 	  }
    290 	case SCTP_INITIATION_ACK :
    291 	  {
    292 	    const struct sctpInitiation *init;
    293 
    294 	    printf("[INIT ACK] ");
    295 	    init=(const struct sctpInitiation*)(chunkDescPtr+1);
    296 	    printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag));
    297 	    printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit));
    298 	    printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams));
    299 	    printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams));
    300 	    printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN));
    301 
    302 #if(0) /* ALC you can add code for optional params here */
    303 	    if( (init+1) < chunkEnd )
    304 	      printf(" @@@@@ UNFINISHED @@@@@@%s\n",
    305 		     "Optional params present, but not printed.");
    306 #endif
    307 	    break;
    308 	  }
    309 	case SCTP_SELECTIVE_ACK:
    310 	  {
    311 	    const struct sctpSelectiveAck *sack;
    312 	    const struct sctpSelectiveFrag *frag;
    313 	    int fragNo, tsnNo;
    314 	    const u_char *dupTSN;
    315 
    316 	    printf("[SACK] ");
    317 	    sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1);
    318 	    printf("[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN));
    319 	    printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd));
    320 	    printf("[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc));
    321 	    printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns));
    322 
    323 
    324 	    /* print gaps */
    325 	    for (frag = ( (const struct sctpSelectiveFrag *)
    326 			  ((const struct sctpSelectiveAck *) sack+1)),
    327 		   fragNo=0;
    328 		 (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc);
    329 		 frag++, fragNo++)
    330 	      printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ",
    331 		     fragNo+1,
    332 		     EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart),
    333 		     EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd));
    334 
    335 
    336 	    /* print duplicate TSNs */
    337 	    for (dupTSN = (const u_char *)frag, tsnNo=0;
    338 		 (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns);
    339 		 dupTSN += 4, tsnNo++)
    340 	      printf("\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
    341 	          EXTRACT_32BITS(dupTSN));
    342 
    343 	    break;
    344 	  }
    345 	case SCTP_HEARTBEAT_REQUEST :
    346 	  printf("[HB REQ] ");
    347 	  break;
    348 	case SCTP_HEARTBEAT_ACK :
    349 	  printf("[HB ACK] ");
    350 	  break;
    351 	case SCTP_ABORT_ASSOCIATION :
    352 	  printf("[ABORT] ");
    353 	  break;
    354 	case SCTP_SHUTDOWN :
    355 	  printf("[SHUTDOWN] ");
    356 	  break;
    357 	case SCTP_SHUTDOWN_ACK :
    358 	  printf("[SHUTDOWN ACK] ");
    359 	  break;
    360 	case SCTP_OPERATION_ERR :
    361 	  printf("[OP ERR] ");
    362 	  break;
    363 	case SCTP_COOKIE_ECHO :
    364 	  printf("[COOKIE ECHO] ");
    365 	  break;
    366 	case SCTP_COOKIE_ACK :
    367 	  printf("[COOKIE ACK] ");
    368 	  break;
    369 	case SCTP_ECN_ECHO :
    370 	  printf("[ECN ECHO] ");
    371 	  break;
    372 	case SCTP_ECN_CWR :
    373 	  printf("[ECN CWR] ");
    374 	  break;
    375 	case SCTP_SHUTDOWN_COMPLETE :
    376 	  printf("[SHUTDOWN COMPLETE] ");
    377 	  break;
    378 	case SCTP_FORWARD_CUM_TSN :
    379 	  printf("[FOR CUM TSN] ");
    380 	  break;
    381 	case SCTP_RELIABLE_CNTL :
    382 	  printf("[REL CTRL] ");
    383 	  break;
    384 	case SCTP_RELIABLE_CNTL_ACK :
    385 	  printf("[REL CTRL ACK] ");
    386 	  break;
    387 	default :
    388 	  printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID);
    389 	  return;
    390 	}
    391 
    392 	if (vflag < 2)
    393 	  sep = ", (";
    394     }
    395     return;
    396 
    397 trunc:
    398     printf("[|sctp]");
    399     return;
    400 }
    401