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