Patchwork [RFC,2/5] hostapd: Add more flexible VLAN briging

login
register
mail settings
Submitter Helmut Schaa
Date March 17, 2014, 1:16 p.m.
Message ID <1395062188-13222-3-git-send-email-helmut.schaa@googlemail.com>
Download mbox | patch
Permalink /patch/331037/
State New
Headers show

Comments

Helmut Schaa - March 17, 2014, 1:16 p.m.
This allows a more flexible VLAN bridging configuration then using
full dynamic vlan tagging (which uses a hardcoded bridge name).

Instead of trying to derive the bridgenames statically allow
another configuration parameter per VLAN that specifies the bridge
interface this VLAN should appear in.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
 hostapd/config_file.c | 46 +++++++++++++++++++++-------------------------
 hostapd/hostapd.vlan  | 10 +++++-----
 src/ap/ap_config.h    |  1 +
 src/ap/ap_drv_ops.c   |  4 ++--
 src/ap/ap_drv_ops.h   |  3 ++-
 src/ap/vlan_init.c    | 24 +++++++++++++++++++++---
 6 files changed, 52 insertions(+), 36 deletions(-)

Patch

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 19d6ad3..c00bc71 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -27,7 +27,7 @@  static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 					 const char *fname)
 {
 	FILE *f;
-	char buf[128], *pos, *pos2;
+	char buf[128], *pos, *ifname, *bridge;
 	int line = 0, vlan_id;
 	struct hostapd_vlan *vlan;
 
@@ -40,26 +40,15 @@  static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 	while (fgets(buf, sizeof(buf), f)) {
 		line++;
 
-		if (buf[0] == '#')
-			continue;
-		pos = buf;
-		while (*pos != '\0') {
-			if (*pos == '\n') {
-				*pos = '\0';
-				break;
-			}
-			pos++;
-		}
-		if (buf[0] == '\0')
+		if (buf[0] == '#' || buf[0] == '\0') 
 			continue;
 
-		if (buf[0] == '*') {
+		pos = strtok(buf, " \t\n");
+		if (pos[0] == '*') {
 			vlan_id = VLAN_ID_WILDCARD;
-			pos = buf + 1;
 		} else {
-			vlan_id = strtol(buf, &pos, 10);
-			if (buf == pos || vlan_id < 1 ||
-			    vlan_id > MAX_VLAN_ID) {
+			vlan_id = strtol(pos, NULL, 10);
+			if (vlan_id < 1 || vlan_id > MAX_VLAN_ID) {
 				wpa_printf(MSG_ERROR, "Invalid VLAN ID at "
 					   "line %d in '%s'", line, fname);
 				fclose(f);
@@ -67,18 +56,23 @@  static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 			}
 		}
 
-		while (*pos == ' ' || *pos == '\t')
-			pos++;
-		pos2 = pos;
-		while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
-			pos2++;
-		*pos2 = '\0';
-		if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
+		pos = strtok(NULL, " \t\n");
+		if (!pos || os_strlen(pos) > IFNAMSIZ) {
 			wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d "
 				   "in '%s'", line, fname);
 			fclose(f);
 			return -1;
 		}
+		ifname = pos;
+
+		pos = strtok(NULL, " \t\n");
+		if (pos && os_strlen(pos) > IFNAMSIZ) {
+			wpa_printf(MSG_ERROR, "Invalid VLAN bridge at line %d "
+				   "in '%s'", line, fname);
+			fclose(f);
+			return -1;
+		}
+		bridge = pos;
 
 		vlan = os_zalloc(sizeof(*vlan));
 		if (vlan == NULL) {
@@ -89,7 +83,9 @@  static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 		}
 
 		vlan->vlan_id = vlan_id;
-		os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
+		os_strlcpy(vlan->ifname, ifname, sizeof(vlan->ifname));
+		if (bridge)
+			os_strlcpy(vlan->bridge, bridge, sizeof(vlan->bridge));
 		vlan->next = bss->vlan;
 		bss->vlan = vlan;
 	}
diff --git a/hostapd/hostapd.vlan b/hostapd/hostapd.vlan
index 98254fa..74fc201 100644
--- a/hostapd/hostapd.vlan
+++ b/hostapd/hostapd.vlan
@@ -1,9 +1,9 @@ 
 # VLAN ID to network interface mapping
-1	vlan1
-2	vlan2
-3	vlan3
-100	guest
+1	vlan1	br1
+2	vlan2	br2
+3	vlan3	br3
+100	guest	br4
 # Optional wildcard entry matching all VLAN IDs. The first # in the interface
 # name will be replaced with the VLAN ID. The network interfaces are created
 # (and removed) dynamically based on the use.
-*	vlan#
+*	vlan#	br#
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 4631ca9..5875529 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -85,6 +85,7 @@  struct hostapd_vlan {
 	struct hostapd_vlan *next;
 	int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
 	char ifname[IFNAMSIZ + 1];
+	char bridge[IFNAMSIZ + 1];
 	int dynamic_vlan;
 #ifdef CONFIG_FULL_DYNAMIC_VLAN
 
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index e998fc6..1c3f423 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -280,12 +280,12 @@  int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
 }
 
 
-int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
+int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname, const char *bridge)
 {
 	char force_ifname[IFNAMSIZ];
 	u8 if_addr[ETH_ALEN];
 	return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
-			      NULL, NULL, force_ifname, if_addr, NULL, 0);
+			      NULL, NULL, force_ifname, if_addr, bridge, 0);
 }
 
 
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 9edaf7d..b283eca 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -30,7 +30,8 @@  int hostapd_set_authorized(struct hostapd_data *hapd,
 int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
 int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
 			      int enabled);
