mlme.c
Go to the documentation of this file.
00001 /*
00002  * WPA Supplicant - Client mode MLME
00003  * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
00004  * Copyright (c) 2004, Instant802 Networks, Inc.
00005  * Copyright (c) 2005-2006, Devicescape Software, Inc.
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License version 2 as
00009  * published by the Free Software Foundation.
00010  *
00011  * Alternatively, this software may be distributed under the terms of BSD
00012  * license.
00013  *
00014  * See README and COPYING for more details.
00015  */
00016 
00017 #include "includes.h"
00018 
00019 #include "common.h"
00020 #include "eloop.h"
00021 #include "config_ssid.h"
00022 #include "wpa_supplicant_i.h"
00023 #include "notify.h"
00024 #include "driver_i.h"
00025 #include "rsn_supp/wpa.h"
00026 #include "common/ieee802_11_defs.h"
00027 #include "common/ieee802_11_common.h"
00028 #include "mlme.h"
00029 
00030 
00031 /* Timeouts and intervals in milliseconds */
00032 #define IEEE80211_AUTH_TIMEOUT (200)
00033 #define IEEE80211_AUTH_MAX_TRIES 3
00034 #define IEEE80211_ASSOC_TIMEOUT (200)
00035 #define IEEE80211_ASSOC_MAX_TRIES 3
00036 #define IEEE80211_MONITORING_INTERVAL (2000)
00037 #define IEEE80211_PROBE_INTERVAL (60000)
00038 #define IEEE80211_RETRY_AUTH_INTERVAL (1000)
00039 #define IEEE80211_SCAN_INTERVAL (2000)
00040 #define IEEE80211_SCAN_INTERVAL_SLOW (15000)
00041 #define IEEE80211_IBSS_JOIN_TIMEOUT (20000)
00042 
00043 #define IEEE80211_PROBE_DELAY (33)
00044 #define IEEE80211_CHANNEL_TIME (33)
00045 #define IEEE80211_PASSIVE_CHANNEL_TIME (200)
00046 #define IEEE80211_SCAN_RESULT_EXPIRE (10000)
00047 #define IEEE80211_IBSS_MERGE_INTERVAL (30000)
00048 #define IEEE80211_IBSS_INACTIVITY_LIMIT (60000)
00049 
00050 #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
00051 
00052 
00053 #define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
00054 
00055 
00056 struct ieee80211_sta_bss {
00057         struct ieee80211_sta_bss *next;
00058         struct ieee80211_sta_bss *hnext;
00059 
00060         u8 bssid[ETH_ALEN];
00061         u8 ssid[MAX_SSID_LEN];
00062         size_t ssid_len;
00063         u16 capability; /* host byte order */
00064         int hw_mode;
00065         int channel;
00066         int freq;
00067         int rssi;
00068         u8 *ie;
00069         size_t ie_len;
00070         u8 *wpa_ie;
00071         size_t wpa_ie_len;
00072         u8 *rsn_ie;
00073         size_t rsn_ie_len;
00074         u8 *wmm_ie;
00075         size_t wmm_ie_len;
00076         u8 *mdie;
00077         size_t mdie_len;
00078 #define IEEE80211_MAX_SUPP_RATES 32
00079         u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
00080         size_t supp_rates_len;
00081         int beacon_int;
00082         u64 timestamp;
00083 
00084         int probe_resp;
00085         struct os_time last_update;
00086 };
00087 
00088 
00089 static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s,
00090                                      const u8 *dst,
00091                                      const u8 *ssid, size_t ssid_len);
00092 static struct ieee80211_sta_bss *
00093 ieee80211_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid);
00094 static int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s);
00095 static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s);
00096 static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx);
00097 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx);
00098 static void ieee80211_build_tspec(struct wpabuf *buf);
00099 static int ieee80211_sta_set_probe_req_ie(struct wpa_supplicant *wpa_s,
00100                                           const u8 *ies, size_t ies_len);
00101 
00102 
00103 static int ieee80211_sta_set_channel(struct wpa_supplicant *wpa_s,
00104                                      enum hostapd_hw_mode phymode, int chan,
00105                                      int freq)
00106 {
00107         size_t i;
00108         struct hostapd_hw_modes *mode;
00109 
00110         for (i = 0; i < wpa_s->mlme.num_modes; i++) {
00111                 mode = &wpa_s->mlme.modes[i];
00112                 if (mode->mode == phymode) {
00113                         wpa_s->mlme.curr_rates = mode->rates;
00114                         wpa_s->mlme.num_curr_rates = mode->num_rates;
00115                         break;
00116                 }
00117         }
00118 
00119         return wpa_drv_set_channel(wpa_s, phymode, chan, freq);
00120 }
00121 
00122 
00123 static int ecw2cw(int ecw)
00124 {
00125         int cw = 1;
00126         while (ecw > 0) {
00127                 cw <<= 1;
00128                 ecw--;
00129         }
00130         return cw - 1;
00131 }
00132 
00133 
00134 static void ieee80211_sta_wmm_params(struct wpa_supplicant *wpa_s,
00135                                      const u8 *wmm_param, size_t wmm_param_len)
00136 {
00137         size_t left;
00138         int count;
00139         const u8 *pos;
00140         u8 wmm_acm;
00141 
00142         if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
00143                 return;
00144         count = wmm_param[6] & 0x0f;
00145         if (count == wpa_s->mlme.wmm_last_param_set)
00146                 return;
00147         wpa_s->mlme.wmm_last_param_set = count;
00148 
00149         pos = wmm_param + 8;
00150         left = wmm_param_len - 8;
00151 
00152         wmm_acm = 0;
00153         for (; left >= 4; left -= 4, pos += 4) {
00154                 int aci = (pos[0] >> 5) & 0x03;
00155                 int acm = (pos[0] >> 4) & 0x01;
00156                 int aifs, cw_max, cw_min, burst_time;
00157 
00158                 switch (aci) {
00159                 case 1: /* AC_BK */
00160                         if (acm)
00161                                 wmm_acm |= BIT(1) | BIT(2); /* BK/- */
00162                         break;
00163                 case 2: /* AC_VI */
00164                         if (acm)
00165                                 wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
00166                         break;
00167                 case 3: /* AC_VO */
00168                         if (acm)
00169                                 wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
00170                         break;
00171                 case 0: /* AC_BE */
00172                 default:
00173                         if (acm)
00174                                 wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
00175                         break;
00176                 }
00177 
00178                 aifs = pos[0] & 0x0f;
00179                 cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
00180                 cw_min = ecw2cw(pos[1] & 0x0f);
00181                 /* TXOP is in units of 32 usec; burst_time in 0.1 ms */
00182                 burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
00183                 wpa_printf(MSG_DEBUG, "MLME: WMM aci=%d acm=%d aifs=%d "
00184                            "cWmin=%d cWmax=%d burst=%d",
00185                            aci, acm, aifs, cw_min, cw_max, burst_time);
00186                 /* TODO: driver configuration */
00187         }
00188 }
00189 
00190 
00191 static void ieee80211_set_associated(struct wpa_supplicant *wpa_s, int assoc)
00192 {
00193         if (wpa_s->mlme.associated == assoc && !assoc)
00194                 return;
00195 
00196         wpa_s->mlme.associated = assoc;
00197 
00198         if (assoc) {
00199                 union wpa_event_data data;
00200                 os_memset(&data, 0, sizeof(data));
00201                 wpa_s->mlme.prev_bssid_set = 1;
00202                 os_memcpy(wpa_s->mlme.prev_bssid, wpa_s->bssid, ETH_ALEN);
00203                 data.assoc_info.req_ies = wpa_s->mlme.assocreq_ies;
00204                 data.assoc_info.req_ies_len = wpa_s->mlme.assocreq_ies_len;
00205                 data.assoc_info.resp_ies = wpa_s->mlme.assocresp_ies;
00206                 data.assoc_info.resp_ies_len = wpa_s->mlme.assocresp_ies_len;
00207                 data.assoc_info.freq = wpa_s->mlme.freq;
00208                 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
00209         } else {
00210                 wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL);
00211         }
00212         os_get_time(&wpa_s->mlme.last_probe);
00213 }
00214 
00215 
00216 static int ieee80211_sta_tx(struct wpa_supplicant *wpa_s, const u8 *buf,
00217                             size_t len)
00218 {
00219         return wpa_drv_send_mlme(wpa_s, buf, len);
00220 }
00221 
00222 
00223 static void ieee80211_send_auth(struct wpa_supplicant *wpa_s,
00224                                 int transaction, const u8 *extra,
00225                                 size_t extra_len, int encrypt)
00226 {
00227         u8 *buf;
00228         size_t len;
00229         struct ieee80211_mgmt *mgmt;
00230 
00231         buf = os_malloc(sizeof(*mgmt) + 6 + extra_len);
00232         if (buf == NULL) {
00233                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
00234                            "auth frame");
00235                 return;
00236         }
00237 
00238         mgmt = (struct ieee80211_mgmt *) buf;
00239         len = 24 + 6;
00240         os_memset(mgmt, 0, 24 + 6);
00241         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
00242                                            WLAN_FC_STYPE_AUTH);
00243         if (encrypt)
00244                 mgmt->frame_control |= host_to_le16(WLAN_FC_ISWEP);
00245         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
00246         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
00247         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
00248         mgmt->u.auth.auth_alg = host_to_le16(wpa_s->mlme.auth_alg);
00249         mgmt->u.auth.auth_transaction = host_to_le16(transaction);
00250         wpa_s->mlme.auth_transaction = transaction + 1;
00251         mgmt->u.auth.status_code = host_to_le16(0);
00252         if (extra) {
00253                 os_memcpy(buf + len, extra, extra_len);
00254                 len += extra_len;
00255         }
00256 
00257         ieee80211_sta_tx(wpa_s, buf, len);
00258         os_free(buf);
00259 }
00260 
00261 
00262 static void ieee80211_reschedule_timer(struct wpa_supplicant *wpa_s, int ms)
00263 {
00264         eloop_cancel_timeout(ieee80211_sta_timer, wpa_s, NULL);
00265         eloop_register_timeout(ms / 1000, 1000 * (ms % 1000),
00266                                ieee80211_sta_timer, wpa_s, NULL);
00267 }
00268 
00269 
00270 static void ieee80211_authenticate(struct wpa_supplicant *wpa_s)
00271 {
00272         u8 *extra;
00273         size_t extra_len;
00274 
00275         wpa_s->mlme.auth_tries++;
00276         if (wpa_s->mlme.auth_tries > IEEE80211_AUTH_MAX_TRIES) {
00277                 wpa_printf(MSG_DEBUG, "MLME: authentication with AP " MACSTR
00278                            " timed out", MAC2STR(wpa_s->bssid));
00279                 return;
00280         }
00281 
00282         wpa_s->mlme.state = IEEE80211_AUTHENTICATE;
00283         wpa_printf(MSG_DEBUG, "MLME: authenticate with AP " MACSTR,
00284                    MAC2STR(wpa_s->bssid));
00285 
00286         extra = NULL;
00287         extra_len = 0;
00288 
00289 #ifdef CONFIG_IEEE80211R
00290         if ((wpa_s->mlme.key_mgmt == KEY_MGMT_FT_802_1X ||
00291              wpa_s->mlme.key_mgmt == KEY_MGMT_FT_PSK) &&
00292             wpa_s->mlme.ft_ies) {
00293                 struct ieee80211_sta_bss *bss;
00294                 struct rsn_mdie *mdie = NULL;
00295                 bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
00296                 if (bss && bss->mdie_len >= 2 + sizeof(*mdie))
00297                         mdie = (struct rsn_mdie *) (bss->mdie + 2);
00298                 if (mdie &&
00299                     os_memcmp(mdie->mobility_domain, wpa_s->mlme.current_md,
00300                               MOBILITY_DOMAIN_ID_LEN) == 0) {
00301                         wpa_printf(MSG_DEBUG, "MLME: Trying to use FT "
00302                                    "over-the-air");
00303                         wpa_s->mlme.auth_alg = WLAN_AUTH_FT;
00304                         extra = wpa_s->mlme.ft_ies;
00305                         extra_len = wpa_s->mlme.ft_ies_len;
00306                 }
00307         }
00308 #endif /* CONFIG_IEEE80211R */
00309 
00310         ieee80211_send_auth(wpa_s, 1, extra, extra_len, 0);
00311 
00312         ieee80211_reschedule_timer(wpa_s, IEEE80211_AUTH_TIMEOUT);
00313 }
00314 
00315 
00316 static void ieee80211_send_assoc(struct wpa_supplicant *wpa_s)
00317 {
00318         struct ieee80211_mgmt *mgmt;
00319         u8 *pos, *ies, *buf;
00320         int i, len;
00321         u16 capab;
00322         struct ieee80211_sta_bss *bss;
00323         int wmm = 0;
00324         size_t blen, buflen;
00325 
00326         if (wpa_s->mlme.curr_rates == NULL) {
00327                 wpa_printf(MSG_DEBUG, "MLME: curr_rates not set for assoc");
00328                 return;
00329         }
00330 
00331         buflen = sizeof(*mgmt) + 200 + wpa_s->mlme.extra_ie_len +
00332                 wpa_s->mlme.ssid_len;
00333 #ifdef CONFIG_IEEE80211R
00334         if (wpa_s->mlme.ft_ies)
00335                 buflen += wpa_s->mlme.ft_ies_len;
00336 #endif /* CONFIG_IEEE80211R */
00337         buf = os_malloc(buflen);
00338         if (buf == NULL) {
00339                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
00340                            "assoc frame");
00341                 return;
00342         }
00343         blen = 0;
00344 
00345         capab = wpa_s->mlme.capab;
00346         if (wpa_s->mlme.phymode == HOSTAPD_MODE_IEEE80211G) {
00347                 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
00348                         WLAN_CAPABILITY_SHORT_PREAMBLE;
00349         }
00350         bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
00351         if (bss) {
00352                 if (bss->capability & WLAN_CAPABILITY_PRIVACY)
00353                         capab |= WLAN_CAPABILITY_PRIVACY;
00354                 if (bss->wmm_ie) {
00355                         wmm = 1;
00356                 }
00357         }
00358 
00359         mgmt = (struct ieee80211_mgmt *) buf;
00360         blen += 24;
00361         os_memset(mgmt, 0, 24);
00362         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
00363         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
00364         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
00365 
00366         if (wpa_s->mlme.prev_bssid_set) {
00367                 blen += 10;
00368                 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
00369                                                    WLAN_FC_STYPE_REASSOC_REQ);
00370                 mgmt->u.reassoc_req.capab_info = host_to_le16(capab);
00371                 mgmt->u.reassoc_req.listen_interval = host_to_le16(1);
00372                 os_memcpy(mgmt->u.reassoc_req.current_ap,
00373                           wpa_s->mlme.prev_bssid,
00374                           ETH_ALEN);
00375         } else {
00376                 blen += 4;
00377                 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
00378                                                    WLAN_FC_STYPE_ASSOC_REQ);
00379                 mgmt->u.assoc_req.capab_info = host_to_le16(capab);
00380                 mgmt->u.assoc_req.listen_interval = host_to_le16(1);
00381         }
00382 
00383         /* SSID */
00384         ies = pos = buf + blen;
00385         blen += 2 + wpa_s->mlme.ssid_len;
00386         *pos++ = WLAN_EID_SSID;
00387         *pos++ = wpa_s->mlme.ssid_len;
00388         os_memcpy(pos, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
00389 
00390         len = wpa_s->mlme.num_curr_rates;
00391         if (len > 8)
00392                 len = 8;
00393         pos = buf + blen;
00394         blen += len + 2;
00395         *pos++ = WLAN_EID_SUPP_RATES;
00396         *pos++ = len;
00397         for (i = 0; i < len; i++)
00398                 *pos++ = (u8) (wpa_s->mlme.curr_rates[i] / 5);
00399 
00400         if (wpa_s->mlme.num_curr_rates > len) {
00401                 pos = buf + blen;
00402                 blen += wpa_s->mlme.num_curr_rates - len + 2;
00403                 *pos++ = WLAN_EID_EXT_SUPP_RATES;
00404                 *pos++ = wpa_s->mlme.num_curr_rates - len;
00405                 for (i = len; i < wpa_s->mlme.num_curr_rates; i++)
00406                         *pos++ = (u8) (wpa_s->mlme.curr_rates[i] / 5);
00407         }
00408 
00409         if (wpa_s->mlme.extra_ie && wpa_s->mlme.auth_alg != WLAN_AUTH_FT) {
00410                 pos = buf + blen;
00411                 blen += wpa_s->mlme.extra_ie_len;
00412                 os_memcpy(pos, wpa_s->mlme.extra_ie, wpa_s->mlme.extra_ie_len);
00413         }
00414 
00415 #ifdef CONFIG_IEEE80211R
00416         if ((wpa_s->mlme.key_mgmt == KEY_MGMT_FT_802_1X ||
00417              wpa_s->mlme.key_mgmt == KEY_MGMT_FT_PSK) &&
00418             wpa_s->mlme.auth_alg != WLAN_AUTH_FT &&
00419             bss && bss->mdie &&
00420             bss->mdie_len >= 2 + sizeof(struct rsn_mdie) &&
00421             bss->mdie[1] >= sizeof(struct rsn_mdie)) {
00422                 pos = buf + blen;
00423                 blen += 2 + sizeof(struct rsn_mdie);
00424                 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
00425                 *pos++ = sizeof(struct rsn_mdie);
00426                 os_memcpy(pos, bss->mdie + 2, MOBILITY_DOMAIN_ID_LEN);
00427                 pos += MOBILITY_DOMAIN_ID_LEN;
00428                 *pos++ = 0; /* FIX: copy from the target AP's MDIE */
00429         }
00430 
00431         if ((wpa_s->mlme.key_mgmt == KEY_MGMT_FT_802_1X ||
00432              wpa_s->mlme.key_mgmt == KEY_MGMT_FT_PSK) &&
00433             wpa_s->mlme.auth_alg == WLAN_AUTH_FT && wpa_s->mlme.ft_ies) {
00434                 pos = buf + blen;
00435                 os_memcpy(pos, wpa_s->mlme.ft_ies, wpa_s->mlme.ft_ies_len);
00436                 pos += wpa_s->mlme.ft_ies_len;
00437                 blen += wpa_s->mlme.ft_ies_len;
00438         }
00439 #endif /* CONFIG_IEEE80211R */
00440 
00441         if (wmm && wpa_s->mlme.wmm_enabled) {
00442                 pos = buf + blen;
00443                 blen += 9;
00444                 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
00445                 *pos++ = 7; /* len */
00446                 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
00447                 *pos++ = 0x50;
00448                 *pos++ = 0xf2;
00449                 *pos++ = 2; /* WMM */
00450                 *pos++ = 0; /* WMM info */
00451                 *pos++ = 1; /* WMM ver */
00452                 *pos++ = 0;
00453         }
00454 
00455         os_free(wpa_s->mlme.assocreq_ies);
00456         wpa_s->mlme.assocreq_ies_len = (buf + blen) - ies;
00457         wpa_s->mlme.assocreq_ies = os_malloc(wpa_s->mlme.assocreq_ies_len);
00458         if (wpa_s->mlme.assocreq_ies) {
00459                 os_memcpy(wpa_s->mlme.assocreq_ies, ies,
00460                           wpa_s->mlme.assocreq_ies_len);
00461         }
00462 
00463         ieee80211_sta_tx(wpa_s, buf, blen);
00464         os_free(buf);
00465 }
00466 
00467 
00468 static void ieee80211_send_deauth(struct wpa_supplicant *wpa_s, u16 reason)
00469 {
00470         u8 *buf;
00471         size_t len;
00472         struct ieee80211_mgmt *mgmt;
00473 
00474         buf = os_zalloc(sizeof(*mgmt));
00475         if (buf == NULL) {
00476                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
00477                            "deauth frame");
00478                 return;
00479         }
00480 
00481         mgmt = (struct ieee80211_mgmt *) buf;
00482         len = 24;
00483         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
00484         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
00485         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
00486         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
00487                                            WLAN_FC_STYPE_DEAUTH);
00488         len += 2;
00489         mgmt->u.deauth.reason_code = host_to_le16(reason);
00490 
00491         ieee80211_sta_tx(wpa_s, buf, len);
00492         os_free(buf);
00493 }
00494 
00495 
00496 static void ieee80211_send_disassoc(struct wpa_supplicant *wpa_s, u16 reason)
00497 {
00498         u8 *buf;
00499         size_t len;
00500         struct ieee80211_mgmt *mgmt;
00501 
00502         buf = os_zalloc(sizeof(*mgmt));
00503         if (buf == NULL) {
00504                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
00505                            "disassoc frame");
00506                 return;
00507         }
00508 
00509         mgmt = (struct ieee80211_mgmt *) buf;
00510         len = 24;
00511         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
00512         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
00513         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
00514         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
00515                                            WLAN_FC_STYPE_DISASSOC);
00516         len += 2;
00517         mgmt->u.disassoc.reason_code = host_to_le16(reason);
00518 
00519         ieee80211_sta_tx(wpa_s, buf, len);
00520         os_free(buf);
00521 }
00522 
00523 
00524 static int ieee80211_privacy_mismatch(struct wpa_supplicant *wpa_s)
00525 {
00526         struct ieee80211_sta_bss *bss;
00527         int res = 0;
00528 
00529         if (wpa_s->mlme.mixed_cell ||
00530             wpa_s->mlme.key_mgmt != KEY_MGMT_NONE)
00531                 return 0;
00532 
00533         bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
00534         if (bss == NULL)
00535                 return 0;
00536 
00537         if (ieee80211_sta_wep_configured(wpa_s) !=
00538             !!(bss->capability & WLAN_CAPABILITY_PRIVACY))
00539                 res = 1;
00540 
00541         return res;
00542 }
00543 
00544 
00545 static void ieee80211_associate(struct wpa_supplicant *wpa_s)
00546 {
00547         wpa_s->mlme.assoc_tries++;
00548         if (wpa_s->mlme.assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
00549                 wpa_printf(MSG_DEBUG, "MLME: association with AP " MACSTR
00550                            " timed out", MAC2STR(wpa_s->bssid));
00551                 return;
00552         }
00553 
00554         wpa_s->mlme.state = IEEE80211_ASSOCIATE;
00555         wpa_printf(MSG_DEBUG, "MLME: associate with AP " MACSTR,
00556                    MAC2STR(wpa_s->bssid));
00557         if (ieee80211_privacy_mismatch(wpa_s)) {
00558                 wpa_printf(MSG_DEBUG, "MLME: mismatch in privacy "
00559                            "configuration and mixed-cell disabled - abort "
00560                            "association");
00561                 return;
00562         }
00563 
00564         ieee80211_send_assoc(wpa_s);
00565 
00566         ieee80211_reschedule_timer(wpa_s, IEEE80211_ASSOC_TIMEOUT);
00567 }
00568 
00569 
00570 static void ieee80211_associated(struct wpa_supplicant *wpa_s)
00571 {
00572         int disassoc;
00573 
00574         /* TODO: start monitoring current AP signal quality and number of
00575          * missed beacons. Scan other channels every now and then and search
00576          * for better APs. */
00577         /* TODO: remove expired BSSes */
00578 
00579         wpa_s->mlme.state = IEEE80211_ASSOCIATED;
00580 
00581 #if 0 /* FIX */
00582         sta = sta_info_get(local, wpa_s->bssid);
00583         if (sta == NULL) {
00584                 wpa_printf(MSG_DEBUG "MLME: No STA entry for own AP " MACSTR,
00585                            MAC2STR(wpa_s->bssid));
00586                 disassoc = 1;
00587         } else {
00588                 disassoc = 0;
00589                 if (time_after(jiffies,
00590                                sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
00591                         if (wpa_s->mlme.probereq_poll) {
00592                                 wpa_printf(MSG_DEBUG "MLME: No ProbeResp from "
00593                                            "current AP " MACSTR " - assume "
00594                                            "out of range",
00595                                            MAC2STR(wpa_s->bssid));
00596                                 disassoc = 1;
00597                         } else {
00598                                 ieee80211_send_probe_req(
00599                                         wpa_s->bssid,
00600                                         wpa_s->mlme.scan_ssid,
00601                                         wpa_s->mlme.scan_ssid_len);
00602                                 wpa_s->mlme.probereq_poll = 1;
00603                         }
00604                 } else {
00605                         wpa_s->mlme.probereq_poll = 0;
00606                         if (time_after(jiffies, wpa_s->mlme.last_probe +
00607                                        IEEE80211_PROBE_INTERVAL)) {
00608                                 wpa_s->mlme.last_probe = jiffies;
00609                                 ieee80211_send_probe_req(wpa_s->bssid,
00610                                                          wpa_s->mlme.ssid,
00611                                                          wpa_s->mlme.ssid_len);
00612                         }
00613                 }
00614                 sta_info_release(local, sta);
00615         }
00616 #else
00617         disassoc = 0;
00618 #endif
00619         if (disassoc) {
00620                 wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL);
00621                 ieee80211_reschedule_timer(wpa_s,
00622                                            IEEE80211_MONITORING_INTERVAL +
00623                                            30000);
00624         } else {
00625                 ieee80211_reschedule_timer(wpa_s,
00626                                            IEEE80211_MONITORING_INTERVAL);
00627         }
00628 }
00629 
00630 
00631 static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s,
00632                                      const u8 *dst,
00633                                      const u8 *ssid, size_t ssid_len)
00634 {
00635         u8 *buf;
00636         size_t len;
00637         struct ieee80211_mgmt *mgmt;
00638         u8 *pos, *supp_rates;
00639         u8 *esupp_rates = NULL;
00640         int i;
00641 
00642         buf = os_malloc(sizeof(*mgmt) + 200 + wpa_s->mlme.extra_probe_ie_len);
00643         if (buf == NULL) {
00644                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
00645                            "probe request");
00646                 return;
00647         }
00648 
00649         mgmt = (struct ieee80211_mgmt *) buf;
00650         len = 24;
00651         os_memset(mgmt, 0, 24);
00652         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
00653                                            WLAN_FC_STYPE_PROBE_REQ);
00654         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
00655         if (dst) {
00656                 os_memcpy(mgmt->da, dst, ETH_ALEN);
00657                 os_memcpy(mgmt->bssid, dst, ETH_ALEN);
00658         } else {
00659                 os_memset(mgmt->da, 0xff, ETH_ALEN);
00660                 os_memset(mgmt->bssid, 0xff, ETH_ALEN);
00661         }
00662         pos = buf + len;
00663         len += 2 + ssid_len;
00664         *pos++ = WLAN_EID_SSID;
00665         *pos++ = ssid_len;
00666         os_memcpy(pos, ssid, ssid_len);
00667 
00668         supp_rates = buf + len;
00669         len += 2;
00670         supp_rates[0] = WLAN_EID_SUPP_RATES;
00671         supp_rates[1] = 0;
00672         for (i = 0; i < wpa_s->mlme.num_curr_rates; i++) {
00673                 if (esupp_rates) {
00674                         pos = buf + len;
00675                         len++;
00676                         esupp_rates[1]++;
00677                 } else if (supp_rates[1] == 8) {
00678                         esupp_rates = pos;
00679                         esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
00680                         esupp_rates[1] = 1;
00681                         pos = &esupp_rates[2];
00682                         len += 3;
00683                 } else {
00684                         pos = buf + len;
00685                         len++;
00686                         supp_rates[1]++;
00687                 }
00688                 *pos++ = wpa_s->mlme.curr_rates[i] / 5;
00689         }
00690 
00691         if (wpa_s->mlme.extra_probe_ie) {
00692                 os_memcpy(pos, wpa_s->mlme.extra_probe_ie,
00693                           wpa_s->mlme.extra_probe_ie_len);
00694                 len += wpa_s->mlme.extra_probe_ie_len;
00695         }
00696 
00697         ieee80211_sta_tx(wpa_s, buf, len);
00698         os_free(buf);
00699 }
00700 
00701 
00702 static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s)
00703 {
00704 #if 0 /* FIX */
00705         if (sdata == NULL || sdata->default_key == NULL ||
00706             sdata->default_key->alg != ALG_WEP)
00707                 return 0;
00708         return 1;
00709 #else
00710         return 0;
00711 #endif
00712 }
00713 
00714 
00715 static void ieee80211_auth_completed(struct wpa_supplicant *wpa_s)
00716 {
00717         wpa_printf(MSG_DEBUG, "MLME: authenticated");
00718         wpa_s->mlme.authenticated = 1;
00719         ieee80211_associate(wpa_s);
00720 }
00721 
00722 
00723 static void ieee80211_auth_challenge(struct wpa_supplicant *wpa_s,
00724                                      struct ieee80211_mgmt *mgmt,
00725                                      size_t len,
00726                                      struct ieee80211_rx_status *rx_status)
00727 {
00728         u8 *pos;
00729         struct ieee802_11_elems elems;
00730 
00731         wpa_printf(MSG_DEBUG, "MLME: replying to auth challenge");
00732         pos = mgmt->u.auth.variable;
00733         if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems, 0)
00734             == ParseFailed) {
00735                 wpa_printf(MSG_DEBUG, "MLME: failed to parse Auth(challenge)");
00736                 return;
00737         }
00738         if (elems.challenge == NULL) {
00739                 wpa_printf(MSG_DEBUG, "MLME: no challenge IE in shared key "
00740                            "auth frame");
00741                 return;
00742         }
00743         ieee80211_send_auth(wpa_s, 3, elems.challenge - 2,
00744                             elems.challenge_len + 2, 1);
00745 }
00746 
00747 
00748 static void ieee80211_rx_mgmt_auth(struct wpa_supplicant *wpa_s,
00749                                    struct ieee80211_mgmt *mgmt,
00750                                    size_t len,
00751                                    struct ieee80211_rx_status *rx_status)
00752 {
00753         struct wpa_ssid *ssid = wpa_s->current_ssid;
00754         u16 auth_alg, auth_transaction, status_code;
00755         int adhoc;
00756 
00757         adhoc = ssid && ssid->mode == WPAS_MODE_IBSS;
00758 
00759         if (wpa_s->mlme.state != IEEE80211_AUTHENTICATE && !adhoc) {
00760                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
00761                            "from " MACSTR ", but not in authenticate state - "
00762                            "ignored", MAC2STR(mgmt->sa));
00763                 return;
00764         }
00765 
00766         if (len < 24 + 6) {
00767                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) authentication "
00768                            "frame received from " MACSTR " - ignored",
00769                            (unsigned long) len, MAC2STR(mgmt->sa));
00770                 return;
00771         }
00772 
00773         if (!adhoc && os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
00774                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
00775                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
00776                            ") - ignored",
00777                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
00778                 return;
00779         }
00780 
00781         if (adhoc && os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0) {
00782                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
00783                            "from unknown BSSID (SA=" MACSTR " BSSID=" MACSTR
00784                            ") - ignored",
00785                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
00786                 return;
00787         }
00788 
00789         auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
00790         auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
00791         status_code = le_to_host16(mgmt->u.auth.status_code);
00792 
00793         wpa_printf(MSG_DEBUG, "MLME: RX authentication from " MACSTR
00794                    " (alg=%d transaction=%d status=%d)",
00795                    MAC2STR(mgmt->sa), auth_alg, auth_transaction, status_code);
00796 
00797         if (adhoc) {
00798                 /* IEEE 802.11 standard does not require authentication in IBSS
00799                  * networks and most implementations do not seem to use it.
00800                  * However, try to reply to authentication attempts if someone
00801                  * has actually implemented this.
00802                  * TODO: Could implement shared key authentication. */
00803                 if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
00804                         wpa_printf(MSG_DEBUG, "MLME: unexpected IBSS "
00805                                    "authentication frame (alg=%d "
00806                                    "transaction=%d)",
00807                                    auth_alg, auth_transaction);
00808                         return;
00809                 }
00810                 ieee80211_send_auth(wpa_s, 2, NULL, 0, 0);
00811         }
00812 
00813         if (auth_alg != wpa_s->mlme.auth_alg ||
00814             auth_transaction != wpa_s->mlme.auth_transaction) {
00815                 wpa_printf(MSG_DEBUG, "MLME: unexpected authentication frame "
00816                            "(alg=%d transaction=%d)",
00817                            auth_alg, auth_transaction);
00818                 return;
00819         }
00820 
00821         if (status_code != WLAN_STATUS_SUCCESS) {
00822                 wpa_printf(MSG_DEBUG, "MLME: AP denied authentication "
00823                            "(auth_alg=%d code=%d)", wpa_s->mlme.auth_alg,
00824                            status_code);
00825                 if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
00826                         const int num_algs = 3;
00827                         u8 algs[num_algs];
00828                         int i, pos;
00829                         algs[0] = algs[1] = algs[2] = 0xff;
00830                         if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_OPEN)
00831                                 algs[0] = WLAN_AUTH_OPEN;
00832                         if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_SHARED)
00833                                 algs[1] = WLAN_AUTH_SHARED_KEY;
00834                         if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_LEAP)
00835                                 algs[2] = WLAN_AUTH_LEAP;
00836                         if (wpa_s->mlme.auth_alg == WLAN_AUTH_OPEN)
00837                                 pos = 0;
00838                         else if (wpa_s->mlme.auth_alg == WLAN_AUTH_SHARED_KEY)
00839                                 pos = 1;
00840                         else
00841                                 pos = 2;
00842                         for (i = 0; i < num_algs; i++) {
00843                                 pos++;
00844                                 if (pos >= num_algs)
00845                                         pos = 0;
00846                                 if (algs[pos] == wpa_s->mlme.auth_alg ||
00847                                     algs[pos] == 0xff)
00848                                         continue;
00849                                 if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
00850                                     !ieee80211_sta_wep_configured(wpa_s))
00851                                         continue;
00852                                 wpa_s->mlme.auth_alg = algs[pos];
00853                                 wpa_printf(MSG_DEBUG, "MLME: set auth_alg=%d "
00854                                            "for next try",
00855                                            wpa_s->mlme.auth_alg);
00856                                 break;
00857                         }
00858                 }
00859                 return;
00860         }
00861 
00862         switch (wpa_s->mlme.auth_alg) {
00863         case WLAN_AUTH_OPEN:
00864         case WLAN_AUTH_LEAP:
00865                 ieee80211_auth_completed(wpa_s);
00866                 break;
00867         case WLAN_AUTH_SHARED_KEY:
00868                 if (wpa_s->mlme.auth_transaction == 4)
00869                         ieee80211_auth_completed(wpa_s);
00870                 else
00871                         ieee80211_auth_challenge(wpa_s, mgmt, len,
00872                                                  rx_status);
00873                 break;
00874 #ifdef CONFIG_IEEE80211R
00875         case WLAN_AUTH_FT:
00876         {
00877                 union wpa_event_data data;
00878                 struct wpabuf *ric = NULL;
00879                 os_memset(&data, 0, sizeof(data));
00880                 data.ft_ies.ies = mgmt->u.auth.variable;
00881                 data.ft_ies.ies_len = len -
00882                         (mgmt->u.auth.variable - (u8 *) mgmt);
00883                 os_memcpy(data.ft_ies.target_ap, wpa_s->bssid, ETH_ALEN);
00884                 if (os_strcmp(wpa_s->driver->name, "test") == 0 &&
00885                     wpa_s->mlme.wmm_enabled) {
00886                         ric = wpabuf_alloc(200);
00887                         if (ric) {
00888                                 /* Build simple RIC-Request: RDIE | TSPEC */
00889 
00890                                 /* RIC Data (RDIE) */
00891                                 wpabuf_put_u8(ric, WLAN_EID_RIC_DATA);
00892                                 wpabuf_put_u8(ric, 4);
00893                                 wpabuf_put_u8(ric, 0); /* RDIE Identifier */
00894                                 wpabuf_put_u8(ric, 1); /* Resource Descriptor
00895                                                         * Count */
00896                                 wpabuf_put_le16(ric, 0); /* Status Code */
00897 
00898                                 /* WMM TSPEC */
00899                                 ieee80211_build_tspec(ric);
00900 
00901                                 data.ft_ies.ric_ies = wpabuf_head(ric);
00902                                 data.ft_ies.ric_ies_len = wpabuf_len(ric);
00903                         }
00904                 }
00905 
00906                 wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &data);
00907                 wpabuf_free(ric);
00908                 ieee80211_auth_completed(wpa_s);
00909                 break;
00910         }
00911 #endif /* CONFIG_IEEE80211R */
00912         }
00913 }
00914 
00915 
00916 static void ieee80211_rx_mgmt_deauth(struct wpa_supplicant *wpa_s,
00917                                      struct ieee80211_mgmt *mgmt,
00918                                      size_t len,
00919                                      struct ieee80211_rx_status *rx_status)
00920 {
00921         u16 reason_code;
00922 
00923         if (len < 24 + 2) {
00924                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) deauthentication "
00925                            "frame received from " MACSTR " - ignored",
00926                            (unsigned long) len, MAC2STR(mgmt->sa));
00927                 return;
00928         }
00929 
00930         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
00931                 wpa_printf(MSG_DEBUG, "MLME: deauthentication frame received "
00932                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
00933                            ") - ignored",
00934                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
00935                 return;
00936         }
00937 
00938         reason_code = le_to_host16(mgmt->u.deauth.reason_code);
00939 
00940         wpa_printf(MSG_DEBUG, "MLME: RX deauthentication from " MACSTR
00941                    " (reason=%d)", MAC2STR(mgmt->sa), reason_code);
00942 
00943         if (wpa_s->mlme.authenticated)
00944                 wpa_printf(MSG_DEBUG, "MLME: deauthenticated");
00945 
00946         if (wpa_s->mlme.state == IEEE80211_AUTHENTICATE ||
00947             wpa_s->mlme.state == IEEE80211_ASSOCIATE ||
00948             wpa_s->mlme.state == IEEE80211_ASSOCIATED) {
00949                 wpa_s->mlme.state = IEEE80211_AUTHENTICATE;
00950                 ieee80211_reschedule_timer(wpa_s,
00951                                            IEEE80211_RETRY_AUTH_INTERVAL);
00952         }
00953 
00954         ieee80211_set_associated(wpa_s, 0);
00955         wpa_s->mlme.authenticated = 0;
00956 }
00957 
00958 
00959 static void ieee80211_rx_mgmt_disassoc(struct wpa_supplicant *wpa_s,
00960                                        struct ieee80211_mgmt *mgmt,
00961                                        size_t len,
00962                                        struct ieee80211_rx_status *rx_status)
00963 {
00964         u16 reason_code;
00965 
00966         if (len < 24 + 2) {
00967                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) disassociation "
00968                            "frame received from " MACSTR " - ignored",
00969                            (unsigned long) len, MAC2STR(mgmt->sa));
00970                 return;
00971         }
00972 
00973         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
00974                 wpa_printf(MSG_DEBUG, "MLME: disassociation frame received "
00975                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
00976                            ") - ignored",
00977                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
00978                 return;
00979         }
00980 
00981         reason_code = le_to_host16(mgmt->u.disassoc.reason_code);
00982 
00983         wpa_printf(MSG_DEBUG, "MLME: RX disassociation from " MACSTR
00984                    " (reason=%d)", MAC2STR(mgmt->sa), reason_code);
00985 
00986         if (wpa_s->mlme.associated)
00987                 wpa_printf(MSG_DEBUG, "MLME: disassociated");
00988 
00989         if (wpa_s->mlme.state == IEEE80211_ASSOCIATED) {
00990                 wpa_s->mlme.state = IEEE80211_ASSOCIATE;
00991                 ieee80211_reschedule_timer(wpa_s,
00992                                            IEEE80211_RETRY_AUTH_INTERVAL);
00993         }
00994 
00995         ieee80211_set_associated(wpa_s, 0);
00996 }
00997 
00998 
00999 static void ieee80211_build_tspec(struct wpabuf *buf)
01000 {
01001         struct wmm_tspec_element *tspec;
01002         int tid, up;
01003 
01004         tspec = wpabuf_put(buf, sizeof(*tspec));
01005         tspec->eid = WLAN_EID_VENDOR_SPECIFIC;
01006         tspec->length = sizeof(*tspec) - 2;
01007         tspec->oui[0] = 0x00;
01008         tspec->oui[1] = 0x50;
01009         tspec->oui[2] = 0xf2;
01010         tspec->oui_type = 2;
01011         tspec->oui_subtype = 2;
01012         tspec->version = 1;
01013 
01014         tid = 1;
01015         up = 6; /* Voice */
01016         tspec->ts_info[0] = (tid << 1) |
01017                 (WMM_TSPEC_DIRECTION_BI_DIRECTIONAL << 5) |
01018                 BIT(7);
01019         tspec->ts_info[1] = up << 3;
01020         tspec->nominal_msdu_size = host_to_le16(1530);
01021         tspec->mean_data_rate = host_to_le32(128000); /* bits per second */
01022         tspec->minimum_phy_rate = host_to_le32(6000000);
01023         tspec->surplus_bandwidth_allowance = host_to_le16(0x3000); /* 150% */
01024 }
01025 
01026 
01027 static void ieee80211_tx_addts(struct wpa_supplicant *wpa_s)
01028 {
01029         struct wpabuf *buf;
01030         struct ieee80211_mgmt *mgmt;
01031         size_t alen;
01032 
01033         wpa_printf(MSG_DEBUG, "MLME: Send ADDTS Request for Voice TSPEC");
01034         mgmt = NULL;
01035         alen = mgmt->u.action.u.wmm_action.variable - (u8 *) mgmt;
01036 
01037         buf = wpabuf_alloc(alen + sizeof(struct wmm_tspec_element));
01038         if (buf == NULL)
01039                 return;
01040 
01041         mgmt = wpabuf_put(buf, alen);
01042         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
01043         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
01044         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
01045         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
01046                                            WLAN_FC_STYPE_ACTION);
01047         mgmt->u.action.category = WLAN_ACTION_WMM;
01048         mgmt->u.action.u.wmm_action.action_code = WMM_ACTION_CODE_ADDTS_REQ;
01049         mgmt->u.action.u.wmm_action.dialog_token = 1;
01050         mgmt->u.action.u.wmm_action.status_code = 0;
01051 
01052         ieee80211_build_tspec(buf);
01053 
01054         ieee80211_sta_tx(wpa_s, wpabuf_head(buf), wpabuf_len(buf));
01055         wpabuf_free(buf);
01056 }
01057 
01058 
01059 static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
01060                                          struct ieee80211_mgmt *mgmt,
01061                                          size_t len,
01062                                          struct ieee80211_rx_status *rx_status,
01063                                          int reassoc)
01064 {
01065         u8 rates[32];
01066         size_t rates_len;
01067         u16 capab_info, status_code, aid;
01068         struct ieee802_11_elems elems;
01069         u8 *pos;
01070 
01071         /* AssocResp and ReassocResp have identical structure, so process both
01072          * of them in this function. */
01073 
01074         if (wpa_s->mlme.state != IEEE80211_ASSOCIATE) {
01075                 wpa_printf(MSG_DEBUG, "MLME: association frame received from "
01076                            MACSTR ", but not in associate state - ignored",
01077                            MAC2STR(mgmt->sa));
01078                 return;
01079         }
01080 
01081         if (len < 24 + 6) {
01082                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) association "
01083                            "frame received from " MACSTR " - ignored",
01084                            (unsigned long) len, MAC2STR(mgmt->sa));
01085                 return;
01086         }
01087 
01088         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
01089                 wpa_printf(MSG_DEBUG, "MLME: association frame received from "
01090                            "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - "
01091                            "ignored", MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
01092                 return;
01093         }
01094 
01095         capab_info = le_to_host16(mgmt->u.assoc_resp.capab_info);
01096         status_code = le_to_host16(mgmt->u.assoc_resp.status_code);
01097         aid = le_to_host16(mgmt->u.assoc_resp.aid);
01098         if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
01099                 wpa_printf(MSG_DEBUG, "MLME: invalid aid value %d; bits 15:14 "
01100                            "not set", aid);
01101         aid &= ~(BIT(15) | BIT(14));
01102 
01103         wpa_printf(MSG_DEBUG, "MLME: RX %sssocResp from " MACSTR
01104                    " (capab=0x%x status=%d aid=%d)",
01105                    reassoc ? "Rea" : "A", MAC2STR(mgmt->sa),
01106                    capab_info, status_code, aid);
01107 
01108         pos = mgmt->u.assoc_resp.variable;
01109         if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems, 0)
01110             == ParseFailed) {
01111                 wpa_printf(MSG_DEBUG, "MLME: failed to parse AssocResp");
01112                 return;
01113         }
01114 
01115         if (status_code != WLAN_STATUS_SUCCESS) {
01116                 wpa_printf(MSG_DEBUG, "MLME: AP denied association (code=%d)",
01117                            status_code);
01118 #ifdef CONFIG_IEEE80211W
01119                 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
01120                     elems.timeout_int && elems.timeout_int_len == 5 &&
01121                     elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
01122                         u32 tu, ms;
01123                         tu = WPA_GET_LE32(elems.timeout_int + 1);
01124                         ms = tu * 1024 / 1000;
01125                         wpa_printf(MSG_DEBUG, "MLME: AP rejected association "
01126                                    "temporarily; comeback duration %u TU "
01127                                    "(%u ms)", tu, ms);
01128                         if (ms > IEEE80211_ASSOC_TIMEOUT) {
01129                                 wpa_printf(MSG_DEBUG, "MLME: Update timer "
01130                                            "based on comeback duration");
01131                                 ieee80211_reschedule_timer(wpa_s, ms);
01132                         }
01133                 }
01134 #endif /* CONFIG_IEEE80211W */
01135                 return;
01136         }
01137 
01138         if (elems.supp_rates == NULL) {
01139                 wpa_printf(MSG_DEBUG, "MLME: no SuppRates element in "
01140                            "AssocResp");
01141                 return;
01142         }
01143 
01144         if (wpa_s->mlme.auth_alg == WLAN_AUTH_FT) {
01145                 if (!reassoc) {
01146                         wpa_printf(MSG_DEBUG, "MLME: AP tried to use "
01147                                    "association, not reassociation, response "
01148                                    "with FT");
01149                         return;
01150                 }
01151                 if (wpa_ft_validate_reassoc_resp(
01152                             wpa_s->wpa, pos, len - (pos - (u8 *) mgmt),
01153                             mgmt->sa) < 0) {
01154                         wpa_printf(MSG_DEBUG, "MLME: FT validation of Reassoc"
01155                                    "Resp failed");
01156                         return;
01157                 }
01158         } else if (wpa_sm_set_ft_params(wpa_s->wpa, pos,
01159                                         len - (pos - (u8 *) mgmt)) < 0)
01160                 return;
01161 
01162         wpa_printf(MSG_DEBUG, "MLME: associated");
01163         wpa_s->mlme.aid = aid;
01164         wpa_s->mlme.ap_capab = capab_info;
01165 
01166         os_free(wpa_s->mlme.assocresp_ies);
01167         wpa_s->mlme.assocresp_ies_len = len - (pos - (u8 *) mgmt);
01168         wpa_s->mlme.assocresp_ies = os_malloc(wpa_s->mlme.assocresp_ies_len);
01169         if (wpa_s->mlme.assocresp_ies) {
01170                 os_memcpy(wpa_s->mlme.assocresp_ies, pos,
01171                           wpa_s->mlme.assocresp_ies_len);
01172         }
01173 
01174         ieee80211_set_associated(wpa_s, 1);
01175 
01176         rates_len = elems.supp_rates_len;
01177         if (rates_len > sizeof(rates))
01178                 rates_len = sizeof(rates);
01179         os_memcpy(rates, elems.supp_rates, rates_len);
01180         if (elems.ext_supp_rates) {
01181                 size_t _len = elems.ext_supp_rates_len;
01182                 if (_len > sizeof(rates) - rates_len)
01183                         _len = sizeof(rates) - rates_len;
01184                 os_memcpy(rates + rates_len, elems.ext_supp_rates, _len);
01185                 rates_len += _len;
01186         }
01187 
01188         if (wpa_drv_set_bssid(wpa_s, wpa_s->bssid) < 0) {
01189                 wpa_printf(MSG_DEBUG, "MLME: failed to set BSSID for the "
01190                            "netstack");
01191         }
01192         if (wpa_drv_set_ssid(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) <
01193             0) {
01194                 wpa_printf(MSG_DEBUG, "MLME: failed to set SSID for the "
01195                            "netstack");
01196         }
01197 
01198         /* Remove STA entry before adding a new one just in case to avoid
01199          * problems with existing configuration (e.g., keys). */
01200         wpa_drv_mlme_remove_sta(wpa_s, wpa_s->bssid);
01201         if (wpa_drv_mlme_add_sta(wpa_s, wpa_s->bssid, rates, rates_len) < 0) {
01202                 wpa_printf(MSG_DEBUG, "MLME: failed to add STA entry to the "
01203                            "netstack");
01204         }
01205 
01206         if (elems.wmm && wpa_s->mlme.wmm_enabled)
01207                 ieee80211_sta_wmm_params(wpa_s, elems.wmm, elems.wmm_len);
01208 
01209         ieee80211_associated(wpa_s);
01210 
01211         if (wpa_s->mlme.auth_alg != WLAN_AUTH_FT &&
01212             os_strcmp(wpa_s->driver->name, "test") == 0 &&
01213             elems.wmm && wpa_s->mlme.wmm_enabled) {
01214                 /* Test WMM-AC - send ADDTS for WMM TSPEC */
01215                 ieee80211_tx_addts(wpa_s);
01216         }
01217 }
01218 
01219 
01220 /* Caller must hold local->sta_bss_lock */
01221 static void __ieee80211_bss_hash_add(struct wpa_supplicant *wpa_s,
01222                                      struct ieee80211_sta_bss *bss)
01223 {
01224         bss->hnext = wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)];
01225         wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)] = bss;
01226 }
01227 
01228 
01229 /* Caller must hold local->sta_bss_lock */
01230 static void __ieee80211_bss_hash_del(struct wpa_supplicant *wpa_s,
01231                                      struct ieee80211_sta_bss *bss)
01232 {
01233         struct ieee80211_sta_bss *b, *prev = NULL;
01234         b = wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)];
01235         while (b) {
01236                 if (b == bss) {
01237                         if (prev == NULL) {
01238                                 wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)]
01239                                         = bss->hnext;
01240                         } else {
01241                                 prev->hnext = bss->hnext;
01242                         }
01243                         break;
01244                 }
01245                 prev = b;
01246                 b = b->hnext;
01247         }
01248 }
01249 
01250 
01251 static struct ieee80211_sta_bss *
01252 ieee80211_bss_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
01253 {
01254         struct ieee80211_sta_bss *bss;
01255 
01256         bss = os_zalloc(sizeof(*bss));
01257         if (bss == NULL)
01258                 return NULL;
01259         os_memcpy(bss->bssid, bssid, ETH_ALEN);
01260 
01261         /* TODO: order by RSSI? */
01262         bss->next = wpa_s->mlme.sta_bss_list;
01263         wpa_s->mlme.sta_bss_list = bss;
01264         __ieee80211_bss_hash_add(wpa_s, bss);
01265         return bss;
01266 }
01267 
01268 
01269 static struct ieee80211_sta_bss *
01270 ieee80211_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid)
01271 {
01272         struct ieee80211_sta_bss *bss;
01273 
01274         bss = wpa_s->mlme.sta_bss_hash[STA_HASH(bssid)];
01275         while (bss) {
01276                 if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
01277                         break;
01278                 bss = bss->hnext;
01279         }
01280         return bss;
01281 }
01282 
01283 
01284 static void ieee80211_bss_free(struct wpa_supplicant *wpa_s,
01285                                struct ieee80211_sta_bss *bss)
01286 {
01287         __ieee80211_bss_hash_del(wpa_s, bss);
01288         os_free(bss->ie);
01289         os_free(bss->wpa_ie);
01290         os_free(bss->rsn_ie);
01291         os_free(bss->wmm_ie);
01292         os_free(bss->mdie);
01293         os_free(bss);
01294 }
01295 
01296 
01297 static void ieee80211_bss_list_deinit(struct wpa_supplicant *wpa_s)
01298 {
01299         struct ieee80211_sta_bss *bss, *prev;
01300 
01301         bss = wpa_s->mlme.sta_bss_list;
01302         wpa_s->mlme.sta_bss_list = NULL;
01303         while (bss) {
01304                 prev = bss;
01305                 bss = bss->next;
01306                 ieee80211_bss_free(wpa_s, prev);
01307         }
01308 }
01309 
01310 
01311 static void ieee80211_bss_info(struct wpa_supplicant *wpa_s,
01312                                struct ieee80211_mgmt *mgmt,
01313                                size_t len,
01314                                struct ieee80211_rx_status *rx_status,
01315                                int beacon)
01316 {
01317         struct ieee802_11_elems elems;
01318         size_t baselen;
01319         int channel, invalid = 0, clen;
01320         struct ieee80211_sta_bss *bss;
01321         u64 timestamp;
01322         u8 *pos, *ie_pos;
01323         size_t ie_len;
01324 
01325         if (!beacon && os_memcmp(mgmt->da, wpa_s->own_addr, ETH_ALEN))
01326                 return; /* ignore ProbeResp to foreign address */
01327 
01328 #if 0
01329         wpa_printf(MSG_MSGDUMP, "MLME: RX %s from " MACSTR " to " MACSTR,
01330                    beacon ? "Beacon" : "Probe Response",
01331                    MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
01332 #endif
01333 
01334         baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
01335         if (baselen > len)
01336                 return;
01337 
01338         pos = mgmt->u.beacon.timestamp;
01339         timestamp = WPA_GET_LE64(pos);
01340 
01341 #if 0 /* FIX */
01342         if (local->conf.mode == IW_MODE_ADHOC && beacon &&
01343             os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0) {
01344 #ifdef IEEE80211_IBSS_DEBUG
01345                 static unsigned long last_tsf_debug = 0;
01346                 u64 tsf;
01347                 if (local->hw->get_tsf)
01348                         tsf = local->hw->get_tsf(local->mdev);
01349                 else
01350                         tsf = -1LLU;
01351                 if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
01352                         wpa_printf(MSG_DEBUG, "RX beacon SA=" MACSTR " BSSID="
01353                                    MACSTR " TSF=0x%llx BCN=0x%llx diff=%lld "
01354                                    "@%ld",
01355                                    MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
01356                                    tsf, timestamp, tsf - timestamp, jiffies);
01357                         last_tsf_debug = jiffies;
01358                 }
01359 #endif /* IEEE80211_IBSS_DEBUG */
01360         }
01361 #endif
01362 
01363         ie_pos = mgmt->u.beacon.variable;
01364         ie_len = len - baselen;
01365         if (ieee802_11_parse_elems(ie_pos, ie_len, &elems, 0) == ParseFailed)
01366                 invalid = 1;
01367 
01368 #if 0 /* FIX */
01369         if (local->conf.mode == IW_MODE_ADHOC && elems.supp_rates &&
01370             os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0 &&
01371             (sta = sta_info_get(local, mgmt->sa))) {
01372                 struct ieee80211_rate *rates;
01373                 size_t num_rates;
01374                 u32 supp_rates, prev_rates;
01375                 int i, j, oper_mode;
01376 
01377                 rates = local->curr_rates;
01378                 num_rates = local->num_curr_rates;
01379                 oper_mode = wpa_s->mlme.sta_scanning ?
01380                         local->scan_oper_phymode : local->conf.phymode;
01381                 for (i = 0; i < local->hw->num_modes; i++) {
01382                         struct ieee80211_hw_modes *mode = &local->hw->modes[i];
01383                         if (oper_mode == mode->mode) {
01384                                 rates = mode->rates;
01385                                 num_rates = mode->num_rates;
01386                                 break;
01387                         }
01388                 }
01389 
01390                 supp_rates = 0;
01391                 for (i = 0; i < elems.supp_rates_len +
01392                              elems.ext_supp_rates_len; i++) {
01393                         u8 rate = 0;
01394                         int own_rate;
01395                         if (i < elems.supp_rates_len)
01396                                 rate = elems.supp_rates[i];
01397                         else if (elems.ext_supp_rates)
01398                                 rate = elems.ext_supp_rates
01399                                         [i - elems.supp_rates_len];
01400                         own_rate = 5 * (rate & 0x7f);
01401                         if (oper_mode == MODE_ATHEROS_TURBO)
01402                                 own_rate *= 2;
01403                         for (j = 0; j < num_rates; j++)
01404                                 if (rates[j].rate == own_rate)
01405                                         supp_rates |= BIT(j);
01406                 }
01407 
01408                 prev_rates = sta->supp_rates;
01409                 sta->supp_rates &= supp_rates;
01410                 if (sta->supp_rates == 0) {
01411                         /* No matching rates - this should not really happen.
01412                          * Make sure that at least one rate is marked
01413                          * supported to avoid issues with TX rate ctrl. */
01414                         sta->supp_rates = wpa_s->mlme.supp_rates_bits;
01415                 }
01416                 if (sta->supp_rates != prev_rates) {
01417                         wpa_printf(MSG_DEBUG, "MLME: updated supp_rates set "
01418                                    "for " MACSTR " based on beacon info "
01419                                    "(0x%x & 0x%x -> 0x%x)",
01420                                    MAC2STR(sta->addr), prev_rates,
01421                                    supp_rates, sta->supp_rates);
01422                 }
01423                 sta_info_release(local, sta);
01424         }
01425 #endif
01426 
01427         if (elems.ssid == NULL)
01428                 return;
01429 
01430         if (elems.ds_params && elems.ds_params_len == 1)
01431                 channel = elems.ds_params[0];
01432         else
01433                 channel = rx_status->channel;
01434 
01435         bss = ieee80211_bss_get(wpa_s, mgmt->bssid);
01436         if (bss == NULL) {
01437                 bss = ieee80211_bss_add(wpa_s, mgmt->bssid);
01438                 if (bss == NULL)
01439                         return;
01440         } else {
01441 #if 0
01442                 /* TODO: order by RSSI? */
01443                 spin_lock_bh(&local->sta_bss_lock);
01444                 list_move_tail(&bss->list, &local->sta_bss_list);
01445                 spin_unlock_bh(&local->sta_bss_lock);
01446 #endif
01447         }
01448 
01449         if (bss->probe_resp && beacon) {
01450                 /* Do not allow beacon to override data from Probe Response. */
01451                 return;
01452         }
01453 
01454         bss->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int);
01455         bss->capability = le_to_host16(mgmt->u.beacon.capab_info);
01456 
01457         if (bss->ie == NULL || bss->ie_len < ie_len) {
01458                 os_free(bss->ie);
01459                 bss->ie = os_malloc(ie_len);
01460         }
01461         if (bss->ie) {
01462                 os_memcpy(bss->ie, ie_pos, ie_len);
01463                 bss->ie_len = ie_len;
01464         }
01465 
01466         if (elems.ssid && elems.ssid_len <= MAX_SSID_LEN) {
01467                 os_memcpy(bss->ssid, elems.ssid, elems.ssid_len);
01468                 bss->ssid_len = elems.ssid_len;
01469         }
01470 
01471         bss->supp_rates_len = 0;
01472         if (elems.supp_rates) {
01473                 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
01474                 if (clen > elems.supp_rates_len)
01475                         clen = elems.supp_rates_len;
01476                 os_memcpy(&bss->supp_rates[bss->supp_rates_len],
01477                           elems.supp_rates, clen);
01478                 bss->supp_rates_len += clen;
01479         }
01480         if (elems.ext_supp_rates) {
01481                 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
01482                 if (clen > elems.ext_supp_rates_len)
01483                         clen = elems.ext_supp_rates_len;
01484                 os_memcpy(&bss->supp_rates[bss->supp_rates_len],
01485                           elems.ext_supp_rates, clen);
01486                 bss->supp_rates_len += clen;
01487         }
01488 
01489         if (elems.wpa_ie &&
01490             (bss->wpa_ie == NULL || bss->wpa_ie_len != elems.wpa_ie_len ||
01491              os_memcmp(bss->wpa_ie, elems.wpa_ie, elems.wpa_ie_len))) {
01492                 os_free(bss->wpa_ie);
01493                 bss->wpa_ie = os_malloc(elems.wpa_ie_len + 2);
01494                 if (bss->wpa_ie) {
01495                         os_memcpy(bss->wpa_ie, elems.wpa_ie - 2,
01496                                   elems.wpa_ie_len + 2);
01497                         bss->wpa_ie_len = elems.wpa_ie_len + 2;
01498                 } else
01499                         bss->wpa_ie_len = 0;
01500         } else if (!elems.wpa_ie && bss->wpa_ie) {
01501                 os_free(bss->wpa_ie);
01502                 bss->wpa_ie = NULL;
01503                 bss->wpa_ie_len = 0;
01504         }
01505 
01506         if (elems.rsn_ie &&
01507             (bss->rsn_ie == NULL || bss->rsn_ie_len != elems.rsn_ie_len ||
01508              os_memcmp(bss->rsn_ie, elems.rsn_ie, elems.rsn_ie_len))) {
01509                 os_free(bss->rsn_ie);
01510                 bss->rsn_ie = os_malloc(elems.rsn_ie_len + 2);
01511                 if (bss->rsn_ie) {
01512                         os_memcpy(bss->rsn_ie, elems.rsn_ie - 2,
01513                                   elems.rsn_ie_len + 2);
01514                         bss->rsn_ie_len = elems.rsn_ie_len + 2;
01515                 } else
01516                         bss->rsn_ie_len = 0;
01517         } else if (!elems.rsn_ie && bss->rsn_ie) {
01518                 os_free(bss->rsn_ie);
01519                 bss->rsn_ie = NULL;
01520                 bss->rsn_ie_len = 0;
01521         }
01522 
01523         if (elems.wmm &&
01524             (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wmm_len ||
01525              os_memcmp(bss->wmm_ie, elems.wmm, elems.wmm_len))) {
01526                 os_free(bss->wmm_ie);
01527                 bss->wmm_ie = os_malloc(elems.wmm_len + 2);
01528                 if (bss->wmm_ie) {
01529                         os_memcpy(bss->wmm_ie, elems.wmm - 2,
01530                                   elems.wmm_len + 2);
01531                         bss->wmm_ie_len = elems.wmm_len + 2;
01532                 } else
01533                         bss->wmm_ie_len = 0;
01534         } else if (!elems.wmm && bss->wmm_ie) {
01535                 os_free(bss->wmm_ie);
01536                 bss->wmm_ie = NULL;
01537                 bss->wmm_ie_len = 0;
01538         }
01539 
01540 #ifdef CONFIG_IEEE80211R
01541         if (elems.mdie &&
01542             (bss->mdie == NULL || bss->mdie_len != elems.mdie_len ||
01543              os_memcmp(bss->mdie, elems.mdie, elems.mdie_len))) {
01544                 os_free(bss->mdie);
01545                 bss->mdie = os_malloc(elems.mdie_len + 2);
01546                 if (bss->mdie) {
01547                         os_memcpy(bss->mdie, elems.mdie - 2,
01548                                   elems.mdie_len + 2);
01549                         bss->mdie_len = elems.mdie_len + 2;
01550                 } else
01551                         bss->mdie_len = 0;
01552         } else if (!elems.mdie && bss->mdie) {
01553                 os_free(bss->mdie);
01554                 bss->mdie = NULL;
01555                 bss->mdie_len = 0;
01556         }
01557 #endif /* CONFIG_IEEE80211R */
01558 
01559         bss->hw_mode = wpa_s->mlme.phymode;
01560         bss->channel = channel;
01561         bss->freq = wpa_s->mlme.freq;
01562         if (channel != wpa_s->mlme.channel &&
01563             (wpa_s->mlme.phymode == HOSTAPD_MODE_IEEE80211G ||
01564              wpa_s->mlme.phymode == HOSTAPD_MODE_IEEE80211B) &&
01565             channel >= 1 && channel <= 14) {
01566                 static const int freq_list[] = {
01567                         2412, 2417, 2422, 2427, 2432, 2437, 2442,
01568                         2447, 2452, 2457, 2462, 2467, 2472, 2484
01569                 };
01570                 /* IEEE 802.11g/b mode can receive packets from neighboring
01571                  * channels, so map the channel into frequency. */
01572                 bss->freq = freq_list[channel - 1];
01573         }
01574         bss->timestamp = timestamp;
01575         os_get_time(&bss->last_update);
01576         bss->rssi = rx_status->ssi;
01577         if (!beacon)
01578                 bss->probe_resp++;
01579 }
01580 
01581 
01582 static void ieee80211_rx_mgmt_probe_resp(struct wpa_supplicant *wpa_s,
01583                                          struct ieee80211_mgmt *mgmt,
01584                                          size_t len,
01585                                          struct ieee80211_rx_status *rx_status)
01586 {
01587         ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 0);
01588 }
01589 
01590 
01591 static void ieee80211_rx_mgmt_beacon(struct wpa_supplicant *wpa_s,
01592                                      struct ieee80211_mgmt *mgmt,
01593                                      size_t len,
01594                                      struct ieee80211_rx_status *rx_status)
01595 {
01596         int use_protection;
01597         size_t baselen;
01598         struct ieee802_11_elems elems;
01599 
01600         ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 1);
01601 
01602         if (!wpa_s->mlme.associated ||
01603             os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0)
01604                 return;
01605 
01606         /* Process beacon from the current BSS */
01607         baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
01608         if (baselen > len)
01609                 return;
01610 
01611         if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
01612                                    &elems, 0) == ParseFailed)
01613                 return;
01614 
01615         use_protection = 0;
01616         if (elems.erp_info && elems.erp_info_len >= 1) {
01617                 use_protection =
01618                         (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
01619         }
01620 
01621         if (use_protection != !!wpa_s->mlme.use_protection) {
01622                 wpa_printf(MSG_DEBUG, "MLME: CTS protection %s (BSSID=" MACSTR
01623                            ")",
01624                            use_protection ? "enabled" : "disabled",
01625                            MAC2STR(wpa_s->bssid));
01626                 wpa_s->mlme.use_protection = use_protection ? 1 : 0;
01627                 wpa_s->mlme.cts_protect_erp_frames = use_protection;
01628         }
01629 
01630         if (elems.wmm && wpa_s->mlme.wmm_enabled) {
01631                 ieee80211_sta_wmm_params(wpa_s, elems.wmm,
01632                                          elems.wmm_len);
01633         }
01634 }
01635 
01636 
01637 static void ieee80211_rx_mgmt_probe_req(struct wpa_supplicant *wpa_s,
01638                                         struct ieee80211_mgmt *mgmt,
01639                                         size_t len,
01640                                         struct ieee80211_rx_status *rx_status)
01641 {
01642         int tx_last_beacon, adhoc;
01643 #if 0 /* FIX */
01644         struct ieee80211_mgmt *resp;
01645 #endif
01646         u8 *pos, *end;
01647         struct wpa_ssid *ssid = wpa_s->current_ssid;
01648 
01649         adhoc = ssid && ssid->mode == WPAS_MODE_IBSS;
01650 
01651         if (!adhoc || wpa_s->mlme.state != IEEE80211_IBSS_JOINED ||
01652             len < 24 + 2 || wpa_s->mlme.probe_resp == NULL)
01653                 return;
01654 
01655 #if 0 /* FIX */
01656         if (local->hw->tx_last_beacon)
01657                 tx_last_beacon = local->hw->tx_last_beacon(local->mdev);
01658         else
01659 #endif
01660                 tx_last_beacon = 1;
01661 
01662 #ifdef IEEE80211_IBSS_DEBUG
01663         wpa_printf(MSG_DEBUG, "MLME: RX ProbeReq SA=" MACSTR " DA=" MACSTR
01664                    " BSSID=" MACSTR " (tx_last_beacon=%d)",
01665                    MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
01666                    MAC2STR(mgmt->bssid), tx_last_beacon);
01667 #endif /* IEEE80211_IBSS_DEBUG */
01668 
01669         if (!tx_last_beacon)
01670                 return;
01671 
01672         if (os_memcmp(mgmt->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
01673             os_memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
01674                 return;
01675 
01676         end = ((u8 *) mgmt) + len;
01677         pos = mgmt->u.probe_req.variable;
01678         if (pos[0] != WLAN_EID_SSID ||
01679             pos + 2 + pos[1] > end) {
01680                 wpa_printf(MSG_DEBUG, "MLME: Invalid SSID IE in ProbeReq from "
01681                            MACSTR, MAC2STR(mgmt->sa));
01682                 return;
01683         }
01684         if (pos[1] != 0 &&
01685             (pos[1] != wpa_s->mlme.ssid_len ||
01686              os_memcmp(pos + 2, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) != 0))
01687         {
01688                 /* Ignore ProbeReq for foreign SSID */
01689                 return;
01690         }
01691 
01692 #if 0 /* FIX */
01693         /* Reply with ProbeResp */
01694         skb = skb_copy(wpa_s->mlme.probe_resp, GFP_ATOMIC);
01695         if (skb == NULL)
01696                 return;
01697 
01698         resp = (struct ieee80211_mgmt *) skb->data;
01699         os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
01700 #ifdef IEEE80211_IBSS_DEBUG
01701         wpa_printf(MSG_DEBUG, "MLME: Sending ProbeResp to " MACSTR,
01702                    MAC2STR(resp->da));
01703 #endif /* IEEE80211_IBSS_DEBUG */
01704         ieee80211_sta_tx(wpa_s, skb, 0, 1);
01705 #endif
01706 }
01707 
01708 
01709 #ifdef CONFIG_IEEE80211R
01710 static void ieee80211_rx_mgmt_ft_action(struct wpa_supplicant *wpa_s,
01711                                         struct ieee80211_mgmt *mgmt,
01712                                         size_t len,
01713                                         struct ieee80211_rx_status *rx_status)
01714 {
01715         union wpa_event_data data;
01716         u16 status;
01717         u8 *sta_addr, *target_ap_addr;
01718 
01719         if (len < 24 + 1 + sizeof(mgmt->u.action.u.ft_action_resp)) {
01720                 wpa_printf(MSG_DEBUG, "MLME: Too short FT Action frame");
01721                 return;
01722         }
01723 
01724         /*
01725          * Only FT Action Response is needed for now since reservation
01726          * protocol is not supported.
01727          */
01728         if (mgmt->u.action.u.ft_action_resp.action != 2) {
01729                 wpa_printf(MSG_DEBUG, "MLME: Unexpected FT Action %d",
01730                            mgmt->u.action.u.ft_action_resp.action);
01731                 return;
01732         }
01733 
01734         status = le_to_host16(mgmt->u.action.u.ft_action_resp.status_code);
01735         sta_addr = mgmt->u.action.u.ft_action_resp.sta_addr;
01736         target_ap_addr = mgmt->u.action.u.ft_action_resp.target_ap_addr;
01737         wpa_printf(MSG_DEBUG, "MLME: Received FT Action Response: STA " MACSTR
01738                    " TargetAP " MACSTR " Status Code %d",
01739                    MAC2STR(sta_addr), MAC2STR(target_ap_addr), status);
01740         if (os_memcmp(sta_addr, wpa_s->own_addr, ETH_ALEN) != 0) {
01741                 wpa_printf(MSG_DEBUG, "MLME: Foreign STA Address " MACSTR
01742                            " in FT Action Response", MAC2STR(sta_addr));
01743                 return;
01744         }
01745 
01746         if (status) {
01747                 wpa_printf(MSG_DEBUG, "MLME: FT Action Response indicates "
01748                            "failure (status code %d)", status);
01749                 /* TODO: report error to FT code(?) */
01750                 return;
01751         }
01752 
01753         os_memset(&data, 0, sizeof(data));
01754         data.ft_ies.ies = mgmt->u.action.u.ft_action_resp.variable;
01755         data.ft_ies.ies_len = len - (mgmt->u.action.u.ft_action_resp.variable -
01756                                      (u8 *) mgmt);
01757         data.ft_ies.ft_action = 1;
01758         os_memcpy(data.ft_ies.target_ap, target_ap_addr, ETH_ALEN);
01759         wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &data);
01760         /* TODO: should only re-associate, if EVENT_FT_RESPONSE was processed
01761          * successfully */
01762         wpa_s->mlme.prev_bssid_set = 1;
01763         wpa_s->mlme.auth_alg = WLAN_AUTH_FT;
01764         os_memcpy(wpa_s->mlme.prev_bssid, wpa_s->bssid, ETH_ALEN);
01765         os_memcpy(wpa_s->bssid, target_ap_addr, ETH_ALEN);
01766         ieee80211_associate(wpa_s);
01767 }
01768 #endif /* CONFIG_IEEE80211R */
01769 
01770 
01771 #ifdef CONFIG_IEEE80211W
01772 
01773 /* MLME-SAQuery.response */
01774 static int ieee80211_sta_send_sa_query_resp(struct wpa_supplicant *wpa_s,
01775                                             const u8 *addr, const u8 *trans_id)
01776 {
01777         struct ieee80211_mgmt *mgmt;
01778         int res;
01779         size_t len;
01780 
01781         mgmt = os_zalloc(sizeof(*mgmt));
01782         if (mgmt == NULL) {
01783                 wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
01784                            "SA Query action frame");
01785                 return -1;
01786         }
01787 
01788         len = 24;
01789         os_memcpy(mgmt->da, addr, ETH_ALEN);
01790         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
01791         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
01792         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
01793                                            WLAN_FC_STYPE_ACTION);
01794         mgmt->u.action.category = WLAN_ACTION_SA_QUERY;
01795         mgmt->u.action.u.sa_query_resp.action = WLAN_SA_QUERY_RESPONSE;
01796         os_memcpy(mgmt->u.action.u.sa_query_resp.trans_id, trans_id,
01797                   WLAN_SA_QUERY_TR_ID_LEN);
01798         len += 1 + sizeof(mgmt->u.action.u.sa_query_resp);
01799 
01800         res = ieee80211_sta_tx(wpa_s, (u8 *) mgmt, len);
01801         os_free(mgmt);
01802 
01803         return res;
01804 }
01805 
01806 
01807 static void ieee80211_rx_mgmt_sa_query_action(
01808         struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
01809         struct ieee80211_rx_status *rx_status)
01810 {
01811         if (len < 24 + 1 + sizeof(mgmt->u.action.u.sa_query_req)) {
01812                 wpa_printf(MSG_DEBUG, "MLME: Too short SA Query Action frame");
01813                 return;
01814         }
01815 
01816         if (mgmt->u.action.u.sa_query_req.action != WLAN_SA_QUERY_REQUEST) {
01817                 wpa_printf(MSG_DEBUG, "MLME: Unexpected SA Query Action %d",
01818                            mgmt->u.action.u.sa_query_req.action);
01819                 return;
01820         }
01821 
01822         if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) {
01823                 wpa_printf(MSG_DEBUG, "MLME: Ignore SA Query from unknown "
01824                            "source " MACSTR, MAC2STR(mgmt->sa));
01825                 return;
01826         }
01827 
01828         if (wpa_s->mlme.state == IEEE80211_ASSOCIATE) {
01829                 wpa_printf(MSG_DEBUG, "MLME: Ignore SA query request during "
01830                            "association process");
01831                 return;
01832         }
01833 
01834         wpa_printf(MSG_DEBUG, "MLME: Replying to SA Query request");
01835         ieee80211_sta_send_sa_query_resp(wpa_s, mgmt->sa, mgmt->u.action.u.
01836                                          sa_query_req.trans_id);
01837 }
01838 
01839 #endif /* CONFIG_IEEE80211W */
01840 
01841 
01842 static void dump_tspec(struct wmm_tspec_element *tspec)
01843 {
01844         int up, psb, dir, tid;
01845         u16 val;
01846 
01847         up = (tspec->ts_info[1] >> 3) & 0x07;
01848         psb = (tspec->ts_info[1] >> 2) & 0x01;
01849         dir = (tspec->ts_info[0] >> 5) & 0x03;
01850         tid = (tspec->ts_info[0] >> 1) & 0x0f;
01851         wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d",
01852                    up, psb, dir, tid);
01853         val = le_to_host16(tspec->nominal_msdu_size);
01854         wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s",
01855                    val & 0x7fff, val & 0x8000 ? " (fixed)" : "");
01856         wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps",
01857                    le_to_host32(tspec->mean_data_rate));
01858         wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps",
01859                    le_to_host32(tspec->minimum_phy_rate));
01860         val = le_to_host16(tspec->surplus_bandwidth_allowance);
01861         wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u",
01862                    val >> 13, 10000 * (val & 0x1fff) / 0x2000);
01863         val = le_to_host16(tspec->medium_time);
01864         wpa_printf(MSG_DEBUG, "WMM: Medium Time: %u (= %u usec/sec)",
01865                    val, 32 * val);
01866 }
01867 
01868 
01869 static int is_wmm_tspec(const u8 *ie, size_t len)
01870 {
01871         const struct wmm_tspec_element *tspec;
01872 
01873         if (len < sizeof(*tspec))
01874                 return 0;
01875 
01876         tspec = (const struct wmm_tspec_element *) ie;
01877         if (tspec->eid != WLAN_EID_VENDOR_SPECIFIC ||
01878             tspec->length < sizeof(*tspec) - 2 ||
01879             tspec->oui[0] != 0x00 || tspec->oui[1] != 0x50 ||
01880             tspec->oui[2] != 0xf2 || tspec->oui_type != 2 ||
01881             tspec->oui_subtype != 2 || tspec->version != 1)
01882                 return 0;
01883 
01884         return 1;
01885 }
01886 
01887 
01888 static void ieee80211_rx_addts_resp(
01889         struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
01890         size_t var_len)
01891 {
01892         struct wmm_tspec_element *tspec;
01893 
01894         wpa_printf(MSG_DEBUG, "WMM: Received ADDTS Response");
01895         wpa_hexdump(MSG_MSGDUMP, "WMM: ADDTS Response IE(s)",
01896                     mgmt->u.action.u.wmm_action.variable, var_len);
01897         if (!is_wmm_tspec(mgmt->u.action.u.wmm_action.variable, var_len))
01898                 return;
01899         tspec = (struct wmm_tspec_element *)
01900                 mgmt->u.action.u.wmm_action.variable;
01901         dump_tspec(tspec);
01902 }
01903 
01904 
01905 static void ieee80211_rx_delts(
01906         struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
01907         size_t var_len)
01908 {
01909         struct wmm_tspec_element *tspec;
01910 
01911         wpa_printf(MSG_DEBUG, "WMM: Received DELTS");
01912         wpa_hexdump(MSG_MSGDUMP, "WMM: DELTS IE(s)",
01913                     mgmt->u.action.u.wmm_action.variable, var_len);
01914         if (!is_wmm_tspec(mgmt->u.action.u.wmm_action.variable, var_len))
01915                 return;
01916         tspec = (struct wmm_tspec_element *)
01917                 mgmt->u.action.u.wmm_action.variable;
01918         dump_tspec(tspec);
01919 }
01920 
01921 
01922 static void ieee80211_rx_mgmt_wmm_action(
01923         struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
01924         struct ieee80211_rx_status *rx_status)
01925 {
01926         size_t alen;
01927 
01928         alen = mgmt->u.action.u.wmm_action.variable - (u8 *) mgmt;
01929         if (len < alen) {
01930                 wpa_printf(MSG_DEBUG, "WMM: Received Action frame too short");
01931                 return;
01932         }
01933 
01934         wpa_printf(MSG_DEBUG, "WMM: Received Action frame: Action Code %d, "
01935                    "Dialog Token %d, Status Code %d",
01936                    mgmt->u.action.u.wmm_action.action_code,
01937                    mgmt->u.action.u.wmm_action.dialog_token,
01938                    mgmt->u.action.u.wmm_action.status_code);
01939 
01940         switch (mgmt->u.action.u.wmm_action.action_code) {
01941         case WMM_ACTION_CODE_ADDTS_RESP:
01942                 ieee80211_rx_addts_resp(wpa_s, mgmt, len, len - alen);
01943                 break;
01944         case WMM_ACTION_CODE_DELTS:
01945                 ieee80211_rx_delts(wpa_s, mgmt, len, len - alen);
01946                 break;
01947         default:
01948                 wpa_printf(MSG_DEBUG, "WMM: Unsupported Action Code %d",
01949                            mgmt->u.action.u.wmm_action.action_code);
01950                 break;
01951         }
01952 }
01953 
01954 
01955 static void ieee80211_rx_mgmt_action(struct wpa_supplicant *wpa_s,
01956                                      struct ieee80211_mgmt *mgmt,
01957                                      size_t len,
01958                                      struct ieee80211_rx_status *rx_status)
01959 {
01960         wpa_printf(MSG_DEBUG, "MLME: received Action frame");
01961 
01962         if (len < 25)
01963                 return;
01964 
01965         switch (mgmt->u.action.category) {
01966 #ifdef CONFIG_IEEE80211R
01967         case WLAN_ACTION_FT:
01968                 ieee80211_rx_mgmt_ft_action(wpa_s, mgmt, len, rx_status);
01969                 break;
01970 #endif /* CONFIG_IEEE80211R */
01971 #ifdef CONFIG_IEEE80211W
01972         case WLAN_ACTION_SA_QUERY:
01973                 ieee80211_rx_mgmt_sa_query_action(wpa_s, mgmt, len, rx_status);
01974                 break;
01975 #endif /* CONFIG_IEEE80211W */
01976         case WLAN_ACTION_WMM:
01977                 ieee80211_rx_mgmt_wmm_action(wpa_s, mgmt, len, rx_status);
01978                 break;
01979         case WLAN_ACTION_PUBLIC:
01980                 if (wpa_s->mlme.public_action_cb) {
01981                         wpa_s->mlme.public_action_cb(
01982                                 wpa_s->mlme.public_action_cb_ctx,
01983                                 (u8 *) mgmt, len, rx_status->freq);
01984                         return;
01985                 }
01986                 break;
01987         default:
01988                 wpa_printf(MSG_DEBUG, "MLME: unknown Action Category %d",
01989                            mgmt->u.action.category);
01990                 break;
01991         }
01992 }
01993 
01994 
01995 static void ieee80211_sta_rx_mgmt(struct wpa_supplicant *wpa_s,
01996                                   const u8 *buf, size_t len,
01997                                   struct ieee80211_rx_status *rx_status)
01998 {
01999         struct ieee80211_mgmt *mgmt;
02000         u16 fc;
02001 
02002         if (len < 24)
02003                 return;
02004 
02005         mgmt = (struct ieee80211_mgmt *) buf;
02006         fc = le_to_host16(mgmt->frame_control);
02007 
02008         switch (WLAN_FC_GET_STYPE(fc)) {
02009         case WLAN_FC_STYPE_PROBE_REQ:
02010                 ieee80211_rx_mgmt_probe_req(wpa_s, mgmt, len, rx_status);
02011                 break;
02012         case WLAN_FC_STYPE_PROBE_RESP:
02013                 ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt, len, rx_status);
02014                 break;
02015         case WLAN_FC_STYPE_BEACON:
02016                 ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status);
02017                 break;
02018         case WLAN_FC_STYPE_AUTH:
02019                 ieee80211_rx_mgmt_auth(wpa_s, mgmt, len, rx_status);
02020                 break;
02021         case WLAN_FC_STYPE_ASSOC_RESP:
02022                 ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 0);
02023                 break;
02024         case WLAN_FC_STYPE_REASSOC_RESP:
02025                 ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 1);
02026                 break;
02027         case WLAN_FC_STYPE_DEAUTH:
02028                 ieee80211_rx_mgmt_deauth(wpa_s, mgmt, len, rx_status);
02029                 break;
02030         case WLAN_FC_STYPE_DISASSOC:
02031                 ieee80211_rx_mgmt_disassoc(wpa_s, mgmt, len, rx_status);
02032                 break;
02033         case WLAN_FC_STYPE_ACTION:
02034                 ieee80211_rx_mgmt_action(wpa_s, mgmt, len, rx_status);
02035                 break;
02036         default:
02037                 wpa_printf(MSG_DEBUG, "MLME: received unknown management "
02038                            "frame - stype=%d", WLAN_FC_GET_STYPE(fc));
02039                 break;
02040         }
02041 }
02042 
02043 
02044 static void ieee80211_sta_rx_scan(struct wpa_supplicant *wpa_s,
02045                                   const u8 *buf, size_t len,
02046                                   struct ieee80211_rx_status *rx_status)
02047 {
02048         struct ieee80211_mgmt *mgmt;
02049         u16 fc;
02050 
02051         if (len < 24)
02052                 return;
02053 
02054         mgmt = (struct ieee80211_mgmt *) buf;
02055         fc = le_to_host16(mgmt->frame_control);
02056 
02057         if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) {
02058                 if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
02059                         ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt,
02060                                                      len, rx_status);
02061                 } else if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) {
02062                         ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status);
02063                 }
02064         }
02065 }
02066 
02067 
02068 static int ieee80211_sta_active_ibss(struct wpa_supplicant *wpa_s)
02069 {
02070         int active = 0;
02071 
02072 #if 0 /* FIX */
02073         list_for_each(ptr, &local->sta_list) {
02074                 sta = list_entry(ptr, struct sta_info, list);
02075                 if (sta->dev == dev &&
02076                     time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
02077                                jiffies)) {
02078                         active++;
02079                         break;
02080                 }
02081         }
02082 #endif
02083 
02084         return active;
02085 }
02086 
02087 
02088 static void ieee80211_sta_expire(struct wpa_supplicant *wpa_s)
02089 {
02090 #if 0 /* FIX */
02091         list_for_each_safe(ptr, n, &local->sta_list) {
02092                 sta = list_entry(ptr, struct sta_info, list);
02093                 if (time_after(jiffies, sta->last_rx +
02094                                IEEE80211_IBSS_INACTIVITY_LIMIT)) {
02095                         wpa_printf(MSG_DEBUG, "MLME: expiring inactive STA "
02096                                    MACSTR, MAC2STR(sta->addr));
02097                         sta_info_free(local, sta, 1);
02098                 }
02099         }
02100 #endif
02101 }
02102 
02103 
02104 static void ieee80211_sta_merge_ibss(struct wpa_supplicant *wpa_s)
02105 {
02106         struct wpa_driver_scan_params params;
02107 
02108         ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL);
02109 
02110         ieee80211_sta_expire(wpa_s);
02111         if (ieee80211_sta_active_ibss(wpa_s))
02112                 return;
02113 
02114         wpa_printf(MSG_DEBUG, "MLME: No active IBSS STAs - trying to scan for "
02115                    "other IBSS networks with same SSID (merge)");
02116         os_memset(&params, 0, sizeof(params));
02117         params.ssids[0].ssid = wpa_s->mlme.ssid;
02118         params.ssids[0].ssid_len = wpa_s->mlme.ssid_len;
02119         params.num_ssids = wpa_s->mlme.ssid_len ? 1 : 0;
02120         ieee80211_sta_req_scan(wpa_s, &params);
02121 }
02122 
02123 
02124 static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx)
02125 {
02126         struct wpa_supplicant *wpa_s = eloop_ctx;
02127 
02128         switch (wpa_s->mlme.state) {
02129         case IEEE80211_DISABLED:
02130                 break;
02131         case IEEE80211_AUTHENTICATE:
02132                 ieee80211_authenticate(wpa_s);
02133                 break;
02134         case IEEE80211_ASSOCIATE:
02135                 ieee80211_associate(wpa_s);
02136                 break;
02137         case IEEE80211_ASSOCIATED:
02138                 ieee80211_associated(wpa_s);
02139                 break;
02140         case IEEE80211_IBSS_SEARCH:
02141                 ieee80211_sta_find_ibss(wpa_s);
02142                 break;
02143         case IEEE80211_IBSS_JOINED:
02144                 ieee80211_sta_merge_ibss(wpa_s);
02145                 break;
02146         default:
02147                 wpa_printf(MSG_DEBUG, "ieee80211_sta_timer: Unknown state %d",
02148                            wpa_s->mlme.state);
02149                 break;
02150         }
02151 
02152         if (ieee80211_privacy_mismatch(wpa_s)) {
02153                 wpa_printf(MSG_DEBUG, "MLME: privacy configuration mismatch "
02154                            "and mixed-cell disabled - disassociate");
02155 
02156                 ieee80211_send_disassoc(wpa_s, WLAN_REASON_UNSPECIFIED);
02157                 ieee80211_set_associated(wpa_s, 0);
02158         }
02159 }
02160 
02161 
02162 static void ieee80211_sta_new_auth(struct wpa_supplicant *wpa_s)
02163 {
02164         struct wpa_ssid *ssid = wpa_s->current_ssid;
02165         if (ssid && ssid->mode != WPAS_MODE_INFRA)
02166                 return;
02167 
02168 #if 0 /* FIX */
02169         if (local->hw->reset_tsf) {
02170                 /* Reset own TSF to allow time synchronization work. */
02171                 local->hw->reset_tsf(local->mdev);
02172         }
02173 #endif
02174 
02175         wpa_s->mlme.wmm_last_param_set = -1; /* allow any WMM update */
02176 
02177 
02178         if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_OPEN)
02179                 wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN;
02180         else if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_SHARED)
02181                 wpa_s->mlme.auth_alg = WLAN_AUTH_SHARED_KEY;
02182         else if (wpa_s->mlme.auth_algs & WPA_AUTH_ALG_LEAP)
02183                 wpa_s->mlme.auth_alg = WLAN_AUTH_LEAP;
02184         else
02185                 wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN;
02186         wpa_printf(MSG_DEBUG, "MLME: Initial auth_alg=%d",
02187                    wpa_s->mlme.auth_alg);
02188         wpa_s->mlme.auth_transaction = -1;
02189         wpa_s->mlme.auth_tries = wpa_s->mlme.assoc_tries = 0;
02190         ieee80211_authenticate(wpa_s);
02191 }
02192 
02193 
02194 static int ieee80211_ibss_allowed(struct wpa_supplicant *wpa_s)
02195 {
02196 #if 0 /* FIX */
02197         int m, c;
02198 
02199         for (m = 0; m < local->hw->num_modes; m++) {
02200                 struct ieee80211_hw_modes *mode = &local->hw->modes[m];
02201                 if (mode->mode != local->conf.phymode)
02202                         continue;
02203                 for (c = 0; c < mode->num_channels; c++) {
02204                         struct ieee80211_channel *chan = &mode->channels[c];
02205                         if (chan->flag & IEEE80211_CHAN_W_SCAN &&
02206                             chan->chan == local->conf.channel) {
02207                                 if (chan->flag & IEEE80211_CHAN_W_IBSS)
02208                                         return 1;
02209                                 break;
02210                         }
02211                 }
02212         }
02213 #endif
02214 
02215         return 0;
02216 }
02217 
02218 
02219 static int ieee80211_sta_join_ibss(struct wpa_supplicant *wpa_s,
02220                                    struct ieee80211_sta_bss *bss)
02221 {
02222         int res = 0, rates, done = 0, bssid_changed;
02223         struct ieee80211_mgmt *mgmt;
02224 #if 0 /* FIX */
02225         struct ieee80211_tx_control control;
02226         struct ieee80211_rate *rate;
02227         struct rate_control_extra extra;
02228 #endif
02229         u8 *pos, *buf;
02230         size_t len;
02231 
02232         /* Remove possible STA entries from other IBSS networks. */
02233 #if 0 /* FIX */
02234         sta_info_flush(local, NULL);
02235 
02236         if (local->hw->reset_tsf) {
02237                 /* Reset own TSF to allow time synchronization work. */
02238                 local->hw->reset_tsf(local->mdev);
02239         }
02240 #endif
02241         bssid_changed = os_memcmp(wpa_s->bssid, bss->bssid, ETH_ALEN);
02242         os_memcpy(wpa_s->bssid, bss->bssid, ETH_ALEN);
02243         if (bssid_changed)
02244                 wpas_notify_bssid_changed(wpa_s);
02245 
02246 #if 0 /* FIX */
02247         local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
02248 
02249         sdata->drop_unencrypted = bss->capability &
02250                 host_to_le16(WLAN_CAPABILITY_PRIVACY) ? 1 : 0;
02251 #endif
02252 
02253 #if 0 /* FIX */
02254         os_memset(&rq, 0, sizeof(rq));
02255         rq.m = bss->freq * 100000;
02256         rq.e = 1;
02257         res = ieee80211_ioctl_siwfreq(wpa_s, NULL, &rq, NULL);
02258 #endif
02259 
02260         if (!ieee80211_ibss_allowed(wpa_s)) {
02261 #if 0 /* FIX */
02262                 wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed on channel %d "
02263                            "(%d MHz)", local->conf.channel,
02264                            local->conf.freq);
02265 #endif
02266                 return -1;
02267         }
02268 
02269         /* Set beacon template based on scan results */
02270         buf = os_malloc(400);
02271         len = 0;
02272         do {
02273                 if (buf == NULL)
02274                         break;
02275 
02276                 mgmt = (struct ieee80211_mgmt *) buf;
02277                 len += 24 + sizeof(mgmt->u.beacon);
02278                 os_memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
02279                 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
02280                                                    WLAN_FC_STYPE_BEACON);
02281                 os_memset(mgmt->da, 0xff, ETH_ALEN);
02282                 os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
02283                 os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
02284 #if 0 /* FIX */
02285                 mgmt->u.beacon.beacon_int =
02286                         host_to_le16(local->conf.beacon_int);
02287 #endif
02288                 mgmt->u.beacon.capab_info = host_to_le16(bss->capability);
02289 
02290                 pos = buf + len;
02291                 len += 2 + wpa_s->mlme.ssid_len;
02292                 *pos++ = WLAN_EID_SSID;
02293                 *pos++ = wpa_s->mlme.ssid_len;
02294                 os_memcpy(pos, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
02295 
02296                 rates = bss->supp_rates_len;
02297                 if (rates > 8)
02298                         rates = 8;
02299                 pos = buf + len;
02300                 len += 2 + rates;
02301                 *pos++ = WLAN_EID_SUPP_RATES;
02302                 *pos++ = rates;
02303                 os_memcpy(pos, bss->supp_rates, rates);
02304 
02305                 pos = buf + len;
02306                 len += 2 + 1;
02307                 *pos++ = WLAN_EID_DS_PARAMS;
02308                 *pos++ = 1;
02309                 *pos++ = bss->channel;
02310 
02311                 pos = buf + len;
02312                 len += 2 + 2;
02313                 *pos++ = WLAN_EID_IBSS_PARAMS;
02314                 *pos++ = 2;
02315                 /* FIX: set ATIM window based on scan results */
02316                 *pos++ = 0;
02317                 *pos++ = 0;
02318 
02319                 if (bss->supp_rates_len > 8) {
02320                         rates = bss->supp_rates_len - 8;
02321                         pos = buf + len;
02322                         len += 2 + rates;
02323                         *pos++ = WLAN_EID_EXT_SUPP_RATES;
02324                         *pos++ = rates;
02325                         os_memcpy(pos, &bss->supp_rates[8], rates);
02326                 }
02327 
02328 #if 0 /* FIX */
02329                 os_memset(&control, 0, sizeof(control));
02330                 control.pkt_type = PKT_PROBE_RESP;
02331                 os_memset(&extra, 0, sizeof(extra));
02332                 extra.endidx = local->num_curr_rates;
02333                 rate = rate_control_get_rate(wpa_s, skb, &extra);
02334                 if (rate == NULL) {
02335                         wpa_printf(MSG_DEBUG, "MLME: Failed to determine TX "
02336                                    "rate for IBSS beacon");
02337                         break;
02338                 }
02339                 control.tx_rate = (wpa_s->mlme.short_preamble &&
02340                                    (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
02341                         rate->val2 : rate->val;
02342                 control.antenna_sel = local->conf.antenna_sel;
02343                 control.power_level = local->conf.power_level;
02344                 control.no_ack = 1;
02345                 control.retry_limit = 1;
02346                 control.rts_cts_duration = 0;
02347 #endif
02348 
02349 #if 0 /* FIX */
02350                 wpa_s->mlme.probe_resp = skb_copy(skb, GFP_ATOMIC);
02351                 if (wpa_s->mlme.probe_resp) {
02352                         mgmt = (struct ieee80211_mgmt *)
02353                                 wpa_s->mlme.probe_resp->data;
02354                         mgmt->frame_control =
02355                                 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
02356                                              WLAN_FC_STYPE_PROBE_RESP);
02357                 } else {
02358                         wpa_printf(MSG_DEBUG, "MLME: Could not allocate "
02359                                    "ProbeResp template for IBSS");
02360                 }
02361 
02362                 if (local->hw->beacon_update &&
02363                     local->hw->beacon_update(wpa_s, skb, &control) == 0) {
02364                         wpa_printf(MSG_DEBUG, "MLME: Configured IBSS beacon "
02365                                    "template based on scan results");
02366                         skb = NULL;
02367                 }
02368 
02369                 rates = 0;
02370                 for (i = 0; i < bss->supp_rates_len; i++) {
02371                         int rate = (bss->supp_rates[i] & 0x7f) * 5;
02372                         if (local->conf.phymode == MODE_ATHEROS_TURBO)
02373                                 rate *= 2;
02374                         for (j = 0; j < local->num_curr_rates; j++)
02375                                 if (local->curr_rates[j] == rate)
02376                                         rates |= BIT(j);
02377                 }
02378                 wpa_s->mlme.supp_rates_bits = rates;
02379 #endif
02380                 done = 1;
02381         } while (0);
02382 
02383         os_free(buf);
02384         if (!done) {
02385                 wpa_printf(MSG_DEBUG, "MLME: Failed to configure IBSS beacon "
02386                            "template");
02387         }
02388 
02389         wpa_s->mlme.state = IEEE80211_IBSS_JOINED;
02390         ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL);
02391 
02392         return res;
02393 }
02394 
02395 
02396 #if 0 /* FIX */
02397 static int ieee80211_sta_create_ibss(struct wpa_supplicant *wpa_s)
02398 {
02399         struct ieee80211_sta_bss *bss;
02400         u8 bssid[ETH_ALEN], *pos;
02401         int i;
02402 
02403 #if 0
02404         /* Easier testing, use fixed BSSID. */
02405         os_memset(bssid, 0xfe, ETH_ALEN);
02406 #else
02407         /* Generate random, not broadcast, locally administered BSSID. Mix in
02408          * own MAC address to make sure that devices that do not have proper
02409          * random number generator get different BSSID. */
02410         os_get_random(bssid, ETH_ALEN);
02411         for (i = 0; i < ETH_ALEN; i++)
02412                 bssid[i] ^= wpa_s->own_addr[i];
02413         bssid[0] &= ~0x01;
02414         bssid[0] |= 0x02;
02415 #endif
02416 
02417         wpa_printf(MSG_DEBUG, "MLME: Creating new IBSS network, BSSID "
02418                    MACSTR "", MAC2STR(bssid));
02419 
02420         bss = ieee80211_bss_add(wpa_s, bssid);
02421         if (bss == NULL)
02422                 return -ENOMEM;
02423 
02424 #if 0 /* FIX */
02425         if (local->conf.beacon_int == 0)
02426                 local->conf.beacon_int = 100;
02427         bss->beacon_int = local->conf.beacon_int;
02428         bss->hw_mode = local->conf.phymode;
02429         bss->channel = local->conf.channel;
02430         bss->freq = local->conf.freq;
02431 #endif
02432         os_get_time(&bss->last_update);
02433         bss->capability = host_to_le16(WLAN_CAPABILITY_IBSS);
02434 #if 0 /* FIX */
02435         if (sdata->default_key) {
02436                 bss->capability |= host_to_le16(WLAN_CAPABILITY_PRIVACY);
02437         } else
02438                 sdata->drop_unencrypted = 0;
02439         bss->supp_rates_len = local->num_curr_rates;
02440 #endif
02441         pos = bss->supp_rates;
02442 #if 0 /* FIX */
02443         for (i = 0; i < local->num_curr_rates; i++) {
02444                 int rate = local->curr_rates[i];
02445                 if (local->conf.phymode == MODE_ATHEROS_TURBO)
02446                         rate /= 2;
02447                 *pos++ = (u8) (rate / 5);
02448         }
02449 #endif
02450 
02451         return ieee80211_sta_join_ibss(wpa_s, bss);
02452 }
02453 #endif
02454 
02455 
02456 static int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s)
02457 {
02458         struct ieee80211_sta_bss *bss;
02459         int found = 0;
02460         u8 bssid[ETH_ALEN];
02461         int active_ibss;
02462         struct os_time now;
02463 
02464         if (wpa_s->mlme.ssid_len == 0)
02465                 return -EINVAL;
02466 
02467         active_ibss = ieee80211_sta_active_ibss(wpa_s);
02468 #ifdef IEEE80211_IBSS_DEBUG
02469         wpa_printf(MSG_DEBUG, "MLME: sta_find_ibss (active_ibss=%d)",
02470                    active_ibss);
02471 #endif /* IEEE80211_IBSS_DEBUG */
02472         for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) {
02473                 if (wpa_s->mlme.ssid_len != bss->ssid_len ||
02474                     os_memcmp(wpa_s->mlme.ssid, bss->ssid, bss->ssid_len) != 0
02475                     || !(bss->capability & WLAN_CAPABILITY_IBSS))
02476                         continue;
02477 #ifdef IEEE80211_IBSS_DEBUG
02478                 wpa_printf(MSG_DEBUG, "   bssid=" MACSTR " found",
02479                            MAC2STR(bss->bssid));
02480 #endif /* IEEE80211_IBSS_DEBUG */
02481                 os_memcpy(bssid, bss->bssid, ETH_ALEN);
02482                 found = 1;
02483                 if (active_ibss ||
02484                     os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0)
02485                         break;
02486         }
02487 
02488 #ifdef IEEE80211_IBSS_DEBUG
02489         wpa_printf(MSG_DEBUG, "   sta_find_ibss: selected " MACSTR " current "
02490                    MACSTR, MAC2STR(bssid), MAC2STR(wpa_s->bssid));
02491 #endif /* IEEE80211_IBSS_DEBUG */
02492         if (found && os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) != 0 &&
02493             (bss = ieee80211_bss_get(wpa_s, bssid))) {
02494                 wpa_printf(MSG_DEBUG, "MLME: Selected IBSS BSSID " MACSTR
02495                            " based on configured SSID",
02496                            MAC2STR(bssid));
02497                 return ieee80211_sta_join_ibss(wpa_s, bss);
02498         }
02499 #ifdef IEEE80211_IBSS_DEBUG
02500         wpa_printf(MSG_DEBUG, "   did not try to join ibss");
02501 #endif /* IEEE80211_IBSS_DEBUG */
02502 
02503         /* Selected IBSS not found in current scan results - try to scan */
02504         os_get_time(&now);
02505 #if 0 /* FIX */
02506         if (wpa_s->mlme.state == IEEE80211_IBSS_JOINED &&
02507             !ieee80211_sta_active_ibss(wpa_s)) {
02508                 ieee80211_reschedule_timer(wpa_s,
02509                                            IEEE80211_IBSS_MERGE_INTERVAL);
02510         } else if (time_after(jiffies, wpa_s->mlme.last_scan_completed +
02511                               IEEE80211_SCAN_INTERVAL)) {
02512                 wpa_printf(MSG_DEBUG, "MLME: Trigger new scan to find an IBSS "
02513                            "to join");
02514                 return ieee80211_sta_req_scan(wpa_s->mlme.ssid,
02515                                               wpa_s->mlme.ssid_len);
02516         } else if (wpa_s->mlme.state != IEEE80211_IBSS_JOINED) {
02517                 int interval = IEEE80211_SCAN_INTERVAL;
02518 
02519                 if (time_after(jiffies, wpa_s->mlme.ibss_join_req +
02520                                IEEE80211_IBSS_JOIN_TIMEOUT)) {
02521                         if (wpa_s->mlme.create_ibss &&
02522                             ieee80211_ibss_allowed(wpa_s))
02523                                 return ieee80211_sta_create_ibss(wpa_s);
02524                         if (wpa_s->mlme.create_ibss) {
02525                                 wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed "
02526                                            "on the configured channel %d "
02527                                            "(%d MHz)",
02528                                            local->conf.channel,
02529                                            local->conf.freq);
02530                         }
02531 
02532                         /* No IBSS found - decrease scan interval and continue
02533                          * scanning. */
02534                         interval = IEEE80211_SCAN_INTERVAL_SLOW;
02535                 }
02536 
02537                 wpa_s->mlme.state = IEEE80211_IBSS_SEARCH;
02538                 ieee80211_reschedule_timer(wpa_s, interval);
02539                 return 0;
02540         }
02541 #endif
02542 
02543         return 0;
02544 }
02545 
02546 
02547 int ieee80211_sta_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid,
02548                            size_t *len)
02549 {
02550         os_memcpy(ssid, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
02551         *len = wpa_s->mlme.ssid_len;
02552         return 0;
02553 }
02554 
02555 
02556 int ieee80211_sta_associate(struct wpa_supplicant *wpa_s,
02557                             struct wpa_driver_associate_params *params)
02558 {
02559         struct ieee80211_sta_bss *bss;
02560         int bssid_changed;
02561 
02562         wpa_s->mlme.bssid_set = 0;
02563         wpa_s->mlme.freq = params->freq;
02564         if (params->bssid) {
02565                 bssid_changed = os_memcmp(wpa_s->bssid, params->bssid,
02566                                           ETH_ALEN);
02567                 os_memcpy(wpa_s->bssid, params->bssid, ETH_ALEN);
02568                 if (bssid_changed)
02569                         wpas_notify_bssid_changed(wpa_s);
02570 
02571                 if (!is_zero_ether_addr(params->bssid))
02572                         wpa_s->mlme.bssid_set = 1;
02573                 bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
02574                 if (bss) {
02575                         wpa_s->mlme.phymode = bss->hw_mode;
02576                         wpa_s->mlme.channel = bss->channel;
02577                         wpa_s->mlme.freq = bss->freq;
02578                 }
02579         }
02580 
02581 #if 0 /* FIX */
02582         /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is
02583          * not defined. */
02584         if (local->hw->conf_tx) {
02585                 struct ieee80211_tx_queue_params qparam;
02586                 int i;
02587 
02588                 os_memset(&qparam, 0, sizeof(qparam));
02589                 /* TODO: are these ok defaults for all hw_modes? */
02590                 qparam.aifs = 2;
02591                 qparam.cw_min =
02592                         local->conf.phymode == MODE_IEEE80211B ? 31 : 15;
02593                 qparam.cw_max = 1023;
02594                 qparam.burst_time = 0;
02595                 for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
02596                 {
02597                         local->hw->conf_tx(wpa_s, i + IEEE80211_TX_QUEUE_DATA0,
02598                                            &qparam);
02599                 }
02600                 /* IBSS uses different parameters for Beacon sending */
02601                 qparam.cw_min++;
02602                 qparam.cw_min *= 2;
02603                 qparam.cw_min--;
02604                 local->hw->conf_tx(wpa_s, IEEE80211_TX_QUEUE_BEACON, &qparam);
02605         }
02606 #endif
02607 
02608         if (wpa_s->mlme.ssid_len != params->ssid_len ||
02609             os_memcmp(wpa_s->mlme.ssid, params->ssid, params->ssid_len) != 0)
02610                 wpa_s->mlme.prev_bssid_set = 0;
02611         os_memcpy(wpa_s->mlme.ssid, params->ssid, params->ssid_len);
02612         os_memset(wpa_s->mlme.ssid + params->ssid_len, 0,
02613                   MAX_SSID_LEN - params->ssid_len);
02614         wpa_s->mlme.ssid_len = params->ssid_len;
02615         wpa_s->mlme.ssid_set = 1;
02616 
02617         os_free(wpa_s->mlme.extra_ie);
02618         if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
02619                 wpa_s->mlme.extra_ie = NULL;
02620                 wpa_s->mlme.extra_ie_len = 0;
02621         } else {
02622                 wpa_s->mlme.extra_ie = os_malloc(params->wpa_ie_len);
02623                 if (wpa_s->mlme.extra_ie == NULL) {
02624                         wpa_s->mlme.extra_ie_len = 0;
02625                         return -1;
02626                 }
02627                 os_memcpy(wpa_s->mlme.extra_ie, params->wpa_ie,
02628                           params->wpa_ie_len);
02629                 wpa_s->mlme.extra_ie_len = params->wpa_ie_len;
02630         }
02631 
02632         wpa_s->mlme.key_mgmt = params->key_mgmt_suite;
02633 
02634         ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode,
02635                                   wpa_s->mlme.channel, wpa_s->mlme.freq);
02636 
02637         if (params->mode == WPAS_MODE_IBSS && !wpa_s->mlme.bssid_set) {
02638                 os_get_time(&wpa_s->mlme.ibss_join_req);
02639                 wpa_s->mlme.state = IEEE80211_IBSS_SEARCH;
02640                 return ieee80211_sta_find_ibss(wpa_s);
02641         }
02642 
02643         if (wpa_s->mlme.bssid_set)
02644                 ieee80211_sta_new_auth(wpa_s);
02645 
02646         return 0;
02647 }
02648 
02649 
02650 static void ieee80211_sta_save_oper_chan(struct wpa_supplicant *wpa_s)
02651 {
02652         wpa_s->mlme.scan_oper_channel = wpa_s->mlme.channel;
02653         wpa_s->mlme.scan_oper_freq = wpa_s->mlme.freq;
02654         wpa_s->mlme.scan_oper_phymode = wpa_s->mlme.phymode;
02655 }
02656 
02657 
02658 static int ieee80211_sta_restore_oper_chan(struct wpa_supplicant *wpa_s)
02659 {
02660         wpa_s->mlme.channel = wpa_s->mlme.scan_oper_channel;
02661         wpa_s->mlme.freq = wpa_s->mlme.scan_oper_freq;
02662         wpa_s->mlme.phymode = wpa_s->mlme.scan_oper_phymode;
02663         if (wpa_s->mlme.freq == 0)
02664                 return 0;
02665         return ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode,
02666                                          wpa_s->mlme.channel,
02667                                          wpa_s->mlme.freq);
02668 }
02669 
02670 
02671 static int ieee80211_active_scan(struct wpa_supplicant *wpa_s)
02672 {
02673         size_t m;
02674         int c;
02675 
02676         for (m = 0; m < wpa_s->mlme.num_modes; m++) {
02677                 struct hostapd_hw_modes *mode = &wpa_s->mlme.modes[m];
02678                 if ((int) mode->mode != (int) wpa_s->mlme.phymode)
02679                         continue;
02680                 for (c = 0; c < mode->num_channels; c++) {
02681                         struct hostapd_channel_data *chan = &mode->channels[c];
02682                         if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
02683                             chan->chan == wpa_s->mlme.channel) {
02684                                 if (!(chan->flag & HOSTAPD_CHAN_PASSIVE_SCAN))
02685                                         return 1;
02686                                 break;
02687                         }
02688                 }
02689         }
02690 
02691         return 0;
02692 }
02693 
02694 
02695 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx)
02696 {
02697         struct wpa_supplicant *wpa_s = eloop_ctx;
02698         struct hostapd_hw_modes *mode;
02699         struct hostapd_channel_data *chan;
02700         int skip = 0;
02701         int timeout = 0;
02702         struct wpa_ssid *ssid = wpa_s->current_ssid;
02703         int adhoc;
02704 
02705         if (!wpa_s->mlme.sta_scanning || wpa_s->mlme.modes == NULL)
02706                 return;
02707 
02708         adhoc = ssid && ssid->mode == 1;
02709 
02710         switch (wpa_s->mlme.scan_state) {
02711         case SCAN_SET_CHANNEL:
02712                 mode = &wpa_s->mlme.modes[wpa_s->mlme.scan_hw_mode_idx];
02713                 if (wpa_s->mlme.scan_hw_mode_idx >=
02714                     (int) wpa_s->mlme.num_modes ||
02715                     (wpa_s->mlme.scan_hw_mode_idx + 1 ==
02716                      (int) wpa_s->mlme.num_modes
02717                      && wpa_s->mlme.scan_channel_idx >= mode->num_channels)) {
02718                         if (ieee80211_sta_restore_oper_chan(wpa_s)) {
02719                                 wpa_printf(MSG_DEBUG, "MLME: failed to "
02720                                            "restore operational channel after "
02721                                            "scan");
02722                         }
02723                         wpa_printf(MSG_DEBUG, "MLME: scan completed");
02724                         wpa_s->mlme.sta_scanning = 0;
02725                         os_get_time(&wpa_s->mlme.last_scan_completed);
02726                         wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
02727                         if (adhoc) {
02728                                 if (!wpa_s->mlme.bssid_set ||
02729                                     (wpa_s->mlme.state ==
02730                                      IEEE80211_IBSS_JOINED &&
02731                                      !ieee80211_sta_active_ibss(wpa_s)))
02732                                         ieee80211_sta_find_ibss(wpa_s);
02733                         }
02734                         return;
02735                 }
02736                 skip = !(wpa_s->mlme.hw_modes & (1 << mode->mode));
02737                 chan = &mode->channels[wpa_s->mlme.scan_channel_idx];
02738                 if ((chan->flag & HOSTAPD_CHAN_DISABLED) ||
02739                     (adhoc && (chan->flag & HOSTAPD_CHAN_NO_IBSS)) ||
02740                     (wpa_s->mlme.hw_modes & (1 << HOSTAPD_MODE_IEEE80211G) &&
02741                      mode->mode == HOSTAPD_MODE_IEEE80211B &&
02742                      wpa_s->mlme.scan_skip_11b))
02743                         skip = 1;
02744                 if (!skip && wpa_s->mlme.scan_freqs) {
02745                         int i, found = 0;
02746                         for (i = 0; wpa_s->mlme.scan_freqs[i]; i++) {
02747                                 if (wpa_s->mlme.scan_freqs[i] == chan->freq) {
02748                                         found = 1;
02749                                         break;
02750                                 }
02751                         }
02752                         if (!found)
02753                                 skip = 1;
02754                 }
02755 
02756                 if (!skip) {
02757                         wpa_printf(MSG_MSGDUMP,
02758                                    "MLME: scan channel %d (%d MHz)",
02759                                    chan->chan, chan->freq);
02760 
02761                         wpa_s->mlme.channel = chan->chan;
02762                         wpa_s->mlme.freq = chan->freq;
02763                         wpa_s->mlme.phymode = mode->mode;
02764                         if (ieee80211_sta_set_channel(wpa_s, mode->mode,
02765                                                       chan->chan, chan->freq))
02766                         {
02767                                 wpa_printf(MSG_DEBUG, "MLME: failed to set "
02768                                            "channel %d (%d MHz) for scan",
02769                                            chan->chan, chan->freq);
02770                                 skip = 1;
02771                         }
02772                 }
02773 
02774                 wpa_s->mlme.scan_channel_idx++;
02775                 if (wpa_s->mlme.scan_channel_idx >=
02776                     wpa_s->mlme.modes[wpa_s->mlme.scan_hw_mode_idx].
02777                     num_channels) {
02778                         wpa_s->mlme.scan_hw_mode_idx++;
02779                         wpa_s->mlme.scan_channel_idx = 0;
02780                 }
02781 
02782                 if (skip) {
02783                         timeout = 0;
02784                         break;
02785                 }
02786 
02787                 timeout = IEEE80211_PROBE_DELAY;
02788                 wpa_s->mlme.scan_state = SCAN_SEND_PROBE;
02789                 break;
02790         case SCAN_SEND_PROBE:
02791                 if (ieee80211_active_scan(wpa_s)) {
02792                         ieee80211_send_probe_req(wpa_s, NULL,
02793                                                  wpa_s->mlme.scan_ssid,
02794                                                  wpa_s->mlme.scan_ssid_len);
02795                         timeout = IEEE80211_CHANNEL_TIME;
02796                 } else {
02797                         timeout = IEEE80211_PASSIVE_CHANNEL_TIME;
02798                 }
02799                 wpa_s->mlme.scan_state = SCAN_SET_CHANNEL;
02800                 break;
02801         }
02802 
02803         eloop_register_timeout(timeout / 1000, 1000 * (timeout % 1000),
02804                                ieee80211_sta_scan_timer, wpa_s, NULL);
02805 }
02806 
02807 
02808 int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s,
02809                            struct wpa_driver_scan_params *params)
02810 {
02811         const u8 *ssid = params->ssids[0].ssid;
02812         size_t ssid_len = params->ssids[0].ssid_len;
02813 
02814         if (ssid_len > MAX_SSID_LEN)
02815                 return -1;
02816 
02817         /* MLME-SCAN.request (page 118)  page 144 (11.1.3.1)
02818          * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
02819          * BSSID: MACAddress
02820          * SSID
02821          * ScanType: ACTIVE, PASSIVE
02822          * ProbeDelay: delay (in microseconds) to be used prior to transmitting
02823          *    a Probe frame during active scanning
02824          * ChannelList
02825          * MinChannelTime (>= ProbeDelay), in TU
02826          * MaxChannelTime: (>= MinChannelTime), in TU
02827          */
02828 
02829          /* MLME-SCAN.confirm
02830           * BSSDescriptionSet
02831           * ResultCode: SUCCESS, INVALID_PARAMETERS
02832          */
02833 
02834         /* TODO: if assoc, move to power save mode for the duration of the
02835          * scan */
02836 
02837         if (wpa_s->mlme.sta_scanning)
02838                 return -1;
02839 
02840         wpa_printf(MSG_DEBUG, "MLME: starting scan");
02841 
02842         ieee80211_sta_set_probe_req_ie(wpa_s, params->extra_ies,
02843                                        params->extra_ies_len);
02844 
02845         os_free(wpa_s->mlme.scan_freqs);
02846         if (params->freqs) {
02847                 int i;
02848                 for (i = 0; params->freqs[i]; i++)
02849                         ;
02850                 wpa_s->mlme.scan_freqs = os_malloc((i + 1) * sizeof(int));
02851                 if (wpa_s->mlme.scan_freqs)
02852                         os_memcpy(wpa_s->mlme.scan_freqs, params->freqs,
02853                                   (i + 1) * sizeof(int));
02854         } else
02855                 wpa_s->mlme.scan_freqs = NULL;
02856 
02857         ieee80211_sta_save_oper_chan(wpa_s);
02858 
02859         wpa_s->mlme.sta_scanning = 1;
02860         /* TODO: stop TX queue? */
02861 
02862         if (ssid) {
02863                 wpa_s->mlme.scan_ssid_len = ssid_len;
02864                 os_memcpy(wpa_s->mlme.scan_ssid, ssid, ssid_len);
02865         } else
02866                 wpa_s->mlme.scan_ssid_len = 0;
02867         wpa_s->mlme.scan_skip_11b = 1; /* FIX: clear this is 11g is not
02868                                         * supported */
02869         wpa_s->mlme.scan_state = SCAN_SET_CHANNEL;
02870         wpa_s->mlme.scan_hw_mode_idx = 0;
02871         wpa_s->mlme.scan_channel_idx = 0;
02872         eloop_register_timeout(0, 1, ieee80211_sta_scan_timer, wpa_s, NULL);
02873 
02874         return 0;
02875 }
02876 
02877 
02878 struct wpa_scan_results *
02879 ieee80211_sta_get_scan_results(struct wpa_supplicant *wpa_s)
02880 {
02881         size_t ap_num = 0;
02882         struct wpa_scan_results *res;
02883         struct wpa_scan_res *r;
02884         struct ieee80211_sta_bss *bss;
02885 
02886         res = os_zalloc(sizeof(*res));
02887         for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next)
02888                 ap_num++;
02889         res->res = os_zalloc(ap_num * sizeof(struct wpa_scan_res *));
02890         if (res->res == NULL) {
02891                 os_free(res);
02892                 return NULL;
02893         }
02894 
02895         for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) {
02896                 r = os_zalloc(sizeof(*r) + bss->ie_len);
02897                 if (r == NULL)
02898                         break;
02899                 os_memcpy(r->bssid, bss->bssid, ETH_ALEN);
02900                 r->freq = bss->freq;
02901                 r->beacon_int = bss->beacon_int;
02902                 r->caps = bss->capability;
02903                 r->level = bss->rssi;
02904                 r->tsf = bss->timestamp;
02905                 if (bss->ie) {
02906                         r->ie_len = bss->ie_len;
02907                         os_memcpy(r + 1, bss->ie, bss->ie_len);
02908                 }
02909 
02910                 res->res[res->num++] = r;
02911         }
02912 
02913         return res;
02914 }
02915 
02916 
02917 #if 0 /* FIX */
02918 struct sta_info * ieee80211_ibss_add_sta(struct wpa_supplicant *wpa_s,
02919                                          struct sk_buff *skb, u8 *bssid,
02920                                          u8 *addr)
02921 {
02922         struct ieee80211_local *local = dev->priv;
02923         struct list_head *ptr;
02924         struct sta_info *sta;
02925         struct wpa_supplicant *sta_dev = NULL;
02926 
02927         /* TODO: Could consider removing the least recently used entry and
02928          * allow new one to be added. */
02929         if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
02930                 if (net_ratelimit()) {
02931                         wpa_printf(MSG_DEBUG, "MLME: No room for a new IBSS "
02932                                    "STA entry " MACSTR, MAC2STR(addr));
02933                 }
02934                 return NULL;
02935         }
02936 
02937         spin_lock_bh(&local->sub_if_lock);
02938         list_for_each(ptr, &local->sub_if_list) {
02939                 sdata = list_entry(ptr, struct ieee80211_sub_if_data, list);
02940                 if (sdata->type == IEEE80211_SUB_IF_TYPE_STA &&
02941                     os_memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
02942                         sta_dev = sdata->dev;
02943                         break;
02944                 }
02945         }
02946         spin_unlock_bh(&local->sub_if_lock);
02947 
02948         if (sta_dev == NULL)
02949                 return NULL;
02950 
02951         wpa_printf(MSG_DEBUG, "MLME: Adding new IBSS station " MACSTR
02952                    " (dev=%s)", MAC2STR(addr), sta_dev->name);
02953 
02954         sta = sta_info_add(wpa_s, addr);
02955         if (sta == NULL) {
02956                 return NULL;
02957         }
02958 
02959         sta->dev = sta_dev;
02960         sta->supp_rates = wpa_s->mlme.supp_rates_bits;
02961 
02962         rate_control_rate_init(local, sta);
02963 
02964         return sta; /* caller will call sta_info_release() */
02965 }
02966 #endif
02967 
02968 
02969 int ieee80211_sta_deauthenticate(struct wpa_supplicant *wpa_s, u16 reason)
02970 {
02971         wpa_printf(MSG_DEBUG, "MLME: deauthenticate(reason=%d)", reason);
02972 
02973         ieee80211_send_deauth(wpa_s, reason);
02974         ieee80211_set_associated(wpa_s, 0);
02975         return 0;
02976 }
02977 
02978 
02979 int ieee80211_sta_disassociate(struct wpa_supplicant *wpa_s, u16 reason)
02980 {
02981         wpa_printf(MSG_DEBUG, "MLME: disassociate(reason=%d)", reason);
02982 
02983         if (!wpa_s->mlme.associated)
02984                 return -1;
02985 
02986         ieee80211_send_disassoc(wpa_s, reason);
02987         ieee80211_set_associated(wpa_s, 0);
02988         return 0;
02989 }
02990 
02991 
02992 void ieee80211_sta_rx(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len,
02993                       struct ieee80211_rx_status *rx_status)
02994 {
02995         struct ieee80211_mgmt *mgmt;
02996         u16 fc;
02997         const u8 *pos;
02998 
02999         /* wpa_hexdump(MSG_MSGDUMP, "MLME: Received frame", buf, len); */
03000 
03001         if (wpa_s->mlme.sta_scanning) {
03002                 ieee80211_sta_rx_scan(wpa_s, buf, len, rx_status);
03003                 return;
03004         }
03005 
03006         if (len < 24)
03007                 return;
03008 
03009         mgmt = (struct ieee80211_mgmt *) buf;
03010         fc = le_to_host16(mgmt->frame_control);
03011 
03012         if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT)
03013                 ieee80211_sta_rx_mgmt(wpa_s, buf, len, rx_status);
03014         else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) {
03015                 if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) !=
03016                     WLAN_FC_FROMDS)
03017                         return;
03018                 /* mgmt->sa is actually BSSID for FromDS data frames */
03019                 if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0)
03020                         return;
03021                 /* Skip IEEE 802.11 and LLC headers */
03022                 pos = buf + 24 + 6;
03023                 if (WPA_GET_BE16(pos) != ETH_P_EAPOL)
03024                         return;
03025                 pos += 2;
03026                 /* mgmt->bssid is actually BSSID for SA data frames */
03027                 wpa_supplicant_rx_eapol(wpa_s, mgmt->bssid,
03028                                         pos, buf + len - pos);
03029         }
03030 }
03031 
03032 
03033 void ieee80211_sta_free_hw_features(struct hostapd_hw_modes *hw_features,
03034                                     size_t num_hw_features)
03035 {
03036         size_t i;
03037 
03038         if (hw_features == NULL)
03039                 return;
03040 
03041         for (i = 0; i < num_hw_features; i++) {
03042                 os_free(hw_features[i].channels);
03043                 os_free(hw_features[i].rates);
03044         }
03045 
03046         os_free(hw_features);
03047 }
03048 
03049 
03050 int ieee80211_sta_init(struct wpa_supplicant *wpa_s)
03051 {
03052         u16 num_modes, flags;
03053 
03054         wpa_s->mlme.modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes,
03055                                                         &flags);
03056         if (wpa_s->mlme.modes == NULL) {
03057                 wpa_printf(MSG_ERROR, "MLME: Failed to read supported "
03058                            "channels and rates from the driver");
03059                 return -1;
03060         }
03061 
03062         wpa_s->mlme.num_modes = num_modes;
03063 
03064         wpa_s->mlme.hw_modes = 1 << HOSTAPD_MODE_IEEE80211A;
03065         wpa_s->mlme.hw_modes |= 1 << HOSTAPD_MODE_IEEE80211B;
03066         wpa_s->mlme.hw_modes |= 1 << HOSTAPD_MODE_IEEE80211G;
03067 
03068         wpa_s->mlme.wmm_enabled = 1;
03069 
03070         return 0;
03071 }
03072 
03073 
03074 void ieee80211_sta_deinit(struct wpa_supplicant *wpa_s)
03075 {
03076         eloop_cancel_timeout(ieee80211_sta_timer, wpa_s, NULL);
03077         eloop_cancel_timeout(ieee80211_sta_scan_timer, wpa_s, NULL);
03078         os_free(wpa_s->mlme.extra_ie);
03079         wpa_s->mlme.extra_ie = NULL;
03080         os_free(wpa_s->mlme.extra_probe_ie);
03081         wpa_s->mlme.extra_probe_ie = NULL;
03082         os_free(wpa_s->mlme.assocreq_ies);
03083         wpa_s->mlme.assocreq_ies = NULL;
03084         os_free(wpa_s->mlme.assocresp_ies);
03085         wpa_s->mlme.assocresp_ies = NULL;
03086         ieee80211_bss_list_deinit(wpa_s);
03087         ieee80211_sta_free_hw_features(wpa_s->mlme.modes,
03088                                        wpa_s->mlme.num_modes);
03089 #ifdef CONFIG_IEEE80211R
03090         os_free(wpa_s->mlme.ft_ies);
03091         wpa_s->mlme.ft_ies = NULL;
03092         wpa_s->mlme.ft_ies_len = 0;
03093 #endif /* CONFIG_IEEE80211R */
03094 
03095         os_free(wpa_s->mlme.scan_freqs);
03096         wpa_s->mlme.scan_freqs = NULL;
03097 }
03098 
03099 
03100 #ifdef CONFIG_IEEE80211R
03101 
03102 int ieee80211_sta_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
03103                                 const u8 *ies, size_t ies_len)
03104 {
03105         if (md == NULL) {
03106                 wpa_printf(MSG_DEBUG, "MLME: Clear FT mobility domain");
03107                 os_memset(wpa_s->mlme.current_md, 0, MOBILITY_DOMAIN_ID_LEN);
03108         } else {
03109                 wpa_printf(MSG_DEBUG, "MLME: Update FT IEs for MD " MACSTR,
03110                            MAC2STR(md));
03111                 os_memcpy(wpa_s->mlme.current_md, md, MOBILITY_DOMAIN_ID_LEN);
03112         }
03113 
03114         wpa_hexdump(MSG_DEBUG, "MLME: FT IEs", ies, ies_len);
03115         os_free(wpa_s->mlme.ft_ies);
03116         wpa_s->mlme.ft_ies = os_malloc(ies_len);
03117         if (wpa_s->mlme.ft_ies == NULL)
03118                 return -1;
03119         os_memcpy(wpa_s->mlme.ft_ies, ies, ies_len);
03120         wpa_s->mlme.ft_ies_len = ies_len;
03121 
03122         return 0;
03123 }
03124 
03125 
03126 int ieee80211_sta_send_ft_action(struct wpa_supplicant *wpa_s, u8 action,
03127                                  const u8 *target_ap,
03128                                  const u8 *ies, size_t ies_len)
03129 {
03130         u8 *buf;
03131         size_t len;
03132         struct ieee80211_mgmt *mgmt;
03133         int res;
03134 
03135         /*
03136          * Action frame payload:
03137          * Category[1] = 6 (Fast BSS Transition)
03138          * Action[1] = 1 (Fast BSS Transition Request)
03139          * STA Address
03140          * Target AP Address
03141          * FT IEs
03142          */
03143 
03144         buf = os_zalloc(sizeof(*mgmt) + ies_len);
03145         if (buf == NULL) {
03146                 wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
03147                            "FT action frame");
03148                 return -1;
03149         }
03150 
03151         mgmt = (struct ieee80211_mgmt *) buf;
03152         len = 24;
03153         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
03154         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
03155         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
03156         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
03157                                            WLAN_FC_STYPE_ACTION);
03158         mgmt->u.action.category = WLAN_ACTION_FT;
03159         mgmt->u.action.u.ft_action_req.action = action;
03160         os_memcpy(mgmt->u.action.u.ft_action_req.sta_addr, wpa_s->own_addr,
03161                   ETH_ALEN);
03162         os_memcpy(mgmt->u.action.u.ft_action_req.target_ap_addr, target_ap,
03163                   ETH_ALEN);
03164         os_memcpy(mgmt->u.action.u.ft_action_req.variable, ies, ies_len);
03165         len += 1 + sizeof(mgmt->u.action.u.ft_action_req) + ies_len;
03166 
03167         wpa_printf(MSG_DEBUG, "MLME: Send FT Action Frame: Action=%d "
03168                    "Target AP=" MACSTR " body_len=%lu",
03169                    action, MAC2STR(target_ap), (unsigned long) ies_len);
03170 
03171         res = ieee80211_sta_tx(wpa_s, buf, len);
03172         os_free(buf);
03173 
03174         return res;
03175 }
03176 
03177 #endif /* CONFIG_IEEE80211R */
03178 
03179 
03180 static int ieee80211_sta_set_probe_req_ie(struct wpa_supplicant *wpa_s,
03181                                           const u8 *ies, size_t ies_len)
03182 {
03183         os_free(wpa_s->mlme.extra_probe_ie);
03184         wpa_s->mlme.extra_probe_ie = NULL;
03185         wpa_s->mlme.extra_probe_ie_len = 0;
03186 
03187         if (ies == NULL)
03188                 return 0;
03189 
03190         wpa_s->mlme.extra_probe_ie = os_malloc(ies_len);
03191         if (wpa_s->mlme.extra_probe_ie == NULL)
03192                 return -1;
03193 
03194         os_memcpy(wpa_s->mlme.extra_probe_ie, ies, ies_len);
03195         wpa_s->mlme.extra_probe_ie_len = ies_len;
03196 
03197         return 0;
03198 }


wpa_supplicant_node
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:25:14