Re-initialize hostapd/wpa_supplicant git repository based on 0.6.3 release
[libeap.git] / src / drivers / driver_wext.c
1 /*
2  * WPA Supplicant - driver interaction with generic Linux Wireless Extensions
3  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  *
14  * This file implements a driver interface for the Linux Wireless Extensions.
15  * When used with WE-18 or newer, this interface can be used as-is with number
16  * of drivers. In addition to this, some of the common functions in this file
17  * can be used by other driver interface implementations that use generic WE
18  * ioctls, but require private ioctls for some of the functionality.
19  */
20
21 #include "includes.h"
22 #include <sys/ioctl.h>
23 #include <net/if_arp.h>
24
25 #include "wireless_copy.h"
26 #include "common.h"
27 #include "driver.h"
28 #include "eloop.h"
29 #include "priv_netlink.h"
30 #include "driver_wext.h"
31 #include "ieee802_11_defs.h"
32
33 #ifdef CONFIG_CLIENT_MLME
34 #include <netpacket/packet.h>
35 /* old definitions from net/mac80211 */
36
37 typedef u32 __bitwise __be32;
38 typedef u64 __bitwise __be64;
39
40 #define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
41 #define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1)
42 #define PRISM2_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 3)
43
44 #define PRISM2_PARAM_USER_SPACE_MLME 1045
45 #define PRISM2_PARAM_MGMT_IF            1046
46 #define PRISM2_HOSTAPD_ADD_STA 2
47 #define PRISM2_HOSTAPD_REMOVE_STA 3
48 #define PRISM2_HOSTAPD_GET_HW_FEATURES  1002
49 #define PRISM2_HOSTAPD_MAX_BUF_SIZE     2048
50
51 #ifndef ALIGNED
52 #define ALIGNED __attribute__ ((aligned))
53 #endif
54
55 struct prism2_hostapd_param {
56         u32 cmd;
57         u8 sta_addr[ETH_ALEN];
58         u8 pad[2];
59         union {
60                 struct {
61                         u16 aid;
62                         u16 capability;
63                         u8 supp_rates[32];
64                         u8 wds_flags;
65 #define IEEE80211_STA_DYNAMIC_ENC BIT(0)
66                         u8 enc_flags;
67                         u16 listen_interval;
68                 } add_sta;
69                 struct {
70                         u16 num_modes;
71                         u16 flags;
72                         u8 data[0] ALIGNED; /* num_modes * feature data */
73                 } hw_features;
74                 struct {
75                         u16 mode; /* MODE_* */
76                         u16 num_supported_rates;
77                         u16 num_basic_rates;
78                         u8 data[0] ALIGNED; /* num_supported_rates * u16 +
79                                              * num_basic_rates * u16 */
80                 } set_rate_sets;
81                 struct {
82                         u16 mode; /* MODE_* */
83                         u16 chan;
84                         u32 flag;
85                         u8 power_level; /* regulatory limit in dBm */
86                         u8 antenna_max;
87                 } set_channel_flag;
88                 struct {
89                         u32 rd;
90                 } set_regulatory_domain;
91                 struct {
92                         u32 queue;
93                         s32 aifs;
94                         u32 cw_min;
95                         u32 cw_max;
96                         u32 burst_time; /* maximum burst time in 0.1 ms, i.e.,
97                                          * 10 = 1 ms */
98                 } tx_queue_params;
99         } u;
100 };
101
102 struct hostapd_ioctl_hw_modes_hdr {
103         int mode;
104         int num_channels;
105         int num_rates;
106 };
107
108 /*
109  * frame format for the management interface that is slated
110  * to be replaced by "cooked monitor" with radiotap
111  */
112 #define IEEE80211_FI_VERSION 0x80211001
113 struct ieee80211_frame_info {
114         __be32 version;
115         __be32 length;
116         __be64 mactime;
117         __be64 hosttime;
118         __be32 phytype;
119         __be32 channel;
120         __be32 datarate;
121         __be32 antenna;
122         __be32 priority;
123         __be32 ssi_type;
124         __be32 ssi_signal;
125         __be32 ssi_noise;
126         __be32 preamble;
127         __be32 encoding;
128
129         /* Note: this structure is otherwise identical to capture format used
130          * in linux-wlan-ng, but this additional field is used to provide meta
131          * data about the frame to hostapd. This was the easiest method for
132          * providing this information, but this might change in the future. */
133         __be32 msg_type;
134 } __attribute__ ((packed));
135
136 /* old mode definitions */
137 enum {
138         MODE_IEEE80211A = 0 /* IEEE 802.11a */,
139         MODE_IEEE80211B = 1 /* IEEE 802.11b only */,
140         MODE_ATHEROS_TURBO = 2 /* Atheros Turbo mode (2x.11a at 5 GHz) */,
141         MODE_IEEE80211G = 3 /* IEEE 802.11g (and 802.11b compatibility) */,
142         MODE_ATHEROS_TURBOG = 4 /* Atheros Turbo mode (2x.11g at 2.4 GHz) */,
143         NUM_IEEE80211_MODES = 5
144 };
145
146 #ifndef ETH_P_ALL
147 #define ETH_P_ALL 0x0003
148 #endif
149 #endif /* CONFIG_CLIENT_MLME */
150
151
152 struct wpa_driver_wext_data {
153         void *ctx;
154         int event_sock;
155         int ioctl_sock;
156         int mlme_sock;
157         char ifname[IFNAMSIZ + 1];
158         int ifindex;
159         int ifindex2;
160         u8 *assoc_req_ies;
161         size_t assoc_req_ies_len;
162         u8 *assoc_resp_ies;
163         size_t assoc_resp_ies_len;
164         struct wpa_driver_capa capa;
165         int has_capability;
166         int we_version_compiled;
167
168         /* for set_auth_alg fallback */
169         int use_crypt;
170         int auth_alg_fallback;
171
172         int operstate;
173
174         char mlmedev[IFNAMSIZ + 1];
175
176         int scan_complete_events;
177 };
178
179
180 static int wpa_driver_wext_flush_pmkid(void *priv);
181 static int wpa_driver_wext_get_range(void *priv);
182
183 static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv,
184                                           int linkmode, int operstate)
185 {
186         struct {
187                 struct nlmsghdr hdr;
188                 struct ifinfomsg ifinfo;
189                 char opts[16];
190         } req;
191         struct rtattr *rta;
192         static int nl_seq;
193         ssize_t ret;
194
195         os_memset(&req, 0, sizeof(req));
196
197         req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
198         req.hdr.nlmsg_type = RTM_SETLINK;
199         req.hdr.nlmsg_flags = NLM_F_REQUEST;
200         req.hdr.nlmsg_seq = ++nl_seq;
201         req.hdr.nlmsg_pid = 0;
202
203         req.ifinfo.ifi_family = AF_UNSPEC;
204         req.ifinfo.ifi_type = 0;
205         req.ifinfo.ifi_index = drv->ifindex;
206         req.ifinfo.ifi_flags = 0;
207         req.ifinfo.ifi_change = 0;
208
209         if (linkmode != -1) {
210                 rta = (struct rtattr *)
211                         ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len));
212                 rta->rta_type = IFLA_LINKMODE;
213                 rta->rta_len = RTA_LENGTH(sizeof(char));
214                 *((char *) RTA_DATA(rta)) = linkmode;
215                 req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
216                         RTA_LENGTH(sizeof(char));
217         }
218         if (operstate != -1) {
219                 rta = (struct rtattr *)
220                         ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len));
221                 rta->rta_type = IFLA_OPERSTATE;
222                 rta->rta_len = RTA_LENGTH(sizeof(char));
223                 *((char *) RTA_DATA(rta)) = operstate;
224                 req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +
225                         RTA_LENGTH(sizeof(char));
226         }
227
228         wpa_printf(MSG_DEBUG, "WEXT: Operstate: linkmode=%d, operstate=%d",
229                    linkmode, operstate);
230
231         ret = send(drv->event_sock, &req, req.hdr.nlmsg_len, 0);
232         if (ret < 0) {
233                 wpa_printf(MSG_DEBUG, "WEXT: Sending operstate IFLA failed: "
234                            "%s (assume operstate is not supported)",
235                            strerror(errno));
236         }
237
238         return ret < 0 ? -1 : 0;
239 }
240
241
242 static int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
243                                           int idx, u32 value)
244 {
245         struct iwreq iwr;
246         int ret = 0;
247
248         os_memset(&iwr, 0, sizeof(iwr));
249         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
250         iwr.u.param.flags = idx & IW_AUTH_INDEX;
251         iwr.u.param.value = value;
252
253         if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) {
254                 perror("ioctl[SIOCSIWAUTH]");
255                 fprintf(stderr, "WEXT auth param %d value 0x%x - ",
256                         idx, value);
257                 ret = errno == EOPNOTSUPP ? -2 : -1;
258         }
259
260         return ret;
261 }
262
263
264 /**
265  * wpa_driver_wext_get_bssid - Get BSSID, SIOCGIWAP
266  * @priv: Pointer to private wext data from wpa_driver_wext_init()
267  * @bssid: Buffer for BSSID
268  * Returns: 0 on success, -1 on failure
269  */
270 int wpa_driver_wext_get_bssid(void *priv, u8 *bssid)
271 {
272         struct wpa_driver_wext_data *drv = priv;
273         struct iwreq iwr;
274         int ret = 0;
275
276         os_memset(&iwr, 0, sizeof(iwr));
277         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
278
279         if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
280                 perror("ioctl[SIOCGIWAP]");
281                 ret = -1;
282         }
283         os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
284
285         return ret;
286 }
287
288
289 /**
290  * wpa_driver_wext_set_bssid - Set BSSID, SIOCSIWAP
291  * @priv: Pointer to private wext data from wpa_driver_wext_init()
292  * @bssid: BSSID
293  * Returns: 0 on success, -1 on failure
294  */
295 int wpa_driver_wext_set_bssid(void *priv, const u8 *bssid)
296 {
297         struct wpa_driver_wext_data *drv = priv;
298         struct iwreq iwr;
299         int ret = 0;
300
301         os_memset(&iwr, 0, sizeof(iwr));
302         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
303         iwr.u.ap_addr.sa_family = ARPHRD_ETHER;
304         if (bssid)
305                 os_memcpy(iwr.u.ap_addr.sa_data, bssid, ETH_ALEN);
306         else
307                 os_memset(iwr.u.ap_addr.sa_data, 0, ETH_ALEN);
308
309         if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr) < 0) {
310                 perror("ioctl[SIOCSIWAP]");
311                 ret = -1;
312         }
313
314         return ret;
315 }
316
317
318 /**
319  * wpa_driver_wext_get_ssid - Get SSID, SIOCGIWESSID
320  * @priv: Pointer to private wext data from wpa_driver_wext_init()
321  * @ssid: Buffer for the SSID; must be at least 32 bytes long
322  * Returns: SSID length on success, -1 on failure
323  */
324 int wpa_driver_wext_get_ssid(void *priv, u8 *ssid)
325 {
326         struct wpa_driver_wext_data *drv = priv;
327         struct iwreq iwr;
328         int ret = 0;
329
330         os_memset(&iwr, 0, sizeof(iwr));
331         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
332         iwr.u.essid.pointer = (caddr_t) ssid;
333         iwr.u.essid.length = 32;
334
335         if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
336                 perror("ioctl[SIOCGIWESSID]");
337                 ret = -1;
338         } else {
339                 ret = iwr.u.essid.length;
340                 if (ret > 32)
341                         ret = 32;
342                 /* Some drivers include nul termination in the SSID, so let's
343                  * remove it here before further processing. WE-21 changes this
344                  * to explicitly require the length _not_ to include nul
345                  * termination. */
346                 if (ret > 0 && ssid[ret - 1] == '\0' &&
347                     drv->we_version_compiled < 21)
348                         ret--;
349         }
350
351         return ret;
352 }
353
354
355 /**
356  * wpa_driver_wext_set_ssid - Set SSID, SIOCSIWESSID
357  * @priv: Pointer to private wext data from wpa_driver_wext_init()
358  * @ssid: SSID
359  * @ssid_len: Length of SSID (0..32)
360  * Returns: 0 on success, -1 on failure
361  */
362 int wpa_driver_wext_set_ssid(void *priv, const u8 *ssid, size_t ssid_len)
363 {
364         struct wpa_driver_wext_data *drv = priv;
365         struct iwreq iwr;
366         int ret = 0;
367         char buf[33];
368
369         if (ssid_len > 32)
370                 return -1;
371
372         os_memset(&iwr, 0, sizeof(iwr));
373         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
374         /* flags: 1 = ESSID is active, 0 = not (promiscuous) */
375         iwr.u.essid.flags = (ssid_len != 0);
376         os_memset(buf, 0, sizeof(buf));
377         os_memcpy(buf, ssid, ssid_len);
378         iwr.u.essid.pointer = (caddr_t) buf;
379         if (drv->we_version_compiled < 21) {
380                 /* For historic reasons, set SSID length to include one extra
381                  * character, C string nul termination, even though SSID is
382                  * really an octet string that should not be presented as a C
383                  * string. Some Linux drivers decrement the length by one and
384                  * can thus end up missing the last octet of the SSID if the
385                  * length is not incremented here. WE-21 changes this to
386                  * explicitly require the length _not_ to include nul
387                  * termination. */
388                 if (ssid_len)
389                         ssid_len++;
390         }
391         iwr.u.essid.length = ssid_len;
392
393         if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
394                 perror("ioctl[SIOCSIWESSID]");
395                 ret = -1;
396         }
397
398         return ret;
399 }
400
401
402 /**
403  * wpa_driver_wext_set_freq - Set frequency/channel, SIOCSIWFREQ
404  * @priv: Pointer to private wext data from wpa_driver_wext_init()
405  * @freq: Frequency in MHz
406  * Returns: 0 on success, -1 on failure
407  */
408 int wpa_driver_wext_set_freq(void *priv, int freq)
409 {
410         struct wpa_driver_wext_data *drv = priv;
411         struct iwreq iwr;
412         int ret = 0;
413
414         os_memset(&iwr, 0, sizeof(iwr));
415         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
416         iwr.u.freq.m = freq * 100000;
417         iwr.u.freq.e = 1;
418
419         if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
420                 perror("ioctl[SIOCSIWFREQ]");
421                 ret = -1;
422         }
423
424         return ret;
425 }
426
427
428 static void
429 wpa_driver_wext_event_wireless_custom(void *ctx, char *custom)
430 {
431         union wpa_event_data data;
432
433         wpa_printf(MSG_MSGDUMP, "WEXT: Custom wireless event: '%s'",
434                    custom);
435
436         os_memset(&data, 0, sizeof(data));
437         /* Host AP driver */
438         if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
439                 data.michael_mic_failure.unicast =
440                         os_strstr(custom, " unicast ") != NULL;
441                 /* TODO: parse parameters(?) */
442                 wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
443         } else if (os_strncmp(custom, "ASSOCINFO(ReqIEs=", 17) == 0) {
444                 char *spos;
445                 int bytes;
446
447                 spos = custom + 17;
448
449                 bytes = strspn(spos, "0123456789abcdefABCDEF");
450                 if (!bytes || (bytes & 1))
451                         return;
452                 bytes /= 2;
453
454                 data.assoc_info.req_ies = os_malloc(bytes);
455                 if (data.assoc_info.req_ies == NULL)
456                         return;
457
458                 data.assoc_info.req_ies_len = bytes;
459                 hexstr2bin(spos, data.assoc_info.req_ies, bytes);
460
461                 spos += bytes * 2;
462
463                 data.assoc_info.resp_ies = NULL;
464                 data.assoc_info.resp_ies_len = 0;
465
466                 if (os_strncmp(spos, " RespIEs=", 9) == 0) {
467                         spos += 9;
468
469                         bytes = strspn(spos, "0123456789abcdefABCDEF");
470                         if (!bytes || (bytes & 1))
471                                 goto done;
472                         bytes /= 2;
473
474                         data.assoc_info.resp_ies = os_malloc(bytes);
475                         if (data.assoc_info.resp_ies == NULL)
476                                 goto done;
477
478                         data.assoc_info.resp_ies_len = bytes;
479                         hexstr2bin(spos, data.assoc_info.resp_ies, bytes);
480                 }
481
482                 wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
483
484         done:
485                 os_free(data.assoc_info.resp_ies);
486                 os_free(data.assoc_info.req_ies);
487 #ifdef CONFIG_PEERKEY
488         } else if (os_strncmp(custom, "STKSTART.request=", 17) == 0) {
489                 if (hwaddr_aton(custom + 17, data.stkstart.peer)) {
490                         wpa_printf(MSG_DEBUG, "WEXT: unrecognized "
491                                    "STKSTART.request '%s'", custom + 17);
492                         return;
493                 }
494                 wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
495 #endif /* CONFIG_PEERKEY */
496         }
497 }
498
499
500 static int wpa_driver_wext_event_wireless_michaelmicfailure(
501         void *ctx, const char *ev, size_t len)
502 {
503         const struct iw_michaelmicfailure *mic;
504         union wpa_event_data data;
505
506         if (len < sizeof(*mic))
507                 return -1;
508
509         mic = (const struct iw_michaelmicfailure *) ev;
510
511         wpa_printf(MSG_DEBUG, "Michael MIC failure wireless event: "
512                    "flags=0x%x src_addr=" MACSTR, mic->flags,
513                    MAC2STR(mic->src_addr.sa_data));
514
515         os_memset(&data, 0, sizeof(data));
516         data.michael_mic_failure.unicast = !(mic->flags & IW_MICFAILURE_GROUP);
517         wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
518
519         return 0;
520 }
521
522
523 static int wpa_driver_wext_event_wireless_pmkidcand(
524         struct wpa_driver_wext_data *drv, const char *ev, size_t len)
525 {
526         const struct iw_pmkid_cand *cand;
527         union wpa_event_data data;
528         const u8 *addr;
529
530         if (len < sizeof(*cand))
531                 return -1;
532
533         cand = (const struct iw_pmkid_cand *) ev;
534         addr = (const u8 *) cand->bssid.sa_data;
535
536         wpa_printf(MSG_DEBUG, "PMKID candidate wireless event: "
537                    "flags=0x%x index=%d bssid=" MACSTR, cand->flags,
538                    cand->index, MAC2STR(addr));
539
540         os_memset(&data, 0, sizeof(data));
541         os_memcpy(data.pmkid_candidate.bssid, addr, ETH_ALEN);
542         data.pmkid_candidate.index = cand->index;
543         data.pmkid_candidate.preauth = cand->flags & IW_PMKID_CAND_PREAUTH;
544         wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
545
546         return 0;
547 }
548
549
550 static int wpa_driver_wext_event_wireless_assocreqie(
551         struct wpa_driver_wext_data *drv, const char *ev, int len)
552 {
553         if (len < 0)
554                 return -1;
555
556         wpa_hexdump(MSG_DEBUG, "AssocReq IE wireless event", (const u8 *) ev,
557                     len);
558         os_free(drv->assoc_req_ies);
559         drv->assoc_req_ies = os_malloc(len);
560         if (drv->assoc_req_ies == NULL) {
561                 drv->assoc_req_ies_len = 0;
562                 return -1;
563         }
564         os_memcpy(drv->assoc_req_ies, ev, len);
565         drv->assoc_req_ies_len = len;
566
567         return 0;
568 }
569
570
571 static int wpa_driver_wext_event_wireless_assocrespie(
572         struct wpa_driver_wext_data *drv, const char *ev, int len)
573 {
574         if (len < 0)
575                 return -1;
576
577         wpa_hexdump(MSG_DEBUG, "AssocResp IE wireless event", (const u8 *) ev,
578                     len);
579         os_free(drv->assoc_resp_ies);
580         drv->assoc_resp_ies = os_malloc(len);
581         if (drv->assoc_resp_ies == NULL) {
582                 drv->assoc_resp_ies_len = 0;
583                 return -1;
584         }
585         os_memcpy(drv->assoc_resp_ies, ev, len);
586         drv->assoc_resp_ies_len = len;
587
588         return 0;
589 }
590
591
592 static void wpa_driver_wext_event_assoc_ies(struct wpa_driver_wext_data *drv)
593 {
594         union wpa_event_data data;
595
596         if (drv->assoc_req_ies == NULL && drv->assoc_resp_ies == NULL)
597                 return;
598
599         os_memset(&data, 0, sizeof(data));
600         if (drv->assoc_req_ies) {
601                 data.assoc_info.req_ies = drv->assoc_req_ies;
602                 drv->assoc_req_ies = NULL;
603                 data.assoc_info.req_ies_len = drv->assoc_req_ies_len;
604         }
605         if (drv->assoc_resp_ies) {
606                 data.assoc_info.resp_ies = drv->assoc_resp_ies;
607                 drv->assoc_resp_ies = NULL;
608                 data.assoc_info.resp_ies_len = drv->assoc_resp_ies_len;
609         }
610
611         wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
612
613         os_free(data.assoc_info.req_ies);
614         os_free(data.assoc_info.resp_ies);
615 }
616
617
618 static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv,
619                                            void *ctx, char *data, int len)
620 {
621         struct iw_event iwe_buf, *iwe = &iwe_buf;
622         char *pos, *end, *custom, *buf;
623
624         pos = data;
625         end = data + len;
626
627         while (pos + IW_EV_LCP_LEN <= end) {
628                 /* Event data may be unaligned, so make a local, aligned copy
629                  * before processing. */
630                 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
631                 wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
632                            iwe->cmd, iwe->len);
633                 if (iwe->len <= IW_EV_LCP_LEN)
634                         return;
635
636                 custom = pos + IW_EV_POINT_LEN;
637                 if (drv->we_version_compiled > 18 &&
638                     (iwe->cmd == IWEVMICHAELMICFAILURE ||
639                      iwe->cmd == IWEVCUSTOM ||
640                      iwe->cmd == IWEVASSOCREQIE ||
641                      iwe->cmd == IWEVASSOCRESPIE ||
642                      iwe->cmd == IWEVPMKIDCAND)) {
643                         /* WE-19 removed the pointer from struct iw_point */
644                         char *dpos = (char *) &iwe_buf.u.data.length;
645                         int dlen = dpos - (char *) &iwe_buf;
646                         os_memcpy(dpos, pos + IW_EV_LCP_LEN,
647                                   sizeof(struct iw_event) - dlen);
648                 } else {
649                         os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
650                         custom += IW_EV_POINT_OFF;
651                 }
652
653                 switch (iwe->cmd) {
654                 case SIOCGIWAP:
655                         wpa_printf(MSG_DEBUG, "Wireless event: new AP: "
656                                    MACSTR,
657                                    MAC2STR((u8 *) iwe->u.ap_addr.sa_data));
658                         if (os_memcmp(iwe->u.ap_addr.sa_data,
659                                       "\x00\x00\x00\x00\x00\x00", ETH_ALEN) ==
660                             0 ||
661                             os_memcmp(iwe->u.ap_addr.sa_data,
662                                       "\x44\x44\x44\x44\x44\x44", ETH_ALEN) ==
663                             0) {
664                                 os_free(drv->assoc_req_ies);
665                                 drv->assoc_req_ies = NULL;
666                                 os_free(drv->assoc_resp_ies);
667                                 drv->assoc_resp_ies = NULL;
668                                 wpa_supplicant_event(ctx, EVENT_DISASSOC,
669                                                      NULL);
670                         
671                         } else {
672                                 wpa_driver_wext_event_assoc_ies(drv);
673                                 wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
674                         }
675                         break;
676                 case IWEVMICHAELMICFAILURE:
677                         wpa_driver_wext_event_wireless_michaelmicfailure(
678                                 ctx, custom, iwe->u.data.length);
679                         break;
680                 case IWEVCUSTOM:
681                         if (custom + iwe->u.data.length > end)
682                                 return;
683                         buf = os_malloc(iwe->u.data.length + 1);
684                         if (buf == NULL)
685                                 return;
686                         os_memcpy(buf, custom, iwe->u.data.length);
687                         buf[iwe->u.data.length] = '\0';
688                         wpa_driver_wext_event_wireless_custom(ctx, buf);
689                         os_free(buf);
690                         break;
691                 case SIOCGIWSCAN:
692                         drv->scan_complete_events = 1;
693                         eloop_cancel_timeout(wpa_driver_wext_scan_timeout,
694                                              drv, ctx);
695                         wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
696                         break;
697                 case IWEVASSOCREQIE:
698                         wpa_driver_wext_event_wireless_assocreqie(
699                                 drv, custom, iwe->u.data.length);
700                         break;
701                 case IWEVASSOCRESPIE:
702                         wpa_driver_wext_event_wireless_assocrespie(
703                                 drv, custom, iwe->u.data.length);
704                         break;
705                 case IWEVPMKIDCAND:
706                         wpa_driver_wext_event_wireless_pmkidcand(
707                                 drv, custom, iwe->u.data.length);
708                         break;
709                 }
710
711                 pos += iwe->len;
712         }
713 }
714
715
716 static void wpa_driver_wext_event_link(void *ctx, char *buf, size_t len,
717                                        int del)
718 {
719         union wpa_event_data event;
720
721         os_memset(&event, 0, sizeof(event));
722         if (len > sizeof(event.interface_status.ifname))
723                 len = sizeof(event.interface_status.ifname) - 1;
724         os_memcpy(event.interface_status.ifname, buf, len);
725         event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
726                 EVENT_INTERFACE_ADDED;
727
728         wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
729                    del ? "DEL" : "NEW",
730                    event.interface_status.ifname,
731                    del ? "removed" : "added");
732
733         wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
734 }
735
736
737 static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv,
738                                               void *ctx, struct nlmsghdr *h,
739                                               size_t len)
740 {
741         struct ifinfomsg *ifi;
742         int attrlen, nlmsg_len, rta_len;
743         struct rtattr * attr;
744
745         if (len < sizeof(*ifi))
746                 return;
747
748         ifi = NLMSG_DATA(h);
749
750         if (drv->ifindex != ifi->ifi_index && drv->ifindex2 != ifi->ifi_index)
751         {
752                 wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d",
753                            ifi->ifi_index);
754                 return;
755         }
756
757         wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
758                    "(%s%s%s%s)",
759                    drv->operstate, ifi->ifi_flags,
760                    (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
761                    (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
762                    (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
763                    (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT" : "");
764         /*
765          * Some drivers send the association event before the operup event--in
766          * this case, lifting operstate in wpa_driver_wext_set_operstate()
767          * fails. This will hit us when wpa_supplicant does not need to do
768          * IEEE 802.1X authentication
769          */
770         if (drv->operstate == 1 &&
771             (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
772             !(ifi->ifi_flags & IFF_RUNNING))
773                 wpa_driver_wext_send_oper_ifla(drv, -1, IF_OPER_UP);
774
775         nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
776
777         attrlen = h->nlmsg_len - nlmsg_len;
778         if (attrlen < 0)
779                 return;
780
781         attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
782
783         rta_len = RTA_ALIGN(sizeof(struct rtattr));
784         while (RTA_OK(attr, attrlen)) {
785                 if (attr->rta_type == IFLA_WIRELESS) {
786                         wpa_driver_wext_event_wireless(
787                                 drv, ctx, ((char *) attr) + rta_len,
788                                 attr->rta_len - rta_len);
789                 } else if (attr->rta_type == IFLA_IFNAME) {
790                         wpa_driver_wext_event_link(ctx,
791                                                    ((char *) attr) + rta_len,
792                                                    attr->rta_len - rta_len, 0);
793                 }
794                 attr = RTA_NEXT(attr, attrlen);
795         }
796 }
797
798
799 static void wpa_driver_wext_event_rtm_dellink(struct wpa_driver_wext_data *drv,
800                                               void *ctx, struct nlmsghdr *h,
801                                               size_t len)
802 {
803         struct ifinfomsg *ifi;
804         int attrlen, nlmsg_len, rta_len;
805         struct rtattr * attr;
806
807         if (len < sizeof(*ifi))
808                 return;
809
810         ifi = NLMSG_DATA(h);
811
812         nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
813
814         attrlen = h->nlmsg_len - nlmsg_len;
815         if (attrlen < 0)
816                 return;
817
818         attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
819
820         rta_len = RTA_ALIGN(sizeof(struct rtattr));
821         while (RTA_OK(attr, attrlen)) {
822                 if (attr->rta_type == IFLA_IFNAME) {
823                         wpa_driver_wext_event_link(ctx,
824                                                    ((char *) attr) + rta_len,
825                                                    attr->rta_len - rta_len, 1);
826                 }
827                 attr = RTA_NEXT(attr, attrlen);
828         }
829 }
830
831
832 static void wpa_driver_wext_event_receive(int sock, void *eloop_ctx,
833                                           void *sock_ctx)
834 {
835         char buf[8192];
836         int left;
837         struct sockaddr_nl from;
838         socklen_t fromlen;
839         struct nlmsghdr *h;
840         int max_events = 10;
841
842 try_again:
843         fromlen = sizeof(from);
844         left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
845                         (struct sockaddr *) &from, &fromlen);
846         if (left < 0) {
847                 if (errno != EINTR && errno != EAGAIN)
848                         perror("recvfrom(netlink)");
849                 return;
850         }
851
852         h = (struct nlmsghdr *) buf;
853         while (left >= (int) sizeof(*h)) {
854                 int len, plen;
855
856                 len = h->nlmsg_len;
857                 plen = len - sizeof(*h);
858                 if (len > left || plen < 0) {
859                         wpa_printf(MSG_DEBUG, "Malformed netlink message: "
860                                    "len=%d left=%d plen=%d",
861                                    len, left, plen);
862                         break;
863                 }
864
865                 switch (h->nlmsg_type) {
866                 case RTM_NEWLINK:
867                         wpa_driver_wext_event_rtm_newlink(eloop_ctx, sock_ctx,
868                                                           h, plen);
869                         break;
870                 case RTM_DELLINK:
871                         wpa_driver_wext_event_rtm_dellink(eloop_ctx, sock_ctx,
872                                                           h, plen);
873                         break;
874                 }
875
876                 len = NLMSG_ALIGN(len);
877                 left -= len;
878                 h = (struct nlmsghdr *) ((char *) h + len);
879         }
880
881         if (left > 0) {
882                 wpa_printf(MSG_DEBUG, "%d extra bytes in the end of netlink "
883                            "message", left);
884         }
885
886         if (--max_events > 0) {
887                 /*
888                  * Try to receive all events in one eloop call in order to
889                  * limit race condition on cases where AssocInfo event, Assoc
890                  * event, and EAPOL frames are received more or less at the
891                  * same time. We want to process the event messages first
892                  * before starting EAPOL processing.
893                  */
894                 goto try_again;
895         }
896 }
897
898
899 static int wpa_driver_wext_get_ifflags_ifname(struct wpa_driver_wext_data *drv,
900                                               const char *ifname, int *flags)
901 {
902         struct ifreq ifr;
903
904         os_memset(&ifr, 0, sizeof(ifr));
905         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
906         if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
907                 perror("ioctl[SIOCGIFFLAGS]");
908                 return -1;
909         }
910         *flags = ifr.ifr_flags & 0xffff;
911         return 0;
912 }
913
914
915 /**
916  * wpa_driver_wext_get_ifflags - Get interface flags (SIOCGIFFLAGS)
917  * @drv: driver_wext private data
918  * @flags: Pointer to returned flags value
919  * Returns: 0 on success, -1 on failure
920  */
921 int wpa_driver_wext_get_ifflags(struct wpa_driver_wext_data *drv, int *flags)
922 {
923         return wpa_driver_wext_get_ifflags_ifname(drv, drv->ifname, flags);
924 }
925
926
927 static int wpa_driver_wext_set_ifflags_ifname(struct wpa_driver_wext_data *drv,
928                                               const char *ifname, int flags)
929 {
930         struct ifreq ifr;
931
932         os_memset(&ifr, 0, sizeof(ifr));
933         os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
934         ifr.ifr_flags = flags & 0xffff;
935         if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
936                 perror("SIOCSIFFLAGS");
937                 return -1;
938         }
939         return 0;
940 }
941
942
943 #ifdef CONFIG_CLIENT_MLME
944
945 static int wpa_driver_prism2_param_set(struct wpa_driver_wext_data *drv,
946                                        int param, int value)
947 {
948         struct iwreq iwr;
949         int *i;
950
951         os_memset(&iwr, 0, sizeof(iwr));
952         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
953         i = (int *) iwr.u.name;
954         *i++ = param;
955         *i++ = value;
956
957         return ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr);
958 }
959
960
961 static int wpa_driver_prism2_param_get(struct wpa_driver_wext_data *drv,
962                                        int param)
963 {
964         struct iwreq iwr;
965         int *i;
966
967         os_memset(&iwr, 0, sizeof(iwr));
968         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
969         i = (int *) iwr.u.name;
970         *i = param;
971
972         if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_GET_PRISM2_PARAM, &iwr) < 0) {
973                 perror("ioctl[PRISM2_IOCTL_GET_PRISM2_PARAM]");
974                 return -1;
975         }
976
977         return *i;
978 }
979
980 #endif /* CONFIG_CLIENT_MLME */
981
982
983 /**
984  * wpa_driver_wext_set_ifflags - Set interface flags (SIOCSIFFLAGS)
985  * @drv: driver_wext private data
986  * @flags: New value for flags
987  * Returns: 0 on success, -1 on failure
988  */
989 int wpa_driver_wext_set_ifflags(struct wpa_driver_wext_data *drv, int flags)
990 {
991         return wpa_driver_wext_set_ifflags_ifname(drv, drv->ifname, flags);
992 }
993
994
995 /**
996  * wpa_driver_wext_init - Initialize WE driver interface
997  * @ctx: context to be used when calling wpa_supplicant functions,
998  * e.g., wpa_supplicant_event()
999  * @ifname: interface name, e.g., wlan0
1000  * Returns: Pointer to private data, %NULL on failure
1001  */
1002 void * wpa_driver_wext_init(void *ctx, const char *ifname)
1003 {
1004         int s, flags;
1005         struct sockaddr_nl local;
1006         struct wpa_driver_wext_data *drv;
1007
1008         drv = os_zalloc(sizeof(*drv));
1009         if (drv == NULL)
1010                 return NULL;
1011         drv->ctx = ctx;
1012         os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
1013
1014         drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
1015         if (drv->ioctl_sock < 0) {
1016                 perror("socket(PF_INET,SOCK_DGRAM)");
1017                 os_free(drv);
1018                 return NULL;
1019         }
1020
1021         s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
1022         if (s < 0) {
1023                 perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
1024                 close(drv->ioctl_sock);
1025                 os_free(drv);
1026                 return NULL;
1027         }
1028
1029         os_memset(&local, 0, sizeof(local));
1030         local.nl_family = AF_NETLINK;
1031         local.nl_groups = RTMGRP_LINK;
1032         if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
1033                 perror("bind(netlink)");
1034                 close(s);
1035                 close(drv->ioctl_sock);
1036                 os_free(drv);
1037                 return NULL;
1038         }
1039
1040         eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx);
1041         drv->event_sock = s;
1042
1043         drv->mlme_sock = -1;
1044
1045         if (wpa_driver_wext_get_ifflags(drv, &flags) != 0)
1046                 printf("Could not get interface '%s' flags\n", drv->ifname);
1047         else if (!(flags & IFF_UP)) {
1048                 if (wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) {
1049                         printf("Could not set interface '%s' UP\n",
1050                                drv->ifname);
1051                 } else {
1052                         /*
1053                          * Wait some time to allow driver to initialize before
1054                          * starting configuring the driver. This seems to be
1055                          * needed at least some drivers that load firmware etc.
1056                          * when the interface is set up.
1057                          */
1058                         wpa_printf(MSG_DEBUG, "Interface %s set UP - waiting "
1059                                    "a second for the driver to complete "
1060                                    "initialization", drv->ifname);
1061                         sleep(1);
1062                 }
1063         }
1064
1065         /*
1066          * Make sure that the driver does not have any obsolete PMKID entries.
1067          */
1068         wpa_driver_wext_flush_pmkid(drv);
1069
1070         if (wpa_driver_wext_set_mode(drv, 0) < 0) {
1071                 printf("Could not configure driver to use managed mode\n");
1072         }
1073
1074         wpa_driver_wext_get_range(drv);
1075
1076         drv->ifindex = if_nametoindex(drv->ifname);
1077
1078         if (os_strncmp(ifname, "wlan", 4) == 0) {
1079                 /*
1080                  * Host AP driver may use both wlan# and wifi# interface in
1081                  * wireless events. Since some of the versions included WE-18
1082                  * support, let's add the alternative ifindex also from
1083                  * driver_wext.c for the time being. This may be removed at
1084                  * some point once it is believed that old versions of the
1085                  * driver are not in use anymore.
1086                  */
1087                 char ifname2[IFNAMSIZ + 1];
1088                 os_strlcpy(ifname2, ifname, sizeof(ifname2));
1089                 os_memcpy(ifname2, "wifi", 4);
1090                 wpa_driver_wext_alternative_ifindex(drv, ifname2);
1091         }
1092
1093         wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT);
1094
1095         return drv;
1096 }
1097
1098
1099 /**
1100  * wpa_driver_wext_deinit - Deinitialize WE driver interface
1101  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1102  *
1103  * Shut down driver interface and processing of driver events. Free
1104  * private data buffer if one was allocated in wpa_driver_wext_init().
1105  */
1106 void wpa_driver_wext_deinit(void *priv)
1107 {
1108         struct wpa_driver_wext_data *drv = priv;
1109         int flags;
1110
1111         eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
1112
1113         /*
1114          * Clear possibly configured driver parameters in order to make it
1115          * easier to use the driver after wpa_supplicant has been terminated.
1116          */
1117         (void) wpa_driver_wext_set_bssid(drv,
1118                                          (u8 *) "\x00\x00\x00\x00\x00\x00");
1119
1120         wpa_driver_wext_send_oper_ifla(priv, 0, IF_OPER_UP);
1121
1122         eloop_unregister_read_sock(drv->event_sock);
1123         if (drv->mlme_sock >= 0)
1124                 eloop_unregister_read_sock(drv->mlme_sock);
1125
1126         if (wpa_driver_wext_get_ifflags(drv, &flags) == 0)
1127                 (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
1128
1129 #ifdef CONFIG_CLIENT_MLME
1130         if (drv->mlmedev[0]) {
1131                 if (wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev,
1132                                                        &flags) == 0)
1133                         (void) wpa_driver_wext_set_ifflags_ifname(
1134                                 drv, drv->mlmedev, flags & ~IFF_UP);
1135                 wpa_driver_prism2_param_set(drv, PRISM2_PARAM_MGMT_IF, 0);
1136                 wpa_driver_prism2_param_set(drv, PRISM2_PARAM_USER_SPACE_MLME,
1137                                             0);
1138         }
1139 #endif /* CONFIG_CLIENT_MLME */
1140
1141         close(drv->event_sock);
1142         close(drv->ioctl_sock);
1143         if (drv->mlme_sock >= 0)
1144                 close(drv->mlme_sock);
1145         os_free(drv->assoc_req_ies);
1146         os_free(drv->assoc_resp_ies);
1147         os_free(drv);
1148 }
1149
1150
1151 /**
1152  * wpa_driver_wext_scan_timeout - Scan timeout to report scan completion
1153  * @eloop_ctx: Unused
1154  * @timeout_ctx: ctx argument given to wpa_driver_wext_init()
1155  *
1156  * This function can be used as registered timeout when starting a scan to
1157  * generate a scan completed event if the driver does not report this.
1158  */
1159 void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
1160 {
1161         wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
1162         wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
1163 }
1164
1165
1166 /**
1167  * wpa_driver_wext_scan - Request the driver to initiate scan
1168  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1169  * @ssid: Specific SSID to scan for (ProbeReq) or %NULL to scan for
1170  *      all SSIDs (either active scan with broadcast SSID or passive
1171  *      scan
1172  * @ssid_len: Length of the SSID
1173  * Returns: 0 on success, -1 on failure
1174  */
1175 int wpa_driver_wext_scan(void *priv, const u8 *ssid, size_t ssid_len)
1176 {
1177         struct wpa_driver_wext_data *drv = priv;
1178         struct iwreq iwr;
1179         int ret = 0, timeout;
1180         struct iw_scan_req req;
1181
1182         if (ssid_len > IW_ESSID_MAX_SIZE) {
1183                 wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
1184                            __FUNCTION__, (unsigned long) ssid_len);
1185                 return -1;
1186         }
1187
1188         os_memset(&iwr, 0, sizeof(iwr));
1189         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1190
1191         if (ssid && ssid_len) {
1192                 os_memset(&req, 0, sizeof(req));
1193                 req.essid_len = ssid_len;
1194                 req.bssid.sa_family = ARPHRD_ETHER;
1195                 os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);
1196                 os_memcpy(req.essid, ssid, ssid_len);
1197                 iwr.u.data.pointer = (caddr_t) &req;
1198                 iwr.u.data.length = sizeof(req);
1199                 iwr.u.data.flags = IW_SCAN_THIS_ESSID;
1200         }
1201
1202         if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
1203                 perror("ioctl[SIOCSIWSCAN]");
1204                 ret = -1;
1205         }
1206
1207         /* Not all drivers generate "scan completed" wireless event, so try to
1208          * read results after a timeout. */
1209         timeout = 5;
1210         if (drv->scan_complete_events) {
1211                 /*
1212                  * The driver seems to deliver SIOCGIWSCAN events to notify
1213                  * when scan is complete, so use longer timeout to avoid race
1214                  * conditions with scanning and following association request.
1215                  */
1216                 timeout = 30;
1217         }
1218         wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
1219                    "seconds", ret, timeout);
1220         eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
1221         eloop_register_timeout(timeout, 0, wpa_driver_wext_scan_timeout, drv,
1222                                drv->ctx);
1223
1224         return ret;
1225 }
1226
1227
1228 static u8 * wpa_driver_wext_giwscan(struct wpa_driver_wext_data *drv,
1229                                     size_t *len)
1230 {
1231         struct iwreq iwr;
1232         u8 *res_buf;
1233         size_t res_buf_len;
1234
1235         res_buf_len = IW_SCAN_MAX_DATA;
1236         for (;;) {
1237                 res_buf = os_malloc(res_buf_len);
1238                 if (res_buf == NULL)
1239                         return NULL;
1240                 os_memset(&iwr, 0, sizeof(iwr));
1241                 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1242                 iwr.u.data.pointer = res_buf;
1243                 iwr.u.data.length = res_buf_len;
1244
1245                 if (ioctl(drv->ioctl_sock, SIOCGIWSCAN, &iwr) == 0)
1246                         break;
1247
1248                 if (errno == E2BIG && res_buf_len < 100000) {
1249                         os_free(res_buf);
1250                         res_buf = NULL;
1251                         res_buf_len *= 2;
1252                         wpa_printf(MSG_DEBUG, "Scan results did not fit - "
1253                                    "trying larger buffer (%lu bytes)",
1254                                    (unsigned long) res_buf_len);
1255                 } else {
1256                         perror("ioctl[SIOCGIWSCAN]");
1257                         os_free(res_buf);
1258                         return NULL;
1259                 }
1260         }
1261
1262         if (iwr.u.data.length > res_buf_len) {
1263                 os_free(res_buf);
1264                 return NULL;
1265         }
1266         *len = iwr.u.data.length;
1267
1268         return res_buf;
1269 }
1270
1271
1272 /*
1273  * Data structure for collecting WEXT scan results. This is needed to allow
1274  * the various methods of reporting IEs to be combined into a single IE buffer.
1275  */
1276 struct wext_scan_data {
1277         struct wpa_scan_res res;
1278         u8 *ie;
1279         size_t ie_len;
1280         u8 ssid[32];
1281         size_t ssid_len;
1282         int maxrate;
1283 };
1284
1285
1286 static void wext_get_scan_mode(struct iw_event *iwe,
1287                                struct wext_scan_data *res)
1288 {
1289         if (iwe->u.mode == IW_MODE_ADHOC)
1290                 res->res.caps |= IEEE80211_CAP_IBSS;
1291         else if (iwe->u.mode == IW_MODE_MASTER || iwe->u.mode == IW_MODE_INFRA)
1292                 res->res.caps |= IEEE80211_CAP_ESS;
1293 }
1294
1295
1296 static void wext_get_scan_ssid(struct iw_event *iwe,
1297                                struct wext_scan_data *res, char *custom,
1298                                char *end)
1299 {
1300         int ssid_len = iwe->u.essid.length;
1301         if (custom + ssid_len > end)
1302                 return;
1303         if (iwe->u.essid.flags &&
1304             ssid_len > 0 &&
1305             ssid_len <= IW_ESSID_MAX_SIZE) {
1306                 os_memcpy(res->ssid, custom, ssid_len);
1307                 res->ssid_len = ssid_len;
1308         }
1309 }
1310
1311
1312 static void wext_get_scan_freq(struct iw_event *iwe,
1313                                struct wext_scan_data *res)
1314 {
1315         int divi = 1000000, i;
1316
1317         if (iwe->u.freq.e == 0) {
1318                 /*
1319                  * Some drivers do not report frequency, but a channel.
1320                  * Try to map this to frequency by assuming they are using
1321                  * IEEE 802.11b/g.
1322                  */
1323                 if (iwe->u.freq.m >= 1 && iwe->u.freq.m <= 13) {
1324                         res->res.freq = 2407 + 5 * iwe->u.freq.m;
1325                         return;
1326                 } else if (iwe->u.freq.m == 14) {
1327                         res->res.freq = 2484;
1328                         return;
1329                 }
1330         }
1331
1332         if (iwe->u.freq.e > 6) {
1333                 wpa_printf(MSG_DEBUG, "Invalid freq in scan results (BSSID="
1334                            MACSTR " m=%d e=%d)",
1335                            MAC2STR(res->res.bssid), iwe->u.freq.m,
1336                            iwe->u.freq.e);
1337                 return;
1338         }
1339
1340         for (i = 0; i < iwe->u.freq.e; i++)
1341                 divi /= 10;
1342         res->res.freq = iwe->u.freq.m / divi;
1343 }
1344
1345
1346 static void wext_get_scan_qual(struct iw_event *iwe,
1347                                struct wext_scan_data *res)
1348 {
1349         res->res.qual = iwe->u.qual.qual;
1350         res->res.noise = iwe->u.qual.noise;
1351         res->res.level = iwe->u.qual.level;
1352 }
1353
1354
1355 static void wext_get_scan_encode(struct iw_event *iwe,
1356                                  struct wext_scan_data *res)
1357 {
1358         if (!(iwe->u.data.flags & IW_ENCODE_DISABLED))
1359                 res->res.caps |= IEEE80211_CAP_PRIVACY;
1360 }
1361
1362
1363 static void wext_get_scan_rate(struct iw_event *iwe,
1364                                struct wext_scan_data *res, char *pos,
1365                                char *end)
1366 {
1367         int maxrate;
1368         char *custom = pos + IW_EV_LCP_LEN;
1369         struct iw_param p;
1370         size_t clen;
1371
1372         clen = iwe->len;
1373         if (custom + clen > end)
1374                 return;
1375         maxrate = 0;
1376         while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) {
1377                 /* Note: may be misaligned, make a local, aligned copy */
1378                 os_memcpy(&p, custom, sizeof(struct iw_param));
1379                 if (p.value > maxrate)
1380                         maxrate = p.value;
1381                 clen -= sizeof(struct iw_param);
1382                 custom += sizeof(struct iw_param);
1383         }
1384         res->maxrate = maxrate;
1385 }
1386
1387
1388 static void wext_get_scan_iwevgenie(struct iw_event *iwe,
1389                                     struct wext_scan_data *res, char *custom,
1390                                     char *end)
1391 {
1392         char *genie, *gpos, *gend;
1393         u8 *tmp;
1394
1395         gpos = genie = custom;
1396         gend = genie + iwe->u.data.length;
1397         if (gend > end) {
1398                 wpa_printf(MSG_INFO, "IWEVGENIE overflow");
1399                 return;
1400         }
1401
1402         tmp = os_realloc(res->ie, res->ie_len + gend - gpos);
1403         if (tmp == NULL)
1404                 return;
1405         os_memcpy(tmp + res->ie_len, gpos, gend - gpos);
1406         res->ie = tmp;
1407         res->ie_len += gend - gpos;
1408 }
1409
1410
1411 static void wext_get_scan_custom(struct iw_event *iwe,
1412                                  struct wext_scan_data *res, char *custom,
1413                                  char *end)
1414 {
1415         size_t clen;
1416         u8 *tmp;
1417
1418         clen = iwe->u.data.length;
1419         if (custom + clen > end)
1420                 return;
1421
1422         if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) {
1423                 char *spos;
1424                 int bytes;
1425                 spos = custom + 7;
1426                 bytes = custom + clen - spos;
1427                 if (bytes & 1)
1428                         return;
1429                 bytes /= 2;
1430                 tmp = os_realloc(res->ie, res->ie_len + bytes);
1431                 if (tmp == NULL)
1432                         return;
1433                 hexstr2bin(spos, tmp + res->ie_len, bytes);
1434                 res->ie = tmp;
1435                 res->ie_len += bytes;
1436         } else if (clen > 7 && os_strncmp(custom, "rsn_ie=", 7) == 0) {
1437                 char *spos;
1438                 int bytes;
1439                 spos = custom + 7;
1440                 bytes = custom + clen - spos;
1441                 if (bytes & 1)
1442                         return;
1443                 bytes /= 2;
1444                 tmp = os_realloc(res->ie, res->ie_len + bytes);
1445                 if (tmp == NULL)
1446                         return;
1447                 hexstr2bin(spos, tmp + res->ie_len, bytes);
1448                 res->ie = tmp;
1449                 res->ie_len += bytes;
1450         } else if (clen > 4 && os_strncmp(custom, "tsf=", 4) == 0) {
1451                 char *spos;
1452                 int bytes;
1453                 u8 bin[8];
1454                 spos = custom + 4;
1455                 bytes = custom + clen - spos;
1456                 if (bytes != 16) {
1457                         wpa_printf(MSG_INFO, "Invalid TSF length (%d)", bytes);
1458                         return;
1459                 }
1460                 bytes /= 2;
1461                 hexstr2bin(spos, bin, bytes);
1462                 res->res.tsf += WPA_GET_BE64(bin);
1463         }
1464 }
1465
1466
1467 static int wext_19_iw_point(struct wpa_driver_wext_data *drv, u16 cmd)
1468 {
1469         return drv->we_version_compiled > 18 &&
1470                 (cmd == SIOCGIWESSID || cmd == SIOCGIWENCODE ||
1471                  cmd == IWEVGENIE || cmd == IWEVCUSTOM);
1472 }
1473
1474
1475 static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
1476                                            struct wext_scan_data *data)
1477 {
1478         struct wpa_scan_res **tmp;
1479         struct wpa_scan_res *r;
1480         size_t extra_len;
1481         u8 *pos, *end, *ssid_ie = NULL, *rate_ie = NULL;
1482
1483         /* Figure out whether we need to fake any IEs */
1484         pos = data->ie;
1485         end = pos + data->ie_len;
1486         while (pos && pos + 1 < end) {
1487                 if (pos + 2 + pos[1] > end)
1488                         break;
1489                 if (pos[0] == WLAN_EID_SSID)
1490                         ssid_ie = pos;
1491                 else if (pos[0] == WLAN_EID_SUPP_RATES)
1492                         rate_ie = pos;
1493                 else if (pos[0] == WLAN_EID_EXT_SUPP_RATES)
1494                         rate_ie = pos;
1495                 pos += 2 + pos[1];
1496         }
1497
1498         extra_len = 0;
1499         if (ssid_ie == NULL)
1500                 extra_len += 2 + data->ssid_len;
1501         if (rate_ie == NULL && data->maxrate)
1502                 extra_len += 3;
1503
1504         r = os_zalloc(sizeof(*r) + extra_len + data->ie_len);
1505         if (r == NULL)
1506                 return;
1507         os_memcpy(r, &data->res, sizeof(*r));
1508         r->ie_len = extra_len + data->ie_len;
1509         pos = (u8 *) (r + 1);
1510         if (ssid_ie == NULL) {
1511                 /*
1512                  * Generate a fake SSID IE since the driver did not report
1513                  * a full IE list.
1514                  */
1515                 *pos++ = WLAN_EID_SSID;
1516                 *pos++ = data->ssid_len;
1517                 os_memcpy(pos, data->ssid, data->ssid_len);
1518                 pos += data->ssid_len;
1519         }
1520         if (rate_ie == NULL && data->maxrate) {
1521                 /*
1522                  * Generate a fake Supported Rates IE since the driver did not
1523                  * report a full IE list.
1524                  */
1525                 *pos++ = WLAN_EID_SUPP_RATES;
1526                 *pos++ = 1;
1527                 *pos++ = data->maxrate;
1528         }
1529         if (data->ie)
1530                 os_memcpy(pos, data->ie, data->ie_len);
1531
1532         tmp = os_realloc(res->res,
1533                          (res->num + 1) * sizeof(struct wpa_scan_res *));
1534         if (tmp == NULL) {
1535                 os_free(r);
1536                 return;
1537         }
1538         tmp[res->num++] = r;
1539         res->res = tmp;
1540 }
1541                                       
1542
1543 /**
1544  * wpa_driver_wext_get_scan_results - Fetch the latest scan results
1545  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1546  * Returns: Scan results on success, -1 on failure
1547  */
1548 struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
1549 {
1550         struct wpa_driver_wext_data *drv = priv;
1551         size_t ap_num = 0, len;
1552         int first;
1553         u8 *res_buf;
1554         struct iw_event iwe_buf, *iwe = &iwe_buf;
1555         char *pos, *end, *custom;
1556         struct wpa_scan_results *res;
1557         struct wext_scan_data data;
1558
1559         res_buf = wpa_driver_wext_giwscan(drv, &len);
1560         if (res_buf == NULL)
1561                 return NULL;
1562
1563         ap_num = 0;
1564         first = 1;
1565
1566         res = os_zalloc(sizeof(*res));
1567         if (res == NULL) {
1568                 os_free(res_buf);
1569                 return NULL;
1570         }
1571
1572         pos = (char *) res_buf;
1573         end = (char *) res_buf + len;
1574         os_memset(&data, 0, sizeof(data));
1575
1576         while (pos + IW_EV_LCP_LEN <= end) {
1577                 /* Event data may be unaligned, so make a local, aligned copy
1578                  * before processing. */
1579                 os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
1580                 if (iwe->len <= IW_EV_LCP_LEN)
1581                         break;
1582
1583                 custom = pos + IW_EV_POINT_LEN;
1584                 if (wext_19_iw_point(drv, iwe->cmd)) {
1585                         /* WE-19 removed the pointer from struct iw_point */
1586                         char *dpos = (char *) &iwe_buf.u.data.length;
1587                         int dlen = dpos - (char *) &iwe_buf;
1588                         os_memcpy(dpos, pos + IW_EV_LCP_LEN,
1589                                   sizeof(struct iw_event) - dlen);
1590                 } else {
1591                         os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
1592                         custom += IW_EV_POINT_OFF;
1593                 }
1594
1595                 switch (iwe->cmd) {
1596                 case SIOCGIWAP:
1597                         if (!first)
1598                                 wpa_driver_wext_add_scan_entry(res, &data);
1599                         first = 0;
1600                         os_free(data.ie);
1601                         os_memset(&data, 0, sizeof(data));
1602                         os_memcpy(data.res.bssid,
1603                                   iwe->u.ap_addr.sa_data, ETH_ALEN);
1604                         break;
1605                 case SIOCGIWMODE:
1606                         wext_get_scan_mode(iwe, &data);
1607                         break;
1608                 case SIOCGIWESSID:
1609                         wext_get_scan_ssid(iwe, &data, custom, end);
1610                         break;
1611                 case SIOCGIWFREQ:
1612                         wext_get_scan_freq(iwe, &data);
1613                         break;
1614                 case IWEVQUAL:
1615                         wext_get_scan_qual(iwe, &data);
1616                         break;
1617                 case SIOCGIWENCODE:
1618                         wext_get_scan_encode(iwe, &data);
1619                         break;
1620                 case SIOCGIWRATE:
1621                         wext_get_scan_rate(iwe, &data, pos, end);
1622                         break;
1623                 case IWEVGENIE:
1624                         wext_get_scan_iwevgenie(iwe, &data, custom, end);
1625                         break;
1626                 case IWEVCUSTOM:
1627                         wext_get_scan_custom(iwe, &data, custom, end);
1628                         break;
1629                 }
1630
1631                 pos += iwe->len;
1632         }
1633         os_free(res_buf);
1634         res_buf = NULL;
1635         if (!first)
1636                 wpa_driver_wext_add_scan_entry(res, &data);
1637         os_free(data.ie);
1638
1639         wpa_printf(MSG_DEBUG, "Received %lu bytes of scan results (%lu BSSes)",
1640                    (unsigned long) len, (unsigned long) res->num);
1641
1642         return res;
1643 }
1644
1645
1646 static int wpa_driver_wext_get_range(void *priv)
1647 {
1648         struct wpa_driver_wext_data *drv = priv;
1649         struct iw_range *range;
1650         struct iwreq iwr;
1651         int minlen;
1652         size_t buflen;
1653
1654         /*
1655          * Use larger buffer than struct iw_range in order to allow the
1656          * structure to grow in the future.
1657          */
1658         buflen = sizeof(struct iw_range) + 500;
1659         range = os_zalloc(buflen);
1660         if (range == NULL)
1661                 return -1;
1662
1663         os_memset(&iwr, 0, sizeof(iwr));
1664         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1665         iwr.u.data.pointer = (caddr_t) range;
1666         iwr.u.data.length = buflen;
1667
1668         minlen = ((char *) &range->enc_capa) - (char *) range +
1669                 sizeof(range->enc_capa);
1670
1671         if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
1672                 perror("ioctl[SIOCGIWRANGE]");
1673                 os_free(range);
1674                 return -1;
1675         } else if (iwr.u.data.length >= minlen &&
1676                    range->we_version_compiled >= 18) {
1677                 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
1678                            "WE(source)=%d enc_capa=0x%x",
1679                            range->we_version_compiled,
1680                            range->we_version_source,
1681                            range->enc_capa);
1682                 drv->has_capability = 1;
1683                 drv->we_version_compiled = range->we_version_compiled;
1684                 if (range->enc_capa & IW_ENC_CAPA_WPA) {
1685                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
1686                                 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK;
1687                 }
1688                 if (range->enc_capa & IW_ENC_CAPA_WPA2) {
1689                         drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
1690                                 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
1691                 }
1692                 drv->capa.enc |= WPA_DRIVER_CAPA_ENC_WEP40 |
1693                         WPA_DRIVER_CAPA_ENC_WEP104;
1694                 if (range->enc_capa & IW_ENC_CAPA_CIPHER_TKIP)
1695                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_TKIP;
1696                 if (range->enc_capa & IW_ENC_CAPA_CIPHER_CCMP)
1697                         drv->capa.enc |= WPA_DRIVER_CAPA_ENC_CCMP;
1698                 wpa_printf(MSG_DEBUG, "  capabilities: key_mgmt 0x%x enc 0x%x",
1699                            drv->capa.key_mgmt, drv->capa.enc);
1700         } else {
1701                 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: too old (short) data - "
1702                            "assuming WPA is not supported");
1703         }
1704
1705         os_free(range);
1706         return 0;
1707 }
1708
1709
1710 static int wpa_driver_wext_set_wpa(void *priv, int enabled)
1711 {
1712         struct wpa_driver_wext_data *drv = priv;
1713         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1714
1715         return wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED,
1716                                               enabled);
1717 }
1718
1719
1720 static int wpa_driver_wext_set_key_ext(void *priv, wpa_alg alg,
1721                                        const u8 *addr, int key_idx,
1722                                        int set_tx, const u8 *seq,
1723                                        size_t seq_len,
1724                                        const u8 *key, size_t key_len)
1725 {
1726         struct wpa_driver_wext_data *drv = priv;
1727         struct iwreq iwr;
1728         int ret = 0;
1729         struct iw_encode_ext *ext;
1730
1731         if (seq_len > IW_ENCODE_SEQ_MAX_SIZE) {
1732                 wpa_printf(MSG_DEBUG, "%s: Invalid seq_len %lu",
1733                            __FUNCTION__, (unsigned long) seq_len);
1734                 return -1;
1735         }
1736
1737         ext = os_zalloc(sizeof(*ext) + key_len);
1738         if (ext == NULL)
1739                 return -1;
1740         os_memset(&iwr, 0, sizeof(iwr));
1741         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1742         iwr.u.encoding.flags = key_idx + 1;
1743         if (alg == WPA_ALG_NONE)
1744                 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1745         iwr.u.encoding.pointer = (caddr_t) ext;
1746         iwr.u.encoding.length = sizeof(*ext) + key_len;
1747
1748         if (addr == NULL ||
1749             os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
1750                 ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
1751         if (set_tx)
1752                 ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
1753
1754         ext->addr.sa_family = ARPHRD_ETHER;
1755         if (addr)
1756                 os_memcpy(ext->addr.sa_data, addr, ETH_ALEN);
1757         else
1758                 os_memset(ext->addr.sa_data, 0xff, ETH_ALEN);
1759         if (key && key_len) {
1760                 os_memcpy(ext + 1, key, key_len);
1761                 ext->key_len = key_len;
1762         }
1763         switch (alg) {
1764         case WPA_ALG_NONE:
1765                 ext->alg = IW_ENCODE_ALG_NONE;
1766                 break;
1767         case WPA_ALG_WEP:
1768                 ext->alg = IW_ENCODE_ALG_WEP;
1769                 break;
1770         case WPA_ALG_TKIP:
1771                 ext->alg = IW_ENCODE_ALG_TKIP;
1772                 break;
1773         case WPA_ALG_CCMP:
1774                 ext->alg = IW_ENCODE_ALG_CCMP;
1775                 break;
1776         default:
1777                 wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d",
1778                            __FUNCTION__, alg);
1779                 os_free(ext);
1780                 return -1;
1781         }
1782
1783         if (seq && seq_len) {
1784                 ext->ext_flags |= IW_ENCODE_EXT_RX_SEQ_VALID;
1785                 os_memcpy(ext->rx_seq, seq, seq_len);
1786         }
1787
1788         if (ioctl(drv->ioctl_sock, SIOCSIWENCODEEXT, &iwr) < 0) {
1789                 ret = errno == EOPNOTSUPP ? -2 : -1;
1790                 if (errno == ENODEV) {
1791                         /*
1792                          * ndiswrapper seems to be returning incorrect error
1793                          * code.. */
1794                         ret = -2;
1795                 }
1796
1797                 perror("ioctl[SIOCSIWENCODEEXT]");
1798         }
1799
1800         os_free(ext);
1801         return ret;
1802 }
1803
1804
1805 /**
1806  * wpa_driver_wext_set_key - Configure encryption key
1807  * @priv: Pointer to private wext data from wpa_driver_wext_init()
1808  * @priv: Private driver interface data
1809  * @alg: Encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
1810  *      %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
1811  * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for
1812  *      broadcast/default keys
1813  * @key_idx: key index (0..3), usually 0 for unicast keys
1814  * @set_tx: Configure this key as the default Tx key (only used when
1815  *      driver does not support separate unicast/individual key
1816  * @seq: Sequence number/packet number, seq_len octets, the next
1817  *      packet number to be used for in replay protection; configured
1818  *      for Rx keys (in most cases, this is only used with broadcast
1819  *      keys and set to zero for unicast keys)
1820  * @seq_len: Length of the seq, depends on the algorithm:
1821  *      TKIP: 6 octets, CCMP: 6 octets
1822  * @key: Key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
1823  *      8-byte Rx Mic Key
1824  * @key_len: Length of the key buffer in octets (WEP: 5 or 13,
1825  *      TKIP: 32, CCMP: 16)
1826  * Returns: 0 on success, -1 on failure
1827  *
1828  * This function uses SIOCSIWENCODEEXT by default, but tries to use
1829  * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key.
1830  */
1831 int wpa_driver_wext_set_key(void *priv, wpa_alg alg,
1832                             const u8 *addr, int key_idx,
1833                             int set_tx, const u8 *seq, size_t seq_len,
1834                             const u8 *key, size_t key_len)
1835 {
1836         struct wpa_driver_wext_data *drv = priv;
1837         struct iwreq iwr;
1838         int ret = 0;
1839
1840         wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
1841                    "key_len=%lu",
1842                    __FUNCTION__, alg, key_idx, set_tx,
1843                    (unsigned long) seq_len, (unsigned long) key_len);
1844
1845         ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx,
1846                                           seq, seq_len, key, key_len);
1847         if (ret == 0)
1848                 return 0;
1849
1850         if (ret == -2 &&
1851             (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) {
1852                 wpa_printf(MSG_DEBUG, "Driver did not support "
1853                            "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
1854                 ret = 0;
1855         } else {
1856                 wpa_printf(MSG_DEBUG, "Driver did not support "
1857                            "SIOCSIWENCODEEXT");
1858                 return ret;
1859         }
1860
1861         os_memset(&iwr, 0, sizeof(iwr));
1862         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1863         iwr.u.encoding.flags = key_idx + 1;
1864         if (alg == WPA_ALG_NONE)
1865                 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
1866         iwr.u.encoding.pointer = (caddr_t) key;
1867         iwr.u.encoding.length = key_len;
1868
1869         if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1870                 perror("ioctl[SIOCSIWENCODE]");
1871                 ret = -1;
1872         }
1873
1874         if (set_tx && alg != WPA_ALG_NONE) {
1875                 os_memset(&iwr, 0, sizeof(iwr));
1876                 os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1877                 iwr.u.encoding.flags = key_idx + 1;
1878                 iwr.u.encoding.pointer = (caddr_t) NULL;
1879                 iwr.u.encoding.length = 0;
1880                 if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
1881                         perror("ioctl[SIOCSIWENCODE] (set_tx)");
1882                         ret = -1;
1883                 }
1884         }
1885
1886         return ret;
1887 }
1888
1889
1890 static int wpa_driver_wext_set_countermeasures(void *priv,
1891                                                int enabled)
1892 {
1893         struct wpa_driver_wext_data *drv = priv;
1894         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1895         return wpa_driver_wext_set_auth_param(drv,
1896                                               IW_AUTH_TKIP_COUNTERMEASURES,
1897                                               enabled);
1898 }
1899
1900
1901 static int wpa_driver_wext_set_drop_unencrypted(void *priv,
1902                                                 int enabled)
1903 {
1904         struct wpa_driver_wext_data *drv = priv;
1905         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1906         drv->use_crypt = enabled;
1907         return wpa_driver_wext_set_auth_param(drv, IW_AUTH_DROP_UNENCRYPTED,
1908                                               enabled);
1909 }
1910
1911
1912 static int wpa_driver_wext_mlme(struct wpa_driver_wext_data *drv,
1913                                 const u8 *addr, int cmd, int reason_code)
1914 {
1915         struct iwreq iwr;
1916         struct iw_mlme mlme;
1917         int ret = 0;
1918
1919         os_memset(&iwr, 0, sizeof(iwr));
1920         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1921         os_memset(&mlme, 0, sizeof(mlme));
1922         mlme.cmd = cmd;
1923         mlme.reason_code = reason_code;
1924         mlme.addr.sa_family = ARPHRD_ETHER;
1925         os_memcpy(mlme.addr.sa_data, addr, ETH_ALEN);
1926         iwr.u.data.pointer = (caddr_t) &mlme;
1927         iwr.u.data.length = sizeof(mlme);
1928
1929         if (ioctl(drv->ioctl_sock, SIOCSIWMLME, &iwr) < 0) {
1930                 perror("ioctl[SIOCSIWMLME]");
1931                 ret = -1;
1932         }
1933
1934         return ret;
1935 }
1936
1937
1938 static int wpa_driver_wext_deauthenticate(void *priv, const u8 *addr,
1939                                           int reason_code)
1940 {
1941         struct wpa_driver_wext_data *drv = priv;
1942         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1943         return wpa_driver_wext_mlme(drv, addr, IW_MLME_DEAUTH, reason_code);
1944 }
1945
1946
1947 static int wpa_driver_wext_disassociate(void *priv, const u8 *addr,
1948                                         int reason_code)
1949 {
1950         struct wpa_driver_wext_data *drv = priv;
1951         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
1952         return wpa_driver_wext_mlme(drv, addr, IW_MLME_DISASSOC,
1953                                     reason_code);
1954 }
1955
1956
1957 static int wpa_driver_wext_set_gen_ie(void *priv, const u8 *ie,
1958                                       size_t ie_len)
1959 {
1960         struct wpa_driver_wext_data *drv = priv;
1961         struct iwreq iwr;
1962         int ret = 0;
1963
1964         os_memset(&iwr, 0, sizeof(iwr));
1965         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
1966         iwr.u.data.pointer = (caddr_t) ie;
1967         iwr.u.data.length = ie_len;
1968
1969         if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) {
1970                 perror("ioctl[SIOCSIWGENIE]");
1971                 ret = -1;
1972         }
1973
1974         return ret;
1975 }
1976
1977
1978 static int wpa_driver_wext_cipher2wext(int cipher)
1979 {
1980         switch (cipher) {
1981         case CIPHER_NONE:
1982                 return IW_AUTH_CIPHER_NONE;
1983         case CIPHER_WEP40:
1984                 return IW_AUTH_CIPHER_WEP40;
1985         case CIPHER_TKIP:
1986                 return IW_AUTH_CIPHER_TKIP;
1987         case CIPHER_CCMP:
1988                 return IW_AUTH_CIPHER_CCMP;
1989         case CIPHER_WEP104:
1990                 return IW_AUTH_CIPHER_WEP104;
1991         default:
1992                 return 0;
1993         }
1994 }
1995
1996
1997 static int wpa_driver_wext_keymgmt2wext(int keymgmt)
1998 {
1999         switch (keymgmt) {
2000         case KEY_MGMT_802_1X:
2001         case KEY_MGMT_802_1X_NO_WPA:
2002                 return IW_AUTH_KEY_MGMT_802_1X;
2003         case KEY_MGMT_PSK:
2004                 return IW_AUTH_KEY_MGMT_PSK;
2005         default:
2006                 return 0;
2007         }
2008 }
2009
2010
2011 static int
2012 wpa_driver_wext_auth_alg_fallback(struct wpa_driver_wext_data *drv,
2013                                   struct wpa_driver_associate_params *params)
2014 {
2015         struct iwreq iwr;
2016         int ret = 0;
2017
2018         wpa_printf(MSG_DEBUG, "WEXT: Driver did not support "
2019                    "SIOCSIWAUTH for AUTH_ALG, trying SIOCSIWENCODE");
2020
2021         os_memset(&iwr, 0, sizeof(iwr));
2022         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2023         /* Just changing mode, not actual keys */
2024         iwr.u.encoding.flags = 0;
2025         iwr.u.encoding.pointer = (caddr_t) NULL;
2026         iwr.u.encoding.length = 0;
2027
2028         /*
2029          * Note: IW_ENCODE_{OPEN,RESTRICTED} can be interpreted to mean two
2030          * different things. Here they are used to indicate Open System vs.
2031          * Shared Key authentication algorithm. However, some drivers may use
2032          * them to select between open/restricted WEP encrypted (open = allow
2033          * both unencrypted and encrypted frames; restricted = only allow
2034          * encrypted frames).
2035          */
2036
2037         if (!drv->use_crypt) {
2038                 iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
2039         } else {
2040                 if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM)
2041                         iwr.u.encoding.flags |= IW_ENCODE_OPEN;
2042                 if (params->auth_alg & AUTH_ALG_SHARED_KEY)
2043                         iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED;
2044         }
2045
2046         if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
2047                 perror("ioctl[SIOCSIWENCODE]");
2048                 ret = -1;
2049         }
2050
2051         return ret;
2052 }
2053
2054
2055 static int
2056 wpa_driver_wext_associate(void *priv,
2057                           struct wpa_driver_associate_params *params)
2058 {
2059         struct wpa_driver_wext_data *drv = priv;
2060         int ret = 0;
2061         int allow_unencrypted_eapol;
2062         int value;
2063
2064         wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
2065
2066         /*
2067          * If the driver did not support SIOCSIWAUTH, fallback to
2068          * SIOCSIWENCODE here.
2069          */
2070         if (drv->auth_alg_fallback &&
2071             wpa_driver_wext_auth_alg_fallback(drv, params) < 0)
2072                 ret = -1;
2073
2074         if (!params->bssid &&
2075             wpa_driver_wext_set_bssid(drv, NULL) < 0)
2076                 ret = -1;
2077
2078         if (wpa_driver_wext_set_mode(drv, params->mode) < 0)
2079                 ret = -1;
2080         /* TODO: should consider getting wpa version and cipher/key_mgmt suites
2081          * from configuration, not from here, where only the selected suite is
2082          * available */
2083         if (wpa_driver_wext_set_gen_ie(drv, params->wpa_ie, params->wpa_ie_len)
2084             < 0)
2085                 ret = -1;
2086         if (params->wpa_ie == NULL || params->wpa_ie_len == 0)
2087                 value = IW_AUTH_WPA_VERSION_DISABLED;
2088         else if (params->wpa_ie[0] == WLAN_EID_RSN)
2089                 value = IW_AUTH_WPA_VERSION_WPA2;
2090         else
2091                 value = IW_AUTH_WPA_VERSION_WPA;
2092         if (wpa_driver_wext_set_auth_param(drv,
2093                                            IW_AUTH_WPA_VERSION, value) < 0)
2094                 ret = -1;
2095         value = wpa_driver_wext_cipher2wext(params->pairwise_suite);
2096         if (wpa_driver_wext_set_auth_param(drv,
2097                                            IW_AUTH_CIPHER_PAIRWISE, value) < 0)
2098                 ret = -1;
2099         value = wpa_driver_wext_cipher2wext(params->group_suite);
2100         if (wpa_driver_wext_set_auth_param(drv,
2101                                            IW_AUTH_CIPHER_GROUP, value) < 0)
2102                 ret = -1;
2103         value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite);
2104         if (wpa_driver_wext_set_auth_param(drv,
2105                                            IW_AUTH_KEY_MGMT, value) < 0)
2106                 ret = -1;
2107         value = params->key_mgmt_suite != KEY_MGMT_NONE ||
2108                 params->pairwise_suite != CIPHER_NONE ||
2109                 params->group_suite != CIPHER_NONE ||
2110                 params->wpa_ie_len;
2111         if (wpa_driver_wext_set_auth_param(drv,
2112                                            IW_AUTH_PRIVACY_INVOKED, value) < 0)
2113                 ret = -1;
2114
2115         /* Allow unencrypted EAPOL messages even if pairwise keys are set when
2116          * not using WPA. IEEE 802.1X specifies that these frames are not
2117          * encrypted, but WPA encrypts them when pairwise keys are in use. */
2118         if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
2119             params->key_mgmt_suite == KEY_MGMT_PSK)
2120                 allow_unencrypted_eapol = 0;
2121         else
2122                 allow_unencrypted_eapol = 1;
2123         
2124         if (wpa_driver_wext_set_auth_param(drv,
2125                                            IW_AUTH_RX_UNENCRYPTED_EAPOL,
2126                                            allow_unencrypted_eapol) < 0)
2127                 ret = -1;
2128         if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0)
2129                 ret = -1;
2130         if (wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
2131                 ret = -1;
2132         if (params->bssid &&
2133             wpa_driver_wext_set_bssid(drv, params->bssid) < 0)
2134                 ret = -1;
2135
2136         return ret;
2137 }
2138
2139
2140 static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg)
2141 {
2142         struct wpa_driver_wext_data *drv = priv;
2143         int algs = 0, res;
2144
2145         if (auth_alg & AUTH_ALG_OPEN_SYSTEM)
2146                 algs |= IW_AUTH_ALG_OPEN_SYSTEM;
2147         if (auth_alg & AUTH_ALG_SHARED_KEY)
2148                 algs |= IW_AUTH_ALG_SHARED_KEY;
2149         if (auth_alg & AUTH_ALG_LEAP)
2150                 algs |= IW_AUTH_ALG_LEAP;
2151         if (algs == 0) {
2152                 /* at least one algorithm should be set */
2153                 algs = IW_AUTH_ALG_OPEN_SYSTEM;
2154         }
2155
2156         res = wpa_driver_wext_set_auth_param(drv, IW_AUTH_80211_AUTH_ALG,
2157                                              algs);
2158         drv->auth_alg_fallback = res == -2;
2159         return res;
2160 }
2161
2162
2163 /**
2164  * wpa_driver_wext_set_mode - Set wireless mode (infra/adhoc), SIOCSIWMODE
2165  * @priv: Pointer to private wext data from wpa_driver_wext_init()
2166  * @mode: 0 = infra/BSS (associate with an AP), 1 = adhoc/IBSS
2167  * Returns: 0 on success, -1 on failure
2168  */
2169 int wpa_driver_wext_set_mode(void *priv, int mode)
2170 {
2171         struct wpa_driver_wext_data *drv = priv;
2172         struct iwreq iwr;
2173         int ret = 0;
2174
2175         os_memset(&iwr, 0, sizeof(iwr));
2176         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2177         iwr.u.mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
2178
2179         if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
2180                 perror("ioctl[SIOCSIWMODE]");
2181                 ret = -1;
2182         }
2183
2184         return ret;
2185 }
2186
2187
2188 static int wpa_driver_wext_pmksa(struct wpa_driver_wext_data *drv,
2189                                  u32 cmd, const u8 *bssid, const u8 *pmkid)
2190 {
2191         struct iwreq iwr;
2192         struct iw_pmksa pmksa;
2193         int ret = 0;
2194
2195         os_memset(&iwr, 0, sizeof(iwr));
2196         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2197         os_memset(&pmksa, 0, sizeof(pmksa));
2198         pmksa.cmd = cmd;
2199         pmksa.bssid.sa_family = ARPHRD_ETHER;
2200         if (bssid)
2201                 os_memcpy(pmksa.bssid.sa_data, bssid, ETH_ALEN);
2202         if (pmkid)
2203                 os_memcpy(pmksa.pmkid, pmkid, IW_PMKID_LEN);
2204         iwr.u.data.pointer = (caddr_t) &pmksa;
2205         iwr.u.data.length = sizeof(pmksa);
2206
2207         if (ioctl(drv->ioctl_sock, SIOCSIWPMKSA, &iwr) < 0) {
2208                 if (errno != EOPNOTSUPP)
2209                         perror("ioctl[SIOCSIWPMKSA]");
2210                 ret = -1;
2211         }
2212
2213         return ret;
2214 }
2215
2216
2217 static int wpa_driver_wext_add_pmkid(void *priv, const u8 *bssid,
2218                                      const u8 *pmkid)
2219 {
2220         struct wpa_driver_wext_data *drv = priv;
2221         return wpa_driver_wext_pmksa(drv, IW_PMKSA_ADD, bssid, pmkid);
2222 }
2223
2224
2225 static int wpa_driver_wext_remove_pmkid(void *priv, const u8 *bssid,
2226                                         const u8 *pmkid)
2227 {
2228         struct wpa_driver_wext_data *drv = priv;
2229         return wpa_driver_wext_pmksa(drv, IW_PMKSA_REMOVE, bssid, pmkid);
2230 }
2231
2232
2233 static int wpa_driver_wext_flush_pmkid(void *priv)
2234 {
2235         struct wpa_driver_wext_data *drv = priv;
2236         return wpa_driver_wext_pmksa(drv, IW_PMKSA_FLUSH, NULL, NULL);
2237 }
2238
2239
2240 static int wpa_driver_wext_get_capa(void *priv, struct wpa_driver_capa *capa)
2241 {
2242         struct wpa_driver_wext_data *drv = priv;
2243         if (!drv->has_capability)
2244                 return -1;
2245         os_memcpy(capa, &drv->capa, sizeof(*capa));
2246         return 0;
2247 }
2248
2249
2250 int wpa_driver_wext_alternative_ifindex(struct wpa_driver_wext_data *drv,
2251                                         const char *ifname)
2252 {
2253         if (ifname == NULL) {
2254                 drv->ifindex2 = -1;
2255                 return 0;
2256         }
2257
2258         drv->ifindex2 = if_nametoindex(ifname);
2259         if (drv->ifindex2 <= 0)
2260                 return -1;
2261
2262         wpa_printf(MSG_DEBUG, "Added alternative ifindex %d (%s) for "
2263                    "wireless events", drv->ifindex2, ifname);
2264
2265         return 0;
2266 }
2267
2268
2269 int wpa_driver_wext_set_operstate(void *priv, int state)
2270 {
2271         struct wpa_driver_wext_data *drv = priv;
2272
2273         wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
2274                    __func__, drv->operstate, state, state ? "UP" : "DORMANT");
2275         drv->operstate = state;
2276         return wpa_driver_wext_send_oper_ifla(
2277                 drv, -1, state ? IF_OPER_UP : IF_OPER_DORMANT);
2278 }
2279
2280
2281 #ifdef CONFIG_CLIENT_MLME
2282 static int hostapd_ioctl(struct wpa_driver_wext_data *drv,
2283                          struct prism2_hostapd_param *param, int len)
2284 {
2285         struct iwreq iwr;
2286
2287         os_memset(&iwr, 0, sizeof(iwr));
2288         os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
2289         iwr.u.data.pointer = (caddr_t) param;
2290         iwr.u.data.length = len;
2291
2292         if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
2293                 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
2294                 return -1;
2295         }
2296
2297         return 0;
2298 }
2299
2300
2301 static struct wpa_hw_modes *
2302 wpa_driver_wext_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
2303 {
2304         struct wpa_driver_wext_data *drv = priv;
2305         struct prism2_hostapd_param *param;
2306         u8 *pos, *end;
2307         struct wpa_hw_modes *modes = NULL;
2308         int i;
2309
2310         param = os_zalloc(PRISM2_HOSTAPD_MAX_BUF_SIZE);
2311         if (param == NULL)
2312                 return NULL;
2313         param->cmd = PRISM2_HOSTAPD_GET_HW_FEATURES;
2314
2315         if (hostapd_ioctl(drv, param, PRISM2_HOSTAPD_MAX_BUF_SIZE) < 0) {
2316                 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
2317                 goto out;
2318         }
2319
2320         *num_modes = param->u.hw_features.num_modes;
2321         *flags = param->u.hw_features.flags;
2322
2323         pos = param->u.hw_features.data;
2324         end = pos + PRISM2_HOSTAPD_MAX_BUF_SIZE -
2325                 (param->u.hw_features.data - (u8 *) param);
2326
2327         modes = os_zalloc(*num_modes * sizeof(struct wpa_hw_modes));
2328         if (modes == NULL)
2329                 goto out;
2330
2331         for (i = 0; i < *num_modes; i++) {
2332                 struct hostapd_ioctl_hw_modes_hdr *hdr;
2333                 struct wpa_hw_modes *feature;
2334                 int clen, rlen;
2335
2336                 hdr = (struct hostapd_ioctl_hw_modes_hdr *) pos;
2337                 pos = (u8 *) (hdr + 1);
2338                 clen = hdr->num_channels * sizeof(struct wpa_channel_data);
2339                 rlen = hdr->num_rates * sizeof(struct wpa_rate_data);
2340
2341                 feature = &modes[i];
2342                 switch (hdr->mode) {
2343                 case MODE_IEEE80211A:
2344                         feature->mode = WPA_MODE_IEEE80211A;
2345                         break;
2346                 case MODE_IEEE80211B:
2347                         feature->mode = WPA_MODE_IEEE80211B;
2348                         break;
2349                 case MODE_IEEE80211G:
2350                         feature->mode = WPA_MODE_IEEE80211G;
2351                         break;
2352                 case MODE_ATHEROS_TURBO:
2353                 case MODE_ATHEROS_TURBOG:
2354                         wpa_printf(MSG_ERROR, "Skip unsupported hw_mode=%d in "
2355                                    "get_hw_features data", hdr->mode);
2356                         pos += clen + rlen;
2357                         continue;
2358                 default:
2359                         wpa_printf(MSG_ERROR, "Unknown hw_mode=%d in "
2360                                    "get_hw_features data", hdr->mode);
2361                         wpa_supplicant_sta_free_hw_features(modes, *num_modes);
2362                         modes = NULL;
2363                         break;
2364                 }
2365                 feature->num_channels = hdr->num_channels;
2366                 feature->num_rates = hdr->num_rates;
2367
2368                 feature->channels = os_malloc(clen);
2369                 feature->rates = os_malloc(rlen);
2370                 if (!feature->channels || !feature->rates ||
2371                     pos + clen + rlen > end) {
2372                         wpa_supplicant_sta_free_hw_features(modes, *num_modes);
2373                         modes = NULL;
2374                         break;
2375                 }
2376
2377                 os_memcpy(feature->channels, pos, clen);
2378                 pos += clen;
2379                 os_memcpy(feature->rates, pos, rlen);
2380                 pos += rlen;
2381         }
2382
2383 out:
2384         os_free(param);
2385         return modes;
2386 }
2387
2388
2389 int wpa_driver_wext_set_channel(void *priv, wpa_hw_mode phymode, int chan,
2390                                 int freq)
2391 {
2392         return wpa_driver_wext_set_freq(priv, freq);
2393 }
2394
2395
2396 static void wpa_driver_wext_mlme_read(int sock, void *eloop_ctx,
2397                                       void *sock_ctx)
2398 {
2399         struct wpa_driver_wext_data *drv = eloop_ctx;
2400         int len;
2401         unsigned char buf[3000];
2402         struct ieee80211_frame_info *fi;
2403         struct ieee80211_rx_status rx_status;
2404
2405         len = recv(sock, buf, sizeof(buf), 0);
2406         if (len < 0) {
2407                 perror("recv[MLME]");
2408                 return;
2409         }
2410
2411         if (len < (int) sizeof(struct ieee80211_frame_info)) {
2412                 wpa_printf(MSG_DEBUG, "WEXT: Too short MLME frame (len=%d)",
2413                            len);
2414                 return;
2415         }
2416
2417         fi = (struct ieee80211_frame_info *) buf;
2418         if (ntohl(fi->version) != IEEE80211_FI_VERSION) {
2419                 wpa_printf(MSG_DEBUG, "WEXT: Invalid MLME frame info version "
2420                            "0x%x", ntohl(fi->version));
2421                 return;
2422         }
2423
2424         os_memset(&rx_status, 0, sizeof(rx_status));
2425         rx_status.ssi = ntohl(fi->ssi_signal);
2426         rx_status.channel = ntohl(fi->channel);
2427
2428         wpa_supplicant_sta_rx(drv->ctx,
2429                               buf + sizeof(struct ieee80211_frame_info),
2430                               len - sizeof(struct ieee80211_frame_info),
2431                               &rx_status);
2432 }
2433
2434
2435 static int wpa_driver_wext_open_mlme(struct wpa_driver_wext_data *drv)
2436 {
2437         int flags, ifindex, s;
2438         struct sockaddr_ll addr;
2439         struct ifreq ifr;
2440
2441         if (wpa_driver_prism2_param_set(drv, PRISM2_PARAM_USER_SPACE_MLME, 1) <
2442             0) {
2443                 wpa_printf(MSG_ERROR, "WEXT: Failed to configure driver to "
2444                            "use user space MLME");
2445                 return -1;
2446         }
2447
2448         if (wpa_driver_prism2_param_set(drv, PRISM2_PARAM_MGMT_IF, 1) < 0) {
2449                 wpa_printf(MSG_ERROR, "WEXT: Failed to add management "
2450                            "interface for user space MLME");
2451                 return -1;
2452         }
2453
2454         ifindex = wpa_driver_prism2_param_get(drv, PRISM2_PARAM_MGMT_IF);
2455         if (ifindex <= 0) {
2456                 wpa_printf(MSG_ERROR, "WEXT: MLME management device not "
2457                            "found");
2458                 return -1;
2459         }
2460
2461         os_memset(&ifr, 0, sizeof(ifr));
2462         ifr.ifr_ifindex = ifindex;
2463         if (ioctl(drv->ioctl_sock, SIOCGIFNAME, &ifr) != 0) {
2464                 perror("ioctl(SIOCGIFNAME)");
2465                 return -1;
2466         }
2467         os_strlcpy(drv->mlmedev, ifr.ifr_name, sizeof(drv->mlmedev));
2468         wpa_printf(MSG_DEBUG, "WEXT: MLME management device '%s'",
2469                    drv->mlmedev);
2470
2471         if (wpa_driver_wext_get_ifflags_ifname(drv, drv->mlmedev, &flags) != 0
2472             || wpa_driver_wext_set_ifflags_ifname(drv, drv->mlmedev,
2473                                                   flags | IFF_UP) != 0) {
2474                 wpa_printf(MSG_ERROR, "WEXT: Could not set interface "
2475                            "'%s' UP", drv->mlmedev);
2476                 return -1;
2477         }
2478
2479         s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
2480         if (s < 0) {
2481                 perror("socket[PF_PACKET,SOCK_RAW]");
2482                 return -1;
2483         }
2484
2485         os_memset(&addr, 0, sizeof(addr));
2486         addr.sll_family = AF_PACKET;
2487         addr.sll_ifindex = ifindex;
2488
2489         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2490                 perror("bind(MLME)");
2491                 return -1;
2492         }
2493
2494         if (eloop_register_read_sock(s, wpa_driver_wext_mlme_read, drv, NULL))
2495         {
2496                 wpa_printf(MSG_ERROR, "WEXT: Could not register MLME read "
2497                            "socket");
2498                 close(s);
2499                 return -1;
2500         }
2501
2502         return s;
2503 }
2504
2505
2506 static int wpa_driver_wext_send_mlme(void *priv, const u8 *data,
2507                                      size_t data_len)
2508 {
2509         struct wpa_driver_wext_data *drv = priv;
2510         int ret;
2511
2512         ret = send(drv->mlme_sock, data, data_len, 0);
2513         if (ret < 0) {
2514                 perror("send[MLME]");
2515                 return -1;
2516         }
2517
2518         return 0;
2519 }
2520
2521
2522 static int wpa_driver_wext_mlme_add_sta(void *priv, const u8 *addr,
2523                                         const u8 *supp_rates,
2524                                         size_t supp_rates_len)
2525 {
2526         struct wpa_driver_wext_data *drv = priv;
2527         struct prism2_hostapd_param param;
2528         size_t len;
2529
2530         os_memset(&param, 0, sizeof(param));
2531         param.cmd = PRISM2_HOSTAPD_ADD_STA;
2532         os_memcpy(param.sta_addr, addr, ETH_ALEN);
2533         len = supp_rates_len;
2534         if (len > sizeof(param.u.add_sta.supp_rates))
2535                 len = sizeof(param.u.add_sta.supp_rates);
2536         os_memcpy(param.u.add_sta.supp_rates, supp_rates, len);
2537         return hostapd_ioctl(drv, &param, sizeof(param));
2538 }
2539
2540
2541 static int wpa_driver_wext_mlme_remove_sta(void *priv, const u8 *addr)
2542 {
2543         struct wpa_driver_wext_data *drv = priv;
2544         struct prism2_hostapd_param param;
2545
2546         os_memset(&param, 0, sizeof(param));
2547         param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
2548         os_memcpy(param.sta_addr, addr, ETH_ALEN);
2549         return hostapd_ioctl(drv, &param, sizeof(param));
2550 }
2551
2552 #endif /* CONFIG_CLIENT_MLME */
2553
2554
2555 static int wpa_driver_wext_set_param(void *priv, const char *param)
2556 {
2557 #ifdef CONFIG_CLIENT_MLME
2558         struct wpa_driver_wext_data *drv = priv;
2559
2560         if (param == NULL)
2561                 return 0;
2562
2563         wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
2564
2565         if (os_strstr(param, "use_mlme=1")) {
2566                 wpa_printf(MSG_DEBUG, "WEXT: Using user space MLME");
2567                 drv->capa.flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME;
2568
2569                 drv->mlme_sock = wpa_driver_wext_open_mlme(drv);
2570                 if (drv->mlme_sock < 0)
2571                         return -1;
2572         }
2573 #endif /* CONFIG_CLIENT_MLME */
2574
2575         return 0;
2576 }
2577
2578
2579 int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv)
2580 {
2581         return drv->we_version_compiled;
2582 }
2583
2584
2585 const struct wpa_driver_ops wpa_driver_wext_ops = {
2586         .name = "wext",
2587         .desc = "Linux wireless extensions (generic)",
2588         .get_bssid = wpa_driver_wext_get_bssid,
2589         .get_ssid = wpa_driver_wext_get_ssid,
2590         .set_wpa = wpa_driver_wext_set_wpa,
2591         .set_key = wpa_driver_wext_set_key,
2592         .set_countermeasures = wpa_driver_wext_set_countermeasures,
2593         .set_drop_unencrypted = wpa_driver_wext_set_drop_unencrypted,
2594         .scan = wpa_driver_wext_scan,
2595         .get_scan_results2 = wpa_driver_wext_get_scan_results,
2596         .deauthenticate = wpa_driver_wext_deauthenticate,
2597         .disassociate = wpa_driver_wext_disassociate,
2598         .associate = wpa_driver_wext_associate,
2599         .set_auth_alg = wpa_driver_wext_set_auth_alg,
2600         .init = wpa_driver_wext_init,
2601         .deinit = wpa_driver_wext_deinit,
2602         .set_param = wpa_driver_wext_set_param,
2603         .add_pmkid = wpa_driver_wext_add_pmkid,
2604         .remove_pmkid = wpa_driver_wext_remove_pmkid,
2605         .flush_pmkid = wpa_driver_wext_flush_pmkid,
2606         .get_capa = wpa_driver_wext_get_capa,
2607         .set_operstate = wpa_driver_wext_set_operstate,
2608 #ifdef CONFIG_CLIENT_MLME
2609         .get_hw_feature_data = wpa_driver_wext_get_hw_feature_data,
2610         .set_channel = wpa_driver_wext_set_channel,
2611         .set_ssid = wpa_driver_wext_set_ssid,
2612         .set_bssid = wpa_driver_wext_set_bssid,
2613         .send_mlme = wpa_driver_wext_send_mlme,
2614         .mlme_add_sta = wpa_driver_wext_mlme_add_sta,
2615         .mlme_remove_sta = wpa_driver_wext_mlme_remove_sta,
2616 #endif /* CONFIG_CLIENT_MLME */
2617 };