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); }