-int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
+int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname,
+			const char *bridge);
 int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
 int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
 			const u8 *addr, int aid, int val);
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 7ff5b1a..4835860 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -933,7 +933,9 @@  static int vlan_dynamic_add(struct hostapd_data *hapd,
 {
 	while (vlan) {
 		if (vlan->vlan_id != VLAN_ID_WILDCARD) {
-			if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
+			if (hostapd_vlan_if_add(hapd, vlan->ifname,
+						vlan->bridge[0] == '\0' ?
+						NULL : vlan->bridge)) {
 				if (errno != EEXIST) {
 					wpa_printf(MSG_ERROR, "VLAN: Could "
 						   "not add VLAN %s: %s",
@@ -1026,6 +1028,7 @@  struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 {
 	struct hostapd_vlan *n = NULL;
 	char *ifname, *pos;
+	char *brname = NULL;
 
 	if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID ||
 	    vlan->vlan_id != VLAN_ID_WILDCARD)
@@ -1041,9 +1044,21 @@  struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 		goto free_ifname;
 	*pos++ = '\0';
 
+	if (vlan->bridge[0] != '\0') {
+		brname = os_strdup(vlan->bridge);
+		if (brname == NULL)
+			goto free_ifname;
+		pos = os_strchr(vlan->bridge, '#');
+		if (pos == NULL)
+			goto free_brname;
+		*pos++ = '\0';
+		os_snprintf(n->bridge, sizeof(n->bridge), "%s%d%s", brname,
+			    vlan_id, pos);
+	}
+
 	n = os_zalloc(sizeof(*n));
 	if (n == NULL)
-		goto free_ifname;
+		goto free_brname;
 
 	n->vlan_id = vlan_id;
 	n->dynamic_vlan = 1;
@@ -1051,7 +1066,8 @@  struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 	os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
 		    pos);
 
-	if (hostapd_vlan_if_add(hapd, n->ifname)) {
+	if (hostapd_vlan_if_add(hapd, n->ifname,
+				n->bridge[0] == '\0' ? NULL : n->bridge)) {
 		os_free(n);
 		n = NULL;
 		goto free_ifname;
@@ -1064,6 +1080,8 @@  struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 	ifconfig_up(n->ifname);
 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
 
+free_brname:
+	os_free(brname);
 free_ifname:
 	os_free(ifname);
 	return n;