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