Rearange interface detachement slightly: before we free the INET6 specific
per-interface data, make sure to call nd6_purge() with it to remove routing entries pointing to the going interface. When we should happen to call this function again later, with the data already gone, just return. Fixes PR kern/49682, ok: christos.
This commit is contained in:
parent
8132f7b227
commit
94a27aa4e3
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6.c,v 1.181 2015/02/20 22:13:48 rjs Exp $ */
|
||||
/* $NetBSD: in6.c,v 1.182 2015/02/23 19:15:59 martin Exp $ */
|
||||
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.181 2015/02/20 22:13:48 rjs Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.182 2015/02/23 19:15:59 martin Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_compat_netbsd.h"
|
||||
@ -2318,7 +2318,7 @@ in6_domifdetach(struct ifnet *ifp, void *aux)
|
||||
{
|
||||
struct in6_ifextra *ext = (struct in6_ifextra *)aux;
|
||||
|
||||
nd6_ifdetach(ext->nd_ifinfo);
|
||||
nd6_ifdetach(ifp, ext);
|
||||
free(ext->in6_ifstat, M_IFADDR);
|
||||
free(ext->icmp6_ifstat, M_IFADDR);
|
||||
scope6_ifdetach(ext->scope6_id);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6_ifattach.c,v 1.94 2014/11/14 17:34:23 maxv Exp $ */
|
||||
/* $NetBSD: in6_ifattach.c,v 1.95 2015/02/23 19:15:59 martin Exp $ */
|
||||
/* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.94 2014/11/14 17:34:23 maxv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.95 2015/02/23 19:15:59 martin Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -848,7 +848,7 @@ in6_ifdetach(struct ifnet *ifp)
|
||||
ip6_mrouter_detach(ifp);
|
||||
|
||||
/* remove neighbor management table */
|
||||
nd6_purge(ifp);
|
||||
nd6_purge(ifp, NULL);
|
||||
|
||||
/* XXX this code is duplicated in in6_purgeif() --dyoung */
|
||||
/* nuke any of IPv6 addresses we have */
|
||||
@ -919,7 +919,7 @@ in6_ifdetach(struct ifnet *ifp)
|
||||
* prefixes after removing all addresses above.
|
||||
* (Or can we just delay calling nd6_purge until at this point?)
|
||||
*/
|
||||
nd6_purge(ifp);
|
||||
nd6_purge(ifp, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nd6.c,v 1.157 2015/02/17 15:14:28 christos Exp $ */
|
||||
/* $NetBSD: nd6.c,v 1.158 2015/02/23 19:15:59 martin Exp $ */
|
||||
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.157 2015/02/17 15:14:28 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.158 2015/02/23 19:15:59 martin Exp $");
|
||||
|
||||
#include "bridge.h"
|
||||
#include "carp.h"
|
||||
@ -205,10 +205,11 @@ nd6_ifattach(struct ifnet *ifp)
|
||||
}
|
||||
|
||||
void
|
||||
nd6_ifdetach(struct nd_ifinfo *nd)
|
||||
nd6_ifdetach(struct ifnet *ifp, struct in6_ifextra *ext)
|
||||
{
|
||||
|
||||
free(nd, M_IP6NDP);
|
||||
nd6_purge(ifp, ext);
|
||||
free(ext->nd_ifinfo, M_IP6NDP);
|
||||
}
|
||||
|
||||
void
|
||||
@ -556,7 +557,7 @@ nd6_timer(void *ignored_arg)
|
||||
|
||||
TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, next_dr) {
|
||||
if (dr->expire && dr->expire < time_second) {
|
||||
defrtrlist_del(dr);
|
||||
defrtrlist_del(dr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -746,12 +747,22 @@ nd6_accepts_rtadv(const struct nd_ifinfo *ndi)
|
||||
* ifp goes away.
|
||||
*/
|
||||
void
|
||||
nd6_purge(struct ifnet *ifp)
|
||||
nd6_purge(struct ifnet *ifp, struct in6_ifextra *ext)
|
||||
{
|
||||
struct llinfo_nd6 *ln, *nln;
|
||||
struct nd_defrouter *dr, *ndr;
|
||||
struct nd_prefix *pr, *npr;
|
||||
|
||||
/*
|
||||
* During detach, the ND info might be already removed, but
|
||||
* then is explitly passed as argument.
|
||||
* Otherwise get it from ifp->if_afdata.
|
||||
*/
|
||||
if (ext == NULL)
|
||||
ext = ifp->if_afdata[AF_INET6];
|
||||
if (ext == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Nuke default router list entries toward ifp.
|
||||
* We defer removal of default router list entries that is installed
|
||||
@ -762,16 +773,20 @@ nd6_purge(struct ifnet *ifp)
|
||||
if (dr->installed)
|
||||
continue;
|
||||
|
||||
if (dr->ifp == ifp)
|
||||
defrtrlist_del(dr);
|
||||
if (dr->ifp == ifp) {
|
||||
KASSERT(ext != NULL);
|
||||
defrtrlist_del(dr, ext);
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(dr, &nd_defrouter, dr_entry, ndr) {
|
||||
if (!dr->installed)
|
||||
continue;
|
||||
|
||||
if (dr->ifp == ifp)
|
||||
defrtrlist_del(dr);
|
||||
if (dr->ifp == ifp) {
|
||||
KASSERT(ext != NULL);
|
||||
defrtrlist_del(dr, ext);
|
||||
}
|
||||
}
|
||||
|
||||
/* Nuke prefix list entries toward ifp */
|
||||
@ -1797,7 +1812,7 @@ nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
|
||||
s = splsoftnet();
|
||||
defrouter_reset();
|
||||
TAILQ_FOREACH_SAFE(drtr, &nd_defrouter, dr_entry, next) {
|
||||
defrtrlist_del(drtr);
|
||||
defrtrlist_del(drtr, NULL);
|
||||
}
|
||||
defrouter_select();
|
||||
splx(s);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nd6.h,v 1.61 2014/12/16 11:42:27 roy Exp $ */
|
||||
/* $NetBSD: nd6.h,v 1.62 2015/02/23 19:15:59 martin Exp $ */
|
||||
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -407,7 +407,7 @@ union nd_opts {
|
||||
/* nd6.c */
|
||||
void nd6_init(void);
|
||||
struct nd_ifinfo *nd6_ifattach(struct ifnet *);
|
||||
void nd6_ifdetach(struct nd_ifinfo *);
|
||||
void nd6_ifdetach(struct ifnet *, struct in6_ifextra *);
|
||||
int nd6_is_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *);
|
||||
void nd6_option_init(void *, int, union nd_opts *);
|
||||
struct nd_opt_hdr *nd6_option(union nd_opts *);
|
||||
@ -417,7 +417,7 @@ void nd6_rtmsg(int, struct rtentry *);
|
||||
void nd6_setmtu(struct ifnet *);
|
||||
void nd6_llinfo_settimer(struct llinfo_nd6 *, long);
|
||||
void nd6_timer(void *);
|
||||
void nd6_purge(struct ifnet *);
|
||||
void nd6_purge(struct ifnet *, struct in6_ifextra *);
|
||||
void nd6_nud_hint(struct rtentry *, struct in6_addr *, int);
|
||||
int nd6_resolve(struct ifnet *, struct rtentry *,
|
||||
struct mbuf *, struct sockaddr *, u_char *);
|
||||
@ -454,7 +454,7 @@ void prelist_del(struct nd_prefix *);
|
||||
void defrouter_addreq(struct nd_defrouter *);
|
||||
void defrouter_reset(void);
|
||||
void defrouter_select(void);
|
||||
void defrtrlist_del(struct nd_defrouter *);
|
||||
void defrtrlist_del(struct nd_defrouter *, struct in6_ifextra *);
|
||||
void prelist_remove(struct nd_prefix *);
|
||||
int nd6_prelist_add(struct nd_prefixctl *, struct nd_defrouter *,
|
||||
struct nd_prefix **);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nd6_nbr.c,v 1.103 2014/12/16 11:42:27 roy Exp $ */
|
||||
/* $NetBSD: nd6_nbr.c,v 1.104 2015/02/23 19:15:59 martin Exp $ */
|
||||
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.103 2014/12/16 11:42:27 roy Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.104 2015/02/23 19:15:59 martin Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
@ -804,7 +804,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
||||
s = splsoftnet();
|
||||
dr = defrouter_lookup(in6, rt->rt_ifp);
|
||||
if (dr)
|
||||
defrtrlist_del(dr);
|
||||
defrtrlist_del(dr, NULL);
|
||||
else if (!ip6_forwarding) {
|
||||
/*
|
||||
* Even if the neighbor is not in the default
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nd6_rtr.c,v 1.95 2014/12/16 11:42:27 roy Exp $ */
|
||||
/* $NetBSD: nd6_rtr.c,v 1.96 2015/02/23 19:15:59 martin Exp $ */
|
||||
/* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.95 2014/12/16 11:42:27 roy Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.96 2015/02/23 19:15:59 martin Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -483,12 +483,20 @@ defrouter_lookup(const struct in6_addr *addr, struct ifnet *ifp)
|
||||
}
|
||||
|
||||
void
|
||||
defrtrlist_del(struct nd_defrouter *dr)
|
||||
defrtrlist_del(struct nd_defrouter *dr, struct in6_ifextra *ext)
|
||||
{
|
||||
struct nd_ifinfo *ndi = ND_IFINFO(dr->ifp);
|
||||
struct nd_defrouter *deldr = NULL;
|
||||
struct nd_prefix *pr;
|
||||
struct in6_ifextra *ext = dr->ifp->if_afdata[AF_INET6];
|
||||
struct nd_ifinfo *ndi;
|
||||
|
||||
if (ext == NULL)
|
||||
ext = dr->ifp->if_afdata[AF_INET6];
|
||||
|
||||
/* detach already in progress, can not do anything */
|
||||
if (ext == NULL)
|
||||
return;
|
||||
|
||||
ndi = ext->nd_ifinfo;
|
||||
|
||||
/*
|
||||
* Flush all the routing table entries that use the router
|
||||
@ -749,7 +757,7 @@ defrtrlist_update(struct nd_defrouter *newdr)
|
||||
if ((dr = defrouter_lookup(&newdr->rtaddr, newdr->ifp)) != NULL) {
|
||||
/* entry exists */
|
||||
if (newdr->rtlifetime == 0) {
|
||||
defrtrlist_del(dr);
|
||||
defrtrlist_del(dr, ext);
|
||||
dr = NULL;
|
||||
} else {
|
||||
int oldpref = rtpref(dr);
|
||||
|
Loading…
Reference in New Issue
Block a user