+
+ case '$':
+ /* Guys we can't handle with one of the usual cases */
+ switch (tag) {
+
+ case TAG_NETBIOS_NODE:
+ /* this option should be at least 1 byte long */
+ if (len < 1) {
+ ND_PRINT((ndo, "ERROR: option %u len %u < 1 bytes",
+ TAG_NETBIOS_NODE, len));
+ break;
+ }
+ tag = *bp++;
+ --len;
+ ND_PRINT((ndo, "%s", tok2str(nbo2str, NULL, tag)));
+ break;
+
+ case TAG_OPT_OVERLOAD:
+ /* this option should be at least 1 byte long */
+ if (len < 1) {
+ ND_PRINT((ndo, "ERROR: option %u len %u < 1 bytes",
+ TAG_OPT_OVERLOAD, len));
+ break;
+ }
+ tag = *bp++;
+ --len;
+ ND_PRINT((ndo, "%s", tok2str(oo2str, NULL, tag)));
+ break;
+
+ case TAG_CLIENT_FQDN:
+ /* this option should be at least 3 bytes long */
+ if (len < 3) {
+ ND_PRINT((ndo, "ERROR: option %u len %u < 3 bytes",
+ TAG_CLIENT_FQDN, len));
+ bp += len;
+ len = 0;
+ break;
+ }
+ if (*bp)
+ ND_PRINT((ndo, "[%s] ", client_fqdn_flags(*bp)));
+ bp++;
+ if (*bp || *(bp+1))
+ ND_PRINT((ndo, "%u/%u ", *bp, *(bp+1)));
+ bp += 2;
+ ND_PRINT((ndo, "\""));
+ if (fn_printn(bp, len - 3, ndo->ndo_snapend)) {
+ ND_PRINT((ndo, "\""));
+ goto trunc;
+ }
+ ND_PRINT((ndo, "\""));
+ bp += len - 3;
+ len = 0;
+ break;
+
+ case TAG_CLIENT_ID:
+ { int type;
+
+ /* this option should be at least 1 byte long */
+ if (len < 1) {
+ ND_PRINT((ndo, "ERROR: option %u len %u < 1 bytes",
+ TAG_CLIENT_ID, len));
+ break;
+ }
+ type = *bp++;
+ len--;
+ if (type == 0) {
+ ND_PRINT((ndo, "\""));
+ if (fn_printn(bp, len, ndo->ndo_snapend)) {
+ ND_PRINT((ndo, "\""));
+ goto trunc;
+ }
+ ND_PRINT((ndo, "\""));
+ bp += len;
+ len = 0;
+ break;
+ } else {
+ ND_PRINT((ndo, "%s ", tok2str(arp2str, "hardware-type %u,", type)));
+ while (len > 0) {
+ if (!first)
+ ND_PRINT((ndo, ":"));
+ ND_PRINT((ndo, "%02x", *bp));
+ ++bp;
+ --len;
+ first = 0;
+ }
+ }
+ break;
+ }
+
+ case TAG_AGENT_CIRCUIT:
+ while (len >= 2) {
+ subopt = *bp++;
+ suboptlen = *bp++;
+ len -= 2;
+ if (suboptlen > len) {
+ ND_PRINT((ndo, "\n\t %s SubOption %u, length %u: length goes past end of option",
+ tok2str(agent_suboption_values, "Unknown", subopt),
+ subopt,
+ suboptlen));
+ bp += len;
+ len = 0;
+ break;
+ }
+ ND_PRINT((ndo, "\n\t %s SubOption %u, length %u: ",
+ tok2str(agent_suboption_values, "Unknown", subopt),
+ subopt,
+ suboptlen));
+ switch (subopt) {
+
+ case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */
+ case AGENT_SUBOPTION_REMOTE_ID:
+ case AGENT_SUBOPTION_SUBSCRIBER_ID:
+ fn_printn(bp, suboptlen, NULL);
+ break;
+
+ default:
+ print_unknown_data(ndo, bp, "\n\t\t", suboptlen);
+ }
+
+ len -= suboptlen;
+ bp += suboptlen;
+ }
+ break;
+
+ case TAG_CLASSLESS_STATIC_RT:
+ case TAG_CLASSLESS_STA_RT_MS:
+ {
+ u_int mask_width, significant_octets, i;
+
+ /* this option should be at least 5 bytes long */
+ if (len < 5) {
+ ND_PRINT((ndo, "ERROR: option %u len %u < 5 bytes",
+ TAG_CLASSLESS_STATIC_RT, len));
+ bp += len;
+ len = 0;
+ break;
+ }
+ while (len > 0) {
+ if (!first)
+ ND_PRINT((ndo, ","));
+ mask_width = *bp++;
+ len--;
+ /* mask_width <= 32 */
+ if (mask_width > 32) {
+ ND_PRINT((ndo, "[ERROR: Mask width (%d) > 32]", mask_width));
+ bp += len;
+ len = 0;
+ break;
+ }
+ significant_octets = (mask_width + 7) / 8;
+ /* significant octets + router(4) */
+ if (len < significant_octets + 4) {
+ ND_PRINT((ndo, "[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4));
+ bp += len;
+ len = 0;
+ break;
+ }
+ ND_PRINT((ndo, "("));
+ if (mask_width == 0)
+ ND_PRINT((ndo, "default"));
+ else {
+ for (i = 0; i < significant_octets ; i++) {
+ if (i > 0)
+ ND_PRINT((ndo, "."));
+ ND_PRINT((ndo, "%d", *bp++));
+ }
+ for (i = significant_octets ; i < 4 ; i++)
+ ND_PRINT((ndo, ".0"));
+ ND_PRINT((ndo, "/%d", mask_width));
+ }
+ memcpy((char *)&ul, (const char *)bp, sizeof(ul));
+ ND_PRINT((ndo, ":%s)", ipaddr_string(&ul)));
+ bp += sizeof(ul);
+ len -= (significant_octets + 4);
+ first = 0;
+ }
+ }
+ break;
+
+ default:
+ ND_PRINT((ndo, "[unknown special tag %u, size %u]",
+ tag, len));
+ bp += len;
+ len = 0;
+ break;
+ }
+ break;