From 213ff71f6d983de15fa921c52f9b196c80b43b08 Mon Sep 17 00:00:00 2001 From: Alexander Bluhm Date: Tue, 15 Jan 2013 10:15:20 +0000 Subject: 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@ --- sys/netinet6/nd6.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'sys/netinet6') 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); -- cgit v1.2.3