diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2017-02-01 20:26:42 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2017-02-01 20:26:42 +0000 |
commit | 3340d77368116708ab5b5b95acf6c9c710528300 (patch) | |
tree | 811e83fd724dc565485db80039bf234ece065b10 /contrib/tcpdump/print-pim.c | |
parent | 151139ad9e119116ae3692d0b8dd13baf691d55e (diff) | |
parent | d79b843cb78484ea27f877f1541055e1a6a5a4d3 (diff) | |
download | src-3340d77368116708ab5b5b95acf6c9c710528300.tar.gz src-3340d77368116708ab5b5b95acf6c9c710528300.zip |
Update tcpdump to 4.9.0.
It fixes many buffer overflow in different protocol parsers, but none of
them are critical, even in absense of Capsicum.
Security: CVE-2016-7922, CVE-2016-7923, CVE-2016-7924, CVE-2016-7925
Security: CVE-2016-7926, CVE-2016-7927, CVE-2016-7928, CVE-2016-7929
Security: CVE-2016-7930, CVE-2016-7931, CVE-2016-7932, CVE-2016-7933
Security: CVE-2016-7934, CVE-2016-7935, CVE-2016-7936, CVE-2016-7937
Security: CVE-2016-7938, CVE-2016-7939, CVE-2016-7940, CVE-2016-7973
Security: CVE-2016-7974, CVE-2016-7975, CVE-2016-7983, CVE-2016-7984
Security: CVE-2016-7985, CVE-2016-7986, CVE-2016-7992, CVE-2016-7993
Security: CVE-2016-8574, CVE-2016-8575, CVE-2017-5202, CVE-2017-5203
Security: CVE-2017-5204, CVE-2017-5205, CVE-2017-5341, CVE-2017-5342
Security: CVE-2017-5482, CVE-2017-5483, CVE-2017-5484, CVE-2017-5485
Security: CVE-2017-5486
Notes
Notes:
svn path=/head/; revision=313048
Diffstat (limited to 'contrib/tcpdump/print-pim.c')
-rw-r--r-- | contrib/tcpdump/print-pim.c | 132 |
1 files changed, 97 insertions, 35 deletions
diff --git a/contrib/tcpdump/print-pim.c b/contrib/tcpdump/print-pim.c index 6738e37c6a50..255259537494 100644 --- a/contrib/tcpdump/print-pim.c +++ b/contrib/tcpdump/print-pim.c @@ -17,22 +17,23 @@ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * $FreeBSD$ */ -#define NETDISSECT_REWORKED +/* \summary: Protocol Independent Multicast (PIM) printer */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include <tcpdump-stdinc.h> +#include <netdissect-stdinc.h> -#include "interface.h" +#include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "ip.h" +#include "ip6.h" +#include "ipproto.h" #define PIMV1_TYPE_QUERY 0 #define PIMV1_TYPE_REGISTER 1 @@ -136,7 +137,7 @@ struct pim { u_short pim_cksum; /* IP style check sum */ }; -static void pimv2_print(netdissect_options *, register const u_char *bp, register u_int len, u_int cksum); +static void pimv2_print(netdissect_options *, register const u_char *bp, register u_int len, const u_char *); static void pimv1_join_prune_print(netdissect_options *ndo, @@ -154,7 +155,7 @@ pimv1_join_prune_print(netdissect_options *ndo, hold = EXTRACT_16BITS(&bp[6]); if (hold != 180) { ND_PRINT((ndo, "Hold ")); - relts_print(ndo, hold); + unsigned_relts_print(ndo, hold); } ND_PRINT((ndo, "%s (%s/%d, %s", njoin ? "Join" : "Prune", ipaddr_string(ndo, &bp[26]), bp[25] & 0x3f, @@ -176,7 +177,7 @@ pimv1_join_prune_print(netdissect_options *ndo, if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n")); ND_PRINT((ndo, " Hold time: ")); - relts_print(ndo, EXTRACT_16BITS(&bp[6])); + unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[6])); if (ndo->ndo_vflag < 2) return; bp += 8; @@ -261,7 +262,7 @@ pimv1_print(netdissect_options *ndo, if (ndo->ndo_vflag) { ND_TCHECK2(bp[10],2); ND_PRINT((ndo, " (Hold-time ")); - relts_print(ndo, EXTRACT_16BITS(&bp[10])); + unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[10])); ND_PRINT((ndo, ")")); } break; @@ -283,7 +284,7 @@ pimv1_print(netdissect_options *ndo, if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[12]))); ND_PRINT((ndo, " RP %s hold ", ipaddr_string(ndo, &bp[16]))); - relts_print(ndo, EXTRACT_16BITS(&bp[22])); + unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[22])); } break; case PIMV1_TYPE_ASSERT: @@ -350,7 +351,7 @@ cisco_autorp_print(netdissect_options *ndo, ND_PRINT((ndo, " Hold ")); hold = EXTRACT_16BITS(&bp[2]); if (hold) - relts_print(ndo, EXTRACT_16BITS(&bp[2])); + unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2])); else ND_PRINT((ndo, "FOREVER")); @@ -417,10 +418,10 @@ trunc: void pim_print(netdissect_options *ndo, - register const u_char *bp, register u_int len, u_int cksum) + register const u_char *bp, register u_int len, const u_char *bp2) { register const u_char *ep; - register struct pim *pim = (struct pim *)bp; + register const struct pim *pim = (const struct pim *)bp; ep = (const u_char *)ndo->ndo_snapend; if (bp >= ep) @@ -442,7 +443,7 @@ pim_print(netdissect_options *ndo, PIM_VER(pim->pim_typever), len, tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)))); - pimv2_print(ndo, bp, len, cksum); + pimv2_print(ndo, bp, len, bp2); } break; default: @@ -536,12 +537,10 @@ pimv2_addr_print(netdissect_options *ndo, af = AF_INET; len = sizeof(struct in_addr); break; -#ifdef INET6 case 2: af = AF_INET6; len = sizeof(struct in6_addr); break; -#endif default: return -1; } @@ -553,11 +552,9 @@ pimv2_addr_print(netdissect_options *ndo, case sizeof(struct in_addr): af = AF_INET; break; -#ifdef INET6 case sizeof(struct in6_addr): af = AF_INET6; break; -#endif default: return -1; break; @@ -574,12 +571,10 @@ pimv2_addr_print(netdissect_options *ndo, if (!silent) ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp))); } -#ifdef INET6 else if (af == AF_INET6) { if (!silent) ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp))); } -#endif return hdrlen + len; case pimv2_group: case pimv2_source: @@ -591,7 +586,6 @@ pimv2_addr_print(netdissect_options *ndo, ND_PRINT((ndo, "/%u", bp[1])); } } -#ifdef INET6 else if (af == AF_INET6) { if (!silent) { ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp + 2))); @@ -599,7 +593,6 @@ pimv2_addr_print(netdissect_options *ndo, ND_PRINT((ndo, "/%u", bp[1])); } } -#endif if (bp[0] && !silent) { if (at == pimv2_group) { ND_PRINT((ndo, "(0x%02x)", bp[0])); @@ -622,13 +615,50 @@ trunc: return -1; } +enum checksum_status { + CORRECT, + INCORRECT, + UNVERIFIED +}; + +static enum checksum_status +pimv2_check_checksum(netdissect_options *ndo, const u_char *bp, + const u_char *bp2, u_int len) +{ + const struct ip *ip; + u_int cksum; + + if (!ND_TTEST2(bp[0], len)) { + /* We don't have all the data. */ + return (UNVERIFIED); + } + ip = (const struct ip *)bp2; + if (IP_V(ip) == 4) { + struct cksum_vec vec[1]; + + vec[0].ptr = bp; + vec[0].len = len; + cksum = in_cksum(vec, 1); + return (cksum ? INCORRECT : CORRECT); + } else if (IP_V(ip) == 6) { + const struct ip6_hdr *ip6; + + ip6 = (const struct ip6_hdr *)bp2; + cksum = nextproto6_cksum(ndo, ip6, bp, len, len, IPPROTO_PIM); + return (cksum ? INCORRECT : CORRECT); + } else { + return (UNVERIFIED); + } +} + static void pimv2_print(netdissect_options *ndo, - register const u_char *bp, register u_int len, u_int cksum) + register const u_char *bp, register u_int len, const u_char *bp2) { register const u_char *ep; - register struct pim *pim = (struct pim *)bp; + register const struct pim *pim = (const struct pim *)bp; int advance; + enum checksum_status cksum_status; ep = (const u_char *)ndo->ndo_snapend; if (bp >= ep) @@ -644,7 +674,41 @@ pimv2_print(netdissect_options *ndo, if (EXTRACT_16BITS(&pim->pim_cksum) == 0) { ND_PRINT((ndo, "(unverified)")); } else { - ND_PRINT((ndo, "(%scorrect)", ND_TTEST2(bp[0], len) && cksum ? "in" : "" )); + if (PIM_TYPE(pim->pim_typever) == PIMV2_TYPE_REGISTER) { + /* + * The checksum only covers the packet header, + * not the encapsulated packet. + */ + cksum_status = pimv2_check_checksum(ndo, bp, bp2, 8); + if (cksum_status == INCORRECT) { + /* + * To quote RFC 4601, "For interoperability + * reasons, a message carrying a checksum + * calculated over the entire PIM Register + * message should also be accepted." + */ + cksum_status = pimv2_check_checksum(ndo, bp, bp2, len); + } + } else { + /* + * The checksum covers the entire packet. + */ + cksum_status = pimv2_check_checksum(ndo, bp, bp2, len); + } + switch (cksum_status) { + + case CORRECT: + ND_PRINT((ndo, "(correct)")); + break; + + case INCORRECT: + ND_PRINT((ndo, "(incorrect)")); + break; + + case UNVERIFIED: + ND_PRINT((ndo, "(unverified)")); + break; + } } switch (PIM_TYPE(pim->pim_typever)) { @@ -665,7 +729,7 @@ pimv2_print(netdissect_options *ndo, switch (otype) { case PIMV2_HELLO_OPTION_HOLDTIME: - relts_print(ndo, EXTRACT_16BITS(bp)); + unsigned_relts_print(ndo, EXTRACT_16BITS(bp)); break; case PIMV2_HELLO_OPTION_LANPRUNEDELAY: @@ -706,7 +770,7 @@ pimv2_print(netdissect_options *ndo, ND_PRINT((ndo, "v%d", *bp)); if (*(bp+1) != 0) { ND_PRINT((ndo, ", interval ")); - relts_print(ndo, *(bp+1)); + unsigned_relts_print(ndo, *(bp+1)); } if (EXTRACT_16BITS(bp+2) != 0) { ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(bp+2))); @@ -721,8 +785,6 @@ pimv2_print(netdissect_options *ndo, if (ndo->ndo_vflag > 1) { const u_char *ptr = bp; while (ptr < (bp+olen)) { - int advance; - ND_PRINT((ndo, "\n\t ")); advance = pimv2_addr_print(ndo, ptr, pimv2_unicast, 0); if (advance < 0) { @@ -748,7 +810,7 @@ pimv2_print(netdissect_options *ndo, case PIMV2_TYPE_REGISTER: { - struct ip *ip; + const struct ip *ip; ND_TCHECK2(*(bp + 4), PIMV2_REGISTER_FLAG_LEN); @@ -759,7 +821,7 @@ pimv2_print(netdissect_options *ndo, bp += 8; len -= 8; /* encapsulated multicast packet */ - ip = (struct ip *)bp; + ip = (const struct ip *)bp; switch (IP_V(ip)) { case 0: /* Null header */ ND_PRINT((ndo, "IP-Null-header %s > %s", @@ -870,7 +932,7 @@ pimv2_print(netdissect_options *ndo, if (holdtime == 0xffff) ND_PRINT((ndo, "infinite")); else - relts_print(ndo, holdtime); + unsigned_relts_print(ndo, holdtime); } bp += 4; len -= 4; for (i = 0; i < ngroup; i++) { @@ -974,7 +1036,7 @@ pimv2_print(netdissect_options *ndo, goto bs_done; } ND_PRINT((ndo, ",holdtime=")); - relts_print(ndo, EXTRACT_16BITS(bp)); + unsigned_relts_print(ndo, EXTRACT_16BITS(bp)); if (bp + 2 >= ep) { ND_PRINT((ndo, "...)")); goto bs_done; @@ -1026,7 +1088,7 @@ pimv2_print(netdissect_options *ndo, ND_PRINT((ndo, " prio=%d", bp[1])); if (bp + 3 >= ep) break; ND_PRINT((ndo, " holdtime=")); - relts_print(ndo, EXTRACT_16BITS(&bp[2])); + unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2])); bp += 4; /* Encoded-Unicast-RP-Address */ @@ -1072,7 +1134,7 @@ pimv2_print(netdissect_options *ndo, bp += advance; ND_TCHECK2(bp[0], 2); ND_PRINT((ndo, " TUNR ")); - relts_print(ndo, EXTRACT_16BITS(bp)); + unsigned_relts_print(ndo, EXTRACT_16BITS(bp)); break; |