X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/674d23116f3e0a6fb56c0a2c66b302c04568618d..309ca62193772fd8ba532fd413b51a61be0c741e:/print-tcp.c diff --git a/print-tcp.c b/print-tcp.c index 225b6cc3..88b46157 100644 --- a/print-tcp.c +++ b/print-tcp.c @@ -1,3 +1,5 @@ +/* $NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $ */ + /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. @@ -23,7 +25,9 @@ #ifndef lint static const char rcsid[] _U_ = -"@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.128 2007-01-29 19:19:51 hannes Exp $ (LBL)"; +"@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.135 2008-11-09 23:35:03 mcr Exp $ (LBL)"; +#else +__RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $"); #endif #ifdef HAVE_CONFIG_H @@ -54,10 +58,7 @@ static const char rcsid[] _U_ = #ifdef HAVE_LIBCRYPTO #include - -#define SIGNATURE_VALID 0 -#define SIGNATURE_INVALID 1 -#define CANT_CHECK_SIGNATURE 2 +#include static int tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, const u_char *data, int length, const u_char *rcvsig); @@ -120,6 +121,7 @@ struct tok tcp_option_values[] = { { TCPOPT_CCECHO, "" }, { TCPOPT_SIGNATURE, "md5" }, { TCPOPT_AUTH, "enhanced auth" }, + { TCPOPT_UTO, "uto" }, { 0, NULL } }; @@ -127,63 +129,9 @@ static int tcp_cksum(register const struct ip *ip, register const struct tcphdr *tp, register u_int len) { - union phu { - struct phdr { - u_int32_t src; - u_int32_t dst; - u_char mbz; - u_char proto; - u_int16_t len; - } ph; - u_int16_t pa[6]; - } phu; - const u_int16_t *sp; - - /* pseudo-header.. */ - phu.ph.len = htons((u_int16_t)len); - phu.ph.mbz = 0; - phu.ph.proto = IPPROTO_TCP; - memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); - if (IP_HL(ip) == 5) - memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); - else - phu.ph.dst = ip_finddst(ip); - - sp = &phu.pa[0]; - return in_cksum((u_short *)tp, len, - sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]); -} - -#ifdef INET6 -static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp, - u_int len) -{ - size_t i; - u_int32_t sum = 0; - union { - struct { - struct in6_addr ph_src; - struct in6_addr ph_dst; - u_int32_t ph_len; - u_int8_t ph_zero[3]; - u_int8_t ph_nxt; - } ph; - u_int16_t pa[20]; - } phu; - - /* pseudo-header */ - memset(&phu, 0, sizeof(phu)); - phu.ph.ph_src = ip6->ip6_src; - phu.ph.ph_dst = ip6->ip6_dst; - phu.ph.ph_len = htonl(len); - phu.ph.ph_nxt = IPPROTO_TCP; - - for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++) - sum += phu.pa[i]; - - return in_cksum((u_short *)tp, len, sum); + return (nextproto4_cksum(ip, (const u_int8_t *)tp, len, + IPPROTO_TCP)); } -#endif void tcp_print(register const u_char *bp, register u_int length, @@ -196,6 +144,7 @@ tcp_print(register const u_char *bp, register u_int length, register char ch; u_int16_t sport, dport, win, urp; u_int32_t seq, ack, thseq, thack; + u_int utoval; int threv; #ifdef INET6 register const struct ip6_hdr *ip6; @@ -223,23 +172,39 @@ tcp_print(register const u_char *bp, register u_int length, hlen = TH_OFF(tp) * 4; /* - * If data present, header length valid, and NFS port used, - * assume NFS. - * Pass offset of data plus 4 bytes for RPC TCP msg length - * to NFS print routines. - */ - if (!qflag && hlen >= sizeof(*tp) && hlen <= length) { - if ((u_char *)tp + 4 + sizeof(struct sunrpc_msg) <= snapend && - dport == NFS_PORT) { - nfsreq_print((u_char *)tp + hlen + 4, length - hlen, - (u_char *)ip); - return; - } else if ((u_char *)tp + 4 + sizeof(struct sunrpc_msg) - <= snapend && - sport == NFS_PORT) { - nfsreply_print((u_char *)tp + hlen + 4, length - hlen, - (u_char *)ip); - return; + * If data present, header length valid, and NFS port used, + * assume NFS. + * Pass offset of data plus 4 bytes for RPC TCP msg length + * to NFS print routines. + */ + if (!qflag && hlen >= sizeof(*tp) && hlen <= length && + (length - hlen) >= 4) { + u_char *fraglenp; + u_int32_t fraglen; + register struct sunrpc_msg *rp; + enum sunrpc_msg_type direction; + + fraglenp = (u_char *)tp + hlen; + if (TTEST2(*fraglenp, 4)) { + fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF; + if (fraglen > (length - hlen) - 4) + fraglen = (length - hlen) - 4; + rp = (struct sunrpc_msg *)(fraglenp + 4); + if (TTEST(rp->rm_direction)) { + direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); + if (dport == NFS_PORT && + direction == SUNRPC_CALL) { + nfsreq_print((u_char *)rp, fraglen, + (u_char *)ip); + return; + } + if (sport == NFS_PORT && + direction == SUNRPC_REPLY) { + nfsreply_print((u_char *)rp, fraglen, + (u_char *)ip); + return; + } + } } } #ifdef INET6 @@ -306,7 +271,6 @@ tcp_print(register const u_char *bp, register u_int length, * both directions). */ #ifdef INET6 - memset(&tha, 0, sizeof(tha)); rev = 0; if (ip6) { src = &ip6->ip6_src; @@ -327,6 +291,27 @@ tcp_print(register const u_char *bp, register u_int length, tha.port = sport << 16 | dport; } } else { + /* + * Zero out the tha structure; the src and dst + * fields are big enough to hold an IPv6 + * address, but we only have IPv4 addresses + * and thus must clear out the remaining 124 + * bits. + * + * XXX - should we just clear those bytes after + * copying the IPv4 addresses, rather than + * zeroing out the entire structure and then + * overwriting some of the zeroes? + * + * XXX - this could fail if we see TCP packets + * with an IPv6 address with the lower 124 bits + * all zero and also see TCP packes with an + * IPv4 address with the same 32 bits as the + * upper 32 bits of the IPv6 address in question. + * Can that happen? Is it likely enough to be + * an issue? + */ + memset(&tha, 0, sizeof(tha)); src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) @@ -405,37 +390,43 @@ tcp_print(register const u_char *bp, register u_int length, return; } - if (IP_V(ip) == 4 && vflag && !Kflag && !fragmented) { + if (vflag && !Kflag && !fragmented) { + /* Check the checksum, if possible. */ u_int16_t sum, tcp_sum; - if (TTEST2(tp->th_sport, length)) { - sum = tcp_cksum(ip, tp, length); - (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); - if (sum != 0) { + if (IP_V(ip) == 4) { + if (TTEST2(tp->th_sport, length)) { + sum = tcp_cksum(ip, tp, length); tcp_sum = EXTRACT_16BITS(&tp->th_sum); - (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); - } else - (void)printf(" (correct)"); + + (void)printf(", cksum 0x%04x", tcp_sum); + if (sum != 0) + (void)printf(" (incorrect -> 0x%04x)", + in_cksum_shouldbe(tcp_sum, sum)); + else + (void)printf(" (correct)"); + } } - } #ifdef INET6 - if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !Kflag && !fragmented) { - u_int16_t sum,tcp_sum; - if (TTEST2(tp->th_sport, length)) { - sum = tcp6_cksum(ip6, tp, length); - (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); - if (sum != 0) { + else if (IP_V(ip) == 6 && ip6->ip6_plen) { + if (TTEST2(tp->th_sport, length)) { + sum = nextproto6_cksum(ip6, (const u_int8_t *)tp, length, IPPROTO_TCP); tcp_sum = EXTRACT_16BITS(&tp->th_sum); - (void)printf(" (incorrect (-> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); - } else - (void)printf(" (correct)"); + (void)printf(", cksum 0x%04x", tcp_sum); + if (sum != 0) + (void)printf(" (incorrect -> 0x%04x)", + in_cksum_shouldbe(tcp_sum, sum)); + else + (void)printf(" (correct)"); + + } } - } #endif + } length -= hlen; - if (vflag > 1 || flags & (TH_SYN | TH_FIN | TH_RST)) { + if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { (void)printf(", seq %u", seq); if (length > 0) { @@ -463,7 +454,8 @@ tcp_print(register const u_char *bp, register u_int length, cp = (const u_char *)tp + sizeof(*tp); printf(", options ["); while (hlen > 0) { - putchar(ch); + if (ch != '\0') + putchar(ch); TCHECK(*cp); opt = *cp++; if (ZEROLENOPT(opt)) @@ -592,6 +584,18 @@ tcp_print(register const u_char *bp, register u_int length, */ break; + case TCPOPT_UTO: + datalen = 2; + LENCHECK(datalen); + utoval = EXTRACT_16BITS(cp); + (void)printf("0x%x", utoval); + if (utoval & 0x0001) + utoval = (utoval >> 1) * 60; + else + utoval >>= 1; + (void)printf(" %u", utoval); + break; + default: datalen = len - 2; for (i = 0; i < datalen; ++i) { @@ -645,6 +649,8 @@ tcp_print(register const u_char *bp, register u_int length, #ifdef TCPDUMP_DO_SMB else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT) nbt_tcp_print(bp, length); + else if (sport == SMB_PORT || dport == SMB_PORT) + smb_tcp_print(bp, length); #endif else if (sport == BEEP_PORT || dport == BEEP_PORT) beep_print(bp, length); @@ -658,6 +664,8 @@ tcp_print(register const u_char *bp, register u_int length, ns_print(bp + 2, length - 2, 0); } else if (sport == MSDP_PORT || dport == MSDP_PORT) { msdp_print(bp, length); + } else if (sport == RPKI_RTR_PORT || dport == RPKI_RTR_PORT) { + rpki_rtr_print(bp, length); } else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) { ldp_print(bp, length); @@ -723,14 +731,21 @@ tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, u_int16_t savecsum, tlen; #ifdef INET6 struct ip6_hdr *ip6; -#endif u_int32_t len32; u_int8_t nxt; +#endif + + if (data + length > snapend) { + printf("snaplen too short, "); + return (CANT_CHECK_SIGNATURE); + } tp1 = *tp; - if (tcpmd5secret == NULL) + if (sigsecret == NULL) { + printf("shared secret not supplied with -M, "); return (CANT_CHECK_SIGNATURE); + } MD5_Init(&ctx); /* @@ -749,7 +764,7 @@ tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, ip6 = (struct ip6_hdr *)ip; MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src)); MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst)); - len32 = htonl(ntohs(ip6->ip6_plen)); + len32 = htonl(EXTRACT_16BITS(&ip6->ip6_plen)); MD5_Update(&ctx, (char *)&len32, sizeof(len32)); nxt = 0; MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); @@ -758,8 +773,14 @@ tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, nxt = IPPROTO_TCP; MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); #endif - } else + } else { +#ifdef INET6 + printf("IP version not 4 or 6, "); +#else + printf("IP version not 4, "); +#endif return (CANT_CHECK_SIGNATURE); + } /* * Step 2: Update MD5 hash with TCP header, excluding options. @@ -777,7 +798,7 @@ tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp, /* * Step 4: Update MD5 hash with shared secret. */ - MD5_Update(&ctx, tcpmd5secret, strlen(tcpmd5secret)); + MD5_Update(&ctx, sigsecret, strlen(sigsecret)); MD5_Final(sig, &ctx); if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0)