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:
parent
b80eb89d8e
commit
b6668734ab
13 changed files with 143 additions and 2 deletions
|
@ -169,6 +169,10 @@ ifdef CONFIG_IEEE80211N
|
||||||
CFLAGS += -DCONFIG_IEEE80211N
|
CFLAGS += -DCONFIG_IEEE80211N
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_WNM
|
||||||
|
CFLAGS += -DCONFIG_WNM
|
||||||
|
endif
|
||||||
|
|
||||||
include ../src/drivers/drivers.mak
|
include ../src/drivers/drivers.mak
|
||||||
OBJS += $(DRV_AP_OBJS)
|
OBJS += $(DRV_AP_OBJS)
|
||||||
CFLAGS += $(DRV_AP_CFLAGS)
|
CFLAGS += $(DRV_AP_CFLAGS)
|
||||||
|
|
|
@ -136,6 +136,10 @@ CONFIG_IPV6=y
|
||||||
# IEEE 802.11n (High Throughput) support
|
# IEEE 802.11n (High Throughput) support
|
||||||
#CONFIG_IEEE80211N=y
|
#CONFIG_IEEE80211N=y
|
||||||
|
|
||||||
|
# Wireless Network Management (IEEE Std 802.11v-2011)
|
||||||
|
# Note: This is experimental and not complete implementation.
|
||||||
|
#CONFIG_WNM=y
|
||||||
|
|
||||||
# Remove debugging code that is printing out debug messages to stdout.
|
# Remove debugging code that is printing out debug messages to stdout.
|
||||||
# This can be used to reduce the size of the hostapd considerably if debugging
|
# This can be used to reduce the size of the hostapd considerably if debugging
|
||||||
# code is not needed.
|
# code is not needed.
|
||||||
|
|
|
@ -876,6 +876,7 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
#endif /* CONFIG_IEEE80211N */
|
#endif /* CONFIG_IEEE80211N */
|
||||||
|
|
||||||
p = hostapd_eid_ext_capab(hapd, p);
|
p = hostapd_eid_ext_capab(hapd, p);
|
||||||
|
p = hostapd_eid_bss_max_idle_period(hapd, p);
|
||||||
|
|
||||||
if (sta->flags & WLAN_STA_WMM)
|
if (sta->flags & WLAN_STA_WMM)
|
||||||
p = hostapd_eid_wmm(hapd, p);
|
p = hostapd_eid_wmm(hapd, p);
|
||||||
|
|
|
@ -72,5 +72,6 @@ u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid);
|
||||||
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
|
u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid);
|
||||||
int hostapd_update_time_adv(struct hostapd_data *hapd);
|
int hostapd_update_time_adv(struct hostapd_data *hapd);
|
||||||
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
|
void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr);
|
||||||
|
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid);
|
||||||
|
|
||||||
#endif /* IEEE802_11_H */
|
#endif /* IEEE802_11_H */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* hostapd / IEEE 802.11 Management
|
* hostapd / IEEE 802.11 Management
|
||||||
* Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -397,3 +397,31 @@ int hostapd_update_time_adv(struct hostapd_data *hapd)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
|
||||||
|
{
|
||||||
|
u8 *pos = eid;
|
||||||
|
|
||||||
|
#ifdef CONFIG_WNM
|
||||||
|
if (hapd->conf->ap_max_inactivity > 0) {
|
||||||
|
unsigned int val;
|
||||||
|
*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
|
||||||
|
*pos++ = 3;
|
||||||
|
val = hapd->conf->ap_max_inactivity;
|
||||||
|
if (val > 68000)
|
||||||
|
val = 68000;
|
||||||
|
val *= 1000;
|
||||||
|
val /= 1024;
|
||||||
|
if (val == 0)
|
||||||
|
val = 1;
|
||||||
|
if (val > 65535)
|
||||||
|
val = 65535;
|
||||||
|
WPA_PUT_LE16(pos, val);
|
||||||
|
pos += 2;
|
||||||
|
*pos++ = 0x00; /* TODO: Protected Keep-Alive Required */
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_WNM */
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* IEEE 802.11 Common routines
|
* IEEE 802.11 Common routines
|
||||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -262,6 +262,15 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||||
elems->interworking = pos;
|
elems->interworking = pos;
|
||||||
elems->interworking_len = elen;
|
elems->interworking_len = elen;
|
||||||
break;
|
break;
|
||||||
|
case WLAN_EID_EXT_CAPAB:
|
||||||
|
elems->ext_capab = pos;
|
||||||
|
elems->ext_capab_len = elen;
|
||||||
|
break;
|
||||||
|
case WLAN_EID_BSS_MAX_IDLE_PERIOD:
|
||||||
|
if (elen < 3)
|
||||||
|
break;
|
||||||
|
elems->bss_max_idle_period = pos;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
unknown++;
|
unknown++;
|
||||||
if (!show_errors)
|
if (!show_errors)
|
||||||
|
|
|
@ -38,6 +38,8 @@ struct ieee802_11_elems {
|
||||||
const u8 *link_id;
|
const u8 *link_id;
|
||||||
const u8 *interworking;
|
const u8 *interworking;
|
||||||
const u8 *hs20;
|
const u8 *hs20;
|
||||||
|
const u8 *ext_capab;
|
||||||
|
const u8 *bss_max_idle_period;
|
||||||
|
|
||||||
u8 ssid_len;
|
u8 ssid_len;
|
||||||
u8 supp_rates_len;
|
u8 supp_rates_len;
|
||||||
|
@ -65,6 +67,7 @@ struct ieee802_11_elems {
|
||||||
u8 p2p_len;
|
u8 p2p_len;
|
||||||
u8 interworking_len;
|
u8 interworking_len;
|
||||||
u8 hs20_len;
|
u8 hs20_len;
|
||||||
|
u8 ext_capab_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
|
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
|
||||||
|
|
|
@ -228,6 +228,7 @@
|
||||||
#define WLAN_EID_20_40_BSS_INTOLERANT 73
|
#define WLAN_EID_20_40_BSS_INTOLERANT 73
|
||||||
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
|
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
|
||||||
#define WLAN_EID_MMIE 76
|
#define WLAN_EID_MMIE 76
|
||||||
|
#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90
|
||||||
#define WLAN_EID_TFS_REQ 91
|
#define WLAN_EID_TFS_REQ 91
|
||||||
#define WLAN_EID_TFS_RESP 92
|
#define WLAN_EID_TFS_RESP 92
|
||||||
#define WLAN_EID_WNMSLEEP 93
|
#define WLAN_EID_WNMSLEEP 93
|
||||||
|
|
|
@ -722,6 +722,10 @@ ifdef CONFIG_IEEE80211N
|
||||||
CFLAGS += -DCONFIG_IEEE80211N
|
CFLAGS += -DCONFIG_IEEE80211N
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_WNM
|
||||||
|
CFLAGS += -DCONFIG_WNM
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef NEED_AP_MLME
|
ifdef NEED_AP_MLME
|
||||||
OBJS += ../src/ap/wmm.o
|
OBJS += ../src/ap/wmm.o
|
||||||
OBJS += ../src/ap/ap_list.o
|
OBJS += ../src/ap/ap_list.o
|
||||||
|
|
|
@ -476,6 +476,10 @@ CONFIG_PEERKEY=y
|
||||||
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
|
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
|
||||||
#CONFIG_IEEE80211N=y
|
#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)
|
# Interworking (IEEE 802.11u)
|
||||||
# This can be used to enable functionality to improve interworking with
|
# This can be used to enable functionality to improve interworking with
|
||||||
# external networks (GAS/ANQP to learn more about the networks and network
|
# external networks (GAS/ANQP to learn more about the networks and network
|
||||||
|
|
|
@ -103,6 +103,8 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
|
||||||
{
|
{
|
||||||
int bssid_changed;
|
int bssid_changed;
|
||||||
|
|
||||||
|
wnm_bss_keep_alive_deinit(wpa_s);
|
||||||
|
|
||||||
#ifdef CONFIG_IBSS_RSN
|
#ifdef CONFIG_IBSS_RSN
|
||||||
ibss_rsn_deinit(wpa_s->ibss_rsn);
|
ibss_rsn_deinit(wpa_s->ibss_rsn);
|
||||||
wpa_s->ibss_rsn = NULL;
|
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 */
|
#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,
|
static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
|
||||||
union wpa_event_data *data)
|
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,
|
wpa_tdls_assoc_resp_ies(wpa_s->wpa, data->assoc_info.resp_ies,
|
||||||
data->assoc_info.resp_ies_len);
|
data->assoc_info.resp_ies_len);
|
||||||
#endif /* CONFIG_TDLS */
|
#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)
|
if (data->assoc_info.beacon_ies)
|
||||||
wpa_hexdump(MSG_DEBUG, "beacon_ies",
|
wpa_hexdump(MSG_DEBUG, "beacon_ies",
|
||||||
|
|
|
@ -449,6 +449,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
|
||||||
|
|
||||||
os_free(wpa_s->bssid_filter);
|
os_free(wpa_s->bssid_filter);
|
||||||
wpa_s->bssid_filter = NULL;
|
wpa_s->bssid_filter = NULL;
|
||||||
|
|
||||||
|
wnm_bss_keep_alive_deinit(wpa_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -423,6 +423,7 @@ struct wpa_supplicant {
|
||||||
struct os_time sa_query_start;
|
struct os_time sa_query_start;
|
||||||
u8 sched_obss_scan;
|
u8 sched_obss_scan;
|
||||||
u16 obss_scan_int;
|
u16 obss_scan_int;
|
||||||
|
u16 bss_max_idle_period;
|
||||||
} sme;
|
} sme;
|
||||||
#endif /* CONFIG_SME */
|
#endif /* CONFIG_SME */
|
||||||
|
|
||||||
|
@ -664,6 +665,7 @@ int wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_ssid *ssid);
|
struct wpa_ssid *ssid);
|
||||||
void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx);
|
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 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 */
|
/* eap_register.c */
|
||||||
int eap_register_methods(void);
|
int eap_register_methods(void);
|
||||||
|
|
Loading…
Reference in a new issue