WNM: Add advertisement of BSS max idle period

If WNM is enabled for the build (CONFIG_WNM=y), add BSS max idle period
information to the (Re)Association Response frame from the AP and parse
this information on the station. For SME-in-wpa_supplicant case, add a
timer to handle periodic transmission of the keep-alive frame. The
actual request for the driver to transmit a frame is not yet
implemented.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2012-05-27 17:35:00 -07:00
parent b80eb89d8e
commit b6668734ab
13 changed files with 143 additions and 2 deletions

View file

@ -722,6 +722,10 @@ ifdef CONFIG_IEEE80211N
CFLAGS += -DCONFIG_IEEE80211N
endif
ifdef CONFIG_WNM
CFLAGS += -DCONFIG_WNM
endif
ifdef NEED_AP_MLME
OBJS += ../src/ap/wmm.o
OBJS += ../src/ap/ap_list.o

View file

@ -476,6 +476,10 @@ CONFIG_PEERKEY=y
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
#CONFIG_IEEE80211N=y
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
#CONFIG_WNM=y
# Interworking (IEEE 802.11u)
# This can be used to enable functionality to improve interworking with
# external networks (GAS/ANQP to learn more about the networks and network

View file

@ -103,6 +103,8 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
{
int bssid_changed;
wnm_bss_keep_alive_deinit(wpa_s);
#ifdef CONFIG_IBSS_RSN
ibss_rsn_deinit(wpa_s->ibss_rsn);
wpa_s->ibss_rsn = NULL;
@ -1200,6 +1202,78 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_NO_SCAN_PROCESSING */
#ifdef CONFIG_WNM
static void wnm_bss_keep_alive(void *eloop_ctx, void *sock_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
if (wpa_s->wpa_state < WPA_ASSOCIATED)
return;
wpa_printf(MSG_DEBUG, "WNM: Send keep-alive");
/* TODO: could skip this if normal data traffic has been sent */
/* TODO: send keep alive frame - better use some short unicast data
* frame that gets protected if PTK is set */
if (wpa_s->sme.bss_max_idle_period) {
unsigned int msec;
msec = wpa_s->sme.bss_max_idle_period * 1024; /* times 1000 */
if (msec > 100)
msec -= 100;
eloop_register_timeout(msec / 1000, msec % 1000 * 1000,
wnm_bss_keep_alive, wpa_s, NULL);
}
}
static void wnm_process_assoc_resp(struct wpa_supplicant *wpa_s,
const u8 *ies, size_t ies_len)
{
struct ieee802_11_elems elems;
if (ies == NULL)
return;
if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
return;
#ifdef CONFIG_SME
if (elems.bss_max_idle_period) {
unsigned int msec;
wpa_s->sme.bss_max_idle_period =
WPA_GET_LE16(elems.bss_max_idle_period);
wpa_printf(MSG_DEBUG, "WNM: BSS Max Idle Period: %u (* 1000 "
"TU)%s", wpa_s->sme.bss_max_idle_period,
(elems.bss_max_idle_period[2] & 0x01) ?
" (protected keep-live required)" : "");
if (wpa_s->sme.bss_max_idle_period == 0)
wpa_s->sme.bss_max_idle_period = 1;
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL);
/* msec times 1000 */
msec = wpa_s->sme.bss_max_idle_period * 1024;
if (msec > 100)
msec -= 100;
eloop_register_timeout(msec / 1000, msec % 1000 * 1000,
wnm_bss_keep_alive, wpa_s,
NULL);
}
}
#endif /* CONFIG_SME */
}
#endif /* CONFIG_WNM */
void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s)
{
#ifdef CONFIG_WNM
eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL);
#endif /* CONFIG_WNM */
}
static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
@ -1217,6 +1291,10 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
wpa_tdls_assoc_resp_ies(wpa_s->wpa, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
#endif /* CONFIG_TDLS */
#ifdef CONFIG_WNM
wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
#endif /* CONFIG_WNM */
}
if (data->assoc_info.beacon_ies)
wpa_hexdump(MSG_DEBUG, "beacon_ies",

View file

@ -449,6 +449,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
os_free(wpa_s->bssid_filter);
wpa_s->bssid_filter = NULL;
wnm_bss_keep_alive_deinit(wpa_s);
}

View file

@ -423,6 +423,7 @@ struct wpa_supplicant {
struct os_time sa_query_start;
u8 sched_obss_scan;
u16 obss_scan_int;
u16 bss_max_idle_period;
} sme;
#endif /* CONFIG_SME */
@ -664,6 +665,7 @@ int wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx);
void wpa_supplicant_delayed_mic_error_report(void *eloop_ctx, void *sock_ctx);
void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s);
/* eap_register.c */
int eap_register_methods(void);