struct sta_info *sta, u32 flags);
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
#ifdef CONFIG_IEEE80211W
-static void ap_ping_timer(void *eloop_ctx, void *timeout_ctx);
+static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx);
#endif /* CONFIG_IEEE80211W */
int ap_for_each_sta(struct hostapd_data *hapd,
}
#ifdef CONFIG_IEEE80211N
- if (sta->flags & WLAN_STA_HT) {
- u16 ht_capab = le_to_host16(
- sta->ht_capabilities.data.capabilities_info);
- if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0)
- hapd->iface->num_sta_ht_no_gf--;
- if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0)
- hapd->iface->num_sta_ht_20mhz--;
- } else
+ if (sta->no_ht_gf_set) {
+ sta->no_ht_gf_set = 0;
+ hapd->iface->num_sta_ht_no_gf--;
+ }
+
+ if (sta->no_ht_set) {
+ sta->no_ht_set = 0;
hapd->iface->num_sta_no_ht--;
+ }
+
+ if (sta->ht_20mhz_set) {
+ sta->ht_20mhz_set = 0;
+ hapd->iface->num_sta_ht_20mhz--;
+ }
if (hostapd_ht_operation_update(hapd->iface) > 0)
set_beacon++;
os_free(sta->challenge);
#ifdef CONFIG_IEEE80211W
- os_free(sta->ping_trans_id);
- eloop_cancel_timeout(ap_ping_timer, hapd, sta);
+ os_free(sta->sa_query_trans_id);
+ eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
#endif /* CONFIG_IEEE80211W */
+ wpabuf_free(sta->wps_ie);
+
os_free(sta);
}
}
+/**
+ * ap_handle_timer - Per STA timer handler
+ * @eloop_ctx: struct hostapd_data *
+ * @timeout_ctx: struct sta_info *
+ *
+ * This function is called to check station activity and to remove inactive
+ * stations.
+ */
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
#ifdef CONFIG_IEEE80211W
-/* MLME-PING.request */
-static void ieee802_11_send_ping_req(struct hostapd_data *hapd, const u8 *addr,
- const u8 *trans_id)
+int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
{
- struct ieee80211_mgmt mgmt;
- u8 *end;
-
- os_memset(&mgmt, 0, sizeof(mgmt));
- 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_PING;
- mgmt.u.action.u.ping_req.action = WLAN_PING_REQUEST;
- os_memcpy(mgmt.u.action.u.ping_req.trans_id, trans_id,
- WLAN_PING_TRANS_ID_LEN);
- end = mgmt.u.action.u.ping_req.trans_id + WLAN_PING_TRANS_ID_LEN;
- if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN +
- end - (u8 *) &mgmt, 0) < 0)
- perror("ieee802_11_send_ping_req: send");
+ 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_ping_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 sta_info *sta = timeout_ctx;
unsigned int timeout, sec, usec;
u8 *trans_id, *nbuf;
- if (sta->ping_count >= hapd->conf->assoc_ping_attempts) {
- hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG,
- "association ping timed out");
- sta->ping_timed_out = 1;
- os_free(sta->ping_trans_id);
- sta->ping_trans_id = NULL;
- sta->ping_count = 0;
+ if (sta->sa_query_count > 0 &&
+ ap_check_sa_query_timeout(hapd, sta))
return;
- }
- nbuf = os_realloc(sta->ping_trans_id,
- (sta->ping_count + 1) * WLAN_PING_TRANS_ID_LEN);
+ nbuf = os_realloc(sta->sa_query_trans_id,
+ (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN);
if (nbuf == NULL)
return;
- trans_id = nbuf + sta->ping_count * WLAN_PING_TRANS_ID_LEN;
- sta->ping_trans_id = nbuf;
- sta->ping_count++;
+ 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;
+ sta->sa_query_trans_id = nbuf;
+ sta->sa_query_count++;
- os_get_random(trans_id, WLAN_PING_TRANS_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_LEVEL_DEBUG,
- "association ping attempt %d", sta->ping_count);
-
- ieee802_11_send_ping_req(hapd, sta->addr, trans_id);
+ "association SA Query attempt %d", sta->sa_query_count);
- timeout = hapd->conf->assoc_ping_timeout;
- sec = ((timeout / 1000) * 1024) / 1000;
- usec = (timeout % 1000) * 1024;
- eloop_register_timeout(sec, usec, ap_ping_timer, hapd, sta);
+ ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
}
-void ap_sta_start_ping(struct hostapd_data *hapd, struct sta_info *sta)
+void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
{
- ap_ping_timer(hapd, sta);
+ ap_sa_query_timer(hapd, sta);
}
-void ap_sta_stop_ping(struct hostapd_data *hapd, struct sta_info *sta)
+void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
{
- eloop_cancel_timeout(ap_ping_timer, hapd, sta);
- os_free(sta->ping_trans_id);
- sta->ping_trans_id = NULL;
- sta->ping_count = 0;
+ eloop_cancel_timeout(ap_sa_query_timer, hapd, sta);
+ os_free(sta->sa_query_trans_id);
+ sta->sa_query_trans_id = NULL;
+ sta->sa_query_count = 0;
}
#endif /* CONFIG_IEEE80211W */