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