diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2001-02-08 15:07:29 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2001-02-08 15:07:29 +0000 |
commit | 76d82f88b09c27bea589469b0e4d11e7a78a1ac6 (patch) | |
tree | ea03c237a04212bf9e20efde97a61fd798b08c19 /sys/netinet6/nd6.c | |
parent | 66fcaf31f978765693b1d7b401232abe9976fa04 (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.c | 36 |
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; |