WMM-AC: Fix hostapd processing of ADDTS Request and add test code
[wpasupplicant] / wpa_supplicant / mlme.c
1 /*
2  * WPA Supplicant - Client mode MLME
3  * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
4  * Copyright (c) 2004, Instant802 Networks, Inc.
5  * Copyright (c) 2005-2006, Devicescape Software, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  * Alternatively, this software may be distributed under the terms of BSD
12  * license.
13  *
14  * See README and COPYING for more details.
15  */
16
17 #include "includes.h"
18
19 #include "common.h"
20 #include "eloop.h"
21 #include "config_ssid.h"
22 #include "wpa_supplicant_i.h"
23 #include "wpa.h"
24 #include "drivers/driver.h"
25 #include "ieee802_11_defs.h"
26 #include "ieee802_11_common.h"
27 #include "mlme.h"
28
29
30 /* Timeouts and intervals in milliseconds */
31 #define IEEE80211_AUTH_TIMEOUT (200)
32 #define IEEE80211_AUTH_MAX_TRIES 3
33 #define IEEE80211_ASSOC_TIMEOUT (200)
34 #define IEEE80211_ASSOC_MAX_TRIES 3
35 #define IEEE80211_MONITORING_INTERVAL (2000)
36 #define IEEE80211_PROBE_INTERVAL (60000)
37 #define IEEE80211_RETRY_AUTH_INTERVAL (1000)
38 #define IEEE80211_SCAN_INTERVAL (2000)
39 #define IEEE80211_SCAN_INTERVAL_SLOW (15000)
40 #define IEEE80211_IBSS_JOIN_TIMEOUT (20000)
41
42 #define IEEE80211_PROBE_DELAY (33)
43 #define IEEE80211_CHANNEL_TIME (33)
44 #define IEEE80211_PASSIVE_CHANNEL_TIME (200)
45 #define IEEE80211_SCAN_RESULT_EXPIRE (10000)
46 #define IEEE80211_IBSS_MERGE_INTERVAL (30000)
47 #define IEEE80211_IBSS_INACTIVITY_LIMIT (60000)
48
49 #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
50
51
52 #define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
53
54
55 struct ieee80211_sta_bss {
56         struct ieee80211_sta_bss *next;
57         struct ieee80211_sta_bss *hnext;
58
59         u8 bssid[ETH_ALEN];
60         u8 ssid[MAX_SSID_LEN];
61         size_t ssid_len;
62         u16 capability; /* host byte order */
63         int hw_mode;
64         int channel;
65         int freq;
66         int rssi;
67         u8 *ie;
68         size_t ie_len;
69         u8 *wpa_ie;
70         size_t wpa_ie_len;
71         u8 *rsn_ie;
72         size_t rsn_ie_len;
73         u8 *wmm_ie;
74         size_t wmm_ie_len;
75         u8 *mdie;
76         size_t mdie_len;
77 #define IEEE80211_MAX_SUPP_RATES 32
78         u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
79         size_t supp_rates_len;
80         int beacon_int;
81         u64 timestamp;
82
83         int probe_resp;
84         struct os_time last_update;
85 };
86
87
88 static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s,
89                                      const u8 *dst,
90                                      const u8 *ssid, size_t ssid_len);
91 static struct ieee80211_sta_bss *
92 ieee80211_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid);
93 static int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s);
94 static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s);
95 static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx);
96 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx);
97
98
99 static int ieee80211_sta_set_channel(struct wpa_supplicant *wpa_s,
100                                      wpa_hw_mode phymode, int chan,
101                                      int freq)
102 {
103         size_t i;
104         struct wpa_hw_modes *mode;
105
106         for (i = 0; i < wpa_s->mlme.num_modes; i++) {
107                 mode = &wpa_s->mlme.modes[i];
108                 if (mode->mode == phymode) {
109                         wpa_s->mlme.curr_rates = mode->rates;
110                         wpa_s->mlme.num_curr_rates = mode->num_rates;
111                         break;
112                 }
113         }
114
115         return wpa_drv_set_channel(wpa_s, phymode, chan, freq);
116 }
117
118
119 static int ecw2cw(int ecw)
120 {
121         int cw = 1;
122         while (ecw > 0) {
123                 cw <<= 1;
124                 ecw--;
125         }
126         return cw - 1;
127 }
128
129
130 static void ieee80211_sta_wmm_params(struct wpa_supplicant *wpa_s,
131                                      u8 *wmm_param, size_t wmm_param_len)
132 {
133         size_t left;
134         int count;
135         u8 *pos;
136         u8 wmm_acm;
137
138         if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
139                 return;
140         count = wmm_param[6] & 0x0f;
141         if (count == wpa_s->mlme.wmm_last_param_set)
142                 return;
143         wpa_s->mlme.wmm_last_param_set = count;
144
145         pos = wmm_param + 8;
146         left = wmm_param_len - 8;
147
148         wmm_acm = 0;
149         for (; left >= 4; left -= 4, pos += 4) {
150                 int aci = (pos[0] >> 5) & 0x03;
151                 int acm = (pos[0] >> 4) & 0x01;
152                 int aifs, cw_max, cw_min, burst_time;
153
154                 switch (aci) {
155                 case 1: /* AC_BK */
156                         if (acm)
157                                 wmm_acm |= BIT(1) | BIT(2); /* BK/- */
158                         break;
159                 case 2: /* AC_VI */
160                         if (acm)
161                                 wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
162                         break;
163                 case 3: /* AC_VO */
164                         if (acm)
165                                 wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
166                         break;
167                 case 0: /* AC_BE */
168                 default:
169                         if (acm)
170                                 wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
171                         break;
172                 }
173
174                 aifs = pos[0] & 0x0f;
175                 cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
176                 cw_min = ecw2cw(pos[1] & 0x0f);
177                 /* TXOP is in units of 32 usec; burst_time in 0.1 ms */
178                 burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
179                 wpa_printf(MSG_DEBUG, "MLME: WMM aci=%d acm=%d aifs=%d "
180                            "cWmin=%d cWmax=%d burst=%d",
181                            aci, acm, aifs, cw_min, cw_max, burst_time);
182                 /* TODO: driver configuration */
183         }
184 }
185
186
187 static void ieee80211_set_associated(struct wpa_supplicant *wpa_s, int assoc)
188 {
189         if (wpa_s->mlme.associated == assoc && !assoc)
190                 return;
191
192         wpa_s->mlme.associated = assoc;
193
194         if (assoc) {
195                 union wpa_event_data data;
196                 os_memset(&data, 0, sizeof(data));
197                 wpa_s->mlme.prev_bssid_set = 1;
198                 os_memcpy(wpa_s->mlme.prev_bssid, wpa_s->bssid, ETH_ALEN);
199                 data.assoc_info.req_ies = wpa_s->mlme.assocreq_ies;
200                 data.assoc_info.req_ies_len = wpa_s->mlme.assocreq_ies_len;
201                 data.assoc_info.resp_ies = wpa_s->mlme.assocresp_ies;
202                 data.assoc_info.resp_ies_len = wpa_s->mlme.assocresp_ies_len;
203                 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
204         } else {
205                 wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL);
206         }
207         os_get_time(&wpa_s->mlme.last_probe);
208 }
209
210
211 static int ieee80211_sta_tx(struct wpa_supplicant *wpa_s, const u8 *buf,
212                             size_t len)
213 {
214         return wpa_drv_send_mlme(wpa_s, buf, len);
215 }
216
217
218 static void ieee80211_send_auth(struct wpa_supplicant *wpa_s,
219                                 int transaction, u8 *extra, size_t extra_len,
220                                 int encrypt)
221 {
222         u8 *buf;
223         size_t len;
224         struct ieee80211_mgmt *mgmt;
225
226         buf = os_malloc(sizeof(*mgmt) + 6 + extra_len);
227         if (buf == NULL) {
228                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
229                            "auth frame");
230                 return;
231         }
232
233         mgmt = (struct ieee80211_mgmt *) buf;
234         len = 24 + 6;
235         os_memset(mgmt, 0, 24 + 6);
236         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
237                                            WLAN_FC_STYPE_AUTH);
238         if (encrypt)
239                 mgmt->frame_control |= host_to_le16(WLAN_FC_ISWEP);
240         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
241         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
242         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
243         mgmt->u.auth.auth_alg = host_to_le16(wpa_s->mlme.auth_alg);
244         mgmt->u.auth.auth_transaction = host_to_le16(transaction);
245         wpa_s->mlme.auth_transaction = transaction + 1;
246         mgmt->u.auth.status_code = host_to_le16(0);
247         if (extra) {
248                 os_memcpy(buf + len, extra, extra_len);
249                 len += extra_len;
250         }
251
252         ieee80211_sta_tx(wpa_s, buf, len);
253         os_free(buf);
254 }
255
256
257 static void ieee80211_reschedule_timer(struct wpa_supplicant *wpa_s, int ms)
258 {
259         eloop_cancel_timeout(ieee80211_sta_timer, wpa_s, NULL);
260         eloop_register_timeout(ms / 1000, 1000 * (ms % 1000),
261                                ieee80211_sta_timer, wpa_s, NULL);
262 }
263
264
265 static void ieee80211_authenticate(struct wpa_supplicant *wpa_s)
266 {
267         u8 *extra;
268         size_t extra_len;
269
270         wpa_s->mlme.auth_tries++;
271         if (wpa_s->mlme.auth_tries > IEEE80211_AUTH_MAX_TRIES) {
272                 wpa_printf(MSG_DEBUG, "MLME: authentication with AP " MACSTR
273                            " timed out", MAC2STR(wpa_s->bssid));
274                 return;
275         }
276
277         wpa_s->mlme.state = IEEE80211_AUTHENTICATE;
278         wpa_printf(MSG_DEBUG, "MLME: authenticate with AP " MACSTR,
279                    MAC2STR(wpa_s->bssid));
280
281         extra = NULL;
282         extra_len = 0;
283
284 #ifdef CONFIG_IEEE80211R
285         if ((wpa_s->mlme.key_mgmt == KEY_MGMT_FT_802_1X ||
286              wpa_s->mlme.key_mgmt == KEY_MGMT_FT_PSK) &&
287             wpa_s->mlme.ft_ies) {
288                 struct ieee80211_sta_bss *bss;
289                 struct rsn_mdie *mdie = NULL;
290                 bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
291                 if (bss && bss->mdie_len >= 2 + sizeof(*mdie))
292                         mdie = (struct rsn_mdie *) (bss->mdie + 2);
293                 if (mdie &&
294                     os_memcmp(mdie->mobility_domain, wpa_s->mlme.current_md,
295                               MOBILITY_DOMAIN_ID_LEN) == 0) {
296                         wpa_printf(MSG_DEBUG, "MLME: Trying to use FT "
297                                    "over-the-air");
298                         wpa_s->mlme.auth_alg = WLAN_AUTH_FT;
299                         extra = wpa_s->mlme.ft_ies;
300                         extra_len = wpa_s->mlme.ft_ies_len;
301                 }
302         }
303 #endif /* CONFIG_IEEE80211R */
304
305         ieee80211_send_auth(wpa_s, 1, extra, extra_len, 0);
306
307         ieee80211_reschedule_timer(wpa_s, IEEE80211_AUTH_TIMEOUT);
308 }
309
310
311 static void ieee80211_send_assoc(struct wpa_supplicant *wpa_s)
312 {
313         struct ieee80211_mgmt *mgmt;
314         u8 *pos, *ies, *buf;
315         int i, len;
316         u16 capab;
317         struct ieee80211_sta_bss *bss;
318         int wmm = 0;
319         size_t blen, buflen;
320
321         if (wpa_s->mlme.curr_rates == NULL) {
322                 wpa_printf(MSG_DEBUG, "MLME: curr_rates not set for assoc");
323                 return;
324         }
325
326         buflen = sizeof(*mgmt) + 200 + wpa_s->mlme.extra_ie_len +
327                 wpa_s->mlme.ssid_len;
328 #ifdef CONFIG_IEEE80211R
329         if (wpa_s->mlme.ft_ies)
330                 buflen += wpa_s->mlme.ft_ies_len;
331 #endif /* CONFIG_IEEE80211R */
332         buf = os_malloc(buflen);
333         if (buf == NULL) {
334                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
335                            "assoc frame");
336                 return;
337         }
338         blen = 0;
339
340         capab = wpa_s->mlme.capab;
341         if (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G) {
342                 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
343                         WLAN_CAPABILITY_SHORT_PREAMBLE;
344         }
345         bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
346         if (bss) {
347                 if (bss->capability & WLAN_CAPABILITY_PRIVACY)
348                         capab |= WLAN_CAPABILITY_PRIVACY;
349                 if (bss->wmm_ie) {
350                         wmm = 1;
351                 }
352         }
353
354         mgmt = (struct ieee80211_mgmt *) buf;
355         blen += 24;
356         os_memset(mgmt, 0, 24);
357         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
358         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
359         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
360
361         if (wpa_s->mlme.prev_bssid_set) {
362                 blen += 10;
363                 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
364                                                    WLAN_FC_STYPE_REASSOC_REQ);
365                 mgmt->u.reassoc_req.capab_info = host_to_le16(capab);
366                 mgmt->u.reassoc_req.listen_interval = host_to_le16(1);
367                 os_memcpy(mgmt->u.reassoc_req.current_ap,
368                           wpa_s->mlme.prev_bssid,
369                           ETH_ALEN);
370         } else {
371                 blen += 4;
372                 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
373                                                    WLAN_FC_STYPE_ASSOC_REQ);
374                 mgmt->u.assoc_req.capab_info = host_to_le16(capab);
375                 mgmt->u.assoc_req.listen_interval = host_to_le16(1);
376         }
377
378         /* SSID */
379         ies = pos = buf + blen;
380         blen += 2 + wpa_s->mlme.ssid_len;
381         *pos++ = WLAN_EID_SSID;
382         *pos++ = wpa_s->mlme.ssid_len;
383         os_memcpy(pos, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
384
385         len = wpa_s->mlme.num_curr_rates;
386         if (len > 8)
387                 len = 8;
388         pos = buf + blen;
389         blen += len + 2;
390         *pos++ = WLAN_EID_SUPP_RATES;
391         *pos++ = len;
392         for (i = 0; i < len; i++) {
393                 int rate = wpa_s->mlme.curr_rates[i].rate;
394                 *pos++ = (u8) (rate / 5);
395         }
396
397         if (wpa_s->mlme.num_curr_rates > len) {
398                 pos = buf + blen;
399                 blen += wpa_s->mlme.num_curr_rates - len + 2;
400                 *pos++ = WLAN_EID_EXT_SUPP_RATES;
401                 *pos++ = wpa_s->mlme.num_curr_rates - len;
402                 for (i = len; i < wpa_s->mlme.num_curr_rates; i++) {
403                         int rate = wpa_s->mlme.curr_rates[i].rate;
404                         *pos++ = (u8) (rate / 5);
405                 }
406         }
407
408         if (wpa_s->mlme.extra_ie && wpa_s->mlme.auth_alg != WLAN_AUTH_FT) {
409                 pos = buf + blen;
410                 blen += wpa_s->mlme.extra_ie_len;
411                 os_memcpy(pos, wpa_s->mlme.extra_ie, wpa_s->mlme.extra_ie_len);
412         }
413
414 #ifdef CONFIG_IEEE80211R
415         if ((wpa_s->mlme.key_mgmt == KEY_MGMT_FT_802_1X ||
416              wpa_s->mlme.key_mgmt == KEY_MGMT_FT_PSK) &&
417             wpa_s->mlme.auth_alg != WLAN_AUTH_FT &&
418             bss && bss->mdie &&
419             bss->mdie_len >= 2 + sizeof(struct rsn_mdie) &&
420             bss->mdie[1] >= sizeof(struct rsn_mdie)) {
421                 pos = buf + blen;
422                 blen += 2 + sizeof(struct rsn_mdie);
423                 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
424                 *pos++ = sizeof(struct rsn_mdie);
425                 os_memcpy(pos, bss->mdie + 2, MOBILITY_DOMAIN_ID_LEN);
426                 pos += MOBILITY_DOMAIN_ID_LEN;
427                 *pos++ = 0; /* FIX: copy from the target AP's MDIE */
428         }
429
430         if ((wpa_s->mlme.key_mgmt == KEY_MGMT_FT_802_1X ||
431              wpa_s->mlme.key_mgmt == KEY_MGMT_FT_PSK) &&
432             wpa_s->mlme.auth_alg == WLAN_AUTH_FT && wpa_s->mlme.ft_ies) {
433                 pos = buf + blen;
434                 os_memcpy(pos, wpa_s->mlme.ft_ies, wpa_s->mlme.ft_ies_len);
435                 pos += wpa_s->mlme.ft_ies_len;
436                 blen += wpa_s->mlme.ft_ies_len;
437         }
438 #endif /* CONFIG_IEEE80211R */
439
440         if (wmm && wpa_s->mlme.wmm_enabled) {
441                 pos = buf + blen;
442                 blen += 9;
443                 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
444                 *pos++ = 7; /* len */
445                 *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
446                 *pos++ = 0x50;
447                 *pos++ = 0xf2;
448                 *pos++ = 2; /* WMM */
449                 *pos++ = 0; /* WMM info */
450                 *pos++ = 1; /* WMM ver */
451                 *pos++ = 0;
452         }
453
454         os_free(wpa_s->mlme.assocreq_ies);
455         wpa_s->mlme.assocreq_ies_len = (buf + blen) - ies;
456         wpa_s->mlme.assocreq_ies = os_malloc(wpa_s->mlme.assocreq_ies_len);
457         if (wpa_s->mlme.assocreq_ies) {
458                 os_memcpy(wpa_s->mlme.assocreq_ies, ies,
459                           wpa_s->mlme.assocreq_ies_len);
460         }
461
462         ieee80211_sta_tx(wpa_s, buf, blen);
463         os_free(buf);
464 }
465
466
467 static void ieee80211_send_deauth(struct wpa_supplicant *wpa_s, u16 reason)
468 {
469         u8 *buf;
470         size_t len;
471         struct ieee80211_mgmt *mgmt;
472
473         buf = os_zalloc(sizeof(*mgmt));
474         if (buf == NULL) {
475                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
476                            "deauth frame");
477                 return;
478         }
479
480         mgmt = (struct ieee80211_mgmt *) buf;
481         len = 24;
482         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
483         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
484         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
485         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
486                                            WLAN_FC_STYPE_DEAUTH);
487         len += 2;
488         mgmt->u.deauth.reason_code = host_to_le16(reason);
489
490         ieee80211_sta_tx(wpa_s, buf, len);
491         os_free(buf);
492 }
493
494
495 static void ieee80211_send_disassoc(struct wpa_supplicant *wpa_s, u16 reason)
496 {
497         u8 *buf;
498         size_t len;
499         struct ieee80211_mgmt *mgmt;
500
501         buf = os_zalloc(sizeof(*mgmt));
502         if (buf == NULL) {
503                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
504                            "disassoc frame");
505                 return;
506         }
507
508         mgmt = (struct ieee80211_mgmt *) buf;
509         len = 24;
510         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
511         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
512         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
513         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
514                                            WLAN_FC_STYPE_DISASSOC);
515         len += 2;
516         mgmt->u.disassoc.reason_code = host_to_le16(reason);
517
518         ieee80211_sta_tx(wpa_s, buf, len);
519         os_free(buf);
520 }
521
522
523 static int ieee80211_privacy_mismatch(struct wpa_supplicant *wpa_s)
524 {
525         struct ieee80211_sta_bss *bss;
526         int res = 0;
527
528         if (wpa_s->mlme.mixed_cell ||
529             wpa_s->mlme.key_mgmt != KEY_MGMT_NONE)
530                 return 0;
531
532         bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
533         if (bss == NULL)
534                 return 0;
535
536         if (ieee80211_sta_wep_configured(wpa_s) !=
537             !!(bss->capability & WLAN_CAPABILITY_PRIVACY))
538                 res = 1;
539
540         return res;
541 }
542
543
544 static void ieee80211_associate(struct wpa_supplicant *wpa_s)
545 {
546         wpa_s->mlme.assoc_tries++;
547         if (wpa_s->mlme.assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
548                 wpa_printf(MSG_DEBUG, "MLME: association with AP " MACSTR
549                            " timed out", MAC2STR(wpa_s->bssid));
550                 return;
551         }
552
553         wpa_s->mlme.state = IEEE80211_ASSOCIATE;
554         wpa_printf(MSG_DEBUG, "MLME: associate with AP " MACSTR,
555                    MAC2STR(wpa_s->bssid));
556         if (ieee80211_privacy_mismatch(wpa_s)) {
557                 wpa_printf(MSG_DEBUG, "MLME: mismatch in privacy "
558                            "configuration and mixed-cell disabled - abort "
559                            "association");
560                 return;
561         }
562
563         ieee80211_send_assoc(wpa_s);
564
565         ieee80211_reschedule_timer(wpa_s, IEEE80211_ASSOC_TIMEOUT);
566 }
567
568
569 static void ieee80211_associated(struct wpa_supplicant *wpa_s)
570 {
571         int disassoc;
572
573         /* TODO: start monitoring current AP signal quality and number of
574          * missed beacons. Scan other channels every now and then and search
575          * for better APs. */
576         /* TODO: remove expired BSSes */
577
578         wpa_s->mlme.state = IEEE80211_ASSOCIATED;
579
580 #if 0 /* FIX */
581         sta = sta_info_get(local, wpa_s->bssid);
582         if (sta == NULL) {
583                 wpa_printf(MSG_DEBUG "MLME: No STA entry for own AP " MACSTR,
584                            MAC2STR(wpa_s->bssid));
585                 disassoc = 1;
586         } else {
587                 disassoc = 0;
588                 if (time_after(jiffies,
589                                sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
590                         if (wpa_s->mlme.probereq_poll) {
591                                 wpa_printf(MSG_DEBUG "MLME: No ProbeResp from "
592                                            "current AP " MACSTR " - assume "
593                                            "out of range",
594                                            MAC2STR(wpa_s->bssid));
595                                 disassoc = 1;
596                         } else {
597                                 ieee80211_send_probe_req(
598                                         wpa_s->bssid,
599                                         wpa_s->mlme.scan_ssid,
600                                         wpa_s->mlme.scan_ssid_len);
601                                 wpa_s->mlme.probereq_poll = 1;
602                         }
603                 } else {
604                         wpa_s->mlme.probereq_poll = 0;
605                         if (time_after(jiffies, wpa_s->mlme.last_probe +
606                                        IEEE80211_PROBE_INTERVAL)) {
607                                 wpa_s->mlme.last_probe = jiffies;
608                                 ieee80211_send_probe_req(wpa_s->bssid,
609                                                          wpa_s->mlme.ssid,
610                                                          wpa_s->mlme.ssid_len);
611                         }
612                 }
613                 sta_info_release(local, sta);
614         }
615 #else
616         disassoc = 0;
617 #endif
618         if (disassoc) {
619                 wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL);
620                 ieee80211_reschedule_timer(wpa_s,
621                                            IEEE80211_MONITORING_INTERVAL +
622                                            30000);
623         } else {
624                 ieee80211_reschedule_timer(wpa_s,
625                                            IEEE80211_MONITORING_INTERVAL);
626         }
627 }
628
629
630 static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s,
631                                      const u8 *dst,
632                                      const u8 *ssid, size_t ssid_len)
633 {
634         u8 *buf;
635         size_t len;
636         struct ieee80211_mgmt *mgmt;
637         u8 *pos, *supp_rates;
638         u8 *esupp_rates = NULL;
639         int i;
640
641         buf = os_malloc(sizeof(*mgmt) + 200 + wpa_s->mlme.extra_probe_ie_len);
642         if (buf == NULL) {
643                 wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for "
644                            "probe request");
645                 return;
646         }
647
648         mgmt = (struct ieee80211_mgmt *) buf;
649         len = 24;
650         os_memset(mgmt, 0, 24);
651         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
652                                            WLAN_FC_STYPE_PROBE_REQ);
653         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
654         if (dst) {
655                 os_memcpy(mgmt->da, dst, ETH_ALEN);
656                 os_memcpy(mgmt->bssid, dst, ETH_ALEN);
657         } else {
658                 os_memset(mgmt->da, 0xff, ETH_ALEN);
659                 os_memset(mgmt->bssid, 0xff, ETH_ALEN);
660         }
661         pos = buf + len;
662         len += 2 + ssid_len;
663         *pos++ = WLAN_EID_SSID;
664         *pos++ = ssid_len;
665         os_memcpy(pos, ssid, ssid_len);
666
667         supp_rates = buf + len;
668         len += 2;
669         supp_rates[0] = WLAN_EID_SUPP_RATES;
670         supp_rates[1] = 0;
671         for (i = 0; i < wpa_s->mlme.num_curr_rates; i++) {
672                 struct wpa_rate_data *rate = &wpa_s->mlme.curr_rates[i];
673                 if (esupp_rates) {
674                         pos = buf + len;
675                         len++;
676                         esupp_rates[1]++;
677                 } else if (supp_rates[1] == 8) {
678                         esupp_rates = pos;
679                         esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
680                         esupp_rates[1] = 1;
681                         pos = &esupp_rates[2];
682                         len += 3;
683                 } else {
684                         pos = buf + len;
685                         len++;
686                         supp_rates[1]++;
687                 }
688                 *pos++ = rate->rate / 5;
689         }
690
691         if (wpa_s->mlme.extra_probe_ie) {
692                 os_memcpy(pos, wpa_s->mlme.extra_probe_ie,
693                           wpa_s->mlme.extra_probe_ie_len);
694                 len += wpa_s->mlme.extra_probe_ie_len;
695         }
696
697         ieee80211_sta_tx(wpa_s, buf, len);
698         os_free(buf);
699 }
700
701
702 static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s)
703 {
704 #if 0 /* FIX */
705         if (sdata == NULL || sdata->default_key == NULL ||
706             sdata->default_key->alg != ALG_WEP)
707                 return 0;
708         return 1;
709 #else
710         return 0;
711 #endif
712 }
713
714
715 static void ieee80211_auth_completed(struct wpa_supplicant *wpa_s)
716 {
717         wpa_printf(MSG_DEBUG, "MLME: authenticated");
718         wpa_s->mlme.authenticated = 1;
719         ieee80211_associate(wpa_s);
720 }
721
722
723 static void ieee80211_auth_challenge(struct wpa_supplicant *wpa_s,
724                                      struct ieee80211_mgmt *mgmt,
725                                      size_t len,
726                                      struct ieee80211_rx_status *rx_status)
727 {
728         u8 *pos;
729         struct ieee802_11_elems elems;
730
731         wpa_printf(MSG_DEBUG, "MLME: replying to auth challenge");
732         pos = mgmt->u.auth.variable;
733         if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems, 0)
734             == ParseFailed) {
735                 wpa_printf(MSG_DEBUG, "MLME: failed to parse Auth(challenge)");
736                 return;
737         }
738         if (elems.challenge == NULL) {
739                 wpa_printf(MSG_DEBUG, "MLME: no challenge IE in shared key "
740                            "auth frame");
741                 return;
742         }
743         ieee80211_send_auth(wpa_s, 3, elems.challenge - 2,
744                             elems.challenge_len + 2, 1);
745 }
746
747
748 static void ieee80211_rx_mgmt_auth(struct wpa_supplicant *wpa_s,
749                                    struct ieee80211_mgmt *mgmt,
750                                    size_t len,
751                                    struct ieee80211_rx_status *rx_status)
752 {
753         struct wpa_ssid *ssid = wpa_s->current_ssid;
754         u16 auth_alg, auth_transaction, status_code;
755         int adhoc;
756
757         adhoc = ssid && ssid->mode == 1;
758
759         if (wpa_s->mlme.state != IEEE80211_AUTHENTICATE && !adhoc) {
760                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
761                            "from " MACSTR ", but not in authenticate state - "
762                            "ignored", MAC2STR(mgmt->sa));
763                 return;
764         }
765
766         if (len < 24 + 6) {
767                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) authentication "
768                            "frame received from " MACSTR " - ignored",
769                            (unsigned long) len, MAC2STR(mgmt->sa));
770                 return;
771         }
772
773         if (!adhoc && os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
774                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
775                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
776                            ") - ignored",
777                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
778                 return;
779         }
780
781         if (adhoc && os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0) {
782                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
783                            "from unknown BSSID (SA=" MACSTR " BSSID=" MACSTR
784                            ") - ignored",
785                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
786                 return;
787         }
788
789         auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
790         auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
791         status_code = le_to_host16(mgmt->u.auth.status_code);
792
793         wpa_printf(MSG_DEBUG, "MLME: RX authentication from " MACSTR
794                    " (alg=%d transaction=%d status=%d)",
795                    MAC2STR(mgmt->sa), auth_alg, auth_transaction, status_code);
796
797         if (adhoc) {
798                 /* IEEE 802.11 standard does not require authentication in IBSS
799                  * networks and most implementations do not seem to use it.
800                  * However, try to reply to authentication attempts if someone
801                  * has actually implemented this.
802                  * TODO: Could implement shared key authentication. */
803                 if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
804                         wpa_printf(MSG_DEBUG, "MLME: unexpected IBSS "
805                                    "authentication frame (alg=%d "
806                                    "transaction=%d)",
807                                    auth_alg, auth_transaction);
808                         return;
809                 }
810                 ieee80211_send_auth(wpa_s, 2, NULL, 0, 0);
811         }
812
813         if (auth_alg != wpa_s->mlme.auth_alg ||
814             auth_transaction != wpa_s->mlme.auth_transaction) {
815                 wpa_printf(MSG_DEBUG, "MLME: unexpected authentication frame "
816                            "(alg=%d transaction=%d)",
817                            auth_alg, auth_transaction);
818                 return;
819         }
820
821         if (status_code != WLAN_STATUS_SUCCESS) {
822                 wpa_printf(MSG_DEBUG, "MLME: AP denied authentication "
823                            "(auth_alg=%d code=%d)", wpa_s->mlme.auth_alg,
824                            status_code);
825                 if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
826                         const int num_algs = 3;
827                         u8 algs[num_algs];
828                         int i, pos;
829                         algs[0] = algs[1] = algs[2] = 0xff;
830                         if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN)
831                                 algs[0] = WLAN_AUTH_OPEN;
832                         if (wpa_s->mlme.auth_algs &
833                             IEEE80211_AUTH_ALG_SHARED_KEY)
834                                 algs[1] = WLAN_AUTH_SHARED_KEY;
835                         if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP)
836                                 algs[2] = WLAN_AUTH_LEAP;
837                         if (wpa_s->mlme.auth_alg == WLAN_AUTH_OPEN)
838                                 pos = 0;
839                         else if (wpa_s->mlme.auth_alg == WLAN_AUTH_SHARED_KEY)
840                                 pos = 1;
841                         else
842                                 pos = 2;
843                         for (i = 0; i < num_algs; i++) {
844                                 pos++;
845                                 if (pos >= num_algs)
846                                         pos = 0;
847                                 if (algs[pos] == wpa_s->mlme.auth_alg ||
848                                     algs[pos] == 0xff)
849                                         continue;
850                                 if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
851                                     !ieee80211_sta_wep_configured(wpa_s))
852                                         continue;
853                                 wpa_s->mlme.auth_alg = algs[pos];
854                                 wpa_printf(MSG_DEBUG, "MLME: set auth_alg=%d "
855                                            "for next try",
856                                            wpa_s->mlme.auth_alg);
857                                 break;
858                         }
859                 }
860                 return;
861         }
862
863         switch (wpa_s->mlme.auth_alg) {
864         case WLAN_AUTH_OPEN:
865         case WLAN_AUTH_LEAP:
866                 ieee80211_auth_completed(wpa_s);
867                 break;
868         case WLAN_AUTH_SHARED_KEY:
869                 if (wpa_s->mlme.auth_transaction == 4)
870                         ieee80211_auth_completed(wpa_s);
871                 else
872                         ieee80211_auth_challenge(wpa_s, mgmt, len,
873                                                  rx_status);
874                 break;
875 #ifdef CONFIG_IEEE80211R
876         case WLAN_AUTH_FT:
877         {
878                 union wpa_event_data data;
879                 os_memset(&data, 0, sizeof(data));
880                 data.ft_ies.ies = mgmt->u.auth.variable;
881                 data.ft_ies.ies_len = len -
882                         (mgmt->u.auth.variable - (u8 *) mgmt);
883                 os_memcpy(data.ft_ies.target_ap, wpa_s->bssid, ETH_ALEN);
884                 wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &data);
885                 ieee80211_auth_completed(wpa_s);
886                 break;
887         }
888 #endif /* CONFIG_IEEE80211R */
889         }
890 }
891
892
893 static void ieee80211_rx_mgmt_deauth(struct wpa_supplicant *wpa_s,
894                                      struct ieee80211_mgmt *mgmt,
895                                      size_t len,
896                                      struct ieee80211_rx_status *rx_status)
897 {
898         u16 reason_code;
899
900         if (len < 24 + 2) {
901                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) deauthentication "
902                            "frame received from " MACSTR " - ignored",
903                            (unsigned long) len, MAC2STR(mgmt->sa));
904                 return;
905         }
906
907         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
908                 wpa_printf(MSG_DEBUG, "MLME: deauthentication frame received "
909                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
910                            ") - ignored",
911                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
912                 return;
913         }
914
915         reason_code = le_to_host16(mgmt->u.deauth.reason_code);
916
917         wpa_printf(MSG_DEBUG, "MLME: RX deauthentication from " MACSTR
918                    " (reason=%d)", MAC2STR(mgmt->sa), reason_code);
919
920         if (wpa_s->mlme.authenticated)
921                 wpa_printf(MSG_DEBUG, "MLME: deauthenticated");
922
923         if (wpa_s->mlme.state == IEEE80211_AUTHENTICATE ||
924             wpa_s->mlme.state == IEEE80211_ASSOCIATE ||
925             wpa_s->mlme.state == IEEE80211_ASSOCIATED) {
926                 wpa_s->mlme.state = IEEE80211_AUTHENTICATE;
927                 ieee80211_reschedule_timer(wpa_s,
928                                            IEEE80211_RETRY_AUTH_INTERVAL);
929         }
930
931         ieee80211_set_associated(wpa_s, 0);
932         wpa_s->mlme.authenticated = 0;
933 }
934
935
936 static void ieee80211_rx_mgmt_disassoc(struct wpa_supplicant *wpa_s,
937                                        struct ieee80211_mgmt *mgmt,
938                                        size_t len,
939                                        struct ieee80211_rx_status *rx_status)
940 {
941         u16 reason_code;
942
943         if (len < 24 + 2) {
944                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) disassociation "
945                            "frame received from " MACSTR " - ignored",
946                            (unsigned long) len, MAC2STR(mgmt->sa));
947                 return;
948         }
949
950         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
951                 wpa_printf(MSG_DEBUG, "MLME: disassociation frame received "
952                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
953                            ") - ignored",
954                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
955                 return;
956         }
957
958         reason_code = le_to_host16(mgmt->u.disassoc.reason_code);
959
960         wpa_printf(MSG_DEBUG, "MLME: RX disassociation from " MACSTR
961                    " (reason=%d)", MAC2STR(mgmt->sa), reason_code);
962
963         if (wpa_s->mlme.associated)
964                 wpa_printf(MSG_DEBUG, "MLME: disassociated");
965
966         if (wpa_s->mlme.state == IEEE80211_ASSOCIATED) {
967                 wpa_s->mlme.state = IEEE80211_ASSOCIATE;
968                 ieee80211_reschedule_timer(wpa_s,
969                                            IEEE80211_RETRY_AUTH_INTERVAL);
970         }
971
972         ieee80211_set_associated(wpa_s, 0);
973 }
974
975
976 static int ieee80211_ft_assoc_resp(struct wpa_supplicant *wpa_s,
977                                    struct ieee802_11_elems *elems)
978 {
979 #ifdef CONFIG_IEEE80211R
980         const u8 *mobility_domain = NULL;
981         const u8 *r0kh_id = NULL;
982         size_t r0kh_id_len = 0;
983         const u8 *r1kh_id = NULL;
984         struct rsn_ftie *hdr;
985         const u8 *pos, *end;
986
987         if (elems->mdie && elems->mdie_len >= MOBILITY_DOMAIN_ID_LEN)
988                 mobility_domain = elems->mdie;
989         if (elems->ftie && elems->ftie_len >= sizeof(struct rsn_ftie)) {
990                 end = elems->ftie + elems->ftie_len;
991                 hdr = (struct rsn_ftie *) elems->ftie;
992                 pos = (const u8 *) (hdr + 1);
993                 while (pos + 1 < end) {
994                         if (pos + 2 + pos[1] > end)
995                                 break;
996                         if (pos[0] == FTIE_SUBELEM_R1KH_ID &&
997                             pos[1] == FT_R1KH_ID_LEN)
998                                 r1kh_id = pos + 2;
999                         else if (pos[0] == FTIE_SUBELEM_R0KH_ID &&
1000                                  pos[1] >= 1 && pos[1] <= FT_R0KH_ID_MAX_LEN) {
1001                                 r0kh_id = pos + 2;
1002                                 r0kh_id_len = pos[1];
1003                         }
1004                         pos += 2 + pos[1];
1005                 }
1006         }
1007         return wpa_sm_set_ft_params(wpa_s->wpa, mobility_domain, r0kh_id,
1008                                     r0kh_id_len, r1kh_id);
1009 #else /* CONFIG_IEEE80211R */
1010         return 0;
1011 #endif /* CONFIG_IEEE80211R */
1012 }
1013
1014
1015 static void ieee80211_tx_addts(struct wpa_supplicant *wpa_s)
1016 {
1017         struct wpabuf *buf;
1018         struct ieee80211_mgmt *mgmt;
1019         struct wmm_tspec_element *tspec;
1020         size_t alen;
1021         int tid, up;
1022
1023         wpa_printf(MSG_DEBUG, "MLME: Send ADDTS Request for Voice TSPEC");
1024         mgmt = NULL;
1025         alen = mgmt->u.action.u.wmm_action.variable - (u8 *) mgmt;
1026
1027         buf = wpabuf_alloc(alen + sizeof(*tspec));
1028         if (buf == NULL)
1029                 return;
1030
1031         mgmt = wpabuf_put(buf, alen);
1032         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
1033         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
1034         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
1035         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
1036                                            WLAN_FC_STYPE_ACTION);
1037         mgmt->u.action.category = WLAN_ACTION_WMM;
1038         mgmt->u.action.u.wmm_action.action_code = WMM_ACTION_CODE_ADDTS_REQ;
1039         mgmt->u.action.u.wmm_action.dialog_token = 1;
1040         mgmt->u.action.u.wmm_action.status_code = 0;
1041
1042         tspec = wpabuf_put(buf, sizeof(*tspec));
1043         tspec->eid = WLAN_EID_VENDOR_SPECIFIC;
1044         tspec->length = sizeof(*tspec) - 2;
1045         tspec->oui[0] = 0x00;
1046         tspec->oui[1] = 0x50;
1047         tspec->oui[2] = 0xf2;
1048         tspec->oui_type = 2;
1049         tspec->oui_subtype = 2;
1050         tspec->version = 1;
1051
1052         tid = 1;
1053         up = 6; /* Voice */
1054         tspec->ts_info[0] = (tid << 1) |
1055                 (WMM_TSPEC_DIRECTION_BI_DIRECTIONAL << 5) |
1056                 BIT(7);
1057         tspec->ts_info[1] = up << 3;
1058         tspec->nominal_msdu_size = host_to_le16(1530);
1059         tspec->mean_data_rate = host_to_le32(128000); /* bits per second */
1060         tspec->minimum_phy_rate = host_to_le32(6000000);
1061         tspec->surplus_bandwidth_allowance = host_to_le16(0x3000); /* 150% */
1062
1063         ieee80211_sta_tx(wpa_s, wpabuf_head(buf), wpabuf_len(buf));
1064         wpabuf_free(buf);
1065 }
1066
1067
1068 static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
1069                                          struct ieee80211_mgmt *mgmt,
1070                                          size_t len,
1071                                          struct ieee80211_rx_status *rx_status,
1072                                          int reassoc)
1073 {
1074         u8 rates[32];
1075         size_t rates_len;
1076         u16 capab_info, status_code, aid;
1077         struct ieee802_11_elems elems;
1078         u8 *pos;
1079
1080         /* AssocResp and ReassocResp have identical structure, so process both
1081          * of them in this function. */
1082
1083         if (wpa_s->mlme.state != IEEE80211_ASSOCIATE) {
1084                 wpa_printf(MSG_DEBUG, "MLME: association frame received from "
1085                            MACSTR ", but not in associate state - ignored",
1086                            MAC2STR(mgmt->sa));
1087                 return;
1088         }
1089
1090         if (len < 24 + 6) {
1091                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) association "
1092                            "frame received from " MACSTR " - ignored",
1093                            (unsigned long) len, MAC2STR(mgmt->sa));
1094                 return;
1095         }
1096
1097         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
1098                 wpa_printf(MSG_DEBUG, "MLME: association frame received from "
1099                            "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - "
1100                            "ignored", MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
1101                 return;
1102         }
1103
1104         capab_info = le_to_host16(mgmt->u.assoc_resp.capab_info);
1105         status_code = le_to_host16(mgmt->u.assoc_resp.status_code);
1106         aid = le_to_host16(mgmt->u.assoc_resp.aid);
1107         if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
1108                 wpa_printf(MSG_DEBUG, "MLME: invalid aid value %d; bits 15:14 "
1109                            "not set", aid);
1110         aid &= ~(BIT(15) | BIT(14));
1111
1112         wpa_printf(MSG_DEBUG, "MLME: RX %sssocResp from " MACSTR
1113                    " (capab=0x%x status=%d aid=%d)",
1114                    reassoc ? "Rea" : "A", MAC2STR(mgmt->sa),
1115                    capab_info, status_code, aid);
1116
1117         pos = mgmt->u.assoc_resp.variable;
1118         if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems, 0)
1119             == ParseFailed) {
1120                 wpa_printf(MSG_DEBUG, "MLME: failed to parse AssocResp");
1121                 return;
1122         }
1123
1124         if (status_code != WLAN_STATUS_SUCCESS) {
1125                 wpa_printf(MSG_DEBUG, "MLME: AP denied association (code=%d)",
1126                            status_code);
1127 #ifdef CONFIG_IEEE80211W
1128                 if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY &&
1129                     elems.timeout_int && elems.timeout_int_len == 5 &&
1130                     elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) {
1131                         u32 tu, ms;
1132                         tu = WPA_GET_LE32(elems.timeout_int + 1);
1133                         ms = tu * 1024 / 1000;
1134                         wpa_printf(MSG_DEBUG, "MLME: AP rejected association "
1135                                    "temporarily; comeback duration %u TU "
1136                                    "(%u ms)", tu, ms);
1137                         if (ms > IEEE80211_ASSOC_TIMEOUT) {
1138                                 wpa_printf(MSG_DEBUG, "MLME: Update timer "
1139                                            "based on comeback duration");
1140                                 ieee80211_reschedule_timer(wpa_s, ms);
1141                         }
1142                 }
1143 #endif /* CONFIG_IEEE80211W */
1144                 return;
1145         }
1146
1147         if (elems.supp_rates == NULL) {
1148                 wpa_printf(MSG_DEBUG, "MLME: no SuppRates element in "
1149                            "AssocResp");
1150                 return;
1151         }
1152
1153         if (wpa_s->mlme.auth_alg == WLAN_AUTH_FT) {
1154                 if (!reassoc) {
1155                         wpa_printf(MSG_DEBUG, "MLME: AP tried to use "
1156                                    "association, not reassociation, response "
1157                                    "with FT");
1158                         return;
1159                 }
1160                 if (wpa_ft_validate_reassoc_resp(
1161                             wpa_s->wpa, pos, len - (pos - (u8 *) mgmt),
1162                             mgmt->sa) < 0) {
1163                         wpa_printf(MSG_DEBUG, "MLME: FT validation of Reassoc"
1164                                    "Resp failed");
1165                         return;
1166                 }
1167         } else if (ieee80211_ft_assoc_resp(wpa_s, &elems) < 0)
1168                 return;
1169
1170         wpa_printf(MSG_DEBUG, "MLME: associated");
1171         wpa_s->mlme.aid = aid;
1172         wpa_s->mlme.ap_capab = capab_info;
1173
1174         os_free(wpa_s->mlme.assocresp_ies);
1175         wpa_s->mlme.assocresp_ies_len = len - (pos - (u8 *) mgmt);
1176         wpa_s->mlme.assocresp_ies = os_malloc(wpa_s->mlme.assocresp_ies_len);
1177         if (wpa_s->mlme.assocresp_ies) {
1178                 os_memcpy(wpa_s->mlme.assocresp_ies, pos,
1179                           wpa_s->mlme.assocresp_ies_len);
1180         }
1181
1182         ieee80211_set_associated(wpa_s, 1);
1183
1184         rates_len = elems.supp_rates_len;
1185         if (rates_len > sizeof(rates))
1186                 rates_len = sizeof(rates);
1187         os_memcpy(rates, elems.supp_rates, rates_len);
1188         if (elems.ext_supp_rates) {
1189                 size_t _len = elems.ext_supp_rates_len;
1190                 if (_len > sizeof(rates) - rates_len)
1191                         _len = sizeof(rates) - rates_len;
1192                 os_memcpy(rates + rates_len, elems.ext_supp_rates, _len);
1193                 rates_len += _len;
1194         }
1195
1196         if (wpa_drv_set_bssid(wpa_s, wpa_s->bssid) < 0) {
1197                 wpa_printf(MSG_DEBUG, "MLME: failed to set BSSID for the "
1198                            "netstack");
1199         }
1200         if (wpa_drv_set_ssid(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) <
1201             0) {
1202                 wpa_printf(MSG_DEBUG, "MLME: failed to set SSID for the "
1203                            "netstack");
1204         }
1205
1206         /* Remove STA entry before adding a new one just in case to avoid
1207          * problems with existing configuration (e.g., keys). */
1208         wpa_drv_mlme_remove_sta(wpa_s, wpa_s->bssid);
1209         if (wpa_drv_mlme_add_sta(wpa_s, wpa_s->bssid, rates, rates_len) < 0) {
1210                 wpa_printf(MSG_DEBUG, "MLME: failed to add STA entry to the "
1211                            "netstack");
1212         }
1213
1214         if (elems.wmm && wpa_s->mlme.wmm_enabled)
1215                 ieee80211_sta_wmm_params(wpa_s, elems.wmm, elems.wmm_len);
1216
1217         ieee80211_associated(wpa_s);
1218
1219         if (os_strcmp(wpa_s->driver->name, "test") == 0 &&
1220             elems.wmm && wpa_s->mlme.wmm_enabled) {
1221                 /* Test WMM-AC - send ADDTS for WMM TSPEC */
1222                 ieee80211_tx_addts(wpa_s);
1223         }
1224 }
1225
1226
1227 /* Caller must hold local->sta_bss_lock */
1228 static void __ieee80211_bss_hash_add(struct wpa_supplicant *wpa_s,
1229                                      struct ieee80211_sta_bss *bss)
1230 {
1231         bss->hnext = wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)];
1232         wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)] = bss;
1233 }
1234
1235
1236 /* Caller must hold local->sta_bss_lock */
1237 static void __ieee80211_bss_hash_del(struct wpa_supplicant *wpa_s,
1238                                      struct ieee80211_sta_bss *bss)
1239 {
1240         struct ieee80211_sta_bss *b, *prev = NULL;
1241         b = wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)];
1242         while (b) {
1243                 if (b == bss) {
1244                         if (prev == NULL) {
1245                                 wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)]
1246                                         = bss->hnext;
1247                         } else {
1248                                 prev->hnext = bss->hnext;
1249                         }
1250                         break;
1251                 }
1252                 prev = b;
1253                 b = b->hnext;
1254         }
1255 }
1256
1257
1258 static struct ieee80211_sta_bss *
1259 ieee80211_bss_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
1260 {
1261         struct ieee80211_sta_bss *bss;
1262
1263         bss = os_zalloc(sizeof(*bss));
1264         if (bss == NULL)
1265                 return NULL;
1266         os_memcpy(bss->bssid, bssid, ETH_ALEN);
1267
1268         /* TODO: order by RSSI? */
1269         bss->next = wpa_s->mlme.sta_bss_list;
1270         wpa_s->mlme.sta_bss_list = bss;
1271         __ieee80211_bss_hash_add(wpa_s, bss);
1272         return bss;
1273 }
1274
1275
1276 static struct ieee80211_sta_bss *
1277 ieee80211_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid)
1278 {
1279         struct ieee80211_sta_bss *bss;
1280
1281         bss = wpa_s->mlme.sta_bss_hash[STA_HASH(bssid)];
1282         while (bss) {
1283                 if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
1284                         break;
1285                 bss = bss->hnext;
1286         }
1287         return bss;
1288 }
1289
1290
1291 static void ieee80211_bss_free(struct wpa_supplicant *wpa_s,
1292                                struct ieee80211_sta_bss *bss)
1293 {
1294         __ieee80211_bss_hash_del(wpa_s, bss);
1295         os_free(bss->ie);
1296         os_free(bss->wpa_ie);
1297         os_free(bss->rsn_ie);
1298         os_free(bss->wmm_ie);
1299         os_free(bss->mdie);
1300         os_free(bss);
1301 }
1302
1303
1304 static void ieee80211_bss_list_deinit(struct wpa_supplicant *wpa_s)
1305 {
1306         struct ieee80211_sta_bss *bss, *prev;
1307
1308         bss = wpa_s->mlme.sta_bss_list;
1309         wpa_s->mlme.sta_bss_list = NULL;
1310         while (bss) {
1311                 prev = bss;
1312                 bss = bss->next;
1313                 ieee80211_bss_free(wpa_s, prev);
1314         }
1315 }
1316
1317
1318 static void ieee80211_bss_info(struct wpa_supplicant *wpa_s,
1319                                struct ieee80211_mgmt *mgmt,
1320                                size_t len,
1321                                struct ieee80211_rx_status *rx_status,
1322                                int beacon)
1323 {
1324         struct ieee802_11_elems elems;
1325         size_t baselen;
1326         int channel, invalid = 0, clen;
1327         struct ieee80211_sta_bss *bss;
1328         u64 timestamp;
1329         u8 *pos, *ie_pos;
1330         size_t ie_len;
1331
1332         if (!beacon && os_memcmp(mgmt->da, wpa_s->own_addr, ETH_ALEN))
1333                 return; /* ignore ProbeResp to foreign address */
1334
1335 #if 0
1336         wpa_printf(MSG_MSGDUMP, "MLME: RX %s from " MACSTR " to " MACSTR,
1337                    beacon ? "Beacon" : "Probe Response",
1338                    MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
1339 #endif
1340
1341         baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
1342         if (baselen > len)
1343                 return;
1344
1345         pos = mgmt->u.beacon.timestamp;
1346         timestamp = WPA_GET_LE64(pos);
1347
1348 #if 0 /* FIX */
1349         if (local->conf.mode == IW_MODE_ADHOC && beacon &&
1350             os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0) {
1351 #ifdef IEEE80211_IBSS_DEBUG
1352                 static unsigned long last_tsf_debug = 0;
1353                 u64 tsf;
1354                 if (local->hw->get_tsf)
1355                         tsf = local->hw->get_tsf(local->mdev);
1356                 else
1357                         tsf = -1LLU;
1358                 if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
1359                         wpa_printf(MSG_DEBUG, "RX beacon SA=" MACSTR " BSSID="
1360                                    MACSTR " TSF=0x%llx BCN=0x%llx diff=%lld "
1361                                    "@%ld",
1362                                    MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
1363                                    tsf, timestamp, tsf - timestamp, jiffies);
1364                         last_tsf_debug = jiffies;
1365                 }
1366 #endif /* IEEE80211_IBSS_DEBUG */
1367         }
1368 #endif
1369
1370         ie_pos = mgmt->u.beacon.variable;
1371         ie_len = len - baselen;
1372         if (ieee802_11_parse_elems(ie_pos, ie_len, &elems, 0) == ParseFailed)
1373                 invalid = 1;
1374
1375 #if 0 /* FIX */
1376         if (local->conf.mode == IW_MODE_ADHOC && elems.supp_rates &&
1377             os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0 &&
1378             (sta = sta_info_get(local, mgmt->sa))) {
1379                 struct ieee80211_rate *rates;
1380                 size_t num_rates;
1381                 u32 supp_rates, prev_rates;
1382                 int i, j, oper_mode;
1383
1384                 rates = local->curr_rates;
1385                 num_rates = local->num_curr_rates;
1386                 oper_mode = wpa_s->mlme.sta_scanning ?
1387                         local->scan_oper_phymode : local->conf.phymode;
1388                 for (i = 0; i < local->hw->num_modes; i++) {
1389                         struct ieee80211_hw_modes *mode = &local->hw->modes[i];
1390                         if (oper_mode == mode->mode) {
1391                                 rates = mode->rates;
1392                                 num_rates = mode->num_rates;
1393                                 break;
1394                         }
1395                 }
1396
1397                 supp_rates = 0;
1398                 for (i = 0; i < elems.supp_rates_len +
1399                              elems.ext_supp_rates_len; i++) {
1400                         u8 rate = 0;
1401                         int own_rate;
1402                         if (i < elems.supp_rates_len)
1403                                 rate = elems.supp_rates[i];
1404                         else if (elems.ext_supp_rates)
1405                                 rate = elems.ext_supp_rates
1406                                         [i - elems.supp_rates_len];
1407                         own_rate = 5 * (rate & 0x7f);
1408                         if (oper_mode == MODE_ATHEROS_TURBO)
1409                                 own_rate *= 2;
1410                         for (j = 0; j < num_rates; j++)
1411                                 if (rates[j].rate == own_rate)
1412                                         supp_rates |= BIT(j);
1413                 }
1414
1415                 prev_rates = sta->supp_rates;
1416                 sta->supp_rates &= supp_rates;
1417                 if (sta->supp_rates == 0) {
1418                         /* No matching rates - this should not really happen.
1419                          * Make sure that at least one rate is marked
1420                          * supported to avoid issues with TX rate ctrl. */
1421                         sta->supp_rates = wpa_s->mlme.supp_rates_bits;
1422                 }
1423                 if (sta->supp_rates != prev_rates) {
1424                         wpa_printf(MSG_DEBUG, "MLME: updated supp_rates set "
1425                                    "for " MACSTR " based on beacon info "
1426                                    "(0x%x & 0x%x -> 0x%x)",
1427                                    MAC2STR(sta->addr), prev_rates,
1428                                    supp_rates, sta->supp_rates);
1429                 }
1430                 sta_info_release(local, sta);
1431         }
1432 #endif
1433
1434         if (elems.ssid == NULL)
1435                 return;
1436
1437         if (elems.ds_params && elems.ds_params_len == 1)
1438                 channel = elems.ds_params[0];
1439         else
1440                 channel = rx_status->channel;
1441
1442         bss = ieee80211_bss_get(wpa_s, mgmt->bssid);
1443         if (bss == NULL) {
1444                 bss = ieee80211_bss_add(wpa_s, mgmt->bssid);
1445                 if (bss == NULL)
1446                         return;
1447         } else {
1448 #if 0
1449                 /* TODO: order by RSSI? */
1450                 spin_lock_bh(&local->sta_bss_lock);
1451                 list_move_tail(&bss->list, &local->sta_bss_list);
1452                 spin_unlock_bh(&local->sta_bss_lock);
1453 #endif
1454         }
1455
1456         if (bss->probe_resp && beacon) {
1457                 /* Do not allow beacon to override data from Probe Response. */
1458                 return;
1459         }
1460
1461         bss->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int);
1462         bss->capability = le_to_host16(mgmt->u.beacon.capab_info);
1463
1464         if (bss->ie == NULL || bss->ie_len < ie_len) {
1465                 os_free(bss->ie);
1466                 bss->ie = os_malloc(ie_len);
1467         }
1468         if (bss->ie) {
1469                 os_memcpy(bss->ie, ie_pos, ie_len);
1470                 bss->ie_len = ie_len;
1471         }
1472
1473         if (elems.ssid && elems.ssid_len <= MAX_SSID_LEN) {
1474                 os_memcpy(bss->ssid, elems.ssid, elems.ssid_len);
1475                 bss->ssid_len = elems.ssid_len;
1476         }
1477
1478         bss->supp_rates_len = 0;
1479         if (elems.supp_rates) {
1480                 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
1481                 if (clen > elems.supp_rates_len)
1482                         clen = elems.supp_rates_len;
1483                 os_memcpy(&bss->supp_rates[bss->supp_rates_len],
1484                           elems.supp_rates, clen);
1485                 bss->supp_rates_len += clen;
1486         }
1487         if (elems.ext_supp_rates) {
1488                 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
1489                 if (clen > elems.ext_supp_rates_len)
1490                         clen = elems.ext_supp_rates_len;
1491                 os_memcpy(&bss->supp_rates[bss->supp_rates_len],
1492                           elems.ext_supp_rates, clen);
1493                 bss->supp_rates_len += clen;
1494         }
1495
1496         if (elems.wpa_ie &&
1497             (bss->wpa_ie == NULL || bss->wpa_ie_len != elems.wpa_ie_len ||
1498              os_memcmp(bss->wpa_ie, elems.wpa_ie, elems.wpa_ie_len))) {
1499                 os_free(bss->wpa_ie);
1500                 bss->wpa_ie = os_malloc(elems.wpa_ie_len + 2);
1501                 if (bss->wpa_ie) {
1502                         os_memcpy(bss->wpa_ie, elems.wpa_ie - 2,
1503                                   elems.wpa_ie_len + 2);
1504                         bss->wpa_ie_len = elems.wpa_ie_len + 2;
1505                 } else
1506                         bss->wpa_ie_len = 0;
1507         } else if (!elems.wpa_ie && bss->wpa_ie) {
1508                 os_free(bss->wpa_ie);
1509                 bss->wpa_ie = NULL;
1510                 bss->wpa_ie_len = 0;
1511         }
1512
1513         if (elems.rsn_ie &&
1514             (bss->rsn_ie == NULL || bss->rsn_ie_len != elems.rsn_ie_len ||
1515              os_memcmp(bss->rsn_ie, elems.rsn_ie, elems.rsn_ie_len))) {
1516                 os_free(bss->rsn_ie);
1517                 bss->rsn_ie = os_malloc(elems.rsn_ie_len + 2);
1518                 if (bss->rsn_ie) {
1519                         os_memcpy(bss->rsn_ie, elems.rsn_ie - 2,
1520                                   elems.rsn_ie_len + 2);
1521                         bss->rsn_ie_len = elems.rsn_ie_len + 2;
1522                 } else
1523                         bss->rsn_ie_len = 0;
1524         } else if (!elems.rsn_ie && bss->rsn_ie) {
1525                 os_free(bss->rsn_ie);
1526                 bss->rsn_ie = NULL;
1527                 bss->rsn_ie_len = 0;
1528         }
1529
1530         if (elems.wmm &&
1531             (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wmm_len ||
1532              os_memcmp(bss->wmm_ie, elems.wmm, elems.wmm_len))) {
1533                 os_free(bss->wmm_ie);
1534                 bss->wmm_ie = os_malloc(elems.wmm_len + 2);
1535                 if (bss->wmm_ie) {
1536                         os_memcpy(bss->wmm_ie, elems.wmm - 2,
1537                                   elems.wmm_len + 2);
1538                         bss->wmm_ie_len = elems.wmm_len + 2;
1539                 } else
1540                         bss->wmm_ie_len = 0;
1541         } else if (!elems.wmm && bss->wmm_ie) {
1542                 os_free(bss->wmm_ie);
1543                 bss->wmm_ie = NULL;
1544                 bss->wmm_ie_len = 0;
1545         }
1546
1547 #ifdef CONFIG_IEEE80211R
1548         if (elems.mdie &&
1549             (bss->mdie == NULL || bss->mdie_len != elems.mdie_len ||
1550              os_memcmp(bss->mdie, elems.mdie, elems.mdie_len))) {
1551                 os_free(bss->mdie);
1552                 bss->mdie = os_malloc(elems.mdie_len + 2);
1553                 if (bss->mdie) {
1554                         os_memcpy(bss->mdie, elems.mdie - 2,
1555                                   elems.mdie_len + 2);
1556                         bss->mdie_len = elems.mdie_len + 2;
1557                 } else
1558                         bss->mdie_len = 0;
1559         } else if (!elems.mdie && bss->mdie) {
1560                 os_free(bss->mdie);
1561                 bss->mdie = NULL;
1562                 bss->mdie_len = 0;
1563         }
1564 #endif /* CONFIG_IEEE80211R */
1565
1566         bss->hw_mode = wpa_s->mlme.phymode;
1567         bss->channel = channel;
1568         bss->freq = wpa_s->mlme.freq;
1569         if (channel != wpa_s->mlme.channel &&
1570             (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G ||
1571              wpa_s->mlme.phymode == WPA_MODE_IEEE80211B) &&
1572             channel >= 1 && channel <= 14) {
1573                 static const int freq_list[] = {
1574                         2412, 2417, 2422, 2427, 2432, 2437, 2442,
1575                         2447, 2452, 2457, 2462, 2467, 2472, 2484
1576                 };
1577                 /* IEEE 802.11g/b mode can receive packets from neighboring
1578                  * channels, so map the channel into frequency. */
1579                 bss->freq = freq_list[channel - 1];
1580         }
1581         bss->timestamp = timestamp;
1582         os_get_time(&bss->last_update);
1583         bss->rssi = rx_status->ssi;
1584         if (!beacon)
1585                 bss->probe_resp++;
1586 }
1587
1588
1589 static void ieee80211_rx_mgmt_probe_resp(struct wpa_supplicant *wpa_s,
1590                                          struct ieee80211_mgmt *mgmt,
1591                                          size_t len,
1592                                          struct ieee80211_rx_status *rx_status)
1593 {
1594         ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 0);
1595 }
1596
1597
1598 static void ieee80211_rx_mgmt_beacon(struct wpa_supplicant *wpa_s,
1599                                      struct ieee80211_mgmt *mgmt,
1600                                      size_t len,
1601                                      struct ieee80211_rx_status *rx_status)
1602 {
1603         int use_protection;
1604         size_t baselen;
1605         struct ieee802_11_elems elems;
1606
1607         ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 1);
1608
1609         if (!wpa_s->mlme.associated ||
1610             os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0)
1611                 return;
1612
1613         /* Process beacon from the current BSS */
1614         baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
1615         if (baselen > len)
1616                 return;
1617
1618         if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
1619                                    &elems, 0) == ParseFailed)
1620                 return;
1621
1622         use_protection = 0;
1623         if (elems.erp_info && elems.erp_info_len >= 1) {
1624                 use_protection =
1625                         (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
1626         }
1627
1628         if (use_protection != !!wpa_s->mlme.use_protection) {
1629                 wpa_printf(MSG_DEBUG, "MLME: CTS protection %s (BSSID=" MACSTR
1630                            ")",
1631                            use_protection ? "enabled" : "disabled",
1632                            MAC2STR(wpa_s->bssid));
1633                 wpa_s->mlme.use_protection = use_protection ? 1 : 0;
1634                 wpa_s->mlme.cts_protect_erp_frames = use_protection;
1635         }
1636
1637         if (elems.wmm && wpa_s->mlme.wmm_enabled) {
1638                 ieee80211_sta_wmm_params(wpa_s, elems.wmm,
1639                                          elems.wmm_len);
1640         }
1641 }
1642
1643
1644 static void ieee80211_rx_mgmt_probe_req(struct wpa_supplicant *wpa_s,
1645                                         struct ieee80211_mgmt *mgmt,
1646                                         size_t len,
1647                                         struct ieee80211_rx_status *rx_status)
1648 {
1649         int tx_last_beacon, adhoc;
1650 #if 0 /* FIX */
1651         struct ieee80211_mgmt *resp;
1652 #endif
1653         u8 *pos, *end;
1654         struct wpa_ssid *ssid = wpa_s->current_ssid;
1655
1656         adhoc = ssid && ssid->mode == 1;
1657
1658         if (!adhoc || wpa_s->mlme.state != IEEE80211_IBSS_JOINED ||
1659             len < 24 + 2 || wpa_s->mlme.probe_resp == NULL)
1660                 return;
1661
1662 #if 0 /* FIX */
1663         if (local->hw->tx_last_beacon)
1664                 tx_last_beacon = local->hw->tx_last_beacon(local->mdev);
1665         else
1666 #endif
1667                 tx_last_beacon = 1;
1668
1669 #ifdef IEEE80211_IBSS_DEBUG
1670         wpa_printf(MSG_DEBUG, "MLME: RX ProbeReq SA=" MACSTR " DA=" MACSTR
1671                    " BSSID=" MACSTR " (tx_last_beacon=%d)",
1672                    MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
1673                    MAC2STR(mgmt->bssid), tx_last_beacon);
1674 #endif /* IEEE80211_IBSS_DEBUG */
1675
1676         if (!tx_last_beacon)
1677                 return;
1678
1679         if (os_memcmp(mgmt->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
1680             os_memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
1681                 return;
1682
1683         end = ((u8 *) mgmt) + len;
1684         pos = mgmt->u.probe_req.variable;
1685         if (pos[0] != WLAN_EID_SSID ||
1686             pos + 2 + pos[1] > end) {
1687                 wpa_printf(MSG_DEBUG, "MLME: Invalid SSID IE in ProbeReq from "
1688                            MACSTR, MAC2STR(mgmt->sa));
1689                 return;
1690         }
1691         if (pos[1] != 0 &&
1692             (pos[1] != wpa_s->mlme.ssid_len ||
1693              os_memcmp(pos + 2, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) != 0))
1694         {
1695                 /* Ignore ProbeReq for foreign SSID */
1696                 return;
1697         }
1698
1699 #if 0 /* FIX */
1700         /* Reply with ProbeResp */
1701         skb = skb_copy(wpa_s->mlme.probe_resp, GFP_ATOMIC);
1702         if (skb == NULL)
1703                 return;
1704
1705         resp = (struct ieee80211_mgmt *) skb->data;
1706         os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
1707 #ifdef IEEE80211_IBSS_DEBUG
1708         wpa_printf(MSG_DEBUG, "MLME: Sending ProbeResp to " MACSTR,
1709                    MAC2STR(resp->da));
1710 #endif /* IEEE80211_IBSS_DEBUG */
1711         ieee80211_sta_tx(wpa_s, skb, 0, 1);
1712 #endif
1713 }
1714
1715
1716 #ifdef CONFIG_IEEE80211R
1717 static void ieee80211_rx_mgmt_ft_action(struct wpa_supplicant *wpa_s,
1718                                         struct ieee80211_mgmt *mgmt,
1719                                         size_t len,
1720                                         struct ieee80211_rx_status *rx_status)
1721 {
1722         union wpa_event_data data;
1723         u16 status;
1724         u8 *sta_addr, *target_ap_addr;
1725
1726         if (len < 24 + 1 + sizeof(mgmt->u.action.u.ft_action_resp)) {
1727                 wpa_printf(MSG_DEBUG, "MLME: Too short FT Action frame");
1728                 return;
1729         }
1730
1731         /*
1732          * Only FT Action Response is needed for now since reservation
1733          * protocol is not supported.
1734          */
1735         if (mgmt->u.action.u.ft_action_resp.action != 2) {
1736                 wpa_printf(MSG_DEBUG, "MLME: Unexpected FT Action %d",
1737                            mgmt->u.action.u.ft_action_resp.action);
1738                 return;
1739         }
1740
1741         status = le_to_host16(mgmt->u.action.u.ft_action_resp.status_code);
1742         sta_addr = mgmt->u.action.u.ft_action_resp.sta_addr;
1743         target_ap_addr = mgmt->u.action.u.ft_action_resp.target_ap_addr;
1744         wpa_printf(MSG_DEBUG, "MLME: Received FT Action Response: STA " MACSTR
1745                    " TargetAP " MACSTR " Status Code %d",
1746                    MAC2STR(sta_addr), MAC2STR(target_ap_addr), status);
1747         if (os_memcmp(sta_addr, wpa_s->own_addr, ETH_ALEN) != 0) {
1748                 wpa_printf(MSG_DEBUG, "MLME: Foreign STA Address " MACSTR
1749                            " in FT Action Response", MAC2STR(sta_addr));
1750                 return;
1751                            
1752         }
1753
1754         if (status) {
1755                 wpa_printf(MSG_DEBUG, "MLME: FT Action Response indicates "
1756                            "failure (status code %d)", status);
1757                 /* TODO: report error to FT code(?) */
1758                 return;
1759         }
1760
1761         os_memset(&data, 0, sizeof(data));
1762         data.ft_ies.ies = mgmt->u.action.u.ft_action_resp.variable;
1763         data.ft_ies.ies_len = len - (mgmt->u.action.u.ft_action_resp.variable -
1764                                      (u8 *) mgmt);
1765         data.ft_ies.ft_action = 1;
1766         os_memcpy(data.ft_ies.target_ap, target_ap_addr, ETH_ALEN);
1767         wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &data);
1768         /* TODO: should only re-associate, if EVENT_FT_RESPONSE was processed
1769          * successfully */
1770         wpa_s->mlme.prev_bssid_set = 1;
1771         wpa_s->mlme.auth_alg = WLAN_AUTH_FT;
1772         os_memcpy(wpa_s->mlme.prev_bssid, wpa_s->bssid, ETH_ALEN);
1773         os_memcpy(wpa_s->bssid, target_ap_addr, ETH_ALEN);
1774         ieee80211_associate(wpa_s);
1775 }
1776 #endif /* CONFIG_IEEE80211R */
1777
1778
1779 #ifdef CONFIG_IEEE80211W
1780
1781 /* MLME-SAQuery.response */
1782 static int ieee80211_sta_send_sa_query_resp(struct wpa_supplicant *wpa_s,
1783                                             const u8 *addr, const u8 *trans_id)
1784 {
1785         struct ieee80211_mgmt *mgmt;
1786         int res;
1787         size_t len;
1788
1789         mgmt = os_zalloc(sizeof(*mgmt));
1790         if (mgmt == NULL) {
1791                 wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
1792                            "SA Query action frame");
1793                 return -1;
1794         }
1795
1796         len = 24;
1797         os_memcpy(mgmt->da, addr, ETH_ALEN);
1798         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
1799         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
1800         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
1801                                            WLAN_FC_STYPE_ACTION);
1802         mgmt->u.action.category = WLAN_ACTION_SA_QUERY;
1803         mgmt->u.action.u.sa_query_resp.action = WLAN_SA_QUERY_RESPONSE;
1804         os_memcpy(mgmt->u.action.u.sa_query_resp.trans_id, trans_id,
1805                   WLAN_SA_QUERY_TR_ID_LEN);
1806         len += 1 + sizeof(mgmt->u.action.u.sa_query_resp);
1807
1808         res = ieee80211_sta_tx(wpa_s, (u8 *) mgmt, len);
1809         os_free(mgmt);
1810
1811         return res;
1812 }
1813
1814
1815 static void ieee80211_rx_mgmt_sa_query_action(
1816         struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
1817         struct ieee80211_rx_status *rx_status)
1818 {
1819         if (len < 24 + 1 + sizeof(mgmt->u.action.u.sa_query_req)) {
1820                 wpa_printf(MSG_DEBUG, "MLME: Too short SA Query Action frame");
1821                 return;
1822         }
1823
1824         if (mgmt->u.action.u.sa_query_req.action != WLAN_SA_QUERY_REQUEST) {
1825                 wpa_printf(MSG_DEBUG, "MLME: Unexpected SA Query Action %d",
1826                            mgmt->u.action.u.sa_query_req.action);
1827                 return;
1828         }
1829
1830         if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) {
1831                 wpa_printf(MSG_DEBUG, "MLME: Ignore SA Query from unknown "
1832                            "source " MACSTR, MAC2STR(mgmt->sa));
1833                 return;
1834         }
1835
1836         if (wpa_s->mlme.state == IEEE80211_ASSOCIATE) {
1837                 wpa_printf(MSG_DEBUG, "MLME: Ignore SA query request during "
1838                            "association process");
1839                 return;
1840         }
1841
1842         wpa_printf(MSG_DEBUG, "MLME: Replying to SA Query request");
1843         ieee80211_sta_send_sa_query_resp(wpa_s, mgmt->sa, mgmt->u.action.u.
1844                                          sa_query_req.trans_id);
1845 }
1846
1847 #endif /* CONFIG_IEEE80211W */
1848
1849
1850 static void dump_tspec(struct wmm_tspec_element *tspec)
1851 {
1852         int up, psb, dir, tid;
1853         u16 val;
1854
1855         up = (tspec->ts_info[1] >> 3) & 0x07;
1856         psb = (tspec->ts_info[1] >> 2) & 0x01;
1857         dir = (tspec->ts_info[0] >> 5) & 0x03;
1858         tid = (tspec->ts_info[0] >> 1) & 0x0f;
1859         wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d",
1860                    up, psb, dir, tid);
1861         val = le_to_host16(tspec->nominal_msdu_size);
1862         wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s",
1863                    val & 0x7fff, val & 0x8000 ? " (fixed)" : "");
1864         wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps",
1865                    le_to_host32(tspec->mean_data_rate));
1866         wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps",
1867                    le_to_host32(tspec->minimum_phy_rate));
1868         val = le_to_host16(tspec->surplus_bandwidth_allowance);
1869         wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u",
1870                    val >> 13, 10000 * (val & 0x1fff) / 0x2000);
1871         val = le_to_host16(tspec->medium_time);
1872         wpa_printf(MSG_DEBUG, "WMM: Medium Time: %u (= %u usec/sec)",
1873                    val, 32 * val);
1874 }
1875
1876
1877 static int is_wmm_tspec(const u8 *ie, size_t len)
1878 {
1879         const struct wmm_tspec_element *tspec;
1880
1881         if (len < sizeof(*tspec))
1882                 return 0;
1883
1884         tspec = (const struct wmm_tspec_element *) ie;
1885         if (tspec->eid != WLAN_EID_VENDOR_SPECIFIC ||
1886             tspec->length < sizeof(*tspec) - 2 ||
1887             tspec->oui[0] != 0x00 || tspec->oui[1] != 0x50 ||
1888             tspec->oui[2] != 0xf2 || tspec->oui_type != 2 ||
1889             tspec->oui_subtype != 2 || tspec->version != 1)
1890                 return 0;
1891
1892         return 1;
1893 }
1894
1895
1896 static void ieee80211_rx_addts_resp(
1897         struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
1898         size_t var_len)
1899 {
1900         struct wmm_tspec_element *tspec;
1901
1902         wpa_printf(MSG_DEBUG, "WMM: Received ADDTS Response");
1903         wpa_hexdump(MSG_MSGDUMP, "WMM: ADDTS Response IE(s)",
1904                     mgmt->u.action.u.wmm_action.variable, var_len);
1905         if (!is_wmm_tspec(mgmt->u.action.u.wmm_action.variable, var_len))
1906                 return;
1907         tspec = (struct wmm_tspec_element *)
1908                 mgmt->u.action.u.wmm_action.variable;
1909         dump_tspec(tspec);
1910 }
1911
1912
1913 static void ieee80211_rx_delts(
1914         struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
1915         size_t var_len)
1916 {
1917         struct wmm_tspec_element *tspec;
1918
1919         wpa_printf(MSG_DEBUG, "WMM: Received DELTS");
1920         wpa_hexdump(MSG_MSGDUMP, "WMM: DELTS IE(s)",
1921                     mgmt->u.action.u.wmm_action.variable, var_len);
1922         if (!is_wmm_tspec(mgmt->u.action.u.wmm_action.variable, var_len))
1923                 return;
1924         tspec = (struct wmm_tspec_element *)
1925                 mgmt->u.action.u.wmm_action.variable;
1926         dump_tspec(tspec);
1927 }
1928
1929
1930 static void ieee80211_rx_mgmt_wmm_action(
1931         struct wpa_supplicant *wpa_s, struct ieee80211_mgmt *mgmt, size_t len,
1932         struct ieee80211_rx_status *rx_status)
1933 {
1934         size_t alen;
1935
1936         alen = mgmt->u.action.u.wmm_action.variable - (u8 *) mgmt;
1937         if (len < alen) {
1938                 wpa_printf(MSG_DEBUG, "WMM: Received Action frame too short");
1939                 return;
1940         }
1941
1942         wpa_printf(MSG_DEBUG, "WMM: Received Action frame: Action Code %d, "
1943                    "Dialog Token %d, Status Code %d",
1944                    mgmt->u.action.u.wmm_action.action_code,
1945                    mgmt->u.action.u.wmm_action.dialog_token,
1946                    mgmt->u.action.u.wmm_action.status_code);
1947
1948         switch (mgmt->u.action.u.wmm_action.action_code) {
1949         case WMM_ACTION_CODE_ADDTS_RESP:
1950                 ieee80211_rx_addts_resp(wpa_s, mgmt, len, len - alen);
1951                 break;
1952         case WMM_ACTION_CODE_DELTS:
1953                 ieee80211_rx_delts(wpa_s, mgmt, len, len - alen);
1954                 break;
1955         default:
1956                 wpa_printf(MSG_DEBUG, "WMM: Unsupported Action Code %d",
1957                            mgmt->u.action.u.wmm_action.action_code);
1958                 break;
1959         }
1960 }
1961
1962
1963 static void ieee80211_rx_mgmt_action(struct wpa_supplicant *wpa_s,
1964                                      struct ieee80211_mgmt *mgmt,
1965                                      size_t len,
1966                                      struct ieee80211_rx_status *rx_status)
1967 {
1968         wpa_printf(MSG_DEBUG, "MLME: received Action frame");
1969
1970         if (len < 25)
1971                 return;
1972
1973         switch (mgmt->u.action.category) {
1974 #ifdef CONFIG_IEEE80211R
1975         case WLAN_ACTION_FT:
1976                 ieee80211_rx_mgmt_ft_action(wpa_s, mgmt, len, rx_status);
1977                 break;
1978 #endif /* CONFIG_IEEE80211R */
1979 #ifdef CONFIG_IEEE80211W
1980         case WLAN_ACTION_SA_QUERY:
1981                 ieee80211_rx_mgmt_sa_query_action(wpa_s, mgmt, len, rx_status);
1982                 break;
1983 #endif /* CONFIG_IEEE80211W */
1984         case WLAN_ACTION_WMM:
1985                 ieee80211_rx_mgmt_wmm_action(wpa_s, mgmt, len, rx_status);
1986                 break;
1987         default:
1988                 wpa_printf(MSG_DEBUG, "MLME: unknown Action Category %d",
1989                            mgmt->u.action.category);
1990                 break;
1991         }
1992 }
1993
1994
1995 static void ieee80211_sta_rx_mgmt(struct wpa_supplicant *wpa_s,
1996                                   const u8 *buf, size_t len,
1997                                   struct ieee80211_rx_status *rx_status)
1998 {
1999         struct ieee80211_mgmt *mgmt;
2000         u16 fc;
2001
2002         if (len < 24)
2003                 return;
2004
2005         mgmt = (struct ieee80211_mgmt *) buf;
2006         fc = le_to_host16(mgmt->frame_control);
2007
2008         switch (WLAN_FC_GET_STYPE(fc)) {
2009         case WLAN_FC_STYPE_PROBE_REQ:
2010                 ieee80211_rx_mgmt_probe_req(wpa_s, mgmt, len, rx_status);
2011                 break;
2012         case WLAN_FC_STYPE_PROBE_RESP:
2013                 ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt, len, rx_status);
2014                 break;
2015         case WLAN_FC_STYPE_BEACON:
2016                 ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status);
2017                 break;
2018         case WLAN_FC_STYPE_AUTH:
2019                 ieee80211_rx_mgmt_auth(wpa_s, mgmt, len, rx_status);
2020                 break;
2021         case WLAN_FC_STYPE_ASSOC_RESP:
2022                 ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 0);
2023                 break;
2024         case WLAN_FC_STYPE_REASSOC_RESP:
2025                 ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 1);
2026                 break;
2027         case WLAN_FC_STYPE_DEAUTH:
2028                 ieee80211_rx_mgmt_deauth(wpa_s, mgmt, len, rx_status);
2029                 break;
2030         case WLAN_FC_STYPE_DISASSOC:
2031                 ieee80211_rx_mgmt_disassoc(wpa_s, mgmt, len, rx_status);
2032                 break;
2033         case WLAN_FC_STYPE_ACTION:
2034                 ieee80211_rx_mgmt_action(wpa_s, mgmt, len, rx_status);
2035                 break;
2036         default:
2037                 wpa_printf(MSG_DEBUG, "MLME: received unknown management "
2038                            "frame - stype=%d", WLAN_FC_GET_STYPE(fc));
2039                 break;
2040         }
2041 }
2042
2043
2044 static void ieee80211_sta_rx_scan(struct wpa_supplicant *wpa_s,
2045                                   const u8 *buf, size_t len,
2046                                   struct ieee80211_rx_status *rx_status)
2047 {
2048         struct ieee80211_mgmt *mgmt;
2049         u16 fc;
2050
2051         if (len < 24)
2052                 return;
2053
2054         mgmt = (struct ieee80211_mgmt *) buf;
2055         fc = le_to_host16(mgmt->frame_control);
2056
2057         if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) {
2058                 if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
2059                         ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt,
2060                                                      len, rx_status);
2061                 } else if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) {
2062                         ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status);
2063                 }
2064         }
2065 }
2066
2067
2068 static int ieee80211_sta_active_ibss(struct wpa_supplicant *wpa_s)
2069 {
2070         int active = 0;
2071
2072 #if 0 /* FIX */
2073         list_for_each(ptr, &local->sta_list) {
2074                 sta = list_entry(ptr, struct sta_info, list);
2075                 if (sta->dev == dev &&
2076                     time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
2077                                jiffies)) {
2078                         active++;
2079                         break;
2080                 }
2081         }
2082 #endif
2083
2084         return active;
2085 }
2086
2087
2088 static void ieee80211_sta_expire(struct wpa_supplicant *wpa_s)
2089 {
2090 #if 0 /* FIX */
2091         list_for_each_safe(ptr, n, &local->sta_list) {
2092                 sta = list_entry(ptr, struct sta_info, list);
2093                 if (time_after(jiffies, sta->last_rx +
2094                                IEEE80211_IBSS_INACTIVITY_LIMIT)) {
2095                         wpa_printf(MSG_DEBUG, "MLME: expiring inactive STA "
2096                                    MACSTR, MAC2STR(sta->addr));
2097                         sta_info_free(local, sta, 1);
2098                 }
2099         }
2100 #endif
2101 }
2102
2103
2104 static void ieee80211_sta_merge_ibss(struct wpa_supplicant *wpa_s)
2105 {
2106         ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL);
2107
2108         ieee80211_sta_expire(wpa_s);
2109         if (ieee80211_sta_active_ibss(wpa_s))
2110                 return;
2111
2112         wpa_printf(MSG_DEBUG, "MLME: No active IBSS STAs - trying to scan for "
2113                    "other IBSS networks with same SSID (merge)");
2114         ieee80211_sta_req_scan(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
2115 }
2116
2117
2118 static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx)
2119 {
2120         struct wpa_supplicant *wpa_s = eloop_ctx;
2121
2122         switch (wpa_s->mlme.state) {
2123         case IEEE80211_DISABLED:
2124                 break;
2125         case IEEE80211_AUTHENTICATE:
2126                 ieee80211_authenticate(wpa_s);
2127                 break;
2128         case IEEE80211_ASSOCIATE:
2129                 ieee80211_associate(wpa_s);
2130                 break;
2131         case IEEE80211_ASSOCIATED:
2132                 ieee80211_associated(wpa_s);
2133                 break;
2134         case IEEE80211_IBSS_SEARCH:
2135                 ieee80211_sta_find_ibss(wpa_s);
2136                 break;
2137         case IEEE80211_IBSS_JOINED:
2138                 ieee80211_sta_merge_ibss(wpa_s);
2139                 break;
2140         default:
2141                 wpa_printf(MSG_DEBUG, "ieee80211_sta_timer: Unknown state %d",
2142                            wpa_s->mlme.state);
2143                 break;
2144         }
2145
2146         if (ieee80211_privacy_mismatch(wpa_s)) {
2147                 wpa_printf(MSG_DEBUG, "MLME: privacy configuration mismatch "
2148                            "and mixed-cell disabled - disassociate");
2149
2150                 ieee80211_send_disassoc(wpa_s, WLAN_REASON_UNSPECIFIED);
2151                 ieee80211_set_associated(wpa_s, 0);
2152         }
2153 }
2154
2155
2156 static void ieee80211_sta_new_auth(struct wpa_supplicant *wpa_s)
2157 {
2158         struct wpa_ssid *ssid = wpa_s->current_ssid;
2159         if (ssid && ssid->mode != 0)
2160                 return;
2161
2162 #if 0 /* FIX */
2163         if (local->hw->reset_tsf) {
2164                 /* Reset own TSF to allow time synchronization work. */
2165                 local->hw->reset_tsf(local->mdev);
2166         }
2167 #endif
2168
2169         wpa_s->mlme.wmm_last_param_set = -1; /* allow any WMM update */
2170
2171
2172         if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN)
2173                 wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN;
2174         else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
2175                 wpa_s->mlme.auth_alg = WLAN_AUTH_SHARED_KEY;
2176         else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP)
2177                 wpa_s->mlme.auth_alg = WLAN_AUTH_LEAP;
2178         else
2179                 wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN;
2180         wpa_printf(MSG_DEBUG, "MLME: Initial auth_alg=%d",
2181                    wpa_s->mlme.auth_alg);
2182         wpa_s->mlme.auth_transaction = -1;
2183         wpa_s->mlme.auth_tries = wpa_s->mlme.assoc_tries = 0;
2184         ieee80211_authenticate(wpa_s);
2185 }
2186
2187
2188 static int ieee80211_ibss_allowed(struct wpa_supplicant *wpa_s)
2189 {
2190 #if 0 /* FIX */
2191         int m, c;
2192
2193         for (m = 0; m < local->hw->num_modes; m++) {
2194                 struct ieee80211_hw_modes *mode = &local->hw->modes[m];
2195                 if (mode->mode != local->conf.phymode)
2196                         continue;
2197                 for (c = 0; c < mode->num_channels; c++) {
2198                         struct ieee80211_channel *chan = &mode->channels[c];
2199                         if (chan->flag & IEEE80211_CHAN_W_SCAN &&
2200                             chan->chan == local->conf.channel) {
2201                                 if (chan->flag & IEEE80211_CHAN_W_IBSS)
2202                                         return 1;
2203                                 break;
2204                         }
2205                 }
2206         }
2207 #endif
2208
2209         return 0;
2210 }
2211
2212
2213 static int ieee80211_sta_join_ibss(struct wpa_supplicant *wpa_s,
2214                                    struct ieee80211_sta_bss *bss)
2215 {
2216         int res = 0, rates, done = 0;
2217         struct ieee80211_mgmt *mgmt;
2218 #if 0 /* FIX */
2219         struct ieee80211_tx_control control;
2220         struct ieee80211_rate *rate;
2221         struct rate_control_extra extra;
2222 #endif
2223         u8 *pos, *buf;
2224         size_t len;
2225
2226         /* Remove possible STA entries from other IBSS networks. */
2227 #if 0 /* FIX */
2228         sta_info_flush(local, NULL);
2229
2230         if (local->hw->reset_tsf) {
2231                 /* Reset own TSF to allow time synchronization work. */
2232                 local->hw->reset_tsf(local->mdev);
2233         }
2234 #endif
2235         os_memcpy(wpa_s->bssid, bss->bssid, ETH_ALEN);
2236
2237 #if 0 /* FIX */
2238         local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
2239
2240         sdata->drop_unencrypted = bss->capability &
2241                 host_to_le16(WLAN_CAPABILITY_PRIVACY) ? 1 : 0;
2242 #endif
2243
2244 #if 0 /* FIX */
2245         os_memset(&rq, 0, sizeof(rq));
2246         rq.m = bss->freq * 100000;
2247         rq.e = 1;
2248         res = ieee80211_ioctl_siwfreq(wpa_s, NULL, &rq, NULL);
2249 #endif
2250
2251         if (!ieee80211_ibss_allowed(wpa_s)) {
2252 #if 0 /* FIX */
2253                 wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed on channel %d "
2254                            "(%d MHz)", local->conf.channel,
2255                            local->conf.freq);
2256 #endif
2257                 return -1;
2258         }
2259
2260         /* Set beacon template based on scan results */
2261         buf = os_malloc(400);
2262         len = 0;
2263         do {
2264                 if (buf == NULL)
2265                         break;
2266
2267                 mgmt = (struct ieee80211_mgmt *) buf;
2268                 len += 24 + sizeof(mgmt->u.beacon);
2269                 os_memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
2270                 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
2271                                                    WLAN_FC_STYPE_BEACON);
2272                 os_memset(mgmt->da, 0xff, ETH_ALEN);
2273                 os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
2274                 os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
2275 #if 0 /* FIX */
2276                 mgmt->u.beacon.beacon_int =
2277                         host_to_le16(local->conf.beacon_int);
2278 #endif
2279                 mgmt->u.beacon.capab_info = host_to_le16(bss->capability);
2280
2281                 pos = buf + len;
2282                 len += 2 + wpa_s->mlme.ssid_len;
2283                 *pos++ = WLAN_EID_SSID;
2284                 *pos++ = wpa_s->mlme.ssid_len;
2285                 os_memcpy(pos, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
2286
2287                 rates = bss->supp_rates_len;
2288                 if (rates > 8)
2289                         rates = 8;
2290                 pos = buf + len;
2291                 len += 2 + rates;
2292                 *pos++ = WLAN_EID_SUPP_RATES;
2293                 *pos++ = rates;
2294                 os_memcpy(pos, bss->supp_rates, rates);
2295
2296                 pos = buf + len;
2297                 len += 2 + 1;
2298                 *pos++ = WLAN_EID_DS_PARAMS;
2299                 *pos++ = 1;
2300                 *pos++ = bss->channel;
2301
2302                 pos = buf + len;
2303                 len += 2 + 2;
2304                 *pos++ = WLAN_EID_IBSS_PARAMS;
2305                 *pos++ = 2;
2306                 /* FIX: set ATIM window based on scan results */
2307                 *pos++ = 0;
2308                 *pos++ = 0;
2309
2310                 if (bss->supp_rates_len > 8) {
2311                         rates = bss->supp_rates_len - 8;
2312                         pos = buf + len;
2313                         len += 2 + rates;
2314                         *pos++ = WLAN_EID_EXT_SUPP_RATES;
2315                         *pos++ = rates;
2316                         os_memcpy(pos, &bss->supp_rates[8], rates);
2317                 }
2318
2319 #if 0 /* FIX */
2320                 os_memset(&control, 0, sizeof(control));
2321                 control.pkt_type = PKT_PROBE_RESP;
2322                 os_memset(&extra, 0, sizeof(extra));
2323                 extra.endidx = local->num_curr_rates;
2324                 rate = rate_control_get_rate(wpa_s, skb, &extra);
2325                 if (rate == NULL) {
2326                         wpa_printf(MSG_DEBUG, "MLME: Failed to determine TX "
2327                                    "rate for IBSS beacon");
2328                         break;
2329                 }
2330                 control.tx_rate = (wpa_s->mlme.short_preamble &&
2331                                    (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
2332                         rate->val2 : rate->val;
2333                 control.antenna_sel = local->conf.antenna_sel;
2334                 control.power_level = local->conf.power_level;
2335                 control.no_ack = 1;
2336                 control.retry_limit = 1;
2337                 control.rts_cts_duration = 0;
2338 #endif
2339
2340 #if 0 /* FIX */
2341                 wpa_s->mlme.probe_resp = skb_copy(skb, GFP_ATOMIC);
2342                 if (wpa_s->mlme.probe_resp) {
2343                         mgmt = (struct ieee80211_mgmt *)
2344                                 wpa_s->mlme.probe_resp->data;
2345                         mgmt->frame_control =
2346                                 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
2347                                              WLAN_FC_STYPE_PROBE_RESP);
2348                 } else {
2349                         wpa_printf(MSG_DEBUG, "MLME: Could not allocate "
2350                                    "ProbeResp template for IBSS");
2351                 }
2352
2353                 if (local->hw->beacon_update &&
2354                     local->hw->beacon_update(wpa_s, skb, &control) == 0) {
2355                         wpa_printf(MSG_DEBUG, "MLME: Configured IBSS beacon "
2356                                    "template based on scan results");
2357                         skb = NULL;
2358                 }
2359
2360                 rates = 0;
2361                 for (i = 0; i < bss->supp_rates_len; i++) {
2362                         int rate = (bss->supp_rates[i] & 0x7f) * 5;
2363                         if (local->conf.phymode == MODE_ATHEROS_TURBO)
2364                                 rate *= 2;
2365                         for (j = 0; j < local->num_curr_rates; j++)
2366                                 if (local->curr_rates[j].rate == rate)
2367                                         rates |= BIT(j);
2368                 }
2369                 wpa_s->mlme.supp_rates_bits = rates;
2370 #endif
2371                 done = 1;
2372         } while (0);
2373
2374         os_free(buf);
2375         if (!done) {
2376                 wpa_printf(MSG_DEBUG, "MLME: Failed to configure IBSS beacon "
2377                            "template");
2378         }
2379
2380         wpa_s->mlme.state = IEEE80211_IBSS_JOINED;
2381         ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL);
2382
2383         return res;
2384 }
2385
2386
2387 #if 0 /* FIX */
2388 static int ieee80211_sta_create_ibss(struct wpa_supplicant *wpa_s)
2389 {
2390         struct ieee80211_sta_bss *bss;
2391         u8 bssid[ETH_ALEN], *pos;
2392         int i;
2393
2394 #if 0
2395         /* Easier testing, use fixed BSSID. */
2396         os_memset(bssid, 0xfe, ETH_ALEN);
2397 #else
2398         /* Generate random, not broadcast, locally administered BSSID. Mix in
2399          * own MAC address to make sure that devices that do not have proper
2400          * random number generator get different BSSID. */
2401         os_get_random(bssid, ETH_ALEN);
2402         for (i = 0; i < ETH_ALEN; i++)
2403                 bssid[i] ^= wpa_s->own_addr[i];
2404         bssid[0] &= ~0x01;
2405         bssid[0] |= 0x02;
2406 #endif
2407
2408         wpa_printf(MSG_DEBUG, "MLME: Creating new IBSS network, BSSID "
2409                    MACSTR "", MAC2STR(bssid));
2410
2411         bss = ieee80211_bss_add(wpa_s, bssid);
2412         if (bss == NULL)
2413                 return -ENOMEM;
2414
2415 #if 0 /* FIX */
2416         if (local->conf.beacon_int == 0)
2417                 local->conf.beacon_int = 100;
2418         bss->beacon_int = local->conf.beacon_int;
2419         bss->hw_mode = local->conf.phymode;
2420         bss->channel = local->conf.channel;
2421         bss->freq = local->conf.freq;
2422 #endif
2423         os_get_time(&bss->last_update);
2424         bss->capability = host_to_le16(WLAN_CAPABILITY_IBSS);
2425 #if 0 /* FIX */
2426         if (sdata->default_key) {
2427                 bss->capability |= host_to_le16(WLAN_CAPABILITY_PRIVACY);
2428         } else
2429                 sdata->drop_unencrypted = 0;
2430         bss->supp_rates_len = local->num_curr_rates;
2431 #endif
2432         pos = bss->supp_rates;
2433 #if 0 /* FIX */
2434         for (i = 0; i < local->num_curr_rates; i++) {
2435                 int rate = local->curr_rates[i].rate;
2436                 if (local->conf.phymode == MODE_ATHEROS_TURBO)
2437                         rate /= 2;
2438                 *pos++ = (u8) (rate / 5);
2439         }
2440 #endif
2441
2442         return ieee80211_sta_join_ibss(wpa_s, bss);
2443 }
2444 #endif
2445
2446
2447 static int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s)
2448 {
2449         struct ieee80211_sta_bss *bss;
2450         int found = 0;
2451         u8 bssid[ETH_ALEN];
2452         int active_ibss;
2453         struct os_time now;
2454
2455         if (wpa_s->mlme.ssid_len == 0)
2456                 return -EINVAL;
2457
2458         active_ibss = ieee80211_sta_active_ibss(wpa_s);
2459 #ifdef IEEE80211_IBSS_DEBUG
2460         wpa_printf(MSG_DEBUG, "MLME: sta_find_ibss (active_ibss=%d)",
2461                    active_ibss);
2462 #endif /* IEEE80211_IBSS_DEBUG */
2463         for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) {
2464                 if (wpa_s->mlme.ssid_len != bss->ssid_len ||
2465                     os_memcmp(wpa_s->mlme.ssid, bss->ssid, bss->ssid_len) != 0
2466                     || !(bss->capability & WLAN_CAPABILITY_IBSS))
2467                         continue;
2468 #ifdef IEEE80211_IBSS_DEBUG
2469                 wpa_printf(MSG_DEBUG, "   bssid=" MACSTR " found",
2470                            MAC2STR(bss->bssid));
2471 #endif /* IEEE80211_IBSS_DEBUG */
2472                 os_memcpy(bssid, bss->bssid, ETH_ALEN);
2473                 found = 1;
2474                 if (active_ibss ||
2475                     os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0)
2476                         break;
2477         }
2478
2479 #ifdef IEEE80211_IBSS_DEBUG
2480         wpa_printf(MSG_DEBUG, "   sta_find_ibss: selected " MACSTR " current "
2481                    MACSTR, MAC2STR(bssid), MAC2STR(wpa_s->bssid));
2482 #endif /* IEEE80211_IBSS_DEBUG */
2483         if (found && os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) != 0 &&
2484             (bss = ieee80211_bss_get(wpa_s, bssid))) {
2485                 wpa_printf(MSG_DEBUG, "MLME: Selected IBSS BSSID " MACSTR
2486                            " based on configured SSID",
2487                            MAC2STR(bssid));
2488                 return ieee80211_sta_join_ibss(wpa_s, bss);
2489         }
2490 #ifdef IEEE80211_IBSS_DEBUG
2491         wpa_printf(MSG_DEBUG, "   did not try to join ibss");
2492 #endif /* IEEE80211_IBSS_DEBUG */
2493
2494         /* Selected IBSS not found in current scan results - try to scan */
2495         os_get_time(&now);
2496 #if 0 /* FIX */
2497         if (wpa_s->mlme.state == IEEE80211_IBSS_JOINED &&
2498             !ieee80211_sta_active_ibss(wpa_s)) {
2499                 ieee80211_reschedule_timer(wpa_s,
2500                                            IEEE80211_IBSS_MERGE_INTERVAL);
2501         } else if (time_after(jiffies, wpa_s->mlme.last_scan_completed +
2502                               IEEE80211_SCAN_INTERVAL)) {
2503                 wpa_printf(MSG_DEBUG, "MLME: Trigger new scan to find an IBSS "
2504                            "to join");
2505                 return ieee80211_sta_req_scan(wpa_s->mlme.ssid,
2506                                               wpa_s->mlme.ssid_len);
2507         } else if (wpa_s->mlme.state != IEEE80211_IBSS_JOINED) {
2508                 int interval = IEEE80211_SCAN_INTERVAL;
2509
2510                 if (time_after(jiffies, wpa_s->mlme.ibss_join_req +
2511                                IEEE80211_IBSS_JOIN_TIMEOUT)) {
2512                         if (wpa_s->mlme.create_ibss &&
2513                             ieee80211_ibss_allowed(wpa_s))
2514                                 return ieee80211_sta_create_ibss(wpa_s);
2515                         if (wpa_s->mlme.create_ibss) {
2516                                 wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed "
2517                                            "on the configured channel %d "
2518                                            "(%d MHz)",
2519                                            local->conf.channel,
2520                                            local->conf.freq);
2521                         }
2522
2523                         /* No IBSS found - decrease scan interval and continue
2524                          * scanning. */
2525                         interval = IEEE80211_SCAN_INTERVAL_SLOW;
2526                 }
2527
2528                 wpa_s->mlme.state = IEEE80211_IBSS_SEARCH;
2529                 ieee80211_reschedule_timer(wpa_s, interval);
2530                 return 0;
2531         }
2532 #endif
2533
2534         return 0;
2535 }
2536
2537
2538 int ieee80211_sta_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid,
2539                            size_t *len)
2540 {
2541         os_memcpy(ssid, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
2542         *len = wpa_s->mlme.ssid_len;
2543         return 0;
2544 }
2545
2546
2547 int ieee80211_sta_associate(struct wpa_supplicant *wpa_s,
2548                             struct wpa_driver_associate_params *params)
2549 {
2550         struct ieee80211_sta_bss *bss;
2551
2552         wpa_s->mlme.bssid_set = 0;
2553         wpa_s->mlme.freq = params->freq;
2554         if (params->bssid) {
2555                 os_memcpy(wpa_s->bssid, params->bssid, ETH_ALEN);
2556                 if (!is_zero_ether_addr(params->bssid))
2557                         wpa_s->mlme.bssid_set = 1;
2558                 bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
2559                 if (bss) {
2560                         wpa_s->mlme.phymode = bss->hw_mode;
2561                         wpa_s->mlme.channel = bss->channel;
2562                         wpa_s->mlme.freq = bss->freq;
2563                 }
2564         }
2565
2566 #if 0 /* FIX */
2567         /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is
2568          * not defined. */
2569         if (local->hw->conf_tx) {
2570                 struct ieee80211_tx_queue_params qparam;
2571                 int i;
2572
2573                 os_memset(&qparam, 0, sizeof(qparam));
2574                 /* TODO: are these ok defaults for all hw_modes? */
2575                 qparam.aifs = 2;
2576                 qparam.cw_min =
2577                         local->conf.phymode == MODE_IEEE80211B ? 31 : 15;
2578                 qparam.cw_max = 1023;
2579                 qparam.burst_time = 0;
2580                 for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
2581                 {
2582                         local->hw->conf_tx(wpa_s, i + IEEE80211_TX_QUEUE_DATA0,
2583                                            &qparam);
2584                 }
2585                 /* IBSS uses different parameters for Beacon sending */
2586                 qparam.cw_min++;
2587                 qparam.cw_min *= 2;
2588                 qparam.cw_min--;
2589                 local->hw->conf_tx(wpa_s, IEEE80211_TX_QUEUE_BEACON, &qparam);
2590         }
2591 #endif
2592
2593         if (wpa_s->mlme.ssid_len != params->ssid_len ||
2594             os_memcmp(wpa_s->mlme.ssid, params->ssid, params->ssid_len) != 0)
2595                 wpa_s->mlme.prev_bssid_set = 0;
2596         os_memcpy(wpa_s->mlme.ssid, params->ssid, params->ssid_len);
2597         os_memset(wpa_s->mlme.ssid + params->ssid_len, 0,
2598                   MAX_SSID_LEN - params->ssid_len);
2599         wpa_s->mlme.ssid_len = params->ssid_len;
2600         wpa_s->mlme.ssid_set = 1;
2601
2602         os_free(wpa_s->mlme.extra_ie);
2603         if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
2604                 wpa_s->mlme.extra_ie = NULL;
2605                 wpa_s->mlme.extra_ie_len = 0;
2606         } else {
2607                 wpa_s->mlme.extra_ie = os_malloc(params->wpa_ie_len);
2608                 if (wpa_s->mlme.extra_ie == NULL) {
2609                         wpa_s->mlme.extra_ie_len = 0;
2610                         return -1;
2611                 }
2612                 os_memcpy(wpa_s->mlme.extra_ie, params->wpa_ie,
2613                           params->wpa_ie_len);
2614                 wpa_s->mlme.extra_ie_len = params->wpa_ie_len;
2615         }
2616
2617         wpa_s->mlme.key_mgmt = params->key_mgmt_suite;
2618
2619         ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode,
2620                                   wpa_s->mlme.channel, wpa_s->mlme.freq);
2621
2622         if (params->mode == 1 && !wpa_s->mlme.bssid_set) {
2623                 os_get_time(&wpa_s->mlme.ibss_join_req);
2624                 wpa_s->mlme.state = IEEE80211_IBSS_SEARCH;
2625                 return ieee80211_sta_find_ibss(wpa_s);
2626         }
2627
2628         if (wpa_s->mlme.bssid_set)
2629                 ieee80211_sta_new_auth(wpa_s);
2630
2631         return 0;
2632 }
2633
2634
2635 static void ieee80211_sta_save_oper_chan(struct wpa_supplicant *wpa_s)
2636 {
2637         wpa_s->mlme.scan_oper_channel = wpa_s->mlme.channel;
2638         wpa_s->mlme.scan_oper_freq = wpa_s->mlme.freq;
2639         wpa_s->mlme.scan_oper_phymode = wpa_s->mlme.phymode;
2640 }
2641
2642
2643 static int ieee80211_sta_restore_oper_chan(struct wpa_supplicant *wpa_s)
2644 {
2645         wpa_s->mlme.channel = wpa_s->mlme.scan_oper_channel;
2646         wpa_s->mlme.freq = wpa_s->mlme.scan_oper_freq;
2647         wpa_s->mlme.phymode = wpa_s->mlme.scan_oper_phymode;
2648         if (wpa_s->mlme.freq == 0)
2649                 return 0;
2650         return ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode,
2651                                          wpa_s->mlme.channel,
2652                                          wpa_s->mlme.freq);
2653 }
2654
2655
2656 static int ieee80211_active_scan(struct wpa_supplicant *wpa_s)
2657 {
2658         size_t m;
2659         int c;
2660
2661         for (m = 0; m < wpa_s->mlme.num_modes; m++) {
2662                 struct wpa_hw_modes *mode = &wpa_s->mlme.modes[m];
2663                 if ((int) mode->mode != (int) wpa_s->mlme.phymode)
2664                         continue;
2665                 for (c = 0; c < mode->num_channels; c++) {
2666                         struct wpa_channel_data *chan = &mode->channels[c];
2667                         if (chan->flag & WPA_CHAN_W_SCAN &&
2668                             chan->chan == wpa_s->mlme.channel) {
2669                                 if (chan->flag & WPA_CHAN_W_ACTIVE_SCAN)
2670                                         return 1;
2671                                 break;
2672                         }
2673                 }
2674         }
2675
2676         return 0;
2677 }
2678
2679
2680 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx)
2681 {
2682         struct wpa_supplicant *wpa_s = eloop_ctx;
2683         struct wpa_hw_modes *mode;
2684         struct wpa_channel_data *chan;
2685         int skip = 0;
2686         int timeout = 0;
2687         struct wpa_ssid *ssid = wpa_s->current_ssid;
2688         int adhoc;
2689
2690         if (!wpa_s->mlme.sta_scanning || wpa_s->mlme.modes == NULL)
2691                 return;
2692
2693         adhoc = ssid && ssid->mode == 1;
2694
2695         switch (wpa_s->mlme.scan_state) {
2696         case SCAN_SET_CHANNEL:
2697                 mode = &wpa_s->mlme.modes[wpa_s->mlme.scan_hw_mode_idx];
2698                 if (wpa_s->mlme.scan_hw_mode_idx >=
2699                     (int) wpa_s->mlme.num_modes ||
2700                     (wpa_s->mlme.scan_hw_mode_idx + 1 ==
2701                      (int) wpa_s->mlme.num_modes
2702                      && wpa_s->mlme.scan_channel_idx >= mode->num_channels)) {
2703                         if (ieee80211_sta_restore_oper_chan(wpa_s)) {
2704                                 wpa_printf(MSG_DEBUG, "MLME: failed to "
2705                                            "restore operational channel after "
2706                                            "scan");
2707                         }
2708                         wpa_printf(MSG_DEBUG, "MLME: scan completed");
2709                         wpa_s->mlme.sta_scanning = 0;
2710                         os_get_time(&wpa_s->mlme.last_scan_completed);
2711                         wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
2712                         if (adhoc) {
2713                                 if (!wpa_s->mlme.bssid_set ||
2714                                     (wpa_s->mlme.state ==
2715                                      IEEE80211_IBSS_JOINED &&
2716                                      !ieee80211_sta_active_ibss(wpa_s)))
2717                                         ieee80211_sta_find_ibss(wpa_s);
2718                         }
2719                         return;
2720                 }
2721                 skip = !(wpa_s->mlme.hw_modes & (1 << mode->mode));
2722                 chan = &mode->channels[wpa_s->mlme.scan_channel_idx];
2723                 if (!(chan->flag & WPA_CHAN_W_SCAN) ||
2724                     (adhoc && !(chan->flag & WPA_CHAN_W_IBSS)) ||
2725                     (wpa_s->mlme.hw_modes & (1 << WPA_MODE_IEEE80211G) &&
2726                      mode->mode == WPA_MODE_IEEE80211B &&
2727                      wpa_s->mlme.scan_skip_11b))
2728                         skip = 1;
2729
2730                 if (!skip) {
2731                         wpa_printf(MSG_MSGDUMP,
2732                                    "MLME: scan channel %d (%d MHz)",
2733                                    chan->chan, chan->freq);
2734
2735                         wpa_s->mlme.channel = chan->chan;
2736                         wpa_s->mlme.freq = chan->freq;
2737                         wpa_s->mlme.phymode = mode->mode;
2738                         if (ieee80211_sta_set_channel(wpa_s, mode->mode,
2739                                                       chan->chan, chan->freq))
2740                         {
2741                                 wpa_printf(MSG_DEBUG, "MLME: failed to set "
2742                                            "channel %d (%d MHz) for scan",
2743                                            chan->chan, chan->freq);
2744                                 skip = 1;
2745                         }
2746                 }
2747
2748                 wpa_s->mlme.scan_channel_idx++;
2749                 if (wpa_s->mlme.scan_channel_idx >=
2750                     wpa_s->mlme.modes[wpa_s->mlme.scan_hw_mode_idx].
2751                     num_channels) {
2752                         wpa_s->mlme.scan_hw_mode_idx++;
2753                         wpa_s->mlme.scan_channel_idx = 0;
2754                 }
2755
2756                 if (skip) {
2757                         timeout = 0;
2758                         break;
2759                 }
2760
2761                 timeout = IEEE80211_PROBE_DELAY;
2762                 wpa_s->mlme.scan_state = SCAN_SEND_PROBE;
2763                 break;
2764         case SCAN_SEND_PROBE:
2765                 if (ieee80211_active_scan(wpa_s)) {
2766                         ieee80211_send_probe_req(wpa_s, NULL,
2767                                                  wpa_s->mlme.scan_ssid,
2768                                                  wpa_s->mlme.scan_ssid_len);
2769                         timeout = IEEE80211_CHANNEL_TIME;
2770                 } else {
2771                         timeout = IEEE80211_PASSIVE_CHANNEL_TIME;
2772                 }
2773                 wpa_s->mlme.scan_state = SCAN_SET_CHANNEL;
2774                 break;
2775         }
2776
2777         eloop_register_timeout(timeout / 1000, 1000 * (timeout % 1000),
2778                                ieee80211_sta_scan_timer, wpa_s, NULL);
2779 }
2780
2781
2782 int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s, const u8 *ssid,
2783                            size_t ssid_len)
2784 {
2785         if (ssid_len > MAX_SSID_LEN)
2786                 return -1;
2787
2788         /* MLME-SCAN.request (page 118)  page 144 (11.1.3.1)
2789          * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
2790          * BSSID: MACAddress
2791          * SSID
2792          * ScanType: ACTIVE, PASSIVE
2793          * ProbeDelay: delay (in microseconds) to be used prior to transmitting
2794          *    a Probe frame during active scanning
2795          * ChannelList
2796          * MinChannelTime (>= ProbeDelay), in TU
2797          * MaxChannelTime: (>= MinChannelTime), in TU
2798          */
2799
2800          /* MLME-SCAN.confirm
2801           * BSSDescriptionSet
2802           * ResultCode: SUCCESS, INVALID_PARAMETERS
2803          */
2804
2805         /* TODO: if assoc, move to power save mode for the duration of the
2806          * scan */
2807
2808         if (wpa_s->mlme.sta_scanning)
2809                 return -1;
2810
2811         wpa_printf(MSG_DEBUG, "MLME: starting scan");
2812
2813         ieee80211_sta_save_oper_chan(wpa_s);
2814
2815         wpa_s->mlme.sta_scanning = 1;
2816         /* TODO: stop TX queue? */
2817
2818         if (ssid) {
2819                 wpa_s->mlme.scan_ssid_len = ssid_len;
2820                 os_memcpy(wpa_s->mlme.scan_ssid, ssid, ssid_len);
2821         } else
2822                 wpa_s->mlme.scan_ssid_len = 0;
2823         wpa_s->mlme.scan_skip_11b = 1; /* FIX: clear this is 11g is not
2824                                         * supported */
2825         wpa_s->mlme.scan_state = SCAN_SET_CHANNEL;
2826         wpa_s->mlme.scan_hw_mode_idx = 0;
2827         wpa_s->mlme.scan_channel_idx = 0;
2828         eloop_register_timeout(0, 1, ieee80211_sta_scan_timer, wpa_s, NULL);
2829
2830         return 0;
2831 }
2832
2833
2834 struct wpa_scan_results *
2835 ieee80211_sta_get_scan_results(struct wpa_supplicant *wpa_s)
2836 {
2837         size_t ap_num = 0;
2838         struct wpa_scan_results *res;
2839         struct wpa_scan_res *r;
2840         struct ieee80211_sta_bss *bss;
2841
2842         res = os_zalloc(sizeof(*res));
2843         for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next)
2844                 ap_num++;
2845         res->res = os_zalloc(ap_num * sizeof(struct wpa_scan_res *));
2846         if (res->res == NULL) {
2847                 os_free(res);
2848                 return NULL;
2849         }
2850
2851         for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) {
2852                 r = os_zalloc(sizeof(*r) + bss->ie_len);
2853                 if (r == NULL)
2854                         break;
2855                 os_memcpy(r->bssid, bss->bssid, ETH_ALEN);
2856                 r->freq = bss->freq;
2857                 r->beacon_int = bss->beacon_int;
2858                 r->caps = bss->capability;
2859                 r->level = bss->rssi;
2860                 r->tsf = bss->timestamp;
2861                 if (bss->ie) {
2862                         r->ie_len = bss->ie_len;
2863                         os_memcpy(r + 1, bss->ie, bss->ie_len);
2864                 }
2865
2866                 res->res[res->num++] = r;
2867         }
2868
2869         return res;
2870 }
2871
2872
2873 #if 0 /* FIX */
2874 struct sta_info * ieee80211_ibss_add_sta(struct wpa_supplicant *wpa_s,
2875                                          struct sk_buff *skb, u8 *bssid,
2876                                          u8 *addr)
2877 {
2878         struct ieee80211_local *local = dev->priv;
2879         struct list_head *ptr;
2880         struct sta_info *sta;
2881         struct wpa_supplicant *sta_dev = NULL;
2882
2883         /* TODO: Could consider removing the least recently used entry and
2884          * allow new one to be added. */
2885         if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
2886                 if (net_ratelimit()) {
2887                         wpa_printf(MSG_DEBUG, "MLME: No room for a new IBSS "
2888                                    "STA entry " MACSTR, MAC2STR(addr));
2889                 }
2890                 return NULL;
2891         }
2892
2893         spin_lock_bh(&local->sub_if_lock);
2894         list_for_each(ptr, &local->sub_if_list) {
2895                 sdata = list_entry(ptr, struct ieee80211_sub_if_data, list);
2896                 if (sdata->type == IEEE80211_SUB_IF_TYPE_STA &&
2897                     os_memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
2898                         sta_dev = sdata->dev;
2899                         break;
2900                 }
2901         }
2902         spin_unlock_bh(&local->sub_if_lock);
2903
2904         if (sta_dev == NULL)
2905                 return NULL;
2906
2907         wpa_printf(MSG_DEBUG, "MLME: Adding new IBSS station " MACSTR
2908                    " (dev=%s)", MAC2STR(addr), sta_dev->name);
2909
2910         sta = sta_info_add(wpa_s, addr);
2911         if (sta == NULL) {
2912                 return NULL;
2913         }
2914
2915         sta->dev = sta_dev;
2916         sta->supp_rates = wpa_s->mlme.supp_rates_bits;
2917
2918         rate_control_rate_init(local, sta);
2919
2920         return sta; /* caller will call sta_info_release() */
2921 }
2922 #endif
2923
2924
2925 int ieee80211_sta_deauthenticate(struct wpa_supplicant *wpa_s, u16 reason)
2926 {
2927         wpa_printf(MSG_DEBUG, "MLME: deauthenticate(reason=%d)", reason);
2928
2929         ieee80211_send_deauth(wpa_s, reason);
2930         ieee80211_set_associated(wpa_s, 0);
2931         return 0;
2932 }
2933
2934
2935 int ieee80211_sta_disassociate(struct wpa_supplicant *wpa_s, u16 reason)
2936 {
2937         wpa_printf(MSG_DEBUG, "MLME: disassociate(reason=%d)", reason);
2938
2939         if (!wpa_s->mlme.associated)
2940                 return -1;
2941
2942         ieee80211_send_disassoc(wpa_s, reason);
2943         ieee80211_set_associated(wpa_s, 0);
2944         return 0;
2945 }
2946
2947
2948 void ieee80211_sta_rx(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len,
2949                       struct ieee80211_rx_status *rx_status)
2950 {
2951         struct ieee80211_mgmt *mgmt;
2952         u16 fc;
2953         const u8 *pos;
2954
2955         /* wpa_hexdump(MSG_MSGDUMP, "MLME: Received frame", buf, len); */
2956
2957         if (wpa_s->mlme.sta_scanning) {
2958                 ieee80211_sta_rx_scan(wpa_s, buf, len, rx_status);
2959                 return;
2960         }
2961
2962         if (len < 24)
2963                 return;
2964
2965         mgmt = (struct ieee80211_mgmt *) buf;
2966         fc = le_to_host16(mgmt->frame_control);
2967
2968         if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT)
2969                 ieee80211_sta_rx_mgmt(wpa_s, buf, len, rx_status);
2970         else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) {
2971                 if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) !=
2972                     WLAN_FC_FROMDS)
2973                         return;
2974                 /* mgmt->sa is actually BSSID for FromDS data frames */
2975                 if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0)
2976                         return;
2977                 /* Skip IEEE 802.11 and LLC headers */
2978                 pos = buf + 24 + 6;
2979                 if (WPA_GET_BE16(pos) != ETH_P_EAPOL)
2980                         return;
2981                 pos += 2;
2982                 /* mgmt->bssid is actually BSSID for SA data frames */
2983                 wpa_supplicant_rx_eapol(wpa_s, mgmt->bssid,
2984                                         pos, buf + len - pos);
2985         }
2986 }
2987
2988
2989 void ieee80211_sta_free_hw_features(struct wpa_hw_modes *hw_features,
2990                                     size_t num_hw_features)
2991 {
2992         size_t i;
2993
2994         if (hw_features == NULL)
2995                 return;
2996
2997         for (i = 0; i < num_hw_features; i++) {
2998                 os_free(hw_features[i].channels);
2999                 os_free(hw_features[i].rates);
3000         }
3001
3002         os_free(hw_features);
3003 }
3004
3005
3006 int ieee80211_sta_init(struct wpa_supplicant *wpa_s)
3007 {
3008         u16 num_modes, flags;
3009
3010         wpa_s->mlme.modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes,
3011                                                         &flags);
3012         if (wpa_s->mlme.modes == NULL) {
3013                 wpa_printf(MSG_ERROR, "MLME: Failed to read supported "
3014                            "channels and rates from the driver");
3015                 return -1;
3016         }
3017
3018         wpa_s->mlme.num_modes = num_modes;
3019
3020         wpa_s->mlme.hw_modes = 1 << WPA_MODE_IEEE80211A;
3021         wpa_s->mlme.hw_modes |= 1 << WPA_MODE_IEEE80211B;
3022         wpa_s->mlme.hw_modes |= 1 << WPA_MODE_IEEE80211G;
3023
3024         wpa_s->mlme.wmm_enabled = 1;
3025
3026         return 0;
3027 }
3028
3029
3030 void ieee80211_sta_deinit(struct wpa_supplicant *wpa_s)
3031 {
3032         eloop_cancel_timeout(ieee80211_sta_timer, wpa_s, NULL);
3033         eloop_cancel_timeout(ieee80211_sta_scan_timer, wpa_s, NULL);
3034         os_free(wpa_s->mlme.extra_ie);
3035         wpa_s->mlme.extra_ie = NULL;
3036         os_free(wpa_s->mlme.extra_probe_ie);
3037         wpa_s->mlme.extra_probe_ie = NULL;
3038         os_free(wpa_s->mlme.assocreq_ies);
3039         wpa_s->mlme.assocreq_ies = NULL;
3040         os_free(wpa_s->mlme.assocresp_ies);
3041         wpa_s->mlme.assocresp_ies = NULL;
3042         ieee80211_bss_list_deinit(wpa_s);
3043         ieee80211_sta_free_hw_features(wpa_s->mlme.modes,
3044                                        wpa_s->mlme.num_modes);
3045 #ifdef CONFIG_IEEE80211R
3046         os_free(wpa_s->mlme.ft_ies);
3047         wpa_s->mlme.ft_ies = NULL;
3048         wpa_s->mlme.ft_ies_len = 0;
3049 #endif /* CONFIG_IEEE80211R */
3050 }
3051
3052
3053 #ifdef CONFIG_IEEE80211R
3054
3055 int ieee80211_sta_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
3056                                 const u8 *ies, size_t ies_len)
3057 {
3058         if (md == NULL) {
3059                 wpa_printf(MSG_DEBUG, "MLME: Clear FT mobility domain");
3060                 os_memset(wpa_s->mlme.current_md, 0, MOBILITY_DOMAIN_ID_LEN);
3061         } else {
3062                 wpa_printf(MSG_DEBUG, "MLME: Update FT IEs for MD " MACSTR,
3063                            MAC2STR(md));
3064                 os_memcpy(wpa_s->mlme.current_md, md, MOBILITY_DOMAIN_ID_LEN);
3065         }
3066
3067         wpa_hexdump(MSG_DEBUG, "MLME: FT IEs", ies, ies_len);
3068         os_free(wpa_s->mlme.ft_ies);
3069         wpa_s->mlme.ft_ies = os_malloc(ies_len);
3070         if (wpa_s->mlme.ft_ies == NULL)
3071                 return -1;
3072         os_memcpy(wpa_s->mlme.ft_ies, ies, ies_len);
3073         wpa_s->mlme.ft_ies_len = ies_len;
3074
3075         return 0;
3076 }
3077
3078
3079 int ieee80211_sta_send_ft_action(struct wpa_supplicant *wpa_s, u8 action,
3080                                  const u8 *target_ap,
3081                                  const u8 *ies, size_t ies_len)
3082 {
3083         u8 *buf;
3084         size_t len;
3085         struct ieee80211_mgmt *mgmt;
3086         int res;
3087
3088         /*
3089          * Action frame payload:
3090          * Category[1] = 6 (Fast BSS Transition)
3091          * Action[1] = 1 (Fast BSS Transition Request)
3092          * STA Address
3093          * Target AP Address
3094          * FT IEs
3095          */
3096
3097         buf = os_zalloc(sizeof(*mgmt) + ies_len);
3098         if (buf == NULL) {
3099                 wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
3100                            "FT action frame");
3101                 return -1;
3102         }
3103
3104         mgmt = (struct ieee80211_mgmt *) buf;
3105         len = 24;
3106         os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN);
3107         os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
3108         os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
3109         mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
3110                                            WLAN_FC_STYPE_ACTION);
3111         mgmt->u.action.category = WLAN_ACTION_FT;
3112         mgmt->u.action.u.ft_action_req.action = action;
3113         os_memcpy(mgmt->u.action.u.ft_action_req.sta_addr, wpa_s->own_addr,
3114                   ETH_ALEN);
3115         os_memcpy(mgmt->u.action.u.ft_action_req.target_ap_addr, target_ap,
3116                   ETH_ALEN);
3117         os_memcpy(mgmt->u.action.u.ft_action_req.variable, ies, ies_len);
3118         len += 1 + sizeof(mgmt->u.action.u.ft_action_req) + ies_len;
3119
3120         wpa_printf(MSG_DEBUG, "MLME: Send FT Action Frame: Action=%d "
3121                    "Target AP=" MACSTR " body_len=%lu",
3122                    action, MAC2STR(target_ap), (unsigned long) ies_len);
3123
3124         res = ieee80211_sta_tx(wpa_s, buf, len);
3125         os_free(buf);
3126
3127         return res;
3128 }
3129
3130 #endif /* CONFIG_IEEE80211R */
3131
3132
3133 int ieee80211_sta_set_probe_req_ie(struct wpa_supplicant *wpa_s, const u8 *ies,
3134                                    size_t ies_len)
3135 {
3136         os_free(wpa_s->mlme.extra_probe_ie);
3137         wpa_s->mlme.extra_probe_ie = NULL;
3138         wpa_s->mlme.extra_probe_ie_len = 0;
3139
3140         if (ies == NULL)
3141                 return 0;
3142
3143         wpa_s->mlme.extra_probe_ie = os_malloc(ies_len);
3144         if (wpa_s->mlme.extra_probe_ie == NULL)
3145                 return -1;
3146
3147         os_memcpy(wpa_s->mlme.extra_probe_ie, ies, ies_len);
3148         wpa_s->mlme.extra_probe_ie_len = ies_len;
3149
3150         return 0;
3151 }