summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/icmp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/icmp6.c')
-rw-r--r--sys/netinet6/icmp6.c45
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;
OpenPOWER on IntegriCloud