+ case DH6OPT_STATUS_CODE:
+ if (optlen < 2) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ ND_PRINT((ndo, " %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0]))));
+ break;
+ case DH6OPT_IA_NA:
+ case DH6OPT_IA_PD:
+ if (optlen < 12) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ ND_PRINT((ndo, " IAID:%u T1:%u T2:%u",
+ EXTRACT_32BITS(&tp[0]),
+ EXTRACT_32BITS(&tp[4]),
+ EXTRACT_32BITS(&tp[8])));
+ if (optlen > 12) {
+ /* there are sub-options */
+ dhcp6opt_print(ndo, tp + 12, tp + optlen);
+ }
+ ND_PRINT((ndo, ")"));
+ break;
+ case DH6OPT_IA_TA:
+ if (optlen < 4) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ ND_PRINT((ndo, " IAID:%u", EXTRACT_32BITS(tp)));
+ if (optlen > 4) {
+ /* there are sub-options */
+ dhcp6opt_print(ndo, tp + 4, tp + optlen);
+ }
+ ND_PRINT((ndo, ")"));
+ break;
+ case DH6OPT_IA_PD_PREFIX:
+ if (optlen < 25) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ ND_PRINT((ndo, " %s/%d", ip6addr_string(ndo, &tp[9]), tp[8]));
+ ND_PRINT((ndo, " pltime:%u vltime:%u",
+ EXTRACT_32BITS(&tp[0]),
+ EXTRACT_32BITS(&tp[4])));
+ if (optlen > 25) {
+ /* there are sub-options */
+ dhcp6opt_print(ndo, tp + 25, tp + optlen);
+ }
+ ND_PRINT((ndo, ")"));
+ break;
+ case DH6OPT_LIFETIME:
+ case DH6OPT_CLT_TIME:
+ if (optlen != 4) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ ND_PRINT((ndo, " %d)", EXTRACT_32BITS(tp)));
+ break;
+ case DH6OPT_REMOTE_ID:
+ if (optlen < 4) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ ND_PRINT((ndo, " %d ", EXTRACT_32BITS(tp)));
+ /*
+ * Print hex dump first 10 characters.
+ */
+ for (i = 4; i < optlen && i < 14; i++)
+ ND_PRINT((ndo, "%02x", tp[i]));
+ ND_PRINT((ndo, "...)"));
+ break;
+ case DH6OPT_LQ_QUERY:
+ if (optlen < 17) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ switch (*tp) {
+ case 1:
+ ND_PRINT((ndo, " by-address"));
+ break;
+ case 2:
+ ND_PRINT((ndo, " by-clientID"));
+ break;
+ default:
+ ND_PRINT((ndo, " type_%d", (int)*tp));
+ break;
+ }
+ ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[1])));
+ if (optlen > 17) {
+ /* there are query-options */
+ dhcp6opt_print(ndo, tp + 17, tp + optlen);
+ }
+ ND_PRINT((ndo, ")"));
+ break;
+ case DH6OPT_CLIENT_DATA:
+ tp = (const u_char *)(dh6o + 1);
+ if (optlen > 0) {
+ /* there are encapsulated options */
+ dhcp6opt_print(ndo, tp, tp + optlen);
+ }
+ ND_PRINT((ndo, ")"));
+ break;
+ case DH6OPT_LQ_RELAY_DATA:
+ if (optlen < 16) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ ND_PRINT((ndo, " %s ", ip6addr_string(ndo, &tp[0])));
+ /*
+ * Print hex dump first 10 characters.
+ */
+ for (i = 16; i < optlen && i < 26; i++)
+ ND_PRINT((ndo, "%02x", tp[i]));
+ ND_PRINT((ndo, "...)"));
+ break;
+ case DH6OPT_NTP_SERVER:
+ if (optlen < 4) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ while (tp < cp + sizeof(*dh6o) + optlen - 4) {
+ subopt_code = EXTRACT_16BITS(tp);
+ tp += 2;
+ subopt_len = EXTRACT_16BITS(tp);
+ tp += 2;
+ if (tp + subopt_len > cp + sizeof(*dh6o) + optlen)
+ goto trunc;
+ ND_PRINT((ndo, " subopt:%d", subopt_code));
+ switch (subopt_code) {
+ case DH6OPT_NTP_SUBOPTION_SRV_ADDR:
+ case DH6OPT_NTP_SUBOPTION_MC_ADDR:
+ if (subopt_len != 16) {
+ ND_PRINT((ndo, " ?"));
+ break;
+ }
+ ND_PRINT((ndo, " %s", ip6addr_string(ndo, &tp[0])));
+ break;
+ case DH6OPT_NTP_SUBOPTION_SRV_FQDN:
+ ND_PRINT((ndo, " "));
+ if (ns_nprint(ndo, tp, tp + subopt_len) == NULL)
+ goto trunc;
+ break;
+ default:
+ ND_PRINT((ndo, " ?"));
+ break;
+ }
+ tp += subopt_len;
+ }
+ ND_PRINT((ndo, ")"));
+ break;
+ case DH6OPT_AFTR_NAME:
+ if (optlen < 3) {
+ ND_PRINT((ndo, " ?)"));
+ break;
+ }
+ tp = (const u_char *)(dh6o + 1);
+ remain_len = optlen;
+ ND_PRINT((ndo, " "));
+ /* Encoding is described in section 3.1 of RFC 1035 */
+ while (remain_len && *tp) {
+ label_len = *tp++;
+ if (label_len < remain_len - 1) {
+ (void)fn_printn(ndo, tp, label_len, NULL);
+ tp += label_len;
+ remain_len -= (label_len + 1);
+ if(*tp) ND_PRINT((ndo, "."));
+ } else {
+ ND_PRINT((ndo, " ?"));
+ break;
+ }
+ }
+ ND_PRINT((ndo, ")"));