]> The Tcpdump Group git mirrors - tcpdump/commitdiff
UDLD: Refine and modernize the code.
authorDenis Ovsienko <[email protected]>
Sat, 3 Oct 2020 14:29:02 +0000 (15:29 +0100)
committerDenis Ovsienko <[email protected]>
Sat, 3 Oct 2020 14:39:11 +0000 (15:39 +0100)
Enable ND_LONGJMP_FROM_TCHECK. Lose a local variable, instead modify the
provided pointer and length in sync and always fetch one field at a time.
When the packet is declard too short, report it as invalid, not truncated
(it may turn out truncated soon thereafter though). Use a named constant.

When not decoding the packet completely (whether invalid or not), still
check that it is fully within the snapshot.

When decoding it completely, add checks at the beginng of the iteration
to test that both the TL and the V fit into the remaining part of the
declared packet. Move an ND_TCHECK_LEN() into the default case to let the
string printing functions guard the snapshot end. Do not declare the
remainder of the packet invalid on TLV type 0, as RFC 5171 Section 6
says: "If an implementation does not understand a Type value, it should
skip over it using the length field."

print-udld.c

index d17e660b35889ea14baef7cbe3239d7e7f664e3a..37e36d6bdace94d2c9653fdfa8e5742f583b2ce9 100644 (file)
 
 #include "netdissect-stdinc.h"
 
+#define ND_LONGJMP_FROM_TCHECK
 #include "netdissect.h"
 #include "extract.h"
 
 
 #define UDLD_HEADER_LEN                        4
+#define UDLD_TLV_HEADER_LEN            4
 #define UDLD_DEVICE_ID_TLV             0x0001
 #define UDLD_PORT_ID_TLV               0x0002
 #define UDLD_ECHO_TLV                  0x0003
@@ -99,60 +101,68 @@ static const struct tok udld_flags_bitmap_str[] = {
 #define        UDLD_EXTRACT_OPCODE(x) ((x)&0x1f)
 
 void
-udld_print(netdissect_options *ndo, const u_char *pptr, u_int length)
+udld_print(netdissect_options *ndo,
+           const u_char *tptr, u_int length)
 {
-    int code, type, len;
-    const u_char *tptr;
+    uint8_t ver, code, flags;
 
     ndo->ndo_protocol = "udld";
     if (length < UDLD_HEADER_LEN)
-        goto trunc;
-
-    tptr = pptr;
-
-    ND_TCHECK_LEN(tptr, UDLD_HEADER_LEN);
+        goto invalid;
 
+    ver = UDLD_EXTRACT_VERSION(GET_U_1(tptr));
     code = UDLD_EXTRACT_OPCODE(GET_U_1(tptr));
+    tptr += 1;
+    length -= 1;
+
+    flags = GET_U_1(tptr);
+    tptr += 1;
+    length -= 1;
 
     ND_PRINT("UDLDv%u, Code %s (%x), Flags [%s] (0x%02x), length %u",
-           UDLD_EXTRACT_VERSION(GET_U_1(tptr)),
+           ver,
            tok2str(udld_code_values, "Reserved", code),
            code,
-           bittok2str(udld_flags_bitmap_str, "none", GET_U_1((tptr + 1))),
-           GET_U_1((tptr + 1)),
-           length);
+           bittok2str(udld_flags_bitmap_str, "none", flags),
+           flags,
+           length + 2);
 
     /*
      * In non-verbose mode, just print version and opcode type
      */
     if (ndo->ndo_vflag < 1) {
-       return;
+        goto tcheck_remainder;
     }
 
-    ND_PRINT("\n\tChecksum 0x%04x (unverified)", GET_BE_U_2(tptr + 2));
+    ND_PRINT("\n\tChecksum 0x%04x (unverified)", GET_BE_U_2(tptr));
+    tptr += 2;
+    length -= 2;
 
-    tptr += UDLD_HEADER_LEN;
+    while (length) {
+        uint16_t type, len;
 
-    while (tptr < (pptr+length)) {
+        if (length < UDLD_TLV_HEADER_LEN)
+            goto invalid;
 
        type = GET_BE_U_2(tptr);
-        len  = GET_BE_U_2(tptr + 2);
+        tptr += 2;
+        length -= 2;
+
+        len  = GET_BE_U_2(tptr);
+        tptr += 2;
+        length -= 2;
 
         ND_PRINT("\n\t%s (0x%04x) TLV, length %u",
                tok2str(udld_tlv_values, "Unknown", type),
                type, len);
 
-        if (type == 0)
-            goto invalid;
-
         /* infinite loop check */
-        if (len <= 4)
+        if (len <= UDLD_TLV_HEADER_LEN)
             goto invalid;
 
-        len -= 4;
-        tptr += 4;
-
-        ND_TCHECK_LEN(tptr, len);
+        len -= UDLD_TLV_HEADER_LEN;
+        if (length < len)
+            goto invalid;
 
         switch (type) {
         case UDLD_DEVICE_ID_TLV:
@@ -181,16 +191,17 @@ udld_print(netdissect_options *ndo, const u_char *pptr, u_int length)
             break;
 
         default:
+            ND_TCHECK_LEN(tptr, len);
             break;
         }
         tptr += len;
+        length -= len;
     }
 
     return;
 
 invalid:
     nd_print_invalid(ndo);
-    return;
-trunc:
-    nd_print_trunc(ndo);
+tcheck_remainder:
+    ND_TCHECK_LEN(tptr, length);
 }