diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-20 15:53:03 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:39 +0200 |
commit | 18fa92c2dcc6c52e0bf27d214d80f0c25a89b47d (patch) | |
tree | a3020ac5b1f366f2f0920941b589808e435dbcee /freebsd/contrib | |
parent | Update to FreeBSD head 2017-12-01 (diff) | |
download | rtems-libbsd-18fa92c2dcc6c52e0bf27d214d80f0c25a89b47d.tar.bz2 |
Update to FreeBSD head 2018-02-01
Git mirror commit d079ae0442af8fa3cfd6d7ede190d04e64a2c0d4.
Update #3472.
Diffstat (limited to 'freebsd/contrib')
98 files changed, 3158 insertions, 1511 deletions
diff --git a/freebsd/contrib/tcpdump/addrtoname.c b/freebsd/contrib/tcpdump/addrtoname.c index fb4550cc..a47b3615 100644 --- a/freebsd/contrib/tcpdump/addrtoname.c +++ b/freebsd/contrib/tcpdump/addrtoname.c @@ -156,13 +156,23 @@ struct enamemem { u_short e_addr2; const char *e_name; u_char *e_nsap; /* used only for nsaptable[] */ -#define e_bs e_nsap /* for bytestringtable */ struct enamemem *e_nxt; }; static struct enamemem enametable[HASHNAMESIZE]; static struct enamemem nsaptable[HASHNAMESIZE]; -static struct enamemem bytestringtable[HASHNAMESIZE]; + +struct bsnamemem { + u_short bs_addr0; + u_short bs_addr1; + u_short bs_addr2; + const char *bs_name; + u_char *bs_bytes; + unsigned int bs_nbytes; + struct bsnamemem *bs_nxt; +}; + +static struct bsnamemem bytestringtable[HASHNAMESIZE]; struct protoidmem { uint32_t p_oui; @@ -348,7 +358,7 @@ getname6(netdissect_options *ndo, const u_char *ap) return (p->name); } -static const char hex[] = "0123456789abcdef"; +static const char hex[16] = "0123456789abcdef"; /* Find the hash node that corresponds the ether address 'ep' */ @@ -386,11 +396,11 @@ lookup_emem(netdissect_options *ndo, const u_char *ep) * with length 'nlen' */ -static inline struct enamemem * +static inline struct bsnamemem * lookup_bytestring(netdissect_options *ndo, register const u_char *bs, const unsigned int nlen) { - struct enamemem *tp; + struct bsnamemem *tp; register u_int i, j, k; if (nlen >= 6) { @@ -405,26 +415,28 @@ lookup_bytestring(netdissect_options *ndo, register const u_char *bs, i = j = k = 0; tp = &bytestringtable[(i ^ j) & (HASHNAMESIZE-1)]; - while (tp->e_nxt) - if (tp->e_addr0 == i && - tp->e_addr1 == j && - tp->e_addr2 == k && - memcmp((const char *)bs, (const char *)(tp->e_bs), nlen) == 0) + while (tp->bs_nxt) + if (nlen == tp->bs_nbytes && + tp->bs_addr0 == i && + tp->bs_addr1 == j && + tp->bs_addr2 == k && + memcmp((const char *)bs, (const char *)(tp->bs_bytes), nlen) == 0) return tp; else - tp = tp->e_nxt; + tp = tp->bs_nxt; - tp->e_addr0 = i; - tp->e_addr1 = j; - tp->e_addr2 = k; + tp->bs_addr0 = i; + tp->bs_addr1 = j; + tp->bs_addr2 = k; - tp->e_bs = (u_char *) calloc(1, nlen + 1); - if (tp->e_bs == NULL) + tp->bs_bytes = (u_char *) calloc(1, nlen); + if (tp->bs_bytes == NULL) (*ndo->ndo_error)(ndo, "lookup_bytestring: calloc"); - memcpy(tp->e_bs, bs, nlen); - tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); - if (tp->e_nxt == NULL) + memcpy(tp->bs_bytes, bs, nlen); + tp->bs_nbytes = nlen; + tp->bs_nxt = (struct bsnamemem *)calloc(1, sizeof(*tp)); + if (tp->bs_nxt == NULL) (*ndo->ndo_error)(ndo, "lookup_bytestring: calloc"); return tp; @@ -451,11 +463,11 @@ lookup_nsap(netdissect_options *ndo, register const u_char *nsap, tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; while (tp->e_nxt) - if (tp->e_addr0 == i && + if (nsap_length == tp->e_nsap[0] && + tp->e_addr0 == i && tp->e_addr1 == j && tp->e_addr2 == k && - tp->e_nsap[0] == nsap_length && - memcmp((const char *)&(nsap[1]), + memcmp((const char *)nsap, (char *)&(tp->e_nsap[1]), nsap_length) == 0) return tp; else @@ -555,12 +567,12 @@ le64addr_string(netdissect_options *ndo, const u_char *ep) const unsigned int len = 8; register u_int i; register char *cp; - register struct enamemem *tp; + register struct bsnamemem *tp; char buf[BUFSIZE]; tp = lookup_bytestring(ndo, ep, len); - if (tp->e_name) - return (tp->e_name); + if (tp->bs_name) + return (tp->bs_name); cp = buf; for (i = len; i > 0 ; --i) { @@ -572,11 +584,11 @@ le64addr_string(netdissect_options *ndo, const u_char *ep) *cp = '\0'; - tp->e_name = strdup(buf); - if (tp->e_name == NULL) + tp->bs_name = strdup(buf); + if (tp->bs_name == NULL) (*ndo->ndo_error)(ndo, "le64addr_string: strdup(buf)"); - return (tp->e_name); + return (tp->bs_name); } const char * @@ -585,7 +597,7 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep, { register u_int i; register char *cp; - register struct enamemem *tp; + register struct bsnamemem *tp; if (len == 0) return ("<empty>"); @@ -597,11 +609,11 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep, return (q922_string(ndo, ep, len)); tp = lookup_bytestring(ndo, ep, len); - if (tp->e_name) - return (tp->e_name); + if (tp->bs_name) + return (tp->bs_name); - tp->e_name = cp = (char *)malloc(len*3); - if (tp->e_name == NULL) + tp->bs_name = cp = (char *)malloc(len*3); + if (tp->bs_name == NULL) (*ndo->ndo_error)(ndo, "linkaddr_string: malloc"); *cp++ = hex[*ep >> 4]; *cp++ = hex[*ep++ & 0xf]; @@ -611,7 +623,7 @@ linkaddr_string(netdissect_options *ndo, const u_char *ep, *cp++ = hex[*ep++ & 0xf]; } *cp = '\0'; - return (tp->e_name); + return (tp->bs_name); } const char * diff --git a/freebsd/contrib/tcpdump/addrtoname.h b/freebsd/contrib/tcpdump/addrtoname.h index 72e5ef19..fe8b6bbe 100644 --- a/freebsd/contrib/tcpdump/addrtoname.h +++ b/freebsd/contrib/tcpdump/addrtoname.h @@ -33,7 +33,8 @@ enum { LINKADDR_ETHER, LINKADDR_FRELAY, LINKADDR_IEEE1394, - LINKADDR_ATM + LINKADDR_ATM, + LINKADDR_OTHER }; #define BUFSIZE 128 diff --git a/freebsd/contrib/tcpdump/addrtostr.c b/freebsd/contrib/tcpdump/addrtostr.c index bf829bb4..c5fea233 100644 --- a/freebsd/contrib/tcpdump/addrtostr.c +++ b/freebsd/contrib/tcpdump/addrtostr.c @@ -116,25 +116,24 @@ addrtostr6 (const void *src, char *dst, size_t size) size_t space_left, added_space; int snprintfed; struct { - long base; - long len; + int base; + int len; } best, cur; - u_long words [IN6ADDRSZ / INT16SZ]; + uint16_t words [IN6ADDRSZ / INT16SZ]; int i; /* Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ - memset (words, 0, sizeof(words)); - for (i = 0; i < IN6ADDRSZ; i++) - words[i/2] |= (srcaddr[i] << ((1 - (i % 2)) << 3)); + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) + words[i] = (srcaddr[2*i] << 8) | srcaddr[2*i + 1]; best.len = 0; best.base = -1; cur.len = 0; cur.base = -1; - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) + for (i = 0; i < (int)(IN6ADDRSZ / INT16SZ); i++) { if (words[i] == 0) { @@ -167,7 +166,7 @@ addrtostr6 (const void *src, char *dst, size_t size) *dp++ = c; \ space_left--; \ } - for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) + for (i = 0; i < (int)(IN6ADDRSZ / INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ @@ -198,7 +197,7 @@ addrtostr6 (const void *src, char *dst, size_t size) space_left -= added_space; break; } - snprintfed = snprintf (dp, space_left, "%lx", words[i]); + snprintfed = snprintf (dp, space_left, "%x", words[i]); if (snprintfed < 0) return (NULL); if ((size_t) snprintfed >= space_left) diff --git a/freebsd/contrib/tcpdump/af.c b/freebsd/contrib/tcpdump/af.c index dfa02dd5..e4f5416b 100644 --- a/freebsd/contrib/tcpdump/af.c +++ b/freebsd/contrib/tcpdump/af.c @@ -18,7 +18,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H diff --git a/freebsd/contrib/tcpdump/af.h b/freebsd/contrib/tcpdump/af.h index 1bde577e..6365b126 100644 --- a/freebsd/contrib/tcpdump/af.h +++ b/freebsd/contrib/tcpdump/af.h @@ -12,7 +12,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ extern const struct tok af_values[]; diff --git a/freebsd/contrib/tcpdump/checksum.c b/freebsd/contrib/tcpdump/checksum.c index 87448b5b..84ce8a77 100644 --- a/freebsd/contrib/tcpdump/checksum.c +++ b/freebsd/contrib/tcpdump/checksum.c @@ -20,7 +20,7 @@ * * miscellaneous checksumming routines * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H diff --git a/freebsd/contrib/tcpdump/extract.h b/freebsd/contrib/tcpdump/extract.h index 23623c28..5969c225 100644 --- a/freebsd/contrib/tcpdump/extract.h +++ b/freebsd/contrib/tcpdump/extract.h @@ -20,8 +20,48 @@ */ /* - * Macros to extract possibly-unaligned big-endian integral values. + * For 8-bit values; provided for the sake of completeness. Byte order + * isn't relevant, and alignment isn't an issue. */ +#define EXTRACT_8BITS(p) (*(p)) +#define EXTRACT_LE_8BITS(p) (*(p)) + +/* + * Inline functions or macros to extract possibly-unaligned big-endian + * integral values. + */ +#include "funcattrs.h" + +/* + * If we have versions of GCC or Clang that support an __attribute__ + * to say "if we're building with unsigned behavior sanitization, + * don't complain about undefined behavior in this function", we + * label these functions with that attribute - we *know* it's undefined + * in the C standard, but we *also* know it does what we want with + * the ISA we're targeting and the compiler we're using. + * + * For GCC 4.9.0 and later, we use __attribute__((no_sanitize_undefined)); + * pre-5.0 GCC doesn't have __has_attribute, and I'm not sure whether + * GCC or Clang first had __attribute__((no_sanitize(XXX)). + * + * For Clang, we check for __attribute__((no_sanitize(XXX)) with + * __has_attribute, as there are versions of Clang that support + * __attribute__((no_sanitize("undefined")) but don't support + * __attribute__((no_sanitize_undefined)). + * + * We define this here, rather than in funcattrs.h, because we + * only want it used here, we don't want it to be broadly used. + * (Any printer will get this defined, but this should at least + * make it harder for people to find.) + */ +#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 409) +#define UNALIGNED_OK __attribute__((no_sanitize_undefined)) +#elif __has_attribute(no_sanitize) +#define UNALIGNED_OK __attribute__((no_sanitize("undefined"))) +#else +#define UNALIGNED_OK +#endif + #ifdef LBL_ALIGN /* * The processor doesn't natively handle unaligned loads. @@ -31,7 +71,7 @@ defined(__mips) || defined(__mips__)) /* - * This is a GCC-compatible compiler and we have __attribute__, which +* This is a GCC-compatible compiler and we have __attribute__, which * we assume that mean we have __attribute__((packed)), and this is * MIPS or Alpha, which has instructions that can help when doing * unaligned loads. @@ -88,19 +128,19 @@ typedef struct { uint32_t val; } __attribute__((packed)) unaligned_uint32_t; -static inline uint16_t +UNALIGNED_OK static inline uint16_t EXTRACT_16BITS(const void *p) { return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val)); } -static inline uint32_t +UNALIGNED_OK static inline uint32_t EXTRACT_32BITS(const void *p) { return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val)); } -static inline uint64_t +UNALIGNED_OK static inline uint64_t EXTRACT_64BITS(const void *p) { return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | @@ -138,19 +178,19 @@ EXTRACT_64BITS(const void *p) * The processor natively handles unaligned loads, so we can just * cast the pointer and fetch through it. */ -static inline uint16_t +static inline uint16_t UNALIGNED_OK EXTRACT_16BITS(const void *p) { return ((uint16_t)ntohs(*(const uint16_t *)(p))); } -static inline uint32_t +static inline uint32_t UNALIGNED_OK EXTRACT_32BITS(const void *p) { return ((uint32_t)ntohl(*(const uint32_t *)(p))); } -static inline uint64_t +static inline uint64_t UNALIGNED_OK EXTRACT_64BITS(const void *p) { return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | @@ -193,7 +233,6 @@ EXTRACT_64BITS(const void *p) * Macros to extract possibly-unaligned little-endian integral values. * XXX - do loads on little-endian machines that support unaligned loads? */ -#define EXTRACT_LE_8BITS(p) (*(p)) #define EXTRACT_LE_16BITS(p) \ ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \ ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0))) @@ -242,3 +281,6 @@ EXTRACT_64BITS(const void *p) #define ND_TTEST_64BITS(p) ND_TTEST2(*(p), 8) #define ND_TCHECK_64BITS(p) ND_TCHECK2(*(p), 8) + +#define ND_TTEST_128BITS(p) ND_TTEST2(*(p), 16) +#define ND_TCHECK_128BITS(p) ND_TCHECK2(*(p), 16) diff --git a/freebsd/contrib/tcpdump/funcattrs.h b/freebsd/contrib/tcpdump/funcattrs.h new file mode 100644 index 00000000..63d3f565 --- /dev/null +++ b/freebsd/contrib/tcpdump/funcattrs.h @@ -0,0 +1,122 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ +/* + * Copyright (c) 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lib_funcattrs_h +#define lib_funcattrs_h + +/* + * Attributes to apply to functions and their arguments, using various + * compiler-specific extensions. + */ + +/* + * This was introduced by Clang: + * + * http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute + * + * in some version (which version?); it has been picked up by GCC 5.0. + */ +#ifndef __has_attribute + /* + * It's a macro, so you can check whether it's defined to check + * whether it's supported. + * + * If it's not, define it to always return 0, so that we move on to + * the fallback checks. + */ + #define __has_attribute(x) 0 +#endif + +/* + * NORETURN, before a function declaration, means "this function + * never returns". (It must go before the function declaration, e.g. + * "extern NORETURN func(...)" rather than after the function + * declaration, as the MSVC version has to go before the declaration.) + */ +#if __has_attribute(noreturn) \ + || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 205)) \ + || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) \ + || (defined(__xlC__) && __xlC__ >= 0x0A01) \ + || (defined(__HP_aCC) && __HP_aCC >= 61000) + /* + * Compiler with support for __attribute((noreturn)), or GCC 2.5 and + * later, or Solaris Studio 12 (Sun C 5.9) and later, or IBM XL C 10.1 + * and later (do any earlier versions of XL C support this?), or + * HP aCC A.06.10 and later. + */ + #define NORETURN __attribute((noreturn)) +#elif defined(_MSC_VER) + /* + * MSVC. + */ + #define NORETURN __declspec(noreturn) +#else + #define NORETURN +#endif + +/* + * PRINTFLIKE(x,y), after a function declaration, means "this function + * does printf-style formatting, with the xth argument being the format + * string and the yth argument being the first argument for the format + * string". + */ +#if __has_attribute(__format__) \ + || (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 203)) \ + || (defined(__xlC__) && __xlC__ >= 0x0A01) \ + || (defined(__HP_aCC) && __HP_aCC >= 61000) + /* + * Compiler with support for it, or GCC 2.3 and later, or IBM XL C 10.1 + * and later (do any earlier versions of XL C support this?), + * or HP aCC A.06.10 and later. + */ + #define PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y))) +#else + #define PRINTFLIKE(x,y) +#endif + +/* + * For flagging arguments as format strings in MSVC. + */ +#if _MSC_VER >= 1400 + #include <sal.h> + #if _MSC_VER > 1400 + #define FORMAT_STRING(p) _Printf_format_string_ p + #else + #define FORMAT_STRING(p) __format_string p + #endif +#else + #define FORMAT_STRING(p) p +#endif + +#endif /* lib_funcattrs_h */ diff --git a/freebsd/contrib/tcpdump/gmpls.c b/freebsd/contrib/tcpdump/gmpls.c index 4b45ba26..e8cb7ff0 100644 --- a/freebsd/contrib/tcpdump/gmpls.c +++ b/freebsd/contrib/tcpdump/gmpls.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H diff --git a/freebsd/contrib/tcpdump/gmpls.h b/freebsd/contrib/tcpdump/gmpls.h index 8b44f949..32fa8114 100644 --- a/freebsd/contrib/tcpdump/gmpls.h +++ b/freebsd/contrib/tcpdump/gmpls.h @@ -10,7 +10,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #define GMPLS_PSC1 1 diff --git a/freebsd/contrib/tcpdump/ip6.h b/freebsd/contrib/tcpdump/ip6.h index 2ea1d0ab..9a24ef14 100644 --- a/freebsd/contrib/tcpdump/ip6.h +++ b/freebsd/contrib/tcpdump/ip6.h @@ -178,14 +178,13 @@ struct ip6_rthdr { /* Type 0 Routing header */ /* Also used for Type 2 */ struct ip6_rthdr0 { - uint8_t ip6r0_nxt; /* next header */ - uint8_t ip6r0_len; /* length in units of 8 octets */ - uint8_t ip6r0_type; /* always zero */ - uint8_t ip6r0_segleft; /* segments left */ - uint8_t ip6r0_reserved; /* reserved field */ - uint8_t ip6r0_slmap[3]; /* strict/loose bit map */ + nd_uint8_t ip6r0_nxt; /* next header */ + nd_uint8_t ip6r0_len; /* length in units of 8 octets */ + nd_uint8_t ip6r0_type; /* always zero */ + nd_uint8_t ip6r0_segleft; /* segments left */ + nd_uint32_t ip6r0_reserved; /* reserved field */ struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */ -} UNALIGNED; +}; /* Fragment header */ struct ip6_frag { diff --git a/freebsd/contrib/tcpdump/ipproto.c b/freebsd/contrib/tcpdump/ipproto.c index 44fae5d6..38c5de80 100644 --- a/freebsd/contrib/tcpdump/ipproto.c +++ b/freebsd/contrib/tcpdump/ipproto.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H @@ -61,6 +61,312 @@ const struct tok ipproto_values[] = { { 0, NULL } }; +/* + * For completeness the number space in the array below comes from IANA: + * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + * However, the spelling tries to match that of /etc/protocols to achieve as + * much consistency as possible with the previously implemented behaviour, + * which was based on getprotobynumber (3). + */ +static const char *const netdb_protocol_names[256] = { + "hopopt", /* 0 (IPPROTO_HOPOPTS, IPv6 Hop-by-Hop Option) */ + "icmp", /* 1 (IPPROTO_ICMP, Internet Control Message) */ + "igmp", /* 2 (IPPROTO_IGMP, Internet Group Management) */ + "ggp", /* 3 (Gateway-to-Gateway) */ + "ipencap", /* 4 (IPPROTO_IPV4, IPv4 encapsulation) */ + "st", /* 5 (Stream, ST datagram mode) */ + "tcp", /* 6 (IPPROTO_TCP, Transmission Control) */ + "cbt", /* 7 (CBT) */ + "egp", /* 8 (IPPROTO_EGP, Exterior Gateway Protocol) */ + "igp", /* 9 (IPPROTO_PIGP, "any private interior gateway + * (used by Cisco for their IGRP)") + */ + "bbn-rcc-mon", /* 10 (BBN RCC Monitoring) */ + "nvp-ii", /* 11 (Network Voice Protocol) */ + "pup", /* 12 (PARC universal packet protocol) */ + "argus", /* 13 (ARGUS) */ + "emcon", /* 14 (EMCON) */ + "xnet", /* 15 (Cross Net Debugger) */ + "chaos", /* 16 (Chaos) */ + "udp", /* 17 (IPPROTO_UDP, User Datagram) */ + "mux", /* 18 (Multiplexing) */ + "dcn-meas", /* 19 (DCN Measurement Subsystems) */ + "hmp", /* 20 (Host Monitoring) */ + "prm", /* 21 (Packet Radio Measurement) */ + "xns-idp", /* 22 (XEROX NS IDP) */ + "trunk-1", /* 23 (Trunk-1) */ + "trunk-2", /* 24 (Trunk-2) */ + "leaf-1", /* 25 (Leaf-1) */ + "leaf-2", /* 26 (Leaf-2) */ + "rdp", /* 27 (Reliable Data Protocol) */ + "irtp", /* 28 (Internet Reliable Transaction) */ + "iso-tp4", /* 29 (ISO Transport Protocol Class 4) */ + "netblt", /* 30 (Bulk Data Transfer Protocol) */ + "mfe-nsp", /* 31 (MFE Network Services Protocol) */ + "merit-inp", /* 32 (MERIT Internodal Protocol) */ + "dccp", /* 33 (IPPROTO_DCCP, Datagram Congestion + * Control Protocol) + */ + "3pc", /* 34 (Third Party Connect Protocol) */ + "idpr", /* 35 (Inter-Domain Policy Routing Protocol) */ + "xtp", /* 36 (Xpress Transfer Protocol) */ + "ddp", /* 37 (Datagram Delivery Protocol) */ + "idpr-cmtp", /* 38 (IDPR Control Message Transport Proto) */ + "tp++", /* 39 (TP++ Transport Protocol) */ + "il", /* 40 (IL Transport Protocol) */ + "ipv6", /* 41 (IPPROTO_IPV6, IPv6 encapsulation) */ + "sdrp", /* 42 (Source Demand Routing Protocol) */ + "ipv6-route", /* 43 (IPPROTO_ROUTING, Routing Header for IPv6) */ + "ipv6-frag", /* 44 (IPPROTO_FRAGMENT, Fragment Header for + * IPv6) + */ + "idrp", /* 45 (Inter-Domain Routing Protocol) */ + "rsvp", /* 46 (IPPROTO_RSVP, Reservation Protocol) */ + "gre", /* 47 (IPPROTO_GRE, Generic Routing + * Encapsulation) + */ + "dsr", /* 48 (Dynamic Source Routing Protocol) */ + "bna", /* 49 (BNA) */ + "esp", /* 50 (IPPROTO_ESP, Encap Security Payload) */ + "ah", /* 51 (IPPROTO_AH, Authentication Header) */ + "i-nlsp", /* 52 (Integrated Net Layer Security TUBA) */ + "swipe", /* 53 (IP with Encryption) */ + "narp", /* 54 (NBMA Address Resolution Protocol) */ + "mobile", /* 55 (IPPROTO_MOBILE, IP Mobility) */ + "tlsp", /* 56 (Transport Layer Security Protocol using + * Kryptonet key management) + */ + "skip", /* 57 (SKIP) */ + "ipv6-icmp", /* 58 (IPPROTO_ICMPV6, ICMP for IPv6) */ + "ipv6-nonxt", /* 59 (IPPROTO_NONE, No Next Header for IPv6) */ + "ipv6-opts", /* 60 (IPPROTO_DSTOPTS, Destination Options for + * IPv6) + */ + NULL, /* 61 (any host internal protocol) */ + "cftp", /* 62 (IPPROTO_MOBILITY_OLD, CFTP, see the note + * in ipproto.h) + */ + NULL, /* 63 (any local network) */ + "sat-expak", /* 64 (SATNET and Backroom EXPAK) */ + "kryptolan", /* 65 (Kryptolan) */ + "rvd", /* 66 (MIT Remote Virtual Disk Protocol) */ + "ippc", /* 67 (Internet Pluribus Packet Core) */ + NULL, /* 68 (any distributed file system) */ + "sat-mon", /* 69 (SATNET Monitoring) */ + "visa", /* 70 (VISA Protocol) */ + "ipcv", /* 71 (Internet Packet Core Utility) */ + "cpnx", /* 72 (Computer Protocol Network Executive) */ + "rspf", /* 73 (Radio Shortest Path First, CPHB -- Computer + * Protocol Heart Beat -- in IANA) + */ + "wsn", /* 74 (Wang Span Network) */ + "pvp", /* 75 (Packet Video Protocol) */ + "br-sat-mon", /* 76 (Backroom SATNET Monitoring) */ + "sun-nd", /* 77 (IPPROTO_ND, SUN ND PROTOCOL-Temporary) */ + "wb-mon", /* 78 (WIDEBAND Monitoring) */ + "wb-expak", /* 79 (WIDEBAND EXPAK) */ + "iso-ip", /* 80 (ISO Internet Protocol) */ + "vmtp", /* 81 (Versatile Message Transport) */ + "secure-vmtp", /* 82 (Secure VMTP) */ + "vines", /* 83 (VINES) */ + "ttp", /* 84 (Transaction Transport Protocol, also IPTM -- + * Internet Protocol Traffic Manager) + */ + "nsfnet-igp", /* 85 (NSFNET-IGP) */ + "dgp", /* 86 (Dissimilar Gateway Protocol) */ + "tcf", /* 87 (TCF) */ + "eigrp", /* 88 (IPPROTO_EIGRP, Cisco EIGRP) */ + "ospf", /* 89 (IPPROTO_OSPF, Open Shortest Path First + * IGP) + */ + "sprite-rpc", /* 90 (Sprite RPC Protocol) */ + "larp", /* 91 (Locus Address Resolution Protocol) */ + "mtp", /* 92 (Multicast Transport Protocol) */ + "ax.25", /* 93 (AX.25 Frames) */ + "ipip", /* 94 (IP-within-IP Encapsulation Protocol) */ + "micp", /* 95 (Mobile Internetworking Control Pro.) */ + "scc-sp", /* 96 (Semaphore Communications Sec. Pro.) */ + "etherip", /* 97 (Ethernet-within-IP Encapsulation) */ + "encap", /* 98 (Encapsulation Header) */ + NULL, /* 99 (any private encryption scheme) */ + "gmtp", /* 100 (GMTP) */ + "ifmp", /* 101 (Ipsilon Flow Management Protocol) */ + "pnni", /* 102 (PNNI over IP) */ + "pim", /* 103 (IPPROTO_PIM, Protocol Independent + * Multicast) + */ + "aris", /* 104 (ARIS) */ + "scps", /* 105 (SCPS) */ + "qnx", /* 106 (QNX) */ + "a/n", /* 107 (Active Networks) */ + "ipcomp", /* 108 (IPPROTO_IPCOMP, IP Payload Compression + * Protocol) + */ + "snp", /* 109 (Sitara Networks Protocol) */ + "compaq-peer", /* 110 (Compaq Peer Protocol) */ + "ipx-in-ip", /* 111 (IPX in IP) */ + "vrrp", /* 112 (IPPROTO_VRRP, Virtual Router Redundancy + * Protocol) + */ + "pgm", /* 113 (IPPROTO_PGM, PGM Reliable Transport + * Protocol) + */ + NULL, /* 114 (any 0-hop protocol) */ + "l2tp", /* 115 (Layer Two Tunneling Protocol) */ + "ddx", /* 116 (D-II Data Exchange (DDX)) */ + "iatp", /* 117 (Interactive Agent Transfer Protocol) */ + "stp", /* 118 (Schedule Transfer Protocol) */ + "srp", /* 119 (SpectraLink Radio Protocol) */ + "uti", /* 120 (UTI) */ + "smp", /* 121 (Simple Message Protocol) */ + "sm", /* 122 (Simple Multicast Protocol) */ + "ptp", /* 123 (Performance Transparency Protocol) */ + "isis", /* 124 (ISIS over IPv4) */ + "fire", /* 125 (FIRE) */ + "crtp", /* 126 (Combat Radio Transport Protocol) */ + "crudp", /* 127 (Combat Radio User Datagram) */ + "sscopmce", /* 128 (SSCOPMCE) */ + "iplt", /* 129 (IPLT) */ + "sps", /* 130 (Secure Packet Shield) */ + "pipe", /* 131 (Private IP Encapsulation within IP) */ + "sctp", /* 132 (IPPROTO_SCTP, Stream Control Transmission + * Protocol) + */ + "fc", /* 133 (Fibre Channel) */ + "rsvp-e2e-ignore", /* 134 (RSVP-E2E-IGNORE) */ + "mobility-header", /* 135 (IPPROTO_MOBILITY, Mobility Header) */ + "udplite", /* 136 (UDPLite) */ + "mpls-in-ip", /* 137 (MPLS-in-IP) */ + "manet", /* 138 (MANET Protocols) */ + "hip", /* 139 (Host Identity Protocol) */ + "shim6", /* 140 (Shim6 Protocol) */ + "wesp", /* 141 (Wrapped Encapsulating Security Payload) */ + "rohc", /* 142 (Robust Header Compression) */ + NULL, /* 143 (unassigned) */ + NULL, /* 144 (unassigned) */ + NULL, /* 145 (unassigned) */ + NULL, /* 146 (unassigned) */ + NULL, /* 147 (unassigned) */ + NULL, /* 148 (unassigned) */ + NULL, /* 149 (unassigned) */ + NULL, /* 150 (unassigned) */ + NULL, /* 151 (unassigned) */ + NULL, /* 152 (unassigned) */ + NULL, /* 153 (unassigned) */ + NULL, /* 154 (unassigned) */ + NULL, /* 155 (unassigned) */ + NULL, /* 156 (unassigned) */ + NULL, /* 157 (unassigned) */ + NULL, /* 158 (unassigned) */ + NULL, /* 159 (unassigned) */ + NULL, /* 160 (unassigned) */ + NULL, /* 161 (unassigned) */ + NULL, /* 162 (unassigned) */ + NULL, /* 163 (unassigned) */ + NULL, /* 164 (unassigned) */ + NULL, /* 165 (unassigned) */ + NULL, /* 166 (unassigned) */ + NULL, /* 167 (unassigned) */ + NULL, /* 168 (unassigned) */ + NULL, /* 169 (unassigned) */ + NULL, /* 170 (unassigned) */ + NULL, /* 171 (unassigned) */ + NULL, /* 172 (unassigned) */ + NULL, /* 173 (unassigned) */ + NULL, /* 174 (unassigned) */ + NULL, /* 175 (unassigned) */ + NULL, /* 176 (unassigned) */ + NULL, /* 177 (unassigned) */ + NULL, /* 178 (unassigned) */ + NULL, /* 179 (unassigned) */ + NULL, /* 180 (unassigned) */ + NULL, /* 181 (unassigned) */ + NULL, /* 182 (unassigned) */ + NULL, /* 183 (unassigned) */ + NULL, /* 184 (unassigned) */ + NULL, /* 185 (unassigned) */ + NULL, /* 186 (unassigned) */ + NULL, /* 187 (unassigned) */ + NULL, /* 188 (unassigned) */ + NULL, /* 189 (unassigned) */ + NULL, /* 190 (unassigned) */ + NULL, /* 191 (unassigned) */ + NULL, /* 192 (unassigned) */ + NULL, /* 193 (unassigned) */ + NULL, /* 194 (unassigned) */ + NULL, /* 195 (unassigned) */ + NULL, /* 196 (unassigned) */ + NULL, /* 197 (unassigned) */ + NULL, /* 198 (unassigned) */ + NULL, /* 199 (unassigned) */ + NULL, /* 200 (unassigned) */ + NULL, /* 201 (unassigned) */ + NULL, /* 202 (unassigned) */ + NULL, /* 203 (unassigned) */ + NULL, /* 204 (unassigned) */ + NULL, /* 205 (unassigned) */ + NULL, /* 206 (unassigned) */ + NULL, /* 207 (unassigned) */ + NULL, /* 208 (unassigned) */ + NULL, /* 209 (unassigned) */ + NULL, /* 210 (unassigned) */ + NULL, /* 211 (unassigned) */ + NULL, /* 212 (unassigned) */ + NULL, /* 213 (unassigned) */ + NULL, /* 214 (unassigned) */ + NULL, /* 215 (unassigned) */ + NULL, /* 216 (unassigned) */ + NULL, /* 217 (unassigned) */ + NULL, /* 218 (unassigned) */ + NULL, /* 219 (unassigned) */ + NULL, /* 220 (unassigned) */ + NULL, /* 221 (unassigned) */ + NULL, /* 222 (unassigned) */ + NULL, /* 223 (unassigned) */ + NULL, /* 224 (unassigned) */ + NULL, /* 225 (unassigned) */ + NULL, /* 226 (unassigned) */ + NULL, /* 227 (unassigned) */ + NULL, /* 228 (unassigned) */ + NULL, /* 229 (unassigned) */ + NULL, /* 230 (unassigned) */ + NULL, /* 231 (unassigned) */ + NULL, /* 232 (unassigned) */ + NULL, /* 233 (unassigned) */ + NULL, /* 234 (unassigned) */ + NULL, /* 235 (unassigned) */ + NULL, /* 236 (unassigned) */ + NULL, /* 237 (unassigned) */ + NULL, /* 238 (unassigned) */ + NULL, /* 239 (unassigned) */ + NULL, /* 240 (unassigned) */ + NULL, /* 241 (unassigned) */ + NULL, /* 242 (unassigned) */ + NULL, /* 243 (unassigned) */ + NULL, /* 244 (unassigned) */ + NULL, /* 245 (unassigned) */ + NULL, /* 246 (unassigned) */ + NULL, /* 247 (unassigned) */ + NULL, /* 248 (unassigned) */ + NULL, /* 249 (unassigned) */ + NULL, /* 250 (unassigned) */ + NULL, /* 251 (unassigned) */ + NULL, /* 252 (unassigned) */ + "exptest-253", /* 253 (Use for experimentation and testing, + * RFC 3692) + */ + "exptest-254", /* 254 (Use for experimentation and testing, + * RFC 3692) + */ + "reserved", /* 255 (reserved) */ +}; + +/* The function enforces the array index to be 8-bit. */ +const char * +netdb_protoname (const nd_uint8_t protoid) +{ + return netdb_protocol_names[protoid]; +} #ifdef __rtems__ #include "rtems-bsd-tcpdump-ipproto-data.h" #endif /* __rtems__ */ diff --git a/freebsd/contrib/tcpdump/ipproto.h b/freebsd/contrib/tcpdump/ipproto.h index 4719d4d3..aeefc809 100644 --- a/freebsd/contrib/tcpdump/ipproto.h +++ b/freebsd/contrib/tcpdump/ipproto.h @@ -36,6 +36,7 @@ */ extern const struct tok ipproto_values[]; +extern const char *netdb_protoname (const nd_uint8_t); #ifndef IPPROTO_IP #define IPPROTO_IP 0 /* dummy for IP */ @@ -109,7 +110,7 @@ extern const struct tok ipproto_values[]; * It appears that 62 used to be used, even though that's assigned to * a protocol called CFTP; however, the only reference for CFTP is a * Network Message from BBN back in 1982, so, for now, we support 62, - * aas well as 135, as a protocol number for mobility headers. + * as well as 135, as a protocol number for mobility headers. */ #define IPPROTO_MOBILITY_OLD 62 #endif diff --git a/freebsd/contrib/tcpdump/l2vpn.c b/freebsd/contrib/tcpdump/l2vpn.c index 5a77136b..72831bf8 100644 --- a/freebsd/contrib/tcpdump/l2vpn.c +++ b/freebsd/contrib/tcpdump/l2vpn.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H diff --git a/freebsd/contrib/tcpdump/l2vpn.h b/freebsd/contrib/tcpdump/l2vpn.h index d93abf15..98b6fcc8 100644 --- a/freebsd/contrib/tcpdump/l2vpn.h +++ b/freebsd/contrib/tcpdump/l2vpn.h @@ -10,7 +10,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ extern const struct tok l2vpn_encaps_values[]; diff --git a/freebsd/contrib/tcpdump/netdissect-stdinc.h b/freebsd/contrib/tcpdump/netdissect-stdinc.h index c7070f0a..8282c584 100644 --- a/freebsd/contrib/tcpdump/netdissect-stdinc.h +++ b/freebsd/contrib/tcpdump/netdissect-stdinc.h @@ -394,6 +394,11 @@ struct in6_addr { * end of Apple deprecation workaround macros */ +/* + * Function attributes, for various compilers. + */ +#include "funcattrs.h" + #ifndef min #define min(a,b) ((a)>(b)?(b):(a)) #endif diff --git a/freebsd/contrib/tcpdump/netdissect.h b/freebsd/contrib/tcpdump/netdissect.h index 1d28c0b7..105c490a 100644 --- a/freebsd/contrib/tcpdump/netdissect.h +++ b/freebsd/contrib/tcpdump/netdissect.h @@ -82,19 +82,13 @@ extern int32_t thiszone; /* seconds offset from gmt to local time */ extern const char istr[]; #if !defined(HAVE_SNPRINTF) -int snprintf (char *str, size_t sz, const char *format, ...) -#ifdef __ATTRIBUTE___FORMAT_OK - __attribute__((format (printf, 3, 4))) -#endif /* __ATTRIBUTE___FORMAT_OK */ - ; +int snprintf (char *str, size_t sz, FORMAT_STRING(const char *format), ...) + PRINTFLIKE(3, 4); #endif /* !defined(HAVE_SNPRINTF) */ #if !defined(HAVE_VSNPRINTF) -int vsnprintf (char *str, size_t sz, const char *format, va_list ap) -#ifdef __ATTRIBUTE___FORMAT_OK - __attribute__((format (printf, 3, 0))) -#endif /* __ATTRIBUTE___FORMAT_OK */ - ; +int vsnprintf (char *str, size_t sz, FORMAT_STRING(const char *format), + va_list ap) PRINTFLIKE(3, 0); #endif /* !defined(HAVE_VSNPRINTF) */ #ifndef HAVE_STRLCAT @@ -531,7 +525,7 @@ extern void ipx_netbios_print(netdissect_options *, const u_char *, u_int); extern void ipx_print(netdissect_options *, const u_char *, u_int); extern void isakmp_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void isakmp_rfc3948_print(netdissect_options *, const u_char *, u_int, const u_char *); -extern void isoclns_print(netdissect_options *, const u_char *, u_int, u_int); +extern void isoclns_print(netdissect_options *, const u_char *, u_int); extern void krb_print(netdissect_options *, const u_char *); extern void l2tp_print(netdissect_options *, const u_char *, u_int); extern void lane_print(netdissect_options *, const u_char *, u_int, u_int); diff --git a/freebsd/contrib/tcpdump/nlpid.c b/freebsd/contrib/tcpdump/nlpid.c index 5060aae6..6ba92f4e 100644 --- a/freebsd/contrib/tcpdump/nlpid.c +++ b/freebsd/contrib/tcpdump/nlpid.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H diff --git a/freebsd/contrib/tcpdump/nlpid.h b/freebsd/contrib/tcpdump/nlpid.h index 63a2e709..a3a69054 100644 --- a/freebsd/contrib/tcpdump/nlpid.h +++ b/freebsd/contrib/tcpdump/nlpid.h @@ -10,7 +10,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ extern const struct tok nlpid_values[]; diff --git a/freebsd/contrib/tcpdump/oui.c b/freebsd/contrib/tcpdump/oui.c index 9fb86c6f..922c6e9e 100644 --- a/freebsd/contrib/tcpdump/oui.c +++ b/freebsd/contrib/tcpdump/oui.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H diff --git a/freebsd/contrib/tcpdump/oui.h b/freebsd/contrib/tcpdump/oui.h index a85f883d..a9f732a7 100644 --- a/freebsd/contrib/tcpdump/oui.h +++ b/freebsd/contrib/tcpdump/oui.h @@ -10,7 +10,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ extern const struct tok oui_values[]; diff --git a/freebsd/contrib/tcpdump/print-802_11.c b/freebsd/contrib/tcpdump/print-802_11.c index 3310eb16..990b5777 100644 --- a/freebsd/contrib/tcpdump/print-802_11.c +++ b/freebsd/contrib/tcpdump/print-802_11.c @@ -1045,10 +1045,6 @@ parse_elements(netdissect_options *ndo, if (ssid.length != 0) { if (ssid.length > sizeof(ssid.ssid) - 1) return 0; - if (!ND_TTEST2(*(p + offset), ssid.length)) - return 0; - if (length < ssid.length) - return 0; memcpy(&ssid.ssid, p + offset, ssid.length); offset += ssid.length; length -= ssid.length; @@ -1074,10 +1070,6 @@ parse_elements(netdissect_options *ndo, if (challenge.length > sizeof(challenge.text) - 1) return 0; - if (!ND_TTEST2(*(p + offset), challenge.length)) - return 0; - if (length < challenge.length) - return 0; memcpy(&challenge.text, p + offset, challenge.length); offset += challenge.length; @@ -1103,10 +1095,6 @@ parse_elements(netdissect_options *ndo, if (rates.length != 0) { if (rates.length > sizeof rates.rate) return 0; - if (!ND_TTEST2(*(p + offset), rates.length)) - return 0; - if (length < rates.length) - return 0; memcpy(&rates.rate, p + offset, rates.length); offset += rates.length; length -= rates.length; @@ -1195,8 +1183,7 @@ parse_elements(netdissect_options *ndo, offset += 3; length -= 3; - memcpy(tim.bitmap, p + (tim.length - 3), - (tim.length - 3)); + memcpy(tim.bitmap, p + offset, tim.length - 3); offset += tim.length - 3; length -= tim.length - 3; /* diff --git a/freebsd/contrib/tcpdump/print-802_15_4.c b/freebsd/contrib/tcpdump/print-802_15_4.c index e1c8b7b5..2b4a6bb2 100644 --- a/freebsd/contrib/tcpdump/print-802_15_4.c +++ b/freebsd/contrib/tcpdump/print-802_15_4.c @@ -44,146 +44,188 @@ static const char *ftypes[] = { "Data", /* 1 */ "ACK", /* 2 */ "Command", /* 3 */ - "Reserved", /* 4 */ - "Reserved", /* 5 */ - "Reserved", /* 6 */ - "Reserved", /* 7 */ + "Reserved (0x4)", /* 4 */ + "Reserved (0x5)", /* 5 */ + "Reserved (0x6)", /* 6 */ + "Reserved (0x7)", /* 7 */ }; -static int -extract_header_length(uint16_t fc) -{ - int len = 0; - - switch ((fc >> 10) & 0x3) { - case 0x00: - if (fc & (1 << 6)) /* intra-PAN with none dest addr */ - return -1; - break; - case 0x01: - return -1; - case 0x02: - len += 4; - break; - case 0x03: - len += 10; - break; - } - - switch ((fc >> 14) & 0x3) { - case 0x00: - break; - case 0x01: - return -1; - case 0x02: - len += 4; - break; - case 0x03: - len += 10; - break; - } - - if (fc & (1 << 6)) { - if (len < 2) - return -1; - len -= 2; - } - - return len; -} - +/* + * Frame Control subfields. + */ +#define FC_FRAME_TYPE(fc) ((fc) & 0x7) +#define FC_SECURITY_ENABLED 0x0008 +#define FC_FRAME_PENDING 0x0010 +#define FC_ACK_REQUEST 0x0020 +#define FC_PAN_ID_COMPRESSION 0x0040 +#define FC_DEST_ADDRESSING_MODE(fc) (((fc) >> 10) & 0x3) +#define FC_FRAME_VERSION(fc) (((fc) >> 12) & 0x3) +#define FC_SRC_ADDRESSING_MODE(fc) (((fc) >> 14) & 0x3) + +#define FC_ADDRESSING_MODE_NONE 0x00 +#define FC_ADDRESSING_MODE_RESERVED 0x01 +#define FC_ADDRESSING_MODE_SHORT 0x02 +#define FC_ADDRESSING_MODE_LONG 0x03 u_int ieee802_15_4_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; - int hdrlen; + u_int hdrlen; uint16_t fc; uint8_t seq; + uint16_t panid = 0; if (caplen < 3) { - ND_PRINT((ndo, "[|802.15.4] %x", caplen)); + ND_PRINT((ndo, "[|802.15.4]")); return caplen; } + hdrlen = 3; fc = EXTRACT_LE_16BITS(p); - hdrlen = extract_header_length(fc); - seq = EXTRACT_LE_8BITS(p + 2); p += 3; caplen -= 3; - ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7])); + ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[FC_FRAME_TYPE(fc)])); if (ndo->ndo_vflag) ND_PRINT((ndo,"seq %02x ", seq)); - if (hdrlen == -1) { - ND_PRINT((ndo,"invalid! ")); - return caplen; - } - - - if (!ndo->ndo_vflag) { - p+= hdrlen; - caplen -= hdrlen; - } else { - uint16_t panid = 0; - switch ((fc >> 10) & 0x3) { - case 0x00: + /* + * Destination address and PAN ID, if present. + */ + switch (FC_DEST_ADDRESSING_MODE(fc)) { + case FC_ADDRESSING_MODE_NONE: + if (fc & FC_PAN_ID_COMPRESSION) { + /* + * PAN ID compression; this requires that both + * the source and destination addresses be present, + * but the destination address is missing. + */ + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; + } + if (ndo->ndo_vflag) ND_PRINT((ndo,"none ")); - break; - case 0x01: + break; + case FC_ADDRESSING_MODE_RESERVED: + if (ndo->ndo_vflag) ND_PRINT((ndo,"reserved destination addressing mode")); - return 0; - case 0x02: - panid = EXTRACT_LE_16BITS(p); - p += 2; + return hdrlen; + case FC_ADDRESSING_MODE_SHORT: + if (caplen < 2) { + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; + } + panid = EXTRACT_LE_16BITS(p); + p += 2; + caplen -= 2; + hdrlen += 2; + if (caplen < 2) { + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; + } + if (ndo->ndo_vflag) ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); - p += 2; - break; - case 0x03: - panid = EXTRACT_LE_16BITS(p); - p += 2; - ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); - p += 8; - break; + p += 2; + caplen -= 2; + hdrlen += 2; + break; + case FC_ADDRESSING_MODE_LONG: + if (caplen < 2) { + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; + } + panid = EXTRACT_LE_16BITS(p); + p += 2; + caplen -= 2; + hdrlen += 2; + if (caplen < 8) { + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; } + if (ndo->ndo_vflag) + ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); + p += 8; + caplen -= 8; + hdrlen += 8; + break; + } + if (ndo->ndo_vflag) ND_PRINT((ndo,"< ")); - switch ((fc >> 14) & 0x3) { - case 0x00: + /* + * Source address and PAN ID, if present. + */ + switch (FC_SRC_ADDRESSING_MODE(fc)) { + case FC_ADDRESSING_MODE_NONE: + if (ndo->ndo_vflag) ND_PRINT((ndo,"none ")); - break; - case 0x01: + break; + case FC_ADDRESSING_MODE_RESERVED: + if (ndo->ndo_vflag) ND_PRINT((ndo,"reserved source addressing mode")); - return 0; - case 0x02: - if (!(fc & (1 << 6))) { - panid = EXTRACT_LE_16BITS(p); - p += 2; + return 0; + case FC_ADDRESSING_MODE_SHORT: + if (!(fc & FC_PAN_ID_COMPRESSION)) { + /* + * The source PAN ID is not compressed out, so + * fetch it. (Otherwise, we'll use the destination + * PAN ID, fetched above.) + */ + if (caplen < 2) { + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; } - ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); + panid = EXTRACT_LE_16BITS(p); p += 2; - break; - case 0x03: - if (!(fc & (1 << 6))) { - panid = EXTRACT_LE_16BITS(p); - p += 2; + caplen -= 2; + hdrlen += 2; + } + if (caplen < 2) { + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; + } + if (ndo->ndo_vflag) + ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p))); + p += 2; + caplen -= 2; + hdrlen += 2; + break; + case FC_ADDRESSING_MODE_LONG: + if (!(fc & FC_PAN_ID_COMPRESSION)) { + /* + * The source PAN ID is not compressed out, so + * fetch it. (Otherwise, we'll use the destination + * PAN ID, fetched above.) + */ + if (caplen < 2) { + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; } - ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); - p += 8; - break; + panid = EXTRACT_LE_16BITS(p); + p += 2; + caplen -= 2; + hdrlen += 2; } - - caplen -= hdrlen; + if (caplen < 8) { + ND_PRINT((ndo, "[|802.15.4]")); + return hdrlen; + } + if (ndo->ndo_vflag) + ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p))); + p += 8; + caplen -= 8; + hdrlen += 8; + break; } if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); - return 0; + return hdrlen; } #ifdef __rtems__ #include "rtems-bsd-tcpdump-print-802_15_4-data.h" diff --git a/freebsd/contrib/tcpdump/print-aodv.c b/freebsd/contrib/tcpdump/print-aodv.c index b1a977c1..98677d5b 100644 --- a/freebsd/contrib/tcpdump/print-aodv.c +++ b/freebsd/contrib/tcpdump/print-aodv.c @@ -48,7 +48,9 @@ #include "addrtoname.h" #include "extract.h" - +/* + * RFC 3561 + */ struct aodv_rreq { uint8_t rreq_type; /* AODV message type (1) */ uint8_t rreq_flags; /* various flags */ @@ -184,12 +186,17 @@ aodv_extension(netdissect_options *ndo, { const struct aodv_hello *ah; + ND_TCHECK(*ep); switch (ep->type) { case AODV_EXT_HELLO: ah = (const struct aodv_hello *)(const void *)ep; ND_TCHECK(*ah); if (length < sizeof(struct aodv_hello)) goto trunc; + if (ep->length < 4) { + ND_PRINT((ndo, "\n\text HELLO - bad length %u", ep->length)); + break; + } ND_PRINT((ndo, "\n\text HELLO %ld ms", (unsigned long)EXTRACT_32BITS(&ah->interval))); break; diff --git a/freebsd/contrib/tcpdump/print-arp.c b/freebsd/contrib/tcpdump/print-arp.c index 86da2bcc..b19e1036 100644 --- a/freebsd/contrib/tcpdump/print-arp.c +++ b/freebsd/contrib/tcpdump/print-arp.c @@ -84,7 +84,7 @@ struct arp_pkthdr { u_char ar_tha[]; /* target hardware address */ u_char ar_tpa[]; /* target protocol address */ #endif -#define ar_sha(ap) (((const u_char *)((ap)+1))+0) +#define ar_sha(ap) (((const u_char *)((ap)+1))+ 0) #define ar_spa(ap) (((const u_char *)((ap)+1))+ (ap)->ar_hln) #define ar_tha(ap) (((const u_char *)((ap)+1))+ (ap)->ar_hln+(ap)->ar_pln) #define ar_tpa(ap) (((const u_char *)((ap)+1))+2*(ap)->ar_hln+(ap)->ar_pln) @@ -196,6 +196,30 @@ isnonzero(const u_char *a, size_t len) } static void +tpaddr_print_ip(netdissect_options *ndo, + const struct arp_pkthdr *ap, u_short pro) +{ + if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) + ND_PRINT((ndo, "<wrong proto type>")); + else if (PROTO_LEN(ap) != 4) + ND_PRINT((ndo, "<wrong len>")); + else + ND_PRINT((ndo, "%s", ipaddr_string(ndo, TPA(ap)))); +} + +static void +spaddr_print_ip(netdissect_options *ndo, + const struct arp_pkthdr *ap, u_short pro) +{ + if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) + ND_PRINT((ndo, "<wrong proto type>")); + else if (PROTO_LEN(ap) != 4) + ND_PRINT((ndo, "<wrong len>")); + else + ND_PRINT((ndo, "%s", ipaddr_string(ndo, SPA(ap)))); +} + +static void atmarp_addr_print(netdissect_options *ndo, const u_char *ha, u_int ha_len, const u_char *srca, u_int srca_len) @@ -211,6 +235,30 @@ atmarp_addr_print(netdissect_options *ndo, } static void +atmarp_tpaddr_print(netdissect_options *ndo, + const struct atmarp_pkthdr *ap, u_short pro) +{ + if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) + ND_PRINT((ndo, "<wrong proto type>")); + else if (ATMTPROTO_LEN(ap) != 4) + ND_PRINT((ndo, "<wrong tplen>")); + else + ND_PRINT((ndo, "%s", ipaddr_string(ndo, ATMTPA(ap)))); +} + +static void +atmarp_spaddr_print(netdissect_options *ndo, + const struct atmarp_pkthdr *ap, u_short pro) +{ + if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) + ND_PRINT((ndo, "<wrong proto type>")); + else if (ATMSPROTO_LEN(ap) != 4) + ND_PRINT((ndo, "<wrong splen>")); + else + ND_PRINT((ndo, "%s", ipaddr_string(ndo, ATMSPA(ap)))); +} + +static void atmarp_print(netdissect_options *ndo, const u_char *bp, u_int length, u_int caplen) { @@ -258,18 +306,21 @@ atmarp_print(netdissect_options *ndo, switch (op) { case ARPOP_REQUEST: - ND_PRINT((ndo, "who-has %s", ipaddr_string(ndo, ATMTPA(ap)))); + ND_PRINT((ndo, "who-has ")); + atmarp_tpaddr_print(ndo, ap, pro); if (ATMTHRD_LEN(ap) != 0) { ND_PRINT((ndo, " (")); atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), ATMTSLN(ap)); ND_PRINT((ndo, ")")); } - ND_PRINT((ndo, "tell %s", ipaddr_string(ndo, ATMSPA(ap)))); + ND_PRINT((ndo, " tell ")); + atmarp_spaddr_print(ndo, ap, pro); break; case ARPOP_REPLY: - ND_PRINT((ndo, "%s is-at ", ipaddr_string(ndo, ATMSPA(ap)))); + atmarp_spaddr_print(ndo, ap, pro); + ND_PRINT((ndo, " is-at ")); atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); break; @@ -286,11 +337,13 @@ atmarp_print(netdissect_options *ndo, case ARPOP_INVREPLY: atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); - ND_PRINT((ndo, "at %s", ipaddr_string(ndo, ATMSPA(ap)))); + ND_PRINT((ndo, "at ")); + atmarp_spaddr_print(ndo, ap, pro); break; case ARPOP_NAK: - ND_PRINT((ndo, "for %s", ipaddr_string(ndo, ATMSPA(ap)))); + ND_PRINT((ndo, "for ")); + atmarp_spaddr_print(ndo, ap, pro); break; default: @@ -338,7 +391,7 @@ arp_print(netdissect_options *ndo, break; } - if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) { + if (!ND_TTEST2(*TPA(ap), PROTO_LEN(ap))) { ND_PRINT((ndo, "%s", tstr)); ND_DEFAULTPRINT((const u_char *)ap, length); return; @@ -373,16 +426,18 @@ arp_print(netdissect_options *ndo, switch (op) { case ARPOP_REQUEST: - ND_PRINT((ndo, "who-has %s", ipaddr_string(ndo, TPA(ap)))); + ND_PRINT((ndo, "who-has ")); + tpaddr_print_ip(ndo, ap, pro); if (isnonzero((const u_char *)THA(ap), HRD_LEN(ap))) ND_PRINT((ndo, " (%s)", linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)))); - ND_PRINT((ndo, " tell %s", ipaddr_string(ndo, SPA(ap)))); + ND_PRINT((ndo, " tell ")); + spaddr_print_ip(ndo, ap, pro); break; case ARPOP_REPLY: - ND_PRINT((ndo, "%s is-at %s", - ipaddr_string(ndo, SPA(ap)), + spaddr_print_ip(ndo, ap, pro); + ND_PRINT((ndo, " is-at %s", linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap)))); break; @@ -393,9 +448,9 @@ arp_print(netdissect_options *ndo, break; case ARPOP_REVREPLY: - ND_PRINT((ndo, "%s at %s", - linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)), - ipaddr_string(ndo, TPA(ap)))); + ND_PRINT((ndo, "%s at ", + linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)))); + tpaddr_print_ip(ndo, ap, pro); break; case ARPOP_INVREQUEST: @@ -405,9 +460,9 @@ arp_print(netdissect_options *ndo, break; case ARPOP_INVREPLY: - ND_PRINT((ndo,"%s at %s", - linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap)), - ipaddr_string(ndo, SPA(ap)))); + ND_PRINT((ndo,"%s at ", + linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap)))); + spaddr_print_ip(ndo, ap, pro); break; default: diff --git a/freebsd/contrib/tcpdump/print-atm.c b/freebsd/contrib/tcpdump/print-atm.c index 1d1578f6..a846c83b 100644 --- a/freebsd/contrib/tcpdump/print-atm.c +++ b/freebsd/contrib/tcpdump/print-atm.c @@ -268,7 +268,7 @@ atm_if_print(netdissect_options *ndo, if (*p == LLC_UI) { if (ndo->ndo_eflag) ND_PRINT((ndo, "CNLPID ")); - isoclns_print(ndo, p + 1, length - 1, caplen - 1); + isoclns_print(ndo, p + 1, length - 1); return hdrlen; } diff --git a/freebsd/contrib/tcpdump/print-beep.c b/freebsd/contrib/tcpdump/print-beep.c index 9a95fbb7..e3a21f51 100644 --- a/freebsd/contrib/tcpdump/print-beep.c +++ b/freebsd/contrib/tcpdump/print-beep.c @@ -34,9 +34,17 @@ */ static int -l_strnstart(const char *tstr1, u_int tl1, const char *str2, u_int l2) +l_strnstart(netdissect_options *ndo, const char *tstr1, u_int tl1, + const char *str2, u_int l2) { - + if (!ND_TTEST2(*str2, tl1)) { + /* + * We don't have tl1 bytes worth of captured data + * for the string, so we can't check for this + * string. + */ + return 0; + } if (tl1 > l2) return 0; @@ -47,19 +55,19 @@ void beep_print(netdissect_options *ndo, const u_char *bp, u_int length) { - if (l_strnstart("MSG", 4, (const char *)bp, length)) /* A REQuest */ + if (l_strnstart(ndo, "MSG", 4, (const char *)bp, length)) /* A REQuest */ ND_PRINT((ndo, " BEEP MSG")); - else if (l_strnstart("RPY ", 4, (const char *)bp, length)) + else if (l_strnstart(ndo, "RPY ", 4, (const char *)bp, length)) ND_PRINT((ndo, " BEEP RPY")); - else if (l_strnstart("ERR ", 4, (const char *)bp, length)) + else if (l_strnstart(ndo, "ERR ", 4, (const char *)bp, length)) ND_PRINT((ndo, " BEEP ERR")); - else if (l_strnstart("ANS ", 4, (const char *)bp, length)) + else if (l_strnstart(ndo, "ANS ", 4, (const char *)bp, length)) ND_PRINT((ndo, " BEEP ANS")); - else if (l_strnstart("NUL ", 4, (const char *)bp, length)) + else if (l_strnstart(ndo, "NUL ", 4, (const char *)bp, length)) ND_PRINT((ndo, " BEEP NUL")); - else if (l_strnstart("SEQ ", 4, (const char *)bp, length)) + else if (l_strnstart(ndo, "SEQ ", 4, (const char *)bp, length)) ND_PRINT((ndo, " BEEP SEQ")); - else if (l_strnstart("END", 4, (const char *)bp, length)) + else if (l_strnstart(ndo, "END", 4, (const char *)bp, length)) ND_PRINT((ndo, " BEEP END")); else ND_PRINT((ndo, " BEEP (payload or undecoded)")); diff --git a/freebsd/contrib/tcpdump/print-bfd.c b/freebsd/contrib/tcpdump/print-bfd.c index 5eb8d174..bec521c1 100644 --- a/freebsd/contrib/tcpdump/print-bfd.c +++ b/freebsd/contrib/tcpdump/print-bfd.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: Bidirectional Forwarding Detection (BFD) printer */ diff --git a/freebsd/contrib/tcpdump/print-bgp.c b/freebsd/contrib/tcpdump/print-bgp.c index ae80d6b7..3d1e2f4d 100644 --- a/freebsd/contrib/tcpdump/print-bgp.c +++ b/freebsd/contrib/tcpdump/print-bgp.c @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Extensively modified by Hannes Gredler (hannes@juniper.net) for more + * Extensively modified by Hannes Gredler (hannes@gredler.at) for more * complete BGP support. */ @@ -762,11 +762,18 @@ decode_rt_routing_info(netdissect_options *ndo, { uint8_t route_target[8]; u_int plen; + char asbuf[sizeof(astostr)]; /* bgp_vpn_rd_print() overwrites astostr */ + /* NLRI "prefix length" from RFC 2858 Section 4. */ ND_TCHECK(pptr[0]); plen = pptr[0]; /* get prefix length */ + /* NLRI "prefix" (ibid), valid lengths are { 0, 32, 33, ..., 96 } bits. + * RFC 4684 Section 4 defines the layout of "origin AS" and "route + * target" fields inside the "prefix" depending on its length. + */ if (0 == plen) { + /* Without "origin AS", without "route target". */ snprintf(buf, buflen, "default route target"); return 1; } @@ -774,20 +781,29 @@ decode_rt_routing_info(netdissect_options *ndo, if (32 > plen) return -1; + /* With at least "origin AS", possibly with "route target". */ + ND_TCHECK_32BITS(pptr + 1); + as_printf(ndo, asbuf, sizeof(asbuf), EXTRACT_32BITS(pptr + 1)); + plen-=32; /* adjust prefix length */ if (64 < plen) return -1; + /* From now on (plen + 7) / 8 evaluates to { 0, 1, 2, ..., 8 } + * and gives the number of octets in the variable-length "route + * target" field inside this NLRI "prefix". Look for it. + */ memset(&route_target, 0, sizeof(route_target)); - ND_TCHECK2(pptr[1], (plen + 7) / 8); - memcpy(&route_target, &pptr[1], (plen + 7) / 8); + ND_TCHECK2(pptr[5], (plen + 7) / 8); + memcpy(&route_target, &pptr[5], (plen + 7) / 8); + /* Which specification says to do this? */ if (plen % 8) { ((u_char *)&route_target)[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } snprintf(buf, buflen, "origin AS: %s, route target %s", - as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr+1)), + asbuf, bgp_vpn_rd_print(ndo, (u_char *)&route_target)); return 5 + (plen + 7) / 8; @@ -901,6 +917,7 @@ static const struct tok bgp_multicast_vpn_route_type_values[] = { { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE, "Source-Active"}, { BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN, "Shared Tree Join"}, { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN, "Source Tree Join"}, + { 0, NULL} }; static int @@ -965,13 +982,13 @@ decode_multicast_vpn(netdissect_options *ndo, case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */ case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN: - ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN); + ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4); offset = strlen(buf); snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s", bgp_vpn_rd_print(ndo, pptr), as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN))); - pptr += BGP_VPN_RD_LEN; + pptr += BGP_VPN_RD_LEN + 4; bgp_vpn_sg_print(ndo, pptr, buf, buflen); break; @@ -1406,6 +1423,7 @@ bgp_attr_print(netdissect_options *ndo, ND_TCHECK(tptr[0]); ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_open_values, "?", tptr[0]))); + ND_TCHECK(tptr[1]); for (i = 0; i < tptr[1] * as_size; i += as_size) { ND_TCHECK2(tptr[2 + i], as_size); ND_PRINT((ndo, "%s ", @@ -1725,7 +1743,7 @@ bgp_attr_print(netdissect_options *ndo, ND_PRINT((ndo, ", no SNPA")); } - while (len - (tptr - pptr) > 0) { + while (tptr < pptr + len) { switch (af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): @@ -1893,7 +1911,7 @@ bgp_attr_print(netdissect_options *ndo, tptr += 3; - while (len - (tptr - pptr) > 0) { + while (tptr < pptr + len) { switch (af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): @@ -2122,11 +2140,11 @@ bgp_attr_print(netdissect_options *ndo, { uint8_t tunnel_type, flags; + ND_TCHECK2(tptr[0], 5); tunnel_type = *(tptr+1); flags = *tptr; tlen = len; - ND_TCHECK2(tptr[0], 5); ND_PRINT((ndo, "\n\t Tunnel-type %s (%u), Flags [%s], MPLS Label %u", tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type), tunnel_type, @@ -2181,35 +2199,42 @@ bgp_attr_print(netdissect_options *ndo, uint8_t type; uint16_t length; - ND_TCHECK2(tptr[0], 3); - tlen = len; while (tlen >= 3) { + ND_TCHECK2(tptr[0], 3); + type = *tptr; length = EXTRACT_16BITS(tptr+1); + tptr += 3; + tlen -= 3; ND_PRINT((ndo, "\n\t %s TLV (%u), length %u", tok2str(bgp_aigp_values, "Unknown", type), type, length)); + if (length < 3) + goto trunc; + length -= 3; + /* * Check if we can read the TLV data. */ - ND_TCHECK2(tptr[3], length - 3); + ND_TCHECK2(tptr[3], length); switch (type) { case BGP_AIGP_TLV: - ND_TCHECK2(tptr[3], 8); + if (length < 8) + goto trunc; ND_PRINT((ndo, ", metric %" PRIu64, - EXTRACT_64BITS(tptr+3))); + EXTRACT_64BITS(tptr))); break; default: if (ndo->ndo_vflag <= 1) { - print_unknown_data(ndo, tptr+3,"\n\t ", length-3); + print_unknown_data(ndo, tptr,"\n\t ", length); } } diff --git a/freebsd/contrib/tcpdump/print-bootp.c b/freebsd/contrib/tcpdump/print-bootp.c index 3f061769..c9f687ff 100644 --- a/freebsd/contrib/tcpdump/print-bootp.c +++ b/freebsd/contrib/tcpdump/print-bootp.c @@ -328,6 +328,7 @@ bootp_print(netdissect_options *ndo, if (EXTRACT_16BITS(&bp->bp_secs)) ND_PRINT((ndo, ", secs %d", EXTRACT_16BITS(&bp->bp_secs))); + ND_TCHECK(bp->bp_flags); ND_PRINT((ndo, ", Flags [%s]", bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags)))); if (ndo->ndo_vflag > 1) diff --git a/freebsd/contrib/tcpdump/print-cfm.c b/freebsd/contrib/tcpdump/print-cfm.c index ddb91e06..897dc032 100644 --- a/freebsd/contrib/tcpdump/print-cfm.c +++ b/freebsd/contrib/tcpdump/print-cfm.c @@ -18,7 +18,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: IEEE 802.1ag Connectivity Fault Management (CFM) protocols printer */ @@ -223,7 +223,7 @@ static const struct tok cfm_tlv_senderid_chassisid_values[] = { static int cfm_network_addr_print(netdissect_options *ndo, - register const u_char *tptr) + register const u_char *tptr, const u_int length) { u_int network_addr_type; u_int hexdump = FALSE; @@ -233,6 +233,11 @@ cfm_network_addr_print(netdissect_options *ndo, * 802.1ab specifies that this field width * is only once octet */ + if (length < 1) { + ND_PRINT((ndo, "\n\t Network Address Type (invalid, no data")); + return hexdump; + } + /* The calling function must make any due ND_TCHECK calls. */ network_addr_type = *tptr; ND_PRINT((ndo, "\n\t Network Address Type %s (%u)", tok2str(af_values, "Unknown", network_addr_type), @@ -243,10 +248,20 @@ cfm_network_addr_print(netdissect_options *ndo, */ switch(network_addr_type) { case AFNUM_INET: + if (length != 1 + 4) { + ND_PRINT((ndo, "(invalid IPv4 address length %u)", length - 1)); + hexdump = TRUE; + break; + } ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr + 1))); break; case AFNUM_INET6: + if (length != 1 + 16) { + ND_PRINT((ndo, "(invalid IPv6 address length %u)", length - 1)); + hexdump = TRUE; + break; + } ND_PRINT((ndo, ", %s", ip6addr_string(ndo, tptr + 1))); break; @@ -374,8 +389,11 @@ cfm_print(netdissect_options *ndo, md_nameformat, md_namelength)); - /* -2 for the MA short name format and length */ - if (md_namelength > names_data_remaining - 2) { + /* + * -3 for the MA short name format and length and one byte + * of MA short name. + */ + if (md_namelength > names_data_remaining - 3) { ND_PRINT((ndo, " (too large, must be <= %u)", names_data_remaining - 2)); return; } @@ -587,11 +605,12 @@ cfm_print(netdissect_options *ndo, if (cfm_tlv_len < 1) { ND_PRINT((ndo, " (too short, must be >= 1)")); - return; + goto next_tlv; } /* * Get the Chassis ID length and check it. + * IEEE 802.1Q-2014 Section 21.5.3.1 */ chassis_id_length = *tptr; tptr++; @@ -599,9 +618,14 @@ cfm_print(netdissect_options *ndo, cfm_tlv_len--; if (chassis_id_length) { + /* + * IEEE 802.1Q-2014 Section 21.5.3.2: Chassis ID Subtype, references + * IEEE 802.1AB-2005 Section 9.5.2.2, subsequently + * IEEE 802.1AB-2016 Section 8.5.2.2: chassis ID subtype + */ if (cfm_tlv_len < 1) { ND_PRINT((ndo, "\n\t (TLV too short)")); - return; + goto next_tlv; } chassis_id_type = *tptr; cfm_tlv_len--; @@ -614,16 +638,22 @@ cfm_print(netdissect_options *ndo, if (cfm_tlv_len < chassis_id_length) { ND_PRINT((ndo, "\n\t (TLV too short)")); - return; + goto next_tlv; } + /* IEEE 802.1Q-2014 Section 21.5.3.3: Chassis ID */ switch (chassis_id_type) { case CFM_CHASSIS_ID_MAC_ADDRESS: + if (chassis_id_length != ETHER_ADDR_LEN) { + ND_PRINT((ndo, " (invalid MAC address length)")); + hexdump = TRUE; + break; + } ND_PRINT((ndo, "\n\t MAC %s", etheraddr_string(ndo, tptr + 1))); break; case CFM_CHASSIS_ID_NETWORK_ADDRESS: - hexdump |= cfm_network_addr_print(ndo, tptr); + hexdump |= cfm_network_addr_print(ndo, tptr + 1, chassis_id_length); break; case CFM_CHASSIS_ID_INTERFACE_NAME: /* fall through */ @@ -646,38 +676,53 @@ cfm_print(netdissect_options *ndo, /* * Check if there is a Management Address. + * IEEE 802.1Q-2014 Section 21.5.3.4: Management Address Domain Length + * This and all subsequent fields are not present if the TLV length + * allows only the above fields. */ if (cfm_tlv_len == 0) { /* No, there isn't; we're done. */ - return; + break; } + /* Here mgmt_addr_length stands for the management domain length. */ mgmt_addr_length = *tptr; tptr++; tlen--; cfm_tlv_len--; + ND_PRINT((ndo, "\n\t Management Address Domain Length %u", mgmt_addr_length)); if (mgmt_addr_length) { + /* IEEE 802.1Q-2014 Section 21.5.3.5: Management Address Domain */ if (cfm_tlv_len < mgmt_addr_length) { ND_PRINT((ndo, "\n\t (TLV too short)")); - return; + goto next_tlv; } cfm_tlv_len -= mgmt_addr_length; /* * XXX - this is an OID; print it as such. */ + hex_print(ndo, "\n\t Management Address Domain: ", tptr, mgmt_addr_length); tptr += mgmt_addr_length; tlen -= mgmt_addr_length; + /* + * IEEE 802.1Q-2014 Section 21.5.3.6: Management Address Length + * This field is present if Management Address Domain Length is not 0. + */ if (cfm_tlv_len < 1) { - ND_PRINT((ndo, "\n\t (TLV too short)")); - return; + ND_PRINT((ndo, " (Management Address Length is missing)")); + hexdump = TRUE; + break; } - + + /* Here mgmt_addr_length stands for the management address length. */ mgmt_addr_length = *tptr; tptr++; tlen--; cfm_tlv_len--; + ND_PRINT((ndo, "\n\t Management Address Length %u", mgmt_addr_length)); if (mgmt_addr_length) { + /* IEEE 802.1Q-2014 Section 21.5.3.7: Management Address */ if (cfm_tlv_len < mgmt_addr_length) { ND_PRINT((ndo, "\n\t (TLV too short)")); return; @@ -686,6 +731,7 @@ cfm_print(netdissect_options *ndo, /* * XXX - this is a TransportDomain; print it as such. */ + hex_print(ndo, "\n\t Management Address: ", tptr, mgmt_addr_length); tptr += mgmt_addr_length; tlen -= mgmt_addr_length; } @@ -709,6 +755,7 @@ cfm_print(netdissect_options *ndo, if (hexdump || ndo->ndo_vflag > 1) print_unknown_data(ndo, tlv_ptr, "\n\t ", cfm_tlv_len); +next_tlv: tptr+=cfm_tlv_len; tlen-=cfm_tlv_len; } diff --git a/freebsd/contrib/tcpdump/print-chdlc.c b/freebsd/contrib/tcpdump/print-chdlc.c index 5ccb849f..03ae73f6 100644 --- a/freebsd/contrib/tcpdump/print-chdlc.c +++ b/freebsd/contrib/tcpdump/print-chdlc.c @@ -52,21 +52,18 @@ static const struct tok chdlc_cast_values[] = { u_int chdlc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { - register u_int length = h->len; - register u_int caplen = h->caplen; - - if (caplen < CHDLC_HDRLEN) { - ND_PRINT((ndo, "[|chdlc]")); - return (caplen); - } - return (chdlc_print(ndo, p,length)); + return chdlc_print(ndo, p, h->len); } u_int chdlc_print(netdissect_options *ndo, register const u_char *p, u_int length) { u_int proto; + const u_char *bp = p; + if (length < CHDLC_HDRLEN) + goto trunc; + ND_TCHECK2(*p, CHDLC_HDRLEN); proto = EXTRACT_16BITS(&p[2]); if (ndo->ndo_eflag) { ND_PRINT((ndo, "%s, ethertype %s (0x%04x), length %u: ", @@ -100,12 +97,15 @@ chdlc_print(netdissect_options *ndo, register const u_char *p, u_int length) break; case ETHERTYPE_ISO: /* is the fudge byte set ? lets verify by spotting ISO headers */ + if (length < 2) + goto trunc; + ND_TCHECK_16BITS(p); if (*(p+1) == 0x81 || *(p+1) == 0x82 || *(p+1) == 0x83) - isoclns_print(ndo, p + 1, length - 1, ndo->ndo_snapend - p - 1); + isoclns_print(ndo, p + 1, length - 1); else - isoclns_print(ndo, p, length, ndo->ndo_snapend - p); + isoclns_print(ndo, p, length); break; default: if (!ndo->ndo_eflag) @@ -114,6 +114,10 @@ chdlc_print(netdissect_options *ndo, register const u_char *p, u_int length) } return (CHDLC_HDRLEN); + +trunc: + ND_PRINT((ndo, "[|chdlc]")); + return ndo->ndo_snapend - bp; } /* diff --git a/freebsd/contrib/tcpdump/print-cnfp.c b/freebsd/contrib/tcpdump/print-cnfp.c index b590afae..9e946f6e 100644 --- a/freebsd/contrib/tcpdump/print-cnfp.c +++ b/freebsd/contrib/tcpdump/print-cnfp.c @@ -165,7 +165,7 @@ cnfp_v1_print(netdissect_options *ndo, const u_char *cp) { register const struct nfhdr_v1 *nh; register const struct nfrec_v1 *nr; - struct protoent *pent; + const char *p_name; int nrecs, ver; #if 0 time_t t; @@ -217,14 +217,13 @@ cnfp_v1_print(netdissect_options *ndo, const u_char *cp) ND_PRINT((ndo, ">> %s\n ", intoa(nr->nhop_ina.s_addr))); - pent = getprotobynumber(nr->proto); - if (!pent || ndo->ndo_nflag) - ND_PRINT((ndo, "%u ", nr->proto)); + if (!ndo->ndo_nflag && (p_name = netdb_protoname(nr->proto)) != NULL) + ND_PRINT((ndo, "%s ", p_name)); else - ND_PRINT((ndo, "%s ", pent->p_name)); + ND_PRINT((ndo, "%u ", nr->proto)); /* tcp flags for tcp only */ - if (pent && pent->p_proto == IPPROTO_TCP) { + if (nr->proto == IPPROTO_TCP) { int flags; flags = nr->tcp_flags; ND_PRINT((ndo, "%s%s%s%s%s%s%s", @@ -255,7 +254,7 @@ cnfp_v5_print(netdissect_options *ndo, const u_char *cp) { register const struct nfhdr_v5 *nh; register const struct nfrec_v5 *nr; - struct protoent *pent; + const char *p_name; int nrecs, ver; #if 0 time_t t; @@ -314,14 +313,13 @@ cnfp_v5_print(netdissect_options *ndo, const u_char *cp) ND_PRINT((ndo, ">> %s\n ", intoa(nr->nhop_ina.s_addr))); - pent = getprotobynumber(nr->proto); - if (!pent || ndo->ndo_nflag) - ND_PRINT((ndo, "%u ", nr->proto)); + if (!ndo->ndo_nflag && (p_name = netdb_protoname(nr->proto)) != NULL) + ND_PRINT((ndo, "%s ", p_name)); else - ND_PRINT((ndo, "%s ", pent->p_name)); + ND_PRINT((ndo, "%u ", nr->proto)); /* tcp flags for tcp only */ - if (pent && pent->p_proto == IPPROTO_TCP) { + if (nr->proto == IPPROTO_TCP) { int flags; flags = nr->tcp_flags; ND_PRINT((ndo, "%s%s%s%s%s%s%s", @@ -352,7 +350,7 @@ cnfp_v6_print(netdissect_options *ndo, const u_char *cp) { register const struct nfhdr_v6 *nh; register const struct nfrec_v6 *nr; - struct protoent *pent; + const char *p_name; int nrecs, ver; #if 0 time_t t; @@ -411,14 +409,13 @@ cnfp_v6_print(netdissect_options *ndo, const u_char *cp) ND_PRINT((ndo, ">> %s\n ", intoa(nr->nhop_ina.s_addr))); - pent = getprotobynumber(nr->proto); - if (!pent || ndo->ndo_nflag) - ND_PRINT((ndo, "%u ", nr->proto)); + if (!ndo->ndo_nflag && (p_name = netdb_protoname(nr->proto)) != NULL) + ND_PRINT((ndo, "%s ", p_name)); else - ND_PRINT((ndo, "%s ", pent->p_name)); + ND_PRINT((ndo, "%u ", nr->proto)); /* tcp flags for tcp only */ - if (pent && pent->p_proto == IPPROTO_TCP) { + if (nr->proto == IPPROTO_TCP) { int flags; flags = nr->tcp_flags; ND_PRINT((ndo, "%s%s%s%s%s%s%s", diff --git a/freebsd/contrib/tcpdump/print-decnet.c b/freebsd/contrib/tcpdump/print-decnet.c index 4d052626..af50492b 100644 --- a/freebsd/contrib/tcpdump/print-decnet.c +++ b/freebsd/contrib/tcpdump/print-decnet.c @@ -548,6 +548,7 @@ decnet_print(netdissect_options *ndo, length -= padlen; caplen -= padlen; rhp = (const union routehdr *)&(ap[sizeof(short)]); + ND_TCHECK(rhp->rh_short.sh_flags); mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); } @@ -619,6 +620,7 @@ print_decnet_ctlmsg(netdissect_options *ndo, register const union routehdr *rhp, u_int length, u_int caplen) { + /* Our caller has already checked for mflags */ int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); register const union controlmsg *cmp = (const union controlmsg *)rhp; int src, dst, info, blksize, eco, ueco, hello, other, vers; diff --git a/freebsd/contrib/tcpdump/print-dhcp6.c b/freebsd/contrib/tcpdump/print-dhcp6.c index 8c7a0974..9815a167 100644 --- a/freebsd/contrib/tcpdump/print-dhcp6.c +++ b/freebsd/contrib/tcpdump/print-dhcp6.c @@ -524,6 +524,10 @@ dhcp6opt_print(netdissect_options *ndo, ND_PRINT((ndo, "...)")); break; case DH6OPT_RECONF_MSG: + if (optlen != 1) { + ND_PRINT((ndo, " ?)")); + break; + } tp = (const u_char *)(dh6o + 1); switch (*tp) { case DH6_RENEW: diff --git a/freebsd/contrib/tcpdump/print-domain.c b/freebsd/contrib/tcpdump/print-domain.c index 904468c4..52348a17 100644 --- a/freebsd/contrib/tcpdump/print-domain.c +++ b/freebsd/contrib/tcpdump/print-domain.c @@ -157,15 +157,14 @@ ns_nprint(netdissect_options *ndo, register u_int i, l; register const u_char *rp = NULL; register int compress = 0; - int chars_processed; int elt; - int data_size = ndo->ndo_snapend - bp; + u_int offset, max_offset; if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); if (!ND_TTEST2(*cp, 1)) return(NULL); - chars_processed = 1; + max_offset = (u_int)(cp - bp); if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) { compress = 0; rp = cp + l; @@ -180,24 +179,28 @@ ns_nprint(netdissect_options *ndo, } if (!ND_TTEST2(*cp, 1)) return(NULL); - cp = bp + (((i << 8) | *cp) & 0x3fff); + offset = (((i << 8) | *cp) & 0x3fff); + /* + * This must move backwards in the packet. + * No RFC explicitly says that, but BIND's + * name decompression code requires it, + * as a way of preventing infinite loops + * and other bad behavior, and it's probably + * what was intended (compress by pointing + * to domain name suffixes already seen in + * the packet). + */ + if (offset >= max_offset) { + ND_PRINT((ndo, "<BAD PTR>")); + return(NULL); + } + max_offset = offset; + cp = bp + offset; if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); if (!ND_TTEST2(*cp, 1)) return(NULL); i = *cp++; - chars_processed++; - - /* - * If we've looked at every character in - * the message, this pointer will make - * us look at some character again, - * which means we're looping. - */ - if (chars_processed >= data_size) { - ND_PRINT((ndo, "<LOOP>")); - return (NULL); - } continue; } if ((i & INDIR_MASK) == EDNS0_MASK) { @@ -218,14 +221,12 @@ ns_nprint(netdissect_options *ndo, } cp += l; - chars_processed += l; ND_PRINT((ndo, ".")); if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); if (!ND_TTEST2(*cp, 1)) return(NULL); i = *cp++; - chars_processed++; if (!compress) rp += l + 1; } diff --git a/freebsd/contrib/tcpdump/print-eap.c b/freebsd/contrib/tcpdump/print-eap.c index 78fbef43..1de61b79 100644 --- a/freebsd/contrib/tcpdump/print-eap.c +++ b/freebsd/contrib/tcpdump/print-eap.c @@ -188,7 +188,9 @@ eap_print(netdissect_options *ndo, switch (eap->type) { case EAP_FRAME_TYPE_PACKET: + ND_TCHECK_8BITS(tptr); type = *(tptr); + ND_TCHECK_16BITS(tptr+2); len = EXTRACT_16BITS(tptr+2); ND_PRINT((ndo, ", %s (%u), id %u, len %u", tok2str(eap_code_values, "unknown", type), @@ -199,10 +201,11 @@ eap_print(netdissect_options *ndo, ND_TCHECK2(*tptr, len); if (type <= 2) { /* For EAP_REQUEST and EAP_RESPONSE only */ + ND_TCHECK_8BITS(tptr+4); subtype = *(tptr+4); ND_PRINT((ndo, "\n\t\t Type %s (%u)", - tok2str(eap_type_values, "unknown", *(tptr+4)), - *(tptr + 4))); + tok2str(eap_type_values, "unknown", subtype), + subtype)); switch (subtype) { case EAP_TYPE_IDENTITY: @@ -228,6 +231,7 @@ eap_print(netdissect_options *ndo, * type one octet per type */ while (count < len) { + ND_TCHECK_8BITS(tptr+count); ND_PRINT((ndo, " %s (%u),", tok2str(eap_type_values, "unknown", *(tptr+count)), *(tptr + count))); @@ -236,19 +240,23 @@ eap_print(netdissect_options *ndo, break; case EAP_TYPE_TTLS: - ND_PRINT((ndo, " TTLSv%u", - EAP_TTLS_VERSION(*(tptr + 5)))); /* fall through */ case EAP_TYPE_TLS: + ND_TCHECK_8BITS(tptr + 5); + if (subtype == EAP_TYPE_TTLS) + ND_PRINT((ndo, " TTLSv%u", + EAP_TTLS_VERSION(*(tptr + 5)))); ND_PRINT((ndo, " flags [%s] 0x%02x,", bittok2str(eap_tls_flags_values, "none", *(tptr+5)), *(tptr + 5))); if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) { + ND_TCHECK_32BITS(tptr + 6); ND_PRINT((ndo, " len %u", EXTRACT_32BITS(tptr + 6))); } break; case EAP_TYPE_FAST: + ND_TCHECK_8BITS(tptr + 5); ND_PRINT((ndo, " FASTv%u", EAP_TTLS_VERSION(*(tptr + 5)))); ND_PRINT((ndo, " flags [%s] 0x%02x,", @@ -256,6 +264,7 @@ eap_print(netdissect_options *ndo, *(tptr + 5))); if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) { + ND_TCHECK_32BITS(tptr + 6); ND_PRINT((ndo, " len %u", EXTRACT_32BITS(tptr + 6))); } @@ -264,6 +273,7 @@ eap_print(netdissect_options *ndo, case EAP_TYPE_AKA: case EAP_TYPE_SIM: + ND_TCHECK_8BITS(tptr + 5); ND_PRINT((ndo, " subtype [%s] 0x%02x,", tok2str(eap_aka_subtype_values, "unknown", *(tptr+5)), *(tptr + 5))); diff --git a/freebsd/contrib/tcpdump/print-eigrp.c b/freebsd/contrib/tcpdump/print-eigrp.c index 14a14b8f..2b1ea588 100644 --- a/freebsd/contrib/tcpdump/print-eigrp.c +++ b/freebsd/contrib/tcpdump/print-eigrp.c @@ -5,7 +5,7 @@ #include "rtems-bsd-tcpdump-namespace.h" #endif /* __rtems__ */ /* - * Copyright (c) 1998-2004 Hannes Gredler <hannes@tcpdump.org> + * Copyright (c) 1998-2004 Hannes Gredler <hannes@gredler.at> * The TCPDUMP project * * Redistribution and use in source and binary forms, with or without @@ -37,6 +37,7 @@ /* * packet format documented at * http://www.rhyshaden.com/eigrp.htm + * RFC 7868 */ struct eigrp_common_header { @@ -252,6 +253,12 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int /* ok they seem to want to know everything - lets fully decode it */ + if (len < sizeof(struct eigrp_common_header)) { + ND_PRINT((ndo, "EIGRP %s, length: %u (too short, < %u)", + tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode), + len, (u_int) sizeof(struct eigrp_common_header))); + return; + } tlen=len-sizeof(struct eigrp_common_header); /* FIXME print other header info */ @@ -292,6 +299,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int eigrp_tlv_type, eigrp_tlv_len)); + if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) { + ND_PRINT((ndo, " (too short, < %u)", + (u_int) sizeof(struct eigrp_tlv_header))); + break; + } tlv_tptr=tptr+sizeof(struct eigrp_tlv_header); tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header); @@ -302,6 +314,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int case EIGRP_TLV_GENERAL_PARM: tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr; + if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) { + ND_PRINT((ndo, " (too short, < %u)", + (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm)))); + break; + } ND_PRINT((ndo, "\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u", EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime), @@ -314,6 +331,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int case EIGRP_TLV_SW_VERSION: tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr; + if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) { + ND_PRINT((ndo, " (too short, < %u)", + (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version)))); + break; + } ND_PRINT((ndo, "\n\t IOS version: %u.%u, EIGRP version %u.%u", tlv_ptr.eigrp_tlv_sw_version->ios_major, @@ -324,6 +346,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int case EIGRP_TLV_IP_INT: tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr; + if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) { + ND_PRINT((ndo, " (too short, < %u)", + (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int)))); + break; + } bit_length = tlv_ptr.eigrp_tlv_ip_int->plen; if (bit_length > 32) { @@ -353,6 +380,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int case EIGRP_TLV_IP_EXT: tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr; + if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) { + ND_PRINT((ndo, " (too short, < %u)", + (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext)))); + break; + } bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen; if (bit_length > 32) { @@ -390,6 +422,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int case EIGRP_TLV_AT_CABLE_SETUP: tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr; + if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) { + ND_PRINT((ndo, " (too short, < %u)", + (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)))); + break; + } ND_PRINT((ndo, "\n\t Cable-range: %u-%u, Router-ID %u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start), @@ -399,6 +436,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int case EIGRP_TLV_AT_INT: tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr; + if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) { + ND_PRINT((ndo, " (too short, < %u)", + (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int)))); + break; + } ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start), @@ -422,6 +464,11 @@ eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int case EIGRP_TLV_AT_EXT: tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr; + if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) { + ND_PRINT((ndo, " (too short, < %u)", + (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext)))); + break; + } ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start), diff --git a/freebsd/contrib/tcpdump/print-esp.c b/freebsd/contrib/tcpdump/print-esp.c index bab7cb52..c92d6fbe 100644 --- a/freebsd/contrib/tcpdump/print-esp.c +++ b/freebsd/contrib/tcpdump/print-esp.c @@ -151,6 +151,39 @@ EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) } #endif +#ifdef HAVE_EVP_CIPHERINIT_EX +/* + * Initialize the cipher by calling EVP_CipherInit_ex(), because + * calling EVP_CipherInit() will reset the cipher context, clearing + * the cipher, so calling it twice, with the second call having a + * null cipher, will clear the already-set cipher. EVP_CipherInit_ex(), + * however, won't reset the cipher context, so you can use it to specify + * the IV oin a second call after a first call to EVP_CipherInit_ex() + * to set the cipher and the key. + * + * XXX - is there some reason why we need to make two calls? + */ +static int +set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, + const unsigned char *iv, int enc) +{ + return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc); +} +#else +/* + * Initialize the cipher by calling EVP_CipherInit(), because we don't + * have EVP_CipherInit_ex(); we rely on it not trashing the context. + */ +static int +set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, + const unsigned char *iv, int enc) +{ + return EVP_CipherInit(ctx, cipher, key, iv, enc); +} +#endif + /* * this will adjust ndo_packetp and ndo_snapend to new buffer! */ @@ -162,8 +195,10 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo, { struct sa_list *sa; const u_char *iv; - int len; + unsigned int len; EVP_CIPHER_CTX *ctx; + unsigned int block_size, output_buffer_size; + u_char *output_buffer; /* initiator arg is any non-zero value */ if(initiator) initiator=1; @@ -194,17 +229,36 @@ int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo, ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) return 0; - if (EVP_CipherInit(ctx, sa->evp, sa->secret, NULL, 0) < 0) + if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL, 0) < 0) (*ndo->ndo_warning)(ndo, "espkey init failed"); - EVP_CipherInit(ctx, NULL, NULL, iv, 0); - EVP_Cipher(ctx, __DECONST(u_char *, buf), buf, len); + set_cipher_parameters(ctx, NULL, NULL, iv, 0); + /* + * Allocate a buffer for the decrypted data. + * The output buffer must be separate from the input buffer, and + * its size must be a multiple of the cipher block size. + */ + block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx); + output_buffer_size = len + (block_size - len % block_size); + output_buffer = (u_char *)malloc(output_buffer_size); + if (output_buffer == NULL) { + (*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer"); + EVP_CIPHER_CTX_free(ctx); + return 0; + } + EVP_Cipher(ctx, output_buffer, buf, len); EVP_CIPHER_CTX_free(ctx); + /* + * XXX - of course this is wrong, because buf is a const buffer, + * but changing this would require a more complicated fix. + */ + memcpy(__DECONST(u_char *, buf), output_buffer, len); + free(output_buffer); + ndo->ndo_packetp = buf; ndo->ndo_snapend = end; return 1; - } USES_APPLE_RST @@ -612,6 +666,8 @@ esp_print(netdissect_options *ndo, const u_char *ivoff; const u_char *p; EVP_CIPHER_CTX *ctx; + unsigned int block_size, output_buffer_size; + u_char *output_buffer; #endif esp = (const struct newesp *)bp; @@ -709,7 +765,9 @@ esp_print(netdissect_options *ndo, ep = bp2 + len; } + /* pointer to the IV, if there is one */ ivoff = (const u_char *)(esp + 1) + 0; + /* length of the IV, if there is one; 0, if there isn't */ ivlen = sa->ivlen; secret = sa->secret; ep = ep - sa->authlen; @@ -717,14 +775,37 @@ esp_print(netdissect_options *ndo, if (sa->evp) { ctx = EVP_CIPHER_CTX_new(); if (ctx != NULL) { - if (EVP_CipherInit(ctx, sa->evp, secret, NULL, 0) < 0) + if (set_cipher_parameters(ctx, sa->evp, secret, NULL, 0) < 0) (*ndo->ndo_warning)(ndo, "espkey init failed"); p = ivoff; - EVP_CipherInit(ctx, NULL, NULL, p, 0); - EVP_Cipher(ctx, __DECONST(u_char *, p + ivlen), - p + ivlen, ep - (p + ivlen)); + set_cipher_parameters(ctx, NULL, NULL, p, 0); + len = ep - (p + ivlen); + + /* + * Allocate a buffer for the decrypted data. + * The output buffer must be separate from the + * input buffer, and its size must be a multiple + * of the cipher block size. + */ + block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx); + output_buffer_size = len + (block_size - len % block_size); + output_buffer = (u_char *)malloc(output_buffer_size); + if (output_buffer == NULL) { + (*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer"); + EVP_CIPHER_CTX_free(ctx); + return -1; + } + + EVP_Cipher(ctx, output_buffer, p + ivlen, len); EVP_CIPHER_CTX_free(ctx); + /* + * XXX - of course this is wrong, because buf is a + * const buffer, but changing this would require a + * more complicated fix. + */ + memcpy(__DECONST(u_char *, p + ivlen), output_buffer, len); + free(output_buffer); advance = ivoff - (const u_char *)esp + ivlen; } else advance = sizeof(struct newesp); diff --git a/freebsd/contrib/tcpdump/print-ether.c b/freebsd/contrib/tcpdump/print-ether.c index 2a72830c..cf996cd3 100644 --- a/freebsd/contrib/tcpdump/print-ether.c +++ b/freebsd/contrib/tcpdump/print-ether.c @@ -372,7 +372,7 @@ ethertype_print(netdissect_options *ndo, ND_PRINT((ndo, " [|osi]")); return (1); } - isoclns_print(ndo, p + 1, length - 1, caplen - 1); + isoclns_print(ndo, p + 1, length - 1); return(1); case ETHERTYPE_PPPOED: diff --git a/freebsd/contrib/tcpdump/print-fr.c b/freebsd/contrib/tcpdump/print-fr.c index 11457ab0..25e0219a 100644 --- a/freebsd/contrib/tcpdump/print-fr.c +++ b/freebsd/contrib/tcpdump/print-fr.c @@ -335,7 +335,7 @@ fr_print(netdissect_options *ndo, case NLPID_CLNP: case NLPID_ESIS: case NLPID_ISIS: - isoclns_print(ndo, p - 1, length + 1, ndo->ndo_snapend - p + 1); /* OSI printers need the NLPID field */ + isoclns_print(ndo, p - 1, length + 1); /* OSI printers need the NLPID field */ break; case NLPID_SNAP: diff --git a/freebsd/contrib/tcpdump/print-frag6.c b/freebsd/contrib/tcpdump/print-frag6.c index 11f97ad2..fb364c4d 100644 --- a/freebsd/contrib/tcpdump/print-frag6.c +++ b/freebsd/contrib/tcpdump/print-frag6.c @@ -33,10 +33,11 @@ #include <netdissect-stdinc.h> -#include "ip6.h" #include "netdissect.h" #include "extract.h" +#include "ip6.h" + int frag6_print(netdissect_options *ndo, register const u_char *bp, register const u_char *bp2) { @@ -46,7 +47,7 @@ frag6_print(netdissect_options *ndo, register const u_char *bp, register const u dp = (const struct ip6_frag *)bp; ip6 = (const struct ip6_hdr *)bp2; - ND_TCHECK(dp->ip6f_offlg); + ND_TCHECK(*dp); if (ndo->ndo_vflag) { ND_PRINT((ndo, "frag (0x%08x:%d|%ld)", diff --git a/freebsd/contrib/tcpdump/print-gre.c b/freebsd/contrib/tcpdump/print-gre.c index 2a13d435..04ad5d2a 100644 --- a/freebsd/contrib/tcpdump/print-gre.c +++ b/freebsd/contrib/tcpdump/print-gre.c @@ -232,7 +232,7 @@ gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length) atalk_print(ndo, bp, len); break; case ETHERTYPE_GRE_ISO: - isoclns_print(ndo, bp, len, ndo->ndo_snapend - bp); + isoclns_print(ndo, bp, len); break; case ETHERTYPE_TEB: ether_print(ndo, bp, len, ndo->ndo_snapend - bp, NULL, NULL); diff --git a/freebsd/contrib/tcpdump/print-hncp.c b/freebsd/contrib/tcpdump/print-hncp.c index 83ee2fd9..34297772 100644 --- a/freebsd/contrib/tcpdump/print-hncp.c +++ b/freebsd/contrib/tcpdump/print-hncp.c @@ -276,6 +276,8 @@ dhcpv4_print(netdissect_options *ndo, i = 0; while (i < length) { + if (i + 2 > length) + return -1; tlv = cp + i; type = (uint8_t)tlv[0]; optlen = (uint8_t)tlv[1]; @@ -287,6 +289,8 @@ dhcpv4_print(netdissect_options *ndo, ND_PRINT((ndo, "%s", tok2str(dh4opt_str, "Unknown", type))); ND_PRINT((ndo," (%u)", optlen + 2 )); + if (i + 2 + optlen > length) + return -1; switch (type) { case DH4OPT_DNS_SERVERS: @@ -324,6 +328,8 @@ dhcpv6_print(netdissect_options *ndo, i = 0; while (i < length) { + if (i + 4 > length) + return -1; tlv = cp + i; type = EXTRACT_16BITS(tlv); optlen = EXTRACT_16BITS(tlv + 2); @@ -335,6 +341,8 @@ dhcpv6_print(netdissect_options *ndo, ND_PRINT((ndo, "%s", tok2str(dh6opt_str, "Unknown", type))); ND_PRINT((ndo," (%u)", optlen + 4 )); + if (i + 4 + optlen > length) + return -1; switch (type) { case DH6OPT_DNS_SERVERS: diff --git a/freebsd/contrib/tcpdump/print-icmp.c b/freebsd/contrib/tcpdump/print-icmp.c index fc4906eb..ce22ce81 100644 --- a/freebsd/contrib/tcpdump/print-icmp.c +++ b/freebsd/contrib/tcpdump/print-icmp.c @@ -588,6 +588,7 @@ icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen, const u_char * ip = (const struct ip *)bp; ndo->ndo_snaplen = ndo->ndo_snapend - bp; snapend_save = ndo->ndo_snapend; + ND_TCHECK_16BITS(&ip->ip_len); ip_print(ndo, bp, EXTRACT_16BITS(&ip->ip_len)); ndo->ndo_snapend = snapend_save; } @@ -605,7 +606,8 @@ icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen, const u_char * * to check if an extension header is present. This is expedient, * however not all implementations set the length field proper. */ - if (!ext_dp->icmp_length) { + if (!ext_dp->icmp_length && + ND_TTEST2(ext_dp->icmp_ext_version_res, plen - ICMP_EXTD_MINLEN)) { vec[0].ptr = (const uint8_t *)(const void *)&ext_dp->icmp_ext_version_res; vec[0].len = plen - ICMP_EXTD_MINLEN; if (in_cksum(vec, 1)) { @@ -626,12 +628,14 @@ icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen, const u_char * } hlen = plen - ICMP_EXTD_MINLEN; - vec[0].ptr = (const uint8_t *)(const void *)&ext_dp->icmp_ext_version_res; - vec[0].len = hlen; - ND_PRINT((ndo, ", checksum 0x%04x (%scorrect), length %u", - EXTRACT_16BITS(ext_dp->icmp_ext_checksum), - in_cksum(vec, 1) ? "in" : "", - hlen)); + if (ND_TTEST2(ext_dp->icmp_ext_version_res, hlen)) { + vec[0].ptr = (const uint8_t *)(const void *)&ext_dp->icmp_ext_version_res; + vec[0].len = hlen; + ND_PRINT((ndo, ", checksum 0x%04x (%scorrect), length %u", + EXTRACT_16BITS(ext_dp->icmp_ext_checksum), + in_cksum(vec, 1) ? "in" : "", + hlen)); + } hlen -= 4; /* subtract common header size */ obj_tptr = (const uint8_t *)ext_dp->icmp_ext_data; diff --git a/freebsd/contrib/tcpdump/print-icmp6.c b/freebsd/contrib/tcpdump/print-icmp6.c index 2e6756cf..e2d44dfb 100644 --- a/freebsd/contrib/tcpdump/print-icmp6.c +++ b/freebsd/contrib/tcpdump/print-icmp6.c @@ -1137,6 +1137,7 @@ icmp6_print(netdissect_options *ndo, if (ndo->ndo_vflag) { ND_TCHECK(dp->icmp6_data16[0]); ND_PRINT((ndo,", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]))); + ND_TCHECK(dp->icmp6_data16[1]); if (dp->icmp6_data16[1] & 0xc0) ND_PRINT((ndo," ")); if (dp->icmp6_data16[1] & 0x80) @@ -1704,6 +1705,7 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, needcomma = 0; + ND_TCHECK2(*dp, sizeof(*ni6)); ni6 = (const struct icmp6_nodeinfo *)dp; ND_PRINT((ndo," node information reply")); ND_PRINT((ndo," (")); /*)*/ @@ -1758,6 +1760,7 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, ND_PRINT((ndo,", ")); ND_PRINT((ndo,"DNS name")); cp = (const u_char *)(ni6 + 1) + 4; + ND_TCHECK(cp[0]); if (cp[0] == ep - cp - 1) { /* icmp-name-lookup-03, pascal string */ if (ndo->ndo_vflag) diff --git a/freebsd/contrib/tcpdump/print-ip.c b/freebsd/contrib/tcpdump/print-ip.c index 6aa5692e..677ed942 100644 --- a/freebsd/contrib/tcpdump/print-ip.c +++ b/freebsd/contrib/tcpdump/print-ip.c @@ -60,7 +60,7 @@ static const struct tok ip_option_values[] = { /* * print the recorded route in an IP RR, LSRR or SSRR option. */ -static void +static int ip_printroute(netdissect_options *ndo, register const u_char *cp, u_int length) { @@ -69,19 +69,25 @@ ip_printroute(netdissect_options *ndo, if (length < 3) { ND_PRINT((ndo, " [bad length %u]", length)); - return; + return (0); } if ((length + 1) & 3) ND_PRINT((ndo, " [bad length %u]", length)); + ND_TCHECK(cp[2]); ptr = cp[2] - 1; if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) ND_PRINT((ndo, " [bad ptr %u]", cp[2])); for (len = 3; len < length; len += 4) { + ND_TCHECK2(cp[len], 4); ND_PRINT((ndo, " %s", ipaddr_string(ndo, &cp[len]))); if (ptr > len) ND_PRINT((ndo, ",")); } + return (0); + +trunc: + return (-1); } /* @@ -168,7 +174,7 @@ nextproto4_cksum(netdissect_options *ndo, return (in_cksum(vec, 2)); } -static void +static int ip_printts(netdissect_options *ndo, register const u_char *cp, u_int length) { @@ -179,16 +185,18 @@ ip_printts(netdissect_options *ndo, if (length < 4) { ND_PRINT((ndo, "[bad length %u]", length)); - return; + return (0); } ND_PRINT((ndo, " TS{")); hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4; if ((length - 4) & (hoplen-1)) ND_PRINT((ndo, "[bad length %u]", length)); + ND_TCHECK(cp[2]); ptr = cp[2] - 1; len = 0; if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1) ND_PRINT((ndo, "[bad ptr %u]", cp[2])); + ND_TCHECK(cp[3]); switch (cp[3]&0xF) { case IPOPT_TS_TSONLY: ND_PRINT((ndo, "TSONLY")); @@ -217,6 +225,7 @@ ip_printts(netdissect_options *ndo, for (len = 4; len < length; len += hoplen) { if (ptr == len) type = " ^ "; + ND_TCHECK2(cp[len], hoplen); ND_PRINT((ndo, "%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]), hoplen!=8 ? "" : ipaddr_string(ndo, &cp[len]))); type = " "; @@ -229,6 +238,10 @@ done: ND_PRINT((ndo, " [%d hops not recorded]} ", cp[3]>>4)); else ND_PRINT((ndo, "}")); + return (0); + +trunc: + return (-1); } /* @@ -278,13 +291,15 @@ ip_optprint(netdissect_options *ndo, return; case IPOPT_TS: - ip_printts(ndo, cp, option_len); + if (ip_printts(ndo, cp, option_len) == -1) + goto trunc; break; case IPOPT_RR: /* fall through */ case IPOPT_SSRR: case IPOPT_LSRR: - ip_printroute(ndo, cp, option_len); + if (ip_printroute(ndo, cp, option_len) == -1) + goto trunc; break; case IPOPT_RA: @@ -330,7 +345,7 @@ static void ip_print_demux(netdissect_options *ndo, struct ip_print_demux_state *ipds) { - struct protoent *proto; + const char *p_name; again: switch (ipds->nh) { @@ -496,8 +511,8 @@ again: #endif default: - if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL) - ND_PRINT((ndo, " %s", proto->p_name)); + if (ndo->ndo_nflag==0 && (p_name = netdb_protoname(ipds->nh)) != NULL) + ND_PRINT((ndo, " %s", p_name)); else ND_PRINT((ndo, " ip-proto-%d", ipds->nh)); ND_PRINT((ndo, " %d", ipds->len)); @@ -538,7 +553,7 @@ ip_print(netdissect_options *ndo, u_int hlen; struct cksum_vec vec[1]; uint16_t sum, ip_sum; - struct protoent *proto; + const char *p_name; ipds->ip = (const struct ip *)bp; ND_TCHECK(ipds->ip->ip_vhl); @@ -683,8 +698,8 @@ ip_print(netdissect_options *ndo, */ ND_PRINT((ndo, "%s > %s:", ipaddr_string(ndo, &ipds->ip->ip_src), ipaddr_string(ndo, &ipds->ip->ip_dst))); - if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL) - ND_PRINT((ndo, " %s", proto->p_name)); + if (!ndo->ndo_nflag && (p_name = netdb_protoname(ipds->ip->ip_p)) != NULL) + ND_PRINT((ndo, " %s", p_name)); else ND_PRINT((ndo, " ip-proto-%d", ipds->ip->ip_p)); } diff --git a/freebsd/contrib/tcpdump/print-ip6.c b/freebsd/contrib/tcpdump/print-ip6.c index c82ead12..047ddfc0 100644 --- a/freebsd/contrib/tcpdump/print-ip6.c +++ b/freebsd/contrib/tcpdump/print-ip6.c @@ -286,6 +286,8 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) advance = sizeof(struct ip6_hdr); nh = ip6->ip6_nxt; while (cp < ndo->ndo_snapend && advance > 0) { + if (len < (u_int)advance) + goto trunc; cp += advance; len -= advance; @@ -328,10 +330,15 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) * mobility header. */ advance = mobility_print(ndo, cp, (const u_char *)ip6); + if (advance < 0) + return; nh = *cp; return; case IPPROTO_ROUTING: + ND_TCHECK(*cp); advance = rt6_print(ndo, cp, (const u_char *)ip6); + if (advance < 0) + return; nh = *cp; break; case IPPROTO_SCTP: @@ -351,12 +358,16 @@ ip6_print(netdissect_options *ndo, const u_char *bp, u_int length) return; case IPPROTO_AH: advance = ah_print(ndo, cp); + if (advance < 0) + return; nh = *cp; break; case IPPROTO_ESP: { int enh, padlen; advance = esp_print(ndo, cp, len, (const u_char *)ip6, &enh, &padlen); + if (advance < 0) + return; nh = enh & 0xff; len -= padlen; break; diff --git a/freebsd/contrib/tcpdump/print-ip6opts.c b/freebsd/contrib/tcpdump/print-ip6opts.c index 782ac550..a35111fa 100644 --- a/freebsd/contrib/tcpdump/print-ip6opts.c +++ b/freebsd/contrib/tcpdump/print-ip6opts.c @@ -41,12 +41,12 @@ #include <netdissect-stdinc.h> -#include "ip6.h" - #include "netdissect.h" #include "addrtoname.h" #include "extract.h" +#include "ip6.h" + static void ip6_sopt_print(netdissect_options *ndo, const u_char *bp, int len) { diff --git a/freebsd/contrib/tcpdump/print-isakmp.c b/freebsd/contrib/tcpdump/print-isakmp.c index c004eea9..fd78bf86 100644 --- a/freebsd/contrib/tcpdump/print-isakmp.c +++ b/freebsd/contrib/tcpdump/print-isakmp.c @@ -57,6 +57,7 @@ #include "ip.h" #include "ip6.h" +#include "ipproto.h" /* refer to RFC 2408 */ @@ -433,7 +434,7 @@ struct notify_messages { char *msg; }; -/* 3.8 Notification Payload */ +/* 3.8 Authentication Payload */ struct ikev2_auth { struct isakmp_gen h; uint8_t auth_method; /* Protocol-ID */ @@ -921,21 +922,25 @@ struct attrmap { static const u_char * ikev1_attrmap_print(netdissect_options *ndo, - const u_char *p, const u_char *ep, + const u_char *p, const u_char *ep2, const struct attrmap *map, size_t nmap) { int totlen; uint32_t t, v; + ND_TCHECK(p[0]); if (p[0] & 0x80) totlen = 4; - else + else { + ND_TCHECK_16BITS(&p[2]); totlen = 4 + EXTRACT_16BITS(&p[2]); - if (ep < p + totlen) { + } + if (ep2 < p + totlen) { ND_PRINT((ndo,"[|attr]")); - return ep + 1; + return ep2 + 1; } + ND_TCHECK_16BITS(&p[0]); ND_PRINT((ndo,"(")); t = EXTRACT_16BITS(&p[0]) & 0x7fff; if (map && t < nmap && map[t].type) @@ -944,47 +949,71 @@ ikev1_attrmap_print(netdissect_options *ndo, ND_PRINT((ndo,"type=#%d ", t)); if (p[0] & 0x80) { ND_PRINT((ndo,"value=")); + ND_TCHECK_16BITS(&p[2]); v = EXTRACT_16BITS(&p[2]); if (map && t < nmap && v < map[t].nvalue && map[t].value[v]) ND_PRINT((ndo,"%s", map[t].value[v])); - else - rawprint(ndo, (const uint8_t *)&p[2], 2); + else { + if (!rawprint(ndo, (const uint8_t *)&p[2], 2)) { + ND_PRINT((ndo,")")); + goto trunc; + } + } } else { - ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&p[2]))); - rawprint(ndo, (const uint8_t *)&p[4], EXTRACT_16BITS(&p[2])); + ND_PRINT((ndo,"len=%d value=", totlen - 4)); + if (!rawprint(ndo, (const uint8_t *)&p[4], totlen - 4)) { + ND_PRINT((ndo,")")); + goto trunc; + } } ND_PRINT((ndo,")")); return p + totlen; + +trunc: + return NULL; } static const u_char * -ikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep) +ikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep2) { int totlen; uint32_t t; + ND_TCHECK(p[0]); if (p[0] & 0x80) totlen = 4; - else + else { + ND_TCHECK_16BITS(&p[2]); totlen = 4 + EXTRACT_16BITS(&p[2]); - if (ep < p + totlen) { + } + if (ep2 < p + totlen) { ND_PRINT((ndo,"[|attr]")); - return ep + 1; + return ep2 + 1; } + ND_TCHECK_16BITS(&p[0]); ND_PRINT((ndo,"(")); t = EXTRACT_16BITS(&p[0]) & 0x7fff; ND_PRINT((ndo,"type=#%d ", t)); if (p[0] & 0x80) { ND_PRINT((ndo,"value=")); t = p[2]; - rawprint(ndo, (const uint8_t *)&p[2], 2); + if (!rawprint(ndo, (const uint8_t *)&p[2], 2)) { + ND_PRINT((ndo,")")); + goto trunc; + } } else { - ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&p[2]))); - rawprint(ndo, (const uint8_t *)&p[4], EXTRACT_16BITS(&p[2])); + ND_PRINT((ndo,"len=%d value=", totlen - 4)); + if (!rawprint(ndo, (const uint8_t *)&p[4], totlen - 4)) { + ND_PRINT((ndo,")")); + goto trunc; + } } ND_PRINT((ndo,")")); return p + totlen; + +trunc: + return NULL; } static const u_char * @@ -1265,11 +1294,12 @@ ikev1_t_print(netdissect_options *ndo, u_char tpay _U_, cp = (const u_char *)(p + 1); ep2 = (const u_char *)p + item_len; while (cp < ep && cp < ep2) { - if (map && nmap) { - cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2, - map, nmap); - } else - cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2); + if (map && nmap) + cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap); + else + cp = ikev1_attr_print(ndo, cp, ep2); + if (cp == NULL) + goto trunc; } if (ep < ep2) ND_PRINT((ndo,"...")); @@ -1293,6 +1323,7 @@ ikev1_ke_print(netdissect_options *ndo, u_char tpay _U_, UNALIGNED_MEMCPY(&e, ext, sizeof(e)); ND_PRINT((ndo," key len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), ntohs(e.len) - 4)) goto trunc; @@ -1356,16 +1387,15 @@ ikev1_id_print(netdissect_options *ndo, u_char tpay _U_, { const struct ipsecdoi_id *doi_p; struct ipsecdoi_id doi_id; - struct protoent *pe; + const char *p_name; doi_p = (const struct ipsecdoi_id *)ext; ND_TCHECK(*doi_p); UNALIGNED_MEMCPY(&doi_id, ext, sizeof(doi_id)); ND_PRINT((ndo," idtype=%s", STR_OR_ID(doi_id.type, ipsecidtypestr))); /* A protocol ID of 0 DOES NOT mean IPPROTO_IP! */ - pe = doi_id.proto_id ? getprotobynumber(doi_id.proto_id) : NULL; - if (pe) - ND_PRINT((ndo," protoid=%s", pe->p_name)); + if (!ndo->ndo_nflag && doi_id.proto_id && (p_name = netdb_protoname(doi_id.proto_id)) != NULL) + ND_PRINT((ndo," protoid=%s", p_name)); else ND_PRINT((ndo," protoid=%u", doi_id.proto_id)); ND_PRINT((ndo," port=%d", ntohs(doi_id.port))); @@ -1416,8 +1446,8 @@ ikev1_id_print(netdissect_options *ndo, u_char tpay _U_, case IPSECDOI_ID_IPV6_ADDR_SUBNET: { const u_char *mask; - if (len < 20) - ND_PRINT((ndo," len=%d [bad: < 20]", len)); + if (len < 32) + ND_PRINT((ndo," len=%d [bad: < 32]", len)); else { mask = (const u_char *)(data + sizeof(struct in6_addr)); /*XXX*/ @@ -1496,6 +1526,7 @@ ikev1_cert_print(netdissect_options *ndo, u_char tpay _U_, ND_PRINT((ndo," len=%d", item_len - 4)); ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr))); if (2 < ndo->ndo_vflag && 4 < item_len) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4)) goto trunc; @@ -1528,6 +1559,7 @@ ikev1_cr_print(netdissect_options *ndo, u_char tpay _U_, ND_PRINT((ndo," len=%d", item_len - 4)); ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr))); if (2 < ndo->ndo_vflag && 4 < item_len) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4)) goto trunc; @@ -1552,6 +1584,7 @@ ikev1_hash_print(netdissect_options *ndo, u_char tpay _U_, UNALIGNED_MEMCPY(&e, ext, sizeof(e)); ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), ntohs(e.len) - 4)) goto trunc; @@ -1576,6 +1609,7 @@ ikev1_sig_print(netdissect_options *ndo, u_char tpay _U_, UNALIGNED_MEMCPY(&e, ext, sizeof(e)); ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), ntohs(e.len) - 4)) goto trunc; @@ -1600,15 +1634,20 @@ ikev1_nonce_print(netdissect_options *ndo, u_char tpay _U_, ND_TCHECK(*ext); UNALIGNED_MEMCPY(&e, ext, sizeof(e)); - ND_PRINT((ndo," n len=%d", ntohs(e.len) - 4)); - if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { - ND_PRINT((ndo," ")); - if (!rawprint(ndo, (const uint8_t *)(ext + 1), ntohs(e.len) - 4)) - goto trunc; - } else if (1 < ndo->ndo_vflag && 4 < ntohs(e.len)) { - ND_PRINT((ndo," ")); - if (!ike_show_somedata(ndo, (const u_char *)(const uint8_t *)(ext + 1), ep)) - goto trunc; + /* + * Our caller has ensured that the length is >= 4. + */ + ND_PRINT((ndo," n len=%u", ntohs(e.len) - 4)); + if (ntohs(e.len) > 4) { + if (ndo->ndo_vflag > 2) { + ND_PRINT((ndo, " ")); + if (!rawprint(ndo, (const uint8_t *)(ext + 1), ntohs(e.len) - 4)) + goto trunc; + } else if (ndo->ndo_vflag > 1) { + ND_PRINT((ndo, " ")); + if (!ike_show_somedata(ndo, (const u_char *)(ext + 1), ep)) + goto trunc; + } } return (const u_char *)ext + ntohs(e.len); trunc: @@ -1619,8 +1658,8 @@ trunc: static const u_char * ikev1_n_print(netdissect_options *ndo, u_char tpay _U_, const struct isakmp_gen *ext, u_int item_len, - const u_char *ep, uint32_t phase, uint32_t doi0 _U_, - uint32_t proto0 _U_, int depth) + const u_char *ep, uint32_t phase _U_, uint32_t doi0 _U_, + uint32_t proto0 _U_, int depth _U_) { const struct ikev1_pl_n *p; struct ikev1_pl_n n; @@ -1722,35 +1761,44 @@ ikev1_n_print(netdissect_options *ndo, u_char tpay _U_, ep2 = (const u_char *)p + item_len; if (cp < ep) { - ND_PRINT((ndo," orig=(")); switch (ntohs(n.type)) { case IPSECDOI_NTYPE_RESPONDER_LIFETIME: { const struct attrmap *map = oakley_t_map; size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]); + ND_PRINT((ndo," attrs=(")); while (cp < ep && cp < ep2) { - cp = ikev1_attrmap_print(ndo, cp, - (ep < ep2) ? ep : ep2, map, nmap); + cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap); + if (cp == NULL) { + ND_PRINT((ndo,")")); + goto trunc; + } } + ND_PRINT((ndo,")")); break; } case IPSECDOI_NTYPE_REPLAY_STATUS: + ND_PRINT((ndo," status=(")); ND_PRINT((ndo,"replay detection %sabled", EXTRACT_32BITS(cp) ? "en" : "dis")); - break; - case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN: - if (ikev1_sub_print(ndo, ISAKMP_NPTYPE_SA, - (const struct isakmp_gen *)cp, ep, phase, doi, proto, - depth) == NULL) - return NULL; + ND_PRINT((ndo,")")); break; default: - /* NULL is dummy */ - isakmp_print(ndo, cp, - item_len - sizeof(*p) - n.spi_size, - NULL); + /* + * XXX - fill in more types here; see, for example, + * draft-ietf-ipsec-notifymsg-04. + */ + if (ndo->ndo_vflag > 3) { + ND_PRINT((ndo," data=(")); + if (!rawprint(ndo, (const uint8_t *)(cp), ep - cp)) + goto trunc; + ND_PRINT((ndo,")")); + } else { + if (!ike_show_somedata(ndo, cp, ep)) + goto trunc; + } + break; } - ND_PRINT((ndo,")")); } return (const u_char *)ext + item_len; trunc: @@ -1817,6 +1865,7 @@ ikev1_vid_print(netdissect_options *ndo, u_char tpay _U_, UNALIGNED_MEMCPY(&e, ext, sizeof(e)); ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), ntohs(e.len) - 4)) goto trunc; @@ -1851,6 +1900,7 @@ ikev2_gen_print(netdissect_options *ndo, u_char tpay, ND_PRINT((ndo," len=%d", ntohs(e.len) - 4)); if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), ntohs(e.len) - 4)) goto trunc; @@ -1925,10 +1975,11 @@ ikev2_t_print(netdissect_options *ndo, int tcount, ep2 = (const u_char *)p + item_len; while (cp < ep && cp < ep2) { if (map && nmap) { - cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2, - map, nmap); + cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap); } else - cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2); + cp = ikev1_attr_print(ndo, cp, ep2); + if (cp == NULL) + goto trunc; } if (ep < ep2) ND_PRINT((ndo,"...")); @@ -1988,7 +2039,6 @@ ikev2_p_print(netdissect_options *ndo, u_char tpay _U_, int pcount _U_, if (prop_length < sizeof(*ext)) goto toolong; ND_TCHECK(*ext); - UNALIGNED_MEMCPY(&e, ext, sizeof(e)); /* @@ -2075,7 +2125,6 @@ ikev2_sa_print(netdissect_options *ndo, u_char tpay, if (sa_length < sizeof(*ext)) goto toolong; ND_TCHECK(*ext); - UNALIGNED_MEMCPY(&e, ext, sizeof(e)); /* @@ -2136,7 +2185,7 @@ ikev2_ke_print(netdissect_options *ndo, u_char tpay, const struct ikev2_ke *k; k = (const struct ikev2_ke *)ext; - ND_TCHECK(*ext); + ND_TCHECK(*k); UNALIGNED_MEMCPY(&ke, ext, sizeof(ke)); ikev2_pay_print(ndo, NPSTR(tpay), ke.h.critical); @@ -2161,12 +2210,14 @@ ikev2_ID_print(netdissect_options *ndo, u_char tpay, uint32_t phase _U_, uint32_t doi _U_, uint32_t proto _U_, int depth _U_) { + const struct ikev2_id *idp; struct ikev2_id id; int id_len, idtype_len, i; unsigned int dumpascii, dumphex; const unsigned char *typedata; - ND_TCHECK(*ext); + idp = (const struct ikev2_id *)ext; + ND_TCHECK(*idp); UNALIGNED_MEMCPY(&id, ext, sizeof(id)); ikev2_pay_print(ndo, NPSTR(tpay), id.h.critical); @@ -2174,6 +2225,7 @@ ikev2_ID_print(netdissect_options *ndo, u_char tpay, ND_PRINT((ndo," len=%d", id_len - 4)); if (2 < ndo->ndo_vflag && 4 < id_len) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), id_len - 4)) goto trunc; @@ -2269,21 +2321,26 @@ ikev2_auth_print(netdissect_options *ndo, u_char tpay, const u_char *authdata = (const u_char*)ext + sizeof(a); unsigned int len; - ND_TCHECK(*ext); + ND_TCHECK2(*ext, sizeof(a)); UNALIGNED_MEMCPY(&a, ext, sizeof(a)); ikev2_pay_print(ndo, NPSTR(tpay), a.h.critical); len = ntohs(a.h.len); - ND_PRINT((ndo," len=%d method=%s", len-4, + /* + * Our caller has ensured that the length is >= 4. + */ + ND_PRINT((ndo," len=%u method=%s", len-4, STR_OR_ID(a.auth_method, v2_auth))); - - if (1 < ndo->ndo_vflag && 4 < len) { - ND_PRINT((ndo," authdata=(")); - if (!rawprint(ndo, (const uint8_t *)authdata, len - sizeof(a))) - goto trunc; - ND_PRINT((ndo,") ")); - } else if(ndo->ndo_vflag && 4 < len) { - if(!ike_show_somedata(ndo, authdata, ep)) goto trunc; + if (len > 4) { + if (ndo->ndo_vflag > 1) { + ND_PRINT((ndo, " authdata=(")); + if (!rawprint(ndo, (const uint8_t *)authdata, len - sizeof(a))) + goto trunc; + ND_PRINT((ndo, ") ")); + } else if (ndo->ndo_vflag) { + if (!ike_show_somedata(ndo, authdata, ep)) + goto trunc; + } } return (const u_char *)ext + len; @@ -2332,7 +2389,7 @@ ikev2_n_print(netdissect_options *ndo, u_char tpay _U_, const struct ikev2_n *p; struct ikev2_n n; const u_char *cp; - u_char showspi, showdata, showsomedata; + u_char showspi, showsomedata; const char *notify_name; uint32_t type; @@ -2342,7 +2399,6 @@ ikev2_n_print(netdissect_options *ndo, u_char tpay _U_, ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_N), n.h.critical); showspi = 1; - showdata = 0; showsomedata=0; notify_name=NULL; @@ -2456,7 +2512,6 @@ ikev2_n_print(netdissect_options *ndo, u_char tpay _U_, notify_name = "cookie"; showspi = 1; showsomedata= 1; - showdata= 0; break; case IV2_NOTIFY_USE_TRANSPORT_MODE: @@ -2509,19 +2564,17 @@ ikev2_n_print(netdissect_options *ndo, u_char tpay _U_, cp = (const u_char *)(p + 1) + n.spi_size; - if(3 < ndo->ndo_vflag) { - showdata = 1; - } - - if ((showdata || (showsomedata && ep-cp < 30)) && cp < ep) { - ND_PRINT((ndo," data=(")); - if (!rawprint(ndo, (const uint8_t *)(cp), ep - cp)) - goto trunc; - - ND_PRINT((ndo,")")); + if (cp < ep) { + if (ndo->ndo_vflag > 3 || (showsomedata && ep-cp < 30)) { + ND_PRINT((ndo," data=(")); + if (!rawprint(ndo, (const uint8_t *)(cp), ep - cp)) + goto trunc; - } else if(showsomedata && cp < ep) { - if(!ike_show_somedata(ndo, cp, ep)) goto trunc; + ND_PRINT((ndo,")")); + } else if (showsomedata) { + if (!ike_show_somedata(ndo, cp, ep)) + goto trunc; + } } return (const u_char *)ext + item_len; @@ -2564,6 +2617,7 @@ ikev2_vid_print(netdissect_options *ndo, u_char tpay, else ND_PRINT((ndo, ".")); } if (2 < ndo->ndo_vflag && 4 < len) { + /* Print the entire payload in hex */ ND_PRINT((ndo," ")); if (!rawprint(ndo, (const uint8_t *)(ext + 1), ntohs(e.len) - 4)) goto trunc; @@ -2729,7 +2783,6 @@ ikev1_sub_print(netdissect_options *ndo, while (np) { ND_TCHECK(*ext); - UNALIGNED_MEMCPY(&e, ext, sizeof(e)); ND_TCHECK2(*ext, ntohs(e.len)); @@ -2897,7 +2950,6 @@ ikev2_sub_print(netdissect_options *ndo, cp = (const u_char *)ext; while (np) { ND_TCHECK(*ext); - UNALIGNED_MEMCPY(&e, ext, sizeof(e)); ND_TCHECK2(*ext, ntohs(e.len)); @@ -3051,7 +3103,7 @@ isakmp_rfc3948_print(netdissect_options *ndo, const u_char *bp, u_int length, const u_char *bp2) { - + ND_TCHECK(bp[0]); if(length == 1 && bp[0]==0xff) { ND_PRINT((ndo, "isakmp-nat-keep-alive")); return; @@ -3060,6 +3112,7 @@ isakmp_rfc3948_print(netdissect_options *ndo, if(length < 4) { goto trunc; } + ND_TCHECK(bp[3]); /* * see if this is an IKE packet @@ -3100,10 +3153,6 @@ trunc: * c-basic-offset: 8 * End: */ - - - - #ifdef __rtems__ #include "rtems-bsd-tcpdump-print-isakmp-data.h" #endif /* __rtems__ */ diff --git a/freebsd/contrib/tcpdump/print-isoclns.c b/freebsd/contrib/tcpdump/print-isoclns.c index 7fec66e0..480e5f19 100644 --- a/freebsd/contrib/tcpdump/print-isoclns.c +++ b/freebsd/contrib/tcpdump/print-isoclns.c @@ -26,7 +26,7 @@ * * Original code by Matt Thomas, Digital Equipment Corporation * - * Extensively modified by Hannes Gredler (hannes@juniper.net) for more + * Extensively modified by Hannes Gredler (hannes@gredler.at) for more * complete IS-IS & CLNP support. */ @@ -570,8 +570,8 @@ struct isis_tlv_ptp_adj { uint8_t neighbor_extd_local_circuit_id[4]; }; -static int osi_print_cksum(netdissect_options *, const uint8_t *pptr, - uint16_t checksum, int checksum_offset, int length); +static void osi_print_cksum(netdissect_options *, const uint8_t *pptr, + uint16_t checksum, int checksum_offset, u_int length); static int clnp_print(netdissect_options *, const uint8_t *, u_int); static void esis_print(netdissect_options *, const uint8_t *, u_int); static int isis_print(netdissect_options *, const uint8_t *, u_int); @@ -676,10 +676,9 @@ struct isis_tlv_lsp { #define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header)) void -isoclns_print(netdissect_options *ndo, - const uint8_t *p, u_int length, u_int caplen) +isoclns_print(netdissect_options *ndo, const uint8_t *p, u_int length) { - if (caplen <= 1) { /* enough bytes on the wire ? */ + if (!ND_TTEST(*p)) { /* enough bytes on the wire ? */ ND_PRINT((ndo, "|OSI")); return; } @@ -691,7 +690,7 @@ isoclns_print(netdissect_options *ndo, case NLPID_CLNP: if (!clnp_print(ndo, p, length)) - print_unknown_data(ndo, p, "\n\t", caplen); + print_unknown_data(ndo, p, "\n\t", length); break; case NLPID_ESIS: @@ -700,7 +699,7 @@ isoclns_print(netdissect_options *ndo, case NLPID_ISIS: if (!isis_print(ndo, p, length)) - print_unknown_data(ndo, p, "\n\t", caplen); + print_unknown_data(ndo, p, "\n\t", length); break; case NLPID_NULLNS: @@ -727,8 +726,8 @@ isoclns_print(netdissect_options *ndo, if (!ndo->ndo_eflag) ND_PRINT((ndo, "OSI NLPID 0x%02x unknown", *p)); ND_PRINT((ndo, "%slength: %u", ndo->ndo_eflag ? "" : ", ", length)); - if (caplen > 1) - print_unknown_data(ndo, p, "\n\t", caplen); + if (length > 1) + print_unknown_data(ndo, p, "\n\t", length); break; } } @@ -871,9 +870,8 @@ clnp_print(netdissect_options *ndo, EXTRACT_16BITS(clnp_header->segment_length), EXTRACT_16BITS(clnp_header->cksum))); - if (osi_print_cksum(ndo, optr, EXTRACT_16BITS(clnp_header->cksum), 7, - clnp_header->length_indicator) == 0) - goto trunc; + osi_print_cksum(ndo, optr, EXTRACT_16BITS(clnp_header->cksum), 7, + clnp_header->length_indicator); ND_PRINT((ndo, "\n\tFlags [%s]", bittok2str(clnp_flag_values, "none", clnp_flags))); @@ -1159,8 +1157,7 @@ esis_print(netdissect_options *ndo, ND_PRINT((ndo, ", v: %u%s", esis_header->version, esis_header->version == ESIS_VERSION ? "" : "unsupported" )); ND_PRINT((ndo, ", checksum: 0x%04x", EXTRACT_16BITS(esis_header->cksum))); - if (osi_print_cksum(ndo, pptr, EXTRACT_16BITS(esis_header->cksum), 7, li) == 0) - goto trunc; + osi_print_cksum(ndo, pptr, EXTRACT_16BITS(esis_header->cksum), 7, li); ND_PRINT((ndo, ", holding time: %us, length indicator: %u", EXTRACT_16BITS(esis_header->holdtime), li)); @@ -1226,10 +1223,18 @@ esis_print(netdissect_options *ndo, pptr += netal; li -= netal; - if (netal == 0) - ND_PRINT((ndo, "\n\t %s", etheraddr_string(ndo, snpa))); + if (snpal == 6) + ND_PRINT((ndo, "\n\t SNPA (length: %u): %s", + snpal, + etheraddr_string(ndo, snpa))); else - ND_PRINT((ndo, "\n\t %s", isonsap_string(ndo, neta, netal))); + ND_PRINT((ndo, "\n\t SNPA (length: %u): %s", + snpal, + linkaddr_string(ndo, snpa, LINKADDR_OTHER, snpal))); + if (netal != 0) + ND_PRINT((ndo, "\n\t NET (length: %u) %s", + netal, + isonsap_string(ndo, neta, netal))); break; } @@ -1335,7 +1340,7 @@ esis_print(netdissect_options *ndo, case ESIS_OPTION_PROTOCOLS: while (opli>0) { - ND_TCHECK(*pptr); + ND_TCHECK(*tptr); ND_PRINT((ndo, "%s (0x%02x)", tok2str(nlpid_values, "unknown", @@ -1368,7 +1373,7 @@ esis_print(netdissect_options *ndo, pptr += opli; } trunc: - return; + ND_PRINT((ndo, "[|esis]")); } static void @@ -1404,6 +1409,7 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo, while (len > 2) { + ND_TCHECK2(*tptr, 2); stlv_type = *(tptr++); stlv_len = *(tptr++); @@ -1416,11 +1422,18 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo, /*len -= TLV_TYPE_LEN_OFFSET;*/ len = len -2; + /* Make sure the subTLV fits within the space left */ + if (len < stlv_len) + goto trunc; + /* Make sure the entire subTLV is in the captured data */ + ND_TCHECK2(*(tptr), stlv_len); + switch (stlv_type) { case ISIS_SUBTLV_SPB_MCID: { - ND_TCHECK2(*(tptr), ISIS_SUBTLV_SPB_MCID_MIN_LEN); + if (stlv_len < ISIS_SUBTLV_SPB_MCID_MIN_LEN) + goto trunc; subtlv_spb_mcid = (const struct isis_subtlv_spb_mcid *)tptr; @@ -1435,15 +1448,17 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo, /*tptr += SPB_MCID_MIN_LEN; len -= SPB_MCID_MIN_LEN; */ - tptr = tptr + sizeof(struct isis_subtlv_spb_mcid); - len = len - sizeof(struct isis_subtlv_spb_mcid); + tptr = tptr + ISIS_SUBTLV_SPB_MCID_MIN_LEN; + len = len - ISIS_SUBTLV_SPB_MCID_MIN_LEN; + stlv_len = stlv_len - ISIS_SUBTLV_SPB_MCID_MIN_LEN; break; } case ISIS_SUBTLV_SPB_DIGEST: { - ND_TCHECK2(*(tptr), ISIS_SUBTLV_SPB_DIGEST_MIN_LEN); + if (stlv_len < ISIS_SUBTLV_SPB_DIGEST_MIN_LEN) + goto trunc; ND_PRINT((ndo, "\n\t RES: %d V: %d A: %d D: %d", (*(tptr) >> 5), (((*tptr)>> 4) & 0x01), @@ -1462,18 +1477,15 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo, } len = len - ISIS_SUBTLV_SPB_DIGEST_MIN_LEN; + stlv_len = stlv_len - ISIS_SUBTLV_SPB_DIGEST_MIN_LEN; break; } case ISIS_SUBTLV_SPB_BVID: { - ND_TCHECK2(*(tptr), stlv_len); - - while (len >= ISIS_SUBTLV_SPB_BVID_MIN_LEN) + while (stlv_len >= ISIS_SUBTLV_SPB_BVID_MIN_LEN) { - ND_TCHECK2(*(tptr), ISIS_SUBTLV_SPB_BVID_MIN_LEN); - ND_PRINT((ndo, "\n\t ECT: %08x", EXTRACT_32BITS(tptr))); @@ -1486,14 +1498,17 @@ isis_print_mt_port_cap_subtlv(netdissect_options *ndo, tptr = tptr + 2; len = len - ISIS_SUBTLV_SPB_BVID_MIN_LEN; + stlv_len = stlv_len - ISIS_SUBTLV_SPB_BVID_MIN_LEN; } break; } default: - break; + break; } + tptr += stlv_len; + len -= stlv_len; } return 0; @@ -1512,6 +1527,7 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo, while (len > 2) { + ND_TCHECK2(*tptr, 2); stlv_type = *(tptr++); stlv_len = *(tptr++); @@ -1523,11 +1539,17 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo, len = len - 2; + /* Make sure the subTLV fits within the space left */ + if (len < stlv_len) + goto trunc; + /* Make sure the entire subTLV is in the captured data */ + ND_TCHECK2(*(tptr), stlv_len); + switch (stlv_type) { case ISIS_SUBTLV_SPB_INSTANCE: - - ND_TCHECK2(*tptr, ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN); + if (stlv_len < ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN) + goto trunc; ND_PRINT((ndo, "\n\t CIST Root-ID: %08x", EXTRACT_32BITS(tptr))); tptr = tptr+4; @@ -1549,10 +1571,12 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo, tmp = *(tptr++); len = len - ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN; + stlv_len = stlv_len - ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN; while (tmp) { - ND_TCHECK2(*tptr, ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN); + if (stlv_len < ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN) + goto trunc; ND_PRINT((ndo, "\n\t U:%d, M:%d, A:%d, RES:%d", *(tptr) >> 7, (*(tptr) >> 6) & 0x01, @@ -1570,14 +1594,15 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo, tptr = tptr + 3; len = len - ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN; + stlv_len = stlv_len - ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN; tmp--; } break; case ISIS_SUBTLV_SPBM_SI: - - ND_TCHECK2(*tptr, 8); + if (stlv_len < 8) + goto trunc; ND_PRINT((ndo, "\n\t BMAC: %08x", EXTRACT_32BITS(tptr))); tptr = tptr+4; @@ -1609,6 +1634,8 @@ isis_print_mt_capability_subtlv(netdissect_options *ndo, default: break; } + tptr += stlv_len; + len -= stlv_len; } return 0; @@ -1625,8 +1652,12 @@ isis_print_id(const uint8_t *cp, int id_len) int i; static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")]; char *pos = id; + int sysid_len; - for (i = 1; i <= SYSTEM_ID_LEN; i++) { + sysid_len = SYSTEM_ID_LEN; + if (sysid_len > id_len) + sysid_len = id_len; + for (i = 1; i <= sysid_len; i++) { snprintf(pos, sizeof(id) - (pos - id), "%02x", *cp++); pos += strlen(pos); if (i == 2 || i == 4) @@ -1836,6 +1867,8 @@ isis_print_is_reach_subtlv(netdissect_options *ndo, break; case ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS: /* fall through */ case ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD: + if (subl == 0) + break; ND_PRINT((ndo, "%sBandwidth Constraints Model ID: %s (%u)", ident, tok2str(diffserv_te_bc_values, "unknown", *tptr), @@ -1843,7 +1876,6 @@ isis_print_is_reach_subtlv(netdissect_options *ndo, tptr++; /* decode BCs until the subTLV ends */ for (te_class = 0; te_class < (subl-1)/4; te_class++) { - ND_TCHECK2(*tptr, 4); bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%s Bandwidth constraint CT%u: %.3f Mbps", ident, @@ -1905,13 +1937,15 @@ isis_print_is_reach_subtlv(netdissect_options *ndo, case GMPLS_PSC2: case GMPLS_PSC3: case GMPLS_PSC4: - ND_TCHECK2(*tptr, 6); + if (subl < 6) + break; bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f * 8 / 1000000)); ND_PRINT((ndo, "%s Interface MTU: %u", ident, EXTRACT_16BITS(tptr + 4))); break; case GMPLS_TSC: - ND_TCHECK2(*tptr, 8); + if (subl < 8) + break; bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f * 8 / 1000000)); ND_PRINT((ndo, "%s Indication %s", ident, @@ -2047,7 +2081,7 @@ isis_print_extd_ip_reach(netdissect_options *ndo, } processed++; } else if (afi == AF_INET6) { - if (!ND_TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */ + if (!ND_TTEST2(*tptr, 2)) /* fetch status & prefix_len byte */ return (0); status_byte=*(tptr++); bit_length=*(tptr++); @@ -2170,6 +2204,8 @@ isis_print(netdissect_options *ndo, TLV verification */ isis_header = (const struct isis_common_header *)p; ND_TCHECK(*isis_header); + if (length < ISIS_COMMON_HEADER_SIZE) + goto trunc; pptr = p+(ISIS_COMMON_HEADER_SIZE); header_iih_lan = (const struct isis_iih_lan_header *)pptr; header_iih_ptp = (const struct isis_iih_ptp_header *)pptr; @@ -2200,6 +2236,16 @@ isis_print(netdissect_options *ndo, return (0); } + if (length < isis_header->fixed_len) { + ND_PRINT((ndo, "fixed header length %u > packet length %u", isis_header->fixed_len, length)); + return (0); + } + + if (isis_header->fixed_len < ISIS_COMMON_HEADER_SIZE) { + ND_PRINT((ndo, "fixed header length %u < minimum header size %u", isis_header->fixed_len, (u_int)ISIS_COMMON_HEADER_SIZE)); + return (0); + } + max_area = isis_header->max_area; switch(max_area) { case 0: @@ -2242,254 +2288,255 @@ isis_print(netdissect_options *ndo, pdu_type=isis_header->pdu_type; /* in non-verbose mode print the basic PDU Type plus PDU specific brief information*/ - if (ndo->ndo_vflag < 1) { + if (ndo->ndo_vflag == 0) { ND_PRINT((ndo, "%s%s", ndo->ndo_eflag ? "" : ", ", tok2str(isis_pdu_values, "unknown PDU-Type %u", pdu_type))); + } else { + /* ok they seem to want to know everything - lets fully decode it */ + ND_PRINT((ndo, "%slength %u", ndo->ndo_eflag ? "" : ", ", length)); - switch (pdu_type) { - - case ISIS_PDU_L1_LAN_IIH: - case ISIS_PDU_L2_LAN_IIH: - ND_TCHECK(*header_iih_lan); - ND_PRINT((ndo, ", src-id %s", - isis_print_id(header_iih_lan->source_id, SYSTEM_ID_LEN))); - ND_PRINT((ndo, ", lan-id %s, prio %u", - isis_print_id(header_iih_lan->lan_id,NODE_ID_LEN), - header_iih_lan->priority)); - break; - case ISIS_PDU_PTP_IIH: - ND_TCHECK(*header_iih_ptp); - ND_PRINT((ndo, ", src-id %s", isis_print_id(header_iih_ptp->source_id, SYSTEM_ID_LEN))); - break; - case ISIS_PDU_L1_LSP: - case ISIS_PDU_L2_LSP: - ND_TCHECK(*header_lsp); - ND_PRINT((ndo, ", lsp-id %s, seq 0x%08x, lifetime %5us", - isis_print_id(header_lsp->lsp_id, LSP_ID_LEN), - EXTRACT_32BITS(header_lsp->sequence_number), - EXTRACT_16BITS(header_lsp->remaining_lifetime))); - break; - case ISIS_PDU_L1_CSNP: - case ISIS_PDU_L2_CSNP: - ND_TCHECK(*header_csnp); - ND_PRINT((ndo, ", src-id %s", isis_print_id(header_csnp->source_id, NODE_ID_LEN))); - break; - case ISIS_PDU_L1_PSNP: - case ISIS_PDU_L2_PSNP: - ND_TCHECK(*header_psnp); - ND_PRINT((ndo, ", src-id %s", isis_print_id(header_psnp->source_id, NODE_ID_LEN))); - break; - - } - ND_PRINT((ndo, ", length %u", length)); - - return(1); - } - - /* ok they seem to want to know everything - lets fully decode it */ - ND_PRINT((ndo, "%slength %u", ndo->ndo_eflag ? "" : ", ", length)); - - ND_PRINT((ndo, "\n\t%s, hlen: %u, v: %u, pdu-v: %u, sys-id-len: %u (%u), max-area: %u (%u)", - tok2str(isis_pdu_values, - "unknown, type %u", - pdu_type), - isis_header->fixed_len, - isis_header->version, - isis_header->pdu_version, - id_length, - isis_header->id_length, - max_area, - isis_header->max_area)); - - if (ndo->ndo_vflag > 1) { - if (!print_unknown_data(ndo, optr, "\n\t", 8)) /* provide the _o_riginal pointer */ - return(0); /* for optionally debugging the common header */ + ND_PRINT((ndo, "\n\t%s, hlen: %u, v: %u, pdu-v: %u, sys-id-len: %u (%u), max-area: %u (%u)", + tok2str(isis_pdu_values, + "unknown, type %u", + pdu_type), + isis_header->fixed_len, + isis_header->version, + isis_header->pdu_version, + id_length, + isis_header->id_length, + max_area, + isis_header->max_area)); + + if (ndo->ndo_vflag > 1) { + if (!print_unknown_data(ndo, optr, "\n\t", 8)) /* provide the _o_riginal pointer */ + return (0); /* for optionally debugging the common header */ + } } switch (pdu_type) { case ISIS_PDU_L1_LAN_IIH: case ISIS_PDU_L2_LAN_IIH: - if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) { - ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", - isis_header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE)); - return (0); - } - - ND_TCHECK(*header_iih_lan); - pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len); - if (packet_len>pdu_len) { - packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ - length=pdu_len; - } + if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) { + ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", + isis_header->fixed_len, (unsigned long)(ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE))); + return (0); + } + ND_TCHECK(*header_iih_lan); + if (length < ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE) + goto trunc; + if (ndo->ndo_vflag == 0) { + ND_PRINT((ndo, ", src-id %s", + isis_print_id(header_iih_lan->source_id, SYSTEM_ID_LEN))); + ND_PRINT((ndo, ", lan-id %s, prio %u", + isis_print_id(header_iih_lan->lan_id,NODE_ID_LEN), + header_iih_lan->priority)); + ND_PRINT((ndo, ", length %u", length)); + return (1); + } + pdu_len=EXTRACT_16BITS(header_iih_lan->pdu_len); + if (packet_len>pdu_len) { + packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ + length=pdu_len; + } - ND_PRINT((ndo, "\n\t source-id: %s, holding time: %us, Flags: [%s]", - isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN), - EXTRACT_16BITS(header_iih_lan->holding_time), - tok2str(isis_iih_circuit_type_values, - "unknown circuit type 0x%02x", - header_iih_lan->circuit_type))); + ND_PRINT((ndo, "\n\t source-id: %s, holding time: %us, Flags: [%s]", + isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN), + EXTRACT_16BITS(header_iih_lan->holding_time), + tok2str(isis_iih_circuit_type_values, + "unknown circuit type 0x%02x", + header_iih_lan->circuit_type))); - ND_PRINT((ndo, "\n\t lan-id: %s, Priority: %u, PDU length: %u", - isis_print_id(header_iih_lan->lan_id, NODE_ID_LEN), - (header_iih_lan->priority) & ISIS_LAN_PRIORITY_MASK, - pdu_len)); + ND_PRINT((ndo, "\n\t lan-id: %s, Priority: %u, PDU length: %u", + isis_print_id(header_iih_lan->lan_id, NODE_ID_LEN), + (header_iih_lan->priority) & ISIS_LAN_PRIORITY_MASK, + pdu_len)); - if (ndo->ndo_vflag > 1) { - if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_IIH_LAN_HEADER_SIZE)) - return(0); - } + if (ndo->ndo_vflag > 1) { + if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_IIH_LAN_HEADER_SIZE)) + return (0); + } - packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); - pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); - break; + packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); + pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE); + break; case ISIS_PDU_PTP_IIH: - if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) { - ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", - isis_header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE)); - return (0); - } - - ND_TCHECK(*header_iih_ptp); - pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len); - if (packet_len>pdu_len) { + if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) { + ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", + isis_header->fixed_len, (unsigned long)(ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE))); + return (0); + } + ND_TCHECK(*header_iih_ptp); + if (length < ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE) + goto trunc; + if (ndo->ndo_vflag == 0) { + ND_PRINT((ndo, ", src-id %s", isis_print_id(header_iih_ptp->source_id, SYSTEM_ID_LEN))); + ND_PRINT((ndo, ", length %u", length)); + return (1); + } + pdu_len=EXTRACT_16BITS(header_iih_ptp->pdu_len); + if (packet_len>pdu_len) { packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ length=pdu_len; - } + } - ND_PRINT((ndo, "\n\t source-id: %s, holding time: %us, Flags: [%s]", - isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN), - EXTRACT_16BITS(header_iih_ptp->holding_time), - tok2str(isis_iih_circuit_type_values, - "unknown circuit type 0x%02x", - header_iih_ptp->circuit_type))); + ND_PRINT((ndo, "\n\t source-id: %s, holding time: %us, Flags: [%s]", + isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN), + EXTRACT_16BITS(header_iih_ptp->holding_time), + tok2str(isis_iih_circuit_type_values, + "unknown circuit type 0x%02x", + header_iih_ptp->circuit_type))); - ND_PRINT((ndo, "\n\t circuit-id: 0x%02x, PDU length: %u", - header_iih_ptp->circuit_id, - pdu_len)); + ND_PRINT((ndo, "\n\t circuit-id: 0x%02x, PDU length: %u", + header_iih_ptp->circuit_id, + pdu_len)); - if (ndo->ndo_vflag > 1) { - if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_IIH_PTP_HEADER_SIZE)) - return(0); - } + if (ndo->ndo_vflag > 1) { + if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_IIH_PTP_HEADER_SIZE)) + return (0); + } - packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); - pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); - break; + packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); + pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE); + break; case ISIS_PDU_L1_LSP: case ISIS_PDU_L2_LSP: - if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) { - ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", - isis_header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE)); - return (0); - } - - ND_TCHECK(*header_lsp); - pdu_len=EXTRACT_16BITS(header_lsp->pdu_len); - if (packet_len>pdu_len) { + if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) { + ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", + isis_header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE)); + return (0); + } + ND_TCHECK(*header_lsp); + if (length < ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE) + goto trunc; + if (ndo->ndo_vflag == 0) { + ND_PRINT((ndo, ", lsp-id %s, seq 0x%08x, lifetime %5us", + isis_print_id(header_lsp->lsp_id, LSP_ID_LEN), + EXTRACT_32BITS(header_lsp->sequence_number), + EXTRACT_16BITS(header_lsp->remaining_lifetime))); + ND_PRINT((ndo, ", length %u", length)); + return (1); + } + pdu_len=EXTRACT_16BITS(header_lsp->pdu_len); + if (packet_len>pdu_len) { packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ length=pdu_len; - } + } - ND_PRINT((ndo, "\n\t lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t chksum: 0x%04x", + ND_PRINT((ndo, "\n\t lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t chksum: 0x%04x", isis_print_id(header_lsp->lsp_id, LSP_ID_LEN), EXTRACT_32BITS(header_lsp->sequence_number), EXTRACT_16BITS(header_lsp->remaining_lifetime), EXTRACT_16BITS(header_lsp->checksum))); - if (osi_print_cksum(ndo, (const uint8_t *)header_lsp->lsp_id, - EXTRACT_16BITS(header_lsp->checksum), - 12, length-12) == 0) - goto trunc; + osi_print_cksum(ndo, (const uint8_t *)header_lsp->lsp_id, + EXTRACT_16BITS(header_lsp->checksum), + 12, length-12); - ND_PRINT((ndo, ", PDU length: %u, Flags: [ %s", + ND_PRINT((ndo, ", PDU length: %u, Flags: [ %s", pdu_len, ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "")); - if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) { - ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "")); - ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "")); - ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "")); - ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "")); - ND_PRINT((ndo, "ATT bit set, ")); - } - ND_PRINT((ndo, "%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "")); - ND_PRINT((ndo, "%s ]", tok2str(isis_lsp_istype_values, "Unknown(0x%x)", - ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)))); + if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) { + ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "")); + ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "")); + ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "")); + ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "")); + ND_PRINT((ndo, "ATT bit set, ")); + } + ND_PRINT((ndo, "%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "")); + ND_PRINT((ndo, "%s ]", tok2str(isis_lsp_istype_values, "Unknown(0x%x)", + ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)))); - if (ndo->ndo_vflag > 1) { - if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_LSP_HEADER_SIZE)) - return(0); - } + if (ndo->ndo_vflag > 1) { + if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_LSP_HEADER_SIZE)) + return (0); + } - packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE); - pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE); - break; + packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE); + pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE); + break; case ISIS_PDU_L1_CSNP: case ISIS_PDU_L2_CSNP: - if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) { - ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", - isis_header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE)); - return (0); - } - - ND_TCHECK(*header_csnp); - pdu_len=EXTRACT_16BITS(header_csnp->pdu_len); - if (packet_len>pdu_len) { + if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) { + ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", + isis_header->fixed_len, (unsigned long)(ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE))); + return (0); + } + ND_TCHECK(*header_csnp); + if (length < ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE) + goto trunc; + if (ndo->ndo_vflag == 0) { + ND_PRINT((ndo, ", src-id %s", isis_print_id(header_csnp->source_id, NODE_ID_LEN))); + ND_PRINT((ndo, ", length %u", length)); + return (1); + } + pdu_len=EXTRACT_16BITS(header_csnp->pdu_len); + if (packet_len>pdu_len) { packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ length=pdu_len; - } + } - ND_PRINT((ndo, "\n\t source-id: %s, PDU length: %u", + ND_PRINT((ndo, "\n\t source-id: %s, PDU length: %u", isis_print_id(header_csnp->source_id, NODE_ID_LEN), pdu_len)); - ND_PRINT((ndo, "\n\t start lsp-id: %s", + ND_PRINT((ndo, "\n\t start lsp-id: %s", isis_print_id(header_csnp->start_lsp_id, LSP_ID_LEN))); - ND_PRINT((ndo, "\n\t end lsp-id: %s", + ND_PRINT((ndo, "\n\t end lsp-id: %s", isis_print_id(header_csnp->end_lsp_id, LSP_ID_LEN))); - if (ndo->ndo_vflag > 1) { - if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_CSNP_HEADER_SIZE)) - return(0); - } + if (ndo->ndo_vflag > 1) { + if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_CSNP_HEADER_SIZE)) + return (0); + } - packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); - pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); + packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); + pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE); break; case ISIS_PDU_L1_PSNP: case ISIS_PDU_L2_PSNP: - if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) { - ND_PRINT((ndo, "- bogus fixed header length %u should be %lu", - isis_header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE)); - return (0); - } - - ND_TCHECK(*header_psnp); - pdu_len=EXTRACT_16BITS(header_psnp->pdu_len); - if (packet_len>pdu_len) { + if (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) { + ND_PRINT((ndo, "- bogus fixed header length %u should be %lu", + isis_header->fixed_len, (unsigned long)(ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE))); + return (0); + } + ND_TCHECK(*header_psnp); + if (length < ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE) + goto trunc; + if (ndo->ndo_vflag == 0) { + ND_PRINT((ndo, ", src-id %s", isis_print_id(header_psnp->source_id, NODE_ID_LEN))); + ND_PRINT((ndo, ", length %u", length)); + return (1); + } + pdu_len=EXTRACT_16BITS(header_psnp->pdu_len); + if (packet_len>pdu_len) { packet_len=pdu_len; /* do TLV decoding as long as it makes sense */ length=pdu_len; - } + } - ND_PRINT((ndo, "\n\t source-id: %s, PDU length: %u", + ND_PRINT((ndo, "\n\t source-id: %s, PDU length: %u", isis_print_id(header_psnp->source_id, NODE_ID_LEN), pdu_len)); - if (ndo->ndo_vflag > 1) { - if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_PSNP_HEADER_SIZE)) - return(0); - } + if (ndo->ndo_vflag > 1) { + if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_PSNP_HEADER_SIZE)) + return (0); + } - packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); - pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); - break; + packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); + pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); + break; default: + if (ndo->ndo_vflag == 0) { + ND_PRINT((ndo, ", length %u", length)); + return (1); + } (void)print_unknown_data(ndo, pptr, "\n\t ", length); return (0); } @@ -2498,20 +2545,15 @@ isis_print(netdissect_options *ndo, * Now print the TLV's. */ - while (packet_len >= 2) { - if (pptr == ndo->ndo_snapend) { - return (1); - } - + while (packet_len > 0) { ND_TCHECK2(*pptr, 2); + if (packet_len < 2) + goto trunc; tlv_type = *pptr++; tlv_len = *pptr++; tmp =tlv_len; /* copy temporary len & pointer to packet data */ tptr = pptr; packet_len -= 2; - if (tlv_len > packet_len) { - break; - } /* first lets see if we know the TLVs name*/ ND_PRINT((ndo, "\n\t %s TLV #%u, length: %u", @@ -2524,12 +2566,16 @@ isis_print(netdissect_options *ndo, if (tlv_len == 0) /* something is invalid */ continue; + if (packet_len < tlv_len) + goto trunc; + /* now check if we have a decoder otherwise do a hexdump at the end*/ switch (tlv_type) { case ISIS_TLV_AREA_ADDR: ND_TCHECK2(*tptr, 1); alen = *tptr++; while (tmp && alen < tmp) { + ND_TCHECK2(*tptr, alen); ND_PRINT((ndo, "\n\t Area address (length: %u): %s", alen, isonsap_string(ndo, tptr, alen))); @@ -2912,9 +2958,8 @@ isis_print(netdissect_options *ndo, * to avoid conflicts the checksum TLV is zeroed. * see rfc3358 for details */ - if (osi_print_cksum(ndo, optr, EXTRACT_16BITS(tptr), tptr-optr, - length) == 0) - goto trunc; + osi_print_cksum(ndo, optr, EXTRACT_16BITS(tptr), tptr-optr, + length); break; case ISIS_TLV_POI: @@ -3108,40 +3153,33 @@ isis_print(netdissect_options *ndo, return(1); } -static int +static void osi_print_cksum(netdissect_options *ndo, const uint8_t *pptr, - uint16_t checksum, int checksum_offset, int length) + uint16_t checksum, int checksum_offset, u_int length) { uint16_t calculated_checksum; /* do not attempt to verify the checksum if it is zero, - * if the total length is nonsense, * if the offset is nonsense, * or the base pointer is not sane */ if (!checksum - || length < 0 || checksum_offset < 0 - || length > ndo->ndo_snaplen - || checksum_offset > ndo->ndo_snaplen - || checksum_offset > length) { + || !ND_TTEST2(*(pptr + checksum_offset), 2) + || (u_int)checksum_offset > length + || !ND_TTEST2(*pptr, length)) { ND_PRINT((ndo, " (unverified)")); - return 1; } else { #if 0 - printf("\nosi_print_cksum: %p %u %u %u\n", pptr, checksum_offset, length, ndo->ndo_snaplen); + printf("\nosi_print_cksum: %p %u %u\n", pptr, checksum_offset, length); #endif - ND_TCHECK2(*pptr, length); calculated_checksum = create_osi_cksum(pptr, checksum_offset, length); if (checksum == calculated_checksum) { ND_PRINT((ndo, " (correct)")); } else { ND_PRINT((ndo, " (incorrect should be 0x%04x)", calculated_checksum)); } - return 1; } -trunc: - return 0; } /* diff --git a/freebsd/contrib/tcpdump/print-juniper.c b/freebsd/contrib/tcpdump/print-juniper.c index 647110ef..db252a9d 100644 --- a/freebsd/contrib/tcpdump/print-juniper.c +++ b/freebsd/contrib/tcpdump/print-juniper.c @@ -18,7 +18,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: DLT_JUNIPER_* printers */ @@ -478,6 +478,7 @@ juniper_ggsn_print(netdissect_options *ndo, p+=l2info.header_len; gh = (struct juniper_ggsn_header *)&l2info.cookie; + ND_TCHECK(*gh); if (ndo->ndo_eflag) { ND_PRINT((ndo, "proto %s (%u), vlan %u: ", tok2str(juniper_protocol_values,"Unknown",gh->proto), @@ -498,6 +499,10 @@ juniper_ggsn_print(netdissect_options *ndo, } return l2info.header_len; + +trunc: + ND_PRINT((ndo, "[|juniper_services]")); + return l2info.header_len; } #endif @@ -525,6 +530,7 @@ juniper_es_print(netdissect_options *ndo, p+=l2info.header_len; ih = (const struct juniper_ipsec_header *)p; + ND_TCHECK(*ih); switch (ih->type) { case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE: case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE: @@ -570,6 +576,10 @@ juniper_es_print(netdissect_options *ndo, ip_print(ndo, p, l2info.length); return l2info.header_len; + +trunc: + ND_PRINT((ndo, "[|juniper_services]")); + return l2info.header_len; } #endif @@ -594,6 +604,7 @@ juniper_monitor_print(netdissect_options *ndo, p+=l2info.header_len; mh = (const struct juniper_monitor_header *)p; + ND_TCHECK(*mh); if (ndo->ndo_eflag) ND_PRINT((ndo, "service-id %u, iif %u, pkt-type %u: ", EXTRACT_32BITS(&mh->service_id), @@ -604,6 +615,10 @@ juniper_monitor_print(netdissect_options *ndo, ip_heuristic_guess (ndo, p, l2info.length); return l2info.header_len; + +trunc: + ND_PRINT((ndo, "[|juniper_services]")); + return l2info.header_len; } #endif @@ -628,6 +643,7 @@ juniper_services_print(netdissect_options *ndo, p+=l2info.header_len; sh = (const struct juniper_services_header *)p; + ND_TCHECK(*sh); if (ndo->ndo_eflag) ND_PRINT((ndo, "service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ", sh->svc_id, @@ -639,6 +655,10 @@ juniper_services_print(netdissect_options *ndo, ip_heuristic_guess (ndo, p, l2info.length); return l2info.header_len; + +trunc: + ND_PRINT((ndo, "[|juniper_services]")); + return l2info.header_len; } #endif @@ -746,6 +766,7 @@ juniper_pppoe_atm_print(netdissect_options *ndo, p+=l2info.header_len; + ND_TCHECK2(p[0], 2); extracted_ethertype = EXTRACT_16BITS(p); /* this DLT contains nothing but raw PPPoE frames, * prepended with a type field*/ @@ -758,6 +779,10 @@ juniper_pppoe_atm_print(netdissect_options *ndo, ND_PRINT((ndo, "unknown ethertype 0x%04x", extracted_ethertype)); return l2info.header_len; + +trunc: + ND_PRINT((ndo, "[|juniper_pppoe_atm]")); + return l2info.header_len; } #endif @@ -799,7 +824,7 @@ juniper_mlppp_print(netdissect_options *ndo, mpls_print(ndo, p, l2info.length); return l2info.header_len; case JUNIPER_LSQ_L3_PROTO_ISO: - isoclns_print(ndo, p, l2info.length, l2info.caplen); + isoclns_print(ndo, p, l2info.length); return l2info.header_len; default: break; @@ -854,7 +879,7 @@ juniper_mfr_print(netdissect_options *ndo, mpls_print(ndo, p, l2info.length); return l2info.header_len; case JUNIPER_LSQ_L3_PROTO_ISO: - isoclns_print(ndo, p, l2info.length, l2info.caplen); + isoclns_print(ndo, p, l2info.length); return l2info.header_len; default: break; @@ -867,13 +892,13 @@ juniper_mfr_print(netdissect_options *ndo, ND_PRINT((ndo, "Bundle-ID %u, ", l2info.bundle)); switch (l2info.proto) { case (LLCSAP_ISONS<<8 | LLCSAP_ISONS): - isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 1); + isoclns_print(ndo, p + 1, l2info.length - 1); break; case (LLC_UI<<8 | NLPID_Q933): case (LLC_UI<<8 | NLPID_IP): case (LLC_UI<<8 | NLPID_IP6): /* pass IP{4,6} to the OSI layer for proper link-layer printing */ - isoclns_print(ndo, p - 1, l2info.length + 1, l2info.caplen + 1); + isoclns_print(ndo, p - 1, l2info.length + 1); break; default: ND_PRINT((ndo, "unknown protocol 0x%04x, length %u", l2info.proto, l2info.length)); @@ -902,13 +927,13 @@ juniper_mlfr_print(netdissect_options *ndo, switch (l2info.proto) { case (LLC_UI): case (LLC_UI<<8): - isoclns_print(ndo, p, l2info.length, l2info.caplen); + isoclns_print(ndo, p, l2info.length); break; case (LLC_UI<<8 | NLPID_Q933): case (LLC_UI<<8 | NLPID_IP): case (LLC_UI<<8 | NLPID_IP6): /* pass IP{4,6} to the OSI layer for proper link-layer printing */ - isoclns_print(ndo, p - 1, l2info.length + 1, l2info.caplen + 1); + isoclns_print(ndo, p - 1, l2info.length + 1); break; default: ND_PRINT((ndo, "unknown protocol 0x%04x, length %u", l2info.proto, l2info.length)); @@ -946,6 +971,7 @@ juniper_atm1_print(netdissect_options *ndo, return l2info.header_len; } + ND_TCHECK2(p[0], 3); if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */ EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */ @@ -955,7 +981,7 @@ juniper_atm1_print(netdissect_options *ndo, } if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */ - isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 1); + isoclns_print(ndo, p + 1, l2info.length - 1); /* FIXME check if frame was recognized */ return l2info.header_len; } @@ -964,6 +990,10 @@ juniper_atm1_print(netdissect_options *ndo, return l2info.header_len; return l2info.header_len; + +trunc: + ND_PRINT((ndo, "[|juniper_atm1]")); + return l2info.header_len; } #endif @@ -995,6 +1025,7 @@ juniper_atm2_print(netdissect_options *ndo, return l2info.header_len; } + ND_TCHECK2(p[0], 3); if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */ EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */ @@ -1010,7 +1041,7 @@ juniper_atm2_print(netdissect_options *ndo, } if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */ - isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 1); + isoclns_print(ndo, p + 1, l2info.length - 1); /* FIXME check if frame was recognized */ return l2info.header_len; } @@ -1022,6 +1053,10 @@ juniper_atm2_print(netdissect_options *ndo, return l2info.header_len; return l2info.header_len; + +trunc: + ND_PRINT((ndo, "[|juniper_atm2]")); + return l2info.header_len; } #endif @@ -1286,6 +1321,7 @@ juniper_parse_header(netdissect_options *ndo, l2info->caplen -= l2info->header_len; /* search through the cookie table and copy values matching for our PIC type */ + ND_TCHECK(p[0]); while (lp->s != NULL) { if (lp->pictype == l2info->pictype) { @@ -1337,6 +1373,7 @@ juniper_parse_header(netdissect_options *ndo, if (ndo->ndo_eflag) ND_PRINT((ndo, ": ")); /* print demarc b/w L2/L3*/ + ND_TCHECK_16BITS(p+l2info->cookie_len); l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len); break; } @@ -1366,6 +1403,7 @@ juniper_parse_header(netdissect_options *ndo, case DLT_JUNIPER_MLFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: + ND_TCHECK2(p[0], 2); l2info->bundle = l2info->cookie[1]; l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; @@ -1389,6 +1427,7 @@ juniper_parse_header(netdissect_options *ndo, case DLT_JUNIPER_MFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: + ND_TCHECK2(p[0], 2); l2info->bundle = l2info->cookie[1]; l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; diff --git a/freebsd/contrib/tcpdump/print-l2tp.c b/freebsd/contrib/tcpdump/print-l2tp.c index a4ea2061..f2100fa7 100644 --- a/freebsd/contrib/tcpdump/print-l2tp.c +++ b/freebsd/contrib/tcpdump/print-l2tp.c @@ -303,10 +303,14 @@ print_32bits_val(netdissect_options *ndo, const uint32_t *dat) /* AVP-specific print out routines */ /***********************************/ static void -l2tp_msgtype_print(netdissect_options *ndo, const u_char *dat) +l2tp_msgtype_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint16_t *ptr = (const uint16_t *)dat; + if (length < 2) { + ND_PRINT((ndo, "AVP too short")); + return; + } ND_PRINT((ndo, "%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u", EXTRACT_16BITS(ptr)))); } @@ -316,28 +320,53 @@ l2tp_result_code_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint16_t *ptr = (const uint16_t *)dat; - ND_PRINT((ndo, "%u", EXTRACT_16BITS(ptr))); ptr++; /* Result Code */ - if (length > 2) { /* Error Code (opt) */ - ND_PRINT((ndo, "/%u", EXTRACT_16BITS(ptr))); ptr++; + /* Result Code */ + if (length < 2) { + ND_PRINT((ndo, "AVP too short")); + return; } - if (length > 4) { /* Error Message (opt) */ - ND_PRINT((ndo, " ")); - print_string(ndo, (const u_char *)ptr, length - 4); + ND_PRINT((ndo, "%u", EXTRACT_16BITS(ptr))); + ptr++; + length -= 2; + + /* Error Code (opt) */ + if (length == 0) + return; + if (length < 2) { + ND_PRINT((ndo, " AVP too short")); + return; } + ND_PRINT((ndo, "/%u", EXTRACT_16BITS(ptr))); + ptr++; + length -= 2; + + /* Error Message (opt) */ + if (length == 0) + return; + ND_PRINT((ndo, " ")); + print_string(ndo, (const u_char *)ptr, length); } static void -l2tp_proto_ver_print(netdissect_options *ndo, const uint16_t *dat) +l2tp_proto_ver_print(netdissect_options *ndo, const uint16_t *dat, u_int length) { + if (length < 2) { + ND_PRINT((ndo, "AVP too short")); + return; + } ND_PRINT((ndo, "%u.%u", (EXTRACT_16BITS(dat) >> 8), (EXTRACT_16BITS(dat) & 0xff))); } static void -l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat) +l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint32_t *ptr = (const uint32_t *)dat; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } if (EXTRACT_32BITS(ptr) & L2TP_FRAMING_CAP_ASYNC_MASK) { ND_PRINT((ndo, "A")); } @@ -347,10 +376,14 @@ l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat) } static void -l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat) +l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint32_t *ptr = (const uint32_t *)dat; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } if (EXTRACT_32BITS(ptr) & L2TP_BEARER_CAP_ANALOG_MASK) { ND_PRINT((ndo, "A")); } @@ -362,19 +395,29 @@ l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat) static void l2tp_q931_cc_print(netdissect_options *ndo, const u_char *dat, u_int length) { + if (length < 3) { + ND_PRINT((ndo, "AVP too short")); + return; + } print_16bits_val(ndo, (const uint16_t *)dat); ND_PRINT((ndo, ", %02x", dat[2])); - if (length > 3) { + dat += 3; + length -= 3; + if (length != 0) { ND_PRINT((ndo, " ")); - print_string(ndo, dat+3, length-3); + print_string(ndo, dat, length); } } static void -l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat) +l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint32_t *ptr = (const uint32_t *)dat; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } if (EXTRACT_32BITS(ptr) & L2TP_BEARER_TYPE_ANALOG_MASK) { ND_PRINT((ndo, "A")); } @@ -384,10 +427,14 @@ l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat) } static void -l2tp_framing_type_print(netdissect_options *ndo, const u_char *dat) +l2tp_framing_type_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint32_t *ptr = (const uint32_t *)dat; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } if (EXTRACT_32BITS(ptr) & L2TP_FRAMING_TYPE_ASYNC_MASK) { ND_PRINT((ndo, "A")); } @@ -403,67 +450,117 @@ l2tp_packet_proc_delay_print(netdissect_options *ndo) } static void -l2tp_proxy_auth_type_print(netdissect_options *ndo, const u_char *dat) +l2tp_proxy_auth_type_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint16_t *ptr = (const uint16_t *)dat; + if (length < 2) { + ND_PRINT((ndo, "AVP too short")); + return; + } ND_PRINT((ndo, "%s", tok2str(l2tp_authentype2str, "AuthType-#%u", EXTRACT_16BITS(ptr)))); } static void -l2tp_proxy_auth_id_print(netdissect_options *ndo, const u_char *dat) +l2tp_proxy_auth_id_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint16_t *ptr = (const uint16_t *)dat; + if (length < 2) { + ND_PRINT((ndo, "AVP too short")); + return; + } ND_PRINT((ndo, "%u", EXTRACT_16BITS(ptr) & L2TP_PROXY_AUTH_ID_MASK)); } static void -l2tp_call_errors_print(netdissect_options *ndo, const u_char *dat) +l2tp_call_errors_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint16_t *ptr = (const uint16_t *)dat; uint16_t val_h, val_l; + if (length < 2) { + ND_PRINT((ndo, "AVP too short")); + return; + } ptr++; /* skip "Reserved" */ + length -= 2; - val_h = EXTRACT_16BITS(ptr); ptr++; - val_l = EXTRACT_16BITS(ptr); ptr++; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } + val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2; + val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2; ND_PRINT((ndo, "CRCErr=%u ", (val_h<<16) + val_l)); - val_h = EXTRACT_16BITS(ptr); ptr++; - val_l = EXTRACT_16BITS(ptr); ptr++; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } + val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2; + val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2; ND_PRINT((ndo, "FrameErr=%u ", (val_h<<16) + val_l)); - val_h = EXTRACT_16BITS(ptr); ptr++; - val_l = EXTRACT_16BITS(ptr); ptr++; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } + val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2; + val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2; ND_PRINT((ndo, "HardOver=%u ", (val_h<<16) + val_l)); - val_h = EXTRACT_16BITS(ptr); ptr++; - val_l = EXTRACT_16BITS(ptr); ptr++; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } + val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2; + val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2; ND_PRINT((ndo, "BufOver=%u ", (val_h<<16) + val_l)); - val_h = EXTRACT_16BITS(ptr); ptr++; - val_l = EXTRACT_16BITS(ptr); ptr++; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } + val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2; + val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2; ND_PRINT((ndo, "Timeout=%u ", (val_h<<16) + val_l)); + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } val_h = EXTRACT_16BITS(ptr); ptr++; val_l = EXTRACT_16BITS(ptr); ptr++; ND_PRINT((ndo, "AlignErr=%u ", (val_h<<16) + val_l)); } static void -l2tp_accm_print(netdissect_options *ndo, const u_char *dat) +l2tp_accm_print(netdissect_options *ndo, const u_char *dat, u_int length) { const uint16_t *ptr = (const uint16_t *)dat; uint16_t val_h, val_l; + if (length < 2) { + ND_PRINT((ndo, "AVP too short")); + return; + } ptr++; /* skip "Reserved" */ + length -= 2; - val_h = EXTRACT_16BITS(ptr); ptr++; - val_l = EXTRACT_16BITS(ptr); ptr++; + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } + val_h = EXTRACT_16BITS(ptr); ptr++; length -= 2; + val_l = EXTRACT_16BITS(ptr); ptr++; length -= 2; ND_PRINT((ndo, "send=%08x ", (val_h<<16) + val_l)); + if (length < 4) { + ND_PRINT((ndo, "AVP too short")); + return; + } val_h = EXTRACT_16BITS(ptr); ptr++; val_l = EXTRACT_16BITS(ptr); ptr++; ND_PRINT((ndo, "recv=%08x ", (val_h<<16) + val_l)); @@ -474,14 +571,27 @@ l2tp_ppp_discon_cc_print(netdissect_options *ndo, const u_char *dat, u_int lengt { const uint16_t *ptr = (const uint16_t *)dat; - ND_PRINT((ndo, "%04x, ", EXTRACT_16BITS(ptr))); ptr++; /* Disconnect Code */ - ND_PRINT((ndo, "%04x ", EXTRACT_16BITS(ptr))); ptr++; /* Control Protocol Number */ + if (length < 5) { + ND_PRINT((ndo, "AVP too short")); + return; + } + /* Disconnect Code */ + ND_PRINT((ndo, "%04x, ", EXTRACT_16BITS(dat))); + dat += 2; + length -= 2; + /* Control Protocol Number */ + ND_PRINT((ndo, "%04x ", EXTRACT_16BITS(dat))); + dat += 2; + length -= 2; + /* Direction */ ND_PRINT((ndo, "%s", tok2str(l2tp_cc_direction2str, - "Direction-#%u", *((const u_char *)ptr++)))); + "Direction-#%u", EXTRACT_8BITS(ptr)))); + ptr++; + length--; - if (length > 5) { + if (length != 0) { ND_PRINT((ndo, " ")); - print_string(ndo, (const u_char *)ptr, length-5); + print_string(ndo, (const u_char *)ptr, length); } } @@ -514,7 +624,12 @@ l2tp_avp_print(netdissect_options *ndo, const u_char *dat, int length) /* If it goes past the end of the remaining length of the captured data, we'll give up. */ ND_TCHECK2(*ptr, len); - /* After this point, no need to worry about truncation */ + + /* + * After this point, we don't need to check whether we go past + * the length of the captured data; however, we *do* need to + * check whether we go past the end of the AVP. + */ if (EXTRACT_16BITS(ptr) & L2TP_AVP_HDR_FLAG_MANDATORY) { ND_PRINT((ndo, "*")); @@ -543,27 +658,35 @@ l2tp_avp_print(netdissect_options *ndo, const u_char *dat, int length) } else { switch (attr_type) { case L2TP_AVP_MSGTYPE: - l2tp_msgtype_print(ndo, (const u_char *)ptr); + l2tp_msgtype_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_RESULT_CODE: l2tp_result_code_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_PROTO_VER: - l2tp_proto_ver_print(ndo, ptr); + l2tp_proto_ver_print(ndo, ptr, len-6); break; case L2TP_AVP_FRAMING_CAP: - l2tp_framing_cap_print(ndo, (const u_char *)ptr); + l2tp_framing_cap_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_BEARER_CAP: - l2tp_bearer_cap_print(ndo, (const u_char *)ptr); + l2tp_bearer_cap_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_TIE_BREAKER: + if (len-6 < 8) { + ND_PRINT((ndo, "AVP too short")); + break; + } print_octets(ndo, (const u_char *)ptr, 8); break; case L2TP_AVP_FIRM_VER: case L2TP_AVP_ASSND_TUN_ID: case L2TP_AVP_RECV_WIN_SIZE: case L2TP_AVP_ASSND_SESS_ID: + if (len-6 < 2) { + ND_PRINT((ndo, "AVP too short")); + break; + } print_16bits_val(ndo, ptr); break; case L2TP_AVP_HOST_NAME: @@ -588,6 +711,10 @@ l2tp_avp_print(netdissect_options *ndo, const u_char *dat, int length) l2tp_q931_cc_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_CHALLENGE_RESP: + if (len-6 < 16) { + ND_PRINT((ndo, "AVP too short")); + break; + } print_octets(ndo, (const u_char *)ptr, 16); break; case L2TP_AVP_CALL_SER_NUM: @@ -596,28 +723,32 @@ l2tp_avp_print(netdissect_options *ndo, const u_char *dat, int length) case L2TP_AVP_TX_CONN_SPEED: case L2TP_AVP_PHY_CHANNEL_ID: case L2TP_AVP_RX_CONN_SPEED: + if (len-6 < 4) { + ND_PRINT((ndo, "AVP too short")); + break; + } print_32bits_val(ndo, (const uint32_t *)ptr); break; case L2TP_AVP_BEARER_TYPE: - l2tp_bearer_type_print(ndo, (const u_char *)ptr); + l2tp_bearer_type_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_FRAMING_TYPE: - l2tp_framing_type_print(ndo, (const u_char *)ptr); + l2tp_framing_type_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_PACKET_PROC_DELAY: l2tp_packet_proc_delay_print(ndo); break; case L2TP_AVP_PROXY_AUTH_TYPE: - l2tp_proxy_auth_type_print(ndo, (const u_char *)ptr); + l2tp_proxy_auth_type_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_PROXY_AUTH_ID: - l2tp_proxy_auth_id_print(ndo, (const u_char *)ptr); + l2tp_proxy_auth_id_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_CALL_ERRORS: - l2tp_call_errors_print(ndo, (const u_char *)ptr); + l2tp_call_errors_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_ACCM: - l2tp_accm_print(ndo, (const u_char *)ptr); + l2tp_accm_print(ndo, (const u_char *)ptr, len-6); break; case L2TP_AVP_SEQ_REQUIRED: break; /* No Attribute Value */ diff --git a/freebsd/contrib/tcpdump/print-ldp.c b/freebsd/contrib/tcpdump/print-ldp.c index 6fe626f8..b0975868 100644 --- a/freebsd/contrib/tcpdump/print-ldp.c +++ b/freebsd/contrib/tcpdump/print-ldp.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) * and Steinar Haug (sthaug@nethelp.no) */ diff --git a/freebsd/contrib/tcpdump/print-llc.c b/freebsd/contrib/tcpdump/print-llc.c index 210bc908..f243f468 100644 --- a/freebsd/contrib/tcpdump/print-llc.c +++ b/freebsd/contrib/tcpdump/print-llc.c @@ -330,7 +330,7 @@ llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, #endif if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS && control == LLC_UI) { - isoclns_print(ndo, p, length, caplen); + isoclns_print(ndo, p, length); return (hdrlen); } diff --git a/freebsd/contrib/tcpdump/print-lldp.c b/freebsd/contrib/tcpdump/print-lldp.c index b48cb3cc..213fd57e 100644 --- a/freebsd/contrib/tcpdump/print-lldp.c +++ b/freebsd/contrib/tcpdump/print-lldp.c @@ -18,7 +18,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) * IEEE and TIA extensions by Carles Kishimoto <carles.kishimoto@gmail.com> * DCBX extensions by Kaladhar Musunuru <kaladharm@sourceforge.net> */ @@ -596,6 +596,7 @@ static const struct tok lldp_evb_mode_values[]={ { LLDP_EVB_MODE_EVB_BRIDGE, "EVB Bridge"}, { LLDP_EVB_MODE_EVB_STATION, "EVB Staion"}, { LLDP_EVB_MODE_RESERVED, "Reserved for future Standardization"}, + { 0, NULL}, }; #define NO_OF_BITS 8 @@ -656,7 +657,7 @@ lldp_private_8021_print(netdissect_options *ndo, int subtype, hexdump = FALSE; u_int sublen; u_int tval; - uint8_t i; + u_int i; if (tlv_len < 4) { return hexdump; @@ -792,9 +793,9 @@ lldp_private_8021_print(netdissect_options *ndo, ND_PRINT((ndo, "\n\t Application Priority Table")); while(i<sublen) { tval=*(tptr+i+5); - ND_PRINT((ndo, "\n\t Priority: %d, RES: %d, Sel: %d", - tval >> 5, (tval >> 3) & 0x03, (tval & 0x07))); - ND_PRINT((ndo, "Protocol ID: %d", EXTRACT_16BITS(tptr + i + 5))); + ND_PRINT((ndo, "\n\t Priority: %u, RES: %u, Sel: %u, Protocol ID: %u", + tval >> 5, (tval >> 3) & 0x03, (tval & 0x07), + EXTRACT_16BITS(tptr + i + 5))); i=i+3; } break; @@ -903,6 +904,9 @@ lldp_private_8023_print(netdissect_options *ndo, break; case LLDP_PRIVATE_8023_SUBTYPE_MTU: + if (tlv_len < 6) { + return hexdump; + } ND_PRINT((ndo, "\n\t MTU size %u", EXTRACT_16BITS(tptr + 4))); break; @@ -932,7 +936,7 @@ lldp_extract_latlon(const u_char *tptr) * (right now there is only one) */ - + static int lldp_private_iana_print(netdissect_options *ndo, const u_char *tptr, u_int tlv_len) @@ -956,12 +960,12 @@ lldp_private_iana_print(netdissect_options *ndo, default: hexdump=TRUE; } - + return hexdump; } - + /* * Print private TIA extensions. */ @@ -1406,7 +1410,7 @@ lldp_mgmt_addr_tlv_print(netdissect_options *ndo, if (tlen) { oid_len = *tptr; - if (tlen < oid_len) { + if (tlen < 1U + oid_len) { return 0; } if (oid_len) { diff --git a/freebsd/contrib/tcpdump/print-lmp.c b/freebsd/contrib/tcpdump/print-lmp.c index 1ea898ee..031fdb96 100644 --- a/freebsd/contrib/tcpdump/print-lmp.c +++ b/freebsd/contrib/tcpdump/print-lmp.c @@ -16,14 +16,15 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) - * Support for LMP service discovery extensions (defined by UNI 1.0) added - * by Manu Pathak (mapathak@cisco.com), May 2005 + * Original code by Hannes Gredler (hannes@gredler.at) + * Support for LMP service discovery extensions (defined by OIF UNI 1.0) + * added by Manu Pathak (mapathak@cisco.com), May 2005 */ /* \summary: Link Management Protocol (LMP) printer */ /* specification: RFC 4204 */ +/* OIF UNI 1.0: http://www.oiforum.com/public/documents/OIF-UNI-01.0.pdf */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -359,6 +360,73 @@ static const struct tok lmp_ctype_values[] = { { 0, NULL} }; +static int +lmp_print_data_link_subobjs(netdissect_options *ndo, const u_char *obj_tptr, + int total_subobj_len, int offset) +{ + int hexdump = FALSE; + int subobj_type, subobj_len; + + union { /* int to float conversion buffer */ + float f; + uint32_t i; + } bw; + + while (total_subobj_len > 0 && hexdump == FALSE ) { + subobj_type = EXTRACT_8BITS(obj_tptr+offset); + subobj_len = EXTRACT_8BITS(obj_tptr+offset+1); + ND_PRINT((ndo, "\n\t Subobject, Type: %s (%u), Length: %u", + tok2str(lmp_data_link_subobj, + "Unknown", + subobj_type), + subobj_type, + subobj_len)); + if (subobj_len < 4) { + ND_PRINT((ndo, " (too short)")); + break; + } + if ((subobj_len % 4) != 0) { + ND_PRINT((ndo, " (not a multiple of 4)")); + break; + } + if (total_subobj_len < subobj_len) { + ND_PRINT((ndo, " (goes past the end of the object)")); + break; + } + switch(subobj_type) { + case INT_SWITCHING_TYPE_SUBOBJ: + ND_PRINT((ndo, "\n\t Switching Type: %s (%u)", + tok2str(gmpls_switch_cap_values, + "Unknown", + EXTRACT_8BITS(obj_tptr+offset+2)), + EXTRACT_8BITS(obj_tptr+offset+2))); + ND_PRINT((ndo, "\n\t Encoding Type: %s (%u)", + tok2str(gmpls_encoding_values, + "Unknown", + EXTRACT_8BITS(obj_tptr+offset+3)), + EXTRACT_8BITS(obj_tptr+offset+3))); + bw.i = EXTRACT_32BITS(obj_tptr+offset+4); + ND_PRINT((ndo, "\n\t Min Reservable Bandwidth: %.3f Mbps", + bw.f*8/1000000)); + bw.i = EXTRACT_32BITS(obj_tptr+offset+8); + ND_PRINT((ndo, "\n\t Max Reservable Bandwidth: %.3f Mbps", + bw.f*8/1000000)); + break; + case WAVELENGTH_SUBOBJ: + ND_PRINT((ndo, "\n\t Wavelength: %u", + EXTRACT_32BITS(obj_tptr+offset+4))); + break; + default: + /* Any Unknown Subobject ==> Exit loop */ + hexdump=TRUE; + break; + } + total_subobj_len-=subobj_len; + offset+=subobj_len; + } + return (hexdump); +} + void lmp_print(netdissect_options *ndo, register const u_char *pptr, register u_int len) @@ -366,10 +434,10 @@ lmp_print(netdissect_options *ndo, const struct lmp_common_header *lmp_com_header; const struct lmp_object_header *lmp_obj_header; const u_char *tptr,*obj_tptr; - int tlen,lmp_obj_len,lmp_obj_ctype,obj_tlen; + u_int tlen,lmp_obj_len,lmp_obj_ctype,obj_tlen; int hexdump; - int offset,subobj_type,subobj_len,total_subobj_len; - int link_type; + u_int offset; + u_int link_type; union { /* int to float conversion buffer */ float f; @@ -407,6 +475,14 @@ lmp_print(netdissect_options *ndo, tok2str(lmp_msg_type_values, "unknown, type: %u",lmp_com_header->msg_type), bittok2str(lmp_header_flag_values,"none",lmp_com_header->flags), tlen)); + if (tlen < sizeof(const struct lmp_common_header)) { + ND_PRINT((ndo, " (too short)")); + return; + } + if (tlen > len) { + ND_PRINT((ndo, " (too long)")); + tlen = len; + } tptr+=sizeof(const struct lmp_common_header); tlen-=sizeof(const struct lmp_common_header); @@ -419,9 +495,6 @@ lmp_print(netdissect_options *ndo, lmp_obj_len=EXTRACT_16BITS(lmp_obj_header->length); lmp_obj_ctype=(lmp_obj_header->ctype)&0x7f; - if(lmp_obj_len % 4 || lmp_obj_len < 4) - return; - ND_PRINT((ndo, "\n\t %s Object (%u), Class-Type: %s (%u) Flags: [%snegotiable], length: %u", tok2str(lmp_obj_values, "Unknown", @@ -434,6 +507,15 @@ lmp_print(netdissect_options *ndo, (lmp_obj_header->ctype)&0x80 ? "" : "non-", lmp_obj_len)); + if (lmp_obj_len < 4) { + ND_PRINT((ndo, " (too short)")); + return; + } + if ((lmp_obj_len % 4) != 0) { + ND_PRINT((ndo, " (not a multiple of 4)")); + return; + } + obj_tptr=tptr+sizeof(struct lmp_object_header); obj_tlen=lmp_obj_len-sizeof(struct lmp_object_header); @@ -447,6 +529,10 @@ lmp_print(netdissect_options *ndo, switch(lmp_obj_ctype) { case LMP_CTYPE_LOC: case LMP_CTYPE_RMT: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Control Channel ID: %u (0x%08x)", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr))); @@ -462,18 +548,30 @@ lmp_print(netdissect_options *ndo, switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4_LOC: case LMP_CTYPE_IPV4_RMT: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t IPv4 Link ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr), EXTRACT_32BITS(obj_tptr))); break; case LMP_CTYPE_IPV6_LOC: case LMP_CTYPE_IPV6_RMT: + if (obj_tlen != 16) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t IPv6 Link ID: %s (0x%08x)", ip6addr_string(ndo, obj_tptr), EXTRACT_32BITS(obj_tptr))); break; case LMP_CTYPE_UNMD_LOC: case LMP_CTYPE_UNMD_RMT: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Link ID: %u (0x%08x)", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr))); @@ -486,11 +584,19 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_MESSAGE_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_1: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Message ID: %u (0x%08x)", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr))); break; case LMP_CTYPE_2: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Message ID Ack: %u (0x%08x)", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr))); @@ -504,6 +610,10 @@ lmp_print(netdissect_options *ndo, switch(lmp_obj_ctype) { case LMP_CTYPE_LOC: case LMP_CTYPE_RMT: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Node ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr), EXTRACT_32BITS(obj_tptr))); @@ -517,6 +627,10 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_CONFIG: switch(lmp_obj_ctype) { case LMP_CTYPE_HELLO_CONFIG: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Hello Interval: %u\n\t Hello Dead Interval: %u", EXTRACT_16BITS(obj_tptr), EXTRACT_16BITS(obj_tptr+2))); @@ -530,6 +644,10 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_HELLO: switch(lmp_obj_ctype) { case LMP_CTYPE_HELLO: + if (obj_tlen != 8) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Tx Seq: %u, Rx Seq: %u", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr+4))); @@ -541,13 +659,17 @@ lmp_print(netdissect_options *ndo, break; case LMP_OBJ_TE_LINK: + switch(lmp_obj_ctype) { + case LMP_CTYPE_IPV4: + if (obj_tlen != 12) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Flags: [%s]", - bittok2str(lmp_obj_te_link_flag_values, + bittok2str(lmp_obj_te_link_flag_values, "none", - EXTRACT_16BITS(obj_tptr)>>8))); + EXTRACT_8BITS(obj_tptr)))); - switch(lmp_obj_ctype) { - case LMP_CTYPE_IPV4: ND_PRINT((ndo, "\n\t Local Link-ID: %s (0x%08x)" "\n\t Remote Link-ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+4), @@ -557,21 +679,57 @@ lmp_print(netdissect_options *ndo, break; case LMP_CTYPE_IPV6: + if (obj_tlen != 36) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } + ND_PRINT((ndo, "\n\t Flags: [%s]", + bittok2str(lmp_obj_te_link_flag_values, + "none", + EXTRACT_8BITS(obj_tptr)))); + + ND_PRINT((ndo, "\n\t Local Link-ID: %s (0x%08x)" + "\n\t Remote Link-ID: %s (0x%08x)", + ip6addr_string(ndo, obj_tptr+4), + EXTRACT_32BITS(obj_tptr+4), + ip6addr_string(ndo, obj_tptr+20), + EXTRACT_32BITS(obj_tptr+20))); + break; + case LMP_CTYPE_UNMD: + if (obj_tlen != 12) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } + ND_PRINT((ndo, "\n\t Flags: [%s]", + bittok2str(lmp_obj_te_link_flag_values, + "none", + EXTRACT_8BITS(obj_tptr)))); + + ND_PRINT((ndo, "\n\t Local Link-ID: %u (0x%08x)" + "\n\t Remote Link-ID: %u (0x%08x)", + EXTRACT_32BITS(obj_tptr+4), + EXTRACT_32BITS(obj_tptr+4), + EXTRACT_32BITS(obj_tptr+8), + EXTRACT_32BITS(obj_tptr+8))); + break; + default: hexdump=TRUE; } break; case LMP_OBJ_DATA_LINK: - ND_PRINT((ndo, "\n\t Flags: [%s]", - bittok2str(lmp_obj_data_link_flag_values, - "none", - EXTRACT_16BITS(obj_tptr)>>8))); - switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: - case LMP_CTYPE_UNMD: + if (obj_tlen < 12) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } + ND_PRINT((ndo, "\n\t Flags: [%s]", + bittok2str(lmp_obj_data_link_flag_values, + "none", + EXTRACT_8BITS(obj_tptr)))); ND_PRINT((ndo, "\n\t Local Interface ID: %s (0x%08x)" "\n\t Remote Interface ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+4), @@ -579,51 +737,50 @@ lmp_print(netdissect_options *ndo, ipaddr_string(ndo, obj_tptr+8), EXTRACT_32BITS(obj_tptr+8))); - total_subobj_len = lmp_obj_len - 16; - offset = 12; - while (total_subobj_len > 0 && hexdump == FALSE ) { - subobj_type = EXTRACT_16BITS(obj_tptr+offset)>>8; - subobj_len = EXTRACT_16BITS(obj_tptr+offset)&0x00FF; - ND_PRINT((ndo, "\n\t Subobject, Type: %s (%u), Length: %u", - tok2str(lmp_data_link_subobj, - "Unknown", - subobj_type), - subobj_type, - subobj_len)); - switch(subobj_type) { - case INT_SWITCHING_TYPE_SUBOBJ: - ND_PRINT((ndo, "\n\t Switching Type: %s (%u)", - tok2str(gmpls_switch_cap_values, - "Unknown", - EXTRACT_16BITS(obj_tptr+offset+2)>>8), - EXTRACT_16BITS(obj_tptr+offset+2)>>8)); - ND_PRINT((ndo, "\n\t Encoding Type: %s (%u)", - tok2str(gmpls_encoding_values, - "Unknown", - EXTRACT_16BITS(obj_tptr+offset+2)&0x00FF), - EXTRACT_16BITS(obj_tptr+offset+2)&0x00FF)); - bw.i = EXTRACT_32BITS(obj_tptr+offset+4); - ND_PRINT((ndo, "\n\t Min Reservable Bandwidth: %.3f Mbps", - bw.f*8/1000000)); - bw.i = EXTRACT_32BITS(obj_tptr+offset+8); - ND_PRINT((ndo, "\n\t Max Reservable Bandwidth: %.3f Mbps", - bw.f*8/1000000)); - break; - case WAVELENGTH_SUBOBJ: - ND_PRINT((ndo, "\n\t Wavelength: %u", - EXTRACT_32BITS(obj_tptr+offset+4))); - break; - default: - /* Any Unknown Subobject ==> Exit loop */ - hexdump=TRUE; - break; - } - total_subobj_len-=subobj_len; - offset+=subobj_len; - } - + if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12)) + hexdump=TRUE; break; + case LMP_CTYPE_IPV6: + if (obj_tlen < 36) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } + ND_PRINT((ndo, "\n\t Flags: [%s]", + bittok2str(lmp_obj_data_link_flag_values, + "none", + EXTRACT_8BITS(obj_tptr)))); + ND_PRINT((ndo, "\n\t Local Interface ID: %s (0x%08x)" + "\n\t Remote Interface ID: %s (0x%08x)", + ip6addr_string(ndo, obj_tptr+4), + EXTRACT_32BITS(obj_tptr+4), + ip6addr_string(ndo, obj_tptr+20), + EXTRACT_32BITS(obj_tptr+20))); + + if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 36, 36)) + hexdump=TRUE; + break; + + case LMP_CTYPE_UNMD: + if (obj_tlen < 12) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } + ND_PRINT((ndo, "\n\t Flags: [%s]", + bittok2str(lmp_obj_data_link_flag_values, + "none", + EXTRACT_8BITS(obj_tptr)))); + ND_PRINT((ndo, "\n\t Local Interface ID: %u (0x%08x)" + "\n\t Remote Interface ID: %u (0x%08x)", + EXTRACT_32BITS(obj_tptr+4), + EXTRACT_32BITS(obj_tptr+4), + EXTRACT_32BITS(obj_tptr+8), + EXTRACT_32BITS(obj_tptr+8))); + + if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12)) + hexdump=TRUE; + break; + default: hexdump=TRUE; } @@ -632,6 +789,10 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_VERIFY_BEGIN: switch(lmp_obj_ctype) { case LMP_CTYPE_1: + if (obj_tlen != 20) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Flags: %s", bittok2str(lmp_obj_begin_verify_flag_values, "none", @@ -660,6 +821,10 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_VERIFY_BEGIN_ACK: switch(lmp_obj_ctype) { case LMP_CTYPE_1: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Verify Dead Interval: %u" "\n\t Verify Transport Response: %u", EXTRACT_16BITS(obj_tptr), @@ -674,6 +839,10 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_VERIFY_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_1: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Verify ID: %u", EXTRACT_32BITS(obj_tptr))); break; @@ -686,19 +855,20 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_CHANNEL_STATUS: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: - case LMP_CTYPE_UNMD: offset = 0; /* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */ - while (offset < (lmp_obj_len-(int)sizeof(struct lmp_object_header)) ) { + while (offset+8 <= obj_tlen) { ND_PRINT((ndo, "\n\t Interface ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+offset), EXTRACT_32BITS(obj_tptr+offset))); - ND_PRINT((ndo, "\n\t\t Active: %s (%u)", (EXTRACT_32BITS(obj_tptr+offset+4)>>31) ? + ND_PRINT((ndo, "\n\t\t Active: %s (%u)", + (EXTRACT_32BITS(obj_tptr+offset+4)>>31) ? "Allocated" : "Non-allocated", (EXTRACT_32BITS(obj_tptr+offset+4)>>31))); - ND_PRINT((ndo, "\n\t\t Direction: %s (%u)", (EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1 ? + ND_PRINT((ndo, "\n\t\t Direction: %s (%u)", + (EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1 ? "Transmit" : "Receive", (EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1)); @@ -710,7 +880,61 @@ lmp_print(netdissect_options *ndo, offset+=8; } break; + case LMP_CTYPE_IPV6: + offset = 0; + /* Decode pairs: <Interface_ID (16 bytes), Channel_status (4 bytes)> */ + while (offset+20 <= obj_tlen) { + ND_PRINT((ndo, "\n\t Interface ID: %s (0x%08x)", + ip6addr_string(ndo, obj_tptr+offset), + EXTRACT_32BITS(obj_tptr+offset))); + + ND_PRINT((ndo, "\n\t\t Active: %s (%u)", + (EXTRACT_32BITS(obj_tptr+offset+16)>>31) ? + "Allocated" : "Non-allocated", + (EXTRACT_32BITS(obj_tptr+offset+16)>>31))); + + ND_PRINT((ndo, "\n\t\t Direction: %s (%u)", + (EXTRACT_32BITS(obj_tptr+offset+16)>>30)&0x1 ? + "Transmit" : "Receive", + (EXTRACT_32BITS(obj_tptr+offset+16)>>30)&0x1)); + + ND_PRINT((ndo, "\n\t\t Channel Status: %s (%u)", + tok2str(lmp_obj_channel_status_values, + "Unknown", + EXTRACT_32BITS(obj_tptr+offset+16)&0x3FFFFFF), + EXTRACT_32BITS(obj_tptr+offset+16)&0x3FFFFFF)); + offset+=20; + } + break; + + case LMP_CTYPE_UNMD: + offset = 0; + /* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */ + while (offset+8 <= obj_tlen) { + ND_PRINT((ndo, "\n\t Interface ID: %u (0x%08x)", + EXTRACT_32BITS(obj_tptr+offset), + EXTRACT_32BITS(obj_tptr+offset))); + + ND_PRINT((ndo, "\n\t\t Active: %s (%u)", + (EXTRACT_32BITS(obj_tptr+offset+4)>>31) ? + "Allocated" : "Non-allocated", + (EXTRACT_32BITS(obj_tptr+offset+4)>>31))); + + ND_PRINT((ndo, "\n\t\t Direction: %s (%u)", + (EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1 ? + "Transmit" : "Receive", + (EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1)); + + ND_PRINT((ndo, "\n\t\t Channel Status: %s (%u)", + tok2str(lmp_obj_channel_status_values, + "Unknown", + EXTRACT_32BITS(obj_tptr+offset+4)&0x3FFFFFF), + EXTRACT_32BITS(obj_tptr+offset+4)&0x3FFFFFF)); + offset+=8; + } + break; + default: hexdump=TRUE; } @@ -719,16 +943,35 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_CHANNEL_STATUS_REQ: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: - case LMP_CTYPE_UNMD: offset = 0; - while (offset < (lmp_obj_len-(int)sizeof(struct lmp_object_header)) ) { + while (offset+4 <= obj_tlen) { ND_PRINT((ndo, "\n\t Interface ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+offset), EXTRACT_32BITS(obj_tptr+offset))); offset+=4; } break; + case LMP_CTYPE_IPV6: + offset = 0; + while (offset+16 <= obj_tlen) { + ND_PRINT((ndo, "\n\t Interface ID: %s (0x%08x)", + ip6addr_string(ndo, obj_tptr+offset), + EXTRACT_32BITS(obj_tptr+offset))); + offset+=16; + } + break; + + case LMP_CTYPE_UNMD: + offset = 0; + while (offset+4 <= obj_tlen) { + ND_PRINT((ndo, "\n\t Interface ID: %u (0x%08x)", + EXTRACT_32BITS(obj_tptr+offset), + EXTRACT_32BITS(obj_tptr+offset))); + offset+=4; + } + break; + default: hexdump=TRUE; } @@ -737,6 +980,10 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_ERROR_CODE: switch(lmp_obj_ctype) { case LMP_CTYPE_BEGIN_VERIFY_ERROR: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Error Code: %s", bittok2str(lmp_obj_begin_verify_error_values, "none", @@ -744,6 +991,10 @@ lmp_print(netdissect_options *ndo, break; case LMP_CTYPE_LINK_SUMMARY_ERROR: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Error Code: %s", bittok2str(lmp_obj_link_summary_error_values, "none", @@ -757,51 +1008,60 @@ lmp_print(netdissect_options *ndo, case LMP_OBJ_SERVICE_CONFIG: switch (lmp_obj_ctype) { case LMP_CTYPE_SERVICE_CONFIG_SP: - + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Flags: %s", bittok2str(lmp_obj_service_config_sp_flag_values, "none", - EXTRACT_16BITS(obj_tptr)>>8))); + EXTRACT_8BITS(obj_tptr)))); ND_PRINT((ndo, "\n\t UNI Version: %u", - EXTRACT_16BITS(obj_tptr) & 0x00FF)); + EXTRACT_8BITS(obj_tptr+1))); break; case LMP_CTYPE_SERVICE_CONFIG_CPSA: + if (obj_tlen != 16) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } - link_type = EXTRACT_16BITS(obj_tptr)>>8; + link_type = EXTRACT_8BITS(obj_tptr); ND_PRINT((ndo, "\n\t Link Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_link_type_values, "Unknown", link_type), link_type)); - if (link_type == LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH) { + switch (link_type) { + case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH: ND_PRINT((ndo, "\n\t Signal Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_signal_type_sdh_values, "Unknown", - EXTRACT_16BITS(obj_tptr) & 0x00FF), - EXTRACT_16BITS(obj_tptr) & 0x00FF)); - } + EXTRACT_8BITS(obj_tptr+1)), + EXTRACT_8BITS(obj_tptr+1))); + break; - if (link_type == LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET) { + case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET: ND_PRINT((ndo, "\n\t Signal Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_signal_type_sonet_values, "Unknown", - EXTRACT_16BITS(obj_tptr) & 0x00FF), - EXTRACT_16BITS(obj_tptr) & 0x00FF)); + EXTRACT_8BITS(obj_tptr+1)), + EXTRACT_8BITS(obj_tptr+1))); + break; } ND_PRINT((ndo, "\n\t Transparency: %s", bittok2str(lmp_obj_service_config_cpsa_tp_flag_values, "none", - EXTRACT_16BITS(obj_tptr+2)>>8))); + EXTRACT_8BITS(obj_tptr+2)))); ND_PRINT((ndo, "\n\t Contiguous Concatenation Types: %s", bittok2str(lmp_obj_service_config_cpsa_cct_flag_values, "none", - EXTRACT_16BITS(obj_tptr+2)>>8 & 0x00FF))); + EXTRACT_8BITS(obj_tptr+3)))); ND_PRINT((ndo, "\n\t Minimum NCC: %u", EXTRACT_16BITS(obj_tptr+4))); @@ -822,6 +1082,10 @@ lmp_print(netdissect_options *ndo, break; case LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM: + if (obj_tlen != 8) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Transparency Flags: %s", bittok2str( @@ -833,17 +1097,21 @@ lmp_print(netdissect_options *ndo, bittok2str( lmp_obj_service_config_nsa_tcm_flag_values, "none", - EXTRACT_16BITS(obj_tptr+6) & 0x00FF))); + EXTRACT_8BITS(obj_tptr+7)))); break; case LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY: + if (obj_tlen != 4) { + ND_PRINT((ndo, " (not correct for object)")); + break; + } ND_PRINT((ndo, "\n\t Diversity: Flags: %s", bittok2str( lmp_obj_service_config_nsa_network_diversity_flag_values, "none", - EXTRACT_16BITS(obj_tptr+2) & 0x00FF))); + EXTRACT_8BITS(obj_tptr+3)))); break; default: diff --git a/freebsd/contrib/tcpdump/print-lspping.c b/freebsd/contrib/tcpdump/print-lspping.c index eb1cc77d..2972df2a 100644 --- a/freebsd/contrib/tcpdump/print-lspping.c +++ b/freebsd/contrib/tcpdump/print-lspping.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: MPLS LSP PING printer */ @@ -110,6 +110,7 @@ static const struct tok lspping_return_code_values[] = { { 11, "No label entry at stack-depth"}, { 12, "Protocol not associated with interface at FEC stack depth"}, { 13, "Premature termination of ping due to label stack shrinking to a single label"}, + { 0, NULL}, }; diff --git a/freebsd/contrib/tcpdump/print-m3ua.c b/freebsd/contrib/tcpdump/print-m3ua.c index e7d7b300..9e363779 100644 --- a/freebsd/contrib/tcpdump/print-m3ua.c +++ b/freebsd/contrib/tcpdump/print-m3ua.c @@ -73,7 +73,7 @@ static const struct tok MessageClasses[] = { { M3UA_MSGC_SSNM, "SS7" }, { M3UA_MSGC_ASPSM, "ASP" }, { M3UA_MSGC_ASPTM, "ASP" }, - { M3UA_MSGC_RKM, "Routing Key Managment" }, + { M3UA_MSGC_RKM, "Routing Key Management"}, { 0, NULL } }; diff --git a/freebsd/contrib/tcpdump/print-mobility.c b/freebsd/contrib/tcpdump/print-mobility.c index e43dc3f0..57435041 100644 --- a/freebsd/contrib/tcpdump/print-mobility.c +++ b/freebsd/contrib/tcpdump/print-mobility.c @@ -34,6 +34,7 @@ */ /* \summary: IPv6 mobility printer */ +/* RFC 3775 */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -41,11 +42,12 @@ #include <netdissect-stdinc.h> -#include "ip6.h" #include "netdissect.h" #include "addrtoname.h" #include "extract.h" +#include "ip6.h" + static const char tstr[] = "[|MOBILITY]"; /* Mobility header */ @@ -154,6 +156,7 @@ mobility_opt_print(netdissect_options *ndo, goto trunc; } /* units of 4 secs */ + ND_TCHECK_16BITS(&bp[i+2]); ND_PRINT((ndo, "(refresh: %u)", EXTRACT_16BITS(&bp[i+2]) << 2)); break; @@ -162,6 +165,7 @@ mobility_opt_print(netdissect_options *ndo, ND_PRINT((ndo, "(altcoa: trunc)")); goto trunc; } + ND_TCHECK_128BITS(&bp[i+2]); ND_PRINT((ndo, "(alt-CoA: %s)", ip6addr_string(ndo, &bp[i+2]))); break; case IP6MOPT_NONCEID: @@ -169,6 +173,8 @@ mobility_opt_print(netdissect_options *ndo, ND_PRINT((ndo, "(ni: trunc)")); goto trunc; } + ND_TCHECK_16BITS(&bp[i+2]); + ND_TCHECK_16BITS(&bp[i+4]); ND_PRINT((ndo, "(ni: ho=0x%04x co=0x%04x)", EXTRACT_16BITS(&bp[i+2]), EXTRACT_16BITS(&bp[i+4]))); @@ -247,7 +253,7 @@ mobility_print(netdissect_options *ndo, case IP6M_CAREOF_TEST_INIT: hlen = IP6M_MINLEN; if (ndo->ndo_vflag) { - ND_TCHECK2(*mh, hlen + 8); + ND_TCHECK_32BITS(&bp[hlen + 4]); ND_PRINT((ndo, " %s Init Cookie=%08x:%08x", type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of", EXTRACT_32BITS(&bp[hlen]), @@ -261,7 +267,7 @@ mobility_print(netdissect_options *ndo, ND_PRINT((ndo, " nonce id=0x%x", EXTRACT_16BITS(&mh->ip6m_data16[0]))); hlen = IP6M_MINLEN; if (ndo->ndo_vflag) { - ND_TCHECK2(*mh, hlen + 8); + ND_TCHECK_32BITS(&bp[hlen + 4]); ND_PRINT((ndo, " %s Init Cookie=%08x:%08x", type == IP6M_HOME_TEST ? "Home" : "Care-of", EXTRACT_32BITS(&bp[hlen]), @@ -269,7 +275,7 @@ mobility_print(netdissect_options *ndo, } hlen += 8; if (ndo->ndo_vflag) { - ND_TCHECK2(*mh, hlen + 8); + ND_TCHECK_32BITS(&bp[hlen + 4]); ND_PRINT((ndo, " %s Keygen Token=%08x:%08x", type == IP6M_HOME_TEST ? "Home" : "Care-of", EXTRACT_32BITS(&bp[hlen]), @@ -281,22 +287,23 @@ mobility_print(netdissect_options *ndo, ND_TCHECK(mh->ip6m_data16[0]); ND_PRINT((ndo, " seq#=%u", EXTRACT_16BITS(&mh->ip6m_data16[0]))); hlen = IP6M_MINLEN; - ND_TCHECK2(*mh, hlen + 1); - if (bp[hlen] & 0xf0) + ND_TCHECK_16BITS(&bp[hlen]); + if (bp[hlen] & 0xf0) { ND_PRINT((ndo, " ")); - if (bp[hlen] & 0x80) - ND_PRINT((ndo, "A")); - if (bp[hlen] & 0x40) - ND_PRINT((ndo, "H")); - if (bp[hlen] & 0x20) - ND_PRINT((ndo, "L")); - if (bp[hlen] & 0x10) - ND_PRINT((ndo, "K")); + if (bp[hlen] & 0x80) + ND_PRINT((ndo, "A")); + if (bp[hlen] & 0x40) + ND_PRINT((ndo, "H")); + if (bp[hlen] & 0x20) + ND_PRINT((ndo, "L")); + if (bp[hlen] & 0x10) + ND_PRINT((ndo, "K")); + } /* Reserved (4bits) */ hlen += 1; /* Reserved (8bits) */ hlen += 1; - ND_TCHECK2(*mh, hlen + 2); + ND_TCHECK_16BITS(&bp[hlen]); /* units of 4 secs */ ND_PRINT((ndo, " lifetime=%u", EXTRACT_16BITS(&bp[hlen]) << 2)); hlen += 2; @@ -304,14 +311,15 @@ mobility_print(netdissect_options *ndo, case IP6M_BINDING_ACK: ND_TCHECK(mh->ip6m_data8[0]); ND_PRINT((ndo, " status=%u", mh->ip6m_data8[0])); + ND_TCHECK(mh->ip6m_data8[1]); if (mh->ip6m_data8[1] & 0x80) ND_PRINT((ndo, " K")); /* Reserved (7bits) */ hlen = IP6M_MINLEN; - ND_TCHECK2(*mh, hlen + 2); + ND_TCHECK_16BITS(&bp[hlen]); ND_PRINT((ndo, " seq#=%u", EXTRACT_16BITS(&bp[hlen]))); hlen += 2; - ND_TCHECK2(*mh, hlen + 2); + ND_TCHECK_16BITS(&bp[hlen]); /* units of 4 secs */ ND_PRINT((ndo, " lifetime=%u", EXTRACT_16BITS(&bp[hlen]) << 2)); hlen += 2; @@ -321,7 +329,7 @@ mobility_print(netdissect_options *ndo, ND_PRINT((ndo, " status=%u", mh->ip6m_data8[0])); /* Reserved */ hlen = IP6M_MINLEN; - ND_TCHECK2(*mh, hlen + 16); + ND_TCHECK2(bp[hlen], 16); ND_PRINT((ndo, " homeaddr %s", ip6addr_string(ndo, &bp[hlen]))); hlen += 16; break; @@ -338,7 +346,7 @@ mobility_print(netdissect_options *ndo, trunc: ND_PRINT((ndo, "%s", tstr)); - return(mhlen); + return(-1); } #ifdef __rtems__ #include "rtems-bsd-tcpdump-print-mobility-data.h" diff --git a/freebsd/contrib/tcpdump/print-mpcp.c b/freebsd/contrib/tcpdump/print-mpcp.c index 55d1fc63..45b36767 100644 --- a/freebsd/contrib/tcpdump/print-mpcp.c +++ b/freebsd/contrib/tcpdump/print-mpcp.c @@ -18,7 +18,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: IEEE 802.3ah Multi-Point Control Protocol (MPCP) printer */ diff --git a/freebsd/contrib/tcpdump/print-mpls.c b/freebsd/contrib/tcpdump/print-mpls.c index a3dadfff..f20f7599 100644 --- a/freebsd/contrib/tcpdump/print-mpls.c +++ b/freebsd/contrib/tcpdump/print-mpls.c @@ -207,7 +207,7 @@ mpls_print(netdissect_options *ndo, const u_char *bp, u_int length) break; case PT_OSI: - isoclns_print(ndo, p, length, length); + isoclns_print(ndo, p, length); break; default: diff --git a/freebsd/contrib/tcpdump/print-mptcp.c b/freebsd/contrib/tcpdump/print-mptcp.c index 54669708..4dcf8129 100644 --- a/freebsd/contrib/tcpdump/print-mptcp.c +++ b/freebsd/contrib/tcpdump/print-mptcp.c @@ -184,7 +184,7 @@ mp_capable_print(netdissect_options *ndo, { const struct mp_capable *mpc = (const struct mp_capable *) opt; - if (!(opt_len == 12 && flags & TH_SYN) && + if (!(opt_len == 12 && (flags & TH_SYN)) && !(opt_len == 20 && (flags & (TH_SYN | TH_ACK)) == TH_ACK)) return 0; @@ -208,9 +208,9 @@ mp_join_print(netdissect_options *ndo, { const struct mp_join *mpj = (const struct mp_join *) opt; - if (!(opt_len == 12 && flags & TH_SYN) && + if (!(opt_len == 12 && (flags & TH_SYN)) && !(opt_len == 16 && (flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) && - !(opt_len == 24 && flags & TH_ACK)) + !(opt_len == 24 && (flags & TH_ACK))) return 0; if (opt_len != 24) { @@ -242,76 +242,92 @@ mp_join_print(netdissect_options *ndo, return 1; } -static u_int mp_dss_len(const struct mp_dss *m, int csum) -{ - u_int len; - - len = 4; - if (m->flags & MP_DSS_A) { - /* Ack present - 4 or 8 octets */ - len += (m->flags & MP_DSS_a) ? 8 : 4; - } - if (m->flags & MP_DSS_M) { - /* - * Data Sequence Number (DSN), Subflow Sequence Number (SSN), - * Data-Level Length present, and Checksum possibly present. - * All but the Checksum are 10 bytes if the m flag is - * clear (4-byte DSN) and 14 bytes if the m flag is set - * (8-byte DSN). - */ - len += (m->flags & MP_DSS_m) ? 14 : 10; - - /* - * The Checksum is present only if negotiated. - */ - if (csum) - len += 2; - } - return len; -} - static int mp_dss_print(netdissect_options *ndo, const u_char *opt, u_int opt_len, u_char flags) { const struct mp_dss *mdss = (const struct mp_dss *) opt; - if ((opt_len != mp_dss_len(mdss, 1) && - opt_len != mp_dss_len(mdss, 0)) || flags & TH_SYN) + /* We need the flags, at a minimum. */ + if (opt_len < 4) + return 0; + + if (flags & TH_SYN) return 0; if (mdss->flags & MP_DSS_F) ND_PRINT((ndo, " fin")); opt += 4; + opt_len -= 4; if (mdss->flags & MP_DSS_A) { + /* Ack present */ ND_PRINT((ndo, " ack ")); + /* + * If the a flag is set, we have an 8-byte ack; if it's + * clear, we have a 4-byte ack. + */ if (mdss->flags & MP_DSS_a) { + if (opt_len < 8) + return 0; ND_PRINT((ndo, "%" PRIu64, EXTRACT_64BITS(opt))); opt += 8; + opt_len -= 8; } else { + if (opt_len < 4) + return 0; ND_PRINT((ndo, "%u", EXTRACT_32BITS(opt))); opt += 4; + opt_len -= 4; } } if (mdss->flags & MP_DSS_M) { + /* + * Data Sequence Number (DSN), Subflow Sequence Number (SSN), + * Data-Level Length present, and Checksum possibly present. + */ ND_PRINT((ndo, " seq ")); + /* + * If the m flag is set, we have an 8-byte NDS; if it's clear, + * we have a 4-byte DSN. + */ if (mdss->flags & MP_DSS_m) { + if (opt_len < 8) + return 0; ND_PRINT((ndo, "%" PRIu64, EXTRACT_64BITS(opt))); opt += 8; + opt_len -= 8; } else { + if (opt_len < 4) + return 0; ND_PRINT((ndo, "%u", EXTRACT_32BITS(opt))); opt += 4; + opt_len -= 4; } + if (opt_len < 4) + return 0; ND_PRINT((ndo, " subseq %u", EXTRACT_32BITS(opt))); opt += 4; + opt_len -= 4; + if (opt_len < 2) + return 0; ND_PRINT((ndo, " len %u", EXTRACT_16BITS(opt))); opt += 2; + opt_len -= 2; - if (opt_len == mp_dss_len(mdss, 1)) + /* + * The Checksum is present only if negotiated. + * If there are at least 2 bytes left, process the next 2 + * bytes as the Checksum. + */ + if (opt_len >= 2) { ND_PRINT((ndo, " csum 0x%x", EXTRACT_16BITS(opt))); + opt_len -= 2; + } } + if (opt_len != 0) + return 0; return 1; } diff --git a/freebsd/contrib/tcpdump/print-nfs.c b/freebsd/contrib/tcpdump/print-nfs.c index 10de4358..97748dce 100644 --- a/freebsd/contrib/tcpdump/print-nfs.c +++ b/freebsd/contrib/tcpdump/print-nfs.c @@ -634,17 +634,15 @@ nfsreq_print_noaddr(netdissect_options *ndo, if ((dp = parsereq(ndo, rp, length)) != NULL && (dp = parsefh(ndo, dp, v3)) != NULL) { if (v3) { - ND_TCHECK(dp[2]); + ND_TCHECK(dp[4]); ND_PRINT((ndo, " %u (%u) bytes @ %" PRIu64, EXTRACT_32BITS(&dp[4]), EXTRACT_32BITS(&dp[2]), EXTRACT_64BITS(&dp[0]))); if (ndo->ndo_vflag) { - dp += 3; - ND_TCHECK(dp[0]); ND_PRINT((ndo, " <%s>", tok2str(nfsv3_writemodes, - NULL, EXTRACT_32BITS(dp)))); + NULL, EXTRACT_32BITS(&dp[3])))); } } else { ND_TCHECK(dp[3]); @@ -815,11 +813,15 @@ nfs_printfh(netdissect_options *ndo, if (sfsname) { /* file system ID is ASCII, not numeric, for this server OS */ - static char temp[NFSX_V3FHMAX+1]; + char temp[NFSX_V3FHMAX+1]; + u_int stringlen; /* Make sure string is null-terminated */ - strncpy(temp, sfsname, NFSX_V3FHMAX); - temp[sizeof(temp) - 1] = '\0'; + stringlen = len; + if (stringlen > NFSX_V3FHMAX) + stringlen = NFSX_V3FHMAX; + strncpy(temp, sfsname, stringlen); + temp[stringlen] = '\0'; /* Remove trailing spaces */ spacep = strchr(temp, ' '); if (spacep) @@ -874,7 +876,7 @@ xid_map_enter(netdissect_options *ndo, const struct ip6_hdr *ip6 = NULL; struct xid_map_entry *xmep; - if (!ND_TTEST(rp->rm_call.cb_vers)) + if (!ND_TTEST(rp->rm_call.cb_proc)) return (0); switch (IP_V((const struct ip *)bp)) { case 4: @@ -1008,11 +1010,11 @@ parserep(netdissect_options *ndo, * skip past the ar_verf credentials. */ dp += (len + (2*sizeof(uint32_t) + 3)) / sizeof(uint32_t); - ND_TCHECK2(dp[0], 0); /* * now we can check the ar_stat field */ + ND_TCHECK(dp[0]); astat = (enum sunrpc_accept_stat) EXTRACT_32BITS(dp); if (astat != SUNRPC_SUCCESS) { ND_PRINT((ndo, " %s", tok2str(sunrpc_str, "ar_stat %d", astat))); @@ -1249,6 +1251,7 @@ static const uint32_t * parse_wcc_attr(netdissect_options *ndo, const uint32_t *dp) { + /* Our caller has already checked this */ ND_PRINT((ndo, " sz %" PRIu64, EXTRACT_64BITS(&dp[0]))); ND_PRINT((ndo, " mtime %u.%06u ctime %u.%06u", EXTRACT_32BITS(&dp[2]), EXTRACT_32BITS(&dp[3]), @@ -1517,8 +1520,10 @@ interp_reply(netdissect_options *ndo, ND_PRINT((ndo, " attr:")); if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag))) break; - if (!er) + if (!er) { + ND_TCHECK(dp[0]); ND_PRINT((ndo, " c %04x", EXTRACT_32BITS(&dp[0]))); + } return; case NFSPROC_READLINK: diff --git a/freebsd/contrib/tcpdump/print-null.c b/freebsd/contrib/tcpdump/print-null.c index 9287709d..53aa294f 100644 --- a/freebsd/contrib/tcpdump/print-null.c +++ b/freebsd/contrib/tcpdump/print-null.c @@ -123,7 +123,7 @@ null_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char break; case BSD_AFNUM_ISO: - isoclns_print(ndo, p, length, caplen); + isoclns_print(ndo, p, length); break; case BSD_AFNUM_APPLETALK: diff --git a/freebsd/contrib/tcpdump/print-olsr.c b/freebsd/contrib/tcpdump/print-olsr.c index de757a8e..ab53a632 100644 --- a/freebsd/contrib/tcpdump/print-olsr.c +++ b/freebsd/contrib/tcpdump/print-olsr.c @@ -19,7 +19,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler <hannes@juniper.net> + * Original code by Hannes Gredler <hannes@gredler.at> * IPv6 additions by Florian Forster <octo at verplant.org> */ @@ -365,10 +365,9 @@ olsr_print(netdissect_options *ndo, } msgptr; int msg_len_valid = 0; - ND_TCHECK2(*tptr, sizeof(struct olsr_msg4)); - if (is_ipv6) { + ND_TCHECK2(*tptr, sizeof(struct olsr_msg6)); msgptr.v6 = (const struct olsr_msg6 *) tptr; msg_type = msgptr.v6->msg_type; msg_len = EXTRACT_16BITS(msgptr.v6->msg_len); @@ -399,6 +398,7 @@ olsr_print(netdissect_options *ndo, } else /* (!is_ipv6) */ { + ND_TCHECK2(*tptr, sizeof(struct olsr_msg4)); msgptr.v4 = (const struct olsr_msg4 *) tptr; msg_type = msgptr.v4->msg_type; msg_len = EXTRACT_16BITS(msgptr.v4->msg_len); @@ -622,22 +622,25 @@ olsr_print(netdissect_options *ndo, case OLSR_NAMESERVICE_MSG: { - u_int name_entries = EXTRACT_16BITS(msg_data+2); - u_int addr_size = 4; - int name_entries_valid = 0; + u_int name_entries; + u_int addr_size; + int name_entries_valid; u_int i; + if (msg_tlen < 4) + goto trunc; + ND_TCHECK2(*msg_data, 4); + + name_entries = EXTRACT_16BITS(msg_data+2); + addr_size = 4; if (is_ipv6) addr_size = 16; + name_entries_valid = 0; if ((name_entries > 0) && ((name_entries * (4 + addr_size)) <= msg_tlen)) name_entries_valid = 1; - if (msg_tlen < 4) - goto trunc; - ND_TCHECK2(*msg_data, 4); - ND_PRINT((ndo, "\n\t Version %u, Entries %u%s", EXTRACT_16BITS(msg_data), name_entries, (name_entries_valid == 0) ? " (invalid)" : "")); diff --git a/freebsd/contrib/tcpdump/print-ospf6.c b/freebsd/contrib/tcpdump/print-ospf6.c index bd3efe9a..333ac774 100644 --- a/freebsd/contrib/tcpdump/print-ospf6.c +++ b/freebsd/contrib/tcpdump/print-ospf6.c @@ -654,6 +654,7 @@ ospf6_print_lsa(netdissect_options *ndo, if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) return (1); lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); + ND_TCHECK(llsap->llsa_nprefix); prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); ND_PRINT((ndo, "\n\t Priority %d, Link-local address %s, Prefixes %d:", llsap->llsa_priority, @@ -741,6 +742,7 @@ ospf6_decode_v3(netdissect_options *ndo, case OSPF_TYPE_HELLO: { register const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); + ND_TCHECK_32BITS(&hellop->hello_options); ND_PRINT((ndo, "\n\tOptions [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&hellop->hello_options)))); @@ -939,10 +941,12 @@ ospf6_decode_v3_trailer(netdissect_options *ndo, if (op->ospf6_type == OSPF_TYPE_HELLO) { const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); + ND_TCHECK(hellop->hello_options); if (EXTRACT_32BITS(&hellop->hello_options) & OSPF6_OPTION_L) lls_hello = 1; } else if (op->ospf6_type == OSPF_TYPE_DD) { const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); + ND_TCHECK(ddp->db_options); if (EXTRACT_32BITS(&ddp->db_options) & OSPF6_OPTION_L) lls_dd = 1; } diff --git a/freebsd/contrib/tcpdump/print-pgm.c b/freebsd/contrib/tcpdump/print-pgm.c index e6c2a18f..b9ace2c0 100644 --- a/freebsd/contrib/tcpdump/print-pgm.c +++ b/freebsd/contrib/tcpdump/print-pgm.c @@ -175,13 +175,12 @@ pgm_print(netdissect_options *ndo, ND_PRINT((ndo, "%s > %s: [|pgm]", ip6addr_string(ndo, &ip6->ip6_src), ip6addr_string(ndo, &ip6->ip6_dst))); - return; } else { ND_PRINT((ndo, "%s > %s: [|pgm]", ipaddr_string(ndo, &ip->ip_src), ipaddr_string(ndo, &ip->ip_dst))); - return; } + return; } sport = EXTRACT_16BITS(&pgm->pgm_sport); @@ -368,6 +367,7 @@ pgm_print(netdissect_options *ndo, * and stopping if we don't have enough. */ bp += (2 * sizeof(uint16_t)); + ND_TCHECK_16BITS(bp); switch (EXTRACT_16BITS(bp)) { case AFNUM_INET: ND_TCHECK2(*bp, sizeof(struct in_addr)); @@ -463,6 +463,10 @@ pgm_print(netdissect_options *ndo, ND_PRINT((ndo, "[Total option length leaves no room for final option]")); return; } + if (!ND_TTEST2(*bp, 2)) { + ND_PRINT((ndo, " [|OPT]")); + return; + } opt_type = *bp++; opt_len = *bp++; if (opt_len < PGM_MIN_OPT_LEN) { @@ -481,112 +485,130 @@ pgm_print(netdissect_options *ndo, switch (opt_type & PGM_OPT_MASK) { case PGM_OPT_LENGTH: - if (opt_len != 4) { - ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != 4]", opt_len)); +#define PGM_OPT_LENGTH_LEN (2+2) + if (opt_len != PGM_OPT_LENGTH_LEN) { + ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != %u]", + opt_len, PGM_OPT_LENGTH_LEN)); return; } ND_PRINT((ndo, " OPTS LEN (extra?) %d", EXTRACT_16BITS(bp))); - bp += sizeof(uint16_t); - opts_len -= 4; + bp += 2; + opts_len -= PGM_OPT_LENGTH_LEN; break; case PGM_OPT_FRAGMENT: - if (opt_len != 16) { - ND_PRINT((ndo, "[Bad OPT_FRAGMENT option, length %u != 16]", opt_len)); +#define PGM_OPT_FRAGMENT_LEN (2+2+4+4+4) + if (opt_len != PGM_OPT_FRAGMENT_LEN) { + ND_PRINT((ndo, "[Bad OPT_FRAGMENT option, length %u != %u]", + opt_len, PGM_OPT_FRAGMENT_LEN)); return; } bp += 2; seq = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; offset = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; len = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; ND_PRINT((ndo, " FRAG seq %u off %u len %u", seq, offset, len)); - opts_len -= 16; + opts_len -= PGM_OPT_FRAGMENT_LEN; break; case PGM_OPT_NAK_LIST: bp += 2; - opt_len -= sizeof(uint32_t); /* option header */ + opt_len -= 4; /* option header */ ND_PRINT((ndo, " NAK LIST")); while (opt_len) { - if (opt_len < sizeof(uint32_t)) { + if (opt_len < 4) { ND_PRINT((ndo, "[Option length not a multiple of 4]")); return; } - ND_TCHECK2(*bp, sizeof(uint32_t)); + ND_TCHECK2(*bp, 4); ND_PRINT((ndo, " %u", EXTRACT_32BITS(bp))); - bp += sizeof(uint32_t); - opt_len -= sizeof(uint32_t); - opts_len -= sizeof(uint32_t); + bp += 4; + opt_len -= 4; + opts_len -= 4; } break; case PGM_OPT_JOIN: - if (opt_len != 8) { - ND_PRINT((ndo, "[Bad OPT_JOIN option, length %u != 8]", opt_len)); +#define PGM_OPT_JOIN_LEN (2+2+4) + if (opt_len != PGM_OPT_JOIN_LEN) { + ND_PRINT((ndo, "[Bad OPT_JOIN option, length %u != %u]", + opt_len, PGM_OPT_JOIN_LEN)); return; } bp += 2; seq = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; ND_PRINT((ndo, " JOIN %u", seq)); - opts_len -= 8; + opts_len -= PGM_OPT_JOIN_LEN; break; case PGM_OPT_NAK_BO_IVL: - if (opt_len != 12) { - ND_PRINT((ndo, "[Bad OPT_NAK_BO_IVL option, length %u != 12]", opt_len)); +#define PGM_OPT_NAK_BO_IVL_LEN (2+2+4+4) + if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) { + ND_PRINT((ndo, "[Bad OPT_NAK_BO_IVL option, length %u != %u]", + opt_len, PGM_OPT_NAK_BO_IVL_LEN)); return; } bp += 2; offset = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; seq = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; ND_PRINT((ndo, " BACKOFF ivl %u ivlseq %u", offset, seq)); - opts_len -= 12; + opts_len -= PGM_OPT_NAK_BO_IVL_LEN; break; case PGM_OPT_NAK_BO_RNG: - if (opt_len != 12) { - ND_PRINT((ndo, "[Bad OPT_NAK_BO_RNG option, length %u != 12]", opt_len)); +#define PGM_OPT_NAK_BO_RNG_LEN (2+2+4+4) + if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) { + ND_PRINT((ndo, "[Bad OPT_NAK_BO_RNG option, length %u != %u]", + opt_len, PGM_OPT_NAK_BO_RNG_LEN)); return; } bp += 2; offset = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; seq = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; ND_PRINT((ndo, " BACKOFF max %u min %u", offset, seq)); - opts_len -= 12; + opts_len -= PGM_OPT_NAK_BO_RNG_LEN; break; case PGM_OPT_REDIRECT: +#define PGM_OPT_REDIRECT_FIXED_LEN (2+2+2+2) + if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) { + ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u < %u]", + opt_len, PGM_OPT_REDIRECT_FIXED_LEN)); + return; + } bp += 2; nla_afnum = EXTRACT_16BITS(bp); - bp += (2 * sizeof(uint16_t)); + bp += 2+2; switch (nla_afnum) { case AFNUM_INET: - if (opt_len != 4 + sizeof(struct in_addr)) { - ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != 4 + address size]", opt_len)); + if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr)) { + ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]", + opt_len, PGM_OPT_REDIRECT_FIXED_LEN)); return; } ND_TCHECK2(*bp, sizeof(struct in_addr)); addrtostr(bp, nla_buf, sizeof(nla_buf)); bp += sizeof(struct in_addr); - opts_len -= 4 + sizeof(struct in_addr); + opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr); break; case AFNUM_INET6: - if (opt_len != 4 + sizeof(struct in6_addr)) { - ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != 4 + address size]", opt_len)); + if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr)) { + ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]", + PGM_OPT_REDIRECT_FIXED_LEN, opt_len)); return; } ND_TCHECK2(*bp, sizeof(struct in6_addr)); addrtostr6(bp, nla_buf, sizeof(nla_buf)); bp += sizeof(struct in6_addr); - opts_len -= 4 + sizeof(struct in6_addr); + opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr); break; default: goto trunc; @@ -597,49 +619,57 @@ pgm_print(netdissect_options *ndo, break; case PGM_OPT_PARITY_PRM: - if (opt_len != 8) { - ND_PRINT((ndo, "[Bad OPT_PARITY_PRM option, length %u != 8]", opt_len)); +#define PGM_OPT_PARITY_PRM_LEN (2+2+4) + if (opt_len != PGM_OPT_PARITY_PRM_LEN) { + ND_PRINT((ndo, "[Bad OPT_PARITY_PRM option, length %u != %u]", + opt_len, PGM_OPT_PARITY_PRM_LEN)); return; } bp += 2; len = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; ND_PRINT((ndo, " PARITY MAXTGS %u", len)); - opts_len -= 8; + opts_len -= PGM_OPT_PARITY_PRM_LEN; break; case PGM_OPT_PARITY_GRP: - if (opt_len != 8) { - ND_PRINT((ndo, "[Bad OPT_PARITY_GRP option, length %u != 8]", opt_len)); +#define PGM_OPT_PARITY_GRP_LEN (2+2+4) + if (opt_len != PGM_OPT_PARITY_GRP_LEN) { + ND_PRINT((ndo, "[Bad OPT_PARITY_GRP option, length %u != %u]", + opt_len, PGM_OPT_PARITY_GRP_LEN)); return; } bp += 2; seq = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; ND_PRINT((ndo, " PARITY GROUP %u", seq)); - opts_len -= 8; + opts_len -= PGM_OPT_PARITY_GRP_LEN; break; case PGM_OPT_CURR_TGSIZE: - if (opt_len != 8) { - ND_PRINT((ndo, "[Bad OPT_CURR_TGSIZE option, length %u != 8]", opt_len)); +#define PGM_OPT_CURR_TGSIZE_LEN (2+2+4) + if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) { + ND_PRINT((ndo, "[Bad OPT_CURR_TGSIZE option, length %u != %u]", + opt_len, PGM_OPT_CURR_TGSIZE_LEN)); return; } bp += 2; len = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; ND_PRINT((ndo, " PARITY ATGS %u", len)); - opts_len -= 8; + opts_len -= PGM_OPT_CURR_TGSIZE_LEN; break; case PGM_OPT_NBR_UNREACH: - if (opt_len != 4) { - ND_PRINT((ndo, "[Bad OPT_NBR_UNREACH option, length %u != 4]", opt_len)); +#define PGM_OPT_NBR_UNREACH_LEN (2+2) + if (opt_len != PGM_OPT_NBR_UNREACH_LEN) { + ND_PRINT((ndo, "[Bad OPT_NBR_UNREACH option, length %u != %u]", + opt_len, PGM_OPT_NBR_UNREACH_LEN)); return; } bp += 2; ND_PRINT((ndo, " NBR_UNREACH")); - opts_len -= 4; + opts_len -= PGM_OPT_NBR_UNREACH_LEN; break; case PGM_OPT_PATH_NLA: @@ -649,33 +679,39 @@ pgm_print(netdissect_options *ndo, break; case PGM_OPT_SYN: - if (opt_len != 4) { - ND_PRINT((ndo, "[Bad OPT_SYN option, length %u != 4]", opt_len)); +#define PGM_OPT_SYN_LEN (2+2) + if (opt_len != PGM_OPT_SYN_LEN) { + ND_PRINT((ndo, "[Bad OPT_SYN option, length %u != %u]", + opt_len, PGM_OPT_SYN_LEN)); return; } bp += 2; ND_PRINT((ndo, " SYN")); - opts_len -= 4; + opts_len -= PGM_OPT_SYN_LEN; break; case PGM_OPT_FIN: - if (opt_len != 4) { - ND_PRINT((ndo, "[Bad OPT_FIN option, length %u != 4]", opt_len)); +#define PGM_OPT_FIN_LEN (2+2) + if (opt_len != PGM_OPT_FIN_LEN) { + ND_PRINT((ndo, "[Bad OPT_FIN option, length %u != %u]", + opt_len, PGM_OPT_FIN_LEN)); return; } bp += 2; ND_PRINT((ndo, " FIN")); - opts_len -= 4; + opts_len -= PGM_OPT_FIN_LEN; break; case PGM_OPT_RST: - if (opt_len != 4) { - ND_PRINT((ndo, "[Bad OPT_RST option, length %u != 4]", opt_len)); +#define PGM_OPT_RST_LEN (2+2) + if (opt_len != PGM_OPT_RST_LEN) { + ND_PRINT((ndo, "[Bad OPT_RST option, length %u != %u]", + opt_len, PGM_OPT_RST_LEN)); return; } bp += 2; ND_PRINT((ndo, " RST")); - opts_len -= 4; + opts_len -= PGM_OPT_RST_LEN; break; case PGM_OPT_CR: @@ -685,41 +721,51 @@ pgm_print(netdissect_options *ndo, break; case PGM_OPT_CRQST: - if (opt_len != 4) { - ND_PRINT((ndo, "[Bad OPT_CRQST option, length %u != 4]", opt_len)); +#define PGM_OPT_CRQST_LEN (2+2) + if (opt_len != PGM_OPT_CRQST_LEN) { + ND_PRINT((ndo, "[Bad OPT_CRQST option, length %u != %u]", + opt_len, PGM_OPT_CRQST_LEN)); return; } bp += 2; ND_PRINT((ndo, " CRQST")); - opts_len -= 4; + opts_len -= PGM_OPT_CRQST_LEN; break; case PGM_OPT_PGMCC_DATA: +#define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2) + if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) { + ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u < %u]", + opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); + return; + } bp += 2; offset = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; nla_afnum = EXTRACT_16BITS(bp); - bp += (2 * sizeof(uint16_t)); + bp += 2+2; switch (nla_afnum) { case AFNUM_INET: - if (opt_len != 12 + sizeof(struct in_addr)) { - ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len)); + if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr)) { + ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]", + opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); return; } ND_TCHECK2(*bp, sizeof(struct in_addr)); addrtostr(bp, nla_buf, sizeof(nla_buf)); bp += sizeof(struct in_addr); - opts_len -= 12 + sizeof(struct in_addr); + opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr); break; case AFNUM_INET6: - if (opt_len != 12 + sizeof(struct in6_addr)) { - ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len)); + if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr)) { + ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]", + opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); return; } ND_TCHECK2(*bp, sizeof(struct in6_addr)); addrtostr6(bp, nla_buf, sizeof(nla_buf)); bp += sizeof(struct in6_addr); - opts_len -= 12 + sizeof(struct in6_addr); + opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr); break; default: goto trunc; @@ -730,31 +776,39 @@ pgm_print(netdissect_options *ndo, break; case PGM_OPT_PGMCC_FEEDBACK: +#define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2) + if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) { + ND_PRINT((ndo, "[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]", + opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); + return; + } bp += 2; offset = EXTRACT_32BITS(bp); - bp += sizeof(uint32_t); + bp += 4; nla_afnum = EXTRACT_16BITS(bp); - bp += (2 * sizeof(uint16_t)); + bp += 2+2; switch (nla_afnum) { case AFNUM_INET: - if (opt_len != 12 + sizeof(struct in_addr)) { - ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len)); + if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr)) { + ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]", + opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); return; } ND_TCHECK2(*bp, sizeof(struct in_addr)); addrtostr(bp, nla_buf, sizeof(nla_buf)); bp += sizeof(struct in_addr); - opts_len -= 12 + sizeof(struct in_addr); + opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr); break; case AFNUM_INET6: - if (opt_len != 12 + sizeof(struct in6_addr)) { - ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len)); + if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr)) { + ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]", + opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); return; } ND_TCHECK2(*bp, sizeof(struct in6_addr)); addrtostr6(bp, nla_buf, sizeof(nla_buf)); bp += sizeof(struct in6_addr); - opts_len -= 12 + sizeof(struct in6_addr); + opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr); break; default: goto trunc; diff --git a/freebsd/contrib/tcpdump/print-pim.c b/freebsd/contrib/tcpdump/print-pim.c index 1762436a..2fa38842 100644 --- a/freebsd/contrib/tcpdump/print-pim.c +++ b/freebsd/contrib/tcpdump/print-pim.c @@ -175,20 +175,28 @@ pimv1_join_prune_print(netdissect_options *ndo, return; } + if (len < sizeof(struct in_addr)) + goto trunc; ND_TCHECK2(bp[0], sizeof(struct in_addr)); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n")); ND_PRINT((ndo, " Upstream Nbr: %s", ipaddr_string(ndo, bp))); - ND_TCHECK2(bp[6], 2); + bp += 4; + len -= 4; + if (len < 4) + goto trunc; + ND_TCHECK2(bp[2], 2); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n")); ND_PRINT((ndo, " Hold time: ")); - unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[6])); + unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2])); if (ndo->ndo_vflag < 2) return; - bp += 8; - len -= 8; + bp += 4; + len -= 4; + if (len < 4) + goto trunc; ND_TCHECK2(bp[0], 4); ngroups = bp[3]; bp += 4; @@ -198,17 +206,27 @@ pimv1_join_prune_print(netdissect_options *ndo, * XXX - does the address have length "addrlen" and the * mask length "maddrlen"? */ + if (len < 4) + goto trunc; ND_TCHECK2(bp[0], sizeof(struct in_addr)); ND_PRINT((ndo, "\n\tGroup: %s", ipaddr_string(ndo, bp))); - ND_TCHECK2(bp[4], sizeof(struct in_addr)); - if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) - ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[4]))); - ND_TCHECK2(bp[8], 4); - njoin = EXTRACT_16BITS(&bp[8]); - nprune = EXTRACT_16BITS(&bp[10]); + bp += 4; + len -= 4; + if (len < 4) + goto trunc; + ND_TCHECK2(bp[0], sizeof(struct in_addr)); + if (EXTRACT_32BITS(&bp[0]) != 0xffffffff) + ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[0]))); + bp += 4; + len -= 4; + if (len < 4) + goto trunc; + ND_TCHECK2(bp[0], 4); + njoin = EXTRACT_16BITS(&bp[0]); + nprune = EXTRACT_16BITS(&bp[2]); ND_PRINT((ndo, " joined: %d pruned: %d", njoin, nprune)); - bp += 12; - len -= 12; + bp += 4; + len -= 4; for (njp = 0; njp < (njoin + nprune); njp++) { const char *type; @@ -216,12 +234,15 @@ pimv1_join_prune_print(netdissect_options *ndo, type = "Join "; else type = "Prune"; + if (len < 6) + goto trunc; ND_TCHECK2(bp[0], 6); ND_PRINT((ndo, "\n\t%s %s%s%s%s/%d", type, (bp[0] & 0x01) ? "Sparse " : "Dense ", (bp[1] & 0x80) ? "WC " : "", (bp[1] & 0x40) ? "RP " : "SPT ", - ipaddr_string(ndo, &bp[2]), bp[1] & 0x3f)); + ipaddr_string(ndo, &bp[2]), + bp[1] & 0x3f)); bp += 6; len -= 6; } @@ -236,13 +257,8 @@ void pimv1_print(netdissect_options *ndo, register const u_char *bp, register u_int len) { - register const u_char *ep; register u_char type; - ep = (const u_char *)ndo->ndo_snapend; - if (bp >= ep) - return; - ND_TCHECK(bp[1]); type = bp[1]; @@ -308,10 +324,14 @@ pimv1_print(netdissect_options *ndo, case PIMV1_TYPE_JOIN_PRUNE: case PIMV1_TYPE_GRAFT: case PIMV1_TYPE_GRAFT_ACK: - if (ndo->ndo_vflag) + if (ndo->ndo_vflag) { + if (len < 8) + goto trunc; pimv1_join_prune_print(ndo, &bp[8], len - 8); + } break; } + ND_TCHECK(bp[4]); if ((bp[4] >> 4) != 1) ND_PRINT((ndo, " [v%d]", bp[4] >> 4)); return; @@ -335,6 +355,8 @@ cisco_autorp_print(netdissect_options *ndo, int numrps; int hold; + if (len < 8) + goto trunc; ND_TCHECK(bp[0]); ND_PRINT((ndo, " auto-rp ")); type = bp[0]; @@ -382,10 +404,16 @@ cisco_autorp_print(netdissect_options *ndo, int nentries; char s; + if (len < 4) + goto trunc; ND_TCHECK2(bp[0], 4); ND_PRINT((ndo, " RP %s", ipaddr_string(ndo, bp))); - ND_TCHECK(bp[4]); - switch (bp[4] & 0x3) { + bp += 4; + len -= 4; + if (len < 1) + goto trunc; + ND_TCHECK(bp[0]); + switch (bp[0] & 0x3) { case 0: ND_PRINT((ndo, " PIMv?")); break; case 1: ND_PRINT((ndo, " PIMv1")); @@ -395,13 +423,20 @@ cisco_autorp_print(netdissect_options *ndo, case 3: ND_PRINT((ndo, " PIMv1+2")); break; } - if (bp[4] & 0xfc) - ND_PRINT((ndo, " [rsvd=0x%02x]", bp[4] & 0xfc)); - ND_TCHECK(bp[5]); - nentries = bp[5]; - bp += 6; len -= 6; + if (bp[0] & 0xfc) + ND_PRINT((ndo, " [rsvd=0x%02x]", bp[0] & 0xfc)); + bp += 1; + len -= 1; + if (len < 1) + goto trunc; + ND_TCHECK(bp[0]); + nentries = bp[0]; + bp += 1; + len -= 1; s = ' '; for (; nentries; nentries--) { + if (len < 6) + goto trunc; ND_TCHECK2(bp[0], 6); ND_PRINT((ndo, "%c%s%s/%d", s, bp[0] & 1 ? "!" : "", ipaddr_string(ndo, &bp[2]), bp[1])); @@ -426,16 +461,13 @@ void pim_print(netdissect_options *ndo, register const u_char *bp, register u_int len, const u_char *bp2) { - register const u_char *ep; register const struct pim *pim = (const struct pim *)bp; - ep = (const u_char *)ndo->ndo_snapend; - if (bp >= ep) - return; #ifdef notyet /* currently we see only version and type */ ND_TCHECK(pim->pim_rsv); #endif + ND_TCHECK(pim->pim_typever); switch (PIM_VER(pim->pim_typever)) { case 2: if (!ndo->ndo_vflag) { @@ -459,6 +491,10 @@ pim_print(netdissect_options *ndo, break; } return; + +trunc: + ND_PRINT((ndo, "[|pim]")); + return; } /* @@ -501,8 +537,6 @@ pim_print(netdissect_options *ndo, * */ -static int pimv2_addr_len; - enum pimv2_addrtype { pimv2_unicast, pimv2_group, pimv2_source }; @@ -529,23 +563,24 @@ enum pimv2_addrtype { */ static int pimv2_addr_print(netdissect_options *ndo, - const u_char *bp, enum pimv2_addrtype at, int silent) + const u_char *bp, u_int len, enum pimv2_addrtype at, + u_int addr_len, int silent) { int af; - int len, hdrlen; - - ND_TCHECK(bp[0]); + int hdrlen; - if (pimv2_addr_len == 0) { + if (addr_len == 0) { + if (len < 2) + goto trunc; ND_TCHECK(bp[1]); switch (bp[0]) { case 1: af = AF_INET; - len = sizeof(struct in_addr); + addr_len = (u_int)sizeof(struct in_addr); break; case 2: af = AF_INET6; - len = sizeof(struct in6_addr); + addr_len = (u_int)sizeof(struct in6_addr); break; default: return -1; @@ -554,7 +589,7 @@ pimv2_addr_print(netdissect_options *ndo, return -1; hdrlen = 2; } else { - switch (pimv2_addr_len) { + switch (addr_len) { case sizeof(struct in_addr): af = AF_INET; break; @@ -565,14 +600,16 @@ pimv2_addr_print(netdissect_options *ndo, return -1; break; } - len = pimv2_addr_len; hdrlen = 0; } bp += hdrlen; + len -= hdrlen; switch (at) { case pimv2_unicast: - ND_TCHECK2(bp[0], len); + if (len < addr_len) + goto trunc; + ND_TCHECK2(bp[0], addr_len); if (af == AF_INET) { if (!silent) ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp))); @@ -581,10 +618,12 @@ pimv2_addr_print(netdissect_options *ndo, if (!silent) ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp))); } - return hdrlen + len; + return hdrlen + addr_len; case pimv2_group: case pimv2_source: - ND_TCHECK2(bp[0], len + 2); + if (len < addr_len + 2) + goto trunc; + ND_TCHECK2(bp[0], addr_len + 2); if (af == AF_INET) { if (!silent) { ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp + 2))); @@ -613,7 +652,7 @@ pimv2_addr_print(netdissect_options *ndo, ND_PRINT((ndo, ")")); } } - return hdrlen + 2 + len; + return hdrlen + 2 + addr_len; default: return -1; } @@ -661,21 +700,21 @@ static void pimv2_print(netdissect_options *ndo, register const u_char *bp, register u_int len, const u_char *bp2) { - register const u_char *ep; register const struct pim *pim = (const struct pim *)bp; int advance; enum checksum_status cksum_status; + int pimv2_addr_len; - ep = (const u_char *)ndo->ndo_snapend; - if (bp >= ep) - return; - if (ep > bp + len) - ep = bp + len; + if (len < 2) + goto trunc; ND_TCHECK(pim->pim_rsv); pimv2_addr_len = pim->pim_rsv; if (pimv2_addr_len != 0) ND_PRINT((ndo, ", RFC2117-encoding")); + if (len < 4) + goto trunc; + ND_TCHECK(pim->pim_cksum); ND_PRINT((ndo, ", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum))); if (EXTRACT_16BITS(&pim->pim_cksum) == 0) { ND_PRINT((ndo, "(unverified)")); @@ -716,26 +755,36 @@ pimv2_print(netdissect_options *ndo, break; } } + bp += 4; + len -= 4; switch (PIM_TYPE(pim->pim_typever)) { case PIMV2_TYPE_HELLO: { uint16_t otype, olen; - bp += 4; - while (bp < ep) { + while (len > 0) { + if (len < 4) + goto trunc; ND_TCHECK2(bp[0], 4); otype = EXTRACT_16BITS(&bp[0]); olen = EXTRACT_16BITS(&bp[2]); - ND_TCHECK2(bp[0], 4 + olen); ND_PRINT((ndo, "\n\t %s Option (%u), length %u, Value: ", tok2str(pimv2_hello_option_values, "Unknown", otype), otype, olen)); bp += 4; + len -= 4; + if (len < olen) + goto trunc; + ND_TCHECK2(bp[0], olen); switch (otype) { case PIMV2_HELLO_OPTION_HOLDTIME: - unsigned_relts_print(ndo, EXTRACT_16BITS(bp)); + if (olen != 2) { + ND_PRINT((ndo, "ERROR: Option Length != 2 Bytes (%u)", olen)); + } else { + unsigned_relts_print(ndo, EXTRACT_16BITS(bp)); + } break; case PIMV2_HELLO_OPTION_LANPRUNEDELAY: @@ -769,17 +818,25 @@ pimv2_print(netdissect_options *ndo, break; case PIMV2_HELLO_OPTION_GENID: - ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(bp))); + if (olen != 4) { + ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen)); + } else { + ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(bp))); + } break; case PIMV2_HELLO_OPTION_REFRESH_CAP: - ND_PRINT((ndo, "v%d", *bp)); - if (*(bp+1) != 0) { - ND_PRINT((ndo, ", interval ")); - unsigned_relts_print(ndo, *(bp+1)); - } - if (EXTRACT_16BITS(bp+2) != 0) { - ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(bp+2))); + if (olen != 4) { + ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen)); + } else { + ND_PRINT((ndo, "v%d", *bp)); + if (*(bp+1) != 0) { + ND_PRINT((ndo, ", interval ")); + unsigned_relts_print(ndo, *(bp+1)); + } + if (EXTRACT_16BITS(bp+2) != 0) { + ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(bp+2))); + } } break; @@ -790,14 +847,14 @@ pimv2_print(netdissect_options *ndo, case PIMV2_HELLO_OPTION_ADDRESS_LIST: if (ndo->ndo_vflag > 1) { const u_char *ptr = bp; + u_int plen = len; while (ptr < (bp+olen)) { ND_PRINT((ndo, "\n\t ")); - advance = pimv2_addr_print(ndo, ptr, pimv2_unicast, 0); - if (advance < 0) { - ND_PRINT((ndo, "...")); - break; - } + advance = pimv2_addr_print(ndo, ptr, plen, pimv2_unicast, pimv2_addr_len, 0); + if (advance < 0) + goto trunc; ptr += advance; + plen -= advance; } } break; @@ -810,6 +867,7 @@ pimv2_print(netdissect_options *ndo, if (ndo->ndo_vflag> 1) print_unknown_data(ndo, bp, "\n\t ", olen); bp += olen; + len -= olen; } break; } @@ -818,18 +876,24 @@ pimv2_print(netdissect_options *ndo, { const struct ip *ip; - ND_TCHECK2(*(bp + 4), PIMV2_REGISTER_FLAG_LEN); + if (len < 4) + goto trunc; + ND_TCHECK2(*bp, PIMV2_REGISTER_FLAG_LEN); ND_PRINT((ndo, ", Flags [ %s ]\n\t", tok2str(pimv2_register_flag_values, "none", - EXTRACT_32BITS(bp+4)))); + EXTRACT_32BITS(bp)))); - bp += 8; len -= 8; + bp += 4; len -= 4; /* encapsulated multicast packet */ + if (len == 0) + goto trunc; ip = (const struct ip *)bp; + ND_TCHECK(ip->ip_vhl); switch (IP_V(ip)) { case 0: /* Null header */ + ND_TCHECK(ip->ip_dst); ND_PRINT((ndo, "IP-Null-header %s > %s", ipaddr_string(ndo, &ip->ip_src), ipaddr_string(ndo, &ip->ip_dst))); @@ -851,22 +915,13 @@ pimv2_print(netdissect_options *ndo, } case PIMV2_TYPE_REGISTER_STOP: - bp += 4; len -= 4; - if (bp >= ep) - break; ND_PRINT((ndo, " group=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; len -= advance; - if (bp >= ep) - break; ND_PRINT((ndo, " source=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; len -= advance; break; @@ -917,19 +972,15 @@ pimv2_print(netdissect_options *ndo, uint16_t nprune; int i, j; - bp += 4; len -= 4; if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ - if (bp >= ep) - break; ND_PRINT((ndo, ", upstream-neighbor: ")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; len -= advance; } - if (bp + 4 > ep) - break; + if (len < 4) + goto trunc; + ND_TCHECK2(*bp, 4); ngroup = bp[1]; holdtime = EXTRACT_16BITS(&bp[2]); ND_PRINT((ndo, "\n\t %u group(s)", ngroup)); @@ -942,139 +993,125 @@ pimv2_print(netdissect_options *ndo, } bp += 4; len -= 4; for (i = 0; i < ngroup; i++) { - if (bp >= ep) - goto jp_done; ND_PRINT((ndo, "\n\t group #%u: ", i+1)); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { - ND_PRINT((ndo, "...)")); - goto jp_done; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; len -= advance; - if (bp + 4 > ep) { - ND_PRINT((ndo, "...)")); - goto jp_done; - } + if (len < 4) + goto trunc; + ND_TCHECK2(*bp, 4); njoin = EXTRACT_16BITS(&bp[0]); nprune = EXTRACT_16BITS(&bp[2]); ND_PRINT((ndo, ", joined sources: %u, pruned sources: %u", njoin, nprune)); bp += 4; len -= 4; for (j = 0; j < njoin; j++) { ND_PRINT((ndo, "\n\t joined source #%u: ", j+1)); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_source, 0)) < 0) { - ND_PRINT((ndo, "...)")); - goto jp_done; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; len -= advance; } for (j = 0; j < nprune; j++) { ND_PRINT((ndo, "\n\t pruned source #%u: ", j+1)); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_source, 0)) < 0) { - ND_PRINT((ndo, "...)")); - goto jp_done; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; len -= advance; } } - jp_done: break; } case PIMV2_TYPE_BOOTSTRAP: { int i, j, frpcnt; - bp += 4; /* Fragment Tag, Hash Mask len, and BSR-priority */ - if (bp + sizeof(uint16_t) >= ep) break; + if (len < 2) + goto trunc; + ND_TCHECK_16BITS(bp); ND_PRINT((ndo, " tag=%x", EXTRACT_16BITS(bp))); - bp += sizeof(uint16_t); - if (bp >= ep) break; + bp += 2; + len -= 2; + if (len < 1) + goto trunc; + ND_TCHECK(bp[0]); ND_PRINT((ndo, " hashmlen=%d", bp[0])); - if (bp + 1 >= ep) break; + if (len < 2) + goto trunc; + ND_TCHECK(bp[2]); ND_PRINT((ndo, " BSRprio=%d", bp[1])); bp += 2; + len -= 2; /* Encoded-Unicast-BSR-Address */ - if (bp >= ep) break; ND_PRINT((ndo, " BSR=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; + len -= advance; - for (i = 0; bp < ep; i++) { + for (i = 0; len > 0; i++) { /* Encoded-Group Address */ ND_PRINT((ndo, " (group%d: ", i)); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) - < 0) { - ND_PRINT((ndo, "...)")); - goto bs_done; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; + len -= advance; /* RP-Count, Frag RP-Cnt, and rsvd */ - if (bp >= ep) { - ND_PRINT((ndo, "...)")); - goto bs_done; - } + if (len < 1) + goto trunc; + ND_TCHECK(bp[0]); ND_PRINT((ndo, " RPcnt=%d", bp[0])); - if (bp + 1 >= ep) { - ND_PRINT((ndo, "...)")); - goto bs_done; - } + if (len < 2) + goto trunc; + ND_TCHECK(bp[1]); ND_PRINT((ndo, " FRPcnt=%d", frpcnt = bp[1])); + if (len < 4) + goto trunc; bp += 4; + len -= 4; - for (j = 0; j < frpcnt && bp < ep; j++) { + for (j = 0; j < frpcnt && len > 0; j++) { /* each RP info */ ND_PRINT((ndo, " RP%d=", j)); - if ((advance = pimv2_addr_print(ndo, bp, + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, - 0)) < 0) { - ND_PRINT((ndo, "...)")); - goto bs_done; - } + pimv2_addr_len, + 0)) < 0) + goto trunc; bp += advance; + len -= advance; - if (bp + 1 >= ep) { - ND_PRINT((ndo, "...)")); - goto bs_done; - } + if (len < 2) + goto trunc; + ND_TCHECK_16BITS(bp); ND_PRINT((ndo, ",holdtime=")); unsigned_relts_print(ndo, EXTRACT_16BITS(bp)); - if (bp + 2 >= ep) { - ND_PRINT((ndo, "...)")); - goto bs_done; - } + if (len < 3) + goto trunc; + ND_TCHECK(bp[2]); ND_PRINT((ndo, ",prio=%d", bp[2])); + if (len < 4) + goto trunc; bp += 4; + len -= 4; } ND_PRINT((ndo, ")")); } - bs_done: break; } case PIMV2_TYPE_ASSERT: - bp += 4; len -= 4; - if (bp >= ep) - break; ND_PRINT((ndo, " group=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; len -= advance; - if (bp >= ep) - break; ND_PRINT((ndo, " src=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; len -= advance; - if (bp + 8 > ep) - break; + if (len < 8) + goto trunc; + ND_TCHECK2(*bp, 8); if (bp[0] & 0x80) ND_PRINT((ndo, " RPT")); ND_PRINT((ndo, " pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff)); @@ -1084,61 +1121,62 @@ pimv2_print(netdissect_options *ndo, case PIMV2_TYPE_CANDIDATE_RP: { int i, pfxcnt; - bp += 4; /* Prefix-Cnt, Priority, and Holdtime */ - if (bp >= ep) break; + if (len < 1) + goto trunc; + ND_TCHECK(bp[0]); ND_PRINT((ndo, " prefix-cnt=%d", bp[0])); pfxcnt = bp[0]; - if (bp + 1 >= ep) break; + if (len < 2) + goto trunc; + ND_TCHECK(bp[1]); ND_PRINT((ndo, " prio=%d", bp[1])); - if (bp + 3 >= ep) break; + if (len < 4) + goto trunc; + ND_TCHECK_16BITS(&bp[2]); ND_PRINT((ndo, " holdtime=")); unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2])); bp += 4; + len -= 4; /* Encoded-Unicast-RP-Address */ - if (bp >= ep) break; ND_PRINT((ndo, " RP=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; + len -= advance; /* Encoded-Group Addresses */ - for (i = 0; i < pfxcnt && bp < ep; i++) { + for (i = 0; i < pfxcnt && len > 0; i++) { ND_PRINT((ndo, " Group%d=", i)); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) - < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; + len -= advance; } break; } case PIMV2_TYPE_PRUNE_REFRESH: ND_PRINT((ndo, " src=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; + len -= advance; ND_PRINT((ndo, " grp=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; + len -= advance; ND_PRINT((ndo, " forwarder=")); - if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { - ND_PRINT((ndo, "...")); - break; - } + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) + goto trunc; bp += advance; - ND_TCHECK2(bp[0], 2); + len -= advance; + if (len < 2) + goto trunc; + ND_TCHECK_16BITS(bp); ND_PRINT((ndo, " TUNR ")); unsigned_relts_print(ndo, EXTRACT_16BITS(bp)); break; diff --git a/freebsd/contrib/tcpdump/print-pktap.c b/freebsd/contrib/tcpdump/print-pktap.c index 3bccd567..a0d69769 100644 --- a/freebsd/contrib/tcpdump/print-pktap.c +++ b/freebsd/contrib/tcpdump/print-pktap.c @@ -110,6 +110,7 @@ pktap_if_print(netdissect_options *ndo, u_int length = h->len; if_printer printer; const pktap_header_t *hdr; + struct pcap_pkthdr nhdr; if (caplen < sizeof(pktap_header_t) || length < sizeof(pktap_header_t)) { ND_PRINT((ndo, "[|pktap]")); @@ -150,7 +151,10 @@ pktap_if_print(netdissect_options *ndo, case PKT_REC_PACKET: if ((printer = lookup_printer(dlt)) != NULL) { - hdrlen += printer(ndo, h, p); + nhdr = *h; + nhdr.caplen = caplen; + nhdr.len = length; + hdrlen += printer(ndo, &nhdr, p); } else { if (!ndo->ndo_eflag) pktap_header_print(ndo, (const u_char *)hdr, diff --git a/freebsd/contrib/tcpdump/print-ppp.c b/freebsd/contrib/tcpdump/print-ppp.c index ab88944d..724cf72b 100644 --- a/freebsd/contrib/tcpdump/print-ppp.c +++ b/freebsd/contrib/tcpdump/print-ppp.c @@ -617,7 +617,7 @@ print_lcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be >= 6)")); return len; } - ND_TCHECK2(*(p + 2), 3); + ND_TCHECK_24BITS(p + 2); ND_PRINT((ndo, ": Vendor: %s (%u)", tok2str(oui_values,"Unknown",EXTRACT_24BITS(p+2)), EXTRACT_24BITS(p + 2))); @@ -636,7 +636,7 @@ print_lcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be = 4)")); return len; } - ND_TCHECK2(*(p + 2), 2); + ND_TCHECK_16BITS(p + 2); ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2))); break; case LCPOPT_ACCM: @@ -644,7 +644,7 @@ print_lcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be = 6)")); return len; } - ND_TCHECK2(*(p + 2), 4); + ND_TCHECK_32BITS(p + 2); ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2))); break; case LCPOPT_AP: @@ -652,7 +652,7 @@ print_lcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be >= 4)")); return len; } - ND_TCHECK2(*(p + 2), 2); + ND_TCHECK_16BITS(p + 2); ND_PRINT((ndo, ": %s", tok2str(ppptype2str, "Unknown Auth Proto (0x04x)", EXTRACT_16BITS(p + 2)))); switch (EXTRACT_16BITS(p+2)) { @@ -674,7 +674,7 @@ print_lcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be >= 4)")); return 0; } - ND_TCHECK2(*(p + 2), 2); + ND_TCHECK_16BITS(p+2); if (EXTRACT_16BITS(p+2) == PPP_LQM) ND_PRINT((ndo, ": LQR")); else @@ -685,7 +685,7 @@ print_lcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be = 6)")); return 0; } - ND_TCHECK2(*(p + 2), 4); + ND_TCHECK_32BITS(p + 2); ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2))); break; case LCPOPT_PFC: @@ -697,7 +697,7 @@ print_lcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be = 4)")); return 0; } - ND_TCHECK2(*(p + 2), 2); + ND_TCHECK_16BITS(p + 2); ND_PRINT((ndo, ": 0x%04x", EXTRACT_16BITS(p + 2))); break; case LCPOPT_CBACK: @@ -716,7 +716,7 @@ print_lcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be = 4)")); return 0; } - ND_TCHECK2(*(p + 2), 2); + ND_TCHECK_16BITS(p + 2); ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2))); break; case LCPOPT_MLED: @@ -817,6 +817,15 @@ handle_mlppp(netdissect_options *ndo, if (!ndo->ndo_eflag) ND_PRINT((ndo, "MLPPP, ")); + if (length < 2) { + ND_PRINT((ndo, "[|mlppp]")); + return; + } + if (!ND_TTEST_16BITS(p)) { + ND_PRINT((ndo, "[|mlppp]")); + return; + } + ND_PRINT((ndo, "seq 0x%03x, Flags [%s], length %u", (EXTRACT_16BITS(p))&0x0fff, /* only support 12-Bit sequence space for now */ bittok2str(ppp_ml_flag_values, "none", *p & 0xc0), @@ -1061,7 +1070,7 @@ print_ipcp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be >= 4)")); return 0; } - ND_TCHECK2(*(p + 2), 2); + ND_TCHECK_16BITS(p+2); compproto = EXTRACT_16BITS(p+2); ND_PRINT((ndo, ": %s (0x%02x):", @@ -1247,7 +1256,7 @@ print_ccp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be >= 3)")); return len; } - ND_TCHECK2(*(p + 2), 1); + ND_TCHECK(p[2]); ND_PRINT((ndo, ": Version: %u, Dictionary Bits: %u", p[2] >> 5, p[2] & 0x1f)); break; @@ -1256,7 +1265,7 @@ print_ccp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be >= 4)")); return len; } - ND_TCHECK2(*(p + 2), 1); + ND_TCHECK(p[3]); ND_PRINT((ndo, ": Features: %u, PxP: %s, History: %u, #CTX-ID: %u", (p[2] & 0xc0) >> 6, (p[2] & 0x20) ? "Enabled" : "Disabled", @@ -1267,10 +1276,10 @@ print_ccp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be >= 4)")); return len; } - ND_TCHECK2(*(p + 2), 1); + ND_TCHECK(p[3]); ND_PRINT((ndo, ": Window: %uK, Method: %s (0x%x), MBZ: %u, CHK: %u", (p[2] & 0xf0) >> 4, - ((p[2] & 0x0f) == 8) ? "zlib" : "unkown", + ((p[2] & 0x0f) == 8) ? "zlib" : "unknown", p[2] & 0x0f, (p[3] & 0xfc) >> 2, p[3] & 0x03)); break; @@ -1342,7 +1351,7 @@ print_bacp_config_options(netdissect_options *ndo, ND_PRINT((ndo, " (length bogus, should be = 6)")); return len; } - ND_TCHECK2(*(p + 2), 4); + ND_TCHECK_32BITS(p + 2); ND_PRINT((ndo, ": Magic-Num 0x%08x", EXTRACT_32BITS(p + 2))); break; default: @@ -1490,7 +1499,7 @@ handle_ppp(netdissect_options *ndo, ipx_print(ndo, p, length); break; case PPP_OSI: - isoclns_print(ndo, p, length, length); + isoclns_print(ndo, p, length); break; case PPP_MPLS_UCAST: case PPP_MPLS_MCAST: diff --git a/freebsd/contrib/tcpdump/print-radius.c b/freebsd/contrib/tcpdump/print-radius.c index 56b692ec..2efbfab4 100644 --- a/freebsd/contrib/tcpdump/print-radius.c +++ b/freebsd/contrib/tcpdump/print-radius.c @@ -502,10 +502,7 @@ print_attr_string(netdissect_options *ndo, { case TUNNEL_PASS: if (length < 3) - { - ND_PRINT((ndo, "%s", tstr)); - return; - } + goto trunc; if (*data && (*data <=0x1F) ) ND_PRINT((ndo, "Tag[%u] ", *data)); else @@ -525,10 +522,7 @@ print_attr_string(netdissect_options *ndo, if (*data <= 0x1F) { if (length < 1) - { - ND_PRINT((ndo, "%s", tstr)); - return; - } + goto trunc; if (*data) ND_PRINT((ndo, "Tag[%u] ", *data)); else @@ -538,6 +532,8 @@ print_attr_string(netdissect_options *ndo, } break; case EGRESS_VLAN_NAME: + if (length < 1) + goto trunc; ND_PRINT((ndo, "%s (0x%02x) ", tok2str(rfc4675_tagged,"Unknown tag",*data), *data)); @@ -546,7 +542,7 @@ print_attr_string(netdissect_options *ndo, break; } - for (i=0; *data && i < length ; i++, data++) + for (i=0; i < length && *data; i++, data++) ND_PRINT((ndo, "%c", (*data < 32 || *data > 126) ? '.' : *data)); return; diff --git a/freebsd/contrib/tcpdump/print-resp.c b/freebsd/contrib/tcpdump/print-resp.c index bb89e13f..96e80b20 100644 --- a/freebsd/contrib/tcpdump/print-resp.c +++ b/freebsd/contrib/tcpdump/print-resp.c @@ -487,8 +487,10 @@ resp_get_length(netdissect_options *ndo, register const u_char *bp, int len, con ND_TCHECK(*bp); c = *bp; if (!(c >= '0' && c <= '9')) { - if (!saw_digit) + if (!saw_digit) { + bp++; goto invalid; + } break; } c -= '0'; @@ -497,7 +499,7 @@ resp_get_length(netdissect_options *ndo, register const u_char *bp, int len, con too_large = 1; } else { result *= 10; - if (result == INT_MAX && c > (INT_MAX % 10)) { + if (result == ((INT_MAX / 10) * 10) && c > (INT_MAX % 10)) { /* This will overflow an int when we add c */ too_large = 1; } else @@ -507,24 +509,24 @@ resp_get_length(netdissect_options *ndo, register const u_char *bp, int len, con len--; saw_digit = 1; } - if (!saw_digit) - goto invalid; /* - * OK, the next thing should be \r\n. + * OK, we found a non-digit character. It should be a \r, followed + * by a \n. */ - if (len == 0) - goto trunc; - ND_TCHECK(*bp); - if (*bp != '\r') + if (*bp != '\r') { + bp++; goto invalid; + } bp++; len--; if (len == 0) goto trunc; ND_TCHECK(*bp); - if (*bp != '\n') + if (*bp != '\n') { + bp++; goto invalid; + } bp++; len--; *endp = bp; @@ -537,9 +539,11 @@ resp_get_length(netdissect_options *ndo, register const u_char *bp, int len, con return (too_large ? -3 : result); trunc: + *endp = bp; return (-2); invalid: + *endp = bp; return (-5); } #ifdef __rtems__ diff --git a/freebsd/contrib/tcpdump/print-ripng.c b/freebsd/contrib/tcpdump/print-ripng.c index 95ec8322..87996c4f 100644 --- a/freebsd/contrib/tcpdump/print-ripng.c +++ b/freebsd/contrib/tcpdump/print-ripng.c @@ -116,67 +116,76 @@ ripng_print(netdissect_options *ndo, const u_char *dat, unsigned int length) { register const struct rip6 *rp = (const struct rip6 *)dat; register const struct netinfo6 *ni; - register u_int amt; - register u_int i; - int j; - int trunc; - - if (ndo->ndo_snapend < dat) - return; - amt = ndo->ndo_snapend - dat; - i = min(length, amt); - if (i < (sizeof(struct rip6) - sizeof(struct netinfo6))) - return; - i -= (sizeof(struct rip6) - sizeof(struct netinfo6)); + unsigned int length_left; + u_int j; + ND_TCHECK(rp->rip6_cmd); switch (rp->rip6_cmd) { case RIP6_REQUEST: - j = length / sizeof(*ni); - if (j == 1 - && rp->rip6_nets->rip6_metric == HOPCNT_INFINITY6 - && IN6_IS_ADDR_UNSPECIFIED(&rp->rip6_nets->rip6_dest)) { - ND_PRINT((ndo, " ripng-req dump")); - break; + length_left = length; + if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6))) + goto trunc; + length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6)); + j = length_left / sizeof(*ni); + if (j == 1) { + ND_TCHECK(rp->rip6_nets); + if (rp->rip6_nets->rip6_metric == HOPCNT_INFINITY6 + && IN6_IS_ADDR_UNSPECIFIED(&rp->rip6_nets->rip6_dest)) { + ND_PRINT((ndo, " ripng-req dump")); + break; + } } - if (j * sizeof(*ni) != length - 4) - ND_PRINT((ndo, " ripng-req %d[%u]:", j, length)); + if (j * sizeof(*ni) != length_left) + ND_PRINT((ndo, " ripng-req %u[%u]:", j, length)); else - ND_PRINT((ndo, " ripng-req %d:", j)); - trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i); - for (ni = rp->rip6_nets; i >= sizeof(*ni); - i -= sizeof(*ni), ++ni) { + ND_PRINT((ndo, " ripng-req %u:", j)); + for (ni = rp->rip6_nets; length_left >= sizeof(*ni); + length_left -= sizeof(*ni), ++ni) { + ND_TCHECK(*ni); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n\t")); else ND_PRINT((ndo, " ")); rip6_entry_print(ndo, ni, 0); } + if (length_left != 0) + goto trunc; break; case RIP6_RESPONSE: - j = length / sizeof(*ni); - if (j * sizeof(*ni) != length - 4) + length_left = length; + if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6))) + goto trunc; + length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6)); + j = length_left / sizeof(*ni); + if (j * sizeof(*ni) != length_left) ND_PRINT((ndo, " ripng-resp %d[%u]:", j, length)); else ND_PRINT((ndo, " ripng-resp %d:", j)); - trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i); - for (ni = rp->rip6_nets; i >= sizeof(*ni); - i -= sizeof(*ni), ++ni) { + for (ni = rp->rip6_nets; length_left >= sizeof(*ni); + length_left -= sizeof(*ni), ++ni) { + ND_TCHECK(*ni); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n\t")); else ND_PRINT((ndo, " ")); rip6_entry_print(ndo, ni, ni->rip6_metric); } - if (trunc) - ND_PRINT((ndo, "[|ripng]")); + if (length_left != 0) + goto trunc; break; default: ND_PRINT((ndo, " ripng-%d ?? %u", rp->rip6_cmd, length)); break; } + ND_TCHECK(rp->rip6_vers); if (rp->rip6_vers != RIP6_VERSION) ND_PRINT((ndo, " [vers %d]", rp->rip6_vers)); + return; + +trunc: + ND_PRINT((ndo, "[|ripng]")); + return; } #ifdef __rtems__ #include "rtems-bsd-tcpdump-print-ripng-data.h" diff --git a/freebsd/contrib/tcpdump/print-rpki-rtr.c b/freebsd/contrib/tcpdump/print-rpki-rtr.c index 17a9a566..e21f67dc 100644 --- a/freebsd/contrib/tcpdump/print-rpki-rtr.c +++ b/freebsd/contrib/tcpdump/print-rpki-rtr.c @@ -18,7 +18,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: Resource Public Key Infrastructure (RPKI) to Router Protocol printer */ @@ -88,6 +88,9 @@ typedef struct rpki_rtr_pdu_ipv6_prefix_ { typedef struct rpki_rtr_pdu_error_report_ { rpki_rtr_pdu pdu_header; u_char encapsulated_pdu_length[4]; /* Encapsulated PDU length */ + /* Copy of Erroneous PDU (variable, optional) */ + /* Length of Error Text (4 octets in network byte order) */ + /* Arbitrary Text of Error Diagnostic Message (variable, optional) */ } rpki_rtr_pdu_error_report; /* @@ -177,17 +180,38 @@ indent_string (u_int indent) /* * Print a single PDU. */ -static int -rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) +static u_int +rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, const u_int len, + const u_char recurse, const u_int indent) { const rpki_rtr_pdu *pdu_header; u_int pdu_type, pdu_len, hexdump; const u_char *msg; + /* Protocol Version */ + ND_TCHECK_8BITS(tptr); + if (*tptr != 0) { + /* Skip the rest of the input buffer because even if this is + * a well-formed PDU of a future RPKI-Router protocol version + * followed by a well-formed PDU of RPKI-Router protocol + * version 0, there is no way to know exactly how to skip the + * current PDU. + */ + ND_PRINT((ndo, "%sRPKI-RTRv%u (unknown)", indent_string(8), *tptr)); + return len; + } + if (len < sizeof(rpki_rtr_pdu)) { + ND_PRINT((ndo, "(%u bytes is too few to decode)", len)); + goto invalid; + } + ND_TCHECK2(*tptr, sizeof(rpki_rtr_pdu)); pdu_header = (const rpki_rtr_pdu *)tptr; pdu_type = pdu_header->pdu_type; pdu_len = EXTRACT_32BITS(pdu_header->length); - ND_TCHECK2(*tptr, pdu_len); + /* Do not check bounds with pdu_len yet, do it in the case blocks + * below to make it possible to decode at least the beginning of + * a truncated Error Report PDU or a truncated encapsulated PDU. + */ hexdump = FALSE; ND_PRINT((ndo, "%sRPKI-RTRv%u, %s PDU (%u), length: %u", @@ -195,6 +219,8 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) pdu_header->version, tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type), pdu_type, pdu_len)); + if (pdu_len < sizeof(rpki_rtr_pdu) || pdu_len > len) + goto invalid; switch (pdu_type) { @@ -204,6 +230,9 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) case RPKI_RTR_SERIAL_NOTIFY_PDU: case RPKI_RTR_SERIAL_QUERY_PDU: case RPKI_RTR_END_OF_DATA_PDU: + if (pdu_len != sizeof(rpki_rtr_pdu) + 4) + goto invalid; + ND_TCHECK2(*tptr, pdu_len); msg = (const u_char *)(pdu_header + 1); ND_PRINT((ndo, "%sSession ID: 0x%04x, Serial: %u", indent_string(indent+2), @@ -216,6 +245,9 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) */ case RPKI_RTR_RESET_QUERY_PDU: case RPKI_RTR_CACHE_RESET_PDU: + if (pdu_len != sizeof(rpki_rtr_pdu)) + goto invalid; + /* no additional boundary to check */ /* * Zero payload PDUs. @@ -223,6 +255,9 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) break; case RPKI_RTR_CACHE_RESPONSE_PDU: + if (pdu_len != sizeof(rpki_rtr_pdu)) + goto invalid; + /* no additional boundary to check */ ND_PRINT((ndo, "%sSession ID: 0x%04x", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.session_id))); @@ -232,6 +267,9 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) { const rpki_rtr_pdu_ipv4_prefix *pdu; + if (pdu_len != sizeof(rpki_rtr_pdu) + 12) + goto invalid; + ND_TCHECK2(*tptr, pdu_len); pdu = (const rpki_rtr_pdu_ipv4_prefix *)tptr; ND_PRINT((ndo, "%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), @@ -245,6 +283,9 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) { const rpki_rtr_pdu_ipv6_prefix *pdu; + if (pdu_len != sizeof(rpki_rtr_pdu) + 24) + goto invalid; + ND_TCHECK2(*tptr, pdu_len); pdu = (const rpki_rtr_pdu_ipv6_prefix *)tptr; ND_PRINT((ndo, "%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), @@ -259,10 +300,17 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) const rpki_rtr_pdu_error_report *pdu; u_int encapsulated_pdu_length, text_length, tlen, error_code; + tlen = sizeof(rpki_rtr_pdu); + /* Do not test for the "Length of Error Text" data element yet. */ + if (pdu_len < tlen + 4) + goto invalid; + ND_TCHECK2(*tptr, tlen + 4); + /* Safe up to and including the "Length of Encapsulated PDU" + * data element, more data elements may be present. + */ pdu = (const rpki_rtr_pdu_error_report *)tptr; encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length); - ND_TCHECK2(*tptr, encapsulated_pdu_length); - tlen = pdu_len; + tlen += 4; error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code); ND_PRINT((ndo, "%sError code: %s (%u), Encapsulated PDU length: %u", @@ -270,41 +318,58 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) tok2str(rpki_rtr_error_codes, "Unknown", error_code), error_code, encapsulated_pdu_length)); - tptr += sizeof(*pdu); - tlen -= sizeof(*pdu); - - /* - * Recurse if there is an encapsulated PDU. - */ - if (encapsulated_pdu_length && - (encapsulated_pdu_length <= tlen)) { - ND_PRINT((ndo, "%s-----encapsulated PDU-----", indent_string(indent+4))); - if (rpki_rtr_pdu_print(ndo, tptr, indent+2)) - goto trunc; + if (encapsulated_pdu_length) { + /* Section 5.10 of RFC 6810 says: + * "An Error Report PDU MUST NOT be sent for an Error Report PDU." + * + * However, as far as the protocol encoding goes Error Report PDUs can + * happen to be nested in each other, however many times, in which case + * the decoder should still print such semantically incorrect PDUs. + * + * That said, "the Erroneous PDU field MAY be truncated" (ibid), thus + * to keep things simple this implementation decodes only the two + * outermost layers of PDUs and makes bounds checks in the outer and + * the inner PDU independently. + */ + if (pdu_len < tlen + encapsulated_pdu_length) + goto invalid; + if (! recurse) { + ND_TCHECK2(*tptr, tlen + encapsulated_pdu_length); + } + else { + ND_PRINT((ndo, "%s-----encapsulated PDU-----", indent_string(indent+4))); + rpki_rtr_pdu_print(ndo, tptr + tlen, + encapsulated_pdu_length, 0, indent + 2); + } + tlen += encapsulated_pdu_length; } - tptr += encapsulated_pdu_length; - tlen -= encapsulated_pdu_length; + if (pdu_len < tlen + 4) + goto invalid; + ND_TCHECK2(*tptr, tlen + 4); + /* Safe up to and including the "Length of Error Text" data element, + * one more data element may be present. + */ /* * Extract, trail-zero and print the Error message. */ - text_length = 0; - if (tlen > 4) { - text_length = EXTRACT_32BITS(tptr); - tptr += 4; - tlen -= 4; - } - ND_TCHECK2(*tptr, text_length); - if (text_length && (text_length <= tlen )) { + text_length = EXTRACT_32BITS(tptr + tlen); + tlen += 4; + + if (text_length) { + if (pdu_len < tlen + text_length) + goto invalid; + /* fn_printn() makes the bounds check */ ND_PRINT((ndo, "%sError text: ", indent_string(indent+2))); - if (fn_printn(ndo, tptr, text_length, ndo->ndo_snapend)) + if (fn_printn(ndo, tptr + tlen, text_length, ndo->ndo_snapend)) goto trunc; } } break; default: + ND_TCHECK2(*tptr, pdu_len); /* * Unknown data, please hexdump. @@ -316,57 +381,29 @@ rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) { print_unknown_data(ndo,tptr,"\n\t ", pdu_len); } - return 0; + return pdu_len; +invalid: + ND_PRINT((ndo, "%s", istr)); + ND_TCHECK2(*tptr, len); + return len; trunc: - return 1; + ND_PRINT((ndo, "\n\t%s", tstr)); + return len; } void rpki_rtr_print(netdissect_options *ndo, register const u_char *pptr, register u_int len) { - u_int tlen, pdu_type, pdu_len; - const u_char *tptr; - const rpki_rtr_pdu *pdu_header; - - tptr = pptr; - tlen = len; - if (!ndo->ndo_vflag) { ND_PRINT((ndo, ", RPKI-RTR")); return; } - - while (tlen >= sizeof(rpki_rtr_pdu)) { - - ND_TCHECK2(*tptr, sizeof(rpki_rtr_pdu)); - - pdu_header = (const rpki_rtr_pdu *)tptr; - pdu_type = pdu_header->pdu_type; - pdu_len = EXTRACT_32BITS(pdu_header->length); - ND_TCHECK2(*tptr, pdu_len); - - /* infinite loop check */ - if (!pdu_type || !pdu_len) { - break; - } - - if (tlen < pdu_len) { - goto trunc; - } - - /* - * Print the PDU. - */ - if (rpki_rtr_pdu_print(ndo, tptr, 8)) - goto trunc; - - tlen -= pdu_len; - tptr += pdu_len; + while (len) { + u_int pdu_len = rpki_rtr_pdu_print(ndo, pptr, len, 1, 8); + len -= pdu_len; + pptr += pdu_len; } - return; -trunc: - ND_PRINT((ndo, "\n\t%s", tstr)); } /* diff --git a/freebsd/contrib/tcpdump/print-rsvp.c b/freebsd/contrib/tcpdump/print-rsvp.c index 727f2db1..102757d0 100644 --- a/freebsd/contrib/tcpdump/print-rsvp.c +++ b/freebsd/contrib/tcpdump/print-rsvp.c @@ -18,7 +18,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: Resource ReSerVation Protocol (RSVP) printer */ @@ -1211,6 +1211,17 @@ rsvp_obj_print(netdissect_options *ndo, /* read variable length subobjects */ total_subobj_len = obj_tlen; while(total_subobj_len > 0) { + /* If RFC 3476 Section 3.1 defined that a sub-object of the + * GENERALIZED_UNI RSVP object must have the Length field as + * a multiple of 4, instead of the check below it would be + * better to test total_subobj_len only once before the loop. + * So long as it does not define it and this while loop does + * not implement such a requirement, let's accept that within + * each iteration subobj_len may happen to be a multiple of 1 + * and test it and total_subobj_len respectively. + */ + if (total_subobj_len < 4) + goto invalid; subobj_len = EXTRACT_16BITS(obj_tptr); subobj_type = (EXTRACT_16BITS(obj_tptr+2))>>8; af = (EXTRACT_16BITS(obj_tptr+2))&0x00FF; @@ -1222,7 +1233,13 @@ rsvp_obj_print(netdissect_options *ndo, tok2str(af_values, "Unknown", af), af, subobj_len)); - if(subobj_len == 0) + /* In addition to what is explained above, the same spec does not + * explicitly say that the same Length field includes the 4-octet + * sub-object header, but as long as this while loop implements it + * as it does include, let's keep the check below consistent with + * the rest of the code. + */ + if(subobj_len < 4 || subobj_len > total_subobj_len) goto invalid; switch(subobj_type) { @@ -1478,12 +1495,12 @@ rsvp_obj_print(netdissect_options *ndo, case RSVP_OBJ_FASTREROUTE: /* the differences between c-type 1 and 7 are minor */ obj_ptr.rsvp_obj_frr = (const struct rsvp_obj_frr_t *)obj_tptr; - bw.i = EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->bandwidth); switch(rsvp_obj_ctype) { case RSVP_CTYPE_1: /* new style */ if (obj_tlen < sizeof(struct rsvp_obj_frr_t)) return-1; + bw.i = EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->bandwidth); ND_PRINT((ndo, "%s Setup Priority: %u, Holding Priority: %u, Hop-limit: %u, Bandwidth: %.10g Mbps", ident, (int)obj_ptr.rsvp_obj_frr->setup_prio, @@ -1502,6 +1519,7 @@ rsvp_obj_print(netdissect_options *ndo, case RSVP_CTYPE_TUNNEL_IPV4: /* old style */ if (obj_tlen < 16) return-1; + bw.i = EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->bandwidth); ND_PRINT((ndo, "%s Setup Priority: %u, Holding Priority: %u, Hop-limit: %u, Bandwidth: %.10g Mbps", ident, (int)obj_ptr.rsvp_obj_frr->setup_prio, diff --git a/freebsd/contrib/tcpdump/print-rt6.c b/freebsd/contrib/tcpdump/print-rt6.c index 5ab86c6c..09784ab9 100644 --- a/freebsd/contrib/tcpdump/print-rt6.c +++ b/freebsd/contrib/tcpdump/print-rt6.c @@ -35,12 +35,12 @@ #include <string.h> -#include "ip6.h" - #include "netdissect.h" #include "addrtoname.h" #include "extract.h" +#include "ip6.h" + int rt6_print(netdissect_options *ndo, register const u_char *bp, const u_char *bp2 _U_) { @@ -51,13 +51,13 @@ rt6_print(netdissect_options *ndo, register const u_char *bp, const u_char *bp2 register const struct in6_addr *addr; dp = (const struct ip6_rthdr *)bp; - len = dp->ip6r_len; /* 'ep' points to the end of available data. */ ep = ndo->ndo_snapend; ND_TCHECK(dp->ip6r_segleft); + len = dp->ip6r_len; ND_PRINT((ndo, "srcrt (len=%d", dp->ip6r_len)); /*)*/ ND_PRINT((ndo, ", type=%d", dp->ip6r_type)); ND_PRINT((ndo, ", segleft=%d", dp->ip6r_segleft)); @@ -68,7 +68,7 @@ rt6_print(netdissect_options *ndo, register const u_char *bp, const u_char *bp2 dp0 = (const struct ip6_rthdr0 *)dp; ND_TCHECK(dp0->ip6r0_reserved); - if (dp0->ip6r0_reserved || ndo->ndo_vflag) { + if (EXTRACT_32BITS(dp0->ip6r0_reserved) || ndo->ndo_vflag) { ND_PRINT((ndo, ", rsv=0x%0x", EXTRACT_32BITS(&dp0->ip6r0_reserved))); } diff --git a/freebsd/contrib/tcpdump/print-rx.c b/freebsd/contrib/tcpdump/print-rx.c index 46342c2e..e7e369bf 100644 --- a/freebsd/contrib/tcpdump/print-rx.c +++ b/freebsd/contrib/tcpdump/print-rx.c @@ -81,12 +81,12 @@ #define PRSFS_ADMINISTER 64 /* Change ACL's */ struct rx_header { - uint32_t epoch; - uint32_t cid; - uint32_t callNumber; - uint32_t seq; - uint32_t serial; - uint8_t type; + nd_uint32_t epoch; + nd_uint32_t cid; + nd_uint32_t callNumber; + nd_uint32_t seq; + nd_uint32_t serial; + nd_uint8_t type; #define RX_PACKET_TYPE_DATA 1 #define RX_PACKET_TYPE_ACK 2 #define RX_PACKET_TYPE_BUSY 3 @@ -97,7 +97,7 @@ struct rx_header { #define RX_PACKET_TYPE_DEBUG 8 #define RX_PACKET_TYPE_PARAMS 9 #define RX_PACKET_TYPE_VERSION 13 - uint8_t flags; + nd_uint8_t flags; #define RX_CLIENT_INITIATED 1 #define RX_REQUEST_ACK 2 #define RX_LAST_PACKET 4 @@ -105,10 +105,10 @@ struct rx_header { #define RX_FREE_PACKET 16 #define RX_SLOW_START_OK 32 #define RX_JUMBO_PACKET 32 - uint8_t userStatus; - uint8_t securityIndex; - uint16_t spare; /* How clever: even though the AFS */ - uint16_t serviceId; /* header files indicate that the */ + nd_uint8_t userStatus; + nd_uint8_t securityIndex; + nd_uint16_t spare; /* How clever: even though the AFS */ + nd_uint16_t serviceId; /* header files indicate that the */ }; /* serviceId is first, it's really */ /* encoded _after_ the spare field */ /* I wasted a day figuring that out! */ @@ -696,11 +696,11 @@ rx_cache_insert(netdissect_options *ndo, if (++rx_cache_next >= RX_CACHE_SIZE) rx_cache_next = 0; - rxent->callnum = rxh->callNumber; + rxent->callnum = EXTRACT_32BITS(&rxh->callNumber); UNALIGNED_MEMCPY(&rxent->client, &ip->ip_src, sizeof(uint32_t)); UNALIGNED_MEMCPY(&rxent->server, &ip->ip_dst, sizeof(uint32_t)); rxent->dport = dport; - rxent->serviceId = rxh->serviceId; + rxent->serviceId = EXTRACT_32BITS(&rxh->serviceId); rxent->opcode = EXTRACT_32BITS(bp + sizeof(struct rx_header)); } @@ -728,10 +728,10 @@ rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport, i = rx_cache_hint; do { rxent = &rx_cache[i]; - if (rxent->callnum == rxh->callNumber && + if (rxent->callnum == EXTRACT_32BITS(&rxh->callNumber) && rxent->client.s_addr == clip && rxent->server.s_addr == sip && - rxent->serviceId == rxh->serviceId && + rxent->serviceId == EXTRACT_32BITS(&rxh->serviceId) && rxent->dport == sport) { /* We got a match! */ @@ -1268,6 +1268,7 @@ cb_print(netdissect_options *ndo, if (j == 0) ND_PRINT((ndo, " <none!>")); + ND_TCHECK_32BITS(bp); j = EXTRACT_32BITS(bp); bp += sizeof(int32_t); @@ -2539,6 +2540,10 @@ ubik_print(netdissect_options *ndo, * gleaned from ubik/ubik_int.xg */ + /* Every function that calls this function first makes a bounds check + * for (sizeof(rx_header) + 4) bytes, so long as it remains this way + * the line below will not over-read. + */ ubik_op = EXTRACT_32BITS(bp + sizeof(struct rx_header)); ND_PRINT((ndo, " ubik call %s", tok2str(ubik_req, "op#%d", ubik_op))); @@ -2583,6 +2588,7 @@ ubik_print(netdissect_options *ndo, INTOUT(); ND_PRINT((ndo, " length")); INTOUT(); + ND_TCHECK_32BITS(bp); temp = EXTRACT_32BITS(bp); bp += sizeof(int32_t); tok2str(ubik_lock_types, "type %d", temp); diff --git a/freebsd/contrib/tcpdump/print-sip.c b/freebsd/contrib/tcpdump/print-sip.c index 6f968bca..a922d87a 100644 --- a/freebsd/contrib/tcpdump/print-sip.c +++ b/freebsd/contrib/tcpdump/print-sip.c @@ -16,7 +16,7 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) * Turned into common "text protocol" code, which this uses, by * Guy Harris. */ diff --git a/freebsd/contrib/tcpdump/print-sl.c b/freebsd/contrib/tcpdump/print-sl.c index b318f322..faaa5ba7 100644 --- a/freebsd/contrib/tcpdump/print-sl.c +++ b/freebsd/contrib/tcpdump/print-sl.c @@ -137,8 +137,21 @@ sliplink_print(netdissect_options *ndo, u_int hlen; dir = p[SLX_DIR]; - ND_PRINT((ndo, dir == SLIPDIR_IN ? "I " : "O ")); + switch (dir) { + case SLIPDIR_IN: + ND_PRINT((ndo, "I ")); + break; + + case SLIPDIR_OUT: + ND_PRINT((ndo, "O ")); + break; + + default: + ND_PRINT((ndo, "Invalid direction %d ", dir)); + dir = -1; + break; + } if (ndo->ndo_nflag) { /* XXX just dump the header */ register int i; @@ -161,13 +174,21 @@ sliplink_print(netdissect_options *ndo, * has restored the IP header copy to IPPROTO_TCP. */ lastconn = ((const struct ip *)&p[SLX_CHDR])->ip_p; + ND_PRINT((ndo, "utcp %d: ", lastconn)); + if (dir == -1) { + /* Direction is bogus, don't use it */ + return; + } hlen = IP_HL(ip); hlen += TH_OFF((const struct tcphdr *)&((const int *)ip)[hlen]); lastlen[dir][lastconn] = length - (hlen << 2); - ND_PRINT((ndo, "utcp %d: ", lastconn)); break; default: + if (dir == -1) { + /* Direction is bogus, don't use it */ + return; + } if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { compressed_sl_print(ndo, &p[SLX_CHDR], ip, length, dir); diff --git a/freebsd/contrib/tcpdump/print-slow.c b/freebsd/contrib/tcpdump/print-slow.c index fe54052f..a5417c0b 100644 --- a/freebsd/contrib/tcpdump/print-slow.c +++ b/freebsd/contrib/tcpdump/print-slow.c @@ -21,7 +21,7 @@ * support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad * OAM as per 802.3ah * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: IEEE "slow protocols" (802.3ad/802.3ah) printer */ diff --git a/freebsd/contrib/tcpdump/print-stp.c b/freebsd/contrib/tcpdump/print-stp.c index e816cf98..ef7f36c8 100644 --- a/freebsd/contrib/tcpdump/print-stp.c +++ b/freebsd/contrib/tcpdump/print-stp.c @@ -262,6 +262,7 @@ stp_print_mstp_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu, return 1; } + ND_TCHECK(stp_bpdu->flags); ND_PRINT((ndo, "\n\tport-role %s, ", tok2str(rstp_obj_port_role_values, "Unknown", RSTP_EXTRACT_PORT_ROLE(stp_bpdu->flags)))); @@ -481,6 +482,7 @@ stp_print(netdissect_options *ndo, const u_char *p, u_int length) if (stp_bpdu->protocol_version == STP_PROTO_SPB) { /* Validate v4 length */ + ND_TCHECK_16BITS(p + MST_BPDU_VER3_LEN_OFFSET + mstp_len); spb_len = EXTRACT_16BITS (p + MST_BPDU_VER3_LEN_OFFSET + mstp_len); spb_len += 2; if (length < (sizeof(struct stp_bpdu_) + mstp_len + spb_len) || diff --git a/freebsd/contrib/tcpdump/print-syslog.c b/freebsd/contrib/tcpdump/print-syslog.c index a79a1660..81140339 100644 --- a/freebsd/contrib/tcpdump/print-syslog.c +++ b/freebsd/contrib/tcpdump/print-syslog.c @@ -5,7 +5,7 @@ #include "rtems-bsd-tcpdump-namespace.h" #endif /* __rtems__ */ /* - * Copyright (c) 1998-2004 Hannes Gredler <hannes@tcpdump.org> + * Copyright (c) 1998-2004 Hannes Gredler <hannes@gredler.at> * The TCPDUMP project * * Redistribution and use in source and binary forms, with or without diff --git a/freebsd/contrib/tcpdump/print-telnet.c b/freebsd/contrib/tcpdump/print-telnet.c index 4d5ab780..5d1e52cd 100644 --- a/freebsd/contrib/tcpdump/print-telnet.c +++ b/freebsd/contrib/tcpdump/print-telnet.c @@ -448,6 +448,7 @@ telnet_parse(netdissect_options *ndo, const u_char *sp, u_int length, int print) break; p++; } + ND_TCHECK(*p); if (*p != IAC) goto pktend; diff --git a/freebsd/contrib/tcpdump/print-tftp.c b/freebsd/contrib/tcpdump/print-tftp.c index a2577e3f..bf4ac34e 100644 --- a/freebsd/contrib/tcpdump/print-tftp.c +++ b/freebsd/contrib/tcpdump/print-tftp.c @@ -52,21 +52,6 @@ #define TFTP_ERROR 05 /* error code */ #define OACK 06 /* option acknowledgement */ -struct tftphdr { - unsigned short th_opcode; /* packet type */ - union { - unsigned short tu_block; /* block # */ - unsigned short tu_code; /* error code */ - char tu_stuff[1]; /* request packet stuff */ - } th_u; - char th_data[1]; /* data or error string */ -}; - -#define th_block th_u.tu_block -#define th_code th_u.tu_code -#define th_stuff th_u.tu_stuff -#define th_msg th_data - /* * Error codes. */ @@ -112,80 +97,75 @@ void tftp_print(netdissect_options *ndo, register const u_char *bp, u_int length) { - register const struct tftphdr *tp; register const char *cp; - register const u_char *p; register int opcode; u_int ui; - tp = (const struct tftphdr *)bp; - /* Print length */ ND_PRINT((ndo, " %d", length)); /* Print tftp request type */ if (length < 2) goto trunc; - ND_TCHECK(tp->th_opcode); - opcode = EXTRACT_16BITS(&tp->th_opcode); + ND_TCHECK_16BITS(bp); + opcode = EXTRACT_16BITS(bp); cp = tok2str(op2str, "tftp-#%d", opcode); - length -= 2; ND_PRINT((ndo, " %s", cp)); /* Bail if bogus opcode */ if (*cp == 't') return; + bp += 2; + length -= 2; switch (opcode) { case RRQ: case WRQ: - p = (const u_char *)tp->th_stuff; if (length == 0) goto trunc; ND_PRINT((ndo, " ")); /* Print filename */ ND_PRINT((ndo, "\"")); - ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); + ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); ND_PRINT((ndo, "\"")); if (ui == 0) goto trunc; - p += ui; + bp += ui; length -= ui; /* Print the mode - RRQ and WRQ only */ if (length == 0) goto trunc; /* no mode */ ND_PRINT((ndo, " ")); - ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); + ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); if (ui == 0) goto trunc; - p += ui; + bp += ui; length -= ui; /* Print options, if any */ while (length != 0) { - ND_TCHECK(*p); - if (*p != '\0') + ND_TCHECK(*bp); + if (*bp != '\0') ND_PRINT((ndo, " ")); - ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); + ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); if (ui == 0) goto trunc; - p += ui; + bp += ui; length -= ui; } break; case OACK: - p = (const u_char *)tp->th_stuff; /* Print options */ while (length != 0) { - ND_TCHECK(*p); - if (*p != '\0') + ND_TCHECK(*bp); + if (*bp != '\0') ND_PRINT((ndo, " ")); - ui = fn_printztn(ndo, p, length, ndo->ndo_snapend); + ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); if (ui == 0) goto trunc; - p += ui; + bp += ui; length -= ui; } break; @@ -194,23 +174,24 @@ tftp_print(netdissect_options *ndo, case DATA: if (length < 2) goto trunc; /* no block number */ - ND_TCHECK(tp->th_block); - ND_PRINT((ndo, " block %d", EXTRACT_16BITS(&tp->th_block))); + ND_TCHECK_16BITS(bp); + ND_PRINT((ndo, " block %d", EXTRACT_16BITS(bp))); break; case TFTP_ERROR: /* Print error code string */ if (length < 2) goto trunc; /* no error code */ - ND_TCHECK(tp->th_code); + ND_TCHECK_16BITS(bp); ND_PRINT((ndo, " %s", tok2str(err2str, "tftp-err-#%d \"", - EXTRACT_16BITS(&tp->th_code)))); + EXTRACT_16BITS(bp)))); + bp += 2; length -= 2; /* Print error message string */ if (length == 0) goto trunc; /* no error message */ ND_PRINT((ndo, " \"")); - ui = fn_printztn(ndo, (const u_char *)tp->th_data, length, ndo->ndo_snapend); + ui = fn_printztn(ndo, bp, length, ndo->ndo_snapend); ND_PRINT((ndo, "\"")); if (ui == 0) goto trunc; diff --git a/freebsd/contrib/tcpdump/print-vqp.c b/freebsd/contrib/tcpdump/print-vqp.c index 7c4e40da..5a7ca2d1 100644 --- a/freebsd/contrib/tcpdump/print-vqp.c +++ b/freebsd/contrib/tcpdump/print-vqp.c @@ -32,6 +32,7 @@ #include "netdissect.h" #include "extract.h" #include "addrtoname.h" +#include "ether.h" #define VQP_VERSION 1 #define VQP_EXTRACT_VERSION(x) ((x)&0xFF) @@ -111,13 +112,15 @@ vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int l const u_char *tptr; uint16_t vqp_obj_len; uint32_t vqp_obj_type; - int tlen; + u_int tlen; uint8_t nitems; tptr=pptr; tlen = len; vqp_common_header = (const struct vqp_common_header_t *)pptr; ND_TCHECK(*vqp_common_header); + if (sizeof(struct vqp_common_header_t) > tlen) + goto trunc; /* * Sanity checking of the header. @@ -157,6 +160,9 @@ vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int l while (nitems > 0 && tlen > 0) { vqp_obj_tlv = (const struct vqp_obj_tlv_t *)tptr; + ND_TCHECK(*vqp_obj_tlv); + if (sizeof(struct vqp_obj_tlv_t) > tlen) + goto trunc; vqp_obj_type = EXTRACT_32BITS(vqp_obj_tlv->obj_type); vqp_obj_len = EXTRACT_16BITS(vqp_obj_tlv->obj_length); tptr+=sizeof(struct vqp_obj_tlv_t); @@ -173,9 +179,13 @@ vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int l /* did we capture enough for fully decoding the object ? */ ND_TCHECK2(*tptr, vqp_obj_len); + if (vqp_obj_len > tlen) + goto trunc; switch(vqp_obj_type) { case VQP_OBJ_IP_ADDRESS: + if (vqp_obj_len != 4) + goto trunc; ND_PRINT((ndo, "%s (0x%08x)", ipaddr_string(ndo, tptr), EXTRACT_32BITS(tptr))); break; /* those objects have similar semantics - fall through */ @@ -188,6 +198,8 @@ vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int l /* those objects have similar semantics - fall through */ case VQP_OBJ_MAC_ADDRESS: case VQP_OBJ_MAC_NULL: + if (vqp_obj_len != ETHER_ADDR_LEN) + goto trunc; ND_PRINT((ndo, "%s", etheraddr_string(ndo, tptr))); break; default: diff --git a/freebsd/contrib/tcpdump/print-vtp.c b/freebsd/contrib/tcpdump/print-vtp.c index 18e2d925..8f8d236b 100644 --- a/freebsd/contrib/tcpdump/print-vtp.c +++ b/freebsd/contrib/tcpdump/print-vtp.c @@ -19,9 +19,8 @@ * FOR A PARTICULAR PURPOSE. * * Reference documentation: - * http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml - * http://www.cisco.com/warp/public/473/21.html - * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm + * http://www.cisco.com/c/en/us/support/docs/lan-switching/vtp/10558-21.html + * http://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm * * Original code ode by Carles Kishimoto <carles.kishimoto@gmail.com> */ @@ -42,7 +41,7 @@ #define VTP_DOMAIN_NAME_LEN 32 #define VTP_MD5_DIGEST_LEN 16 #define VTP_UPDATE_TIMESTAMP_LEN 12 -#define VTP_VLAN_INFO_OFFSET 12 +#define VTP_VLAN_INFO_FIXED_PART_LEN 12 /* length of VLAN info before VLAN name */ #define VTP_SUMMARY_ADV 0x01 #define VTP_SUBSET_ADV 0x02 @@ -229,6 +228,7 @@ vtp_print (netdissect_options *ndo, * */ + ND_TCHECK_32BITS(tptr); ND_PRINT((ndo, ", Config Rev %x", EXTRACT_32BITS(tptr))); /* @@ -249,6 +249,7 @@ vtp_print (netdissect_options *ndo, tptr += 4; while (tptr < (pptr+length)) { + ND_TCHECK_8BITS(tptr); len = *tptr; if (len == 0) break; @@ -256,6 +257,8 @@ vtp_print (netdissect_options *ndo, ND_TCHECK2(*tptr, len); vtp_vlan = (const struct vtp_vlan_*)tptr; + if (len < VTP_VLAN_INFO_FIXED_PART_LEN) + goto trunc; ND_TCHECK(*vtp_vlan); ND_PRINT((ndo, "\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name ", tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status), @@ -263,22 +266,33 @@ vtp_print (netdissect_options *ndo, EXTRACT_16BITS(&vtp_vlan->vlanid), EXTRACT_16BITS(&vtp_vlan->mtu), EXTRACT_32BITS(&vtp_vlan->index))); - fn_printzp(ndo, tptr + VTP_VLAN_INFO_OFFSET, vtp_vlan->name_len, NULL); - - /* - * Vlan names are aligned to 32-bit boundaries. - */ - len -= VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); - tptr += VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); + len -= VTP_VLAN_INFO_FIXED_PART_LEN; + tptr += VTP_VLAN_INFO_FIXED_PART_LEN; + if (len < 4*((vtp_vlan->name_len + 3)/4)) + goto trunc; + ND_TCHECK2(*tptr, vtp_vlan->name_len); + fn_printzp(ndo, tptr, vtp_vlan->name_len, NULL); + + /* + * Vlan names are aligned to 32-bit boundaries. + */ + len -= 4*((vtp_vlan->name_len + 3)/4); + tptr += 4*((vtp_vlan->name_len + 3)/4); /* TLV information follows */ while (len > 0) { /* - * Cisco specs says 2 bytes for type + 2 bytes for length, take only 1 - * See: http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm + * Cisco specs say 2 bytes for type + 2 bytes for length; + * see http://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm + * However, actual packets on the wire appear to use 1 + * byte for the type and 1 byte for the length, so that's + * what we do. */ + if (len < 2) + goto trunc; + ND_TCHECK2(*tptr, 2); type = *tptr; tlv_len = *(tptr+1); @@ -286,59 +300,65 @@ vtp_print (netdissect_options *ndo, tok2str(vtp_vlan_tlv_values, "Unknown", type), type)); - /* - * infinite loop check - */ - if (type == 0 || tlv_len == 0) { + if (len < tlv_len * 2 + 2) { + ND_PRINT((ndo, " (TLV goes past the end of the packet)")); return; } - ND_TCHECK2(*tptr, tlv_len * 2 +2); - tlv_value = EXTRACT_16BITS(tptr+2); - - switch (type) { - case VTP_VLAN_STE_HOP_COUNT: - ND_PRINT((ndo, ", %u", tlv_value)); - break; - - case VTP_VLAN_PRUNING: - ND_PRINT((ndo, ", %s (%u)", - tlv_value == 1 ? "Enabled" : "Disabled", - tlv_value)); - break; - - case VTP_VLAN_STP_TYPE: - ND_PRINT((ndo, ", %s (%u)", - tok2str(vtp_stp_type_values, "Unknown", tlv_value), - tlv_value)); - break; - - case VTP_VLAN_BRIDGE_TYPE: - ND_PRINT((ndo, ", %s (%u)", - tlv_value == 1 ? "SRB" : "SRT", - tlv_value)); - break; - - case VTP_VLAN_BACKUP_CRF_MODE: - ND_PRINT((ndo, ", %s (%u)", - tlv_value == 1 ? "Backup" : "Not backup", - tlv_value)); - break; - - /* - * FIXME those are the defined TLVs that lack a decoder - * you are welcome to contribute code ;-) - */ - - case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: - case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: - case VTP_VLAN_PARENT_VLAN: - case VTP_VLAN_TRANS_BRIDGED_VLAN: - case VTP_VLAN_ARP_HOP_COUNT: - default: - print_unknown_data(ndo, tptr, "\n\t\t ", 2 + tlv_len*2); - break; + /* + * We assume the value is a 2-byte integer; the length is + * in units of 16-bit words. + */ + if (tlv_len != 1) { + ND_PRINT((ndo, " (invalid TLV length %u != 1)", tlv_len)); + return; + } else { + tlv_value = EXTRACT_16BITS(tptr+2); + + switch (type) { + case VTP_VLAN_STE_HOP_COUNT: + ND_PRINT((ndo, ", %u", tlv_value)); + break; + + case VTP_VLAN_PRUNING: + ND_PRINT((ndo, ", %s (%u)", + tlv_value == 1 ? "Enabled" : "Disabled", + tlv_value)); + break; + + case VTP_VLAN_STP_TYPE: + ND_PRINT((ndo, ", %s (%u)", + tok2str(vtp_stp_type_values, "Unknown", tlv_value), + tlv_value)); + break; + + case VTP_VLAN_BRIDGE_TYPE: + ND_PRINT((ndo, ", %s (%u)", + tlv_value == 1 ? "SRB" : "SRT", + tlv_value)); + break; + + case VTP_VLAN_BACKUP_CRF_MODE: + ND_PRINT((ndo, ", %s (%u)", + tlv_value == 1 ? "Backup" : "Not backup", + tlv_value)); + break; + + /* + * FIXME those are the defined TLVs that lack a decoder + * you are welcome to contribute code ;-) + */ + + case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: + case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: + case VTP_VLAN_PARENT_VLAN: + case VTP_VLAN_TRANS_BRIDGED_VLAN: + case VTP_VLAN_ARP_HOP_COUNT: + default: + print_unknown_data(ndo, tptr, "\n\t\t ", 2 + tlv_len*2); + break; + } } len -= 2 + tlv_len*2; tptr += 2 + tlv_len*2; diff --git a/freebsd/contrib/tcpdump/print-wb.c b/freebsd/contrib/tcpdump/print-wb.c index 60892bbd..aeab01c3 100644 --- a/freebsd/contrib/tcpdump/print-wb.c +++ b/freebsd/contrib/tcpdump/print-wb.c @@ -269,9 +269,8 @@ wb_prep(netdissect_options *ndo, const u_char *ep = ndo->ndo_snapend; ND_PRINT((ndo, " wb-prep:")); - if (len < sizeof(*prep)) { + if (len < sizeof(*prep) || !ND_TTEST(*prep)) return (-1); - } n = EXTRACT_32BITS(&prep->pp_n); ps = (const struct pgstate *)(prep + 1); while (--n >= 0 && ND_TTEST(*ps)) { @@ -425,31 +424,37 @@ wb_print(netdissect_options *ndo, case PT_ID: if (wb_id(ndo, (const struct pkt_id *)(ph + 1), len) >= 0) return; + ND_PRINT((ndo, "%s", tstr)); break; case PT_RREQ: if (wb_rreq(ndo, (const struct pkt_rreq *)(ph + 1), len) >= 0) return; + ND_PRINT((ndo, "%s", tstr)); break; case PT_RREP: if (wb_rrep(ndo, (const struct pkt_rrep *)(ph + 1), len) >= 0) return; + ND_PRINT((ndo, "%s", tstr)); break; case PT_DRAWOP: if (wb_drawop(ndo, (const struct pkt_dop *)(ph + 1), len) >= 0) return; + ND_PRINT((ndo, "%s", tstr)); break; case PT_PREQ: if (wb_preq(ndo, (const struct pkt_preq *)(ph + 1), len) >= 0) return; + ND_PRINT((ndo, "%s", tstr)); break; case PT_PREP: if (wb_prep(ndo, (const struct pkt_prep *)(ph + 1), len) >= 0) return; + ND_PRINT((ndo, "%s", tstr)); break; default: diff --git a/freebsd/contrib/tcpdump/print-zephyr.c b/freebsd/contrib/tcpdump/print-zephyr.c index f44c3057..630c7095 100644 --- a/freebsd/contrib/tcpdump/print-zephyr.c +++ b/freebsd/contrib/tcpdump/print-zephyr.c @@ -82,30 +82,41 @@ static const struct tok z_types[] = { { Z_PACKET_SERVACK, "serv-ack" }, { Z_PACKET_SERVNAK, "serv-nak" }, { Z_PACKET_CLIENTACK, "client-ack" }, - { Z_PACKET_STAT, "stat" } + { Z_PACKET_STAT, "stat" }, + { 0, NULL } }; static char z_buf[256]; static const char * -parse_field(netdissect_options *ndo, const char **pptr, int *len) +parse_field(netdissect_options *ndo, const char **pptr, int *len, int *truncated) { const char *s; - if (*len <= 0 || !pptr || !*pptr) - return NULL; - if (*pptr > (const char *) ndo->ndo_snapend) - return NULL; - + /* Start of string */ s = *pptr; - while (*pptr <= (const char *) ndo->ndo_snapend && *len >= 0 && **pptr) { + /* Scan for the NUL terminator */ + for (;;) { + if (*len == 0) { + /* Ran out of packet data without finding it */ + return NULL; + } + if (!ND_TTEST(**pptr)) { + /* Ran out of captured data without finding it */ + *truncated = 1; + return NULL; + } + if (**pptr == '\0') { + /* Found it */ + break; + } + /* Keep scanning */ (*pptr)++; (*len)--; } + /* Skip the NUL terminator */ (*pptr)++; (*len)--; - if (*len < 0 || *pptr > (const char *) ndo->ndo_snapend) - return NULL; return s; } @@ -144,6 +155,7 @@ zephyr_print(netdissect_options *ndo, const u_char *cp, int length) int parselen = length; const char *s; int lose = 0; + int truncated = 0; /* squelch compiler warnings */ @@ -154,8 +166,9 @@ zephyr_print(netdissect_options *ndo, const u_char *cp, int length) z.sender = 0; z.recipient = 0; -#define PARSE_STRING \ - s = parse_field(ndo, &parse, &parselen); \ +#define PARSE_STRING \ + s = parse_field(ndo, &parse, &parselen, &truncated); \ + if (truncated) goto trunc; \ if (!s) lose = 1; #define PARSE_FIELD_INT(field) \ @@ -188,10 +201,8 @@ zephyr_print(netdissect_options *ndo, const u_char *cp, int length) PARSE_FIELD_INT(z.multi); PARSE_FIELD_STR(z.multi_uid); - if (lose) { - ND_PRINT((ndo, " [|zephyr] (%d)", length)); - return; - } + if (lose) + goto trunc; ND_PRINT((ndo, " zephyr")); if (strncmp(z.version+4, "0.2", 3)) { @@ -323,6 +334,11 @@ zephyr_print(netdissect_options *ndo, const u_char *cp, int length) ND_PRINT((ndo, " to %s", z_triple(z.class, z.inst, z.recipient))); if (*z.opcode) ND_PRINT((ndo, " op %s", z.opcode)); + return; + +trunc: + ND_PRINT((ndo, " [|zephyr] (%d)", length)); + return; } #ifdef __rtems__ #include "rtems-bsd-tcpdump-print-zephyr-data.h" diff --git a/freebsd/contrib/tcpdump/print.c b/freebsd/contrib/tcpdump/print.c index 767a235e..2bbfc04b 100644 --- a/freebsd/contrib/tcpdump/print.c +++ b/freebsd/contrib/tcpdump/print.c @@ -232,23 +232,16 @@ static const struct printer printers[] = { static void ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length); -static void ndo_error(netdissect_options *ndo, const char *fmt, ...) - __attribute__((noreturn)) -#ifdef __ATTRIBUTE___FORMAT_OK - __attribute__((format (printf, 2, 3))) -#endif /* __ATTRIBUTE___FORMAT_OK */ - ; -static void ndo_warning(netdissect_options *ndo, const char *fmt, ...) -#ifdef __ATTRIBUTE___FORMAT_OK - __attribute__((format (printf, 2, 3))) -#endif /* __ATTRIBUTE___FORMAT_OK */ - ; - -static int ndo_printf(netdissect_options *ndo, const char *fmt, ...) -#ifdef __ATTRIBUTE___FORMAT_OK - __attribute ((format (printf, 2, 3))) -#endif /* __ATTRIBUTE___FORMAT_OK */ - ; +static void ndo_error(netdissect_options *ndo, + FORMAT_STRING(const char *fmt), ...) + NORETURN PRINTFLIKE(2, 3); +static void ndo_warning(netdissect_options *ndo, + FORMAT_STRING(const char *fmt), ...) + PRINTFLIKE(2, 3); + +static int ndo_printf(netdissect_options *ndo, + FORMAT_STRING(const char *fmt), ...) + PRINTFLIKE(2, 3); void init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask, diff --git a/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-addrtoname-data.h b/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-addrtoname-data.h index 19986243..9b6b1d8c 100644 --- a/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-addrtoname-data.h +++ b/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-addrtoname-data.h @@ -2,7 +2,7 @@ #include <rtems/linkersets.h> #include "rtems-bsd-tcpdump-data.h" /* addrtoname.c */ -RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static struct enamemem bytestringtable[]); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static struct bsnamemem bytestringtable[]); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static struct enamemem enametable[]); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static struct enamemem nsaptable[]); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static struct h6namemem h6nametable[]); diff --git a/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-namespace.h b/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-namespace.h index b0ed4329..bb4ed207 100644 --- a/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-namespace.h +++ b/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-namespace.h @@ -46,6 +46,7 @@ #define in_cksum _bsd_tcpdump_in_cksum #define in_cksum_shouldbe _bsd_tcpdump_in_cksum_shouldbe /* ipproto.c */ +#define netdb_protoname _bsd_tcpdump_netdb_protoname /* l2vpn.c */ /* machdep.c */ #define abort_on_misalignment _bsd_tcpdump_abort_on_misalignment diff --git a/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-tcpdump-data.h b/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-tcpdump-data.h index 17b75076..126e0f46 100644 --- a/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-tcpdump-data.h +++ b/freebsd/contrib/tcpdump/rtems-bsd-tcpdump-tcpdump-data.h @@ -4,7 +4,6 @@ /* tcpdump.c */ RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static char *zflag); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int Bflag); -RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int Cflag); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int Cflag_count); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int Dflag); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int Gflag); @@ -23,6 +22,7 @@ RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int infoprint); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int jflag); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int pflag); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static int supports_monitor_mode); +RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static long int Cflag); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static pcap_t *pd); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static time_t Gflag_time); RTEMS_LINKER_RWSET_CONTENT(bsd_prog_tcpdump, static u_int packets_captured); diff --git a/freebsd/contrib/tcpdump/signature.c b/freebsd/contrib/tcpdump/signature.c index 2e654aea..861f59cd 100644 --- a/freebsd/contrib/tcpdump/signature.c +++ b/freebsd/contrib/tcpdump/signature.c @@ -18,7 +18,7 @@ * * Functions for signature and digest verification. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H diff --git a/freebsd/contrib/tcpdump/signature.h b/freebsd/contrib/tcpdump/signature.h index 239ee3e8..bbb63edf 100644 --- a/freebsd/contrib/tcpdump/signature.h +++ b/freebsd/contrib/tcpdump/signature.h @@ -12,7 +12,7 @@ * * Functions for signature and digest verification. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ /* for netdissect_options */ diff --git a/freebsd/contrib/tcpdump/smbutil.c b/freebsd/contrib/tcpdump/smbutil.c index b1f9b098..5ed188b6 100644 --- a/freebsd/contrib/tcpdump/smbutil.c +++ b/freebsd/contrib/tcpdump/smbutil.c @@ -243,6 +243,7 @@ name_len(netdissect_options *ndo, return(-1); /* name goes past the end of the buffer */ ND_TCHECK2(*s, 1); s += (*s) + 1; + ND_TCHECK2(*s, 1); } return(PTR_DIFF(s, s0) + 1); diff --git a/freebsd/contrib/tcpdump/tcpdump.c b/freebsd/contrib/tcpdump/tcpdump.c index 52fd2260..26761ad7 100644 --- a/freebsd/contrib/tcpdump/tcpdump.c +++ b/freebsd/contrib/tcpdump/tcpdump.c @@ -156,7 +156,7 @@ The Regents of the University of California. All rights reserved.\n"; #endif static int Bflag; /* buffer size */ -static int Cflag; /* rotate dump files after this many bytes */ +static long Cflag; /* rotate dump files after this many bytes */ static int Cflag_count; /* Keep track of which file number we're writing */ static int Dflag; /* list available devices and exit */ /* @@ -204,26 +204,17 @@ cap_channel_t *capdns; #endif /* Forwards */ -static void error(const char *, ...) - __attribute__((noreturn)) -#ifdef __ATTRIBUTE___FORMAT_OK - __attribute__((format (printf, 1, 2))) -#endif /* __ATTRIBUTE___FORMAT_OK */ - ; -static void warning(const char *, ...) -#ifdef __ATTRIBUTE___FORMAT_OK - __attribute__((format (printf, 1, 2))) -#endif /* __ATTRIBUTE___FORMAT_OK */ - ; -static void exit_tcpdump(int) __attribute__((noreturn)); +static void error(FORMAT_STRING(const char *), ...) NORETURN PRINTFLIKE(1, 2); +static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2); +static void exit_tcpdump(int) NORETURN; static RETSIGTYPE cleanup(int); static RETSIGTYPE child_cleanup(int); static void print_version(void); static void print_usage(void); -static void show_tstamp_types_and_exit(pcap_t *, const char *device) __attribute__((noreturn)); -static void show_dlts_and_exit(pcap_t *, const char *device) __attribute__((noreturn)); +static void show_tstamp_types_and_exit(pcap_t *, const char *device) NORETURN; +static void show_dlts_and_exit(pcap_t *, const char *device) NORETURN; #ifdef HAVE_PCAP_FINDALLDEVS -static void show_devices_and_exit (void) __attribute__((noreturn)); +static void show_devices_and_exit (void) NORETURN; #endif static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); @@ -2063,10 +2054,10 @@ main(int argc, char **argv) /* * The various libpcap devices use a combination of - * read (bpf), ioctl (bpf, netmap), poll (netmap). - * Grant the relevant access rights, sorted by name. + * read (bpf), ioctl (bpf, netmap), poll (netmap) + * so we add the relevant access rights. */ - cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ); + cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT); if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && errno != ENOSYS) { error("unable to limit pcap descriptor"); @@ -2819,6 +2810,14 @@ print_version(void) smi_version_string = nd_smi_version_string(); if (smi_version_string != NULL) (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string); + +#if defined(__SANITIZE_ADDRESS__) + (void)fprintf (stderr, "Compiled with AddressSanitizer/GCC.\n"); +#elif defined(__has_feature) +# if __has_feature(address_sanitizer) + (void)fprintf (stderr, "Compiled with AddressSanitizer/CLang.\n"); +# endif +#endif /* __SANITIZE_ADDRESS__ or __has_feature */ } USES_APPLE_RST diff --git a/freebsd/contrib/tcpdump/util-print.c b/freebsd/contrib/tcpdump/util-print.c index a4b482ff..7a5269dd 100644 --- a/freebsd/contrib/tcpdump/util-print.c +++ b/freebsd/contrib/tcpdump/util-print.c @@ -27,7 +27,7 @@ /* * txtproto_print() derived from original code by Hannes Gredler - * (hannes@juniper.net): + * (hannes@gredler.at): * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code @@ -527,8 +527,9 @@ static char * bittok2str_internal(register const struct tok *lp, register const char *fmt, register u_int v, const char *sep) { - static char buf[256]; /* our stringbuffer */ - int buflen=0; + static char buf[1024+1]; /* our string buffer */ + char *bufp = buf; + size_t space_left = sizeof(buf), string_size; register u_int rotbit; /* this is the bit we rotate through all bitpositions */ register u_int tokval; const char * sepstr = ""; @@ -543,8 +544,20 @@ bittok2str_internal(register const struct tok *lp, register const char *fmt, */ if (tokval == (v&rotbit)) { /* ok we have found something */ - buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s", - sepstr, lp->s); + if (space_left <= 1) + return (buf); /* only enough room left for NUL, if that */ + string_size = strlcpy(bufp, sepstr, space_left); + if (string_size >= space_left) + return (buf); /* we ran out of room */ + bufp += string_size; + space_left -= string_size; + if (space_left <= 1) + return (buf); /* only enough room left for NUL, if that */ + string_size = strlcpy(bufp, lp->s, space_left); + if (string_size >= space_left) + return (buf); /* we ran out of room */ + bufp += string_size; + space_left -= string_size; sepstr = sep; break; } @@ -553,7 +566,7 @@ bittok2str_internal(register const struct tok *lp, register const char *fmt, lp++; } - if (buflen == 0) + if (bufp == buf) /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */ (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : fmt, v); return (buf); @@ -908,7 +921,7 @@ safeputs(netdissect_options *ndo, { u_int idx = 0; - while (*s && idx < maxlen) { + while (idx < maxlen && *s) { safeputchar(ndo, *s); idx++; s++; |