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 37 static const char rcsid[] _U_ = 38 "@(#) $Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.16.2.4 2005/07/07 01:24:38 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 printf("bogus chunk length %u]", 210 htons(chunkDescPtr->chunkLength)); 211 return; 212 } 213 default_print(payloadPtr, 214 htons(chunkDescPtr->chunkLength) - 215 (sizeof(struct sctpDataPart)+ 216 sizeof(struct sctpChunkDesc)+1)); 217 } else 218 printf("]"); 219 } 220 break; 221 } 222 case SCTP_INITIATION : 223 { 224 const struct sctpInitiation *init; 225 226 printf("[INIT] "); 227 init=(const struct sctpInitiation*)(chunkDescPtr+1); 228 printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); 229 printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); 230 printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); 231 printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); 232 printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); 233 234 #if(0) /* ALC you can add code for optional params here */ 235 if( (init+1) < chunkEnd ) 236 printf(" @@@@@ UNFINISHED @@@@@@%s\n", 237 "Optional params present, but not printed."); 238 #endif 239 break; 240 } 241 case SCTP_INITIATION_ACK : 242 { 243 const struct sctpInitiation *init; 244 245 printf("[INIT ACK] "); 246 init=(const struct sctpInitiation*)(chunkDescPtr+1); 247 printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); 248 printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); 249 printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); 250 printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); 251 printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); 252 253 #if(0) /* ALC you can add code for optional params here */ 254 if( (init+1) < chunkEnd ) 255 printf(" @@@@@ UNFINISHED @@@@@@%s\n", 256 "Optional params present, but not printed."); 257 #endif 258 break; 259 } 260 case SCTP_SELECTIVE_ACK: 261 { 262 const struct sctpSelectiveAck *sack; 263 const struct sctpSelectiveFrag *frag; 264 int fragNo, tsnNo; 265 const u_char *dupTSN; 266 267 printf("[SACK] "); 268 sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1); 269 printf("[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN)); 270 printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd)); 271 printf("[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc)); 272 printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns)); 273 274 275 /* print gaps */ 276 for (frag = ( (const struct sctpSelectiveFrag *) 277 ((const struct sctpSelectiveAck *) sack+1)), 278 fragNo=0; 279 (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc); 280 frag++, fragNo++) 281 printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ", 282 fragNo+1, 283 EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart), 284 EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd)); 285 286 287 /* print duplicate TSNs */ 288 for (dupTSN = (const u_char *)frag, tsnNo=0; 289 (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns); 290 dupTSN += 4, tsnNo++) 291 printf("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, 292 EXTRACT_32BITS(dupTSN)); 293 294 break; 295 } 296 case SCTP_HEARTBEAT_REQUEST : 297 { 298 const struct sctpHBsender *hb; 299 300 hb=(const struct sctpHBsender*)chunkDescPtr; 301 302 printf("[HB REQ] "); 303 304 break; 305 } 306 case SCTP_HEARTBEAT_ACK : 307 printf("[HB ACK] "); 308 break; 309 case SCTP_ABORT_ASSOCIATION : 310 printf("[ABORT] "); 311 break; 312 case SCTP_SHUTDOWN : 313 printf("[SHUTDOWN] "); 314 break; 315 case SCTP_SHUTDOWN_ACK : 316 printf("[SHUTDOWN ACK] "); 317 break; 318 case SCTP_OPERATION_ERR : 319 printf("[OP ERR] "); 320 break; 321 case SCTP_COOKIE_ECHO : 322 printf("[COOKIE ECHO] "); 323 break; 324 case SCTP_COOKIE_ACK : 325 printf("[COOKIE ACK] "); 326 break; 327 case SCTP_ECN_ECHO : 328 printf("[ECN ECHO] "); 329 break; 330 case SCTP_ECN_CWR : 331 printf("[ECN CWR] "); 332 break; 333 case SCTP_SHUTDOWN_COMPLETE : 334 printf("[SHUTDOWN COMPLETE] "); 335 break; 336 case SCTP_FORWARD_CUM_TSN : 337 printf("[FOR CUM TSN] "); 338 break; 339 case SCTP_RELIABLE_CNTL : 340 printf("[REL CTRL] "); 341 break; 342 case SCTP_RELIABLE_CNTL_ACK : 343 printf("[REL CTRL ACK] "); 344 break; 345 default : 346 printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID); 347 return; 348 } 349 350 if (vflag < 2) 351 sep = ", ("; 352 } 353 return; 354 355 trunc: 356 printf("[|sctp]"); 357 return; 358 } 359