hostapd: add support for overriding the bridge name per VLAN via vlan_file

Message ID 20181114165023.99218-1-nbd@nbd.name
State New
Headers show
Series
  • hostapd: add support for overriding the bridge name per VLAN via vlan_file
Related show

Commit Message

Felix Fietkau Nov. 14, 2018, 4:50 p.m.
This makes it easier to integrate dynamic VLANs in custom network
configurations.
The bridge name is added after the interface name in the vlan_file line,
also separated by whitespace

Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
 hostapd/config_file.c | 15 +++++++++++++--
 hostapd/hostapd.conf  |  1 +
 src/ap/ap_config.h    |  1 +
 src/ap/vlan_full.c    | 15 +++++++++------
 src/ap/vlan_init.c    |  1 +
 5 files changed, 25 insertions(+), 8 deletions(-)

Patch

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index b26da71a8..288f02685 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -37,7 +37,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, *pos2, *pos3;
 	int line = 0, vlan_id;
 	struct hostapd_vlan *vlan;
 
@@ -82,7 +82,10 @@  static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 		pos2 = pos;
 		while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
 			pos2++;
-		*pos2 = '\0';
+
+		if (*pos2 != '\0')
+			*(pos2++) = '\0';
+
 		if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
 			wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d "
 				   "in '%s'", line, fname);
@@ -90,6 +93,13 @@  static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 			return -1;
 		}
 
+		while (*pos2 == ' ' || *pos2 == '\t')
+			pos2++;
+		pos3 = pos2;
+		while (*pos3 != ' ' && *pos3 != '\t' && *pos3 != '\0')
+			pos3++;
+		*pos3 = '\0';
+
 		vlan = os_zalloc(sizeof(*vlan));
 		if (vlan == NULL) {
 			wpa_printf(MSG_ERROR, "Out of memory while reading "
@@ -102,6 +112,7 @@  static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 		vlan->vlan_desc.untagged = vlan_id;
 		vlan->vlan_desc.notempty = !!vlan_id;
 		os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
+		os_strlcpy(vlan->bridge, pos2, sizeof(vlan->bridge));
 		vlan->next = bss->vlan;
 		bss->vlan = vlan;
 	}
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index a00521711..aac1cfb04 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1128,6 +1128,7 @@  own_ip_addr=127.0.0.1
 # white space (space or tab).
 # If no entries are provided by this file, the station is statically mapped
 # to <bss-iface>.<vlan-id> interfaces.
+# Each line can optionally also contain the name of a bridge to add the VLAN to
 #vlan_file=/etc/hostapd.vlan
 
 # Interface where 802.1q tagged packets should appear when a RADIUS server is
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 778366d49..d816dfa32 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -122,6 +122,7 @@  struct hostapd_vlan {
 	int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
 	struct vlan_description vlan_desc;
 	char ifname[IFNAMSIZ + 1];
+	char bridge[IFNAMSIZ + 1];
 	int configured;
 	int dynamic_vlan;
 #ifdef CONFIG_FULL_DYNAMIC_VLAN
diff --git a/src/ap/vlan_full.c b/src/ap/vlan_full.c
index aa42335b9..702051b41 100644
--- a/src/ap/vlan_full.c
+++ b/src/ap/vlan_full.c
@@ -384,11 +384,14 @@  static void vlan_newlink_tagged(int vlan_naming, const char *tagged_interface,
 }
 
 
-static void vlan_bridge_name(char *br_name, struct hostapd_data *hapd, int vid)
+static void vlan_bridge_name(char *br_name, struct hostapd_data *hapd,
+			     struct hostapd_vlan *vlan, int vid)
 {
 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
 
-	if (hapd->conf->vlan_bridge[0]) {
+	if (vlan->bridge[0]) {
+		os_strlcpy(br_name, vlan->bridge, IFNAMSIZ);
+	} else if (hapd->conf->vlan_bridge[0]) {
 		os_snprintf(br_name, IFNAMSIZ, "%s%d",
 			    hapd->conf->vlan_bridge, vid);
 	} else if (tagged_interface) {
@@ -445,7 +448,7 @@  void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
 		    !br_addif(hapd->conf->bridge, ifname))
 			vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
 	} else if (untagged > 0 && untagged <= MAX_VLAN_ID) {
-		vlan_bridge_name(br_name, hapd, untagged);
+		vlan_bridge_name(br_name, hapd, vlan, untagged);
 
 		vlan_get_bridge(br_name, hapd, untagged);
 
@@ -458,7 +461,7 @@  void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
 		    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_bridge_name(br_name, hapd, vlan, tagged[i]);
 		vlan_get_bridge(br_name, hapd, tagged[i]);
 		vlan_newlink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
 				    ifname, br_name, tagged[i], hapd);
@@ -543,7 +546,7 @@  void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
 			    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_bridge_name(br_name, hapd, vlan, tagged[i]);
 			vlan_dellink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
 					    ifname, br_name, tagged[i], hapd);
 			vlan_put_bridge(br_name, hapd, tagged[i]);
@@ -555,7 +558,7 @@  void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
 			    (vlan->clean & DVLAN_CLEAN_WLAN_PORT))
 				br_delif(hapd->conf->bridge, ifname);
 		} else if (untagged > 0 && untagged <= MAX_VLAN_ID) {
-			vlan_bridge_name(br_name, hapd, untagged);
+			vlan_bridge_name(br_name, hapd, vlan, untagged);
 
 			if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
 				br_delif(br_name, vlan->ifname);
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 01fecee02..ce37fdaf9 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -210,6 +210,7 @@  struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
 
 	os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
 		    pos);
+	os_strlcpy(n->bridge, vlan->bridge, sizeof(n->bridge));
 
 	n->next = hapd->conf->vlan;
 	hapd->conf->vlan = n;