void ip6_opt_print(const u_char *bp, int len) { int i; int optlen = 0; for (i = 0; i < len; i += optlen) { if (bp[i] == IP6OPT_PAD1) optlen = 1; else { if (i + 1 < len) optlen = bp[i + 1] + 2; else goto trunc; } if (i + optlen > len) goto trunc; switch (bp[i]) { case IP6OPT_PAD1: printf("(pad1)"); break; case IP6OPT_PADN: if (len - i < IP6OPT_MINLEN) { printf("(padn: trunc)"); goto trunc; } printf("(padn)"); break; case IP6OPT_ROUTER_ALERT: if (len - i < IP6OPT_RTALERT_LEN) { printf("(rtalert: trunc)"); goto trunc; } if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) { printf("(rtalert: invalid len %d)", bp[i + 1]); goto trunc; } printf("(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2])); break; case IP6OPT_JUMBO: if (len - i < IP6OPT_JUMBO_LEN) { printf("(jumbo: trunc)"); goto trunc; } if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) { printf("(jumbo: invalid len %d)", bp[i + 1]); goto trunc; } printf("(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2])); break; case IP6OPT_HOME_ADDRESS: if (len - i < IP6OPT_HOMEADDR_MINLEN) { printf("(homeaddr: trunc)"); goto trunc; } if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) { printf("(homeaddr: invalid len %d)", bp[i + 1]); goto trunc; } printf("(homeaddr: %s", ip6addr_string(&bp[i + 2])); if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) { ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN], (optlen - IP6OPT_HOMEADDR_MINLEN)); } printf(")"); break; case IP6OPT_BINDING_UPDATE: if (len - i < IP6OPT_BU_MINLEN) { printf("(bu: trunc)"); goto trunc; } if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) { printf("(bu: invalid len %d)", bp[i + 1]); goto trunc; } printf("(bu: "); if (bp[i + 2] & 0x80) printf("A"); if (bp[i + 2] & 0x40) printf("H"); if (bp[i + 2] & 0x20) printf("S"); if (bp[i + 2] & 0x10) printf("D"); if ((bp[i + 2] & 0x0f) || bp[i + 3] || bp[i + 4]) printf("res"); printf(", sequence: %u", bp[i + 5]); printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 6])); if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) { ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN], (optlen - IP6OPT_BU_MINLEN)); } printf(")"); break; case IP6OPT_BINDING_ACK: if (len - i < IP6OPT_BA_MINLEN) { printf("(ba: trunc)"); goto trunc; } if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) { printf("(ba: invalid len %d)", bp[i + 1]); goto trunc; } printf("(ba: "); printf("status: %u", bp[i + 2]); if (bp[i + 3]) printf("res"); printf(", sequence: %u", bp[i + 4]); printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 5])); printf(", refresh: %u", EXTRACT_32BITS(&bp[i + 9])); if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) { ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN], (optlen - IP6OPT_BA_MINLEN)); } printf(")"); break; case IP6OPT_BINDING_REQ: if (len - i < IP6OPT_BR_MINLEN) { printf("(br: trunc)"); goto trunc; } printf("(br"); if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) { ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN], (optlen - IP6OPT_BR_MINLEN)); } printf(")"); break; default: if (len - i < IP6OPT_MINLEN) { printf("(type %d: trunc)", bp[i]); goto trunc; } printf("(opt_type 0x%02x: len=%d) ", bp[i], bp[i + 1]); break; } } #if 0 end: #endif return; trunc: printf("[trunc] "); }
static void ip6_opt_print(netdissect_options *ndo, const u_char *bp, int len) { int i; int optlen = 0; if (len == 0) return; for (i = 0; i < len; i += optlen) { if (bp[i] == IP6OPT_PAD1) optlen = 1; else { if (i + 1 < len) optlen = bp[i + 1] + 2; else goto trunc; } if (i + optlen > len) goto trunc; switch (bp[i]) { case IP6OPT_PAD1: ND_PRINT((ndo, "(pad1)")); break; case IP6OPT_PADN: if (len - i < IP6OPT_MINLEN) { ND_PRINT((ndo, "(padn: trunc)")); goto trunc; } ND_PRINT((ndo, "(padn)")); break; case IP6OPT_ROUTER_ALERT: if (len - i < IP6OPT_RTALERT_LEN) { ND_PRINT((ndo, "(rtalert: trunc)")); goto trunc; } if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) { ND_PRINT((ndo, "(rtalert: invalid len %d)", bp[i + 1])); goto trunc; } ND_PRINT((ndo, "(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2]))); break; case IP6OPT_JUMBO: if (len - i < IP6OPT_JUMBO_LEN) { ND_PRINT((ndo, "(jumbo: trunc)")); goto trunc; } if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) { ND_PRINT((ndo, "(jumbo: invalid len %d)", bp[i + 1])); goto trunc; } ND_PRINT((ndo, "(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2]))); break; case IP6OPT_HOME_ADDRESS: if (len - i < IP6OPT_HOMEADDR_MINLEN) { ND_PRINT((ndo, "(homeaddr: trunc)")); goto trunc; } if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) { ND_PRINT((ndo, "(homeaddr: invalid len %d)", bp[i + 1])); goto trunc; } ND_PRINT((ndo, "(homeaddr: %s", ip6addr_string(ndo, &bp[i + 2]))); if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) { ip6_sopt_print(ndo, &bp[i + IP6OPT_HOMEADDR_MINLEN], (optlen - IP6OPT_HOMEADDR_MINLEN)); } ND_PRINT((ndo, ")")); break; default: if (len - i < IP6OPT_MINLEN) { ND_PRINT((ndo, "(type %d: trunc)", bp[i])); goto trunc; } ND_PRINT((ndo, "(opt_type 0x%02x: len=%d)", bp[i], bp[i + 1])); break; } } ND_PRINT((ndo, " ")); return; trunc: ND_PRINT((ndo, "[trunc] ")); }