Browse Source

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 <michael-dev@fami-braun.de>
Michael Braun 9 years ago
parent
commit
d0bdc96bdd
1 changed files with 40 additions and 4 deletions
  1. 40 4
      src/ap/vlan_init.c

+ 40 - 4
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;