From d0bdc96bdda1e37a32eca0a77e323613f1e61038 Mon Sep 17 00:00:00 2001 From: Michael Braun Date: Thu, 21 Jan 2016 14:51:59 +0100 Subject: [PATCH] VLAN: Actually add tagged VLANs to AP_VLAN 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 --- src/ap/vlan_init.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c index 70110ef7a..56959e5d6 100644 --- a/src/ap/vlan_init.c +++ b/src/ap/vlan_init.c @@ -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;