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