According to the last commit message to print-dhcp6.c by dlg:
if someone is interested in making this easier to read, it would
be a straightforward and  well contained project to better handle
option printing.

I'm playing around a little with dhcp6 and I heeded the call.

This diff does a few things:
- Extract the 24 bits as specified by the spec instead of stripping them
  inside the printf
- Add the defines of all the options inside RFC8415.  This one can be
  expanded by iana's official list[0], but that's too much for this
  diff.
- Print the human readable name of options, or print the numeric value
  if unknown.
  I also opted for the OPTION_* syntax, instead of the full name,
  because "Identity Association for Non-temporary Addresses" seemed a
  bit much and it keeps the code simpler.
- Pretty print the clientid, serverid, and elapsed_time options. In my
  minimal test setup these were the first ones to come by. Values of
  other options continue to be printed as they were and might follow if
  people are interested in this diff.

OK?

martijn@

[0] https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml

Index: print-dhcp6.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-dhcp6.c,v
retrieving revision 1.12
diff -u -p -r1.12 print-dhcp6.c
--- print-dhcp6.c       2 Dec 2019 22:07:20 -0000       1.12
+++ print-dhcp6.c       16 Jun 2021 14:55:42 -0000
@@ -49,10 +49,44 @@ struct rtentry;
 #define DH6_RELAY_FORW         12
 #define DH6_RELAY_REPL         13
 
