X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/06201e8b521887f2307f660c3f752080aa2cca00..4c2790a43252b9cac1fe7f6b50b51c3c55d2370a:/print-sctp.c diff --git a/print-sctp.c b/print-sctp.c index c6e002a8..a8990a9a 100644 --- a/print-sctp.c +++ b/print-sctp.c @@ -34,31 +34,20 @@ */ #ifndef lint -static const char rcsid[] = -"@(#) $Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.3 2001-05-09 02:42:50 itojun Exp $ (NETLAB/PEL)"; +static const char rcsid[] _U_ = +"@(#) $Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.21 2007-09-13 18:03:49 guy Exp $ (NETLAB/PEL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include -#include -#include +#include -#include #include "sctpHeader.h" #include "sctpConstants.h" #include -#if __STDC__ -struct mbuf; -struct rtentry; -#endif -#include - -#include - #include #include @@ -70,172 +59,226 @@ struct rtentry; #include "ip6.h" #endif +#define CHAN_HP 6704 +#define CHAN_MP 6705 +#define CHAN_LP 6706 + +struct tok ForCES_channels[] = { + { CHAN_HP, "ForCES HP" }, + { CHAN_MP, "ForCES MP" }, + { CHAN_LP, "ForCES LP" }, + { 0, NULL } +}; + +static inline int isForCES_port(u_short Port) +{ + if (Port == CHAN_HP) + return 1; + if (Port == CHAN_MP) + return 1; + if (Port == CHAN_LP) + return 1; + + return 0; +} + void sctp_print(const u_char *bp, /* beginning of sctp packet */ const u_char *bp2, /* beginning of enclosing */ u_int sctpPacketLength) /* ip packet */ -{ +{ const struct sctpHeader *sctpPktHdr; const struct ip *ip; #ifdef INET6 const struct ip6_hdr *ip6; #endif - const u_char *cp; - void *endPacketPtr; + const void *endPacketPtr; u_short sourcePort, destPort; int chunkCount; - struct sctpChunkDesc *chunkDescPtr; - void *nextChunk; + const struct sctpChunkDesc *chunkDescPtr; + const void *nextChunk; + const char *sep; + int isforces = 0; + + + sctpPktHdr = (const struct sctpHeader*) bp; + endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength; - sctpPktHdr = (struct sctpHeader*) bp; - endPacketPtr = ((u_char*)((u_char*)sctpPktHdr+sctpPacketLength)); - if( (u_long) endPacketPtr > (u_long) snapend) - endPacketPtr = (void *) snapend; + endPacketPtr = (const void *) snapend; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) - ip6 = (struct ip6_hdr *)bp2; + ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ - cp = (u_char *)(sctpPktHdr + 1); - if (cp > snapend) - { - printf("[|sctp]"); - return; - } - - if (sctpPacketLength < sizeof(struct sctpHeader)) + TCHECK(*sctpPktHdr); + + if (sctpPacketLength < sizeof(struct sctpHeader)) { - (void)printf("truncated-sctp - %d bytes missing!", - sctpPacketLength-sizeof(struct sctpHeader)); + (void)printf("truncated-sctp - %ld bytes missing!", + (long)sctpPacketLength-sizeof(struct sctpHeader)); return; } - + /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */ /* is now only as long as the payload */ - sourcePort = ntohs(sctpPktHdr->source); - destPort = ntohs(sctpPktHdr->destination); - + sourcePort = EXTRACT_16BITS(&sctpPktHdr->source); + destPort = EXTRACT_16BITS(&sctpPktHdr->destination); + #ifdef INET6 if (ip6) { - if (ip6->ip6_nxt == IPPROTO_SCTP) { - (void)printf("%s.%d > %s.%d: sctp", - ip6addr_string(&ip6->ip6_src), - sourcePort, - ip6addr_string(&ip6->ip6_dst), - destPort); - } else { - (void)printf("%d > %d: sctp", - sourcePort, destPort); - } + (void)printf("%s.%d > %s.%d: sctp", + ip6addr_string(&ip6->ip6_src), + sourcePort, + ip6addr_string(&ip6->ip6_dst), + destPort); } else #endif /*INET6*/ { - if (ip->ip_p == IPPROTO_SCTP) { - (void)printf("%s.%d > %s.%d: sctp", - ipaddr_string(&ip->ip_src), - sourcePort, - ipaddr_string(&ip->ip_dst), - destPort); - } else { - (void)printf("%d > %d: sctp", - sourcePort, destPort); - } + (void)printf("%s.%d > %s.%d: sctp", + ipaddr_string(&ip->ip_src), + sourcePort, + ipaddr_string(&ip->ip_dst), + destPort); } fflush(stdout); - if (vflag < 2) - return; - + if (isForCES_port(sourcePort)) { + printf("[%s]", tok2str(ForCES_channels, NULL, sourcePort)); + isforces = 1; + } + if (isForCES_port(destPort)) { + printf("[%s]", tok2str(ForCES_channels, NULL, destPort)); + isforces = 1; + } + + if (vflag >= 2) + sep = "\n\t"; + else + sep = " ("; /* cycle through all chunks, printing information on each one */ - for (chunkCount = 0, - chunkDescPtr = (struct sctpChunkDesc *) ( (u_char*) sctpPktHdr + - sizeof(struct sctpHeader)); + for (chunkCount = 0, + chunkDescPtr = (const struct sctpChunkDesc *) + ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader)); chunkDescPtr != NULL && - ( (void *) ((u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc)) + ( (const void *) + ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc)) <= endPacketPtr); - - chunkDescPtr = (struct sctpChunkDesc *) nextChunk, chunkCount++) + + chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++) { - u_short align; - u_char *chunkEnd; - - chunkEnd = ((u_char*)chunkDescPtr + ntohs(chunkDescPtr->chunkLength)); - - align=ntohs(chunkDescPtr->chunkLength) % 4; + u_int16_t chunkLength; + const u_char *chunkEnd; + u_int16_t align; + + TCHECK(*chunkDescPtr); + chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength); + if (chunkLength < sizeof(*chunkDescPtr)) { + printf("%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength); + break; + } + + TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength); + chunkEnd = ((const u_char*)chunkDescPtr + chunkLength); + + align=chunkLength % 4; if (align != 0) align = 4 - align; - nextChunk = (void *) (chunkEnd + align); + nextChunk = (const void *) (chunkEnd + align); - printf("\n\t%d) ", chunkCount+1); + printf("%s%d) ", sep, chunkCount+1); switch (chunkDescPtr->chunkID) { case SCTP_DATA : { - struct sctpDataPart *dataHdrPtr; - + const struct sctpDataPart *dataHdrPtr; + printf("[DATA] "); - - if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) + + if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) printf("(U)"); - if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) + if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) printf("(B)"); - - if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) + + if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) printf("(E)"); - if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) - == SCTP_DATA_UNORDERED) + if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) + == SCTP_DATA_UNORDERED) || - ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) + ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) || - ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) + ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ) printf(" "); - dataHdrPtr=(struct sctpDataPart*)(chunkDescPtr+1); - - printf("[TSN: %u] ", (u_int32_t)ntohl(dataHdrPtr->TSN)); - printf("[SID: %u] ", ntohs(dataHdrPtr->streamId)); - printf("[SSEQ %u] ", ntohs(dataHdrPtr->sequence)); - printf("[PPID 0x%x] ", (u_int32_t)ntohl(dataHdrPtr->payloadtype)); + dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1); + + printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN)); + printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId)); + printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence)); + printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr->payloadtype)); fflush(stdout); + if (isforces) { + const u_char *payloadPtr; + u_int chunksize = sizeof(struct sctpDataPart)+ + sizeof(struct sctpChunkDesc); + payloadPtr = (const u_char *) (dataHdrPtr + 1); + if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) < + sizeof(struct sctpDataPart)+ + sizeof(struct sctpChunkDesc)+1) { + /* Less than 1 byte of chunk payload */ + printf("bogus ForCES chunk length %u]", + EXTRACT_16BITS(&chunkDescPtr->chunkLength)); + return; + } + + forces_print(payloadPtr, EXTRACT_16BITS(&chunkDescPtr->chunkLength)- chunksize); + } else if (vflag >= 2) { /* if verbose output is specified */ + /* at the command line */ + const u_char *payloadPtr; - if (vflag) /* if verbose output is specified */ - { /* at the command line */ - char *payloadPtr; - - printf("[Payload: {"); - fflush(stdout); - - payloadPtr = (char *) (++dataHdrPtr); - write(STDOUT_FILENO, payloadPtr, - htons(chunkDescPtr->chunkLength)-1 - - sizeof(struct sctpDataPart)-sizeof(struct sctpChunkDesc)); - printf("}] "); - fflush(stdout); + printf("[Payload"); + + if (!suppress_default_print) { + payloadPtr = (const u_char *) (++dataHdrPtr); + printf(":"); + if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) < + sizeof(struct sctpDataPart)+ + sizeof(struct sctpChunkDesc)+1) { + /* Less than 1 byte of chunk payload */ + printf("bogus chunk length %u]", + EXTRACT_16BITS(&chunkDescPtr->chunkLength)); + return; + } + default_print(payloadPtr, + EXTRACT_16BITS(&chunkDescPtr->chunkLength) - + (sizeof(struct sctpDataPart)+ + sizeof(struct sctpChunkDesc))); + } else + printf("]"); } break; } case SCTP_INITIATION : { - struct sctpInitiation *init; + const struct sctpInitiation *init; printf("[INIT] "); - init=(struct sctpInitiation*)(chunkDescPtr+1); - printf("[init tag: %u] ", (u_int32_t)ntohl(init->initTag)); - printf("[rwnd: %u] ", (u_int32_t)ntohl(init->rcvWindowCredit)); - printf("[OS: %u] ", ntohs(init->NumPreopenStreams)); - printf("[MIS: %u] ", ntohs(init->MaxInboundStreams)); - printf("[init TSN: %u] ", (u_int32_t)ntohl(init->initialTSN)); + init=(const struct sctpInitiation*)(chunkDescPtr+1); + printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); + printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); + printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); + printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); + printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); #if(0) /* ALC you can add code for optional params here */ if( (init+1) < chunkEnd ) @@ -246,16 +289,16 @@ void sctp_print(const u_char *bp, /* beginning of sctp packet */ } case SCTP_INITIATION_ACK : { - struct sctpInitiation *init; - + const struct sctpInitiation *init; + printf("[INIT ACK] "); - init=(struct sctpInitiation*)(chunkDescPtr+1); - printf("[init tag: %u] ", (u_int32_t)ntohl(init->initTag)); - printf("[rwnd: %u] ", (u_int32_t)ntohl(init->rcvWindowCredit)); - printf("[OS: %u] ", ntohs(init->NumPreopenStreams)); - printf("[MIS: %u] ", ntohs(init->MaxInboundStreams)); - printf("[init TSN: %u] ", (u_int32_t)ntohl(init->initialTSN)); - + init=(const struct sctpInitiation*)(chunkDescPtr+1); + printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); + printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); + printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); + printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); + printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); + #if(0) /* ALC you can add code for optional params here */ if( (init+1) < chunkEnd ) printf(" @@@@@ UNFINISHED @@@@@@%s\n", @@ -265,48 +308,48 @@ void sctp_print(const u_char *bp, /* beginning of sctp packet */ } case SCTP_SELECTIVE_ACK: { - struct sctpSelectiveAck *sack; - struct sctpSelectiveFrag *frag; + const struct sctpSelectiveAck *sack; + const struct sctpSelectiveFrag *frag; int fragNo, tsnNo; - u_long *dupTSN; + const u_char *dupTSN; printf("[SACK] "); - sack=(struct sctpSelectiveAck*)(chunkDescPtr+1); - printf("[cum ack %u] ", (u_int32_t)ntohl(sack->highestConseqTSN)); - printf("[a_rwnd %u] ", (u_int32_t)ntohl(sack->updatedRwnd)); - printf("[#gap acks %u] ", ntohs(sack->numberOfdesc)); - printf("[#dup tsns %u] ", ntohs(sack->numDupTsns)); - - + sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1); + printf("[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN)); + printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd)); + printf("[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc)); + printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns)); + + /* print gaps */ - for (frag = ( (struct sctpSelectiveFrag *) - ((struct sctpSelectiveAck *) sack+1)), + for (frag = ( (const struct sctpSelectiveFrag *) + ((const struct sctpSelectiveAck *) sack+1)), fragNo=0; - (void *)frag < nextChunk && fragNo < ntohs(sack->numberOfdesc); + (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc); frag++, fragNo++) - printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ", + printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ", fragNo+1, - (u_int32_t)(ntohl(sack->highestConseqTSN) + ntohs(frag->fragmentStart)), - (u_int32_t)(ntohl(sack->highestConseqTSN) + ntohs(frag->fragmentEnd))); - + EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart), + EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd)); + /* print duplicate TSNs */ - for (dupTSN = (u_long*)frag, tsnNo=0; - (void *) dupTSN < nextChunk && tsnNonumDupTsns); - dupTSN++, tsnNo++) + for (dupTSN = (const u_char *)frag, tsnNo=0; + (const void *) dupTSN < nextChunk && tsnNonumDupTsns); + dupTSN += 4, tsnNo++) printf("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, - (u_int32_t)ntohl(*dupTSN)); + EXTRACT_32BITS(dupTSN)); break; } case SCTP_HEARTBEAT_REQUEST : { - struct sctpHBsender *hb; + const struct sctpHBsender *hb; - hb=(struct sctpHBsender*)chunkDescPtr; + hb=(const struct sctpHBsender*)chunkDescPtr; printf("[HB REQ] "); - + break; } case SCTP_HEARTBEAT_ACK : @@ -333,7 +376,7 @@ void sctp_print(const u_char *bp, /* beginning of sctp packet */ case SCTP_ECN_ECHO : printf("[ECN ECHO] "); break; - case SCTP_ECN_CWR : + case SCTP_ECN_CWR : printf("[ECN CWR] "); break; case SCTP_SHUTDOWN_COMPLETE : @@ -352,5 +395,13 @@ void sctp_print(const u_char *bp, /* beginning of sctp packet */ printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID); return; } + + if (vflag < 2) + sep = ", ("; } + return; + +trunc: + printf("[|sctp]"); + return; }