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