summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2006-02-09 00:05:56 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2006-02-09 00:05:56 +0000
commit9f538de4e1b1e7230c39dc8e4c9f965ee26be942 (patch)
treeb17e6d63bb693de67a715d26e9146ad11fce32ca
parentf423f970c207e23bbab7378ff100d7feea27fe76 (diff)
add an interface detach hook and use it with the vlan(4) driver. this
fixes a possible crash if the parent interface has been destroyed (like vlan on trunk) before destroying the vlan interface. ok brad@
-rw-r--r--sys/net/if.c16
-rw-r--r--sys/net/if.h3
-rw-r--r--sys/net/if_vlan.c31
-rw-r--r--sys/net/if_vlan_var.h3
4 files changed, 46 insertions, 7 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 0d616d5f8cf..4cd166fb3c9 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.142 2006/01/05 03:28:34 deraadt Exp $ */
+/* $OpenBSD: if.c,v 1.143 2006/02/09 00:05:55 reyk Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -405,6 +405,11 @@ if_attachhead(struct ifnet *ifp)
if (ifp->if_linkstatehooks == NULL)
panic("if_attachhead: malloc");
TAILQ_INIT(ifp->if_linkstatehooks);
+ ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
+ M_TEMP, M_NOWAIT);
+ if (ifp->if_detachhooks == NULL)
+ panic("if_attachhead: malloc");
+ TAILQ_INIT(ifp->if_detachhooks);
TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
if_attachsetup(ifp);
}
@@ -431,6 +436,11 @@ if_attach(struct ifnet *ifp)
if (ifp->if_linkstatehooks == NULL)
panic("if_attach: malloc");
TAILQ_INIT(ifp->if_linkstatehooks);
+ ifp->if_detachhooks = malloc(sizeof(*ifp->if_detachhooks),
+ M_TEMP, M_NOWAIT);
+ if (ifp->if_detachhooks == NULL)
+ panic("if_attach: malloc");
+ TAILQ_INIT(ifp->if_detachhooks);
#if NCARP > 0
if (ifp->if_type != IFT_CARP)
@@ -500,6 +510,9 @@ if_detach(struct ifnet *ifp)
ifp->if_init = if_detached_init;
ifp->if_watchdog = if_detached_watchdog;
+ /* Call detach hooks, ie. to remove vlan interfaces */
+ dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
+
#if NTRUNK > 0
if (ifp->if_type == IFT_IEEE8023ADLAG)
trunk_port_ifdetach(ifp);
@@ -626,6 +639,7 @@ do { \
free(ifp->if_addrhooks, M_TEMP);
free(ifp->if_linkstatehooks, M_TEMP);
+ free(ifp->if_detachhooks, M_TEMP);
for (dp = domains; dp; dp = dp->dom_next) {
if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
diff --git a/sys/net/if.h b/sys/net/if.h
index 1db23f36d84..4bab20af4c1 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.76 2005/06/14 04:00:39 henning Exp $ */
+/* $OpenBSD: if.h,v 1.77 2006/02/09 00:05:55 reyk Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -177,6 +177,7 @@ struct ifnet { /* and the entries */
TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
struct hook_desc_head *if_addrhooks; /* address change callbacks */
struct hook_desc_head *if_linkstatehooks; /* link change callbacks */
+ struct hook_desc_head *if_detachhooks; /* detach callbacks */
char if_xname[IFNAMSIZ]; /* external name (name + unit) */
int if_pcount; /* number of promiscuous listeners */
caddr_t if_bpf; /* packet filter structure */
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 3f4ce7e8bd9..c47b3178c6c 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vlan.c,v 1.62 2006/01/05 14:57:24 norby Exp $ */
+/* $OpenBSD: if_vlan.c,v 1.63 2006/02/09 00:05:55 reyk Exp $ */
/*
* Copyright 1998 Massachusetts Institute of Technology
@@ -97,6 +97,7 @@ int vlan_ether_delmulti(struct ifvlan *, struct ifreq *);
void vlan_ether_purgemulti(struct ifvlan *);
int vlan_clone_create(struct if_clone *, int);
int vlan_clone_destroy(struct ifnet *);
+void vlan_ifdetach(void *);
struct if_clone vlan_cloner =
IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
@@ -159,6 +160,20 @@ vlan_clone_destroy(struct ifnet *ifp)
}
void
+vlan_ifdetach(void *ptr)
+{
+ struct ifvlan *ifv = (struct ifvlan *)ptr;
+ /*
+ * Destroy the vlan interface because the parent has been
+ * detached. Set the dh_cookie to NULL because we're running
+ * inside of dohooks which is told to disestablish the hook
+ * for us (otherwise we would kill the TAILQ element...).
+ */
+ ifv->dh_cookie = NULL;
+ vlan_clone_destroy(&ifv->ifv_if);
+}
+
+void
vlan_start(struct ifnet *ifp)
{
struct ifvlan *ifv;
@@ -389,6 +404,11 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
/* Register callback for physical link state changes */
ifv->lh_cookie = hook_establish(p->if_linkstatehooks, 1,
vlan_vlandev_state, ifv);
+
+ /* Register callback if parent wants to unregister */
+ ifv->dh_cookie = hook_establish(p->if_detachhooks, 1,
+ vlan_ifdetach, ifv);
+
vlan_vlandev_state(ifv);
splx(s);
@@ -407,15 +427,18 @@ vlan_unconfig(struct ifnet *ifp)
ifv = ifp->if_softc;
p = ifv->ifv_p;
- ifr = (struct ifreq *)&ifp->if_data;
- ifr_p = (struct ifreq *)&ifv->ifv_p->if_data;
-
if (p == NULL)
return 0;
+ ifr = (struct ifreq *)&ifp->if_data;
+ ifr_p = (struct ifreq *)&ifv->ifv_p->if_data;
+
s = splnet();
LIST_REMOVE(ifv, ifv_list);
hook_disestablish(p->if_linkstatehooks, ifv->lh_cookie);
+ /* The cookie is NULL if disestablished externally */
+ if (ifv->dh_cookie != NULL)
+ hook_disestablish(p->if_detachhooks, ifv->dh_cookie);
splx(s);
/*
diff --git a/sys/net/if_vlan_var.h b/sys/net/if_vlan_var.h
index d29a9bd8c5c..3534f92d7e0 100644
--- a/sys/net/if_vlan_var.h
+++ b/sys/net/if_vlan_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vlan_var.h,v 1.17 2006/01/05 14:57:24 norby Exp $ */
+/* $OpenBSD: if_vlan_var.h,v 1.18 2006/02/09 00:05:55 reyk Exp $ */
/*
* Copyright 1998 Massachusetts Institute of Technology
@@ -58,6 +58,7 @@ struct ifvlan {
LIST_ENTRY(ifvlan) ifv_list;
int ifv_flags;
void *lh_cookie;
+ void *dh_cookie;
};
#define ifv_if ifv_ac.ac_if