]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/ap/drv_callbacks.c
Add new drv_flag for indicating user space AP MLME
[thirdparty/hostap.git] / src / ap / drv_callbacks.c
index 142ceb7cd00d8fb9200bb86c6f73b15668c63a23..cf06a4fb8f4eece5909a62cf376b157a21c865f4 100644 (file)
@@ -2,14 +2,8 @@
  * hostapd / Callback functions for driver wrappers
  * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
  *
- * 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
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "utils/includes.h"
@@ -32,6 +26,7 @@
 #include "wps_hostapd.h"
 #include "ap_drv_ops.h"
 #include "ap_config.h"
+#include "hw_features.h"
 
 
 int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
@@ -84,10 +79,19 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
        sta = ap_get_sta(hapd, addr);
        if (sta) {
                accounting_sta_stop(hapd, sta);
+
+               /*
+                * Make sure that the previously registered inactivity timer
+                * will not remove the STA immediately.
+                */
+               sta->timeout_next = STA_NULLFUNC;
        } else {
                sta = ap_sta_add(hapd, addr);
-               if (sta == NULL)
+               if (sta == NULL) {
+                       hostapd_drv_sta_disassoc(hapd, addr,
+                                                WLAN_REASON_DISASSOC_AP_BUSY);
                        return -1;
+               }
        }
        sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
 
@@ -203,8 +207,10 @@ skip_wpa_check:
        ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
 
 #ifdef CONFIG_P2P
-       p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
-                             req_ies, req_ies_len);
+       if (req_ies) {
+               p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
+                                     req_ies, req_ies_len);
+       }
 #endif /* CONFIG_P2P */
 
        return 0;
@@ -268,8 +274,36 @@ void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
 }
 
 
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
+                            int offset)
+{
+#ifdef NEED_AP_MLME
+       int channel;
+
+       hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+                      HOSTAPD_LEVEL_INFO, "driver had channel switch: "
+                      "freq=%d, ht=%d, offset=%d", freq, ht, offset);
+
+       hapd->iface->freq = freq;
+
+       channel = hostapd_hw_get_channel(hapd, freq);
+       if (!channel) {
+               hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+                              HOSTAPD_LEVEL_WARNING, "driver switched to "
+                              "bad channel!");
+               return;
+       }
+
+       hapd->iconf->channel = channel;
+       hapd->iconf->ieee80211n = ht;
+       hapd->iconf->secondary_channel = offset;
+#endif /* NEED_AP_MLME */
+}
+
+
 int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
-                        const u8 *bssid, const u8 *ie, size_t ie_len)
+                        const u8 *bssid, const u8 *ie, size_t ie_len,
+                        int ssi_signal)
 {
        size_t i;
        int ret = 0;
@@ -280,7 +314,8 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
        random_add_randomness(sa, ETH_ALEN);
        for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
                if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
-                                           sa, da, bssid, ie, ie_len) > 0) {
+                                           sa, da, bssid, ie, ie_len,
+                                           ssi_signal) > 0) {
                        ret = 1;
                        break;
                }
@@ -467,6 +502,23 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                          union wpa_event_data *data)
 {
        struct hostapd_data *hapd = ctx;
+#ifndef CONFIG_NO_STDOUT_DEBUG
+       int level = MSG_DEBUG;
+
+       if (event == EVENT_RX_MGMT && data && data->rx_mgmt.frame &&
+           data->rx_mgmt.frame_len >= 24) {
+               const struct ieee80211_hdr *hdr;
+               u16 fc;
+               hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
+               fc = le_to_host16(hdr->frame_control);
+               if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+                   WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
+                       level = MSG_EXCESSIVE;
+       }
+
+       wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
+               event_to_string(event), event);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
 
        switch (event) {
        case EVENT_MICHAEL_MIC_FAILURE:
@@ -502,6 +554,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                        break;
                }
                break;
+       case EVENT_EAPOL_TX_STATUS:
+               hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
+                                       data->eapol_tx_status.data,
+                                       data->eapol_tx_status.data_len,
+                                       data->eapol_tx_status.ack);
+               break;
        case EVENT_DRIVER_CLIENT_POLL_OK:
                hostapd_client_poll_ok(hapd, data->client_poll.addr);
                break;
@@ -522,7 +580,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                                     data->rx_probe_req.da,
                                     data->rx_probe_req.bssid,
                                     data->rx_probe_req.ie,
-                                    data->rx_probe_req.ie_len);
+                                    data->rx_probe_req.ie_len,
+                                    data->rx_probe_req.ssi_signal);
                break;
        case EVENT_NEW_STA:
                hostapd_event_new_sta(hapd, data->new_sta.addr);
@@ -559,6 +618,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                hostapd_rx_action(hapd, &data->rx_action);
                break;
 #endif /* NEED_AP_MLME */
+       case EVENT_CH_SWITCH:
+               if (!data)
+                       break;
+               hostapd_event_ch_switch(hapd, data->ch_switch.freq,
+                                       data->ch_switch.ht_enabled,
+                                       data->ch_switch.ch_offset);
+               break;
        default:
                wpa_printf(MSG_DEBUG, "Unknown event %d", event);
                break;