From 2025cad9b8af457051db0e7171ad48fb8b55843c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 2 Aug 2013 00:37:48 +0300 Subject: [PATCH] WNM: Move ESS Disassoc Imminent sending to a helper function This makes it easier to trigger the ESS Disassociation Imminent operation from different sources. Signed-hostap: Jouni Malinen --- hostapd/ctrl_iface.c | 83 +++++++--------------------------------------------- src/ap/wnm_ap.c | 74 +++++++++++++++++++++++++++++++++++++++++++++- src/ap/wnm_ap.h | 6 +++- 3 files changed, 89 insertions(+), 74 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 427c054..6d82cd8 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -29,6 +29,7 @@ #include "ap/wps_hostapd.h" #include "ap/ctrl_iface_ap.h" #include "ap/ap_drv_ops.h" +#include "ap/wnm_ap.h" #include "ap/wpa_auth.h" #include "wps/wps_defs.h" #include "wps/wps.h" @@ -708,14 +709,20 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, { u8 addr[ETH_ALEN]; const char *url, *timerstr; - u8 buf[1000], *pos; - struct ieee80211_mgmt *mgmt; - size_t url_len; int disassoc_timer; + struct sta_info *sta; if (hwaddr_aton(cmd, addr)) return -1; + sta = ap_get_sta(hapd, addr); + if (sta == NULL) { + wpa_printf(MSG_DEBUG, "Station " MACSTR + " not found for ESS disassociation imminent message", + MAC2STR(addr)); + return -1; + } + timerstr = cmd + 17; if (*timerstr != ' ') return -1; @@ -728,76 +735,8 @@ static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd, if (url == NULL) return -1; url++; - url_len = os_strlen(url); - if (url_len > 255) - return -1; - - os_memset(buf, 0, sizeof(buf)); - mgmt = (struct ieee80211_mgmt *) buf; - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(mgmt->da, addr, ETH_ALEN); - os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); - mgmt->u.action.category = WLAN_ACTION_WNM; - mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; - mgmt->u.action.u.bss_tm_req.dialog_token = 1; - mgmt->u.action.u.bss_tm_req.req_mode = - WNM_BSS_TM_REQ_DISASSOC_IMMINENT | - WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; - mgmt->u.action.u.bss_tm_req.disassoc_timer = - host_to_le16(disassoc_timer); - mgmt->u.action.u.bss_tm_req.validity_interval = 0x01; - - pos = mgmt->u.action.u.bss_tm_req.variable; - - /* Session Information URL */ - *pos++ = url_len; - os_memcpy(pos, url, url_len); - pos += url_len; - if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) { - wpa_printf(MSG_DEBUG, "Failed to send BSS Transition " - "Management Request frame"); - return -1; - } - - /* send disassociation frame after time-out */ - if (disassoc_timer) { - struct sta_info *sta; - int timeout, beacon_int; - - /* - * Prevent STA from reconnecting using cached PMKSA to force - * full authentication with the authentication server (which may - * decide to reject the connection), - */ - wpa_auth_pmksa_remove(hapd->wpa_auth, addr); - - sta = ap_get_sta(hapd, addr); - if (sta == NULL) { - wpa_printf(MSG_DEBUG, "Station " MACSTR " not found " - "for ESS disassociation imminent message", - MAC2STR(addr)); - return -1; - } - - beacon_int = hapd->iconf->beacon_int; - if (beacon_int < 1) - beacon_int = 100; /* best guess */ - /* Calculate timeout in ms based on beacon_int in TU */ - timeout = disassoc_timer * beacon_int * 128 / 125; - wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR - " set to %d ms", MAC2STR(addr), timeout); - - sta->timeout_next = STA_DISASSOC_FROM_CLI; - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(timeout / 1000, - timeout % 1000 * 1000, - ap_handle_timer, hapd, sta); - } - - return 0; + return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer); } #endif /* CONFIG_WNM */ diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 225fe02..9d4363a 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -1,6 +1,6 @@ /* * hostapd - WNM - * Copyright (c) 2011-2012, Qualcomm Atheros, Inc. + * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -9,6 +9,7 @@ #include "utils/includes.h" #include "utils/common.h" +#include "utils/eloop.h" #include "common/ieee802_11_defs.h" #include "ap/hostapd.h" #include "ap/sta_info.h" @@ -390,3 +391,74 @@ int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd, action->data[0], MAC2STR(action->sa)); return -1; } + + +int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd, + struct sta_info *sta, const char *url, + int disassoc_timer) +{ + u8 buf[1000], *pos; + struct ieee80211_mgmt *mgmt; + size_t url_len; + + os_memset(buf, 0, sizeof(buf)); + mgmt = (struct ieee80211_mgmt *) buf; + mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(mgmt->da, sta->addr, ETH_ALEN); + os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); + mgmt->u.action.category = WLAN_ACTION_WNM; + mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ; + mgmt->u.action.u.bss_tm_req.dialog_token = 1; + mgmt->u.action.u.bss_tm_req.req_mode = + WNM_BSS_TM_REQ_DISASSOC_IMMINENT | + WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT; + mgmt->u.action.u.bss_tm_req.disassoc_timer = + host_to_le16(disassoc_timer); + mgmt->u.action.u.bss_tm_req.validity_interval = 0x01; + + pos = mgmt->u.action.u.bss_tm_req.variable; + + /* Session Information URL */ + url_len = os_strlen(url); + if (url_len > 255) + return -1; + *pos++ = url_len; + os_memcpy(pos, url, url_len); + pos += url_len; + + if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) { + wpa_printf(MSG_DEBUG, "Failed to send BSS Transition " + "Management Request frame"); + return -1; + } + + /* send disassociation frame after time-out */ + if (disassoc_timer) { + int timeout, beacon_int; + + /* + * Prevent STA from reconnecting using cached PMKSA to force + * full authentication with the authentication server (which may + * decide to reject the connection), + */ + wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr); + + beacon_int = hapd->iconf->beacon_int; + if (beacon_int < 1) + beacon_int = 100; /* best guess */ + /* Calculate timeout in ms based on beacon_int in TU */ + timeout = disassoc_timer * beacon_int * 128 / 125; + wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR + " set to %d ms", MAC2STR(sta->addr), timeout); + + sta->timeout_next = STA_DISASSOC_FROM_CLI; + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(timeout / 1000, + timeout % 1000 * 1000, + ap_handle_timer, hapd, sta); + } + + return 0; +} diff --git a/src/ap/wnm_ap.h b/src/ap/wnm_ap.h index f05726e..3ed0c56 100644 --- a/src/ap/wnm_ap.h +++ b/src/ap/wnm_ap.h @@ -1,6 +1,6 @@ /* * IEEE 802.11v WNM related functions and structures - * Copyright (c) 2011-2012, Qualcomm Atheros, Inc. + * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -10,8 +10,12 @@ #define WNM_AP_H struct rx_action; +struct sta_info; int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd, struct rx_action *action); +int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd, + struct sta_info *sta, const char *url, + int disassoc_timer); #endif /* WNM_AP_H */ -- 2.1.4