diff options
Diffstat (limited to 'sys/netinet6/icmp6.c')
-rw-r--r-- | sys/netinet6/icmp6.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 1c8a132..f49a407 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -403,6 +403,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) INIT_VNET_INET6(curvnet); INIT_VPROCG(TD_TO_VPROCG(curthread)); /* XXX V_hostname needs this */ struct mbuf *m = *mp, *n; + struct ifnet *ifp; struct ip6_hdr *ip6, *nip6; struct icmp6_hdr *icmp6, *nicmp6; int off = *offp; @@ -410,6 +411,8 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) int code, sum, noff; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; + ifp = m->m_pkthdr.rcvif; + #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), IPPROTO_DONE); /* m might change if M_LOOP. So, call mtod after this */ @@ -431,10 +434,8 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) * Note: SSM filters are not applied for ICMPv6 traffic. */ if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { - struct ifnet *ifp; - struct in6_multi *inm; + struct in6_multi *inm; - ifp = m->m_pkthdr.rcvif; inm = in6m_lookup(ifp, &ip6->ip6_dst); if (inm == NULL) { IP6STAT_INC(ip6s_notmember); @@ -483,19 +484,19 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) } ICMP6STAT_INC(icp6s_inhist[icmp6->icmp6_type]); - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg); + icmp6_ifstat_inc(ifp, ifs6_in_msg); if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK) - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error); + icmp6_ifstat_inc(ifp, ifs6_in_error); switch (icmp6->icmp6_type) { case ICMP6_DST_UNREACH: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_dstunreach); + icmp6_ifstat_inc(ifp, ifs6_in_dstunreach); switch (code) { case ICMP6_DST_UNREACH_NOROUTE: code = PRC_UNREACH_NET; break; case ICMP6_DST_UNREACH_ADMIN: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_adminprohib); + icmp6_ifstat_inc(ifp, ifs6_in_adminprohib); code = PRC_UNREACH_PROTOCOL; /* is this a good code? */ break; case ICMP6_DST_UNREACH_ADDR: @@ -515,7 +516,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ICMP6_PACKET_TOO_BIG: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig); + icmp6_ifstat_inc(ifp, ifs6_in_pkttoobig); /* validation is made in icmp6_mtudisc_update */ @@ -529,7 +530,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ICMP6_TIME_EXCEEDED: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_timeexceed); + icmp6_ifstat_inc(ifp, ifs6_in_timeexceed); switch (code) { case ICMP6_TIME_EXCEED_TRANSIT: code = PRC_TIMXCEED_INTRANS; @@ -544,7 +545,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ICMP6_PARAM_PROB: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_paramprob); + icmp6_ifstat_inc(ifp, ifs6_in_paramprob); switch (code) { case ICMP6_PARAMPROB_NEXTHEADER: code = PRC_UNREACH_PROTOCOL; @@ -560,7 +561,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ICMP6_ECHO_REQUEST: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echo); + icmp6_ifstat_inc(ifp, ifs6_in_echo); if (code != 0) goto badcode; if ((n = m_copy(m, 0, M_COPYALL)) == NULL) { @@ -623,7 +624,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ICMP6_ECHO_REPLY: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_echoreply); + icmp6_ifstat_inc(ifp, ifs6_in_echoreply); if (code != 0) goto badcode; break; @@ -633,11 +634,15 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) case MLD_LISTENER_DONE: case MLDV2_LISTENER_REPORT: /* - * Drop MLD traffic which is not link-local. + * Drop MLD traffic which is not link-local, has a hop limit + * of greater than 1 hop, or which does not have the + * IPv6 HBH Router Alert option. + * As IPv6 HBH options are stripped in ip6_input() we must + * check an mbuf header flag. * XXX Should we also sanity check that these messages * were directed to a link-local multicast prefix? */ - if (ip6->ip6_hlim != 1) + if ((ip6->ip6_hlim != 1) || (m->m_flags & M_RTALERT_MLD) == 0) goto freeit; if (mld_input(m, off, icmp6len) != 0) return (IPPROTO_DONE); @@ -748,7 +753,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ND_ROUTER_SOLICIT: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routersolicit); + icmp6_ifstat_inc(ifp, ifs6_in_routersolicit); if (code != 0) goto badcode; if (icmp6len < sizeof(struct nd_router_solicit)) @@ -764,7 +769,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ND_ROUTER_ADVERT: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_routeradvert); + icmp6_ifstat_inc(ifp, ifs6_in_routeradvert); if (code != 0) goto badcode; if (icmp6len < sizeof(struct nd_router_advert)) @@ -780,7 +785,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ND_NEIGHBOR_SOLICIT: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighborsolicit); + icmp6_ifstat_inc(ifp, ifs6_in_neighborsolicit); if (code != 0) goto badcode; if (icmp6len < sizeof(struct nd_neighbor_solicit)) @@ -796,7 +801,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ND_NEIGHBOR_ADVERT: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_neighboradvert); + icmp6_ifstat_inc(ifp, ifs6_in_neighboradvert); if (code != 0) goto badcode; if (icmp6len < sizeof(struct nd_neighbor_advert)) @@ -812,7 +817,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) break; case ND_REDIRECT: - icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_redirect); + icmp6_ifstat_inc(ifp, ifs6_in_redirect); if (code != 0) goto badcode; if (icmp6len < sizeof(struct nd_redirect)) @@ -840,7 +845,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) "icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n", icmp6->icmp6_type, ip6_sprintf(ip6bufs, &ip6->ip6_src), ip6_sprintf(ip6bufd, &ip6->ip6_dst), - m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0)); + ifp ? ifp->if_index : 0)); if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { /* ICMPv6 error: MUST deliver it by spec... */ code = PRC_NCMDS; |