[PATCHv2 14/21] VLAN: use untagged/tagged for interface configuration
Michael Braun
michael-dev
Thu Jun 6 03:09:54 PDT 2013
Signed-hostap: Michael Braun <michael-dev at fami-braun.de>
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 2ddc192..9638d0e 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -92,6 +92,10 @@ struct hostapd_vlan {
/* untagged = VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
vlan_t vlan_id;
char ifname[IFNAMSIZ + 1];
+ /* VLANs created automatically for a WILDCARD entry use this id for id
+ * generation. The linked list is sorted by this id (ascending);
+ * non-dynamically generated entries get value zero */
+ int artifical_id;
int dynamic_vlan;
#ifdef CONFIG_FULL_DYNAMIC_VLAN
@@ -99,7 +103,7 @@ struct hostapd_vlan {
#define DVLAN_CLEAN_VLAN 0x2
#define DVLAN_CLEAN_VLAN_PORT 0x4
#define DVLAN_CLEAN_WLAN_PORT 0x8
- int clean;
+ int *clean;
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
};
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 3ec17b8..efed3c8 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -693,14 +693,19 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
else if (vlan_notempty(&sta->vlan_id) &&
vlan_untagged(&sta->vlan_id) >= 0) {
vlan = hapd->conf->vlan;
+ struct hostapd_vlan *wildcard_vlan = NULL;
while (vlan) {
- if (vlan_cmp(&vlan->vlan_id, &sta->vlan_id) ||
- vlan_untagged(&vlan->vlan_id) == VLAN_ID_WILDCARD) {
+ if (vlan_cmp(&vlan->vlan_id, &sta->vlan_id)) {
iface = vlan->ifname;
break;
}
+ if (vlan_untagged(&vlan->vlan_id) == VLAN_ID_WILDCARD) {
+ wildcard_vlan = vlan;
+ }
vlan = vlan->next;
}
+ if (!vlan)
+ vlan = wildcard_vlan;
}
if (vlan_notempty(&sta->vlan_id) &&
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index b199615..20c9ff9 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -594,166 +594,210 @@ static int hapd_put_dynamic_iface(char *parent, char *ifname,
return 1;
}
-static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
+static void vlan_newlink_vlan(const int vlan_id, char *ifname, int *clean,
+ struct hostapd_data *hapd)
{
- char vlan_ifname[IFNAMSIZ];
- char br_name[IFNAMSIZ];
- struct hostapd_vlan *vlan = hapd->conf->vlan;
+ char vlan_ifname[IFNAMSIZ+1];
+ char br_name[IFNAMSIZ+1];
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
int vlan_naming = hapd->conf->ssid.vlan_naming;
int ret;
+ if (hapd->conf->vlan_bridge[0]) {
+ os_snprintf(br_name, sizeof(br_name), "%s%d",
+ hapd->conf->vlan_bridge, vlan_id);
+ } else if (tagged_interface) {
+ os_snprintf(br_name, sizeof(br_name), "br%s.%d",
+ tagged_interface, vlan_id);
+ } else {
+ os_snprintf(br_name, sizeof(br_name), "brvlan%d", vlan_id);
+ }
+
+ ret = br_addbr(br_name);
+ if (hapd_get_dynamic_iface(NULL, br_name, (ret == 0), hapd))
+ if (clean)
+ *clean |= DVLAN_CLEAN_BR;
+ 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, vlan_id);
+ else
+ os_snprintf(vlan_ifname, sizeof(vlan_ifname),
+ "vlan%d", vlan_id);
+
+ ifconfig_up(tagged_interface);
+ ret = vlan_add(tagged_interface, vlan_id, vlan_ifname);
+ if (hapd_get_dynamic_iface(NULL, vlan_ifname, (ret == 0), hapd))
+ if (clean)
+ *clean |= DVLAN_CLEAN_VLAN;
+ ifconfig_up(vlan_ifname);
+
+ ret = br_addif(br_name, vlan_ifname);
+ if (hapd_get_dynamic_iface(br_name, vlan_ifname, (ret == 0),
+ hapd))
+ if (clean)
+ *clean |= DVLAN_CLEAN_VLAN_PORT;
+ }
+
+ ifconfig_up(ifname);
+
+ ret = br_addif(br_name, ifname);
+ if (hapd_get_dynamic_iface(br_name, ifname, (ret == 0), hapd))
+ if (clean)
+ *clean |= DVLAN_CLEAN_WLAN_PORT;
+}
+
+static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
+{
+ struct hostapd_vlan *vlan;
+ char vlan_ifname[IFNAMSIZ+1];
+ int i, ret;
+
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
- while (vlan) {
- if (os_strcmp(ifname, vlan->ifname) == 0) {
-
- if (hapd->conf->vlan_bridge[0]) {
- os_snprintf(br_name, sizeof(br_name), "%s%d",
- hapd->conf->vlan_bridge,
- vlan_untagged(&vlan->vlan_id));
- } else if (tagged_interface) {
- os_snprintf(br_name, sizeof(br_name),
- "br%s.%d", tagged_interface,
- vlan_untagged(&vlan->vlan_id));
- } else {
- os_snprintf(br_name, sizeof(br_name),
- "brvlan%d",
- vlan_untagged(&vlan->vlan_id));
- }
+ for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
+ if (os_strcmp(ifname, vlan->ifname) != 0)
+ continue;
- ret = br_addbr(br_name);
- if (hapd_get_dynamic_iface(NULL, br_name, (ret == 0),
- hapd))
- vlan->clean |= DVLAN_CLEAN_BR;
-
- 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,
- vlan_untagged(
- &vlan->vlan_id));
- else
- os_snprintf(vlan_ifname,
- sizeof(vlan_ifname),
- "vlan%d",
- vlan_untagged(
- &vlan->vlan_id));
-
- ifconfig_up(tagged_interface);
- ret = vlan_add(tagged_interface,
- vlan_untagged(&vlan->vlan_id),
- vlan_ifname);
- if (hapd_get_dynamic_iface(NULL, vlan_ifname,
- (ret == 0), hapd))
- vlan->clean |= DVLAN_CLEAN_VLAN;
-
- ret = br_addif(br_name, vlan_ifname);
- if (hapd_get_dynamic_iface(br_name,
- vlan_ifname,
- (ret == 0), hapd))
- vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
-
- ifconfig_up(vlan_ifname);
- }
+ int untagged, num_tagged, *tagged;
+ num_tagged = vlan_tagged(&vlan->vlan_id, &tagged);
+ untagged = vlan_untagged(&vlan->vlan_id);
- ret = br_addif(br_name, ifname);
- if (hapd_get_dynamic_iface(br_name, ifname, (ret == 0),
- hapd))
- vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
+ if (!vlan->clean)
+ vlan->clean = os_zalloc((num_tagged + 1) *
+ sizeof(*(vlan->clean)));
+ if (untagged > 0) {
+ vlan_newlink_vlan(untagged, ifname, vlan->clean, hapd);
+ } else {
ifconfig_up(ifname);
-
- break;
}
- vlan = vlan->next;
+ for (i = 0; i < num_tagged; i++) {
+ const int tagged_vlan_id = tagged[i];
+ // add tagged interface on wlan
+ ret = os_snprintf(vlan_ifname, sizeof(vlan_ifname),
+ "%s.%d", ifname, tagged_vlan_id);
+ if (ret >= sizeof(vlan_ifname) || ret < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: length limit for "
+ "interfaces names reached.");
+ continue;
+ }
+ vlan_add(ifname, tagged_vlan_id, vlan_ifname);
+ // add this to bridge
+ int *clean = NULL;
+ if (vlan->clean)
+ clean = &(vlan->clean[i+1]);
+ vlan_newlink_vlan(tagged_vlan_id, vlan_ifname, clean,
+ hapd);
+ }
+ break;
}
}
-static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
+static void vlan_dellink_vlan(int vlan_id, char* ifname, int *clean,
+ struct hostapd_data *hapd)
{
- char vlan_ifname[IFNAMSIZ];
- char br_name[IFNAMSIZ];
- struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
+ char vlan_ifname[IFNAMSIZ+1];
+ char br_name[IFNAMSIZ+1];
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
int vlan_naming = hapd->conf->ssid.vlan_naming;
- wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
+ if (hapd->conf->vlan_bridge[0]) {
+ os_snprintf(br_name, sizeof(br_name), "%s%d",
+ hapd->conf->vlan_bridge, vlan_id);
+ } else if (tagged_interface) {
+ os_snprintf(br_name, sizeof(br_name), "br%s.%d",
+ tagged_interface, vlan_id);
+ } else {
+ os_snprintf(br_name, sizeof(br_name), "brvlan%d", vlan_id);
+ }
- first = prev = vlan;
+ if (clean && (*clean & DVLAN_CLEAN_WLAN_PORT) &&
+ hapd_put_dynamic_iface(br_name, ifname, hapd))
+ br_delif(br_name, ifname);
+
+ if (tagged_interface) {
+ if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
+ os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
+ tagged_interface, vlan_id);
+ else
+ os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d",
+ vlan_id);
+ if (clean && (*clean & DVLAN_CLEAN_VLAN_PORT) &&
+ hapd_put_dynamic_iface(br_name, vlan_ifname, hapd))
+ br_delif(br_name, vlan_ifname);
+
+ if (clean && (*clean & DVLAN_CLEAN_VLAN) &&
+ hapd_put_dynamic_iface(NULL, vlan_ifname, hapd)) {
+ ifconfig_down(vlan_ifname);
+ vlan_rem(vlan_ifname);
+ }
+ }
- while (vlan) {
- if (os_strcmp(ifname, vlan->ifname) == 0) {
- if (hapd->conf->vlan_bridge[0]) {
- os_snprintf(br_name, sizeof(br_name), "%s%d",
- hapd->conf->vlan_bridge,
- vlan_untagged(&vlan->vlan_id));
- } else if (tagged_interface) {
- os_snprintf(br_name, sizeof(br_name), "br%s.%d",
- tagged_interface,
- vlan_untagged(&vlan->vlan_id));
- } else {
- os_snprintf(br_name, sizeof(br_name),
- "brvlan%d",
- vlan_untagged(&vlan->vlan_id));
- }
+ if (clean && (*clean & DVLAN_CLEAN_BR) &&
+ hapd_put_dynamic_iface(NULL, br_name, hapd) &&
+ br_getnumports(br_name) == 0) {
+ ifconfig_down(br_name);
+ br_delbr(br_name);
+ }
- if ((vlan->clean & DVLAN_CLEAN_WLAN_PORT) &&
- hapd_put_dynamic_iface(br_name, vlan->ifname,
- hapd))
- 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,
- vlan_untagged(
- &vlan->vlan_id));
- else
- os_snprintf(vlan_ifname,
- sizeof(vlan_ifname),
- "vlan%d",
- vlan_untagged(
- &vlan->vlan_id));
- if ((vlan->clean & DVLAN_CLEAN_VLAN_PORT) &&
- hapd_put_dynamic_iface(br_name,
- vlan_ifname, hapd))
- br_delif(br_name, vlan_ifname);
- ifconfig_down(vlan_ifname);
-
- if ((vlan->clean & DVLAN_CLEAN_VLAN) &&
- hapd_put_dynamic_iface(NULL,
- vlan_ifname, hapd))
- vlan_rem(vlan_ifname);
- }
+ if (clean)
+ *clean = 0;
+}
- if ((vlan->clean & DVLAN_CLEAN_BR) &&
- hapd_put_dynamic_iface(NULL, br_name, hapd) &&
- br_getnumports(br_name) == 0) {
- ifconfig_down(br_name);
- br_delbr(br_name);
- }
+static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
+{
+ struct hostapd_vlan *first, *prev, *vlan;
+ char vlan_ifname[IFNAMSIZ];
+ int i, ret;
- if (vlan == first) {
- hapd->conf->vlan = vlan->next;
- } else {
- prev->next = vlan->next;
- }
+ wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
- vlan_free(&vlan->vlan_id);
- os_free(vlan);
+ for (first = prev = vlan = hapd->conf->vlan; vlan;
+ prev = vlan, vlan = vlan->next) {
+ if (os_strcmp(ifname, vlan->ifname) != 0)
+ continue;
- break;
+ int untagged = vlan_untagged(&vlan->vlan_id);
+ if (untagged > 0) {
+ vlan_dellink_vlan(untagged, ifname, vlan->clean, hapd);
}
- prev = vlan;
- vlan = vlan->next;
+
+ int num_tagged, *tagged;
+ num_tagged = vlan_tagged(&vlan->vlan_id, &tagged);
+ for (i = 0; i < num_tagged; i++) {
+ const int tagged_vlan_id = tagged[i];
+ // add tagged interface on wlan
+ ret = os_snprintf(vlan_ifname, sizeof(vlan_ifname),
+ "%s.%d", ifname, tagged_vlan_id);
+ if (ret >= sizeof(vlan_ifname) || ret < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: length limit for "
+ "interfaces names reached.");
+ continue;
+ }
+ int *clean = NULL;
+ if (vlan->clean)
+ clean = &(vlan->clean[i+1]);
+ vlan_dellink_vlan(tagged_vlan_id, vlan_ifname, clean,
+ hapd);
+ vlan_rem(vlan_ifname);
+ }
+ if (vlan == first) {
+ hapd->conf->vlan = vlan->next;
+ } else {
+ prev->next = vlan->next;
+ }
+
+ vlan_free(&vlan->vlan_id);
+ os_free(vlan->clean);
+ vlan->clean = NULL;
+
+ os_free(vlan);
+
+ break;
}
}
@@ -1038,12 +1082,14 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
struct hostapd_vlan *vlan,
vlan_t vlan_id)
{
- struct hostapd_vlan *n;
+ struct hostapd_vlan *n, *i, *prev;
char *ifname, *pos;
- if (vlan == NULL || vlan_untagged(&vlan_id) <= 0 ||
- vlan_untagged(&vlan_id) > MAX_VLAN_ID ||
- vlan_untagged(&vlan->vlan_id) != VLAN_ID_WILDCARD)
+ if (vlan == NULL
+ || vlan_untagged(&vlan_id) <= 0
+ || vlan_untagged(&vlan_id) > MAX_VLAN_ID
+ || !vlan_notempty(&vlan_id)
+ || vlan_untagged(&vlan->vlan_id) != VLAN_ID_WILDCARD)
return NULL;
wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%s ifname=%s)",
@@ -1067,8 +1113,34 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
vlan_alloc_copy(&n->vlan_id, &vlan_id);
n->dynamic_vlan = 1;
+ /* artifical id := untagged vlan id (if no tagged vlan id given)
+ * := MAX_VLAN_ID + seq (if tagged vlan is set)
+ */
+ int artifical_id = vlan_untagged(&vlan_id);
+ int num_tagged, *tagged;
+ num_tagged = vlan_tagged(&vlan_id, &tagged);
+ if (num_tagged > 0) {
+ /* get free artifical id, start searching at 4096 */
+ artifical_id = MAX_VLAN_ID + 2;
+ prev = NULL;
+ for (i = hapd->conf->vlan;
+ i && i->artifical_id <= artifical_id;
+ i = i->next) {
+ if ( artifical_id == i->artifical_id )
+ artifical_id++;
+ prev = i;
+ }
+ } else {
+ prev = NULL;
+ for (i = hapd->conf->vlan;
+ i && i->artifical_id <= artifical_id;
+ i = i->next) {
+ prev = i;
+ }
+ }
+ n->artifical_id = artifical_id;
os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname,
- vlan_untagged(&vlan_id), pos);
+ artifical_id, pos);
os_free(ifname);
if (hostapd_vlan_if_add(hapd, n->ifname)) {
@@ -1076,8 +1148,14 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
return NULL;
}
- n->next = hapd->conf->vlan;
- hapd->conf->vlan = n;
+ /* insert into list */
+ if (!prev) {
+ n->next = hapd->conf->vlan;
+ hapd->conf->vlan = n;
+ } else {
+ n->next = prev->next;
+ prev->next = n;
+ }
#ifdef CONFIG_FULL_DYNAMIC_VLAN
ifconfig_up(n->ifname);
More information about the Hostap
mailing list