#define ICMP6_MAXTYPE 201
#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
-#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */
+#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */
#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */
#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */
#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */
-#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
+#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */
#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */
nd_uint8_t nd_opt_rdnss_len;
nd_uint16_t nd_opt_rdnss_reserved;
nd_uint32_t nd_opt_rdnss_lifetime;
- nd_ipv6 nd_opt_rdnss_addr[1]; /* variable-length */
+ nd_ipv6 nd_opt_rdnss_addr[1]; /* variable-length */
};
struct nd_opt_dnssl { /* DNSSL RFC 6106 5.2 */
static const char *get_rtpref(u_int);
static const char *get_lifetime(uint32_t);
static void print_lladdr(netdissect_options *ndo, const u_char *, size_t);
-static void icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
+static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
static void mld6_print(netdissect_options *ndo, const u_char *);
static void mldv2_report_print(netdissect_options *ndo, const u_char *, u_int);
static void mldv2_query_print(netdissect_options *ndo, const u_char *, u_int);
}
}
-static int icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
+static uint16_t icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
const struct icmp6_hdr *icp, u_int len)
{
return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)icp, len, len,
}
return;
trunc:
- ND_PRINT(" [|truncated]");
+ nd_print_trunc(ndo);
return;
}
}
return;
trunc:
- ND_PRINT(" [|truncated]");
+ nd_print_trunc(ndo);
return;
}
ND_TCHECK_SIZE(dao);
if (length < ND_RPL_DAO_MIN_LEN)
- goto tooshort;
+ goto tooshort;
bp += ND_RPL_DAO_MIN_LEN;
length -= ND_RPL_DAO_MIN_LEN;
return;
trunc:
- ND_PRINT(" [|truncated]");
+ nd_print_trunc(ndo);
return;
tooshort:
ND_TCHECK_LEN(daoack, ND_RPL_DAOACK_MIN_LEN);
if (length < ND_RPL_DAOACK_MIN_LEN)
- goto tooshort;
+ goto tooshort;
bp += ND_RPL_DAOACK_MIN_LEN;
length -= ND_RPL_DAOACK_MIN_LEN;
return;
trunc:
- ND_PRINT(" [|dao-truncated]");
+ nd_print_trunc(ndo);
return;
tooshort:
#if 0
trunc:
- ND_PRINT(" [|truncated]");
+ nd_print_trunc(ndo);
return;
#endif
const u_char *ep;
u_int prot;
+ ndo->ndo_protocol = "icmp6";
dp = (const struct icmp6_hdr *)bp;
ip = (const struct ip6_hdr *)bp2;
oip = (const struct ip6_hdr *)(dp + 1);
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
+ if (length == 0) {
+ ND_PRINT("ICMP6, length 0");
+ nd_print_invalid(ndo);
+ return;
+ }
if (ndo->ndo_vflag && !fragmented) {
uint16_t sum, udp_sum;
break;
case ICMP6_ECHO_REQUEST:
case ICMP6_ECHO_REPLY:
+ /* The check below covers both icmp6_id and icmp6_seq. */
ND_TCHECK_2(dp->icmp6_seq);
- ND_PRINT(", seq %u", EXTRACT_BE_U_2(dp->icmp6_seq));
+ ND_PRINT(", id %u, seq %u", EXTRACT_BE_U_2(dp->icmp6_id), EXTRACT_BE_U_2(dp->icmp6_seq));
break;
case ICMP6_MEMBERSHIP_QUERY:
if (length == MLD_MINLEN) {
case ND_ROUTER_SOLICIT:
#define RTSOLLEN 8
if (ndo->ndo_vflag) {
- icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN,
- length - RTSOLLEN);
+ if (icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN,
+ length - RTSOLLEN) == -1)
+ goto trunc;
}
break;
case ND_ROUTER_ADVERT:
p = (const struct nd_router_advert *)dp;
ND_TCHECK_4(p->nd_ra_retransmit);
ND_PRINT("\n\thop limit %u, Flags [%s]"
- ", pref %s, router lifetime %us, reachable time %us, retrans time %us",
+ ", pref %s, router lifetime %us, reachable time %ums, retrans timer %ums",
EXTRACT_U_1(p->nd_ra_curhoplimit),
bittok2str(icmp6_opt_ra_flag_values,"none",EXTRACT_U_1(p->nd_ra_flags_reserved)),
get_rtpref(EXTRACT_U_1(p->nd_ra_flags_reserved)),
EXTRACT_BE_U_4(p->nd_ra_reachable),
EXTRACT_BE_U_4(p->nd_ra_retransmit));
- icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN,
- length - RTADVLEN);
+ if (icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN,
+ length - RTADVLEN) == -1)
+ goto trunc;
}
break;
case ND_NEIGHBOR_SOLICIT:
ND_PRINT(", who has %s", ip6addr_string(ndo, p->nd_ns_target));
if (ndo->ndo_vflag) {
#define NDSOLLEN 24
- icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN,
- length - NDSOLLEN);
+ if (icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN,
+ length - NDSOLLEN) == -1)
+ goto trunc;
}
}
break;
"none",
EXTRACT_BE_U_4(p->nd_na_flags_reserved)));
#define NDADVLEN 24
- icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN,
- length - NDADVLEN);
+ if (icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN,
+ length - NDADVLEN) == -1)
+ goto trunc;
#undef NDADVLEN
}
}
ND_PRINT(" to %s", ip6addr_string(ndo, p->nd_rd_target));
#define REDIRECTLEN 40
if (ndo->ndo_vflag) {
- icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN,
- length - REDIRECTLEN);
+ if (icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN,
+ length - REDIRECTLEN) == -1)
+ goto trunc;
#undef REDIRECTLEN
}
}
if (flags & 0x4000)
ND_PRINT("O");
#define MPADVLEN 8
- icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN,
- length - MPADVLEN);
+ if (icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN,
+ length - MPADVLEN) == -1)
+ goto trunc;
}
break;
case ND_RPL_MESSAGE:
ND_PRINT(", length %u", length);
return;
trunc:
- ND_PRINT("[|icmp6]");
+ nd_print_trunc(ndo);
}
static const struct udphdr *
return(NULL); /* should be notreached, though */
}
-static void
+static int
icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
{
const struct nd_opt_hdr *op;
size_t l;
u_int i;
-#define ECHECK(var) if ((const u_char *)&(var) > ep - sizeof(var)) return
-
cp = bp;
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
while (cp < ep) {
op = (const struct nd_opt_hdr *)cp;
- ECHECK(op->nd_opt_len);
+ ND_TCHECK_1(op->nd_opt_len);
if (resid <= 0)
- return;
+ return 0;
opt_type = EXTRACT_U_1(op->nd_opt_type);
opt_len = EXTRACT_U_1(op->nd_opt_len);
if (opt_len == 0)
while (domp < cp + (opt_len << 3) && EXTRACT_U_1(domp) != '\0')
{
ND_PRINT(" ");
- if ((domp = ns_nprint (ndo, domp, bp)) == NULL)
+ if ((domp = ns_nprint(ndo, domp, bp)) == NULL)
goto trunc;
}
break;
default:
if (ndo->ndo_vflag <= 1) {
print_unknown_data(ndo,cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */
- return;
+ return 0;
}
break;
}
cp += opt_len << 3;
resid -= opt_len << 3;
}
- return;
+ return 0;
- trunc:
- ND_PRINT("[ndp opt]");
- return;
-#undef ECHECK
+trunc:
+ return -1;
}
static void
}
return;
trunc:
- ND_PRINT("[|icmp6]");
+ nd_print_trunc(ndo);
return;
}
ND_PRINT("]");
return;
trunc:
- ND_PRINT("[|icmp6]");
+ nd_print_trunc(ndo);
return;
}
break;
}
while (i-- && cp < ep) {
- safeputchar(ndo, EXTRACT_U_1(cp));
+ fn_print_char(ndo, EXTRACT_U_1(cp));
cp++;
}
if (cp + 1 < ep && EXTRACT_U_1(cp))
cp++;
ND_PRINT(", \"");
while (cp < ep) {
- safeputchar(ndo, EXTRACT_U_1(cp));
+ fn_print_char(ndo, EXTRACT_U_1(cp));
cp++;
}
ND_PRINT("\"");
break;
case ICMP6_NI_REPLY:
- if (icmp6len > siz) {
- ND_PRINT("[|icmp6: node information reply]");
- break;
- }
+ if (icmp6len > siz)
+ goto trunc;
needcomma = 0;
cp++;
ND_PRINT(", \"");
while (cp < ep) {
- safeputchar(ndo, EXTRACT_U_1(cp));
+ fn_print_char(ndo, EXTRACT_U_1(cp));
cp++;
}
ND_PRINT("\"");
return;
trunc:
- ND_PRINT("[|icmp6]");
+ nd_print_trunc(ndo);
}
static void
return;
trunc:
- ND_PRINT("[|icmp6]");
+ nd_print_trunc(ndo);
}
-
-/*
- * Local Variables:
- * c-style: whitesmith
- * c-basic-offset: 8
- * End:
- */