OSDN Git Service

am be5cce4a: Check if interface is valid in wpa_ctrl_close()
[android-x86/external-wpa_supplicant.git] / 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 (esupp_rates) {
989                         pos = buf + len;
990                         len++;
991                         esupp_rates[1]++;
992                 } else if (supp_rates[1] == 8) {
993                         esupp_rates = pos;
994                         esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
995                         esupp_rates[1] = 1;
996                         pos = &esupp_rates[2];
997                         len += 3;
998                 } else {
999                         pos = buf + len;
1000                         len++;
1001                         supp_rates[1]++;
1002                 }
1003                 *pos = rate->rate / 5;
1004         }
1005
1006         ieee80211_sta_tx(wpa_s, buf, len);
1007         os_free(buf);
1008 }
1009
1010
1011 static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s)
1012 {
1013 #if 0 /* FIX */
1014         if (sdata == NULL || sdata->default_key == NULL ||
1015             sdata->default_key->alg != ALG_WEP)
1016                 return 0;
1017         return 1;
1018 #else
1019         return 0;
1020 #endif
1021 }
1022
1023
1024 static void ieee80211_auth_completed(struct wpa_supplicant *wpa_s)
1025 {
1026         wpa_printf(MSG_DEBUG, "MLME: authenticated");
1027         wpa_s->mlme.authenticated = 1;
1028         ieee80211_associate(wpa_s);
1029 }
1030
1031
1032 static void ieee80211_auth_challenge(struct wpa_supplicant *wpa_s,
1033                                      struct ieee80211_mgmt *mgmt,
1034                                      size_t len,
1035                                      struct ieee80211_rx_status *rx_status)
1036 {
1037         u8 *pos;
1038         struct ieee802_11_elems elems;
1039
1040         wpa_printf(MSG_DEBUG, "MLME: replying to auth challenge");
1041         pos = mgmt->u.auth.variable;
1042         if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
1043             == ParseFailed) {
1044                 wpa_printf(MSG_DEBUG, "MLME: failed to parse Auth(challenge)");
1045                 return;
1046         }
1047         if (elems.challenge == NULL) {
1048                 wpa_printf(MSG_DEBUG, "MLME: no challenge IE in shared key "
1049                            "auth frame");
1050                 return;
1051         }
1052         ieee80211_send_auth(wpa_s, 3, elems.challenge - 2,
1053                             elems.challenge_len + 2, 1);
1054 }
1055
1056
1057 static void ieee80211_rx_mgmt_auth(struct wpa_supplicant *wpa_s,
1058                                    struct ieee80211_mgmt *mgmt,
1059                                    size_t len,
1060                                    struct ieee80211_rx_status *rx_status)
1061 {
1062         struct wpa_ssid *ssid = wpa_s->current_ssid;
1063         u16 auth_alg, auth_transaction, status_code;
1064         int adhoc;
1065
1066         adhoc = ssid && ssid->mode == 1;
1067
1068         if (wpa_s->mlme.state != IEEE80211_AUTHENTICATE && !adhoc) {
1069                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
1070                            "from " MACSTR ", but not in authenticate state - "
1071                            "ignored", MAC2STR(mgmt->sa));
1072                 return;
1073         }
1074
1075         if (len < 24 + 6) {
1076                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) authentication "
1077                            "frame received from " MACSTR " - ignored",
1078                            (unsigned long) len, MAC2STR(mgmt->sa));
1079                 return;
1080         }
1081
1082         if (!adhoc && os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
1083                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
1084                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
1085                            ") - ignored",
1086                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
1087                 return;
1088         }
1089
1090         if (adhoc && os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0) {
1091                 wpa_printf(MSG_DEBUG, "MLME: authentication frame received "
1092                            "from unknown BSSID (SA=" MACSTR " BSSID=" MACSTR
1093                            ") - ignored",
1094                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
1095                 return;
1096         }
1097
1098         auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
1099         auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
1100         status_code = le_to_host16(mgmt->u.auth.status_code);
1101
1102         wpa_printf(MSG_DEBUG, "MLME: RX authentication from " MACSTR
1103                    " (alg=%d transaction=%d status=%d)",
1104                    MAC2STR(mgmt->sa), auth_alg, auth_transaction, status_code);
1105
1106         if (adhoc) {
1107                 /* IEEE 802.11 standard does not require authentication in IBSS
1108                  * networks and most implementations do not seem to use it.
1109                  * However, try to reply to authentication attempts if someone
1110                  * has actually implemented this.
1111                  * TODO: Could implement shared key authentication. */
1112                 if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
1113                         wpa_printf(MSG_DEBUG, "MLME: unexpected IBSS "
1114                                    "authentication frame (alg=%d "
1115                                    "transaction=%d)",
1116                                    auth_alg, auth_transaction);
1117                         return;
1118                 }
1119                 ieee80211_send_auth(wpa_s, 2, NULL, 0, 0);
1120         }
1121
1122         if (auth_alg != wpa_s->mlme.auth_alg ||
1123             auth_transaction != wpa_s->mlme.auth_transaction) {
1124                 wpa_printf(MSG_DEBUG, "MLME: unexpected authentication frame "
1125                            "(alg=%d transaction=%d)",
1126                            auth_alg, auth_transaction);
1127                 return;
1128         }
1129
1130         if (status_code != WLAN_STATUS_SUCCESS) {
1131                 wpa_printf(MSG_DEBUG, "MLME: AP denied authentication "
1132                            "(auth_alg=%d code=%d)", wpa_s->mlme.auth_alg,
1133                            status_code);
1134                 if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
1135                         const int num_algs = 3;
1136                         u8 algs[num_algs];
1137                         int i, pos;
1138                         algs[0] = algs[1] = algs[2] = 0xff;
1139                         if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN)
1140                                 algs[0] = WLAN_AUTH_OPEN;
1141                         if (wpa_s->mlme.auth_algs &
1142                             IEEE80211_AUTH_ALG_SHARED_KEY)
1143                                 algs[1] = WLAN_AUTH_SHARED_KEY;
1144                         if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP)
1145                                 algs[2] = WLAN_AUTH_LEAP;
1146                         if (wpa_s->mlme.auth_alg == WLAN_AUTH_OPEN)
1147                                 pos = 0;
1148                         else if (wpa_s->mlme.auth_alg == WLAN_AUTH_SHARED_KEY)
1149                                 pos = 1;
1150                         else
1151                                 pos = 2;
1152                         for (i = 0; i < num_algs; i++) {
1153                                 pos++;
1154                                 if (pos >= num_algs)
1155                                         pos = 0;
1156                                 if (algs[pos] == wpa_s->mlme.auth_alg ||
1157                                     algs[pos] == 0xff)
1158                                         continue;
1159                                 if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
1160                                     !ieee80211_sta_wep_configured(wpa_s))
1161                                         continue;
1162                                 wpa_s->mlme.auth_alg = algs[pos];
1163                                 wpa_printf(MSG_DEBUG, "MLME: set auth_alg=%d "
1164                                            "for next try",
1165                                            wpa_s->mlme.auth_alg);
1166                                 break;
1167                         }
1168                 }
1169                 return;
1170         }
1171
1172         switch (wpa_s->mlme.auth_alg) {
1173         case WLAN_AUTH_OPEN:
1174         case WLAN_AUTH_LEAP:
1175                 ieee80211_auth_completed(wpa_s);
1176                 break;
1177         case WLAN_AUTH_SHARED_KEY:
1178                 if (wpa_s->mlme.auth_transaction == 4)
1179                         ieee80211_auth_completed(wpa_s);
1180                 else
1181                         ieee80211_auth_challenge(wpa_s, mgmt, len,
1182                                                  rx_status);
1183                 break;
1184         }
1185 }
1186
1187
1188 static void ieee80211_rx_mgmt_deauth(struct wpa_supplicant *wpa_s,
1189                                      struct ieee80211_mgmt *mgmt,
1190                                      size_t len,
1191                                      struct ieee80211_rx_status *rx_status)
1192 {
1193         u16 reason_code;
1194
1195         if (len < 24 + 2) {
1196                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) deauthentication "
1197                            "frame received from " MACSTR " - ignored",
1198                            (unsigned long) len, MAC2STR(mgmt->sa));
1199                 return;
1200         }
1201
1202         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
1203                 wpa_printf(MSG_DEBUG, "MLME: deauthentication frame received "
1204                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
1205                            ") - ignored",
1206                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
1207                 return;
1208         }
1209
1210         reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1211
1212         wpa_printf(MSG_DEBUG, "MLME: RX deauthentication from " MACSTR
1213                    " (reason=%d)", MAC2STR(mgmt->sa), reason_code);
1214
1215         if (wpa_s->mlme.authenticated)
1216                 wpa_printf(MSG_DEBUG, "MLME: deauthenticated");
1217
1218         if (wpa_s->mlme.state == IEEE80211_AUTHENTICATE ||
1219             wpa_s->mlme.state == IEEE80211_ASSOCIATE ||
1220             wpa_s->mlme.state == IEEE80211_ASSOCIATED) {
1221                 wpa_s->mlme.state = IEEE80211_AUTHENTICATE;
1222                 ieee80211_reschedule_timer(wpa_s,
1223                                            IEEE80211_RETRY_AUTH_INTERVAL);
1224         }
1225
1226         ieee80211_set_associated(wpa_s, 0);
1227         wpa_s->mlme.authenticated = 0;
1228 }
1229
1230
1231 static void ieee80211_rx_mgmt_disassoc(struct wpa_supplicant *wpa_s,
1232                                        struct ieee80211_mgmt *mgmt,
1233                                        size_t len,
1234                                        struct ieee80211_rx_status *rx_status)
1235 {
1236         u16 reason_code;
1237
1238         if (len < 24 + 2) {
1239                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) disassociation "
1240                            "frame received from " MACSTR " - ignored",
1241                            (unsigned long) len, MAC2STR(mgmt->sa));
1242                 return;
1243         }
1244
1245         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
1246                 wpa_printf(MSG_DEBUG, "MLME: disassociation frame received "
1247                            "from unknown AP (SA=" MACSTR " BSSID=" MACSTR
1248                            ") - ignored",
1249                            MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
1250                 return;
1251         }
1252
1253         reason_code = le_to_host16(mgmt->u.disassoc.reason_code);
1254
1255         wpa_printf(MSG_DEBUG, "MLME: RX disassociation from " MACSTR
1256                    " (reason=%d)", MAC2STR(mgmt->sa), reason_code);
1257
1258         if (wpa_s->mlme.associated)
1259                 wpa_printf(MSG_DEBUG, "MLME: disassociated");
1260
1261         if (wpa_s->mlme.state == IEEE80211_ASSOCIATED) {
1262                 wpa_s->mlme.state = IEEE80211_ASSOCIATE;
1263                 ieee80211_reschedule_timer(wpa_s,
1264                                            IEEE80211_RETRY_AUTH_INTERVAL);
1265         }
1266
1267         ieee80211_set_associated(wpa_s, 0);
1268 }
1269
1270
1271 static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s,
1272                                          struct ieee80211_mgmt *mgmt,
1273                                          size_t len,
1274                                          struct ieee80211_rx_status *rx_status,
1275                                          int reassoc)
1276 {
1277         u8 rates[32];
1278         size_t rates_len;
1279         u16 capab_info, status_code, aid;
1280         struct ieee802_11_elems elems;
1281         u8 *pos;
1282
1283         /* AssocResp and ReassocResp have identical structure, so process both
1284          * of them in this function. */
1285
1286         if (wpa_s->mlme.state != IEEE80211_ASSOCIATE) {
1287                 wpa_printf(MSG_DEBUG, "MLME: association frame received from "
1288                            MACSTR ", but not in associate state - ignored",
1289                            MAC2STR(mgmt->sa));
1290                 return;
1291         }
1292
1293         if (len < 24 + 6) {
1294                 wpa_printf(MSG_DEBUG, "MLME: too short (%lu) association "
1295                            "frame received from " MACSTR " - ignored",
1296                            (unsigned long) len, MAC2STR(mgmt->sa));
1297                 return;
1298         }
1299
1300         if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) {
1301                 wpa_printf(MSG_DEBUG, "MLME: association frame received from "
1302                            "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - "
1303                            "ignored", MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid));
1304                 return;
1305         }
1306
1307         capab_info = le_to_host16(mgmt->u.assoc_resp.capab_info);
1308         status_code = le_to_host16(mgmt->u.assoc_resp.status_code);
1309         aid = le_to_host16(mgmt->u.assoc_resp.aid);
1310         if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
1311                 wpa_printf(MSG_DEBUG, "MLME: invalid aid value %d; bits 15:14 "
1312                            "not set", aid);
1313         aid &= ~(BIT(15) | BIT(14));
1314
1315         wpa_printf(MSG_DEBUG, "MLME: RX %sssocResp from " MACSTR
1316                    " (capab=0x%x status=%d aid=%d)",
1317                    reassoc ? "Rea" : "A", MAC2STR(mgmt->sa),
1318                    capab_info, status_code, aid);
1319
1320         if (status_code != WLAN_STATUS_SUCCESS) {
1321                 wpa_printf(MSG_DEBUG, "MLME: AP denied association (code=%d)",
1322                            status_code);
1323                 return;
1324         }
1325
1326         pos = mgmt->u.assoc_resp.variable;
1327         if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
1328             == ParseFailed) {
1329                 wpa_printf(MSG_DEBUG, "MLME: failed to parse AssocResp");
1330                 return;
1331         }
1332
1333         if (elems.supp_rates == NULL) {
1334                 wpa_printf(MSG_DEBUG, "MLME: no SuppRates element in "
1335                            "AssocResp");
1336                 return;
1337         }
1338
1339         wpa_printf(MSG_DEBUG, "MLME: associated");
1340         wpa_s->mlme.aid = aid;
1341         wpa_s->mlme.ap_capab = capab_info;
1342
1343         os_free(wpa_s->mlme.assocresp_ies);
1344         wpa_s->mlme.assocresp_ies_len = len - (pos - (u8 *) mgmt);
1345         wpa_s->mlme.assocresp_ies = os_malloc(wpa_s->mlme.assocresp_ies_len);
1346         if (wpa_s->mlme.assocresp_ies) {
1347                 os_memcpy(wpa_s->mlme.assocresp_ies, pos,
1348                           wpa_s->mlme.assocresp_ies_len);
1349         }
1350
1351         ieee80211_set_associated(wpa_s, 1);
1352
1353         rates_len = elems.supp_rates_len;
1354         if (rates_len > sizeof(rates))
1355                 rates_len = sizeof(rates);
1356         os_memcpy(rates, elems.supp_rates, rates_len);
1357         if (elems.ext_supp_rates) {
1358                 size_t _len = elems.ext_supp_rates_len;
1359                 if (_len > sizeof(rates) - rates_len)
1360                         _len = sizeof(rates) - rates_len;
1361                 os_memcpy(rates + rates_len, elems.ext_supp_rates, _len);
1362                 rates_len += _len;
1363         }
1364
1365         if (wpa_drv_set_bssid(wpa_s, wpa_s->bssid) < 0) {
1366                 wpa_printf(MSG_DEBUG, "MLME: failed to set BSSID for the "
1367                            "netstack");
1368         }
1369         if (wpa_drv_set_ssid(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) <
1370             0) {
1371                 wpa_printf(MSG_DEBUG, "MLME: failed to set SSID for the "
1372                            "netstack");
1373         }
1374
1375         /* Remove STA entry before adding a new one just in case to avoid
1376          * problems with existing configuration (e.g., keys). */
1377         wpa_drv_mlme_remove_sta(wpa_s, wpa_s->bssid);
1378         if (wpa_drv_mlme_add_sta(wpa_s, wpa_s->bssid, rates, rates_len) < 0) {
1379                 wpa_printf(MSG_DEBUG, "MLME: failed to add STA entry to the "
1380                            "netstack");
1381         }
1382
1383 #if 0 /* FIX? */
1384         sta->assoc_ap = 1;
1385
1386         if (elems.wmm_param && wpa_s->mlme.wmm_enabled) {
1387                 sta->flags |= WLAN_STA_WME;
1388                 ieee80211_sta_wmm_params(wpa_s, elems.wmm_param,
1389                                          elems.wmm_param_len);
1390         }
1391 #endif
1392
1393         ieee80211_associated(wpa_s);
1394 }
1395
1396
1397 /* Caller must hold local->sta_bss_lock */
1398 static void __ieee80211_bss_hash_add(struct wpa_supplicant *wpa_s,
1399                                      struct ieee80211_sta_bss *bss)
1400 {
1401         bss->hnext = wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)];
1402         wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)] = bss;
1403 }
1404
1405
1406 /* Caller must hold local->sta_bss_lock */
1407 static void __ieee80211_bss_hash_del(struct wpa_supplicant *wpa_s,
1408                                      struct ieee80211_sta_bss *bss)
1409 {
1410         struct ieee80211_sta_bss *b, *prev = NULL;
1411         b = wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)];
1412         while (b) {
1413                 if (b == bss) {
1414                         if (prev == NULL) {
1415                                 wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)]
1416                                         = bss->hnext;
1417                         } else {
1418                                 prev->hnext = bss->hnext;
1419                         }
1420                         break;
1421                 }
1422                 prev = b;
1423                 b = b->hnext;
1424         }
1425 }
1426
1427
1428 static struct ieee80211_sta_bss *
1429 ieee80211_bss_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
1430 {
1431         struct ieee80211_sta_bss *bss;
1432
1433         bss = os_zalloc(sizeof(*bss));
1434         if (bss == NULL)
1435                 return NULL;
1436         os_memcpy(bss->bssid, bssid, ETH_ALEN);
1437
1438         /* TODO: order by RSSI? */
1439         bss->next = wpa_s->mlme.sta_bss_list;
1440         wpa_s->mlme.sta_bss_list = bss;
1441         __ieee80211_bss_hash_add(wpa_s, bss);
1442         return bss;
1443 }
1444
1445
1446 static struct ieee80211_sta_bss *
1447 ieee80211_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid)
1448 {
1449         struct ieee80211_sta_bss *bss;
1450
1451         bss = wpa_s->mlme.sta_bss_hash[STA_HASH(bssid)];
1452         while (bss) {
1453                 if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
1454                         break;
1455                 bss = bss->hnext;
1456         }
1457         return bss;
1458 }
1459
1460
1461 static void ieee80211_bss_free(struct wpa_supplicant *wpa_s,
1462                                struct ieee80211_sta_bss *bss)
1463 {
1464         __ieee80211_bss_hash_del(wpa_s, bss);
1465         os_free(bss->wpa_ie);
1466         os_free(bss->rsn_ie);
1467         os_free(bss->wmm_ie);
1468         os_free(bss);
1469 }
1470
1471
1472 static void ieee80211_bss_list_deinit(struct wpa_supplicant *wpa_s)
1473 {
1474         struct ieee80211_sta_bss *bss, *prev;
1475
1476         bss = wpa_s->mlme.sta_bss_list;
1477         wpa_s->mlme.sta_bss_list = NULL;
1478         while (bss) {
1479                 prev = bss;
1480                 bss = bss->next;
1481                 ieee80211_bss_free(wpa_s, prev);
1482         }
1483 }
1484
1485
1486 static void ieee80211_bss_info(struct wpa_supplicant *wpa_s,
1487                                struct ieee80211_mgmt *mgmt,
1488                                size_t len,
1489                                struct ieee80211_rx_status *rx_status,
1490                                int beacon)
1491 {
1492         struct ieee802_11_elems elems;
1493         size_t baselen;
1494         int channel, invalid = 0, clen;
1495         struct ieee80211_sta_bss *bss;
1496         u64 timestamp;
1497         u8 *pos;
1498
1499         if (!beacon && os_memcmp(mgmt->da, wpa_s->own_addr, ETH_ALEN))
1500                 return; /* ignore ProbeResp to foreign address */
1501
1502 #if 0
1503         wpa_printf(MSG_MSGDUMP, "MLME: RX %s from " MACSTR " to " MACSTR,
1504                    beacon ? "Beacon" : "Probe Response",
1505                    MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
1506 #endif
1507
1508         baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
1509         if (baselen > len)
1510                 return;
1511
1512         pos = mgmt->u.beacon.timestamp;
1513         timestamp = ((u64) pos[7] << 56) | ((u64) pos[6] << 48) |
1514                 ((u64) pos[5] << 40) | ((u64) pos[4] << 32) |
1515                 ((u64) pos[3] << 24) | ((u64) pos[2] << 16) |
1516                 ((u64) pos[1] << 8) | ((u64) pos[0]);
1517
1518 #if 0 /* FIX */
1519         if (local->conf.mode == IW_MODE_ADHOC && beacon &&
1520             os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0) {
1521 #ifdef IEEE80211_IBSS_DEBUG
1522                 static unsigned long last_tsf_debug = 0;
1523                 u64 tsf;
1524                 if (local->hw->get_tsf)
1525                         tsf = local->hw->get_tsf(local->mdev);
1526                 else
1527                         tsf = -1LLU;
1528                 if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
1529                         wpa_printf(MSG_DEBUG, "RX beacon SA=" MACSTR " BSSID="
1530                                    MACSTR " TSF=0x%llx BCN=0x%llx diff=%lld "
1531                                    "@%ld",
1532                                    MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
1533                                    tsf, timestamp, tsf - timestamp, jiffies);
1534                         last_tsf_debug = jiffies;
1535                 }
1536 #endif /* IEEE80211_IBSS_DEBUG */
1537         }
1538 #endif
1539
1540         if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
1541                                    &elems) == ParseFailed)
1542                 invalid = 1;
1543
1544 #if 0 /* FIX */
1545         if (local->conf.mode == IW_MODE_ADHOC && elems.supp_rates &&
1546             os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0 &&
1547             (sta = sta_info_get(local, mgmt->sa))) {
1548                 struct ieee80211_rate *rates;
1549                 size_t num_rates;
1550                 u32 supp_rates, prev_rates;
1551                 int i, j, oper_mode;
1552
1553                 rates = local->curr_rates;
1554                 num_rates = local->num_curr_rates;
1555                 oper_mode = wpa_s->mlme.sta_scanning ?
1556                         local->scan_oper_phymode : local->conf.phymode;
1557                 for (i = 0; i < local->hw->num_modes; i++) {
1558                         struct ieee80211_hw_modes *mode = &local->hw->modes[i];
1559                         if (oper_mode == mode->mode) {
1560                                 rates = mode->rates;
1561                                 num_rates = mode->num_rates;
1562                                 break;
1563                         }
1564                 }
1565
1566                 supp_rates = 0;
1567                 for (i = 0; i < elems.supp_rates_len +
1568                              elems.ext_supp_rates_len; i++) {
1569                         u8 rate = 0;
1570                         int own_rate;
1571                         if (i < elems.supp_rates_len)
1572                                 rate = elems.supp_rates[i];
1573                         else if (elems.ext_supp_rates)
1574                                 rate = elems.ext_supp_rates
1575                                         [i - elems.supp_rates_len];
1576                         own_rate = 5 * (rate & 0x7f);
1577                         if (oper_mode == MODE_ATHEROS_TURBO)
1578                                 own_rate *= 2;
1579                         for (j = 0; j < num_rates; j++)
1580                                 if (rates[j].rate == own_rate)
1581                                         supp_rates |= BIT(j);
1582                 }
1583
1584                 prev_rates = sta->supp_rates;
1585                 sta->supp_rates &= supp_rates;
1586                 if (sta->supp_rates == 0) {
1587                         /* No matching rates - this should not really happen.
1588                          * Make sure that at least one rate is marked
1589                          * supported to avoid issues with TX rate ctrl. */
1590                         sta->supp_rates = wpa_s->mlme.supp_rates_bits;
1591                 }
1592                 if (sta->supp_rates != prev_rates) {
1593                         wpa_printf(MSG_DEBUG, "MLME: updated supp_rates set "
1594                                    "for " MACSTR " based on beacon info "
1595                                    "(0x%x & 0x%x -> 0x%x)",
1596                                    MAC2STR(sta->addr), prev_rates,
1597                                    supp_rates, sta->supp_rates);
1598                 }
1599                 sta_info_release(local, sta);
1600         }
1601 #endif
1602
1603         if (elems.ssid == NULL)
1604                 return;
1605
1606         if (elems.ds_params && elems.ds_params_len == 1)
1607                 channel = elems.ds_params[0];
1608         else
1609                 channel = rx_status->channel;
1610
1611         bss = ieee80211_bss_get(wpa_s, mgmt->bssid);
1612         if (bss == NULL) {
1613                 bss = ieee80211_bss_add(wpa_s, mgmt->bssid);
1614                 if (bss == NULL)
1615                         return;
1616         } else {
1617 #if 0
1618                 /* TODO: order by RSSI? */
1619                 spin_lock_bh(&local->sta_bss_lock);
1620                 list_move_tail(&bss->list, &local->sta_bss_list);
1621                 spin_unlock_bh(&local->sta_bss_lock);
1622 #endif
1623         }
1624
1625         if (bss->probe_resp && beacon) {
1626                 /* Do not allow beacon to override data from Probe Response. */
1627                 return;
1628         }
1629
1630         bss->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int);
1631         bss->capability = le_to_host16(mgmt->u.beacon.capab_info);
1632         if (elems.ssid && elems.ssid_len <= MAX_SSID_LEN) {
1633                 os_memcpy(bss->ssid, elems.ssid, elems.ssid_len);
1634                 bss->ssid_len = elems.ssid_len;
1635         }
1636
1637         bss->supp_rates_len = 0;
1638         if (elems.supp_rates) {
1639                 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
1640                 if (clen > elems.supp_rates_len)
1641                         clen = elems.supp_rates_len;
1642                 os_memcpy(&bss->supp_rates[bss->supp_rates_len],
1643                           elems.supp_rates, clen);
1644                 bss->supp_rates_len += clen;
1645         }
1646         if (elems.ext_supp_rates) {
1647                 clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
1648                 if (clen > elems.ext_supp_rates_len)
1649                         clen = elems.ext_supp_rates_len;
1650                 os_memcpy(&bss->supp_rates[bss->supp_rates_len],
1651                           elems.ext_supp_rates, clen);
1652                 bss->supp_rates_len += clen;
1653         }
1654
1655         if (elems.wpa &&
1656             (bss->wpa_ie == NULL || bss->wpa_ie_len != elems.wpa_len ||
1657              os_memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
1658                 os_free(bss->wpa_ie);
1659                 bss->wpa_ie = os_malloc(elems.wpa_len + 2);
1660                 if (bss->wpa_ie) {
1661                         os_memcpy(bss->wpa_ie, elems.wpa - 2,
1662                                   elems.wpa_len + 2);
1663                         bss->wpa_ie_len = elems.wpa_len + 2;
1664                 } else
1665                         bss->wpa_ie_len = 0;
1666         } else if (!elems.wpa && bss->wpa_ie) {
1667                 os_free(bss->wpa_ie);
1668                 bss->wpa_ie = NULL;
1669                 bss->wpa_ie_len = 0;
1670         }
1671
1672         if (elems.rsn &&
1673             (bss->rsn_ie == NULL || bss->rsn_ie_len != elems.rsn_len ||
1674              os_memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
1675                 os_free(bss->rsn_ie);
1676                 bss->rsn_ie = os_malloc(elems.rsn_len + 2);
1677                 if (bss->rsn_ie) {
1678                         os_memcpy(bss->rsn_ie, elems.rsn - 2,
1679                                   elems.rsn_len + 2);
1680                         bss->rsn_ie_len = elems.rsn_len + 2;
1681                 } else
1682                         bss->rsn_ie_len = 0;
1683         } else if (!elems.rsn && bss->rsn_ie) {
1684                 os_free(bss->rsn_ie);
1685                 bss->rsn_ie = NULL;
1686                 bss->rsn_ie_len = 0;
1687         }
1688
1689         if (elems.wmm_param &&
1690             (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wmm_param_len ||
1691              os_memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
1692                 os_free(bss->wmm_ie);
1693                 bss->wmm_ie = os_malloc(elems.wmm_param_len + 2);
1694                 if (bss->wmm_ie) {
1695                         os_memcpy(bss->wmm_ie, elems.wmm_param - 2,
1696                                   elems.wmm_param_len + 2);
1697                         bss->wmm_ie_len = elems.wmm_param_len + 2;
1698                 } else
1699                         bss->wmm_ie_len = 0;
1700         } else if (!elems.wmm_param && bss->wmm_ie) {
1701                 os_free(bss->wmm_ie);
1702                 bss->wmm_ie = NULL;
1703                 bss->wmm_ie_len = 0;
1704         }
1705
1706
1707         bss->hw_mode = wpa_s->mlme.phymode;
1708         bss->channel = channel;
1709         bss->freq = wpa_s->mlme.freq;
1710         if (channel != wpa_s->mlme.channel &&
1711             (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G ||
1712              wpa_s->mlme.phymode == WPA_MODE_IEEE80211B) &&
1713             channel >= 1 && channel <= 14) {
1714                 static const int freq_list[] = {
1715                         2412, 2417, 2422, 2427, 2432, 2437, 2442,
1716                         2447, 2452, 2457, 2462, 2467, 2472, 2484
1717                 };
1718                 /* IEEE 802.11g/b mode can receive packets from neighboring
1719                  * channels, so map the channel into frequency. */
1720                 bss->freq = freq_list[channel - 1];
1721         }
1722         bss->timestamp = timestamp;
1723         os_get_time(&bss->last_update);
1724         bss->rssi = rx_status->ssi;
1725         if (!beacon)
1726                 bss->probe_resp++;
1727 }
1728
1729
1730 static void ieee80211_rx_mgmt_probe_resp(struct wpa_supplicant *wpa_s,
1731                                          struct ieee80211_mgmt *mgmt,
1732                                          size_t len,
1733                                          struct ieee80211_rx_status *rx_status)
1734 {
1735         ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 0);
1736 }
1737
1738
1739 static void ieee80211_rx_mgmt_beacon(struct wpa_supplicant *wpa_s,
1740                                      struct ieee80211_mgmt *mgmt,
1741                                      size_t len,
1742                                      struct ieee80211_rx_status *rx_status)
1743 {
1744         int use_protection;
1745         size_t baselen;
1746         struct ieee802_11_elems elems;
1747
1748         ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 1);
1749
1750         if (!wpa_s->mlme.associated ||
1751             os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0)
1752                 return;
1753
1754         /* Process beacon from the current BSS */
1755         baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
1756         if (baselen > len)
1757                 return;
1758
1759         if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
1760                                    &elems) == ParseFailed)
1761                 return;
1762
1763         use_protection = 0;
1764         if (elems.erp_info && elems.erp_info_len >= 1) {
1765                 use_protection =
1766                         (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
1767         }
1768
1769         if (use_protection != !!wpa_s->mlme.use_protection) {
1770                 wpa_printf(MSG_DEBUG, "MLME: CTS protection %s (BSSID=" MACSTR
1771                            ")",
1772                            use_protection ? "enabled" : "disabled",
1773                            MAC2STR(wpa_s->bssid));
1774                 wpa_s->mlme.use_protection = use_protection ? 1 : 0;
1775                 wpa_s->mlme.cts_protect_erp_frames = use_protection;
1776         }
1777
1778         if (elems.wmm_param && wpa_s->mlme.wmm_enabled) {
1779                 ieee80211_sta_wmm_params(wpa_s, elems.wmm_param,
1780                                          elems.wmm_param_len);
1781         }
1782 }
1783
1784
1785 static void ieee80211_rx_mgmt_probe_req(struct wpa_supplicant *wpa_s,
1786                                         struct ieee80211_mgmt *mgmt,
1787                                         size_t len,
1788                                         struct ieee80211_rx_status *rx_status)
1789 {
1790         int tx_last_beacon, adhoc;
1791 #if 0 /* FIX */
1792         struct ieee80211_mgmt *resp;
1793 #endif
1794         u8 *pos, *end;
1795         struct wpa_ssid *ssid = wpa_s->current_ssid;
1796
1797         adhoc = ssid && ssid->mode == 1;
1798
1799         if (!adhoc || wpa_s->mlme.state != IEEE80211_IBSS_JOINED ||
1800             len < 24 + 2 || wpa_s->mlme.probe_resp == NULL)
1801                 return;
1802
1803 #if 0 /* FIX */
1804         if (local->hw->tx_last_beacon)
1805                 tx_last_beacon = local->hw->tx_last_beacon(local->mdev);
1806         else
1807 #endif
1808                 tx_last_beacon = 1;
1809
1810 #ifdef IEEE80211_IBSS_DEBUG
1811         wpa_printf(MSG_DEBUG, "MLME: RX ProbeReq SA=" MACSTR " DA=" MACSTR
1812                    " BSSID=" MACSTR " (tx_last_beacon=%d)",
1813                    MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
1814                    MAC2STR(mgmt->bssid), tx_last_beacon);
1815 #endif /* IEEE80211_IBSS_DEBUG */
1816
1817         if (!tx_last_beacon)
1818                 return;
1819
1820         if (os_memcmp(mgmt->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
1821             os_memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
1822                 return;
1823
1824         end = ((u8 *) mgmt) + len;
1825         pos = mgmt->u.probe_req.variable;
1826         if (pos[0] != WLAN_EID_SSID ||
1827             pos + 2 + pos[1] > end) {
1828                 wpa_printf(MSG_DEBUG, "MLME: Invalid SSID IE in ProbeReq from "
1829                            MACSTR, MAC2STR(mgmt->sa));
1830                 return;
1831         }
1832         if (pos[1] != 0 &&
1833             (pos[1] != wpa_s->mlme.ssid_len ||
1834              os_memcmp(pos + 2, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) != 0))
1835         {
1836                 /* Ignore ProbeReq for foreign SSID */
1837                 return;
1838         }
1839
1840 #if 0 /* FIX */
1841         /* Reply with ProbeResp */
1842         skb = skb_copy(wpa_s->mlme.probe_resp, GFP_ATOMIC);
1843         if (skb == NULL)
1844                 return;
1845
1846         resp = (struct ieee80211_mgmt *) skb->data;
1847         os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
1848 #ifdef IEEE80211_IBSS_DEBUG
1849         wpa_printf(MSG_DEBUG, "MLME: Sending ProbeResp to " MACSTR,
1850                    MAC2STR(resp->da));
1851 #endif /* IEEE80211_IBSS_DEBUG */
1852         ieee80211_sta_tx(wpa_s, skb, 0, 1);
1853 #endif
1854 }
1855
1856
1857 static void ieee80211_sta_rx_mgmt(struct wpa_supplicant *wpa_s,
1858                                   const u8 *buf, size_t len,
1859                                   struct ieee80211_rx_status *rx_status)
1860 {
1861         struct ieee80211_mgmt *mgmt;
1862         u16 fc;
1863
1864         if (len < 24)
1865                 return;
1866
1867         mgmt = (struct ieee80211_mgmt *) buf;
1868         fc = le_to_host16(mgmt->frame_control);
1869
1870         switch (WLAN_FC_GET_STYPE(fc)) {
1871         case WLAN_FC_STYPE_PROBE_REQ:
1872                 ieee80211_rx_mgmt_probe_req(wpa_s, mgmt, len, rx_status);
1873                 break;
1874         case WLAN_FC_STYPE_PROBE_RESP:
1875                 ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt, len, rx_status);
1876                 break;
1877         case WLAN_FC_STYPE_BEACON:
1878                 ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status);
1879                 break;
1880         case WLAN_FC_STYPE_AUTH:
1881                 ieee80211_rx_mgmt_auth(wpa_s, mgmt, len, rx_status);
1882                 break;
1883         case WLAN_FC_STYPE_ASSOC_RESP:
1884                 ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 0);
1885                 break;
1886         case WLAN_FC_STYPE_REASSOC_RESP:
1887                 ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 1);
1888                 break;
1889         case WLAN_FC_STYPE_DEAUTH:
1890                 ieee80211_rx_mgmt_deauth(wpa_s, mgmt, len, rx_status);
1891                 break;
1892         case WLAN_FC_STYPE_DISASSOC:
1893                 ieee80211_rx_mgmt_disassoc(wpa_s, mgmt, len, rx_status);
1894                 break;
1895         default:
1896                 wpa_printf(MSG_DEBUG, "MLME: received unknown management "
1897                            "frame - stype=%d", WLAN_FC_GET_STYPE(fc));
1898                 break;
1899         }
1900 }
1901
1902
1903 static void ieee80211_sta_rx_scan(struct wpa_supplicant *wpa_s,
1904                                   const u8 *buf, size_t len,
1905                                   struct ieee80211_rx_status *rx_status)
1906 {
1907         struct ieee80211_mgmt *mgmt;
1908         u16 fc;
1909
1910         if (len < 24)
1911                 return;
1912
1913         mgmt = (struct ieee80211_mgmt *) buf;
1914         fc = le_to_host16(mgmt->frame_control);
1915
1916         if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) {
1917                 if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
1918                         ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt,
1919                                                      len, rx_status);
1920                 } else if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) {
1921                         ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status);
1922                 }
1923         }
1924 }
1925
1926
1927 static int ieee80211_sta_active_ibss(struct wpa_supplicant *wpa_s)
1928 {
1929         int active = 0;
1930
1931 #if 0 /* FIX */
1932         list_for_each(ptr, &local->sta_list) {
1933                 sta = list_entry(ptr, struct sta_info, list);
1934                 if (sta->dev == dev &&
1935                     time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
1936                                jiffies)) {
1937                         active++;
1938                         break;
1939                 }
1940         }
1941 #endif
1942
1943         return active;
1944 }
1945
1946
1947 static void ieee80211_sta_expire(struct wpa_supplicant *wpa_s)
1948 {
1949 #if 0 /* FIX */
1950         list_for_each_safe(ptr, n, &local->sta_list) {
1951                 sta = list_entry(ptr, struct sta_info, list);
1952                 if (time_after(jiffies, sta->last_rx +
1953                                IEEE80211_IBSS_INACTIVITY_LIMIT)) {
1954                         wpa_printf(MSG_DEBUG, "MLME: expiring inactive STA "
1955                                    MACSTR, MAC2STR(sta->addr));
1956                         sta_info_free(local, sta, 1);
1957                 }
1958         }
1959 #endif
1960 }
1961
1962
1963 static void ieee80211_sta_merge_ibss(struct wpa_supplicant *wpa_s)
1964 {
1965         ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL);
1966
1967         ieee80211_sta_expire(wpa_s);
1968         if (ieee80211_sta_active_ibss(wpa_s))
1969                 return;
1970
1971         wpa_printf(MSG_DEBUG, "MLME: No active IBSS STAs - trying to scan for "
1972                    "other IBSS networks with same SSID (merge)");
1973         ieee80211_sta_req_scan(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
1974 }
1975
1976
1977 static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx)
1978 {
1979         struct wpa_supplicant *wpa_s = eloop_ctx;
1980
1981         switch (wpa_s->mlme.state) {
1982         case IEEE80211_DISABLED:
1983                 break;
1984         case IEEE80211_AUTHENTICATE:
1985                 ieee80211_authenticate(wpa_s);
1986                 break;
1987         case IEEE80211_ASSOCIATE:
1988                 ieee80211_associate(wpa_s);
1989                 break;
1990         case IEEE80211_ASSOCIATED:
1991                 ieee80211_associated(wpa_s);
1992                 break;
1993         case IEEE80211_IBSS_SEARCH:
1994                 ieee80211_sta_find_ibss(wpa_s);
1995                 break;
1996         case IEEE80211_IBSS_JOINED:
1997                 ieee80211_sta_merge_ibss(wpa_s);
1998                 break;
1999         default:
2000                 wpa_printf(MSG_DEBUG, "ieee80211_sta_timer: Unknown state %d",
2001                            wpa_s->mlme.state);
2002                 break;
2003         }
2004
2005         if (ieee80211_privacy_mismatch(wpa_s)) {
2006                 wpa_printf(MSG_DEBUG, "MLME: privacy configuration mismatch "
2007                            "and mixed-cell disabled - disassociate");
2008
2009                 ieee80211_send_disassoc(wpa_s, WLAN_REASON_UNSPECIFIED);
2010                 ieee80211_set_associated(wpa_s, 0);
2011         }
2012 }
2013
2014
2015 static void ieee80211_sta_new_auth(struct wpa_supplicant *wpa_s)
2016 {
2017         struct wpa_ssid *ssid = wpa_s->current_ssid;
2018         if (ssid && ssid->mode != 0)
2019                 return;
2020
2021 #if 0 /* FIX */
2022         if (local->hw->reset_tsf) {
2023                 /* Reset own TSF to allow time synchronization work. */
2024                 local->hw->reset_tsf(local->mdev);
2025         }
2026 #endif
2027
2028         wpa_s->mlme.wmm_last_param_set = -1; /* allow any WMM update */
2029
2030
2031         if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN)
2032                 wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN;
2033         else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
2034                 wpa_s->mlme.auth_alg = WLAN_AUTH_SHARED_KEY;
2035         else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP)
2036                 wpa_s->mlme.auth_alg = WLAN_AUTH_LEAP;
2037         else
2038                 wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN;
2039         wpa_printf(MSG_DEBUG, "MLME: Initial auth_alg=%d",
2040                    wpa_s->mlme.auth_alg);
2041         wpa_s->mlme.auth_transaction = -1;
2042         wpa_s->mlme.auth_tries = wpa_s->mlme.assoc_tries = 0;
2043         ieee80211_authenticate(wpa_s);
2044 }
2045
2046
2047 static int ieee80211_ibss_allowed(struct wpa_supplicant *wpa_s)
2048 {
2049 #if 0 /* FIX */
2050         int m, c;
2051
2052         for (m = 0; m < local->hw->num_modes; m++) {
2053                 struct ieee80211_hw_modes *mode = &local->hw->modes[m];
2054                 if (mode->mode != local->conf.phymode)
2055                         continue;
2056                 for (c = 0; c < mode->num_channels; c++) {
2057                         struct ieee80211_channel *chan = &mode->channels[c];
2058                         if (chan->flag & IEEE80211_CHAN_W_SCAN &&
2059                             chan->chan == local->conf.channel) {
2060                                 if (chan->flag & IEEE80211_CHAN_W_IBSS)
2061                                         return 1;
2062                                 break;
2063                         }
2064                 }
2065         }
2066 #endif
2067
2068         return 0;
2069 }
2070
2071
2072 static int ieee80211_sta_join_ibss(struct wpa_supplicant *wpa_s,
2073                                    struct ieee80211_sta_bss *bss)
2074 {
2075         int res = 0, rates, done = 0;
2076         struct ieee80211_mgmt *mgmt;
2077 #if 0 /* FIX */
2078         struct ieee80211_tx_control control;
2079         struct ieee80211_rate *rate;
2080         struct rate_control_extra extra;
2081 #endif
2082         u8 *pos, *buf;
2083         size_t len;
2084
2085         /* Remove possible STA entries from other IBSS networks. */
2086 #if 0 /* FIX */
2087         sta_info_flush(local, NULL);
2088
2089         if (local->hw->reset_tsf) {
2090                 /* Reset own TSF to allow time synchronization work. */
2091                 local->hw->reset_tsf(local->mdev);
2092         }
2093 #endif
2094         os_memcpy(wpa_s->bssid, bss->bssid, ETH_ALEN);
2095
2096 #if 0 /* FIX */
2097         local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
2098
2099         sdata->drop_unencrypted = bss->capability &
2100                 host_to_le16(WLAN_CAPABILITY_PRIVACY) ? 1 : 0;
2101 #endif
2102
2103 #if 0 /* FIX */
2104         os_memset(&rq, 0, sizeof(rq));
2105         rq.m = bss->freq * 100000;
2106         rq.e = 1;
2107         res = ieee80211_ioctl_siwfreq(wpa_s, NULL, &rq, NULL);
2108 #endif
2109
2110         if (!ieee80211_ibss_allowed(wpa_s)) {
2111 #if 0 /* FIX */
2112                 wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed on channel %d "
2113                            "(%d MHz)", local->conf.channel,
2114                            local->conf.freq);
2115 #endif
2116                 return -1;
2117         }
2118
2119         /* Set beacon template based on scan results */
2120         buf = os_malloc(400);
2121         len = 0;
2122         do {
2123                 if (buf == NULL)
2124                         break;
2125
2126                 mgmt = (struct ieee80211_mgmt *) buf;
2127                 len += 24 + sizeof(mgmt->u.beacon);
2128                 os_memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
2129                 mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
2130                                                    WLAN_FC_STYPE_BEACON);
2131                 os_memset(mgmt->da, 0xff, ETH_ALEN);
2132                 os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN);
2133                 os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN);
2134 #if 0 /* FIX */
2135                 mgmt->u.beacon.beacon_int =
2136                         host_to_le16(local->conf.beacon_int);
2137 #endif
2138                 mgmt->u.beacon.capab_info = host_to_le16(bss->capability);
2139
2140                 pos = buf + len;
2141                 len += 2 + wpa_s->mlme.ssid_len;
2142                 *pos++ = WLAN_EID_SSID;
2143                 *pos++ = wpa_s->mlme.ssid_len;
2144                 os_memcpy(pos, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
2145
2146                 rates = bss->supp_rates_len;
2147                 if (rates > 8)
2148                         rates = 8;
2149                 pos = buf + len;
2150                 len += 2 + rates;
2151                 *pos++ = WLAN_EID_SUPP_RATES;
2152                 *pos++ = rates;
2153                 os_memcpy(pos, bss->supp_rates, rates);
2154
2155                 pos = buf + len;
2156                 len += 2 + 1;
2157                 *pos++ = WLAN_EID_DS_PARAMS;
2158                 *pos++ = 1;
2159                 *pos++ = bss->channel;
2160
2161                 pos = buf + len;
2162                 len += 2 + 2;
2163                 *pos++ = WLAN_EID_IBSS_PARAMS;
2164                 *pos++ = 2;
2165                 /* FIX: set ATIM window based on scan results */
2166                 *pos++ = 0;
2167                 *pos++ = 0;
2168
2169                 if (bss->supp_rates_len > 8) {
2170                         rates = bss->supp_rates_len - 8;
2171                         pos = buf + len;
2172                         len += 2 + rates;
2173                         *pos++ = WLAN_EID_EXT_SUPP_RATES;
2174                         *pos++ = rates;
2175                         os_memcpy(pos, &bss->supp_rates[8], rates);
2176                 }
2177
2178 #if 0 /* FIX */
2179                 os_memset(&control, 0, sizeof(control));
2180                 control.pkt_type = PKT_PROBE_RESP;
2181                 os_memset(&extra, 0, sizeof(extra));
2182                 extra.endidx = local->num_curr_rates;
2183                 rate = rate_control_get_rate(wpa_s, skb, &extra);
2184                 if (rate == NULL) {
2185                         wpa_printf(MSG_DEBUG, "MLME: Failed to determine TX "
2186                                    "rate for IBSS beacon");
2187                         break;
2188                 }
2189                 control.tx_rate = (wpa_s->mlme.short_preamble &&
2190                                    (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
2191                         rate->val2 : rate->val;
2192                 control.antenna_sel = local->conf.antenna_sel;
2193                 control.power_level = local->conf.power_level;
2194                 control.no_ack = 1;
2195                 control.retry_limit = 1;
2196                 control.rts_cts_duration = 0;
2197 #endif
2198
2199 #if 0 /* FIX */
2200                 wpa_s->mlme.probe_resp = skb_copy(skb, GFP_ATOMIC);
2201                 if (wpa_s->mlme.probe_resp) {
2202                         mgmt = (struct ieee80211_mgmt *)
2203                                 wpa_s->mlme.probe_resp->data;
2204                         mgmt->frame_control =
2205                                 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
2206                                              WLAN_FC_STYPE_PROBE_RESP);
2207                 } else {
2208                         wpa_printf(MSG_DEBUG, "MLME: Could not allocate "
2209                                    "ProbeResp template for IBSS");
2210                 }
2211
2212                 if (local->hw->beacon_update &&
2213                     local->hw->beacon_update(wpa_s, skb, &control) == 0) {
2214                         wpa_printf(MSG_DEBUG, "MLME: Configured IBSS beacon "
2215                                    "template based on scan results");
2216                         skb = NULL;
2217                 }
2218
2219                 rates = 0;
2220                 for (i = 0; i < bss->supp_rates_len; i++) {
2221                         int rate = (bss->supp_rates[i] & 0x7f) * 5;
2222                         if (local->conf.phymode == MODE_ATHEROS_TURBO)
2223                                 rate *= 2;
2224                         for (j = 0; j < local->num_curr_rates; j++)
2225                                 if (local->curr_rates[j].rate == rate)
2226                                         rates |= BIT(j);
2227                 }
2228                 wpa_s->mlme.supp_rates_bits = rates;
2229 #endif
2230                 done = 1;
2231         } while (0);
2232
2233         os_free(buf);
2234         if (!done) {
2235                 wpa_printf(MSG_DEBUG, "MLME: Failed to configure IBSS beacon "
2236                            "template");
2237         }
2238
2239         wpa_s->mlme.state = IEEE80211_IBSS_JOINED;
2240         ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL);
2241
2242         return res;
2243 }
2244
2245
2246 #if 0 /* FIX */
2247 static int ieee80211_sta_create_ibss(struct wpa_supplicant *wpa_s)
2248 {
2249         struct ieee80211_sta_bss *bss;
2250         u8 bssid[ETH_ALEN], *pos;
2251         int i;
2252
2253 #if 0
2254         /* Easier testing, use fixed BSSID. */
2255         os_memset(bssid, 0xfe, ETH_ALEN);
2256 #else
2257         /* Generate random, not broadcast, locally administered BSSID. Mix in
2258          * own MAC address to make sure that devices that do not have proper
2259          * random number generator get different BSSID. */
2260         os_get_random(bssid, ETH_ALEN);
2261         for (i = 0; i < ETH_ALEN; i++)
2262                 bssid[i] ^= wpa_s->own_addr[i];
2263         bssid[0] &= ~0x01;
2264         bssid[0] |= 0x02;
2265 #endif
2266
2267         wpa_printf(MSG_DEBUG, "MLME: Creating new IBSS network, BSSID "
2268                    MACSTR "", MAC2STR(bssid));
2269
2270         bss = ieee80211_bss_add(wpa_s, bssid);
2271         if (bss == NULL)
2272                 return -ENOMEM;
2273
2274 #if 0 /* FIX */
2275         if (local->conf.beacon_int == 0)
2276                 local->conf.beacon_int = 100;
2277         bss->beacon_int = local->conf.beacon_int;
2278         bss->hw_mode = local->conf.phymode;
2279         bss->channel = local->conf.channel;
2280         bss->freq = local->conf.freq;
2281 #endif
2282         os_get_time(&bss->last_update);
2283         bss->capability = host_to_le16(WLAN_CAPABILITY_IBSS);
2284 #if 0 /* FIX */
2285         if (sdata->default_key) {
2286                 bss->capability |= host_to_le16(WLAN_CAPABILITY_PRIVACY);
2287         } else
2288                 sdata->drop_unencrypted = 0;
2289         bss->supp_rates_len = local->num_curr_rates;
2290 #endif
2291         pos = bss->supp_rates;
2292 #if 0 /* FIX */
2293         for (i = 0; i < local->num_curr_rates; i++) {
2294                 int rate = local->curr_rates[i].rate;
2295                 if (local->conf.phymode == MODE_ATHEROS_TURBO)
2296                         rate /= 2;
2297                 *pos++ = (u8) (rate / 5);
2298         }
2299 #endif
2300
2301         return ieee80211_sta_join_ibss(wpa_s, bss);
2302 }
2303 #endif
2304
2305
2306 static int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s)
2307 {
2308         struct ieee80211_sta_bss *bss;
2309         int found = 0;
2310         u8 bssid[ETH_ALEN];
2311         int active_ibss;
2312         struct os_time now;
2313
2314         if (wpa_s->mlme.ssid_len == 0)
2315                 return -EINVAL;
2316
2317         active_ibss = ieee80211_sta_active_ibss(wpa_s);
2318 #ifdef IEEE80211_IBSS_DEBUG
2319         wpa_printf(MSG_DEBUG, "MLME: sta_find_ibss (active_ibss=%d)",
2320                    active_ibss);
2321 #endif /* IEEE80211_IBSS_DEBUG */
2322         for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) {
2323                 if (wpa_s->mlme.ssid_len != bss->ssid_len ||
2324                     os_memcmp(wpa_s->mlme.ssid, bss->ssid, bss->ssid_len) != 0
2325                     || !(bss->capability & WLAN_CAPABILITY_IBSS))
2326                         continue;
2327 #ifdef IEEE80211_IBSS_DEBUG
2328                 wpa_printf(MSG_DEBUG, "   bssid=" MACSTR " found",
2329                            MAC2STR(bss->bssid));
2330 #endif /* IEEE80211_IBSS_DEBUG */
2331                 os_memcpy(bssid, bss->bssid, ETH_ALEN);
2332                 found = 1;
2333                 if (active_ibss ||
2334                     os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0)
2335                         break;
2336         }
2337
2338 #ifdef IEEE80211_IBSS_DEBUG
2339         wpa_printf(MSG_DEBUG, "   sta_find_ibss: selected " MACSTR " current "
2340                    MACSTR, MAC2STR(bssid), MAC2STR(wpa_s->bssid));
2341 #endif /* IEEE80211_IBSS_DEBUG */
2342         if (found && os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) != 0 &&
2343             (bss = ieee80211_bss_get(wpa_s, bssid))) {
2344                 wpa_printf(MSG_DEBUG, "MLME: Selected IBSS BSSID " MACSTR
2345                            " based on configured SSID",
2346                            MAC2STR(bssid));
2347                 return ieee80211_sta_join_ibss(wpa_s, bss);
2348         }
2349 #ifdef IEEE80211_IBSS_DEBUG
2350         wpa_printf(MSG_DEBUG, "   did not try to join ibss");
2351 #endif /* IEEE80211_IBSS_DEBUG */
2352
2353         /* Selected IBSS not found in current scan results - try to scan */
2354         os_get_time(&now);
2355 #if 0 /* FIX */
2356         if (wpa_s->mlme.state == IEEE80211_IBSS_JOINED &&
2357             !ieee80211_sta_active_ibss(wpa_s)) {
2358                 ieee80211_reschedule_timer(wpa_s,
2359                                            IEEE80211_IBSS_MERGE_INTERVAL);
2360         } else if (time_after(jiffies, wpa_s->mlme.last_scan_completed +
2361                               IEEE80211_SCAN_INTERVAL)) {
2362                 wpa_printf(MSG_DEBUG, "MLME: Trigger new scan to find an IBSS "
2363                            "to join");
2364                 return ieee80211_sta_req_scan(wpa_s->mlme.ssid,
2365                                               wpa_s->mlme.ssid_len);
2366         } else if (wpa_s->mlme.state != IEEE80211_IBSS_JOINED) {
2367                 int interval = IEEE80211_SCAN_INTERVAL;
2368
2369                 if (time_after(jiffies, wpa_s->mlme.ibss_join_req +
2370                                IEEE80211_IBSS_JOIN_TIMEOUT)) {
2371                         if (wpa_s->mlme.create_ibss &&
2372                             ieee80211_ibss_allowed(wpa_s))
2373                                 return ieee80211_sta_create_ibss(wpa_s);
2374                         if (wpa_s->mlme.create_ibss) {
2375                                 wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed "
2376                                            "on the configured channel %d "
2377                                            "(%d MHz)",
2378                                            local->conf.channel,
2379                                            local->conf.freq);
2380                         }
2381
2382                         /* No IBSS found - decrease scan interval and continue
2383                          * scanning. */
2384                         interval = IEEE80211_SCAN_INTERVAL_SLOW;
2385                 }
2386
2387                 wpa_s->mlme.state = IEEE80211_IBSS_SEARCH;
2388                 ieee80211_reschedule_timer(wpa_s, interval);
2389                 return 0;
2390         }
2391 #endif
2392
2393         return 0;
2394 }
2395
2396
2397 int ieee80211_sta_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid,
2398                            size_t *len)
2399 {
2400         os_memcpy(ssid, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len);
2401         *len = wpa_s->mlme.ssid_len;
2402         return 0;
2403 }
2404
2405
2406 int ieee80211_sta_associate(struct wpa_supplicant *wpa_s,
2407                             struct wpa_driver_associate_params *params)
2408 {
2409         struct ieee80211_sta_bss *bss;
2410
2411         wpa_s->mlme.bssid_set = 0;
2412         wpa_s->mlme.freq = params->freq;
2413         if (params->bssid) {
2414                 os_memcpy(wpa_s->bssid, params->bssid, ETH_ALEN);
2415                 if (os_memcmp(params->bssid, "\x00\x00\x00\x00\x00\x00",
2416                               ETH_ALEN))
2417                         wpa_s->mlme.bssid_set = 1;
2418                 bss = ieee80211_bss_get(wpa_s, wpa_s->bssid);
2419                 if (bss) {
2420                         wpa_s->mlme.phymode = bss->hw_mode;
2421                         wpa_s->mlme.channel = bss->channel;
2422                         wpa_s->mlme.freq = bss->freq;
2423                 }
2424         }
2425
2426 #if 0 /* FIX */
2427         /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is
2428          * not defined. */
2429         if (local->hw->conf_tx) {
2430                 struct ieee80211_tx_queue_params qparam;
2431                 int i;
2432
2433                 os_memset(&qparam, 0, sizeof(qparam));
2434                 /* TODO: are these ok defaults for all hw_modes? */
2435                 qparam.aifs = 2;
2436                 qparam.cw_min =
2437                         local->conf.phymode == MODE_IEEE80211B ? 31 : 15;
2438                 qparam.cw_max = 1023;
2439                 qparam.burst_time = 0;
2440                 for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
2441                 {
2442                         local->hw->conf_tx(wpa_s, i + IEEE80211_TX_QUEUE_DATA0,
2443                                            &qparam);
2444                 }
2445                 /* IBSS uses different parameters for Beacon sending */
2446                 qparam.cw_min++;
2447                 qparam.cw_min *= 2;
2448                 qparam.cw_min--;
2449                 local->hw->conf_tx(wpa_s, IEEE80211_TX_QUEUE_BEACON, &qparam);
2450         }
2451 #endif
2452
2453         if (wpa_s->mlme.ssid_len != params->ssid_len ||
2454             os_memcmp(wpa_s->mlme.ssid, params->ssid, params->ssid_len) != 0)
2455                 wpa_s->mlme.prev_bssid_set = 0;
2456         os_memcpy(wpa_s->mlme.ssid, params->ssid, params->ssid_len);
2457         os_memset(wpa_s->mlme.ssid + params->ssid_len, 0,
2458                   MAX_SSID_LEN - params->ssid_len);
2459         wpa_s->mlme.ssid_len = params->ssid_len;
2460         wpa_s->mlme.ssid_set = 1;
2461
2462         os_free(wpa_s->mlme.extra_ie);
2463         if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
2464                 wpa_s->mlme.extra_ie = NULL;
2465                 wpa_s->mlme.extra_ie_len = 0;
2466                 return 0;
2467         }
2468         wpa_s->mlme.extra_ie = os_malloc(params->wpa_ie_len);
2469         if (wpa_s->mlme.extra_ie == NULL) {
2470                 wpa_s->mlme.extra_ie_len = 0;
2471                 return -1;
2472         }
2473         os_memcpy(wpa_s->mlme.extra_ie, params->wpa_ie, params->wpa_ie_len);
2474         wpa_s->mlme.extra_ie_len = params->wpa_ie_len;
2475
2476         wpa_s->mlme.key_mgmt = params->key_mgmt_suite;
2477
2478         ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode,
2479                                   wpa_s->mlme.channel, wpa_s->mlme.freq);
2480
2481         if (params->mode == 1 && !wpa_s->mlme.bssid_set) {
2482                 os_get_time(&wpa_s->mlme.ibss_join_req);
2483                 wpa_s->mlme.state = IEEE80211_IBSS_SEARCH;
2484                 return ieee80211_sta_find_ibss(wpa_s);
2485         }
2486
2487         if (wpa_s->mlme.bssid_set)
2488                 ieee80211_sta_new_auth(wpa_s);
2489
2490         return 0;
2491 }
2492
2493
2494 static void ieee80211_sta_save_oper_chan(struct wpa_supplicant *wpa_s)
2495 {
2496         wpa_s->mlme.scan_oper_channel = wpa_s->mlme.channel;
2497         wpa_s->mlme.scan_oper_freq = wpa_s->mlme.freq;
2498         wpa_s->mlme.scan_oper_phymode = wpa_s->mlme.phymode;
2499 }
2500
2501
2502 static int ieee80211_sta_restore_oper_chan(struct wpa_supplicant *wpa_s)
2503 {
2504         wpa_s->mlme.channel = wpa_s->mlme.scan_oper_channel;
2505         wpa_s->mlme.freq = wpa_s->mlme.scan_oper_freq;
2506         wpa_s->mlme.phymode = wpa_s->mlme.scan_oper_phymode;
2507         if (wpa_s->mlme.freq == 0)
2508                 return 0;
2509         return ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode,
2510                                          wpa_s->mlme.channel,
2511                                          wpa_s->mlme.freq);
2512 }
2513
2514
2515 static int ieee80211_active_scan(struct wpa_supplicant *wpa_s)
2516 {
2517         size_t m;
2518         int c;
2519
2520         for (m = 0; m < wpa_s->mlme.num_modes; m++) {
2521                 struct wpa_hw_modes *mode = &wpa_s->mlme.modes[m];
2522                 if ((int) mode->mode != (int) wpa_s->mlme.phymode)
2523                         continue;
2524                 for (c = 0; c < mode->num_channels; c++) {
2525                         struct wpa_channel_data *chan = &mode->channels[c];
2526                         if (chan->flag & WPA_CHAN_W_SCAN &&
2527                             chan->chan == wpa_s->mlme.channel) {
2528                                 if (chan->flag & WPA_CHAN_W_ACTIVE_SCAN)
2529                                         return 1;
2530                                 break;
2531                         }
2532                 }
2533         }
2534
2535         return 0;
2536 }
2537
2538
2539 static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx)
2540 {
2541         struct wpa_supplicant *wpa_s = eloop_ctx;
2542         struct wpa_hw_modes *mode;
2543         struct wpa_channel_data *chan;
2544         int skip = 0;
2545         int timeout = 0;
2546         struct wpa_ssid *ssid = wpa_s->current_ssid;
2547         int adhoc;
2548
2549         if (!wpa_s->mlme.sta_scanning || wpa_s->mlme.modes == NULL)
2550                 return;
2551
2552         adhoc = ssid && ssid->mode == 1;
2553
2554         switch (wpa_s->mlme.scan_state) {
2555         case SCAN_SET_CHANNEL:
2556                 mode = &wpa_s->mlme.modes[wpa_s->mlme.scan_hw_mode_idx];
2557                 if (wpa_s->mlme.scan_hw_mode_idx >=
2558                     (int) wpa_s->mlme.num_modes ||
2559                     (wpa_s->mlme.scan_hw_mode_idx + 1 ==
2560                      (int) wpa_s->mlme.num_modes
2561                      && wpa_s->mlme.scan_channel_idx >= mode->num_channels)) {
2562                         if (ieee80211_sta_restore_oper_chan(wpa_s)) {
2563                                 wpa_printf(MSG_DEBUG, "MLME: failed to "
2564                                            "restore operational channel after "
2565                                            "scan");
2566                         }
2567                         wpa_printf(MSG_DEBUG, "MLME: scan completed");
2568                         wpa_s->mlme.sta_scanning = 0;
2569                         os_get_time(&wpa_s->mlme.last_scan_completed);
2570                         wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
2571                         if (adhoc) {
2572                                 if (!wpa_s->mlme.bssid_set ||
2573                                     (wpa_s->mlme.state ==
2574                                      IEEE80211_IBSS_JOINED &&
2575                                      !ieee80211_sta_active_ibss(wpa_s)))
2576                                         ieee80211_sta_find_ibss(wpa_s);
2577                         }
2578                         return;
2579                 }
2580                 skip = !(wpa_s->mlme.hw_modes & (1 << mode->mode));
2581                 chan = &mode->channels[wpa_s->mlme.scan_channel_idx];
2582                 if (!(chan->flag & WPA_CHAN_W_SCAN) ||
2583                     (adhoc && !(chan->flag & WPA_CHAN_W_IBSS)) ||
2584                     (wpa_s->mlme.hw_modes & (1 << WPA_MODE_IEEE80211G) &&
2585                      mode->mode == WPA_MODE_IEEE80211B &&
2586                      wpa_s->mlme.scan_skip_11b))
2587                         skip = 1;
2588
2589                 if (!skip) {
2590                         wpa_printf(MSG_MSGDUMP,
2591                                    "MLME: scan channel %d (%d MHz)",
2592                                    chan->chan, chan->freq);
2593
2594                         wpa_s->mlme.channel = chan->chan;
2595                         wpa_s->mlme.freq = chan->freq;
2596                         wpa_s->mlme.phymode = mode->mode;
2597                         if (ieee80211_sta_set_channel(wpa_s, mode->mode,
2598                                                       chan->chan, chan->freq))
2599                         {
2600                                 wpa_printf(MSG_DEBUG, "MLME: failed to set "
2601                                            "channel %d (%d MHz) for scan",
2602                                            chan->chan, chan->freq);
2603                                 skip = 1;
2604                         }
2605                 }
2606
2607                 wpa_s->mlme.scan_channel_idx++;
2608                 if (wpa_s->mlme.scan_channel_idx >=
2609                     wpa_s->mlme.modes[wpa_s->mlme.scan_hw_mode_idx].
2610                     num_channels) {
2611                         wpa_s->mlme.scan_hw_mode_idx++;
2612                         wpa_s->mlme.scan_channel_idx = 0;
2613                 }
2614
2615                 if (skip) {
2616                         timeout = 0;
2617                         break;
2618                 }
2619
2620                 timeout = IEEE80211_PROBE_DELAY;
2621                 wpa_s->mlme.scan_state = SCAN_SEND_PROBE;
2622                 break;
2623         case SCAN_SEND_PROBE:
2624                 if (ieee80211_active_scan(wpa_s)) {
2625                         ieee80211_send_probe_req(wpa_s, NULL,
2626                                                  wpa_s->mlme.scan_ssid,
2627                                                  wpa_s->mlme.scan_ssid_len);
2628                         timeout = IEEE80211_CHANNEL_TIME;
2629                 } else {
2630                         timeout = IEEE80211_PASSIVE_CHANNEL_TIME;
2631                 }
2632                 wpa_s->mlme.scan_state = SCAN_SET_CHANNEL;
2633                 break;
2634         }
2635
2636         eloop_register_timeout(timeout / 1000, 1000 * (timeout % 1000),
2637                                ieee80211_sta_scan_timer, wpa_s, NULL);
2638 }
2639
2640
2641 int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s, const u8 *ssid,
2642                            size_t ssid_len)
2643 {
2644         if (ssid_len > MAX_SSID_LEN)
2645                 return -1;
2646
2647         /* MLME-SCAN.request (page 118)  page 144 (11.1.3.1)
2648          * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
2649          * BSSID: MACAddress
2650          * SSID
2651          * ScanType: ACTIVE, PASSIVE
2652          * ProbeDelay: delay (in microseconds) to be used prior to transmitting
2653          *    a Probe frame during active scanning
2654          * ChannelList
2655          * MinChannelTime (>= ProbeDelay), in TU
2656          * MaxChannelTime: (>= MinChannelTime), in TU
2657          */
2658
2659          /* MLME-SCAN.confirm
2660           * BSSDescriptionSet
2661           * ResultCode: SUCCESS, INVALID_PARAMETERS
2662          */
2663
2664         /* TODO: if assoc, move to power save mode for the duration of the
2665          * scan */
2666
2667         if (wpa_s->mlme.sta_scanning)
2668                 return -1;
2669
2670         wpa_printf(MSG_DEBUG, "MLME: starting scan");
2671
2672         ieee80211_sta_save_oper_chan(wpa_s);
2673
2674         wpa_s->mlme.sta_scanning = 1;
2675         /* TODO: stop TX queue? */
2676
2677         if (ssid) {
2678                 wpa_s->mlme.scan_ssid_len = ssid_len;
2679                 os_memcpy(wpa_s->mlme.scan_ssid, ssid, ssid_len);
2680         } else
2681                 wpa_s->mlme.scan_ssid_len = 0;
2682         wpa_s->mlme.scan_skip_11b = 1; /* FIX: clear this is 11g is not
2683                                         * supported */
2684         wpa_s->mlme.scan_state = SCAN_SET_CHANNEL;
2685         wpa_s->mlme.scan_hw_mode_idx = 0;
2686         wpa_s->mlme.scan_channel_idx = 0;
2687         eloop_register_timeout(0, 1, ieee80211_sta_scan_timer, wpa_s, NULL);
2688
2689         return 0;
2690 }
2691
2692
2693 int ieee80211_sta_get_scan_results(struct wpa_supplicant *wpa_s,
2694                                    struct wpa_scan_result *results,
2695                                    size_t max_size)
2696 {
2697         size_t ap_num = 0;
2698         struct wpa_scan_result *r;
2699         struct ieee80211_sta_bss *bss;
2700
2701         os_memset(results, 0, max_size * sizeof(struct wpa_scan_result));
2702         for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) {
2703                 r = &results[ap_num];
2704                 os_memcpy(r->bssid, bss->bssid, ETH_ALEN);
2705                 os_memcpy(r->ssid, bss->ssid, bss->ssid_len);
2706                 r->ssid_len = bss->ssid_len;
2707                 if (bss->wpa_ie && bss->wpa_ie_len < SSID_MAX_WPA_IE_LEN) {
2708                         os_memcpy(r->wpa_ie, bss->wpa_ie, bss->wpa_ie_len);
2709                         r->wpa_ie_len = bss->wpa_ie_len;
2710                 }
2711                 if (bss->rsn_ie && bss->rsn_ie_len < SSID_MAX_WPA_IE_LEN) {
2712                         os_memcpy(r->rsn_ie, bss->rsn_ie, bss->rsn_ie_len);
2713                         r->rsn_ie_len = bss->rsn_ie_len;
2714                 }
2715                 r->freq = bss->freq;
2716                 r->caps = bss->capability;
2717                 r->level = bss->rssi;
2718
2719                 ap_num++;
2720                 if (ap_num >= max_size)
2721                         break;
2722         }
2723
2724         return ap_num;
2725 }
2726
2727
2728 #if 0 /* FIX */
2729 struct sta_info * ieee80211_ibss_add_sta(struct wpa_supplicant *wpa_s,
2730                                          struct sk_buff *skb, u8 *bssid,
2731                                          u8 *addr)
2732 {
2733         struct ieee80211_local *local = dev->priv;
2734         struct list_head *ptr;
2735         struct sta_info *sta;
2736         struct wpa_supplicant *sta_dev = NULL;
2737
2738         /* TODO: Could consider removing the least recently used entry and
2739          * allow new one to be added. */
2740         if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
2741                 if (net_ratelimit()) {
2742                         wpa_printf(MSG_DEBUG, "MLME: No room for a new IBSS "
2743                                    "STA entry " MACSTR, MAC2STR(addr));
2744                 }
2745                 return NULL;
2746         }
2747
2748         spin_lock_bh(&local->sub_if_lock);
2749         list_for_each(ptr, &local->sub_if_list) {
2750                 sdata = list_entry(ptr, struct ieee80211_sub_if_data, list);
2751                 if (sdata->type == IEEE80211_SUB_IF_TYPE_STA &&
2752                     os_memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
2753                         sta_dev = sdata->dev;
2754                         break;
2755                 }
2756         }
2757         spin_unlock_bh(&local->sub_if_lock);
2758
2759         if (sta_dev == NULL)
2760                 return NULL;
2761
2762         wpa_printf(MSG_DEBUG, "MLME: Adding new IBSS station " MACSTR
2763                    " (dev=%s)", MAC2STR(addr), sta_dev->name);
2764
2765         sta = sta_info_add(wpa_s, addr);
2766         if (sta == NULL) {
2767                 return NULL;
2768         }
2769
2770         sta->dev = sta_dev;
2771         sta->supp_rates = wpa_s->mlme.supp_rates_bits;
2772
2773         rate_control_rate_init(local, sta);
2774
2775         return sta; /* caller will call sta_info_release() */
2776 }
2777 #endif
2778
2779
2780 int ieee80211_sta_deauthenticate(struct wpa_supplicant *wpa_s, u16 reason)
2781 {
2782         wpa_printf(MSG_DEBUG, "MLME: deauthenticate(reason=%d)", reason);
2783
2784         ieee80211_send_deauth(wpa_s, reason);
2785         ieee80211_set_associated(wpa_s, 0);
2786         return 0;
2787 }
2788
2789
2790 int ieee80211_sta_disassociate(struct wpa_supplicant *wpa_s, u16 reason)
2791 {
2792         wpa_printf(MSG_DEBUG, "MLME: disassociate(reason=%d)", reason);
2793
2794         if (!wpa_s->mlme.associated)
2795                 return -1;
2796
2797         ieee80211_send_disassoc(wpa_s, reason);
2798         ieee80211_set_associated(wpa_s, 0);
2799         return 0;
2800 }
2801
2802
2803 void ieee80211_sta_rx(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len,
2804                       struct ieee80211_rx_status *rx_status)
2805 {
2806         struct ieee80211_mgmt *mgmt;
2807         u16 fc;
2808         const u8 *pos;
2809
2810         /* wpa_hexdump(MSG_MSGDUMP, "MLME: Received frame", buf, len); */
2811
2812         if (wpa_s->mlme.sta_scanning) {
2813                 ieee80211_sta_rx_scan(wpa_s, buf, len, rx_status);
2814                 return;
2815         }
2816
2817         if (len < 24)
2818                 return;
2819
2820         mgmt = (struct ieee80211_mgmt *) buf;
2821         fc = le_to_host16(mgmt->frame_control);
2822
2823         if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT)
2824                 ieee80211_sta_rx_mgmt(wpa_s, buf, len, rx_status);
2825         else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) {
2826                 if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) !=
2827                     WLAN_FC_FROMDS)
2828                         return;
2829                 /* mgmt->sa is actually BSSID for FromDS data frames */
2830                 if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0)
2831                         return;
2832                 /* Skip IEEE 802.11 and LLC headers */
2833                 pos = buf + 24 + 6;
2834                 if (WPA_GET_BE16(pos) != ETH_P_EAPOL)
2835                         return;
2836                 pos += 2;
2837                 /* mgmt->bssid is actually BSSID for SA data frames */
2838                 wpa_supplicant_rx_eapol(wpa_s, mgmt->bssid,
2839                                         pos, buf + len - pos);
2840         }
2841 }
2842
2843
2844 void ieee80211_sta_free_hw_features(struct wpa_hw_modes *hw_features,
2845                                     size_t num_hw_features)
2846 {
2847         size_t i;
2848
2849         if (hw_features == NULL)
2850                 return;
2851
2852         for (i = 0; i < num_hw_features; i++) {
2853                 os_free(hw_features[i].channels);
2854                 os_free(hw_features[i].rates);
2855         }
2856
2857         os_free(hw_features);
2858 }
2859
2860
2861 int ieee80211_sta_init(struct wpa_supplicant *wpa_s)
2862 {
2863         u16 num_modes, flags;
2864
2865         wpa_s->mlme.modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes,
2866                                                         &flags);
2867         if (wpa_s->mlme.modes == NULL) {
2868                 wpa_printf(MSG_ERROR, "MLME: Failed to read supported "
2869                            "channels and rates from the driver");
2870                 return -1;
2871         }
2872
2873         wpa_s->mlme.num_modes = num_modes;
2874
2875         wpa_s->mlme.hw_modes = 1 << WPA_MODE_IEEE80211A;
2876         wpa_s->mlme.hw_modes |= 1 << WPA_MODE_IEEE80211B;
2877         wpa_s->mlme.hw_modes |= 1 << WPA_MODE_IEEE80211G;
2878
2879         return 0;
2880 }
2881
2882
2883 void ieee80211_sta_deinit(struct wpa_supplicant *wpa_s)
2884 {
2885         eloop_cancel_timeout(ieee80211_sta_timer, wpa_s, NULL);
2886         eloop_cancel_timeout(ieee80211_sta_scan_timer, wpa_s, NULL);
2887         os_free(wpa_s->mlme.extra_ie);
2888         wpa_s->mlme.extra_ie = NULL;
2889         os_free(wpa_s->mlme.assocreq_ies);
2890         wpa_s->mlme.assocreq_ies = NULL;
2891         os_free(wpa_s->mlme.assocresp_ies);
2892         wpa_s->mlme.assocresp_ies = NULL;
2893         ieee80211_bss_list_deinit(wpa_s);
2894         ieee80211_sta_free_hw_features(wpa_s->mlme.modes,
2895                                        wpa_s->mlme.num_modes);
2896 }