]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/events.c
Move struct hostapd_frame_info definition away from driver API
[thirdparty/hostap.git] / wpa_supplicant / events.c
index 16f8b62a6edf7511e2fda3d29dfc65bf7963126e..9f17b82356b7035c58fb8604d1551f204838c0c6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant - Driver event processing
- * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2010, 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
 
 #include "common.h"
 #include "eapol_supp/eapol_supp_sm.h"
-#include "wpa.h"
+#include "rsn_supp/wpa.h"
 #include "eloop.h"
 #include "config.h"
 #include "l2_packet/l2_packet.h"
 #include "wpa_supplicant_i.h"
 #include "driver_i.h"
 #include "pcsc_funcs.h"
-#include "preauth.h"
-#include "pmksa_cache.h"
-#include "wpa_ctrl.h"
+#include "rsn_supp/preauth.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "common/wpa_ctrl.h"
 #include "eap_peer/eap.h"
 #include "notify.h"
-#include "ieee802_11_defs.h"
+#include "common/ieee802_11_defs.h"
 #include "blacklist.h"
 #include "wpas_glue.h"
 #include "wps_supplicant.h"
 #include "ibss_rsn.h"
 #include "sme.h"
 #include "bgscan.h"
+#include "ap.h"
+#include "bss.h"
+#include "mlme.h"
 
 
 static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
@@ -388,8 +391,9 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
 }
 
 
-static struct wpa_scan_res *
+static struct wpa_bss *
 wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
+                             struct wpa_scan_results *scan_res,
                              struct wpa_ssid *group,
                              struct wpa_ssid **selected_ssid)
 {
@@ -400,10 +404,10 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
        const u8 *ie;
 
        wpa_printf(MSG_DEBUG, "Try to find WPA-enabled AP");
-       for (i = 0; i < wpa_s->scan_res->num; i++) {
+       for (i = 0; i < scan_res->num; i++) {
                const u8 *ssid_;
                u8 wpa_ie_len, rsn_ie_len, ssid_len;
-               bss = wpa_s->scan_res->res[i];
+               bss = scan_res->res[i];
 
                ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
                ssid_ = ie ? ie + 2 : (u8 *) "";
@@ -427,6 +431,11 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
                        continue;
                }
 
+               if (ssid_len == 0) {
+                       wpa_printf(MSG_DEBUG, "   skip - SSID not known");
+                       continue;
+               }
+
                if (wpa_ie_len == 0 && rsn_ie_len == 0) {
                        wpa_printf(MSG_DEBUG, "   skip - no WPA/RSN IE");
                        continue;
@@ -470,7 +479,7 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
                                   MAC2STR(bss->bssid),
                                   wpa_ssid_txt(ssid_, ssid_len));
                        *selected_ssid = ssid;
-                       return bss;
+                       return wpa_bss_get(wpa_s, bss->bssid, ssid_, ssid_len);
                }
        }
 
@@ -478,8 +487,9 @@ wpa_supplicant_select_bss_wpa(struct wpa_supplicant *wpa_s,
 }
 
 
-static struct wpa_scan_res *
+static struct wpa_bss *
 wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
+                                 struct wpa_scan_results *scan_res,
                                  struct wpa_ssid *group,
                                  struct wpa_ssid **selected_ssid)
 {
@@ -490,10 +500,10 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
        const u8 *ie;
 
        wpa_printf(MSG_DEBUG, "Try to find non-WPA AP");
-       for (i = 0; i < wpa_s->scan_res->num; i++) {
+       for (i = 0; i < scan_res->num; i++) {
                const u8 *ssid_;
                u8 wpa_ie_len, rsn_ie_len, ssid_len;
-               bss = wpa_s->scan_res->res[i];
+               bss = scan_res->res[i];
 
                ie = wpa_scan_get_ie(bss, WLAN_EID_SSID);
                ssid_ = ie ? ie + 2 : (u8 *) "";
@@ -517,6 +527,11 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
                        continue;
                }
 
+               if (ssid_len == 0) {
+                       wpa_printf(MSG_DEBUG, "   skip - SSID not known");
+                       continue;
+               }
+
                for (ssid = group; ssid; ssid = ssid->pnext) {
                        int check_ssid = ssid->ssid_len != 0;
 
@@ -591,7 +606,7 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
                                   MAC2STR(bss->bssid),
                                   wpa_ssid_txt(ssid_, ssid_len));
                        *selected_ssid = ssid;
-                       return bss;
+                       return wpa_bss_get(wpa_s, bss->bssid, ssid_, ssid_len);
                }
        }
 
@@ -599,37 +614,42 @@ wpa_supplicant_select_bss_non_wpa(struct wpa_supplicant *wpa_s,
 }
 
 
