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