]> The Tcpdump Group git mirrors - tcpdump/commitdiff
CDP: Modernize packet parsing style.
authorDenis Ovsienko <[email protected]>
Tue, 8 Dec 2020 23:50:23 +0000 (23:50 +0000)
committerDenis Ovsienko <[email protected]>
Tue, 8 Dec 2020 23:50:23 +0000 (23:50 +0000)
Enable ND_LONGJMP_FROM_TCHECK. Remove many redundant ND_TCHECK*()
instances. Report invalid packets as invalid with a reason, not
truncated. Test whether the invalid packet is entirely in the buffer.

Remove redundant and add plenty of new length checks. Reduce scope for
some variables. Consistently decrement length when advancing the current
pointer. Resort to ND_TCHECK_LEN() only when there are no better ways to
test the packet buffer space.

Do not pass caplen to cdp_print() and remove an improvised snapshot end
guard. Move TLV type-specific code from cdp_print() into standalone
small functions and upgrade a TLV name lookup table into a more
developed TLV registry table along the lines of what was done for
OpenFlow.

In cdp_print_addr() instead of comparing pointers test the address
counter only and trust the loop to do the length checks.

Replace cdp_get_number() with GET_*() macros.

Rewrite the code to make it easier to follow and make indentation more
consistent while at it.

Remove a stray CDP case block from print-chdlc.c.

netdissect.h
print-cdp.c
print-chdlc.c
print-llc.c

index 854fb8a522333cecd8eabd867f71bd4c52b353c0..e50c319a9b73b231d79f778c49c089897233859b 100644 (file)
@@ -568,7 +568,7 @@ extern const char *bgp_vpn_rd_print(netdissect_options *, const u_char *);
 extern void bootp_print(netdissect_options *, const u_char *, u_int);
 extern void calm_fast_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *);
 extern void carp_print(netdissect_options *, const u_char *, u_int, u_int);
-extern void cdp_print(netdissect_options *, const u_char *, u_int, u_int);
+extern void cdp_print(netdissect_options *, const u_char *, u_int);
 extern void cfm_print(netdissect_options *, const u_char *, u_int);
 extern u_int chdlc_print(netdissect_options *, const u_char *, u_int);
 extern void cisco_autorp_print(netdissect_options *, const u_char *, u_int);
index 0ab646e51dee71dd63296ee4bd1b9c80a58ac94a..9f5c24bca6bd375aa3431ac287a46f282e85d61b 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <string.h>
 
+#define ND_LONGJMP_FROM_TCHECK
 #include "netdissect.h"
 #include "addrtoname.h"
 #include "extract.h"
 #define CDP_TLV_TYPE_OFFSET 0
 #define CDP_TLV_LEN_OFFSET  2
 
