Merge branch 'moonshot' of ssh://moonshot.suchdamage.org:822/srv/git/libeap into...
[libeap.git] / wpa_supplicant / mlme.c
index e894c46..eb60ac5 100644 (file)
 #include "eloop.h"
 #include "config_ssid.h"
 #include "wpa_supplicant_i.h"
+#include "notify.h"
 #include "driver_i.h"
-#include "wpa.h"
-#include "ieee802_11_defs.h"
-#include "ieee802_11_common.h"
+#include "rsn_supp/wpa.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
 #include "mlme.h"
 
 
@@ -95,10 +96,12 @@ static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s);
 static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx);
 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx);
 static void ieee80211_build_tspec(struct wpabuf *buf);
+static int ieee80211_sta_set_probe_req_ie(struct wpa_supplicant *wpa_s,
+                                         const u8 *ies, size_t ies_len);
 
 
 static int ieee80211_sta_set_channel(struct wpa_supplicant *wpa_s,
-                                    hostapd_hw_mode phymode, int chan,
+                                    enum hostapd_hw_mode phymode, int chan,
                                     int freq)
 {
        size_t i;
@@ -129,11 +132,11 @@ static int ecw2cw(int ecw)
 
 
 static void ieee80211_sta_wmm_params(struct wpa_supplicant *wpa_s,
-                                    u8 *wmm_param, size_t wmm_param_len)
+                                    const u8 *wmm_param, size_t wmm_param_len)
 {
        size_t left;
        int count;
-       u8 *pos;
+       const u8 *pos;
        u8 wmm_acm;
 
        if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
@@ -201,6 +204,7 @@ static void ieee80211_set_associated(struct wpa_supplicant *wpa_s, int assoc)
                data.assoc_info.req_ies_len = wpa_s->mlme.assocreq_ies_len;
                data.assoc_info.resp_ies = wpa_s->mlme.assocresp_ies;
                data.assoc_info.resp_ies_len = wpa_s->mlme.assocresp_ies_len;
+               data.assoc_info.freq = wpa_s->mlme.freq;
                wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
        } else {
                wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL);
