[RFC 2/5] hostapd: Add more flexible VLAN briging
Helmut Schaa
helmut.schaa
Mon Mar 17 06:16:25 PDT 2014
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 at 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(-)
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;
--
1.8.1.4
More information about the Hostap
mailing list