From a91af134655cb94d293a8d398490ac309734b4e8 Mon Sep 17 00:00:00 2001 From: mav Date: Tue, 30 May 2017 16:34:18 +0000 Subject: MFC r318689: Add parent interface reference counting to if_vlan. Using plain ifunit() looks like a request for troubles. --- sys/net/if_vlan.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index a98c173..0af2128 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -469,6 +469,7 @@ trunk_destroy(struct ifvlantrunk *trunk) trunk->parent->if_vlantrunk = NULL; TRUNK_UNLOCK(trunk); TRUNK_LOCK_DESTROY(trunk); + if_rele(trunk->parent); free(trunk, M_VLAN); } @@ -843,16 +844,20 @@ vlan_clone_match_ethervid(const char *name, int *vidp) if ((cp = strchr(ifname, '.')) == NULL) return (NULL); *cp = '\0'; - if ((ifp = ifunit(ifname)) == NULL) + if ((ifp = ifunit_ref(ifname)) == NULL) return (NULL); /* Parse VID. */ - if (*++cp == '\0') + if (*++cp == '\0') { + if_rele(ifp); return (NULL); + } vid = 0; for(; *cp >= '0' && *cp <= '9'; cp++) vid = (vid * 10) + (*cp - '0'); - if (*cp != '\0') + if (*cp != '\0') { + if_rele(ifp); return (NULL); + } if (vidp != NULL) *vidp = vid; @@ -885,7 +890,6 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) int unit; int error; int vid; - int ethertag; struct ifvlan *ifv; struct ifnet *ifp; struct ifnet *p; @@ -910,23 +914,21 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) error = copyin(params, &vlr, sizeof(vlr)); if (error) return error; - p = ifunit(vlr.vlr_parent); + p = ifunit_ref(vlr.vlr_parent); if (p == NULL) return (ENXIO); error = ifc_name2unit(name, &unit); - if (error != 0) + if (error != 0) { + if_rele(p); return (error); - - ethertag = 1; + } vid = vlr.vlr_tag; wildcard = (unit < 0); } else if ((p = vlan_clone_match_ethervid(name, &vid)) != NULL) { - ethertag = 1; unit = -1; wildcard = 0; } else { - ethertag = 0; - + p = NULL; error = ifc_name2unit(name, &unit); if (error != 0) return (error); @@ -935,8 +937,11 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) } error = ifc_alloc_unit(ifc, &unit); - if (error != 0) + if (error != 0) { + if (p != NULL) + if_rele(p); return (error); + } /* In the wildcard case, we need to update the name. */ if (wildcard) { @@ -952,6 +957,8 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) if (ifp == NULL) { ifc_free_unit(ifc, unit); free(ifv, M_VLAN); + if (p != NULL) + if_rele(p); return (ENOSPC); } SLIST_INIT(&ifv->vlan_mc_listhead); @@ -982,8 +989,9 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) sdl = (struct sockaddr_dl *)ifa->ifa_addr; sdl->sdl_type = IFT_L2VLAN; - if (ethertag) { + if (p != NULL) { error = vlan_config(ifv, p, vid); + if_rele(p); if (error != 0) { /* * Since we've partially failed, we need to back @@ -1270,6 +1278,7 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t vid) TRUNK_LOCK(trunk); p->if_vlantrunk = trunk; trunk->parent = p; + if_ref(trunk->parent); } else { VLAN_LOCK(); exists: @@ -1676,8 +1685,10 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) VLAN_LOCK(); if (TRUNK(ifv) != NULL) { p = PARENT(ifv); + if_ref(p); VLAN_UNLOCK(); error = (*p->if_ioctl)(p, SIOCGIFMEDIA, data); + if_rele(p); /* Limit the result to the parent's current config. */ if (error == 0) { struct ifmediareq *ifmr; @@ -1739,12 +1750,13 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) vlan_unconfig(ifp); break; } - p = ifunit(vlr.vlr_parent); + p = ifunit_ref(vlr.vlr_parent); if (p == NULL) { error = ENOENT; break; } error = vlan_config(ifv, p, vlr.vlr_tag); + if_rele(p); if (error) break; -- cgit v1.1