Home | History | Annotate | Download | only in wpa_supplicant_lib
      1 /*
      2  * WPA Supplicant - driver interaction with generic Linux Wireless Extensions
      3  * Copyright (c) 2003-2007, Jouni Malinen <j (at) 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 
     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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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  */
   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