Browse Source

VLAN: Factor out per-vid code in newlink/dellink

To prepare for adding tagged VLAN support in vlan_init.c, vlan_newlink()
and vlan_dellink() are split into multiple functions. This reduces
indention and eases adding tagged VLANs as well.

Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
Michael Braun 9 years ago
parent
commit
f9c00188ca
1 changed files with 139 additions and 112 deletions
  1. 139 112
      src/ap/vlan_init.c

+ 139 - 112
src/ap/vlan_init.c

@@ -623,155 +623,182 @@ static int vlan_set_name_type(unsigned int name_type)
 #endif /* CONFIG_VLAN_NETLINK */
 
 
-static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
+static void vlan_newlink_tagged(int vlan_naming, const char *tagged_interface,
+				const char *br_name, int vid,
+				struct hostapd_data *hapd)
 {
 	char vlan_ifname[IFNAMSIZ];
-	char br_name[IFNAMSIZ];
-	struct hostapd_vlan *vlan = hapd->conf->vlan;
+	int clean;
+
+	if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
+		os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
+			    tagged_interface, vid);
+	else
+		os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
+
+	clean = 0;
+	ifconfig_up(tagged_interface);
+	if (!vlan_add(tagged_interface, vid, vlan_ifname))
+		clean |= DVLAN_CLEAN_VLAN;
+
+	if (!br_addif(br_name, vlan_ifname))
+		clean |= DVLAN_CLEAN_VLAN_PORT;
+
+	dyn_iface_get(hapd, vlan_ifname, clean);
+
+	ifconfig_up(vlan_ifname);
+}
+
+
+static void vlan_bridge_name(char *br_name, struct hostapd_data *hapd, int vid)
+{
+	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
+
+	if (hapd->conf->vlan_bridge[0]) {
+		os_snprintf(br_name, IFNAMSIZ, "%s%d",
+			    hapd->conf->vlan_bridge, vid);
+	} else if (tagged_interface) {
+		os_snprintf(br_name, IFNAMSIZ, "br%s.%d",
+			    tagged_interface, vid);
+	} else {
+		os_snprintf(br_name, IFNAMSIZ, "brvlan%d", vid);
+	}
+}
+
+
+static void vlan_get_bridge(const char *br_name, struct hostapd_data *hapd,
+			    int vid)
+{
 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
 	int vlan_naming = hapd->conf->ssid.vlan_naming;
-	int clean, untagged;
 
-	wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
+	dyn_iface_get(hapd, br_name, br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
 
-	while (vlan) {
-		untagged = vlan->vlan_desc.untagged;
-		if (os_strcmp(ifname, vlan->ifname) == 0 && !vlan->configured) {
-			vlan->configured = 1;
-
-			if (hapd->conf->vlan_bridge[0]) {
-				os_snprintf(br_name, sizeof(br_name), "%s%d",
-					    hapd->conf->vlan_bridge,
-					    untagged);
-			} else if (tagged_interface) {
-				os_snprintf(br_name, sizeof(br_name),
-				            "br%s.%d", tagged_interface,
-					    untagged);
-			} else {
-				os_snprintf(br_name, sizeof(br_name),
-					    "brvlan%d", untagged);
-			}
+	ifconfig_up(br_name);
 
-			dyn_iface_get(hapd, br_name,
-				      br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
+	if (tagged_interface)
+		vlan_newlink_tagged(vlan_naming, tagged_interface, br_name,
+				    vid, hapd);
+}
 
-			ifconfig_up(br_name);
 
-			if (tagged_interface) {
-				if (vlan_naming ==
-				    DYNAMIC_VLAN_NAMING_WITH_DEVICE)
-					os_snprintf(vlan_ifname,
-						    sizeof(vlan_ifname),
-						    "%s.%d", tagged_interface,
-						    untagged);
-				else
-					os_snprintf(vlan_ifname,
-						    sizeof(vlan_ifname),
-						    "vlan%d", untagged);
+static void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
+{
+	char br_name[IFNAMSIZ];
+	struct hostapd_vlan *vlan;
+	int untagged;
 
-				clean = 0;
-				ifconfig_up(tagged_interface);
-				if (!vlan_add(tagged_interface, untagged,
-					      vlan_ifname))
-					clean |= DVLAN_CLEAN_VLAN;
+	wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
 
-				if (!br_addif(br_name, vlan_ifname))
-					clean |= DVLAN_CLEAN_VLAN_PORT;
+	for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
+		if (vlan->configured ||
+		    os_strcmp(ifname, vlan->ifname) != 0)
+			continue;
+		break;
+	}
+	if (!vlan)
+		return;
 
-				dyn_iface_get(hapd, vlan_ifname, clean);
+	vlan->configured = 1;
 
-				ifconfig_up(vlan_ifname);
-			}
+	untagged = vlan->vlan_desc.untagged;
 
-			if (!br_addif(br_name, ifname))
-				vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
+	if (untagged > 0 && untagged <= MAX_VLAN_ID) {
+		vlan_bridge_name(br_name, hapd, untagged);
 
-			ifconfig_up(ifname);
+		vlan_get_bridge(br_name, hapd, untagged);
 
-			break;
-		}
-		vlan = vlan->next;
+		if (!br_addif(br_name, ifname))
+			vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
 	}
+
+	ifconfig_up(ifname);
 }
 
 
-static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
+static void vlan_dellink_tagged(int vlan_naming, const char *tagged_interface,
+				const char *br_name, int vid,
+				struct hostapd_data *hapd)
 {
 	char vlan_ifname[IFNAMSIZ];
-	char br_name[IFNAMSIZ];
-	struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
+	int clean;
+
+	if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
+		os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
+			    tagged_interface, vid);
+	else
+		os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
+
+	clean = dyn_iface_put(hapd, vlan_ifname);
+
+	if (clean & DVLAN_CLEAN_VLAN_PORT)
+		br_delif(br_name, vlan_ifname);
+
+	if (clean & DVLAN_CLEAN_VLAN) {
+		ifconfig_down(vlan_ifname);
+		vlan_rem(vlan_ifname);
+	}
+}
+
+
+static void vlan_put_bridge(const char *br_name, struct hostapd_data *hapd,
+			    int vid)
+{
+	int clean;
 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
 	int vlan_naming = hapd->conf->ssid.vlan_naming;
-	int clean, untagged;
+
+	if (tagged_interface)
+		vlan_dellink_tagged(vlan_naming, tagged_interface, br_name,
+				    vid, hapd);
+
+	clean = dyn_iface_put(hapd, br_name);
+	if ((clean & DVLAN_CLEAN_BR) && br_getnumports(br_name) == 0) {
+		ifconfig_down(br_name);
+		br_delbr(br_name);
+	}
+}
+
+
+static void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
+{
+	struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
 
 	wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
 
 	first = prev = vlan;
 
 	while (vlan) {
-		untagged = vlan->vlan_desc.untagged;
-		if (os_strcmp(ifname, vlan->ifname) == 0 &&
-		    vlan->configured) {
-			if (hapd->conf->vlan_bridge[0]) {
-				os_snprintf(br_name, sizeof(br_name), "%s%d",
-					    hapd->conf->vlan_bridge,
-					    untagged);
-			} else if (tagged_interface) {
-				os_snprintf(br_name, sizeof(br_name),
-				            "br%s.%d", tagged_interface,
-					    untagged);
-			} else {
-				os_snprintf(br_name, sizeof(br_name),
-					    "brvlan%d", untagged);
-			}
+		if (os_strcmp(ifname, vlan->ifname) != 0) {
+			prev = vlan;
+			vlan = vlan->next;
+			continue;
+		}
+		break;
+	}
+	if (!vlan)
+		return;
+
+	if (vlan->configured) {
+		int untagged = vlan->vlan_desc.untagged;
+		char br_name[IFNAMSIZ];
+
+		if (untagged > 0 && untagged <= MAX_VLAN_ID) {
+			vlan_bridge_name(br_name, hapd, untagged);
 
 			if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
 				br_delif(br_name, vlan->ifname);
 
-			if (tagged_interface) {
-				if (vlan_naming ==
-				    DYNAMIC_VLAN_NAMING_WITH_DEVICE)
-					os_snprintf(vlan_ifname,
-						    sizeof(vlan_ifname),
-						    "%s.%d", tagged_interface,
-						    untagged);
-				else
-					os_snprintf(vlan_ifname,
-						    sizeof(vlan_ifname),
-						    "vlan%d", untagged);
-
-				clean = dyn_iface_put(hapd, vlan_ifname);
-
-				if (clean & DVLAN_CLEAN_VLAN_PORT)
-					br_delif(br_name, vlan_ifname);
-
-				if (clean & DVLAN_CLEAN_VLAN) {
-					ifconfig_down(vlan_ifname);
-					vlan_rem(vlan_ifname);
-				}
-			}
-
-			clean = dyn_iface_put(hapd, br_name);
-			if ((clean & DVLAN_CLEAN_BR) &&
-			    br_getnumports(br_name) == 0) {
-				ifconfig_down(br_name);
-				br_delbr(br_name);
-			}
+			vlan_put_bridge(br_name, hapd, untagged);
 		}
+	}
 
-		if (os_strcmp(ifname, vlan->ifname) == 0) {
-			if (vlan == first) {
-				hapd->conf->vlan = vlan->next;
-			} else {
-				prev->next = vlan->next;
-			}
-			os_free(vlan);
+	if (vlan == first)
+		hapd->conf->vlan = vlan->next;
+	else
+		prev->next = vlan->next;
 
-			break;
-		}
-		prev = vlan;
-		vlan = vlan->next;
-	}
+	os_free(vlan);
 }