]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
VLAN: Actually add tagged VLANs to AP_VLAN
authorMichael Braun <michael-dev@fami-braun.de>
Thu, 21 Jan 2016 13:51:59 +0000 (14:51 +0100)
committerJouni Malinen <j@w1.fi>
Wed, 17 Feb 2016 09:46:13 +0000 (11:46 +0200)
This makes vlan_newlink() and vlan_dellink() add tagged VLANs to AP_VLAN
interfaces as given by struct vlan_description.

hostapd_vlan_if_remove() is done in vlan_dellink() as tagged interfaces
need to be removed before the interface can be deleted and a DELLINK
message can be generated.

Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
src/ap/vlan_init.c

index 70110ef7a5e8316a60e5aea151300ea99ff21ce8..56959e5d6f11f17f34458c4eb6357f7c1cf4c567 100644 (file)
@@ -686,7 +686,7 @@ static void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
 {
        char br_name[IFNAMSIZ];
        struct hostapd_vlan *vlan;
-       int untagged;
+       int untagged, *tagged, i;
 
        wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
 
@@ -702,6 +702,7 @@ static void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
        vlan->configured = 1;
 
        untagged = vlan->vlan_desc.untagged;
+       tagged = vlan->vlan_desc.tagged;
 
        if (untagged > 0 && untagged <= MAX_VLAN_ID) {
                vlan_bridge_name(br_name, hapd, untagged);
@@ -712,6 +713,17 @@ static void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
                        vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
        }
 
+       for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
+               if (tagged[i] == untagged ||
+                   tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
+                   (i > 0 && tagged[i] == tagged[i - 1]))
+                       continue;
+               vlan_bridge_name(br_name, hapd, tagged[i]);
+               vlan_get_bridge(br_name, hapd, tagged[i]);
+               vlan_newlink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
+                                   ifname, br_name, tagged[i], hapd);
+       }
+
        ifconfig_up(ifname);
 }
 
@@ -781,7 +793,20 @@ static void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
 
        if (vlan->configured) {
                int untagged = vlan->vlan_desc.untagged;
+               int *tagged = vlan->vlan_desc.tagged;
                char br_name[IFNAMSIZ];
+               int i;
+
+               for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
+                       if (tagged[i] == untagged ||
+                           tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
+                           (i > 0 && tagged[i] == tagged[i - 1]))
+                               continue;
+                       vlan_bridge_name(br_name, hapd, tagged[i]);
+                       vlan_dellink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
+                                           ifname, br_name, tagged[i], hapd);
+                       vlan_put_bridge(br_name, hapd, tagged[i]);
+               }
 
                if (untagged > 0 && untagged <= MAX_VLAN_ID) {
                        vlan_bridge_name(br_name, hapd, untagged);
@@ -793,6 +818,15 @@ static void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
                }
        }
 
+       /*
+        * Ensure this VLAN interface is actually removed even if
+        * NEWLINK message is only received later.
+        */
+       if (if_nametoindex(vlan->ifname) && vlan_if_remove(hapd, vlan))
+               wpa_printf(MSG_ERROR,
+                          "VLAN: Could not remove VLAN iface: %s: %s",
+                          vlan->ifname, strerror(errno));
+
        if (vlan == first)
                hapd->conf->vlan = vlan->next;
        else
@@ -1006,15 +1040,17 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd,
        while (vlan) {
                next = vlan->next;
 
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+               /* vlan_dellink() takes care of cleanup and interface removal */
+               if (vlan->vlan_id != VLAN_ID_WILDCARD)
+                       vlan_dellink(vlan->ifname, hapd);
+#else /* CONFIG_FULL_DYNAMIC_VLAN */
                if (vlan->vlan_id != VLAN_ID_WILDCARD &&
                    vlan_if_remove(hapd, vlan)) {
                        wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
                                   "iface: %s: %s",
                                   vlan->ifname, strerror(errno));
                }
-#ifdef CONFIG_FULL_DYNAMIC_VLAN
-               if (vlan->clean)
-                       vlan_dellink(vlan->ifname, hapd);
 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
 
                vlan = next;