-static const struct tok cdp_tlv_values[] = {
-    { 0x01,             "Device-ID"},
-    { 0x02,             "Address"},
-    { 0x03,             "Port-ID"},
-    { 0x04,             "Capability"},
-    { 0x05,             "Version String"},
-    { 0x06,             "Platform"},
-    { 0x07,             "Prefixes"},
-    { 0x08,             "Protocol-Hello option"},
-    { 0x09,             "VTP Management Domain"},
-    { 0x0a,             "Native VLAN ID"},
-    { 0x0b,             "Duplex"},
-    { 0x0e,             "ATA-186 VoIP VLAN assignment"},
-    { 0x0f,             "ATA-186 VoIP VLAN request"},
-    { 0x10,             "power consumption"},
-    { 0x11,             "MTU"},
-    { 0x12,             "AVVID trust bitmap"},
-    { 0x13,             "AVVID untrusted ports CoS"},
-    { 0x14,             "System Name"},
-    { 0x15,             "System Object ID (not decoded)"},
-    { 0x16,             "Management Addresses"},
-    { 0x17,             "Physical Location"},
-    { 0, NULL}
-};
-
 static const struct tok cdp_capability_values[] = {
     { 0x01,             "Router" },
     { 0x02,             "Transparent Bridge" },
@@ -85,207 +61,268 @@ static const struct tok cdp_capability_values[] = {
     { 0, NULL }
 };
 
-static int cdp_print_addr(netdissect_options *, const u_char *, u_int);
-static int cdp_print_prefixes(netdissect_options *, const u_char *, u_int);
-static unsigned int cdp_get_number(netdissect_options *, const u_char *, u_int);
+static void cdp_print_addr(netdissect_options *, const u_char *, u_int);
+static void cdp_print_prefixes(netdissect_options *, const u_char *, u_int);
+
+static void
+cdp_print_string(netdissect_options *ndo,
+                 const u_char *cp, const u_int len)
+{
+       ND_PRINT("'");
+       (void)nd_printn(ndo, cp, len, NULL);
+       ND_PRINT("'");
+}
+
+static void
+cdp_print_power(netdissect_options *ndo,
+                const u_char *cp, const u_int len)
+{
+       u_int val = 0;
+
+       switch (len) {
+       case 1:
+               val = GET_U_1(cp);
+               break;
+       case 2:
+               val = GET_BE_U_2(cp);
+               break;
+       case 3:
+               val = GET_BE_U_3(cp);
+               break;
+       }
+       ND_PRINT("%1.2fW", val / 1000.0);
+}
+
+static void
+cdp_print_capability(netdissect_options *ndo,
+                     const u_char *cp, const u_int len _U_)
+{
+       uint32_t val = GET_BE_U_4(cp);
+
+       ND_PRINT("(0x%08x): %s", val,
+                bittok2str(cdp_capability_values, "none", val));
+}
+
+/* Rework the version string to get a nice indentation. */
+static void
+cdp_print_version(netdissect_options *ndo,
+                  const u_char *cp, const u_int len)
+{
+       unsigned i;
+
+       ND_PRINT("\n\t  ");
+       for (i = 0; i < len; i++) {
+               u_char c = GET_U_1(cp + i);
+
+               if (c == '\n')
+                       ND_PRINT("\n\t  ");
+               else
+                       fn_print_char(ndo, c);
+       }
+}
+
+static void
+cdp_print_uint16(netdissect_options *ndo,
+                 const u_char *cp, const u_int len _U_)
+{
+       ND_PRINT("%u", GET_BE_U_2(cp));
+}
+
+static void
+cdp_print_duplex(netdissect_options *ndo,
+                 const u_char *cp, const u_int len _U_)
+{
+       ND_PRINT("%s", GET_U_1(cp) ? "full": "half");
+}
+
+/* https://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cata/186/2_12_m/english/release/notes/186rn21m.html
+* plus more details from other sources
+*
+* There are apparently versions of the request with both
+* 2 bytes and 3 bytes of value.  The 3 bytes of value
+* appear to be a 1-byte application type followed by a
+* 2-byte VLAN ID; the 2 bytes of value are unknown
+* (they're 0x20 0x00 in some captures I've seen; that
+* is not a valid VLAN ID, as VLAN IDs are 12 bits).
+*
+* The replies all appear to be 3 bytes long.
+*/
+static void
+cdp_print_ata186(netdissect_options *ndo,
+                 const u_char *cp, const u_int len)
+{
+       if (len == 2)
+               ND_PRINT("unknown 0x%04x", GET_BE_U_2(cp));
+       else
+               ND_PRINT("app %u, vlan %u", GET_U_1(cp), GET_BE_U_2(cp + 1));
+}
+
+static void
+cdp_print_mtu(netdissect_options *ndo,
+              const u_char *cp, const u_int len _U_)
+{
+       ND_PRINT("%u bytes", GET_BE_U_4(cp));
+}
+
+static void
+cdp_print_uint8x(netdissect_options *ndo,
+                 const u_char *cp, const u_int len _U_)
+{
+       ND_PRINT("0x%02x", GET_U_1(cp));
+}
+
+static void
+cdp_print_phys_loc(netdissect_options *ndo,
+                   const u_char *cp, const u_int len)
+{
+       ND_PRINT("0x%02x", GET_U_1(cp));
+       if (len > 1) {
+               ND_PRINT("/");
+               (void)nd_printn(ndo, cp + 1, len - 1, NULL);
+       }
+}
+
+struct cdp_tlvinfo {
+       const char *name;
+       void (*printer)(netdissect_options *ndo, const u_char *, u_int);
+       int min_len, max_len;
+};
+
+#define T_DEV_ID 0x01
+#define T_MAX 0x17
+static const struct cdp_tlvinfo cdptlvs[T_MAX + 1] = {
+       /* 0x00 */
+       [ T_DEV_ID ] = { "Device-ID", cdp_print_string, -1, -1 },
+       [ 0x02 ] = { "Address", cdp_print_addr, -1, -1 },
+       [ 0x03 ] = { "Port-ID", cdp_print_string, -1, -1 },
+       [ 0x04 ] = { "Capability", cdp_print_capability, 4, 4 },
+       [ 0x05 ] = { "Version String", cdp_print_version, -1, -1 },
+       [ 0x06 ] = { "Platform", cdp_print_string, -1, -1 },
+       [ 0x07 ] = { "Prefixes", cdp_print_prefixes, -1, -1 },
+       /* not documented */
+       [ 0x08 ] = { "Protocol-Hello option", NULL, -1, -1 },
+       /* CDPv2 */
+       [ 0x09 ] = { "VTP Management Domain", cdp_print_string, -1, -1 },
+       /* CDPv2 */
+       [ 0x0a ] = { "Native VLAN ID", cdp_print_uint16, 2, 2 },
+       /* CDPv2 */
+       [ 0x0b ] = { "Duplex", cdp_print_duplex, 1, 1 },
+       /* 0x0c */
+       /* 0x0d */
+       /* incomplete doc. */
+       [ 0x0e ] = { "ATA-186 VoIP VLAN assignment", cdp_print_ata186, 3, 3 },
+       /* incomplete doc. */
+       [ 0x0f ] = { "ATA-186 VoIP VLAN request", cdp_print_ata186, 2, 3 },
+       /* not documented */
+       [ 0x10 ] = { "power consumption", cdp_print_power, 1, 3 },
+       /* not documented */
+       [ 0x11 ] = { "MTU", cdp_print_mtu, 4, 4 },
+       /* not documented */
+       [ 0x12 ] = { "AVVID trust bitmap", cdp_print_uint8x, 1, 1 },
+       /* not documented */
+       [ 0x13 ] = { "AVVID untrusted ports CoS", cdp_print_uint8x, 1, 1 },
+       /* not documented */
+       [ 0x14 ] = { "System Name", cdp_print_string, -1, -1 },
+       /* not documented */
+       [ 0x15 ] = { "System Object ID (not decoded)", NULL, -1, -1 },
+       [ 0x16 ] = { "Management Addresses", cdp_print_addr, 4, -1 },
+       /* not documented */
+       [ 0x17 ] = { "Physical Location", cdp_print_phys_loc, 1, -1 },
+};
 
 void
 cdp_print(netdissect_options *ndo,
-          const u_char *pptr, u_int length, u_int caplen)
+          const u_char *tptr, u_int length)
 {
-       u_int type, len, i;
-       const u_char *tptr;
+       u_int orig_length = length;
+       uint16_t checksum;
 
        ndo->ndo_protocol = "cdp";
-       if (caplen < CDP_HEADER_LEN) {
-               nd_print_trunc(ndo);
-               return;
-       }
 
-       tptr = pptr; /* temporary pointer */
-
-       ND_TCHECK_LEN(tptr, CDP_HEADER_LEN);
+       if (length < CDP_HEADER_LEN) {
+               ND_PRINT(" (packet length %u < %u)", length, CDP_HEADER_LEN);
+               goto invalid;
+       }
        ND_PRINT("CDPv%u, ttl: %us",
-                                          GET_U_1((tptr + CDP_HEADER_VERSION_OFFSET)),
-                                          GET_U_1(tptr + CDP_HEADER_TTL_OFFSET));
+                GET_U_1(tptr + CDP_HEADER_VERSION_OFFSET),
+                GET_U_1(tptr + CDP_HEADER_TTL_OFFSET));
+       checksum = GET_BE_U_2(tptr + CDP_HEADER_CHECKSUM_OFFSET);
        if (ndo->ndo_vflag)
                ND_PRINT(", checksum: 0x%04x (unverified), length %u",
-                        GET_BE_U_2(tptr + CDP_HEADER_CHECKSUM_OFFSET),
-                        length);
+                        checksum, orig_length);
        tptr += CDP_HEADER_LEN;
