+ bp += 2;
+ ND_PRINT(" CRQST");
+ opts_len -= PGM_OPT_CRQST_LEN;
+ break;
+
+ case PGM_OPT_PGMCC_DATA:
+#define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2)
+ if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) {
+ ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u < %u]",
+ opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
+ return;
+ }
+ bp += 2;
+ offset = GET_BE_U_4(bp);
+ bp += 4;
+ nla_afnum = GET_BE_U_2(bp);
+ bp += 2+2;
+ switch (nla_afnum) {
+ case AFNUM_IP:
+ if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4)) {
+ ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
+ opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
+ return;
+ }
+ ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
+ addrtostr(bp, nla_buf, sizeof(nla_buf));
+ bp += sizeof(nd_ipv4);
+ opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4);
+ break;
+ case AFNUM_IP6:
+ if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6)) {
+ ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
+ opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
+ return;
+ }
+ ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
+ addrtostr6(bp, nla_buf, sizeof(nla_buf));
+ bp += sizeof(nd_ipv6);
+ opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6);
+ break;
+ default:
+ goto invalid;
+ }
+
+ ND_PRINT(" PGMCC DATA %u %s", offset, nla_buf);
+ break;
+
+ case PGM_OPT_PGMCC_FEEDBACK:
+#define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2)
+ if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) {
+ ND_PRINT("[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]",
+ opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
+ return;
+ }
+ bp += 2;
+ offset = GET_BE_U_4(bp);
+ bp += 4;
+ nla_afnum = GET_BE_U_2(bp);
+ bp += 2+2;
+ switch (nla_afnum) {
+ case AFNUM_IP:
+ if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4)) {
+ ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
+ opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
+ return;
+ }
+ ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
+ addrtostr(bp, nla_buf, sizeof(nla_buf));
+ bp += sizeof(nd_ipv4);
+ opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4);
+ break;
+ case AFNUM_IP6:
+ if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6)) {
+ ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
+ opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
+ return;
+ }
+ ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
+ addrtostr6(bp, nla_buf, sizeof(nla_buf));
+ bp += sizeof(nd_ipv6);
+ opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6);
+ break;
+ default:
+ goto invalid;
+ }
+
+ ND_PRINT(" PGMCC FEEDBACK %u %s", offset, nla_buf);