diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2006-02-09 00:05:56 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2006-02-09 00:05:56 +0000 |
commit | 9f538de4e1b1e7230c39dc8e4c9f965ee26be942 (patch) | |
tree | b17e6d63bb693de67a715d26e9146ad11fce32ca | |
parent | f423f970c207e23bbab7378ff100d7feea27fe76 (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.c | 16 | ||||
-rw-r--r-- | sys/net/if.h | 3 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 31 | ||||
-rw-r--r-- | sys/net/if_vlan_var.h | 3 |
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 |