Avoid direct call to hostapd_new_assoc_sta from ieee802_11.c
[libeap.git] / hostapd / sta_info.c
index df11901..7e564b2 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * hostapd / Station table
  * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2007-2008, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,6 +14,7 @@
 
 #include "includes.h"
 
+#include "common.h"
 #include "hostapd.h"
 #include "sta_info.h"
 #include "eloop.h"
@@ -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"
@@ -120,6 +120,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 
        accounting_sta_stop(hapd, sta);
 
+       hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0);
        if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) &&
            !(sta->flags & WLAN_STA_PREAUTH))
                hostapd_sta_remove(hapd, sta->addr);
@@ -128,7 +129,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) {
@@ -154,7 +156,6 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
                        set_beacon++;
        }
 
-#ifdef CONFIG_IEEE80211N
        if (sta->no_ht_gf_set) {
                sta->no_ht_gf_set = 0;
                hapd->iface->num_sta_ht_no_gf--;
@@ -170,9 +171,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
                hapd->iface->num_sta_ht_20mhz--;
        }
 
+#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N)
        if (hostapd_ht_operation_update(hapd->iface) > 0)
                set_beacon++;
-#endif /* CONFIG_IEEE80211N */
+#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
 
        if (set_beacon)
                ieee802_11_set_beacons(hapd->iface);
@@ -183,7 +185,9 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
        ieee802_1x_free_station(sta);
        wpa_auth_sta_deinit(sta->wpa_sm);
        rsn_preauth_free_station(hapd, sta);
+#ifndef CONFIG_NO_RADIUS
        radius_client_flush_auth(hapd->radius, sta->addr);
+#endif /* CONFIG_NO_RADIUS */
 
        os_free(sta->last_assoc_req);
        os_free(sta->challenge);
@@ -195,6 +199,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 
        wpabuf_free(sta->wps_ie);
 
+       os_free(sta->ht_capabilities);
+
        os_free(sta);
 }
 
@@ -219,6 +225,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;
@@ -280,19 +294,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);
+               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 (hapd->drv.send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0)
                        perror("ap_handle_timer: send");
 #endif /* CONFIG_NATIVE_WINDOWS */
        } else if (sta->timeout_next != STA_REMOVE) {
@@ -413,7 +438,7 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
                wpa_printf(MSG_ERROR, "malloc failed");
                return NULL;
        }
-       sta->acct_interim_interval = hapd->conf->radius->acct_interim_interval;
+       sta->acct_interim_interval = hapd->conf->acct_interim_interval;
 
        /* initialize STA info data */
        eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
@@ -510,6 +535,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;
 
@@ -608,35 +634,14 @@ 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-SAQuery.request */
-static void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
-                                        const u8 *addr, const u8 *trans_id)
-{
-       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_SA_QUERY;
-       mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
-       os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id,
-                 WLAN_SA_QUERY_TR_ID_LEN);
-       end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN;
-       if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN +
-                                   end - (u8 *) &mgmt, 0) < 0)
-               perror("ieee802_11_send_sa_query_req: send");
-}
-
-
 int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta)
 {
        u32 tu;
@@ -695,7 +700,9 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
                       HOSTAPD_LEVEL_DEBUG,
                       "association SA Query attempt %d", sta->sa_query_count);
 
+#ifdef NEED_AP_MLME
        ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id);
+#endif /* NEED_AP_MLME */
 }
 
 
@@ -714,3 +721,22 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta)
 }
 
 #endif /* CONFIG_IEEE80211W */
+
+
+void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
+                      const u8 *addr, u16 reason)
+{
+
+       if (sta == NULL && addr)
+               sta = ap_get_sta(hapd, addr);
+
+       if (addr)
+               hostapd_sta_deauth(hapd, addr, reason);
+
+       if (sta == NULL)
+               return;
+       sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
+       eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+       eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta);
+       sta->timeout_next = STA_REMOVE;
+}