Author: mav
Date: Tue May 30 16:34:18 2017
New Revision: 319224
URL: https://svnweb.freebsd.org/changeset/base/319224

Log:
  MFC r318689: Add parent interface reference counting to if_vlan.
  
  Using plain ifunit() looks like a request for troubles.

Modified:
  stable/11/sys/net/if_vlan.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/net/if_vlan.c
==============================================================================
--- stable/11/sys/net/if_vlan.c Tue May 30 16:17:00 2017        (r319223)
+++ stable/11/sys/net/if_vlan.c Tue May 30 16:34:18 2017        (r319224)
@@ -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, si
        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, si
                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, si
        }
 
        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, si
        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, si
        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, uint1
                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;
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to