@@ -217,8 +221,8 @@ static int ieee80211_sta_tx(struct wpa_supplicant *wpa_s, const u8 *buf,
 
 
 static void ieee80211_send_auth(struct wpa_supplicant *wpa_s,
-                               int transaction, u8 *extra, size_t extra_len,
-                               int encrypt)
+                               int transaction, const u8 *extra,
+                               size_t extra_len, int encrypt)
 {
        u8 *buf;
        size_t len;
@@ -390,20 +394,16 @@ static void ieee80211_send_assoc(struct wpa_supplicant *wpa_s)
        blen += len + 2;
        *pos++ = WLAN_EID_SUPP_RATES;
        *pos++ = len;
-       for (i = 0; i < len; i++) {
-               int rate = wpa_s->mlme.curr_rates[i].rate;
-               *pos++ = (u8) (rate / 5);
-       }
+       for (i = 0; i < len; i++)
+               *pos++ = (u8) (wpa_s->mlme.curr_rates[i] / 5);
 
        if (wpa_s->mlme.num_curr_rates > len) {
                pos = buf + blen;
                blen += wpa_s->mlme.num_curr_rates - len + 2;
                *pos++ = WLAN_EID_EXT_SUPP_RATES;
                *pos++ = wpa_s->mlme.num_curr_rates - len;
-               for (i = len; i < wpa_s->mlme.num_curr_rates; i++) {
-                       int rate = wpa_s->mlme.curr_rates[i].rate;
-                       *pos++ = (u8) (rate / 5);
-               }
+               for (i = len; i < wpa_s->mlme.num_curr_rates; i++)
+                       *pos++ = (u8) (wpa_s->mlme.curr_rates[i] / 5);
        }
 
        if (wpa_s->mlme.extra_ie && wpa_s->mlme.auth_alg != WLAN_AUTH_FT) {
@@ -670,7 +670,6 @@ static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s,
        supp_rates[0] = WLAN_EID_SUPP_RATES;
        supp_rates[1] = 0;
        for (i = 0; i < wpa_s->mlme.num_curr_rates; i++) {
-               struct hostapd_rate_data *rate = &wpa_s->mlme.curr_rates[i];
                if (esupp_rates) {
                        pos = buf + len;
                        len++;
@@ -686,7 +685,7 @@ static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s,
                        len++;
                        supp_rates[1]++;
                }
-               *pos++ = rate->rate / 5;
+               *pos++ = wpa_s->mlme.curr_rates[i] / 5;
        }
 
        if (wpa_s->mlme.extra_probe_ie) {
@@ -755,7 +754,7 @@ static void ieee80211_rx_mgmt_auth(struct wpa_supplicant *wpa_s,
        u16 auth_alg, auth_transaction, status_code;
        int adhoc;
 
-       adhoc = ssid && ssid->mode == 1;
+       adhoc = ssid && ssid->mode == WPAS_MODE_IBSS;
 
        if (wpa_s->mlme.state != IEEE80211_AUTHENTICATE && !adhoc) {
                wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
@@ -828,12 +827,11 @@ static void ieee80211_rx_mgmt_auth(struct wpa_supplicant *wpa_s,
                        u8 algs[num_algs];
                        int i, pos;
                        algs[0] = algs[1] = algs[2] = 0xff;
-                       if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN)
+                       if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_OPEN)
                                algs[0] = WLAN_AUTH_OPEN;
-                       if (wpa_s->mlme.auth_algs &
-                           IEEE80211_AUTH_ALG_SHARED_KEY)
+                       if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_SHARED)
                                algs[1] = WLAN_AUTH_SHARED_KEY;
-                       if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP)
+                       if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_LEAP)
                                algs[2] = WLAN_AUTH_LEAP;
                        if (wpa_s->mlme.auth_alg == WLAN_AUTH_OPEN)
                                pos = 0;
@@ -998,45 +996,6 @@ static void ieee80211_rx_mgmt_disassoc(struct wpa_supplicant *wpa_s,
 }
 
 
-static int ieee80211_ft_assoc_resp(struct wpa_supplicant *wpa_s,
-                                  struct ieee802_11_elems *elems)
-{
-#ifdef CONFIG_IEEE80211R
-       const u8 *mobility_domain = NULL;
-       const u8 *r0kh_id = NULL;
-       size_t r0kh_id_len = 0;
-       const u8 *r1kh_id = NULL;
-       struct rsn_ftie *hdr;
-       const u8 *pos, *end;
-
-       if (elems->mdie && elems->mdie_len >= MOBILITY_DOMAIN_ID_LEN)
-               mobility_domain = elems->mdie;
-       if (elems->ftie && elems->ftie_len >= sizeof(struct rsn_ftie)) {
-               end = elems->ftie + elems->ftie_len;
-               hdr = (struct rsn_ftie *) elems->ftie;
-               pos = (const u8 *) (hdr + 1);
-               while (pos + 1 < end) {
-                       if (pos + 2 + pos[1] > end)
-                               break;
-                       if (pos[0] == FTIE_SUBELEM_R1KH_ID &&
-                           pos[1] == FT_R1KH_ID_LEN)
-                               r1kh_id = pos + 2;
-                       else if (pos[0] == FTIE_SUBELEM_R0KH_ID &&
-                                pos[1] >= 1 && pos[1] <= FT_R0KH_ID_MAX_LEN) {
-                               r0kh_id = pos + 2;
-                               r0kh_id_len = pos[1];
-                       }
-                       pos += 2 + pos[1];
-               }
-       }
-       return wpa_sm_set_ft_params(wpa_s->wpa, mobility_domain, r0kh_id,
-                                   r0kh_id_len, r1kh_id);
-#else /* CONFIG_IEEE80211R */
-       return 0;
-#endif /* CONFIG_IEEE80211R */
-}
-
-
 static void ieee80211_build_tspec(struct wpabuf *buf)
 {
        struct wmm_tspec_element *tspec;
@@ -1196,7 +1155,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
                                   "Resp failed");
                        return;
                }
-       } else if (ieee80211_ft_assoc_resp(wpa_s, &elems) < 0)
+       } else if (wpa_sm_set_ft_params(wpa_s->wpa, pos,
+                                       len - (pos - (u8 *) mgmt)) < 0)
                return;
 
        wpa_printf(MSG_DEBUG, "MLME: associated");
