[PATCH v4 16/25] VLAN: add tagged vlan to vlan data structure
Michael Braun
michael-dev
Sat Jul 27 12:55:47 PDT 2013
Signed-hostap: Michael Braun <michael-dev at fami-braun.de>
---
hostapd/config_file.c | 6 +
src/ap/ap_config.h | 1
src/ap/ieee802_11.c | 8 +-
src/ap/ieee802_11_auth.c | 3 -
src/ap/ieee802_1x.c | 6 +
src/ap/sta_info.c | 19 ++--
src/ap/vlan_init.c | 13 +--
src/ap/wpa_auth.c | 19 ++--
src/ap/wpa_auth_ie.c | 4 -
src/common/vlan.h | 181 ++++++++++++++++++++++++++++++++++++++++++
src/drivers/driver_nl80211.c | 4 -
src/drivers/driver_test.c | 4 -
12 files changed, 222 insertions(+), 46 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 45a2cb9..165bc96 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -58,7 +58,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
continue;
if (buf[0] == '*') {
- vlan_alloc(&vlan_id, VLAN_ID_WILDCARD);
+ vlan_alloc(&vlan_id, VLAN_ID_WILDCARD, 0, NULL);
pos = buf + 1;
} else {
int untagged_vlan_id = strtol(buf, &pos, 10);
@@ -69,7 +69,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
fclose(f);
return -1;
}
- vlan_alloc(&vlan_id, untagged_vlan_id);
+ vlan_alloc(&vlan_id, untagged_vlan_id, 0, NULL);
}
while (*pos == ' ' || *pos == '\t')
@@ -164,7 +164,7 @@ static int hostapd_config_read_maclist(const char *fname,
while (*pos == ' ' || *pos == '\t')
pos++;
if (*pos != '\0')
- vlan_alloc(&vlan_id, atoi(pos));
+ vlan_alloc(&vlan_id, atoi(pos), 0, NULL);
newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
if (newacl == NULL) {
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 1e46f69..c450219 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -17,7 +17,6 @@
#include "wps/wps.h"
#define MAX_STA_COUNT 2007
-#define MAX_VLAN_ID 4094
typedef u8 macaddr[ETH_ALEN];
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 88f24ec..01f2a04 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -653,15 +653,15 @@ static void handle_auth(struct hostapd_data *hapd,
if (!hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
- "%d received from RADIUS server",
- vlan_untagged(&vlan_id));
+ "%s received from RADIUS server",
+ vlan2str(&vlan_id));
resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto fail;
}
vlan_alloc_copy(&sta->vlan_id, &vlan_id);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_INFO, "VLAN ID %d",
- vlan_untagged(&sta->vlan_id));
+ HOSTAPD_LEVEL_INFO, "VLAN ID %s",
+ vlan2str(&sta->vlan_id));
}
vlan_free(&vlan_id);
diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
index 604b54a..9d077eb 100644
--- a/src/ap/ieee802_11_auth.c
+++ b/src/ap/ieee802_11_auth.c
@@ -540,7 +540,8 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
cache->acct_interim_interval = 0;
}
- vlan_alloc(&cache->vlan_id, radius_msg_get_vlanid(msg));
+ vlan_alloc(&cache->vlan_id, radius_msg_get_vlanid(msg), 0,
+ NULL);
decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
msg, req, cache);
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 38c5b08..ce8700f 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1334,7 +1334,8 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
#ifndef CONFIG_NO_VLAN
else {
vlan_alloc_copy(&old_vlanid, &sta->vlan_id);
- vlan_alloc(&sta->vlan_id, radius_msg_get_vlanid(msg));
+ vlan_alloc(&sta->vlan_id, radius_msg_get_vlanid(msg),
+ 0, NULL);
}
if (vlan_notempty(&sta->vlan_id) &&
vlan_untagged(&sta->vlan_id) > 0 &&
@@ -1342,8 +1343,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
- "VLAN ID %d",
- vlan_untagged(&sta->vlan_id));
+ "VLAN ID %s", vlan2str(&sta->vlan_id));
} else if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_REQUIRED) {
sta->eapol_sm->authFail = TRUE;
hostapd_logger(hapd, sta->addr,
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 1082a3a..d3d9349 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -711,8 +711,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
vlan_untagged(&sta->vlan_id) >= 0 && vlan == NULL) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
- "binding station to (vlan_id=%d)",
- vlan_untagged(&sta->vlan_id));
+ "binding station to (vlan_id=%s)",
+ vlan2str(&sta->vlan_id));
return -1;
} else if (vlan_notempty(&sta->vlan_id) &&
vlan_untagged(&sta->vlan_id) >= 0 &&
@@ -722,8 +722,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not add "
- "dynamic VLAN interface for vlan_id=%d",
- vlan_untagged(&sta->vlan_id));
+ "dynamic VLAN interface for vlan_id=%s",
+ vlan2str(&sta->vlan_id));
return -1;
}
@@ -733,8 +733,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not "
"configure encryption for dynamic VLAN "
- "interface for vlan_id=%d",
- vlan_untagged(&sta->vlan_id));
+ "interface for vlan_id=%s",
+ vlan2str(&sta->vlan_id));
}
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
@@ -761,8 +761,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not "
"configure encryption for VLAN "
- "interface for vlan_id=%d",
- vlan_untagged(&sta->vlan_id));
+ "interface for vlan_id=%s",
+ vlan2str(&sta->vlan_id));
}
}
@@ -777,8 +777,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
if (ret < 0) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not bind the STA "
- "entry to vlan_id=%d",
- vlan_untagged(&sta->vlan_id));
+ "entry to vlan_id=%s", vlan2str(&sta->vlan_id));
}
return ret;
#else /* CONFIG_NO_VLAN */
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index a501a25..3b024fa 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -1012,7 +1012,7 @@ int vlan_init(struct hostapd_data *hapd)
return -1;
}
- vlan_alloc(&vlan->vlan_id, VLAN_ID_WILDCARD);
+ vlan_alloc(&vlan->vlan_id, VLAN_ID_WILDCARD, 0, NULL);
os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
hapd->conf->iface);
vlan->next = hapd->conf->vlan;
@@ -1048,8 +1048,8 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
vlan_untagged(&vlan->vlan_id) != VLAN_ID_WILDCARD)
return NULL;
- wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
- __func__, vlan_untagged(&vlan_id), vlan->ifname);
+ wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%s ifname=%s)",
+ __func__, vlan2str(&vlan_id), vlan->ifname);
ifname = os_strdup(vlan->ifname);
if (ifname == NULL)
return NULL;
@@ -1093,12 +1093,11 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, vlan_t vlan_id)
{
struct hostapd_vlan *vlan;
- if (vlan_untagged(&vlan_id) <= 0 ||
- vlan_untagged(&vlan_id) > MAX_VLAN_ID)
+ if (vlan_untagged(&vlan->vlan_id) == VLAN_ID_WILDCARD)
return 1;
- wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__,
- vlan_untagged(&vlan_id));
+ wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%s)", __func__,
+ vlan2str(&vlan_id));
vlan = hapd->conf->vlan;
while (vlan) {
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index eca8c1e..3b44912 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -2397,7 +2397,7 @@ static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
- "GTK_INIT (VLAN-ID %d)", vlan_untagged(&group->vlan_id));
+ "GTK_INIT (VLAN-ID %s)", vlan2str(&group->vlan_id));
group->changed = FALSE; /* GInit is not cleared here; avoid loop */
group->wpa_group_state = WPA_GROUP_GTK_INIT;
@@ -2534,7 +2534,7 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
int tmp;
wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
- "SETKEYS (VLAN-ID %d)", vlan_untagged(&group->vlan_id));
+ "SETKEYS (VLAN-ID %s)", vlan2str(&group->vlan_id));
group->changed = TRUE;
group->wpa_group_state = WPA_GROUP_SETKEYS;
group->GTKReKey = FALSE;
@@ -2591,7 +2591,7 @@ static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
wpa_printf(MSG_DEBUG, "WPA: group state machine entering state "
- "SETKEYSDONE (VLAN-ID %d)", vlan_untagged(&group->vlan_id));
+ "SETKEYSDONE (VLAN-ID %s)", vlan2str(&group->vlan_id));
group->changed = TRUE;
group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
@@ -2982,13 +2982,14 @@ static void wpa_group_free(void *eloop_ctx, void *timeout_ctx)
struct wpa_group *group = timeout_ctx;
struct wpa_group *prev = wpa_auth->group;
- wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
- vlan_untagged(&group->vlan_id));
+ wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %s",
+ vlan2str(&group->vlan_id));
while (prev) {
if (prev->next == group) {
/* This never frees the special first group as needed */
prev->next = group->next;
+ vlan_free(&group->vlan_id);
os_free(group);
break;
}
@@ -3037,8 +3038,8 @@ wpa_auth_add_group(struct wpa_authenticator *wpa_auth, vlan_t vlan_id)
if (wpa_auth == NULL || wpa_auth->group == NULL)
return NULL;
- wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d",
- vlan_untagged(&vlan_id));
+ wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %s",
+ vlan2str(&vlan_id));
group = wpa_group_init(wpa_auth, vlan_id, 0);
if (group == NULL)
return NULL;
@@ -3074,8 +3075,8 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, vlan_t vlan_id)
return 0;
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
- "machine for VLAN ID %d", MAC2STR(sm->addr),
- vlan_untagged(&vlan_id));
+ "machine for VLAN ID %s", MAC2STR(sm->addr),
+ vlan2str(&vlan_id));
wpa_group_put(sm->wpa_auth, sm->group);
sm->group = group;
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index b0aa98a..d103881 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -607,9 +607,9 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
if (sm->pmksa) {
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
"PMKID found from PMKSA cache "
- "eap_type=%d vlan_id=%d",
+ "eap_type=%d vlan_id=%s",
sm->pmksa->eap_type_authsrv,
- vlan_untagged(&sm->pmksa->vlan_id));
+ vlan2str(&sm->pmksa->vlan_id));
os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
}
diff --git a/src/common/vlan.h b/src/common/vlan.h
index 9982d46..79dc14e 100644
--- a/src/common/vlan.h
+++ b/src/common/vlan.h
@@ -9,10 +9,169 @@
#ifndef HOSTAPD_VLAN_H
#define HOSTAPD_VLAN_H
+#ifdef DEBUG_VLAN_FREE
+#include <signal.h>
+#endif /* DEBUG_VLAN_FREE */
+
+#define MAX_VLAN_ID 4094
+
+#ifdef CONFIG_VLAN_TAGGED
+#define VLAN_NULL (struct vlan_description) {0}
+
+struct vlan_description {
+ int untagged;
+ unsigned int num_tagged;
+ int* tagged;
+ unsigned int* references;
+#ifdef DEBUG_VLAN_FREE
+ /* enforce that copies cannot be freed by error */
+ struct vlan_description *self;
+#endif /* DEBUG_VLAN_FREE */
+};
+typedef struct vlan_description vlan_t;
+
+static inline void vlan_free(vlan_t *dst)
+{
+#ifdef DEBUG_VLAN_FREE
+ /* check that the vlan_t instance was not moved around ! */
+ if (dst->self != NULL && dst->self != dst)
+ raise(SIGILL);
+ dst->self = NULL;
+#endif /* DEBUG_VLAN_FREE */
+ /* end */
+ dst->untagged = 0;
+ if (dst->num_tagged == 0)
+ return;
+ dst->references--;
+ if (dst->references == 0) {
+ os_free(dst->tagged);
+ os_free(dst->references);
+ }
+ dst->tagged = NULL;
+ dst->num_tagged = 0;
+ dst->references = NULL;
+}
+
+static int cmp_int(const void *a, const void *b)
+{
+ const int *ia = (const int *) a;
+ const int *ib = (const int *) b;
+ return (*ia > *ib) - (*ia < *ib);
+}
+
+static inline void vlan_alloc(vlan_t *dst, const int untagged,
+ const unsigned int num_tagged, const int* tagged)
+{
+ int i, offset=0;
+
+ vlan_free(dst);
+
+ dst->untagged = untagged;
+ dst->num_tagged = num_tagged;
+#ifdef DEBUG_VLAN_FREE
+ dst->self = dst;
+#endif /* DEBUG_VLAN_FREE */
+ if (dst->num_tagged == 0)
+ return;
+ dst->references = os_zalloc(sizeof(dst->references));
+ dst->tagged = os_zalloc(sizeof(*dst->tagged) * num_tagged);
+ if (!dst->tagged || !dst->references) {
+ dst->num_tagged = 0;
+ return;
+ }
+ os_memcpy(dst->tagged, tagged, sizeof(*dst->tagged) * num_tagged);
+ (*dst->references)++;
+
+ qsort(dst->tagged, dst->num_tagged, sizeof(int), cmp_int);
+ for (i=1; i < dst->num_tagged; i++) {
+ if (dst->tagged[i-1-offset] == dst->tagged[i])
+ offset++;
+ else if (dst->tagged[i] <= 0 || dst->tagged[i] > MAX_VLAN_ID)
+ offset++;
+ else if (offset > 0)
+ dst->tagged[i-offset] = dst->tagged[i];
+ }
+ dst->num_tagged -= offset;
+}
+
+static inline void vlan_alloc_copy(vlan_t *dst, const vlan_t *src)
+{
+ vlan_free(dst);
+ dst->untagged = src->untagged;
+ dst->num_tagged = src->num_tagged;
+#ifdef DEBUG_VLAN_FREE
+ dst->self = dst;
+#endif /* DEBUG_VLAN_FREE */
+ if (dst->num_tagged == 0)
+ return;
+ dst->references = src->references;
+ dst->tagged = src->tagged;
+ (*dst->references)++;
+}
+
+static inline int vlan_cmp(const vlan_t *a, const vlan_t *b)
+{
+ int i;
+ if (!a && !b)
+ return 1;
+ if (!a || !b)
+ return 0;
+ if (a->untagged != b->untagged)
+ return 0;
+ if (a->num_tagged != b->num_tagged)
+ return 0;
+ for (i=0; i < a->num_tagged; i++)
+ if (a->tagged[i] != b->tagged[i]) return 0;
+ return 1;
+}
+
+static inline int vlan_untagged(const vlan_t *a)
+{
+ if (!a)
+ return 0;
+ return a->untagged;
+}
+
+static inline int vlan_tagged(const vlan_t *a, int **tagged)
+{
+ if (tagged)
+ *tagged = NULL;
+ if (!a)
+ return 0;
+ if (tagged)
+ *tagged = a->tagged;
+ return a->num_tagged;
+}
+
+static inline int vlan_notempty(const vlan_t *a)
+{
+ if (!a)
+ return 0;
+ return a->untagged || a->num_tagged;
+}
+
+static inline char* vlan2str(const vlan_t *a)
+{
+ if (!a)
+ return "";
+ static char buf[6 * 4096];
+ int i;
+ char *pos = buf;
+ pos += os_snprintf(pos, sizeof(buf) + buf - pos, "u%d", a->untagged);
+ for (i=0; i < a->num_tagged; i++) {
+ pos += os_snprintf(pos, sizeof(buf) + buf - pos, "t%d",
+ a->tagged[i]);
+ }
+ return buf;
+}
+
+#else /* CONFIG_VLAN_TAGGED */
+
#define VLAN_NULL 0
typedef int vlan_t;
-static inline void vlan_alloc(vlan_t *dst, const int untagged)
+static inline void vlan_alloc(vlan_t *dst, const int untagged,
+ const unsigned int num_tagged, const int* tagged)
{
*dst = untagged;
}
@@ -43,6 +202,13 @@ static inline int vlan_untagged(const vlan_t *a)
return *a;
}
+static inline int vlan_tagged(const vlan_t *a, int **tagged)
+{
+ if (tagged)
+ *tagged = NULL;
+ return 0;
+}
+
static inline int vlan_notempty(const vlan_t *a)
{
if (!a)
@@ -50,4 +216,15 @@ static inline int vlan_notempty(const vlan_t *a)
return *a;
}
-#endif
+static inline char* vlan2str(vlan_t *a)
+{
+ if (!a)
+ return "";
+ static char buf[5];
+ snprintf(buf, sizeof(buf), "%d", *a);
+ return buf;
+}
+
+#endif /* CONFIG_VLAN_TAGGED */
+
+#endif /* HOSTAPD_VLAN_H */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index aa4310b..829772e 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -8536,8 +8536,8 @@ static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,
msg = NULL;
if (ret < 0) {
wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
- MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
- MAC2STR(addr), ifname, vlan_untagged(&vlan_id), ret,
+ MACSTR " ifname=%s vlan_id=%s) failed: %d (%s)",
+ MAC2STR(addr), ifname, vlan2str(&vlan_id), ret,
strerror(-ret));
}
nla_put_failure:
diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c
index e19845f..bca109a 100644
--- a/src/drivers/driver_test.c
+++ b/src/drivers/driver_test.c
@@ -1129,8 +1129,8 @@ static int test_driver_set_privacy(void *priv, int enabled)
static int test_driver_set_sta_vlan(void *priv, const u8 *addr,
const char *ifname, vlan_t vlan_id)
{
- wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " ifname=%s vlan_id=%d)",
- __func__, MAC2STR(addr), ifname, vlan_untagged(&vlan_id));
+ wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " ifname=%s vlan_id=%s)",
+ __func__, MAC2STR(addr), ifname, vlan2str(&vlan_id));
return 0;
}
More information about the Hostap
mailing list