-static struct wpa_scan_res *
-wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group,
+static struct wpa_bss *
+wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
+                         struct wpa_scan_results *scan_res,
+                         struct wpa_ssid *group,
                          struct wpa_ssid **selected_ssid)
 {
-       struct wpa_scan_res *selected;
+       struct wpa_bss *selected;
 
        wpa_printf(MSG_DEBUG, "Selecting BSS from priority group %d",
                   group->priority);
 
        /* First, try to find WPA-enabled AP */
-       selected = wpa_supplicant_select_bss_wpa(wpa_s, group, selected_ssid);
+       selected = wpa_supplicant_select_bss_wpa(wpa_s, scan_res, group,
+                                                selected_ssid);
        if (selected)
                return selected;
 
        /* If no WPA-enabled AP found, try to find non-WPA AP, if configuration
         * allows this. */
-       return wpa_supplicant_select_bss_non_wpa(wpa_s, group, selected_ssid);
+       return wpa_supplicant_select_bss_non_wpa(wpa_s, scan_res, group,
+                                                selected_ssid);
 }
 
 
-static struct wpa_scan_res *
+static struct wpa_bss *
 wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
+                           struct wpa_scan_results *scan_res,
                            struct wpa_ssid **selected_ssid)
 {
-       struct wpa_scan_res *selected = NULL;
+       struct wpa_bss *selected = NULL;
        int prio;
 
        while (selected == NULL) {
                for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
                        selected = wpa_supplicant_select_bss(
-                               wpa_s, wpa_s->conf->pssid[prio],
+                               wpa_s, scan_res, wpa_s->conf->pssid[prio],
                                selected_ssid);
                        if (selected)
                                break;
@@ -672,7 +692,7 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s,
 
 
 static void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
-                                  struct wpa_scan_res *selected,
+                                  struct wpa_bss *selected,
                                   struct wpa_ssid *ssid)
 {
        if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) {
@@ -701,7 +721,6 @@ static void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
                wpa_printf(MSG_DEBUG, "Already associated with the selected "
                           "AP");
        }
-       rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res);
 }
 
 
@@ -725,14 +744,49 @@ wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s)
 }
 
 
-static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
+/* TODO: move the rsn_preauth_scan_result*() to be called from notify.c based
+ * on BSS added and BSS changed events */
+static void wpa_supplicant_rsn_preauth_scan_results(
+       struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res)
+{
+       int i;
+
+       if (rsn_preauth_scan_results(wpa_s->wpa) < 0)
+               return;
+
+       for (i = scan_res->num - 1; i >= 0; i--) {
+               const u8 *ssid, *rsn;
+               struct wpa_scan_res *r;
+
+               r = scan_res->res[i];
+
+               ssid = wpa_scan_get_ie(r, WLAN_EID_SSID);
+               if (ssid == NULL)
+                       continue;
+
+               rsn = wpa_scan_get_ie(r, WLAN_EID_RSN);
+               if (rsn == NULL)
+                       continue;
+
+               rsn_preauth_scan_result(wpa_s->wpa, r->bssid, ssid, rsn);
+       }
+
+}
+
+
+static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
+                                             union wpa_event_data *data)
 {
-       struct wpa_scan_res *selected;
+       struct wpa_bss *selected;
        struct wpa_ssid *ssid = NULL;
+       struct wpa_scan_results *scan_res;
 
        wpa_supplicant_notify_scanning(wpa_s, 0);
 
-       if (wpa_supplicant_get_scan_results(wpa_s) < 0) {
+       scan_res = wpa_supplicant_get_scan_results(wpa_s,
+                                                  data ? &data->scan_info :
+                                                  NULL, 1);
+       if (scan_res == NULL) {
                if (wpa_s->conf->ap_scan == 2)
                        return;
                wpa_printf(MSG_DEBUG, "Failed to get scan results - try "
@@ -746,28 +800,38 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
         * and there were no results.
         */
        if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1 &&
-           wpa_s->scan_res->num == 0) {
+           scan_res->num == 0) {
                wpa_msg(wpa_s, MSG_DEBUG, "Cached scan results are "
                        "empty - not posting");
        } else {
-               wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
+               wpa_printf(MSG_DEBUG, "New scan results available");
+               wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
                wpas_notify_scan_results(wpa_s);
        }
 
        wpas_notify_scan_done(wpa_s, 1);
 
-       if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
+       if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) {
+               wpa_scan_results_free(scan_res);
                return;
+       }
 
        if (wpa_s->disconnected) {
                wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+               wpa_scan_results_free(scan_res);
                return;
        }
 
-       if (bgscan_notify_scan(wpa_s) == 1)
+       if (bgscan_notify_scan(wpa_s) == 1) {
+               wpa_scan_results_free(scan_res);
                return;
+       }
+
+       wpa_supplicant_rsn_preauth_scan_results(wpa_s, scan_res);
+
+       selected = wpa_supplicant_pick_network(wpa_s, scan_res, &ssid);
+       wpa_scan_results_free(scan_res);
 
-       selected = wpa_supplicant_pick_network(wpa_s, &ssid);
        if (selected) {
                wpa_supplicant_connect(wpa_s, selected, ssid);
        } else {
@@ -847,6 +911,8 @@ static void wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
                wpa_hexdump(MSG_DEBUG, "beacon_ies",
                            data->assoc_info.beacon_ies,
                            data->assoc_info.beacon_ies_len);
+       if (data->assoc_info.freq)
+               wpa_printf(MSG_DEBUG, "freq=%u MHz", data->assoc_info.freq);
 
        p = data->assoc_info.req_ies;
        l = data->assoc_info.req_ies_len;
@@ -934,6 +1000,8 @@ static void wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
                wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
        if (wpa_found || rsn_found)
                wpa_s->ap_ies_from_associnfo = 1;
+
+       wpa_s->assoc_freq = data->assoc_info.freq;
 }
 
 
@@ -970,8 +1038,24 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
                                wpa_s, WLAN_REASON_DEAUTH_LEAVING);
                        return;
                }
