X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/09e38732e77d97e926165088c8518f6560847744..296d466cd6bbf2f7e75e15bb6a01268e88c76ed0:/print-ip.c diff --git a/print-ip.c b/print-ip.c index b4e287a6..a332bd78 100644 --- a/print-ip.c +++ b/print-ip.c @@ -21,14 +21,10 @@ /* \summary: IP printer */ -#ifdef HAVE_CONFIG_H #include -#endif #include "netdissect-stdinc.h" -#include - #include "netdissect.h" #include "addrtoname.h" #include "extract.h" @@ -66,14 +62,13 @@ ip_printroute(netdissect_options *ndo, } if ((length + 1) & 3) ND_PRINT(" [bad length %u]", length); - ND_TCHECK_1(cp + 2); ptr = GET_U_1(cp + 2) - 1; if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) ND_PRINT(" [bad ptr %u]", GET_U_1(cp + 2)); for (len = 3; len < length; len += 4) { - ND_TCHECK_4(cp + len); - ND_PRINT(" %s", ipaddr_string(ndo, cp + len)); + ND_TCHECK_4(cp + len); /* Needed to print the IP addresses */ + ND_PRINT(" %s", GET_IPADDR_STRING(cp + len)); if (ptr > len) ND_PRINT(","); } @@ -107,14 +102,12 @@ ip_finddst(netdissect_options *ndo, for (; length != 0; cp += len, length -= len) { int tt; - ND_TCHECK_1(cp); tt = GET_U_1(cp); if (tt == IPOPT_EOL) break; else if (tt == IPOPT_NOP) len = 1; else { - ND_TCHECK_1(cp + 1); len = GET_U_1(cp + 1); if (len < 2) break; @@ -183,16 +176,13 @@ ip_printts(netdissect_options *ndo, return (0); } ND_PRINT(" TS{"); - ND_TCHECK_1(cp + 3); hoplen = ((GET_U_1(cp + 3) & 0xF) != IPOPT_TS_TSONLY) ? 8 : 4; if ((length - 4) & (hoplen-1)) ND_PRINT("[bad length %u]", length); - ND_TCHECK_1(cp + 2); ptr = GET_U_1(cp + 2) - 1; len = 0; if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1) ND_PRINT("[bad ptr %u]", GET_U_1(cp + 2)); - ND_TCHECK_1(cp + 3); switch (GET_U_1(cp + 3)&0xF) { case IPOPT_TS_TSONLY: ND_PRINT("TSONLY"); @@ -200,16 +190,7 @@ ip_printts(netdissect_options *ndo, case IPOPT_TS_TSANDADDR: ND_PRINT("TS+ADDR"); break; - /* - * prespecified should really be 3, but some ones might send 2 - * instead, and the IPOPT_TS_PRESPEC constant can apparently - * have both values, so we have to hard-code it here. - */ - - case 2: - ND_PRINT("PRESPEC2.0"); - break; - case 3: /* IPOPT_TS_PRESPEC */ + case IPOPT_TS_PRESPEC: ND_PRINT("PRESPEC"); break; default: @@ -223,7 +204,7 @@ ip_printts(netdissect_options *ndo, type = " ^ "; ND_TCHECK_LEN(cp + len, hoplen); ND_PRINT("%s%u@%s", type, GET_BE_U_4(cp + len + hoplen - 4), - hoplen!=8 ? "" : ipaddr_string(ndo, cp + len)); + hoplen!=8 ? "" : GET_IPADDR_STRING(cp + len)); type = " "; } @@ -257,7 +238,6 @@ ip_optprint(netdissect_options *ndo, ND_PRINT("%s", sep); sep = ","; - ND_TCHECK_1(cp); option_code = GET_U_1(cp); ND_PRINT("%s", @@ -268,7 +248,6 @@ ip_optprint(netdissect_options *ndo, option_len = 1; else { - ND_TCHECK_1(cp + 1); option_len = GET_U_1(cp + 1); if (option_len < 2) { ND_PRINT(" [bad length %u]", option_len); @@ -337,7 +316,7 @@ static const struct tok ip_frag_values[] = { void ip_print(netdissect_options *ndo, const u_char *bp, - u_int length) + const u_int length) { const struct ip *ip; u_int off; @@ -348,55 +327,45 @@ ip_print(netdissect_options *ndo, uint16_t sum, ip_sum; const char *p_name; int truncated = 0; + int presumed_tso = 0; ndo->ndo_protocol = "ip"; ip = (const struct ip *)bp; - if (IP_V(ip) != 4) { /* print version and fail if != 4 */ - if (IP_V(ip) == 6) - ND_PRINT("IP6, wrong link-layer encapsulation"); - else - ND_PRINT("IP%u", IP_V(ip)); - nd_print_invalid(ndo); - return; - } - if (!ndo->ndo_eflag) - ND_PRINT("IP "); - ND_TCHECK_SIZE(ip); - if (length < sizeof (struct ip)) { - ND_PRINT("truncated-ip %u", length); - return; + if (!ndo->ndo_eflag) { + nd_print_protocol_caps(ndo); + ND_PRINT(" "); } + + ND_ICHECK_ZU(length, <, sizeof (struct ip)); + ND_ICHECKMSG_U("version", IP_V(ip), !=, 4); + hlen = IP_HL(ip) * 4; - if (hlen < sizeof (struct ip)) { - ND_PRINT("bad-hlen %u", hlen); - return; - } + ND_ICHECKMSG_ZU("header length", hlen, <, sizeof (struct ip)); len = GET_BE_U_2(ip->ip_len); - if (length < len) - ND_PRINT("truncated-ip - %u bytes missing! ", - len - length); - if (len < hlen) { -#ifdef GUESS_TSO - if (len) { - ND_PRINT("bad-len %u", len); - return; - } - else { - /* we guess that it is a TSO send */ - len = length; - } -#else - ND_PRINT("bad-len %u", len); - return; -#endif /* GUESS_TSO */ + if (len > length) { + ND_PRINT("[total length %u > length %u]", len, length); + nd_print_invalid(ndo); + ND_PRINT(" "); } + if (len == 0) { + /* we guess that it is a TSO send */ + len = length; + presumed_tso = 1; + } else + ND_ICHECKMSG_U("total length", len, <, hlen); + ND_TCHECK_SIZE(ip); /* - * Cut off the snapshot length to the end of the IP payload. + * Cut off the snapshot length to the end of the IP payload + * or the end of the data in which it's contained, whichever + * comes first. */ - nd_push_snapend(ndo, bp + len); + if (!nd_push_snaplen(ndo, bp, ND_MIN(length, len))) { + (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, + "%s: can't push snaplen on buffer stack", __func__); + } len -= hlen; @@ -442,9 +411,12 @@ ip_print(netdissect_options *ndo, tok2str(ipproto_values, "unknown", ip_proto), ip_proto); - ND_PRINT(", length %u", GET_BE_U_2(ip->ip_len)); + if (presumed_tso) + ND_PRINT(", length %u [was 0, presumed TSO]", length); + else + ND_PRINT(", length %u", GET_BE_U_2(ip->ip_len)); - if ((hlen - sizeof(struct ip)) > 0) { + if ((hlen > sizeof(struct ip))) { ND_PRINT(", options ("); if (ip_optprint(ndo, (const u_char *)(ip + 1), hlen - sizeof(struct ip)) == -1) { @@ -468,8 +440,8 @@ ip_print(netdissect_options *ndo, ND_PRINT(")\n "); if (truncated) { ND_PRINT("%s > %s: ", - ipaddr_string(ndo, ip->ip_src), - ipaddr_string(ndo, ip->ip_dst)); + GET_IPADDR_STRING(ip->ip_src), + GET_IPADDR_STRING(ip->ip_dst)); nd_print_trunc(ndo); nd_pop_packet_info(ndo); return; @@ -487,11 +459,21 @@ ip_print(netdissect_options *ndo, if (nh != IPPROTO_TCP && nh != IPPROTO_UDP && nh != IPPROTO_SCTP && nh != IPPROTO_DCCP) { ND_PRINT("%s > %s: ", - ipaddr_string(ndo, ip->ip_src), - ipaddr_string(ndo, ip->ip_dst)); + GET_IPADDR_STRING(ip->ip_src), + GET_IPADDR_STRING(ip->ip_dst)); + } + /* + * Do a bounds check before calling ip_demux_print(). + * At least the header data is required. + */ + if (!ND_TTEST_LEN((const u_char *)ip, hlen)) { + ND_PRINT(" [remaining caplen(%u) < header length(%u)]", + ND_BYTES_AVAILABLE_AFTER((const u_char *)ip), + hlen); + nd_trunc_longjmp(ndo); } - ip_print_demux(ndo, (const u_char *)ip + hlen, len, 4, - off & IP_MF, GET_U_1(ip->ip_ttl), nh, bp); + ip_demux_print(ndo, (const u_char *)ip + hlen, len, 4, + off & IP_MF, GET_U_1(ip->ip_ttl), nh, bp); } else { /* * Ultra quiet now means that all this stuff should be @@ -507,8 +489,8 @@ ip_print(netdissect_options *ndo, * next level protocol header. print the ip addr * and the protocol. */ - ND_PRINT("%s > %s:", ipaddr_string(ndo, ip->ip_src), - ipaddr_string(ndo, ip->ip_dst)); + ND_PRINT("%s > %s:", GET_IPADDR_STRING(ip->ip_src), + GET_IPADDR_STRING(ip->ip_dst)); if (!ndo->ndo_nflag && (p_name = netdb_protoname(ip_proto)) != NULL) ND_PRINT(" %s", p_name); else @@ -520,18 +502,20 @@ ip_print(netdissect_options *ndo, trunc: nd_print_trunc(ndo); return; + +invalid: + nd_print_invalid(ndo); } void ipN_print(netdissect_options *ndo, const u_char *bp, u_int length) { - ndo->ndo_protocol = "ipN"; + ndo->ndo_protocol = "ipn"; if (length < 1) { ND_PRINT("truncated-ip %u", length); return; } - ND_TCHECK_1(bp); switch (GET_U_1(bp) & 0xF0) { case 0x40: ip_print(ndo, bp, length); @@ -543,9 +527,4 @@ ipN_print(netdissect_options *ndo, const u_char *bp, u_int length) ND_PRINT("unknown ip %u", (GET_U_1(bp) & 0xF0) >> 4); break; } - return; - -trunc: - nd_print_trunc(ndo); - return; }