-
-       while (tptr < (pptr+length)) {
-               ND_TCHECK_LEN(tptr, CDP_TLV_HEADER_LEN); /* read out Type and Length */
+       length -= CDP_HEADER_LEN;
+
+       while (length) {
+               u_int type, len;
+               const struct cdp_tlvinfo *info;
+               const char *name;
+               u_char covered = 0;
+
+               if (length < CDP_TLV_HEADER_LEN) {
+                       ND_PRINT(" (remaining packet length %u < %u)",
+                                length, CDP_TLV_HEADER_LEN);
+                       goto invalid;
+               }
                type = GET_BE_U_2(tptr + CDP_TLV_TYPE_OFFSET);
                len  = GET_BE_U_2(tptr + CDP_TLV_LEN_OFFSET); /* object length includes the 4 bytes header length */
+               info = type <= T_MAX ? &cdptlvs[type] : NULL;
+               name = (info && info->name) ? info->name : "unknown field type";
                if (len < CDP_TLV_HEADER_LEN) {
-                   if (ndo->ndo_vflag)
-                       ND_PRINT("\n\t%s (0x%02x), TLV length: %u byte%s (too short)",
-                              tok2str(cdp_tlv_values,"unknown field type", type),
-                              type,
-                              len,
-                              PLURAL_SUFFIX(len)); /* plural */
-                   else
-                       ND_PRINT(", %s TLV length %u too short",
-                              tok2str(cdp_tlv_values,"unknown field type", type),
-                              len);
-                   break;
+                       if (ndo->ndo_vflag)
+                               ND_PRINT("\n\t%s (0x%02x), TLV length: %u byte%s (too short)",
+                                        name, type, len, PLURAL_SUFFIX(len));
+                       else
+                               ND_PRINT(", %s TLV length %u too short",
+                                        name, len);
+                       goto invalid;
+               }
+               if (len > length) {
+                       ND_PRINT(" (TLV length %u > %u)", len, length);
+                       goto invalid;
                }
                tptr += CDP_TLV_HEADER_LEN;
+               length -= CDP_TLV_HEADER_LEN;
                len -= CDP_TLV_HEADER_LEN;
 
-               ND_TCHECK_LEN(tptr, len);
-
-               if (ndo->ndo_vflag || type == 1) { /* in non-verbose mode just print Device-ID */
-
-                   if (ndo->ndo_vflag)
+               /* In non-verbose mode just print Device-ID. */
+               if (!ndo->ndo_vflag && type == T_DEV_ID)
+                       ND_PRINT(", Device-ID ");
+               else if (ndo->ndo_vflag)
                        ND_PRINT("\n\t%s (0x%02x), value length: %u byte%s: ",
-                              tok2str(cdp_tlv_values,"unknown field type", type),
-                              type,
-                              len,
-                              PLURAL_SUFFIX(len)); /* plural */
-
-                   switch (type) {
-
-                   case 0x01: /* Device-ID */
-                       if (!ndo->ndo_vflag)
-                           ND_PRINT(", Device-ID ");
-                       ND_PRINT("'");
-                       (void)nd_printn(ndo, tptr, len, NULL);
-                       ND_PRINT("'");
-                       break;
-                   case 0x02: /* Address */
-                       if (cdp_print_addr(ndo, tptr, len) < 0)
-                           goto trunc;
-                       break;
-                   case 0x03: /* Port-ID */
-                       ND_PRINT("'");
-                       (void)nd_printn(ndo, tptr, len, NULL);
-                       ND_PRINT("'");
-                       break;
-                   case 0x04: /* Capabilities */
-                       if (len < 4)
-                           goto trunc;
-                       ND_PRINT("(0x%08x): %s",
-                              GET_BE_U_4(tptr),
-                              bittok2str(cdp_capability_values, "none", GET_BE_U_4(tptr)));
-                       break;
-                   case 0x05: /* Version */
-                       ND_PRINT("\n\t  ");
-                       for (i=0;i<len;i++) {
-                           u_char c;
-
-                           c = GET_U_1(tptr + i);
-                           if (c == '\n') /* lets rework the version string to
-                                             get a nice indentation */
-                               ND_PRINT("\n\t  ");
-                           else
-                               fn_print_char(ndo, c);
+                                name, type, len, PLURAL_SUFFIX(len));
+
+               if (info) {
+                       if ((info->min_len > 0 && len < (unsigned)info->min_len) ||
+                           (info->max_len > 0 && len > (unsigned)info->max_len))
+                               ND_PRINT(" (malformed TLV)");
+                       else if (ndo->ndo_vflag || type == T_DEV_ID) {
+                               if (info->printer)
+                                       info->printer(ndo, tptr, len);
+                               else
+                                       ND_TCHECK_LEN(tptr, len);
+                               /*
+                                * When the type is defined without a printer,
+                                * do not print the hex dump.
+                                */
+                               covered = 1;
                        }
-                       break;
-                   case 0x06: /* Platform */
-                       ND_PRINT("'");
-                       (void)nd_printn(ndo, tptr, len, NULL);
-                       ND_PRINT("'");
-                       break;
-                   case 0x07: /* Prefixes */
-                       if (cdp_print_prefixes(ndo, tptr, len) < 0)
-                           goto trunc;
-                       break;
-                   case 0x08: /* Protocol Hello Option - not documented */
-                       break;
-                   case 0x09: /* VTP Mgmt Domain  - CDPv2 */
-                       ND_PRINT("'");
-                       (void)nd_printn(ndo, tptr, len, NULL);
-                       ND_PRINT("'");
-                       break;
-                   case 0x0a: /* Native VLAN ID - CDPv2 */
-                       if (len < 2)
-                           goto trunc;
-                       ND_PRINT("%u", GET_BE_U_2(tptr));
-                       break;
-                   case 0x0b: /* Duplex - CDPv2 */
-                       if (len < 1)
-                           goto trunc;
-                       ND_PRINT("%s", GET_U_1(tptr) ? "full": "half");
-                       break;
-
-                   /* https://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cata/186/2_12_m/english/release/notes/186rn21m.html
-                    * plus more details from other sources
-                    *
-                    * There are apparently versions of the request with both
-                    * 2 bytes and 3 bytes of value.  The 3 bytes of value
-                    * appear to be a 1-byte application type followed by a
-                    * 2-byte VLAN ID; the 2 bytes of value are unknown
-                    * (they're 0x20 0x00 in some captures I've seen; that
-                    * is not a valid VLAN ID, as VLAN IDs are 12 bits).
-                    *
-                    * The replies all appear to be 3 bytes long.
-                    */
-                   case 0x0e: /* ATA-186 VoIP VLAN assignment - incomplete doc. */
-                       if (len < 3)
-                           goto trunc;
-                       ND_PRINT("app %u, vlan %u", GET_U_1(tptr),
-                                GET_BE_U_2(tptr + 1));
-                       break;
-                   case 0x0f: /* ATA-186 VoIP VLAN request - incomplete doc. */
-                       if (len < 2)
-                           goto trunc;
-                       if (len == 2)
-                           ND_PRINT("unknown 0x%04x", GET_BE_U_2(tptr));
-                       else
-                           ND_PRINT("app %u, vlan %u", GET_U_1(tptr),
-                                    GET_BE_U_2(tptr + 1));
-                       break;
-                   case 0x10: /* Power - not documented */
-                       ND_PRINT("%1.2fW", cdp_get_number(ndo, tptr, len) / 1000.0);
-                       break;
-                   case 0x11: /* MTU - not documented */
-                       if (len < 4)
-                           goto trunc;
-                       ND_PRINT("%u bytes", GET_BE_U_4(tptr));
-                       break;
-                   case 0x12: /* AVVID trust bitmap - not documented */
-                       if (len < 1)
-                           goto trunc;
-                       ND_PRINT("0x%02x", GET_U_1(tptr));
-                       break;
-                   case 0x13: /* AVVID untrusted port CoS - not documented */
-                       if (len < 1)
-                           goto trunc;
-                       ND_PRINT("0x%02x", GET_U_1(tptr));
-                       break;
-                   case 0x14: /* System Name - not documented */
-                       ND_PRINT("'");
-                       (void)nd_printn(ndo, tptr, len, NULL);
-                       ND_PRINT("'");
-                       break;
-                   case 0x16: /* System Object ID - not documented */
-                       if (cdp_print_addr(ndo, tptr, len) < 0)
-                               goto trunc;
-                       break;
-                   case 0x17: /* Physical Location - not documented */
-                       if (len < 1)
-                           goto trunc;
-                       ND_PRINT("0x%02x", GET_U_1(tptr));
-                       if (len > 1) {
-                               ND_PRINT("/");
-                               (void)nd_printn(ndo, tptr + 1, len - 1, NULL);
-                       }
-                       break;
-                   default:
+               }
+
+               if (!covered) {
+                       ND_TCHECK_LEN(tptr, len);
                        print_unknown_data(ndo, tptr, "\n\t  ", len);
-                       break;
-                   }
                }
-               tptr = tptr+len;
+               tptr += len;
+               length -= len;
        }
        if (ndo->ndo_vflag < 1)
-           ND_PRINT(", length %u", caplen);
+               ND_PRINT(", length %u", orig_length);
 
        return;
-trunc:
-       nd_print_trunc(ndo);
+invalid:
+       nd_print_invalid(ndo);
+       ND_TCHECK_LEN(tptr, length);
 }
 
 /*
@@ -299,33 +336,40 @@ trunc:
 #define PT_NLPID               1       /* OSI NLPID */
 #define PT_IEEE_802_2          2       /* IEEE 802.2 LLC header */
 
-static int
+static void
 cdp_print_addr(netdissect_options *ndo,
-              const u_char * p, u_int l)
+               const u_char * p, u_int l)
 {
-       u_int pt, pl, al, num;
-       const u_char *endp = p + l;
+       u_int num;
        static const u_char prot_ipv6[] = {
                0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd
        };
 
-       ND_TCHECK_4(p);
-       if (p + 4 > endp)
-               goto trunc;
+       if (l < 4) {
+               ND_PRINT(" (not enough space for num)");
+               goto invalid;
+       }
        num = GET_BE_U_4(p);
        p += 4;
+       l -= 4;
 
-       while (p < endp && num != 0) {
-               ND_TCHECK_2(p);
-               if (p + 2 > endp)
-                       goto trunc;
+       while (num) {
+               u_int pt, pl, al;
+
+               if (l < 2) {
+                       ND_PRINT(" (not enough space for PT+PL)");
+                       goto invalid;
+               }
                pt = GET_U_1(p);                /* type of "protocol" field */
                pl = GET_U_1(p + 1);    /* length of "protocol" field */
                p += 2;
+               l -= 2;
 
-               ND_TCHECK_2(p + pl);
-               if (p + pl + 2 > endp)
-                       goto trunc;
+               if (l < pl + 2) {
+                       ND_PRINT(" (not enough space for P+AL)");
+                       goto invalid;
+               }
+               /* Skip the protocol for now. */
                al = GET_BE_U_2(p + pl);        /* address length */
 
                if (pt == PT_NLPID && pl == 1 && GET_U_1(p) == NLPID_IP &&
@@ -335,54 +379,59 @@ cdp_print_addr(netdissect_options *ndo,
                         * (1-byte NLPID), protocol = 0xcc (NLPID for IPv4),
                         * address length = 4
                         */
-                       p += 3;
-
-                       if (p + 4 > endp)
-                               goto trunc;
+                       p += pl + 2;
+                       l -= pl + 2;
+                       /* p is just beyond al now. */
+                       if (l < al) {
+                               ND_PRINT(" (not enough space for A)");
+                               goto invalid;
+                       }
                        ND_PRINT("IPv4 (%u) %s", num, GET_IPADDR_STRING(p));
-                       p += 4;
+                       p += al;
+                       l -= al;
                }
                else if (pt == PT_IEEE_802_2 && pl == 8 &&
-                   memcmp(p, prot_ipv6, 8) == 0 && al == 16) {
+                        memcmp(p, prot_ipv6, 8) == 0 && al == 16) {
                        /*
                         * IPv6: protocol type = IEEE 802.2 header,
                         * protocol length = 8 (size of LLC+SNAP header),
                         * protocol = LLC+SNAP header with the IPv6
                         * Ethertype, address length = 16
                         */
-                       p += 10;
-                       ND_TCHECK_LEN(p, al);
-                       if (p + al > endp)
-                               goto trunc;
-
+                       p += pl + 2;
+                       l -= pl + 2;
+                       /* p is just beyond al now. */
+                       if (l < al) {
+                               ND_PRINT(" (not enough space for A)");
+                               goto invalid;
+                       }
                        ND_PRINT("IPv6 (%u) %s", num, GET_IP6ADDR_STRING(p));
                        p += al;
+                       l -= al;
                }
                else {
                        /*
                         * Generic case: just print raw data
                         */
-                       ND_TCHECK_LEN(p, pl);
-                       if (p + pl > endp)
-                               goto trunc;
-                       ND_PRINT("pt=0x%02x, pl=%u, pb=", GET_U_1((p - 2)),
-                                pl);
+                       ND_PRINT("pt=0x%02x, pl=%u, pb=", pt, pl);
                        while (pl != 0) {
                                ND_PRINT(" %02x", GET_U_1(p));
                                p++;
+                               l--;
                                pl--;
                        }
-                       ND_TCHECK_2(p);
-                       if (p + 2 > endp)
-                               goto trunc;
                        ND_PRINT(", al=%u, a=", al);
                        p += 2;
-                       ND_TCHECK_LEN(p, al);
-                       if (p + al > endp)
-                               goto trunc;
+                       l -= 2;
+                       /* p is just beyond al now. */
+                       if (l < al) {
+                               ND_PRINT(" (not enough space for A)");
+                               goto invalid;
+                       }
                        while (al != 0) {
                                ND_PRINT(" %02x", GET_U_1(p));
                                p++;
+                               l--;
                                al--;
                        }
                }
@@ -390,48 +439,34 @@ cdp_print_addr(netdissect_options *ndo,
                if (num)
                        ND_PRINT(" ");
        }
+       if (l)
+               ND_PRINT(" (%u bytes of stray data)", l);
+       return;
 
-       return 0;
-
-trunc:
-       return -1;
+invalid:
+       ND_TCHECK_LEN(p, l);
 }
 
-
-static int
+static void
 cdp_print_prefixes(netdissect_options *ndo,
-                  const u_char * p, u_int l)
+                   const u_char * p, u_int l)
 {
-       if (l % 5)
-               goto trunc;
+       if (l % 5) {
+               ND_PRINT(" [length %u is not a multiple of 5]", l);
+               goto invalid;
+       }
 
        ND_PRINT(" IPv4 Prefixes (%u):", l / 5);
 
        while (l > 0) {
                ND_PRINT(" %u.%u.%u.%u/%u",
-                         GET_U_1(p), GET_U_1(p + 1), GET_U_1(p + 2),
-                         GET_U_1(p + 3), GET_U_1(p + 4));
+                        GET_U_1(p), GET_U_1(p + 1), GET_U_1(p + 2),
+                        GET_U_1(p + 3), GET_U_1(p + 4));
                l -= 5;
                p += 5;
        }
+       return;
 
-       return 0;
-
-trunc:
-       return -1;
-}
-
-/* read in a <n>-byte number, MSB first
- * (of course this can handle max sizeof(int))
- */
-static unsigned int
-cdp_get_number(netdissect_options *ndo, const u_char * p, u_int l)
-{
-    unsigned int res=0;
-    while( l>0 )
-    {
-       res = (res<<8) + GET_U_1(p);
-       p++; l--;
-    }
-    return res;
+invalid:
+       ND_TCHECK_LEN(p, l);
 }
index e0accf9e8f8a49064b457f1de211a1bdd0df6e90..235675da42b17ebc35653799e447735ea146774b 100644 (file)
@@ -82,11 +82,6 @@ chdlc_print(netdissect_options *ndo, const u_char *p, u_int length)
        case CHDLC_TYPE_SLARP:
                chdlc_slarp_print(ndo, p, length);
                break;
-#if 0
-       case CHDLC_TYPE_CDP:
-               chdlc_cdp_print(p, length);
-               break;
-#endif
         case ETHERTYPE_MPLS:
         case ETHERTYPE_MPLS_MULTI:
                 mpls_print(ndo, p, length);
index 750a8ccdae5499a4f2f5127922ae9b813dad90f4..ae3ae4cf5c34517f4318141bef0fa1b7e9a2f848 100644 (file)
@@ -485,7 +485,7 @@ snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen,
        case OUI_CISCO:
                 switch (et) {
                 case PID_CISCO_CDP:
-                        cdp_print(ndo, p, length, caplen);
+                        cdp_print(ndo, p, length);
                         return (1);
                 case PID_CISCO_DTP:
                         dtp_print(ndo, p, length);