+               if (wpa_s->current_ssid) {
+                       struct wpa_bss *bss = NULL;
+                       struct wpa_ssid *ssid = wpa_s->current_ssid;
+                       if (ssid->ssid_len > 0)
+                               bss = wpa_bss_get(wpa_s, bssid,
+                                                 ssid->ssid, ssid->ssid_len);
+                       if (!bss)
+                               bss = wpa_bss_get_bssid(wpa_s, bssid);
+                       if (bss)
+                               wpa_s->current_bss = bss;
+               }
        }
 
+#ifdef CONFIG_SME
+       os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN);
+       wpa_s->sme.prev_bssid_set = 1;
+#endif /* CONFIG_SME */
+
        wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid));
        if (wpa_s->current_ssid) {
                /* When using scanning (ap_scan=1), SIM PC/SC interface can be
@@ -1001,7 +1085,9 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
        eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
        wpa_s->eapol_received = 0;
        if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
-           wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
+           wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE ||
+           (wpa_s->current_ssid &&
+            wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) {
                wpa_supplicant_cancel_auth_timeout(wpa_s);
                wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
        } else if (!ft_completed) {
@@ -1338,8 +1424,11 @@ void wpa_supplicant_event(void *ctx, wpa_event_type event,
        case EVENT_ASSOC:
                wpa_supplicant_event_assoc(wpa_s, data);
                break;
-       case EVENT_DEAUTH:
        case EVENT_DISASSOC:
+               if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
+                       sme_event_disassoc(wpa_s, data);
+               /* fall through */
+       case EVENT_DEAUTH:
                wpa_supplicant_event_disassoc(wpa_s);
                break;
        case EVENT_MICHAEL_MIC_FAILURE:
@@ -1347,7 +1436,7 @@ void wpa_supplicant_event(void *ctx, wpa_event_type event,
                break;
 #ifndef CONFIG_NO_SCAN_PROCESSING
        case EVENT_SCAN_RESULTS:
-               wpa_supplicant_event_scan_results(wpa_s);
+               wpa_supplicant_event_scan_results(wpa_s, data);
                break;
 #endif /* CONFIG_NO_SCAN_PROCESSING */
        case EVENT_ASSOCINFO:
@@ -1383,6 +1472,50 @@ void wpa_supplicant_event(void *ctx, wpa_event_type event,
        case EVENT_ASSOC_TIMED_OUT:
                sme_event_assoc_timed_out(wpa_s, data);
                break;
+#ifdef CONFIG_AP
+       case EVENT_TX_STATUS:
+               if (wpa_s->ap_iface == NULL)
+                       break;
+               switch (data->tx_status.type) {
+               case WLAN_FC_TYPE_MGMT:
+                       ap_mgmt_tx_cb(wpa_s, data->tx_status.data,
+                                     data->tx_status.data_len,
+                                     data->tx_status.stype,
+                                     data->tx_status.ack);
+                       break;
+               case WLAN_FC_TYPE_DATA:
+                       ap_tx_status(wpa_s, data->tx_status.dst,
+                                    data->tx_status.data,
+                                    data->tx_status.data_len,
+                                    data->tx_status.ack);
+                       break;
+               }
+               break;
+       case EVENT_RX_FROM_UNKNOWN:
+               if (wpa_s->ap_iface == NULL)
+                       break;
+               ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.hdr,
+                                      data->rx_from_unknown.len);
+               break;
+       case EVENT_RX_MGMT:
+               if (wpa_s->ap_iface == NULL)
+                       break;
+               ap_mgmt_rx(wpa_s, &data->rx_mgmt);
+               break;
+#endif /* CONFIG_AP */
+#ifdef CONFIG_CLIENT_MLME
+       case EVENT_MLME_RX: {
+               struct ieee80211_rx_status rx_status;
+               os_memset(&rx_status, 0, sizeof(rx_status));
+               rx_status.freq = data->mlme_rx.freq;
+               rx_status.channel = data->mlme_rx.channel;
+               rx_status.ssi = data->mlme_rx.ssi;
+               ieee80211_sta_rx(wpa_s, data->mlme_rx.buf, data->mlme_rx.len,
+                                &rx_status);
+               break;
+       }
+#endif /* CONFIG_CLIENT_MLME */
+
        default:
                wpa_printf(MSG_INFO, "Unknown event %d", event);
                break;