diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2013-01-15 10:15:20 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2013-01-15 10:15:20 +0000 |
commit | 213ff71f6d983de15fa921c52f9b196c80b43b08 (patch) | |
tree | bffb6969f67a65b6caebe39c2adbed6b25fbc194 /sys/netinet6 | |
parent | 5a44e133130a94e220716b64d26af483ec08b5e4 (diff) |
Flushing prefixes of autoconfigured IPv6 addresses with ndp -P
caused an uvm fault. The function in6_purgeaddr() might already
free the prefix before prelist_remove() is called. So call
in6_purgeaddr() for all addresses first and then loop over the
remaining prefixes and call prelist_remove().
OK claudio@
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/nd6.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index c1a0696db3c..dee5c7a1c87 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.c,v 1.92 2012/09/19 09:47:25 bluhm Exp $ */ +/* $OpenBSD: nd6.c,v 1.93 2013/01/15 10:15:19 bluhm Exp $ */ /* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */ /* @@ -1389,6 +1389,7 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) struct nd_prefix *pr, *next; s = splsoftnet(); + /* First purge the addresses referenced by a prefix. */ for (pr = LIST_FIRST(&nd_prefix); pr; pr = next) { struct in6_ifaddr *ia, *ia_next; @@ -1408,6 +1409,18 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) if (ia->ia6_ndpr == pr) in6_purgeaddr(&ia->ia_ifa); } + } + /* + * Purging the addresses might remove the prefix as well. + * So run the loop again to access only prefixes that have + * not been freed already. + */ + for (pr = LIST_FIRST(&nd_prefix); pr; pr = next) { + next = LIST_NEXT(pr, ndpr_entry); + + if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr)) + continue; /* XXX */ + prelist_remove(pr); } splx(s); |