Updated SA Query procedure to use timeouts per 802.11w/D7.0
The previous max_attempts * timeout is now replaced with two timeouts (one for each retry, the other one for maximum wait).
This commit is contained in:
parent
93b76319f1
commit
45c94154a6
7 changed files with 77 additions and 39 deletions
|
@ -106,6 +106,7 @@ struct sta_info {
|
||||||
u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
|
u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
|
||||||
* sa_query_count octets of pending SA Query
|
* sa_query_count octets of pending SA Query
|
||||||
* transaction identifiers */
|
* transaction identifiers */
|
||||||
|
struct os_time sa_query_start;
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
|
||||||
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
|
struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */
|
||||||
|
|
|
@ -184,8 +184,8 @@ static void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
||||||
bss->max_listen_interval = 65535;
|
bss->max_listen_interval = 65535;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
bss->assoc_ping_timeout = 1000;
|
bss->assoc_sa_query_max_timeout = 1000;
|
||||||
bss->assoc_ping_attempts = 3;
|
bss->assoc_sa_query_retry_timeout = 201;
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
#ifdef EAP_FAST
|
#ifdef EAP_FAST
|
||||||
/* both anonymous and authenticated provisioning */
|
/* both anonymous and authenticated provisioning */
|
||||||
|
@ -2064,18 +2064,20 @@ struct hostapd_config * hostapd_config_read(const char *fname)
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
} else if (os_strcmp(buf, "ieee80211w") == 0) {
|
} else if (os_strcmp(buf, "ieee80211w") == 0) {
|
||||||
bss->ieee80211w = atoi(pos);
|
bss->ieee80211w = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "assoc_ping_timeout") == 0) {
|
} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
|
||||||
bss->assoc_ping_timeout = atoi(pos);
|
bss->assoc_sa_query_max_timeout = atoi(pos);
|
||||||
if (bss->assoc_ping_timeout == 0) {
|
if (bss->assoc_sa_query_max_timeout == 0) {
|
||||||
printf("Line %d: invalid assoc_ping_timeout\n",
|
printf("Line %d: invalid "
|
||||||
line);
|
"assoc_sa_query_max_timeout\n",
|
||||||
|
line);
|
||||||
errors++;
|
errors++;
|
||||||
}
|
}
|
||||||
} else if (os_strcmp(buf, "assoc_ping_attempts") == 0) {
|
} else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0)
|
||||||
bss->assoc_ping_timeout = atoi(pos);
|
{
|
||||||
if (bss->assoc_ping_timeout == 0) {
|
bss->assoc_sa_query_retry_timeout = atoi(pos);
|
||||||
printf("Line %d: invalid assoc_ping_attempts "
|
if (bss->assoc_sa_query_retry_timeout == 0) {
|
||||||
"(valid range: 1..255)\n",
|
printf("Line %d: invalid "
|
||||||
|
"assoc_sa_query_retry_timeout\n",
|
||||||
line);
|
line);
|
||||||
errors++;
|
errors++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,10 +210,10 @@ struct hostapd_bss_config {
|
||||||
IEEE80211W_OPTIONAL = 1,
|
IEEE80211W_OPTIONAL = 1,
|
||||||
IEEE80211W_REQUIRED = 2
|
IEEE80211W_REQUIRED = 2
|
||||||
} ieee80211w;
|
} ieee80211w;
|
||||||
/* dot11AssociationPingResponseTimeout (in TU) */
|
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
||||||
unsigned int assoc_ping_timeout;
|
unsigned int assoc_sa_query_max_timeout;
|
||||||
/* dot11AssociationMaximumPingAttempts */
|
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
|
||||||
int assoc_ping_attempts;
|
int assoc_sa_query_retry_timeout;
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
int wpa_pairwise;
|
int wpa_pairwise;
|
||||||
int wpa_group;
|
int wpa_group;
|
||||||
|
|
|
@ -755,13 +755,15 @@ own_ip_addr=127.0.0.1
|
||||||
# 2 = required
|
# 2 = required
|
||||||
#ieee80211w=0
|
#ieee80211w=0
|
||||||
|
|
||||||
# Association ping timeout (in TU = 1.024 ms; for MFP)
|
# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
|
||||||
# dot11AssociationPingResponseTimeout, 1...4294967295
|
# (maximum time to wait for a SA Query response)
|
||||||
#assoc_ping_timeout=1000
|
# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
|
||||||
|
#assoc_sa_query_max_timeout=1000
|
||||||
|
|
||||||
# Maximum number of association pings
|
# Association SA Query retry timeout (in TU = 1.024 ms; for MFP)
|
||||||
# dot11AssociationMaximumPingAttempts , 1...255
|
# (time between two subsequent SA Query requests)
|
||||||
#assoc_ping_attempts=3
|
# dot11AssociationSAQueryRetryTimeout, 1...4294967295
|
||||||
|
#assoc_sa_query_retry_timeout=201
|
||||||
|
|
||||||
|
|
||||||
# okc: Opportunistic Key Caching (aka Proactive Key Caching)
|
# okc: Opportunistic Key Caching (aka Proactive Key Caching)
|
||||||
|
|
|
@ -298,12 +298,20 @@ static u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta, u8 *eid)
|
struct sta_info *sta, u8 *eid)
|
||||||
{
|
{
|
||||||
u8 *pos = eid;
|
u8 *pos = eid;
|
||||||
u32 timeout;
|
u32 timeout, tu;
|
||||||
|
struct os_time now, passed;
|
||||||
|
|
||||||
*pos++ = WLAN_EID_ASSOC_COMEBACK_TIME;
|
*pos++ = WLAN_EID_ASSOC_COMEBACK_TIME;
|
||||||
*pos++ = 4;
|
*pos++ = 4;
|
||||||
timeout = (hapd->conf->assoc_ping_attempts - sta->sa_query_count + 1) *
|
os_get_time(&now);
|
||||||
hapd->conf->assoc_ping_timeout;
|
os_time_sub(&now, &sta->sa_query_start, &passed);
|
||||||
|
tu = (passed.sec * 1000000 + passed.usec) / 1024;
|
||||||
|
if (hapd->conf->assoc_sa_query_max_timeout > tu)
|
||||||
|
timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
|
||||||
|
else
|
||||||
|
timeout = 0;
|
||||||
|
if (timeout < hapd->conf->assoc_sa_query_max_timeout)
|
||||||
|
timeout++; /* add some extra time for local timers */
|
||||||
WPA_PUT_LE32(pos, timeout);
|
WPA_PUT_LE32(pos, timeout);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
|
|
||||||
|
@ -893,6 +901,9 @@ static void handle_assoc(struct hostapd_data *hapd,
|
||||||
if (resp != WLAN_STATUS_SUCCESS)
|
if (resp != WLAN_STATUS_SUCCESS)
|
||||||
goto fail;
|
goto fail;
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
|
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
|
||||||
|
sta->sa_query_count > 0)
|
||||||
|
ap_check_sa_query_timeout(hapd, sta);
|
||||||
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out) {
|
if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out) {
|
||||||
/*
|
/*
|
||||||
* STA has already been associated with MFP and SA
|
* STA has already been associated with MFP and SA
|
||||||
|
|
|
@ -637,6 +637,30 @@ static void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
|
{
|
||||||
|
u32 tu;
|
||||||
|
struct os_time now, passed;
|
||||||
|
os_get_time(&now);
|
||||||
|
os_time_sub(&now, &sta->sa_query_start, &passed);
|
||||||
|
tu = (passed.sec * 1000000 + passed.usec) / 1024;
|
||||||
|
if (hapd->conf->assoc_sa_query_max_timeout < tu) {
|
||||||
|
hostapd_logger(hapd, sta->addr,
|
||||||
|
HOSTAPD_MODULE_IEEE80211,
|
||||||
|
HOSTAPD_LEVEL_DEBUG,
|
||||||
|
"association SA Query timed out");
|
||||||
|
sta->sa_query_timed_out = 1;
|
||||||
|
os_free(sta->sa_query_trans_id);
|
||||||
|
sta->sa_query_trans_id = NULL;
|
||||||
|
sta->sa_query_count = 0;
|
||||||
|
eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = eloop_ctx;
|
struct hostapd_data *hapd = eloop_ctx;
|
||||||
|
@ -644,37 +668,34 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
|
||||||
unsigned int timeout, sec, usec;
|
unsigned int timeout, sec, usec;
|
||||||
u8 *trans_id, *nbuf;
|
u8 *trans_id, *nbuf;
|
||||||
|
|
||||||
if (sta->sa_query_count >= hapd->conf->assoc_ping_attempts) {
|
if (sta->sa_query_count > 0 &&
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
ap_check_sa_query_timeout(hapd, sta))
|
||||||
HOSTAPD_LEVEL_DEBUG,
|
|
||||||
"association SA Query timed out");
|
|
||||||
sta->sa_query_timed_out = 1;
|
|
||||||
os_free(sta->sa_query_trans_id);
|
|
||||||
sta->sa_query_trans_id = NULL;
|
|
||||||
sta->sa_query_count = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
nbuf = os_realloc(sta->sa_query_trans_id,
|
nbuf = os_realloc(sta->sa_query_trans_id,
|
||||||
(sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
|
(sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
|
||||||
if (nbuf == NULL)
|
if (nbuf == NULL)
|
||||||
return;
|
return;
|
||||||
|
if (sta->sa_query_count == 0) {
|
||||||
|
/* Starting a new SA Query procedure */
|
||||||
|
os_get_time(&sta->sa_query_start);
|
||||||
|
}
|
||||||
trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
|
trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
|
||||||
sta->sa_query_trans_id = nbuf;
|
sta->sa_query_trans_id = nbuf;
|
||||||
sta->sa_query_count++;
|
sta->sa_query_count++;
|
||||||
|
|
||||||
os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
|
||||||
|
|
||||||
|
timeout = hapd->conf->assoc_sa_query_retry_timeout;
|
||||||
|
sec = ((timeout / 1000) * 1024) / 1000;
|
||||||
|
usec = (timeout % 1000) * 1024;
|
||||||
|
eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
|
||||||
|
|
||||||
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
||||||
HOSTAPD_LEVEL_DEBUG,
|
HOSTAPD_LEVEL_DEBUG,
|
||||||
"association SA Query attempt %d", sta->sa_query_count);
|
"association SA Query attempt %d", sta->sa_query_count);
|
||||||
|
|
||||||
ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
|
ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
|
||||||
|
|
||||||
timeout = hapd->conf->assoc_ping_timeout;
|
|
||||||
sec = ((timeout / 1000) * 1024) / 1000;
|
|
||||||
usec = (timeout % 1000) * 1024;
|
|
||||||
eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,5 +38,6 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
int old_vlanid);
|
int old_vlanid);
|
||||||
void ap_sta_start_sa_query(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);
|
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);
|
||||||
|
|
||||||
#endif /* STA_INFO_H */
|
#endif /* STA_INFO_H */
|
||||||
|
|
Loading…
Reference in a new issue