Patchwork [PATCHv2,05/21] Remove WPA per-VLAN groups when all stations left on rekeying

login
register
mail settings
Submitter michael-dev@fami-braun.de
Date May 16, 2013, 11:23 p.m.
Message ID <0f82cfad3073d0214df89198c1493508f577af37.1370512966.git.michael-dev@fami-braun.de>
Download mbox | patch
Permalink /patch/249366/
State Changes Requested
Headers show

Comments

michael-dev@fami-braun.de - May 16, 2013, 11:23 p.m.
This adds a references counter to struct wpa_group and frees
a group if it is unused during rekeying.

This is useful when extending the number of VLANs supported.

Signed-hostap: Michael Braun <michael-dev@fami-braun.de>
Jouni Malinen - June 25, 2013, 9:10 a.m.
On Fri, May 17, 2013 at 01:23:02AM +0200, Michael Braun wrote:
> This adds a references counter to struct wpa_group and frees
> a group if it is unused during rekeying.
> 
> This is useful when extending the number of VLANs supported.

> diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
> @@ -234,15 +242,26 @@ static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
>  static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)

> +		if (group->references == 0 && prev) {
> +			/* this does never delete the special first group */
> +			prev->next = group->next;
> +			wpa_group_free(group);
> +			group = prev->next;

Why would this be in wpa_rekey_gtk() instead of wpa_free_sta_sm() and
wpa_auth_sta_set_vlan() that are the only places where the references
counter is decremented?

Patch

diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 83cc857..f08ded8 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -211,6 +211,14 @@  static int wpa_use_aes_cmac(struct wpa_state_machine *sm)
 }
 
 
+static void wpa_group_free(struct wpa_group *group)
+{
+	wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
+		   group->vlan_id);
+	os_free(group);
+}
+
+
 static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_authenticator *wpa_auth = eloop_ctx;
@@ -234,15 +242,26 @@  static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
 static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_authenticator *wpa_auth = eloop_ctx;
-	struct wpa_group *group;
+	struct wpa_group *group, *prev;
 
 	wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
-	for (group = wpa_auth->group; group; group = group->next) {
+	group = wpa_auth->group;
+	prev = NULL;
+	while (group) {
 		group->GTKReKey = TRUE;
 		do {
 			group->changed = FALSE;
 			wpa_group_sm_step(wpa_auth, group);
 		} while (group->changed);
+		if (group->references == 0 && prev) {
+			/* this does never delete the special first group */
+			prev->next = group->next;
+			wpa_group_free(group);
+			group = prev->next;
+		} else {
+			prev = group;
+			group = group->next;
+		}
 	}
 
 	if (wpa_auth->conf.wpa_group_rekey) {
@@ -519,6 +538,7 @@  wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr)
 
 	sm->wpa_auth = wpa_auth;
 	sm->group = wpa_auth->group;
+	sm->group->references++;
 
 	return sm;
 }
@@ -581,6 +601,7 @@  static void wpa_free_sta_sm(struct wpa_state_machine *sm)
 #endif /* CONFIG_IEEE80211R */
 	os_free(sm->last_rx_eapol_key);
 	os_free(sm->wpa_ie);
+	sm->group->references--;
 	os_free(sm);
 }
 
@@ -3007,7 +3028,10 @@  int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
 	wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
 		   "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
 
+	sm->group->references--;
 	sm->group = group;
+	sm->group->references++;
+
 	return 0;
 }
 
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 97489d3..8fbd4ff 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -151,6 +151,8 @@  struct wpa_group {
 	u8 IGTK[2][WPA_IGTK_LEN];
 	int GN_igtk, GM_igtk;
 #endif /* CONFIG_IEEE80211W */
+	/* number of references except those in struct wpa_group->next */
+	unsigned int references;
 };