From patchwork Fri May 17 17:02:15 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: michael-dev X-Patchwork-Id: 249373 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "maxx.shmoo.com", Issuer "CA Cert Signing Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id B850F2C0096 for ; Thu, 6 Jun 2013 20:14:15 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 9854F17C04C; Thu, 6 Jun 2013 06:12:59 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id I8k-9rgW6dnU; Thu, 6 Jun 2013 06:12:59 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 2D91A9C234; Thu, 6 Jun 2013 06:09:51 -0400 (EDT) X-Original-To: mailman-post+hostap@maxx.shmoo.com Delivered-To: mailman-post+hostap@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id DEE3C9C230 for ; Thu, 6 Jun 2013 06:09:49 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ffpd4n13pepg for ; Thu, 6 Jun 2013 06:09:44 -0400 (EDT) Received: from mail.fem.tu-ilmenau.de (mail.fem.tu-ilmenau.de [141.24.101.79]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 41DC09C13D for ; Thu, 6 Jun 2013 06:09:11 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by mail.fem.tu-ilmenau.de (Postfix) with ESMTP id 10AEA654F for ; Thu, 6 Jun 2013 12:09:11 +0200 (CEST) X-Virus-Scanned: amavisd-new at fem.tu-ilmenau.de Received: from mail.fem.tu-ilmenau.de ([127.0.0.1]) by localhost (mail.fem.tu-ilmenau.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zo8xl7EsayfC; Thu, 6 Jun 2013 12:09:10 +0200 (CEST) Received: from a234.fem.tu-ilmenau.de (unknown [10.42.51.234]) by mail.fem.tu-ilmenau.de (Postfix) with ESMTP; Thu, 6 Jun 2013 12:09:08 +0200 (CEST) Received: by a234.fem.tu-ilmenau.de (Postfix, from userid 0) id 4548720A676; Thu, 6 Jun 2013 12:09:07 +0200 (CEST) Message-Id: <3d6684a2de9569254f9187668d3a7f45bae1360a.1370512966.git.michael-dev@fami-braun.de> In-Reply-To: References: From: Michael Braun Date: Fri, 17 May 2013 19:02:15 +0200 Subject: [PATCHv2 16/21] Fix STA dynamic vlan tracking To: hostap@lists.shmoo.com MIME-Version: 1.0 Cc: projekt-wlan@fem.tu-ilmenau.de X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.11 Precedence: list Reply-To: projekt-wlan@fem.tu-ilmenau.de List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com When an STA is authenticated, it gets moved to appropiate (dynamic) vlan using ap_sta_bind_vlan. Though, it is not removed when the station disconnects - even if the struct sta_info is freed. This results in dynamic interfaces not being removed. Solution: The struct sta_info tracks the dynamic vlans the station has been assigned. This information can be used to release the VLAN the STA has been added to it before. Signed-hostap: Michael Braun diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 1492a43..f1c198c 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -1470,7 +1470,6 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0) break; - vlan_free(&old_vlanid); /* RFC 3580, Ch. 3.17 */ if (session_timeout_set && termination_action == @@ -1525,6 +1524,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, sm->eap_if->aaaEapReq = FALSE; eapol_auth_step(sm); + vlan_free(&old_vlanid); return RADIUS_RX_QUEUED; } diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index efed3c8..3950839 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -119,6 +119,22 @@ static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta) } +/** + * This method marks the STA as not being assigned to any VLAN currently. + * It may only be called if the STA is not assigned to its VLAN interface + * in kernel! + * It is used before freeing the sta data structure to release + * tehe vlan_id_bound VLAN pointer. + */ +void ap_unbind_sta_vlan(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (vlan_notempty(&sta->vlan_id_bound) && + vlan_untagged(&sta->vlan_id_bound) >= 0) + vlan_remove_dynamic(hapd, sta->vlan_id_bound); + vlan_free(&sta->vlan_id_bound); +} + + void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) { int set_beacon = 0; @@ -247,6 +263,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) #endif /* CONFIG_SAE */ vlan_free(&sta->vlan_id); + ap_unbind_sta_vlan(hapd, sta); os_free(sta); } @@ -662,12 +679,18 @@ int ap_sta_wps_cancel(struct hostapd_data *hapd, #endif /* CONFIG_WPS */ +/** + * Moves the STA to its VLAN. + * @param old_vlanid Used to check if anything has changed. Might differ from + * sta->bound_vlanid as tracking in hostapd is not exact. + */ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, vlan_t old_vlanid) { #ifndef CONFIG_NO_VLAN const char *iface; struct hostapd_vlan *vlan = NULL; + int boundVLANchanged; int ret; /* @@ -681,8 +704,9 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, * During 1x reauth, if the vlan id changes, then remove the old id and * proceed furthur to add the new one. */ - if (vlan_notempty(&old_vlanid) && vlan_untagged(&old_vlanid) >= 0) - vlan_remove_dynamic(hapd, old_vlanid); + boundVLANchanged = !vlan_cmp(&sta->vlan_id, &sta->vlan_id_bound); + if (boundVLANchanged) + ap_unbind_sta_vlan(hapd, sta); iface = hapd->conf->iface; if (sta->ssid->vlan[0]) @@ -743,7 +767,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, "interface '%s'", iface); } else if (vlan && vlan_cmp(&vlan->vlan_id, &sta->vlan_id)) { if (vlan_notempty(&sta->vlan_id) && - vlan_untagged(&sta->vlan_id) >= 0) { + vlan_untagged(&sta->vlan_id) >= 0 && + boundVLANchanged) { vlan->dynamic_vlan++; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, @@ -771,6 +796,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, HOSTAPD_LEVEL_DEBUG, "binding station to interface " "'%s'", iface); + if (boundVLANchanged) + vlan_alloc_copy(&sta->vlan_id_bound, &sta->vlan_id); if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index c2d1525..ac25d9b 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -97,7 +97,10 @@ struct sta_info { struct hostapd_ssid *ssid; /* SSID selection based on (Re)AssocReq */ struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */ + /* VLAN-ID given by auth or acl */ vlan_t vlan_id; + /* VLAN ID currently in use (as counted with vlan->dynamic_vlan) */ + vlan_t vlan_id_bound; /* PSKs from RADIUS authentication server */ struct hostapd_sta_wpa_psk_short *psk; @@ -177,6 +180,7 @@ int ap_sta_wps_cancel(struct hostapd_data *hapd, #endif /* CONFIG_WPS */ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, vlan_t old_vlanid); +void ap_unbind_sta_vlan(struct hostapd_data *hapd, struct sta_info *sta); void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);