summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6/icmp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet6/icmp6.c')
-rw-r--r--freebsd/sys/netinet6/icmp6.c48
1 files changed, 21 insertions, 27 deletions
diff --git a/freebsd/sys/netinet6/icmp6.c b/freebsd/sys/netinet6/icmp6.c
index 54758cd4..f73dee04 100644
--- a/freebsd/sys/netinet6/icmp6.c
+++ b/freebsd/sys/netinet6/icmp6.c
@@ -361,7 +361,7 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
m_adj(m, ICMPV6_PLD_MAXLEN - m->m_pkthdr.len);
preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
- M_PREPEND(m, preplen, M_DONTWAIT);
+ M_PREPEND(m, preplen, M_DONTWAIT); /* FIB is also copied over. */
if (m && m->m_len < preplen)
m = m_pullup(m, preplen);
if (m == NULL) {
@@ -583,7 +583,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
MGETHDR(n, M_DONTWAIT, n0->m_type);
n0len = n0->m_pkthdr.len; /* save for use below */
if (n)
- M_MOVE_PKTHDR(n, n0);
+ M_MOVE_PKTHDR(n, n0); /* FIB copied. */
if (n && maxlen >= MHLEN) {
MCLGET(n, M_DONTWAIT);
if ((n->m_flags & M_EXT) == 0) {
@@ -1429,7 +1429,7 @@ ni6_input(struct mbuf *m, int off)
m_freem(m);
return (NULL);
}
- M_MOVE_PKTHDR(n, m); /* just for recvif */
+ M_MOVE_PKTHDR(n, m); /* just for recvif and FIB */
if (replylen > MHLEN) {
if (replylen > MCLBYTES) {
/*
@@ -1711,9 +1711,9 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
}
IFNET_RLOCK_NOSLEEP();
- for (ifp = TAILQ_FIRST(&V_ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
+ TAILQ_FOREACH(ifp, &V_ifnet, if_list) {
addrsofif = 0;
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -1764,7 +1764,7 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m, struct ifnet **ifpp,
}
addrsofif++; /* count the address */
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (iffound) {
*ifpp = ifp;
IFNET_RUNLOCK_NOSLEEP();
@@ -1782,7 +1782,7 @@ static int
ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
struct ifnet *ifp0, int resid)
{
- struct ifnet *ifp = ifp0 ? ifp0 : TAILQ_FIRST(&V_ifnet);
+ struct ifnet *ifp;
struct in6_ifaddr *ifa6;
struct ifaddr *ifa;
struct ifnet *ifp_dep = NULL;
@@ -1795,10 +1795,11 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
return (0); /* needless to copy */
IFNET_RLOCK_NOSLEEP();
+ ifp = ifp0 ? ifp0 : TAILQ_FIRST(&V_ifnet);
again:
for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
- IF_ADDR_LOCK(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -1853,7 +1854,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
/* now we can copy the address */
if (resid < sizeof(struct in6_addr) +
sizeof(u_int32_t)) {
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
/*
* We give up much more copy.
* Set the truncate flag and return.
@@ -1900,7 +1901,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6, struct icmp6_nodeinfo *nni6,
resid -= (sizeof(struct in6_addr) + sizeof(u_int32_t));
copied += (sizeof(struct in6_addr) + sizeof(u_int32_t));
}
- IF_ADDR_UNLOCK(ifp);
+ IF_ADDR_RUNLOCK(ifp);
if (ifp0) /* we need search only on the specified IF */
break;
}
@@ -2175,10 +2176,6 @@ icmp6_reflect(struct mbuf *m, size_t off)
}
}
- if ((srcp != NULL) &&
- (in6_addrscope(srcp) != in6_addrscope(&ip6->ip6_src)))
- srcp = NULL;
-
if (srcp == NULL) {
int e;
struct sockaddr_in6 sin6;
@@ -2284,8 +2281,6 @@ icmp6_redirect_input(struct mbuf *m, int off)
int icmp6len = ntohs(ip6->ip6_plen);
char *lladdr = NULL;
int lladdrlen = 0;
- u_char *redirhdr = NULL;
- int redirhdrlen = 0;
struct rtentry *rt = NULL;
int is_router;
int is_onlink;
@@ -2351,7 +2346,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
bcopy(&reddst6, &sin6.sin6_addr, sizeof(reddst6));
- rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
+ rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL, RT_DEFAULT_FIB);
if (rt) {
if (rt->rt_gateway == NULL ||
rt->rt_gateway->sa_family != AF_INET6) {
@@ -2421,11 +2416,6 @@ icmp6_redirect_input(struct mbuf *m, int off)
lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
}
- if (ndopts.nd_opts_rh) {
- redirhdrlen = ndopts.nd_opts_rh->nd_opt_rh_len;
- redirhdr = (u_char *)(ndopts.nd_opts_rh + 1); /* xxx */
- }
-
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
nd6log((LOG_INFO,
"icmp6_redirect_input: lladdrlen mismatch for %s "
@@ -2445,6 +2435,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
struct sockaddr_in6 sdst;
struct sockaddr_in6 sgw;
struct sockaddr_in6 ssrc;
+ u_int fibnum;
bzero(&sdst, sizeof(sdst));
bzero(&sgw, sizeof(sgw));
@@ -2455,9 +2446,11 @@ icmp6_redirect_input(struct mbuf *m, int off)
bcopy(&redtgt6, &sgw.sin6_addr, sizeof(struct in6_addr));
bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
bcopy(&src6, &ssrc.sin6_addr, sizeof(struct in6_addr));
- rtredirect((struct sockaddr *)&sdst, (struct sockaddr *)&sgw,
- (struct sockaddr *)NULL, RTF_GATEWAY | RTF_HOST,
- (struct sockaddr *)&ssrc);
+ for (fibnum = 0; fibnum < rt_numfibs; fibnum++)
+ in6_rtredirect((struct sockaddr *)&sdst,
+ (struct sockaddr *)&sgw, (struct sockaddr *)NULL,
+ RTF_GATEWAY | RTF_HOST, (struct sockaddr *)&ssrc,
+ fibnum);
}
/* finally update cached route in each socket via pfctlinput */
{
@@ -2541,6 +2534,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
MCLGET(m, M_DONTWAIT);
if (!m)
goto fail;
+ M_SETFIB(m, rt->rt_fibnum);
m->m_pkthdr.rcvif = NULL;
m->m_len = 0;
maxlen = M_TRAILINGSPACE(m);
@@ -2620,9 +2614,9 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
struct nd_opt_hdr *nd_opt;
char *lladdr;
- IF_AFDATA_LOCK(ifp);
+ IF_AFDATA_RLOCK(ifp);
ln = nd6_lookup(router_ll6, 0, ifp);
- IF_AFDATA_UNLOCK(ifp);
+ IF_AFDATA_RUNLOCK(ifp);
if (ln == NULL)
goto nolladdropt;