static int
ip6_opt_process(netdissect_options *ndo, const u_char *bp, int len,
- int *found_jumbo, uint32_t *jumbolen)
+ int *found_jumbop, uint32_t *payload_len)
{
int i;
int optlen = 0;
+ int found_jumbo = 0;
+ uint32_t jumbolen = 0;
if (len == 0)
return 0;
ND_PRINT("(jumbo: invalid len %u)", GET_U_1(bp + i + 1));
goto trunc;
}
- *found_jumbo = 1;
- *jumbolen = GET_BE_U_4(bp + i + 2);
- if (ndo->ndo_vflag)
- ND_PRINT("(jumbo: %u) ", *jumbolen);
+ jumbolen = GET_BE_U_4(bp + i + 2);
+ if (found_jumbo) {
+ /* More than one Jumbo Payload option */
+ if (ndo->ndo_vflag)
+ ND_PRINT("(jumbo: %u - already seen) ", jumbolen);
+ } else {
+ found_jumbo = 1;
+ if (payload_len == NULL) {
+ /* Not a hop-by-hop option - not valid */
+ if (ndo->ndo_vflag)
+ ND_PRINT("(jumbo: %u - not a hop-by-hop option) ", jumbolen);
+ } else if (*payload_len != 0) {
+ /* Payload length was non-zero - not valid */
+ if (ndo->ndo_vflag)
+ ND_PRINT("(jumbo: %u - payload len != 0) ", jumbolen);
+ } else {
+ /*
+ * This is a hop-by-hop option, and Payload length
+ * was zero in the IPv6 header.
+ */
+ if (jumbolen < 65536) {
+ /* Too short */
+ if (ndo->ndo_vflag)
+ ND_PRINT("(jumbo: %u - < 65536) ", jumbolen);
+ } else {
+ /* OK, this is valid */
+ *found_jumbop = 1;
+ *payload_len = jumbolen;
+ if (ndo->ndo_vflag)
+ ND_PRINT("(jumbo: %u) ", jumbolen);
+ }
+ }
+ }
break;
case IP6OPT_HOME_ADDRESS:
if (len - i < IP6OPT_HOMEADDR_MINLEN) {
goto trunc;
}
if (ndo->ndo_vflag) {
- ND_PRINT("(homeaddr: %s", ip6addr_string(ndo, bp + i + 2));
+ ND_PRINT("(homeaddr: %s", GET_IP6ADDR_STRING(bp + i + 2));
if (GET_U_1(bp + i + 1) > IP6OPT_HOMEADDR_MINLEN - 2) {
if (ip6_sopt_print(ndo, bp + i + IP6OPT_HOMEADDR_MINLEN,
(optlen - IP6OPT_HOMEADDR_MINLEN)) == -1)
u_int hbhlen = 0;
ndo->ndo_protocol = "hbhopt";
- ND_TCHECK_1(dp->ip6h_len);
hbhlen = (GET_U_1(dp->ip6h_len) + 1) << 3;
ND_TCHECK_LEN(dp, hbhlen);
ND_PRINT("HBH ");
{
const struct ip6_dest *dp = (const struct ip6_dest *)bp;
u_int dstoptlen = 0;
- int found_jumbo;
- uint32_t jumbolen;
ndo->ndo_protocol = "dstopt";
- ND_TCHECK_1(dp->ip6d_len);
dstoptlen = (GET_U_1(dp->ip6d_len) + 1) << 3;
ND_TCHECK_LEN(dp, dstoptlen);
ND_PRINT("DSTOPT ");
if (ndo->ndo_vflag) {
/*
- * The Jumbo Payload option is a hop-by-hop option; we print,
- * but don't honor, Jumbo Payload destination options.
+ * The Jumbo Payload option is a hop-by-hop option; we don't
+ * honor Jumbo Payload destination options, reporting them
+ * as invalid.
*/
if (ip6_opt_process(ndo, (const u_char *)dp + sizeof(*dp),
- dstoptlen - sizeof(*dp), &found_jumbo,
- &jumbolen) == -1)
+ dstoptlen - sizeof(*dp), NULL, NULL) == -1)
goto trunc;
}