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