Fix small HTTP processing issues
[wpasupplicant] / hostapd / sta_info.c
index 855c548..7a22e92 100644 (file)
@@ -25,7 +25,7 @@
 #include "wpa.h"
 #include "preauth.h"
 #include "radius/radius_client.h"
-#include "driver.h"
+#include "driver_i.h"
 #include "beacon.h"
 #include "hw_features.h"
 #include "mlme.h"
@@ -35,7 +35,7 @@ static int ap_sta_in_other_bss(struct hostapd_data *hapd,
                               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,
@@ -128,7 +128,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
        ap_sta_list_del(hapd, sta);
 
        if (sta->aid > 0)
-               hapd->sta_aid[sta->aid - 1] = NULL;
+               hapd->sta_aid[(sta->aid - 1) / 32] &=
+                       ~BIT((sta->aid - 1) % 32);
 
        hapd->num_sta--;
        if (sta->nonerp_set) {
@@ -155,18 +156,25 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
        }
 
 #ifdef CONFIG_IEEE80211N
-       if (sta->flags & WLAN_STA_HT) {
-               if ((sta->ht_capabilities.data.capabilities_info &
-                    HT_CAP_INFO_GREEN_FIELD) == 0)
-                       hapd->iface->num_sta_ht_no_gf--;
-               if ((sta->ht_capabilities.data.capabilities_info &
-                    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--;
+       }
+
+#ifdef NEED_MLME
        if (hostapd_ht_operation_update(hapd->iface) > 0)
                set_beacon++;
+#endif /* NEED_MLME */
 #endif /* CONFIG_IEEE80211N */
 
        if (set_beacon)
@@ -184,10 +192,12 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
        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);
 }
 
@@ -212,6 +222,14 @@ void hostapd_free_stas(struct hostapd_data *hapd)
 }
 
 
+/**
+ * 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;
@@ -273,20 +291,30 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
                sta->flags |= WLAN_STA_PENDING_POLL;
 
 #ifndef CONFIG_NATIVE_WINDOWS
-               /* FIX: WLAN_FC_STYPE_NULLFUNC would be more appropriate, but
-                * it is apparently not retried so TX Exc events are not
-                * received for it */
                os_memset(&hdr, 0, sizeof(hdr));
-               hdr.frame_control =
-                       IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
-               hdr.frame_control |= host_to_le16(BIT(1));
+               if (hapd->driver &&
+                   os_strcmp(hapd->driver->name, "hostap") == 0) {
+                       /*
+                        * WLAN_FC_STYPE_NULLFUNC would be more appropriate,
+                        * but it is apparently not retried so TX Exc events
+                        * are not received for it.
+                        */
+                       hdr.frame_control =
+                               IEEE80211_FC(WLAN_FC_TYPE_DATA,
+                                            WLAN_FC_STYPE_DATA);
+               } else {
+                       hdr.frame_control =
+                               IEEE80211_FC(WLAN_FC_TYPE_DATA,
+                                            WLAN_FC_STYPE_NULLFUNC);
+               }
+
                hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
                os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
                os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
                          ETH_ALEN);
                os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
 
-               if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr), 0) < 0)
+               if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0)
                        perror("ap_handle_timer: send");
 #endif /* CONFIG_NATIVE_WINDOWS */
        } else if (sta->timeout_next != STA_REMOVE) {
@@ -504,6 +532,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
 int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
                     int old_vlanid)
 {
+#ifndef CONFIG_NO_VLAN
        const char *iface;
        struct hostapd_vlan *vlan = NULL;
 
@@ -602,88 +631,90 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
                wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA");
 
        return hostapd_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id);
+#else /* CONFIG_NO_VLAN */
+       return 0;
+#endif /* CONFIG_NO_VLAN */
 }
 
 
 #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);
+                      "association SA Query attempt %d", sta->sa_query_count);
 
-       ieee802_11_send_ping_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_ping_timer, hapd, sta);
+#ifdef NEED_MLME
+       ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
+#endif /* NEED_MLME */
 }
 
 
-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 */