diff options
author | olah <olah@FreeBSD.org> | 1995-03-08 13:13:01 +0000 |
---|---|---|
committer | olah <olah@FreeBSD.org> | 1995-03-08 13:13:01 +0000 |
commit | 82f9d23eb5277a4f7f1a5ffa77125e4f162ca5b9 (patch) | |
tree | cc1cc24bc7b1d8b721e4fd706110c2c41d4237f2 /usr.sbin/tcpdump | |
parent | 48fc7bedf7186fa650bf61612b46dacd1522a4a2 (diff) | |
download | FreeBSD-src-82f9d23eb5277a4f7f1a5ffa77125e4f162ca5b9.zip FreeBSD-src-82f9d23eb5277a4f7f1a5ffa77125e4f162ca5b9.tar.gz |
Make tcpdump understand the T/TCP (RFC-1644) options. Some extra sanity
checks were also introduced to the tcp_print function so it doesn't try
to interpret TCP options beyond the length of the sniffed packet.
Diffstat (limited to 'usr.sbin/tcpdump')
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/print-tcp.c | 151 |
1 files changed, 91 insertions, 60 deletions
diff --git a/usr.sbin/tcpdump/tcpdump/print-tcp.c b/usr.sbin/tcpdump/tcpdump/print-tcp.c index 6e1e58d..0642315 100644 --- a/usr.sbin/tcpdump/tcpdump/print-tcp.c +++ b/usr.sbin/tcpdump/tcpdump/print-tcp.c @@ -21,7 +21,7 @@ #ifndef lint static char rcsid[] = - "@(#) $Header: print-tcp.c,v 1.28 94/06/16 01:26:40 mccanne Exp $ (LBL)"; + "@(#) $Header: /home/ncvs/src/usr.sbin/tcpdump/tcpdump/print-tcp.c,v 1.2 1995/03/08 12:52:44 olah Exp $ (LBL)"; #endif #include <sys/param.h> @@ -62,6 +62,39 @@ static char rcsid[] = #ifndef TCPOPT_TIMESTAMP #define TCPOPT_TIMESTAMP 8 /* timestamps (rfc1323) */ #endif +#ifndef TCPOPT_CC +#define TCPOPT_CC 11 /* connection count (rfc1644) */ +#endif +#ifndef TCPOPT_CCNEW +#define TCPOPT_CCNEW 12 /* connection count new (rfc1644) */ +#endif +#ifndef TCPOPT_CCECHO +#define TCPOPT_CCECHO 13 /* connection count echo (rfc1644) */ +#endif + +struct opt_table { + int len; /* option length, zero if unknown */ + const char *nam; /* option name */ +}; + +static struct opt_table tcp_opts[] = { + { 1, "eol" }, + { 1, "nop" }, + { 4, "mss" }, + { 3, "wscale" }, + { 2, "sackOK" }, + { 0, "sack" }, /* XXX sack: don't know how long */ + { 6, "echo" }, + { 6, "echoreply" }, + {10, "timestamp" }, + { 0, "opt-%d:" }, + { 0, "opt-%d:" }, + { 6, "cc" }, + { 6, "ccnew" }, + { 6, "ccecho" }, + { 0, "opt-%d:" }, /* last entry must be an unknown option */ +}; +#define MAXTCPOPT (sizeof(tcp_opts)/sizeof(tcp_opts[0])-1) struct tha { struct in_addr src; @@ -193,84 +226,82 @@ tcp_print(register const u_char *bp, register int length, register const u_char *cp = (const u_char *)tp + sizeof(*tp); int i; char ch = '<'; + char lch = '>'; putchar(' '); - while (--hlen >= 0) { + /* adjust length if necessary */ + if (cp + hlen > snapend) { + hlen = snapend - cp; + lch = '|'; + } + while (hlen > 0) { + register struct opt_table *opt; + putchar(ch); - switch (*cp++) { - case TCPOPT_MAXSEG: - { - (void)printf("mss %d", cp[1] << 8 | cp[2]); - if (*cp != 4) - (void)printf("[len %d]", *cp); - cp += 3; - hlen -= 3; - break; + ch = ','; + + opt = *cp < MAXTCPOPT ? + &tcp_opts[*cp] : &tcp_opts[MAXTCPOPT]; + (void)printf(opt->nam, *cp); + + /* eol and nop have no length */ + if (opt->len == 1) { + hlen--, cp++; + continue; } - case TCPOPT_EOL: - (void)printf("eol"); + /* quit if options are truncated */ + if ((hlen == 1) || + (opt->len != 0 && hlen < opt->len) || + (opt->len == 0 && hlen < *(cp + 1))) { + lch = '|'; break; - case TCPOPT_NOP: - (void)printf("nop"); + } + /* check if optlen in segment is what we assume */ + if (opt->len != 0 && *(cp + 1) != opt->len) { + register int l = *(cp + 1); + + (void)printf("[len %d]", l); + hlen -= l; + cp += l; + continue; + } + + /* print the option body */ + switch (*cp) { + case TCPOPT_MAXSEG: + (void)printf(" %d", cp[2] << 8 | cp[3]); break; case TCPOPT_WSCALE: - (void)printf("wscale %d", cp[1]); - if (*cp != 3) - (void)printf("[len %d]", *cp); - cp += 2; - hlen -= 2; + (void)printf(" %d", cp[2]); break; case TCPOPT_SACKOK: - (void)printf("sackOK"); - if (*cp != 2) - (void)printf("[len %d]", *cp); - cp += 1; - hlen -= 1; break; case TCPOPT_ECHO: - { - (void)printf("echo %u", - cp[1] << 24 | cp[2] << 16 | - cp[3] << 8 | cp[4]); - if (*cp != 6) - (void)printf("[len %d]", *cp); - cp += 5; - hlen -= 5; - break; - } case TCPOPT_ECHOREPLY: - { - (void)printf("echoreply %u", - cp[1] << 24 | cp[2] << 16 | - cp[3] << 8 | cp[4]); - if (*cp != 6) - (void)printf("[len %d]", *cp); - cp += 5; - hlen -= 5; + case TCPOPT_CC: + case TCPOPT_CCNEW: + case TCPOPT_CCECHO: + (void)printf(" %lu", + cp[2] << 24 | cp[3] << 16 | + cp[4] << 8 | cp[5]); break; - } case TCPOPT_TIMESTAMP: - { - (void)printf("timestamp %lu %lu", - cp[1] << 24 | cp[2] << 16 | - cp[3] << 8 | cp[4], - cp[5] << 24 | cp[6] << 16 | - cp[7] << 8 | cp[8]); - if (*cp != 10) - (void)printf("[len %d]", *cp); - cp += 9; - hlen -= 9; + (void)printf(" %lu %lu", + cp[2] << 24 | cp[3] << 16 | + cp[4] << 8 | cp[5], + cp[6] << 24 | cp[7] << 16 | + cp[8] << 8 | cp[9]); break; - } default: - (void)printf("opt-%d:", cp[-1]); - for (i = *cp++ - 2, hlen -= i + 1; i > 0; --i) + hlen -= *++cp; + for (i = *cp++ - 2; i > 0; --i) (void)printf("%02x", *cp++); break; } - ch = ','; + /* adjust length */ + hlen -= opt->len; + cp += opt->len; } - putchar('>'); + putchar(lch); } } - |