@@ -1686,7 +1646,7 @@ static void ieee80211_rx_mgmt_probe_req(struct wpa_supplicant *wpa_s,
        u8 *pos, *end;
        struct wpa_ssid *ssid = wpa_s->current_ssid;
 
-       adhoc = ssid && ssid->mode == 1;
+       adhoc = ssid && ssid->mode == WPAS_MODE_IBSS;
 
        if (!adhoc || wpa_s->mlme.state != IEEE80211_IBSS_JOINED ||
            len < 24 + 2 || wpa_s->mlme.probe_resp == NULL)
@@ -1781,7 +1741,6 @@ static void ieee80211_rx_mgmt_ft_action(struct wpa_supplicant *wpa_s,
                wpa_printf(MSG_DEBUG, "MLME: Foreign STA Address " MACSTR
                           " in FT Action Response", MAC2STR(sta_addr));
                return;
-                          
        }
 
        if (status) {
@@ -2017,6 +1976,14 @@ static void ieee80211_rx_mgmt_action(struct wpa_supplicant *wpa_s,
        case WLAN_ACTION_WMM:
                ieee80211_rx_mgmt_wmm_action(wpa_s, mgmt, len, rx_status);
                break;
+       case WLAN_ACTION_PUBLIC:
+               if (wpa_s->mlme.public_action_cb) {
+                       wpa_s->mlme.public_action_cb(
+                               wpa_s->mlme.public_action_cb_ctx,
+                               (u8 *) mgmt, len, rx_status->freq);
+                       return;
+               }
+               break;
        default:
                wpa_printf(MSG_DEBUG, "MLME: unknown Action Category %d",
                           mgmt->u.action.category);
@@ -2136,6 +2103,8 @@ static void ieee80211_sta_expire(struct wpa_supplicant *wpa_s)
 
 static void ieee80211_sta_merge_ibss(struct wpa_supplicant *wpa_s)
 {
+       struct wpa_driver_scan_params params;
+
        ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL);
 
        ieee80211_sta_expire(wpa_s);
@@ -2144,7 +2113,11 @@ static void ieee80211_sta_merge_ibss(struct wpa_supplicant *wpa_s)
 
        wpa_printf(MSG_DEBUG, "MLME: No active IBSS STAs - trying to scan for "
                   "other IBSS networks with same SSID (merge)");
-       ieee80211_sta_req_scan(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
+       os_memset(&params, 0, sizeof(params));
+       params.ssids[0].ssid = wpa_s->mlme.ssid;
+       params.ssids[0].ssid_len = wpa_s->mlme.ssid_len;
+       params.num_ssids = wpa_s->mlme.ssid_len ? 1 : 0;
+       ieee80211_sta_req_scan(wpa_s, &params);
 }
 
 
@@ -2189,7 +2162,7 @@ static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx)
 static void ieee80211_sta_new_auth(struct wpa_supplicant *wpa_s)
 {
        struct wpa_ssid *ssid = wpa_s->current_ssid;
-       if (ssid && ssid->mode != 0)
+       if (ssid && ssid->mode != WPAS_MODE_INFRA)
                return;
 
 #if 0 /* FIX */
@@ -2202,11 +2175,11 @@ static void ieee80211_sta_new_auth(struct wpa_supplicant *wpa_s)
        wpa_s->mlme.wmm_last_param_set = -1; /* allow any WMM update */
 
 
-       if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN)
+       if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_OPEN)
                wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN;
-       else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
+       else if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_SHARED)
                wpa_s->mlme.auth_alg = WLAN_AUTH_SHARED_KEY;
-       else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP)
+       else if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_LEAP)
                wpa_s->mlme.auth_alg = WLAN_AUTH_LEAP;
        else
                wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN;
