• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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