summaryrefslogtreecommitdiff
path: root/sys/netinet6
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/nd6.c15
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);