+#define XIDLENGTH              3
+
+#define OPTION_CLIENTID                1
+#define OPTION_SERVERID                2
+#define OPTION_IA_NA           3
+#define OPTION_IA_TA           4
+#define OPTION_IAADDR          5
+#define OPTION_ORO             6
+#define OPTION_PREFERENCE      7
+#define OPTION_ELAPSED_TIME    8
+#define OPTION_RELAY_MSG       9
+#define OPTION_AUTH            11
+#define OPTION_UNICAST         12
+#define OPTION_STATUS_CODE     13
+#define OPTION_RAPID_COMMIT    14
+#define OPTION_USER_CLASS      15
+#define OPTION_VENDOR_CLASS    16
+#define OPTION_VENDOR_OPTS     17
+#define OPTION_INTERFACE_ID    18
+#define OPTION_RECONF_MSG      19
+#define OPTION_RECONF_ACCEPT   20
+#define OPTION_IA_PD           25
+#define OPTION_IAPREFIX                26
+#define OPTION_INFORMATION_REFRESH_TIME        32
+#define OPTION_SOL_MAX_RT      82
+#define OPTION_INF_MAX_RT      83
+
+#define CASEEXPAND(var, OPTION) \
+case OPTION:                   \
+       var = #OPTION;          \
+       break;
+
 static void
 dhcp6opt_print(const u_char *cp, u_int length)
 {
        uint16_t code, len;
+       const char *codename;
+       char codenameunknown[sizeof("OPTION (65535)")];
        u_int i;
        int l = snapend - cp;
 
@@ -77,22 +111,96 @@ dhcp6opt_print(const u_char *cp, u_int l
                length -= sizeof(len);
                l -= sizeof(len);
 
-               printf("\n\toption %u len %u", code, len);
+               switch (code) {
+               CASEEXPAND(codename, OPTION_CLIENTID)
+               CASEEXPAND(codename, OPTION_SERVERID)
+               CASEEXPAND(codename, OPTION_IA_NA)
+               CASEEXPAND(codename, OPTION_IA_TA)
+               CASEEXPAND(codename, OPTION_IAADDR)
+               CASEEXPAND(codename, OPTION_ORO)
+               CASEEXPAND(codename, OPTION_PREFERENCE)
+               CASEEXPAND(codename, OPTION_ELAPSED_TIME)
+               CASEEXPAND(codename, OPTION_RELAY_MSG)
+               CASEEXPAND(codename, OPTION_AUTH)
+               CASEEXPAND(codename, OPTION_UNICAST)
+               CASEEXPAND(codename, OPTION_STATUS_CODE)
+               CASEEXPAND(codename, OPTION_RAPID_COMMIT)
+               CASEEXPAND(codename, OPTION_USER_CLASS)
+               CASEEXPAND(codename, OPTION_VENDOR_CLASS)
+               CASEEXPAND(codename, OPTION_VENDOR_OPTS)
+               CASEEXPAND(codename, OPTION_INTERFACE_ID)
+               CASEEXPAND(codename, OPTION_RECONF_MSG)
+               CASEEXPAND(codename, OPTION_RECONF_ACCEPT)
+               CASEEXPAND(codename, OPTION_IA_PD)
+               CASEEXPAND(codename, OPTION_IAPREFIX)
+               CASEEXPAND(codename, OPTION_INFORMATION_REFRESH_TIME)
+               CASEEXPAND(codename, OPTION_SOL_MAX_RT)
+               CASEEXPAND(codename, OPTION_INF_MAX_RT)
+               default:
+                       snprintf(codenameunknown, sizeof(codenameunknown),
+                           "OPTION (%hd)", code);
+                       codename = codenameunknown;
+                       break;
+               }
 
-               if (len > 0) {
-                       if (l < len)
-                               goto trunc;
-                       if (length < len)
-                               goto iptrunc;
-
-                       printf(" ");
-                       for (i = 0; i < len; i++)
-                               printf("%02x", cp[4 + i] & 0xff);
-
-                       cp += len;
-                       length -= len;
-                       l -= len;
+               printf("\n\t%s", codename);
+
+               switch (code) {
+               case OPTION_CLIENTID:
+               case OPTION_SERVERID: {
+                       size_t i;
+
+                       for (i = 0; i < len; i++) {
+                               if (l == 0)
+                                       goto trunc;
+                               if (length == 0)
+                                       goto iptrunc;
+                               printf("%s%02hhx", i == 0 ? ": " : ":", cp[0]);
+                               cp++;
+                               l--;
+                               length--;
+                       }
+                       }
+                       break;
+               case OPTION_ELAPSED_TIME: {
+                       uint16_t time;
+
+                       if (len != 2) {
+                               printf(": Invalid value");
+                               goto badvalue;
+                       } else {
+                               if (l == 0)
+                                       goto trunc;
+                               if (length == 0)
+                                       goto iptrunc;
+                               time = EXTRACT_16BITS(cp);
+                               cp += 2;
+                               l -= 2;
+                               length -= 2;
+
+                               printf(": %d.%02ds", time/100, time % 100);
+                       }
+                       }
+                       break;
+               default:
+ badvalue:
+                       if (len > 0) {
+                               if (l < len)
+                                       goto trunc;
+                               if (length < len)
+                                       goto iptrunc;
+
+                               printf(": ");
+                               for (i = 0; i < len; i++)
+                                       printf("%02x", cp[4 + i] & 0xff);
+
+                               cp += len;
+                               length -= len;
+                               l -= len;
+                       }
+                       break;
                }
+
        }
        return;
 
@@ -127,7 +235,7 @@ void
 dhcp6_print(const u_char *cp, u_int length)
 {
        uint8_t msgtype;
-       uint32_t hdr;
+       uint32_t xid;
        int l = snapend - cp;
        const char *msgname;
 
@@ -184,18 +292,21 @@ dhcp6_print(const u_char *cp, u_int leng
        }
 
        printf(" %s", msgname);
+       cp++;
+       length--;
+       l--;
 
-       if (l < sizeof(hdr))
+       if (l < XIDLENGTH)
                goto trunc;
-       if (length < sizeof(hdr))
+       if (length < XIDLENGTH)
                goto iptrunc;
 
-       hdr = EXTRACT_32BITS(cp);
-       printf(" xid %x", hdr & 0xffffff);
+       xid = EXTRACT_24BITS(cp);
+       printf(" xid 0x%6x", xid);
 
        if (vflag) {
-               cp += sizeof(hdr);
-               length -= sizeof(hdr);
+               cp += XIDLENGTH;
+               length -= XIDLENGTH;
 
                dhcp6opt_print(cp, length);
        }


Reply via email to