summaryrefslogtreecommitdiff
path: root/sys/netinet6/nd6.c
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2001-02-08 15:07:29 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2001-02-08 15:07:29 +0000
commit76d82f88b09c27bea589469b0e4d11e7a78a1ac6 (patch)
treeea03c237a04212bf9e20efde97a61fd798b08c19 /sys/netinet6/nd6.c
parent66fcaf31f978765693b1d7b401232abe9976fa04 (diff)
when chasing nd6_llinfo chain, make sure we do not touch dangling
pointer (due to RTM_DELETE during default router list management). from kame
Diffstat (limited to 'sys/netinet6/nd6.c')
-rw-r--r--sys/netinet6/nd6.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index b91584497cc..5bca449a625 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6.c,v 1.23 2001/02/08 14:51:22 itojun Exp $ */
+/* $OpenBSD: nd6.c,v 1.24 2001/02/08 15:07:27 itojun Exp $ */
/* $KAME: nd6.c,v 1.114 2001/02/08 10:57:00 itojun Exp $ */
/*
@@ -452,7 +452,7 @@ nd6_timer(ignored_arg)
ICMP6_DST_UNREACH_ADDR, 0);
ln->ln_hold = NULL;
}
- nd6_free(rt);
+ next = nd6_free(rt);
}
break;
case ND6_LLINFO_REACHABLE:
@@ -483,12 +483,11 @@ nd6_timer(ignored_arg)
nd_ifinfo[ifp->if_index].retrans / 1000;
nd6_ns_output(ifp, &dst->sin6_addr,
&dst->sin6_addr, ln, 0);
- } else {
- nd6_free(rt);
- }
+ } else
+ next = nd6_free(rt);
break;
case ND6_LLINFO_WAITDELETE:
- nd6_free(rt);
+ next = nd6_free(rt);
break;
}
ln = next;
@@ -619,7 +618,7 @@ nd6_purge(ifp)
rt->rt_gateway->sa_family == AF_LINK) {
sdl = (struct sockaddr_dl *)rt->rt_gateway;
if (sdl->sdl_index == ifp->if_index)
- nd6_free(rt);
+ nln = nd6_free(rt);
}
ln = nln;
}
@@ -797,11 +796,11 @@ nd6_is_addr_neighbor(addr, ifp)
/*
* Free an nd6 llinfo entry.
*/
-void
+struct llinfo_nd6 *
nd6_free(rt)
struct rtentry *rt;
{
- struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
+ struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo, *next;
struct sockaddr_dl *sdl;
struct in6_addr in6 = ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
struct nd_defrouter *dr;
@@ -866,11 +865,26 @@ nd6_free(rt)
ln->ln_state = ND6_LLINFO_WAITDELETE;
ln->ln_asked = 0;
rt->rt_flags &= ~RTF_REJECT;
- return;
+ return ln->ln_next;
}
+ /*
+ * Before deleting the entry, remember the next entry as the
+ * return value. We need this because pfxlist_onlink_check() above
+ * might have freed other entries (particularly the old next entry) as
+ * a side effect (XXX).
+ */
+ next = ln->ln_next;
+
+ /*
+ * Detach the route from the routing tree and the list of neighbor
+ * caches, and disable the route entry not to be used in already
+ * cached routes.
+ */
rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
rt_mask(rt), 0, (struct rtentry **)0);
+
+ return next;
}
/*
@@ -1578,7 +1592,7 @@ nd6_cache_lladdr(ifp, from, lladdr, lladdrlen, type, code)
return NULL;
if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) {
fail:
- nd6_free(rt);
+ (void)nd6_free(rt);
return NULL;
}
ln = (struct llinfo_nd6 *)rt->rt_llinfo;