diff options
author | green <green@FreeBSD.org> | 2004-10-03 00:49:33 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 2004-10-03 00:49:33 +0000 |
commit | fb8e0f5c565014d25acf01392491739fb7bb3718 (patch) | |
tree | 8c0c7c0c477e29e87b7c4c10ce1d8e206342d888 /sys/netinet6/nd6.c | |
parent | cb606898b9f83045c54ca6796b13313487916ac0 (diff) | |
download | FreeBSD-src-fb8e0f5c565014d25acf01392491739fb7bb3718.zip FreeBSD-src-fb8e0f5c565014d25acf01392491739fb7bb3718.tar.gz |
Prevent reentrancy of the IPv6 routing code (leading to crash with
INVARIANTS on, who knows what with it off).
Diffstat (limited to 'sys/netinet6/nd6.c')
-rw-r--r-- | sys/netinet6/nd6.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 2461fc8..fef8855 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -104,6 +104,8 @@ struct nd_prhead nd_prefix = { 0 }; int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL; static struct sockaddr_in6 all1_sa; +static int nd6_is_new_addr_neighbor __P((struct sockaddr_in6 *, + struct ifnet *)); static void nd6_setmtu0 __P((struct ifnet *, struct nd_ifinfo *)); static void nd6_slowtimo __P((void *)); static int regen_tmpaddr __P((struct in6_ifaddr *)); @@ -869,11 +871,12 @@ nd6_lookup(addr6, create, ifp) } /* - * Detect if a given IPv6 address identifies a neighbor on a given link. - * XXX: should take care of the destination of a p2p link? + * Test whether a given IPv6 address is a neighbor or not, ignoring + * the actual neighbor cache. The neighbor cache is ignored in order + * to not reenter the routing code from within itself. */ -int -nd6_is_addr_neighbor(addr, ifp) +static int +nd6_is_new_addr_neighbor(addr, ifp) struct sockaddr_in6 *addr; struct ifnet *ifp; { @@ -918,6 +921,23 @@ nd6_is_addr_neighbor(addr, ifp) return (1); } + return (0); +} + + +/* + * Detect if a given IPv6 address identifies a neighbor on a given link. + * XXX: should take care of the destination of a p2p link? + */ +int +nd6_is_addr_neighbor(addr, ifp) + struct sockaddr_in6 *addr; + struct ifnet *ifp; +{ + + if (nd6_is_new_addr_neighbor(addr, ifp)) + return (1); + /* * Even if the address matches none of our addresses, it might be * in the neighbor cache. @@ -1101,7 +1121,8 @@ nd6_rtrequest(req, rt, info) if (req == RTM_RESOLVE && (nd6_need_cache(ifp) == 0 || /* stf case */ - !nd6_is_addr_neighbor((struct sockaddr_in6 *)rt_key(rt), ifp))) { + !nd6_is_new_addr_neighbor((struct sockaddr_in6 *)rt_key(rt), + ifp))) { /* * FreeBSD and BSD/OS often make a cloned host route based * on a less-specific route (e.g. the default route). |