@@ -2246,7 +2219,7 @@ static int ieee80211_ibss_allowed(struct wpa_supplicant *wpa_s)
 static int ieee80211_sta_join_ibss(struct wpa_supplicant *wpa_s,
                                   struct ieee80211_sta_bss *bss)
 {
-       int res = 0, rates, done = 0;
+       int res = 0, rates, done = 0, bssid_changed;
        struct ieee80211_mgmt *mgmt;
 #if 0 /* FIX */
        struct ieee80211_tx_control control;
@@ -2265,7 +2238,10 @@ static int ieee80211_sta_join_ibss(struct wpa_supplicant *wpa_s,
                local->hw->reset_tsf(local->mdev);
        }
 #endif
+       bssid_changed = os_memcmp(wpa_s->bssid, bss->bssid, ETH_ALEN);
        os_memcpy(wpa_s->bssid, bss->bssid, ETH_ALEN);
+       if (bssid_changed)
+               wpas_notify_bssid_changed(wpa_s);
 
 #if 0 /* FIX */
        local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
@@ -2396,7 +2372,7 @@ static int ieee80211_sta_join_ibss(struct wpa_supplicant *wpa_s,
                        if (local->conf.phymode == MODE_ATHEROS_TURBO)
                                rate *= 2;
                        for (j = 0; j < local->num_curr_rates; j++)
-                               if (local->curr_rates[j].rate == rate)
+                               if (local->curr_rates[j] == rate)
                                        rates |= BIT(j);
                }
                wpa_s->mlme.supp_rates_bits = rates;
@@ -2465,7 +2441,7 @@ static int ieee80211_sta_create_ibss(struct wpa_supplicant *wpa_s)
        pos = bss->supp_rates;
 #if 0 /* FIX */
        for (i = 0; i < local->num_curr_rates; i++) {
-               int rate = local->curr_rates[i].rate;
+               int rate = local->curr_rates[i];
                if (local->conf.phymode == MODE_ATHEROS_TURBO)
                        rate /= 2;
                *pos++ = (u8) (rate / 5);
@@ -2581,11 +2557,17 @@ int ieee80211_sta_associate(struct wpa_supplicant *wpa_s,
                            struct wpa_driver_associate_params *params)
 {
        struct ieee80211_sta_bss *bss;
+       int bssid_changed;
 
        wpa_s->mlme.bssid_set = 0;
        wpa_s->mlme.freq = params->freq;
        if (params->bssid) {
+               bssid_changed = os_memcmp(wpa_s->bssid, params->bssid,
+                                         ETH_ALEN);
                os_memcpy(wpa_s->bssid, params->bssid, ETH_ALEN);
+               if (bssid_changed)
+                       wpas_notify_bssid_changed(wpa_s);
+
                if (!is_zero_ether_addr(params->bssid))
                        wpa_s->mlme.bssid_set = 1;
                bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
@@ -2652,7 +2634,7 @@ int ieee80211_sta_associate(struct wpa_supplicant *wpa_s,
        ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode,
                                  wpa_s->mlme.channel, wpa_s->mlme.freq);
 
-       if (params->mode == 1 && !wpa_s->mlme.bssid_set) {
+       if (params->mode == WPAS_MODE_IBSS && !wpa_s->mlme.bssid_set) {
                os_get_time(&wpa_s->mlme.ibss_join_req);
                wpa_s->mlme.state = IEEE80211_IBSS_SEARCH;
                return ieee80211_sta_find_ibss(wpa_s);
@@ -2759,6 +2741,17 @@ static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx)
                     mode->mode == HOSTAPD_MODE_IEEE80211B &&
                     wpa_s->mlme.scan_skip_11b))
                        skip = 1;
+               if (!skip && wpa_s->mlme.scan_freqs) {
+                       int i, found = 0;
+                       for (i = 0; wpa_s->mlme.scan_freqs[i]; i++) {
+                               if (wpa_s->mlme.scan_freqs[i] == chan->freq) {
+                                       found = 1;
+                                       break;
+                               }
+                       }
+                       if (!found)
+                               skip = 1;
+               }
 
                if (!skip) {
                        wpa_printf(MSG_MSGDUMP,
@@ -2812,9 +2805,12 @@ static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx)
 }
 
 
-int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s, const u8 *ssid,
-                          size_t ssid_len)
+int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s,
+                          struct wpa_driver_scan_params *params)
 {
+       const u8 *ssid = params->ssids[0].ssid;
+       size_t ssid_len = params->ssids[0].ssid_len;
+
        if (ssid_len > MAX_SSID_LEN)
                return -1;
 
@@ -2843,6 +2839,21 @@ int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s, const u8 *ssid,
 
        wpa_printf(MSG_DEBUG, "MLME: starting scan");
 
+       ieee80211_sta_set_probe_req_ie(wpa_s, params->extra_ies,
+                                      params->extra_ies_len);
+
+       os_free(wpa_s->mlme.scan_freqs);
+       if (params->freqs) {
+               int i;
+               for (i = 0; params->freqs[i]; i++)
+                       ;
+               wpa_s->mlme.scan_freqs = os_malloc((i + 1) * sizeof(int));
+               if (wpa_s->mlme.scan_freqs)
+                       os_memcpy(wpa_s->mlme.scan_freqs, params->freqs,
+                                 (i + 1) * sizeof(int));
+       } else
+               wpa_s->mlme.scan_freqs = NULL;
+
        ieee80211_sta_save_oper_chan(wpa_s);
 
        wpa_s->mlme.sta_scanning = 1;
@@ -3080,6 +3091,9 @@ void ieee80211_sta_deinit(struct wpa_supplicant *wpa_s)
        wpa_s->mlme.ft_ies = NULL;
        wpa_s->mlme.ft_ies_len = 0;
 #endif /* CONFIG_IEEE80211R */
+
+       os_free(wpa_s->mlme.scan_freqs);
+       wpa_s->mlme.scan_freqs = NULL;
 }
 
 
@@ -3163,8 +3177,8 @@ int ieee80211_sta_send_ft_action(struct wpa_supplicant *wpa_s, u8 action,
 #endif /* CONFIG_IEEE80211R */
 
 
-int ieee80211_sta_set_probe_req_ie(struct wpa_supplicant *wpa_s, const u8 *ies,
-                                  size_t ies_len)
+static int ieee80211_sta_set_probe_req_ie(struct wpa_supplicant *wpa_s,
+                                         const u8 *ies, size_t ies_len)
 {
        os_free(wpa_s->mlme.extra_probe_ie);
        wpa_s->mlme.extra_probe_ie = NULL;