LCOV - code coverage report
Current view: top level - src/drivers - driver_nl80211.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1426431149 Lines: 3361 4330 77.6 %
Date: 2015-03-15 Functions: 234 245 95.5 %

          Line data    Source code
       1             : /*
       2             :  * Driver interaction with Linux nl80211/cfg80211
       3             :  * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
       4             :  * Copyright (c) 2003-2004, Instant802 Networks, Inc.
       5             :  * Copyright (c) 2005-2006, Devicescape Software, Inc.
       6             :  * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
       7             :  * Copyright (c) 2009-2010, Atheros Communications
       8             :  *
       9             :  * This software may be distributed under the terms of the BSD license.
      10             :  * See README for more details.
      11             :  */
      12             : 
      13             : #include "includes.h"
      14             : #include <sys/types.h>
      15             : #include <fcntl.h>
      16             : #include <net/if.h>
      17             : #include <netlink/genl/genl.h>
      18             : #include <netlink/genl/ctrl.h>
      19             : #ifdef CONFIG_LIBNL3_ROUTE
      20             : #include <netlink/route/neighbour.h>
      21             : #endif /* CONFIG_LIBNL3_ROUTE */
      22             : #include <linux/rtnetlink.h>
      23             : #include <netpacket/packet.h>
      24             : #include <linux/errqueue.h>
      25             : 
      26             : #include "common.h"
      27             : #include "eloop.h"
      28             : #include "common/qca-vendor.h"
      29             : #include "common/qca-vendor-attr.h"
      30             : #include "common/ieee802_11_defs.h"
      31             : #include "common/ieee802_11_common.h"
      32             : #include "l2_packet/l2_packet.h"
      33             : #include "netlink.h"
      34             : #include "linux_defines.h"
      35             : #include "linux_ioctl.h"
      36             : #include "radiotap.h"
      37             : #include "radiotap_iter.h"
      38             : #include "rfkill.h"
      39             : #include "driver_nl80211.h"
      40             : 
      41             : 
      42             : #ifndef CONFIG_LIBNL20
      43             : /*
      44             :  * libnl 1.1 has a bug, it tries to allocate socket numbers densely
      45             :  * but when you free a socket again it will mess up its bitmap and
      46             :  * and use the wrong number the next time it needs a socket ID.
      47             :  * Therefore, we wrap the handle alloc/destroy and add our own pid
      48             :  * accounting.
      49             :  */
      50             : static uint32_t port_bitmap[32] = { 0 };
      51             : 
      52             : static struct nl_handle *nl80211_handle_alloc(void *cb)
      53             : {
      54             :         struct nl_handle *handle;
      55             :         uint32_t pid = getpid() & 0x3FFFFF;
      56             :         int i;
      57             : 
      58             :         handle = nl_handle_alloc_cb(cb);
      59             : 
      60             :         for (i = 0; i < 1024; i++) {
      61             :                 if (port_bitmap[i / 32] & (1 << (i % 32)))
      62             :                         continue;
      63             :                 port_bitmap[i / 32] |= 1 << (i % 32);
      64             :                 pid += i << 22;
      65             :                 break;
      66             :         }
      67             : 
      68             :         nl_socket_set_local_port(handle, pid);
      69             : 
      70             :         return handle;
      71             : }
      72             : 
      73             : static void nl80211_handle_destroy(struct nl_handle *handle)
      74             : {
      75             :         uint32_t port = nl_socket_get_local_port(handle);
      76             : 
      77             :         port >>= 22;
      78             :         port_bitmap[port / 32] &= ~(1 << (port % 32));
      79             : 
      80             :         nl_handle_destroy(handle);
      81             : }
      82             : #endif /* CONFIG_LIBNL20 */
      83             : 
      84             : 
      85             : #ifdef ANDROID
      86             : /* system/core/libnl_2 does not include nl_socket_set_nonblocking() */
      87             : #undef nl_socket_set_nonblocking
      88             : #define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h)
      89             : 
      90             : #define genl_ctrl_resolve android_genl_ctrl_resolve
      91             : #endif /* ANDROID */
      92             : 
      93             : 
      94        4777 : static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
      95             : {
      96             :         struct nl_handle *handle;
      97             : 
      98        4777 :         handle = nl80211_handle_alloc(cb);
      99        4777 :         if (handle == NULL) {
     100           0 :                 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
     101             :                            "callbacks (%s)", dbg);
     102           0 :                 return NULL;
     103             :         }
     104             : 
     105        4777 :         if (genl_connect(handle)) {
     106           0 :                 wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
     107             :                            "netlink (%s)", dbg);
     108           0 :                 nl80211_handle_destroy(handle);
     109           0 :                 return NULL;
     110             :         }
     111             : 
     112        4777 :         return handle;
     113             : }
     114             : 
     115             : 
     116        4777 : static void nl_destroy_handles(struct nl_handle **handle)
     117             : {
     118        4777 :         if (*handle == NULL)
     119        4777 :                 return;
     120        4777 :         nl80211_handle_destroy(*handle);
     121        4777 :         *handle = NULL;
     122             : }
     123             : 
     124             : 
     125             : #if __WORDSIZE == 64
     126             : #define ELOOP_SOCKET_INVALID    (intptr_t) 0x8888888888888889ULL
     127             : #else
     128             : #define ELOOP_SOCKET_INVALID    (intptr_t) 0x88888889ULL
     129             : #endif
     130             : 
     131        4749 : static void nl80211_register_eloop_read(struct nl_handle **handle,
     132             :                                         eloop_sock_handler handler,
     133             :                                         void *eloop_data)
     134             : {
     135             : #ifdef CONFIG_LIBNL20
     136             :         /*
     137             :          * libnl uses a pretty small buffer (32 kB that gets converted to 64 kB)
     138             :          * by default. It is possible to hit that limit in some cases where
     139             :          * operations are blocked, e.g., with a burst of Deauthentication frames
     140             :          * to hostapd and STA entry deletion. Try to increase the buffer to make
     141             :          * this less likely to occur.
     142             :          */
     143        4749 :         if (nl_socket_set_buffer_size(*handle, 262144, 0) < 0) {
     144           0 :                 wpa_printf(MSG_DEBUG,
     145             :                            "nl80211: Could not set nl_socket RX buffer size: %s",
     146           0 :                            strerror(errno));
     147             :                 /* continue anyway with the default (smaller) buffer */
     148             :         }
     149             : #endif /* CONFIG_LIBNL20 */
     150             : 
     151        4749 :         nl_socket_set_nonblocking(*handle);
     152        4749 :         eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
     153             :                                  eloop_data, *handle);
     154        4749 :         *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
     155        4749 : }
     156             : 
     157             : 
     158        4749 : static void nl80211_destroy_eloop_handle(struct nl_handle **handle)
     159             : {
     160        4749 :         *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
     161        4749 :         eloop_unregister_read_sock(nl_socket_get_fd(*handle));
     162        4749 :         nl_destroy_handles(handle);
     163        4749 : }
     164             : 
     165             : 
     166             : static void nl80211_global_deinit(void *priv);
     167             : static void nl80211_check_global(struct nl80211_global *global);
     168             : 
     169             : static void wpa_driver_nl80211_deinit(struct i802_bss *bss);
     170             : static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
     171             :                                             struct hostapd_freq_params *freq);
     172             : 
     173             : static int
     174             : wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
     175             :                                    const u8 *set_addr, int first,
     176             :                                    const char *driver_params);
     177             : static int nl80211_send_frame_cmd(struct i802_bss *bss,
     178             :                                   unsigned int freq, unsigned int wait,
     179             :                                   const u8 *buf, size_t buf_len, u64 *cookie,
     180             :                                   int no_cck, int no_ack, int offchanok);
     181             : static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
     182             :                                                int report);
     183             : 
     184             : static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
     185             : static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
     186             : static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
     187             : 
     188             : static int nl80211_set_channel(struct i802_bss *bss,
     189             :                                struct hostapd_freq_params *freq, int set_chan);
     190             : static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
     191             :                                      int ifindex, int disabled);
     192             : 
     193             : static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
     194             :                               int reset_mode);
     195             : 
     196             : static int i802_set_iface_flags(struct i802_bss *bss, int up);
     197             : static int nl80211_set_param(void *priv, const char *param);
     198             : 
     199             : 
     200             : /* Converts nl80211_chan_width to a common format */
     201         121 : enum chan_width convert2width(int width)
     202             : {
     203         121 :         switch (width) {
     204             :         case NL80211_CHAN_WIDTH_20_NOHT:
     205          17 :                 return CHAN_WIDTH_20_NOHT;
     206             :         case NL80211_CHAN_WIDTH_20:
     207          68 :                 return CHAN_WIDTH_20;
     208             :         case NL80211_CHAN_WIDTH_40:
     209          24 :                 return CHAN_WIDTH_40;
     210             :         case NL80211_CHAN_WIDTH_80:
     211           7 :                 return CHAN_WIDTH_80;
     212             :         case NL80211_CHAN_WIDTH_80P80:
     213           1 :                 return CHAN_WIDTH_80P80;
     214             :         case NL80211_CHAN_WIDTH_160:
     215           4 :                 return CHAN_WIDTH_160;
     216             :         }
     217           0 :         return CHAN_WIDTH_UNKNOWN;
     218             : }
     219             : 
     220             : 
     221       37707 : int is_ap_interface(enum nl80211_iftype nlmode)
     222             : {
     223       37707 :         return nlmode == NL80211_IFTYPE_AP ||
     224             :                 nlmode == NL80211_IFTYPE_P2P_GO;
     225             : }
     226             : 
     227             : 
     228       12499 : int is_sta_interface(enum nl80211_iftype nlmode)
     229             : {
     230       12499 :         return nlmode == NL80211_IFTYPE_STATION ||
     231             :                 nlmode == NL80211_IFTYPE_P2P_CLIENT;
     232             : }
     233             : 
     234             : 
     235        9059 : static int is_p2p_net_interface(enum nl80211_iftype nlmode)
     236             : {
     237        9059 :         return nlmode == NL80211_IFTYPE_P2P_CLIENT ||
     238             :                 nlmode == NL80211_IFTYPE_P2P_GO;
     239             : }
     240             : 
     241             : 
     242          46 : struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv,
     243             :                                   int ifindex)
     244             : {
     245             :         struct i802_bss *bss;
     246             : 
     247          46 :         for (bss = drv->first_bss; bss; bss = bss->next) {
     248          46 :                 if (bss->ifindex == ifindex)
     249          46 :                         return bss;
     250             :         }
     251             : 
     252           0 :         return NULL;
     253             : }
     254             : 
     255             : 
     256        6993 : static int is_mesh_interface(enum nl80211_iftype nlmode)
     257             : {
     258        6993 :         return nlmode == NL80211_IFTYPE_MESH_POINT;
     259             : }
     260             : 
     261             : 
     262        9786 : void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
     263             : {
     264        9786 :         if (drv->associated)
     265        2556 :                 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
     266        9786 :         drv->associated = 0;
     267        9786 :         os_memset(drv->bssid, 0, ETH_ALEN);
     268        9786 : }
     269             : 
     270             : 
     271             : /* nl80211 code */
     272      136900 : static int ack_handler(struct nl_msg *msg, void *arg)
     273             : {
     274      136900 :         int *err = arg;
     275      136900 :         *err = 0;
     276      136900 :         return NL_STOP;
     277             : }
     278             : 
     279       16192 : static int finish_handler(struct nl_msg *msg, void *arg)
     280             : {
     281       16192 :         int *ret = arg;
     282       16192 :         *ret = 0;
     283       16192 :         return NL_SKIP;
     284             : }
     285             : 
     286       26928 : static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
     287             :                          void *arg)
     288             : {
     289       26928 :         int *ret = arg;
     290       26928 :         *ret = err->error;
     291       26928 :         return NL_SKIP;
     292             : }
     293             : 
     294             : 
     295     1034007 : static int no_seq_check(struct nl_msg *msg, void *arg)
     296             : {
     297     1034007 :         return NL_OK;
     298             : }
     299             : 
     300             : 
     301        7435 : static void nl80211_nlmsg_clear(struct nl_msg *msg)
     302             : {
     303             :         /*
     304             :          * Clear nlmsg data, e.g., to make sure key material is not left in
     305             :          * heap memory for unnecessarily long time.
     306             :          */
     307        7435 :         if (msg) {
     308        7435 :                 struct nlmsghdr *hdr = nlmsg_hdr(msg);
     309        7435 :                 void *data = nlmsg_data(hdr);
     310             :                 /*
     311             :                  * This would use nlmsg_datalen() or the older nlmsg_len() if
     312             :                  * only libnl were to maintain a stable API.. Neither will work
     313             :                  * with all released versions, so just calculate the length
     314             :                  * here.
     315             :                  */
     316        7435 :                 int len = hdr->nlmsg_len - NLMSG_HDRLEN;
     317             : 
     318        7435 :                 os_memset(data, 0, len);
     319             :         }
     320        7435 : }
     321             : 
     322             : 
     323      180020 : static int send_and_recv(struct nl80211_global *global,
     324             :                          struct nl_handle *nl_handle, struct nl_msg *msg,
     325             :                          int (*valid_handler)(struct nl_msg *, void *),
     326             :                          void *valid_data)
     327             : {
     328             :         struct nl_cb *cb;
     329      180020 :         int err = -ENOMEM;
     330             : 
     331      180020 :         if (!msg)
     332           0 :                 return -ENOMEM;
     333             : 
     334      180020 :         cb = nl_cb_clone(global->nl_cb);
     335      180020 :         if (!cb)
     336           0 :                 goto out;
     337             : 
     338      180020 :         err = nl_send_auto_complete(nl_handle, msg);
     339      180020 :         if (err < 0)
     340           0 :                 goto out;
     341             : 
     342      180020 :         err = 1;
     343             : 
     344      180020 :         nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
     345      180020 :         nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
     346      180020 :         nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
     347             : 
     348      180020 :         if (valid_handler)
     349       67134 :                 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
     350             :                           valid_handler, valid_data);
     351             : 
     352      587422 :         while (err > 0) {
     353      227382 :                 int res = nl_recvmsgs(nl_handle, cb);
     354      227382 :                 if (res < 0) {
     355           0 :                         wpa_printf(MSG_INFO,
     356             :                                    "nl80211: %s->nl_recvmsgs failed: %d",
     357             :                                    __func__, res);
     358             :                 }
     359             :         }
     360             :  out:
     361      180020 :         nl_cb_put(cb);
     362      180020 :         if (!valid_handler && valid_data == (void *) -1)
     363        7435 :                 nl80211_nlmsg_clear(msg);
     364      180020 :         nlmsg_free(msg);
     365      180020 :         return err;
     366             : }
     367             : 
     368             : 
     369      145266 : int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
     370             :                        struct nl_msg *msg,
     371             :                        int (*valid_handler)(struct nl_msg *, void *),
     372             :                        void *valid_data)
     373             : {
     374      145266 :         return send_and_recv(drv->global, drv->global->nl, msg,
     375             :                              valid_handler, valid_data);
     376             : }
     377             : 
     378             : 
     379             : struct family_data {
     380             :         const char *group;
     381             :         int id;
     382             : };
     383             : 
     384             : 
     385        5024 : static int family_handler(struct nl_msg *msg, void *arg)
     386             : {
     387        5024 :         struct family_data *res = arg;
     388             :         struct nlattr *tb[CTRL_ATTR_MAX + 1];
     389        5024 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     390             :         struct nlattr *mcgrp;
     391             :         int i;
     392             : 
     393        5024 :         nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     394             :                   genlmsg_attrlen(gnlh, 0), NULL);
     395        5024 :         if (!tb[CTRL_ATTR_MCAST_GROUPS])
     396           0 :                 return NL_SKIP;
     397             : 
     398       35168 :         nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
     399             :                 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
     400       17584 :                 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
     401             :                           nla_len(mcgrp), NULL);
     402       35168 :                 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
     403       35168 :                     !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
     404       17584 :                     os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
     405             :                                res->group,
     406             :                                nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
     407       12560 :                         continue;
     408        5024 :                 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
     409        5024 :                 break;
     410             :         };
     411             : 
     412        5024 :         return NL_SKIP;
     413             : }
     414             : 
     415             : 
     416        5024 : static int nl_get_multicast_id(struct nl80211_global *global,
     417             :                                const char *family, const char *group)
     418             : {
     419             :         struct nl_msg *msg;
     420             :         int ret;
     421        5024 :         struct family_data res = { group, -ENOENT };
     422             : 
     423        5024 :         msg = nlmsg_alloc();
     424        5024 :         if (!msg)
     425           0 :                 return -ENOMEM;
     426        5024 :         if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
     427        5024 :                          0, 0, CTRL_CMD_GETFAMILY, 0) ||
     428        5024 :             nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
     429           0 :                 nlmsg_free(msg);
     430           0 :                 return -1;
     431             :         }
     432             : 
     433        5024 :         ret = send_and_recv(global, global->nl, msg, family_handler, &res);
     434        5024 :         if (ret == 0)
     435        5024 :                 ret = res.id;
     436        5024 :         return ret;
     437             : }
     438             : 
     439             : 
     440      174997 : void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
     441             :                    struct nl_msg *msg, int flags, uint8_t cmd)
     442             : {
     443      174997 :         return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
     444             :                            0, flags, cmd, 0);
     445             : }
     446             : 
     447             : 
     448       71952 : static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss)
     449             : {
     450       71952 :         if (bss->wdev_id_set)
     451         335 :                 return nla_put_u64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
     452       71617 :         return nla_put_u32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
     453             : }
     454             : 
     455             : 
     456       71952 : struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
     457             : {
     458             :         struct nl_msg *msg;
     459             : 
     460       71952 :         msg = nlmsg_alloc();
     461       71952 :         if (!msg)
     462           0 :                 return NULL;
     463             : 
     464      143904 :         if (!nl80211_cmd(bss->drv, msg, flags, cmd) ||
     465       71952 :             nl80211_set_iface_id(msg, bss) < 0) {
     466           0 :                 nlmsg_free(msg);
     467           0 :                 return NULL;
     468             :         }
     469             : 
     470       71952 :         return msg;
     471             : }
     472             : 
     473             : 
     474             : static struct nl_msg *
     475       82580 : nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
     476             :                     int flags, uint8_t cmd)
     477             : {
     478             :         struct nl_msg *msg;
     479             : 
     480       82580 :         msg = nlmsg_alloc();
     481       82580 :         if (!msg)
     482           0 :                 return NULL;
     483             : 
     484      165160 :         if (!nl80211_cmd(drv, msg, flags, cmd) ||
     485       82580 :             nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
     486           0 :                 nlmsg_free(msg);
     487           0 :                 return NULL;
     488             :         }
     489             : 
     490       82580 :         return msg;
     491             : }
     492             : 
     493             : 
     494       15400 : struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
     495             :                                 uint8_t cmd)
     496             : {
     497       15400 :         return nl80211_ifindex_msg(drv, drv->ifindex, flags, cmd);
     498             : }
     499             : 
     500             : 
     501       31498 : struct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd)
     502             : {
     503       31498 :         return nl80211_ifindex_msg(bss->drv, bss->ifindex, flags, cmd);
     504             : }
     505             : 
     506             : 
     507             : struct wiphy_idx_data {
     508             :         int wiphy_idx;
     509             :         enum nl80211_iftype nlmode;
     510             :         u8 *macaddr;
     511             : };
     512             : 
     513             : 
     514        7720 : static int netdev_info_handler(struct nl_msg *msg, void *arg)
     515             : {
     516             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
     517        7720 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     518        7720 :         struct wiphy_idx_data *info = arg;
     519             : 
     520        7720 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     521             :                   genlmsg_attrlen(gnlh, 0), NULL);
     522             : 
     523        7720 :         if (tb[NL80211_ATTR_WIPHY])
     524        7720 :                 info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
     525             : 
     526        7720 :         if (tb[NL80211_ATTR_IFTYPE])
     527        7720 :                 info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
     528             : 
     529        7720 :         if (tb[NL80211_ATTR_MAC] && info->macaddr)
     530           8 :                 os_memcpy(info->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
     531             :                           ETH_ALEN);
     532             : 
     533        7720 :         return NL_SKIP;
     534             : }
     535             : 
     536             : 
     537        2652 : int nl80211_get_wiphy_index(struct i802_bss *bss)
     538             : {
     539             :         struct nl_msg *msg;
     540        2652 :         struct wiphy_idx_data data = {
     541             :                 .wiphy_idx = -1,
     542             :                 .macaddr = NULL,
     543             :         };
     544             : 
     545        2652 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
     546           0 :                 return -1;
     547             : 
     548        2652 :         if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
     549        2652 :                 return data.wiphy_idx;
     550           0 :         return -1;
     551             : }
     552             : 
     553             : 
     554        5123 : static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
     555             : {
     556             :         struct nl_msg *msg;
     557        5123 :         struct wiphy_idx_data data = {
     558             :                 .nlmode = NL80211_IFTYPE_UNSPECIFIED,
     559             :                 .macaddr = NULL,
     560             :         };
     561             : 
     562        5123 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
     563           0 :                 return NL80211_IFTYPE_UNSPECIFIED;
     564             : 
     565        5123 :         if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
     566        5060 :                 return data.nlmode;
     567          63 :         return NL80211_IFTYPE_UNSPECIFIED;
     568             : }
     569             : 
     570             : 
     571           8 : static int nl80211_get_macaddr(struct i802_bss *bss)
     572             : {
     573             :         struct nl_msg *msg;
     574          16 :         struct wiphy_idx_data data = {
     575           8 :                 .macaddr = bss->addr,
     576             :         };
     577             : 
     578           8 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
     579           0 :                 return -1;
     580             : 
     581           8 :         return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data);
     582             : }
     583             : 
     584             : 
     585        1279 : static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
     586             :                                     struct nl80211_wiphy_data *w)
     587             : {
     588             :         struct nl_msg *msg;
     589             :         int ret;
     590             : 
     591        1279 :         msg = nlmsg_alloc();
     592        1279 :         if (!msg)
     593           0 :                 return -1;
     594             : 
     595        2558 :         if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS) ||
     596        1279 :             nla_put_u32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx)) {
     597           0 :                 nlmsg_free(msg);
     598           0 :                 return -1;
     599             :         }
     600             : 
     601        1279 :         ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);
     602        1279 :         if (ret) {
     603           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
     604             :                            "failed: ret=%d (%s)",
     605             :                            ret, strerror(-ret));
     606             :         }
     607        1279 :         return ret;
     608             : }
     609             : 
     610             : 
     611        5688 : static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle)
     612             : {
     613        5688 :         struct nl80211_wiphy_data *w = eloop_ctx;
     614             :         int res;
     615             : 
     616        5688 :         wpa_printf(MSG_EXCESSIVE, "nl80211: Beacon event message available");
     617             : 
     618        5688 :         res = nl_recvmsgs(handle, w->nl_cb);
     619        5688 :         if (res < 0) {
     620           0 :                 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
     621             :                            __func__, res);
     622             :         }
     623        5688 : }
     624             : 
     625             : 
     626        5684 : static int process_beacon_event(struct nl_msg *msg, void *arg)
     627             : {
     628        5684 :         struct nl80211_wiphy_data *w = arg;
     629             :         struct wpa_driver_nl80211_data *drv;
     630        5684 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
     631             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
     632             :         union wpa_event_data event;
     633             : 
     634        5684 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
     635             :                   genlmsg_attrlen(gnlh, 0), NULL);
     636             : 
     637        5684 :         if (gnlh->cmd != NL80211_CMD_FRAME) {
     638           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)",
     639           0 :                            gnlh->cmd);
     640           0 :                 return NL_SKIP;
     641             :         }
     642             : 
     643        5684 :         if (!tb[NL80211_ATTR_FRAME])
     644           0 :                 return NL_SKIP;
     645             : 
     646       11368 :         dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data,
     647             :                          wiphy_list) {
     648        5684 :                 os_memset(&event, 0, sizeof(event));
     649        5684 :                 event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);
     650        5684 :                 event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);
     651        5684 :                 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
     652             :         }
     653             : 
     654        5684 :         return NL_SKIP;
     655             : }
     656             : 
     657             : 
     658             : static struct nl80211_wiphy_data *
     659        1444 : nl80211_get_wiphy_data_ap(struct i802_bss *bss)
     660             : {
     661             :         static DEFINE_DL_LIST(nl80211_wiphys);
     662             :         struct nl80211_wiphy_data *w;
     663        1444 :         int wiphy_idx, found = 0;
     664             :         struct i802_bss *tmp_bss;
     665             : 
     666        1444 :         if (bss->wiphy_data != NULL)
     667           0 :                 return bss->wiphy_data;
     668             : 
     669        1444 :         wiphy_idx = nl80211_get_wiphy_index(bss);
     670             : 
     671        1615 :         dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) {
     672         336 :                 if (w->wiphy_idx == wiphy_idx)
     673         165 :                         goto add;
     674             :         }
     675             : 
     676             :         /* alloc new one */
     677        1279 :         w = os_zalloc(sizeof(*w));
     678        1279 :         if (w == NULL)
     679           0 :                 return NULL;
     680        1279 :         w->wiphy_idx = wiphy_idx;
     681        1279 :         dl_list_init(&w->bsss);
     682        1279 :         dl_list_init(&w->drvs);
     683             : 
     684        1279 :         w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
     685        1279 :         if (!w->nl_cb) {
     686           0 :                 os_free(w);
     687           0 :                 return NULL;
     688             :         }
     689        1279 :         nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
     690        1279 :         nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,
     691             :                   w);
     692             : 
     693        1279 :         w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
     694             :                                          "wiphy beacons");
     695        1279 :         if (w->nl_beacons == NULL) {
     696           0 :                 os_free(w);
     697           0 :                 return NULL;
     698             :         }
     699             : 
     700        1279 :         if (nl80211_register_beacons(bss->drv, w)) {
     701           0 :                 nl_destroy_handles(&w->nl_beacons);
     702           0 :                 os_free(w);
     703           0 :                 return NULL;
     704             :         }
     705             : 
     706        1279 :         nl80211_register_eloop_read(&w->nl_beacons, nl80211_recv_beacons, w);
     707             : 
     708        1279 :         dl_list_add(&nl80211_wiphys, &w->list);
     709             : 
     710             : add:
     711             :         /* drv entry for this bss already there? */
     712        5350 :         dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
     713        3947 :                 if (tmp_bss->drv == bss->drv) {
     714          41 :                         found = 1;
     715          41 :                         break;
     716             :                 }
     717             :         }
     718             :         /* if not add it */
     719        1444 :         if (!found)
     720        1403 :                 dl_list_add(&w->drvs, &bss->drv->wiphy_list);
     721             : 
     722        1444 :         dl_list_add(&w->bsss, &bss->wiphy_list);
     723        1444 :         bss->wiphy_data = w;
     724        1444 :         return w;
     725             : }
     726             : 
     727             : 
     728        2259 : static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
     729             : {
     730        2259 :         struct nl80211_wiphy_data *w = bss->wiphy_data;
     731             :         struct i802_bss *tmp_bss;
     732        2259 :         int found = 0;
     733             : 
     734        2259 :         if (w == NULL)
     735         815 :                 return;
     736        1444 :         bss->wiphy_data = NULL;
     737        1444 :         dl_list_del(&bss->wiphy_list);
     738             : 
     739             :         /* still any for this drv present? */
     740        5350 :         dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
     741        3947 :                 if (tmp_bss->drv == bss->drv) {
     742          41 :                         found = 1;
     743          41 :                         break;
     744             :                 }
     745             :         }
     746             :         /* if not remove it */
     747        1444 :         if (!found)
     748        1403 :                 dl_list_del(&bss->drv->wiphy_list);
     749             : 
     750        1444 :         if (!dl_list_empty(&w->bsss))
     751         165 :                 return;
     752             : 
     753        1279 :         nl80211_destroy_eloop_handle(&w->nl_beacons);
     754             : 
     755        1279 :         nl_cb_put(w->nl_cb);
     756        1279 :         dl_list_del(&w->list);
     757        1279 :         os_free(w);
     758             : }
     759             : 
     760             : 
     761        4450 : static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
     762             : {
     763        4450 :         struct i802_bss *bss = priv;
     764        4450 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     765        4450 :         if (!drv->associated)
     766           0 :                 return -1;
     767        4450 :         os_memcpy(bssid, drv->bssid, ETH_ALEN);
     768        4450 :         return 0;
     769             : }
     770             : 
     771             : 
     772        1393 : static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
     773             : {
     774        1393 :         struct i802_bss *bss = priv;
     775        1393 :         struct wpa_driver_nl80211_data *drv = bss->drv;
     776        1393 :         if (!drv->associated)
     777           1 :                 return -1;
     778        1392 :         os_memcpy(ssid, drv->ssid, drv->ssid_len);
     779        1392 :         return drv->ssid_len;
     780             : }
     781             : 
     782             : 
     783       20807 : static void wpa_driver_nl80211_event_newlink(
     784             :         struct wpa_driver_nl80211_data *drv, const char *ifname)
     785             : {
     786             :         union wpa_event_data event;
     787             : 
     788       20807 :         if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
     789       20521 :                 if (if_nametoindex(drv->first_bss->ifname) == 0) {
     790          22 :                         wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
     791          22 :                                    drv->first_bss->ifname);
     792          22 :                         return;
     793             :                 }
     794       20499 :                 if (!drv->if_removed)
     795       20499 :                         return;
     796           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event",
     797           0 :                            drv->first_bss->ifname);
     798           0 :                 drv->if_removed = 0;
     799             :         }
     800             : 
     801         286 :         os_memset(&event, 0, sizeof(event));
     802         286 :         os_strlcpy(event.interface_status.ifname, ifname,
     803             :                    sizeof(event.interface_status.ifname));
     804         286 :         event.interface_status.ievent = EVENT_INTERFACE_ADDED;
     805         286 :         wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
     806             : }
     807             : 
     808             : 
     809          17 : static void wpa_driver_nl80211_event_dellink(
     810             :         struct wpa_driver_nl80211_data *drv, const char *ifname)
     811             : {
     812             :         union wpa_event_data event;
     813             : 
     814          17 :         if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
     815          16 :                 if (drv->if_removed) {
     816           0 :                         wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
     817             :                                    ifname);
     818          17 :                         return;
     819             :                 }
     820          16 :                 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1",
     821             :                            ifname);
     822          16 :                 drv->if_removed = 1;
     823             :         } else {
     824           1 :                 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed",
     825             :                            ifname);
     826             :         }
     827             : 
     828          17 :         os_memset(&event, 0, sizeof(event));
     829          17 :         os_strlcpy(event.interface_status.ifname, ifname,
     830             :                    sizeof(event.interface_status.ifname));
     831          17 :         event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
     832          17 :         wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
     833             : }
     834             : 
     835             : 
     836          10 : static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
     837             :                                          u8 *buf, size_t len)
     838             : {
     839             :         int attrlen, rta_len;
     840             :         struct rtattr *attr;
     841             : 
     842          10 :         attrlen = len;
     843          10 :         attr = (struct rtattr *) buf;
     844             : 
     845          10 :         rta_len = RTA_ALIGN(sizeof(struct rtattr));
     846          20 :         while (RTA_OK(attr, attrlen)) {
     847          10 :                 if (attr->rta_type == IFLA_IFNAME) {
     848          10 :                         if (os_strcmp(((char *) attr) + rta_len,
     849             :                                       drv->first_bss->ifname) == 0)
     850           0 :                                 return 1;
     851             :                         else
     852          10 :                                 break;
     853             :                 }
     854           0 :                 attr = RTA_NEXT(attr, attrlen);
     855             :         }
     856             : 
     857          10 :         return 0;
     858             : }
     859             : 
     860             : 
     861      103111 : static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
     862             :                                           int ifindex, u8 *buf, size_t len)
     863             : {
     864      103111 :         if (drv->ifindex == ifindex)
     865       20883 :                 return 1;
     866             : 
     867       82228 :         if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
     868           0 :                 nl80211_check_global(drv->global);
     869           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
     870             :                            "interface");
     871           0 :                 wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL);
     872           0 :                 return 1;
     873             :         }
     874             : 
     875       82228 :         return 0;
     876             : }
     877             : 
     878             : 
     879             : static struct wpa_driver_nl80211_data *
     880      114279 : nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
     881             : {
     882             :         struct wpa_driver_nl80211_data *drv;
     883      196100 :         dl_list_for_each(drv, &global->interfaces,
     884             :                          struct wpa_driver_nl80211_data, list) {
     885      185339 :                 if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
     886       82228 :                     have_ifidx(drv, idx))
     887       21290 :                         return drv;
     888             :         }
     889       92989 :         return NULL;
     890             : }
     891             : 
     892             : 
     893      112913 : static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
     894             :                                                  struct ifinfomsg *ifi,
     895             :                                                  u8 *buf, size_t len)
     896             : {
     897      112913 :         struct nl80211_global *global = ctx;
     898             :         struct wpa_driver_nl80211_data *drv;
     899             :         int attrlen;
     900             :         struct rtattr *attr;
     901      112913 :         u32 brid = 0;
     902             :         char namebuf[IFNAMSIZ];
     903             :         char ifname[IFNAMSIZ + 1];
     904             :         char extra[100], *pos, *end;
     905             : 
     906      112913 :         drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
     907      112913 :         if (!drv) {
     908       91689 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d",
     909             :                            ifi->ifi_index);
     910       91689 :                 return;
     911             :         }
     912             : 
     913       21224 :         extra[0] = '\0';
     914       21224 :         pos = extra;
     915       21224 :         end = pos + sizeof(extra);
     916       21224 :         ifname[0] = '\0';
     917             : 
     918       21224 :         attrlen = len;
     919       21224 :         attr = (struct rtattr *) buf;
     920      253977 :         while (RTA_OK(attr, attrlen)) {
     921      211529 :                 switch (attr->rta_type) {
     922             :                 case IFLA_IFNAME:
     923       21224 :                         if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
     924           0 :                                 break;
     925       21224 :                         os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
     926       21224 :                         ifname[RTA_PAYLOAD(attr)] = '\0';
     927       21224 :                         break;
     928             :                 case IFLA_MASTER:
     929         321 :                         brid = nla_get_u32((struct nlattr *) attr);
     930         321 :                         pos += os_snprintf(pos, end - pos, " master=%u", brid);
     931         321 :                         break;
     932             :                 case IFLA_WIRELESS:
     933       10525 :                         pos += os_snprintf(pos, end - pos, " wext");
     934       10525 :                         break;
     935             :                 case IFLA_OPERSTATE:
     936       10699 :                         pos += os_snprintf(pos, end - pos, " operstate=%u",
     937             :                                            nla_get_u32((struct nlattr *) attr));
     938       10699 :                         break;
     939             :                 case IFLA_LINKMODE:
     940       10496 :                         pos += os_snprintf(pos, end - pos, " linkmode=%u",
     941             :                                            nla_get_u32((struct nlattr *) attr));
     942       10496 :                         break;
     943             :                 }
     944      211529 :                 attr = RTA_NEXT(attr, attrlen);
     945             :         }
     946       21224 :         extra[sizeof(extra) - 1] = '\0';
     947             : 
     948      106120 :         wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
     949       21224 :                    ifi->ifi_index, ifname, extra, ifi->ifi_family,
     950             :                    ifi->ifi_flags,
     951       21224 :                    (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
     952       21224 :                    (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
     953       21224 :                    (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
     954       21224 :                    (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
     955             : 
     956       21224 :         if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
     957         491 :                 namebuf[0] = '\0';
     958         964 :                 if (if_indextoname(ifi->ifi_index, namebuf) &&
     959         473 :                     linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) {
     960         415 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
     961             :                                    "event since interface %s is up", namebuf);
     962         415 :                         drv->ignore_if_down_event = 0;
     963         415 :                         return;
     964             :                 }
     965          76 :                 wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
     966             :                            namebuf, ifname);
     967          76 :                 if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
     968          47 :                         wpa_printf(MSG_DEBUG,
     969             :                                    "nl80211: Not the main interface (%s) - do not indicate interface down",
     970          47 :                                    drv->first_bss->ifname);
     971          29 :                 } else if (drv->ignore_if_down_event) {
     972           0 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
     973             :                                    "event generated by mode change");
     974           0 :                         drv->ignore_if_down_event = 0;
     975             :                 } else {
     976          29 :                         drv->if_disabled = 1;
     977          29 :                         wpa_supplicant_event(drv->ctx,
     978             :                                              EVENT_INTERFACE_DISABLED, NULL);
     979             : 
     980             :                         /*
     981             :                          * Try to get drv again, since it may be removed as
     982             :                          * part of the EVENT_INTERFACE_DISABLED handling for
     983             :                          * dynamic interfaces
     984             :                          */
     985          29 :                         drv = nl80211_find_drv(global, ifi->ifi_index,
     986             :                                                buf, len);
     987          29 :                         if (!drv)
     988           2 :                                 return;
     989             :                 }
     990             :         }
     991             : 
     992       20807 :         if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
     993          37 :                 if (if_indextoname(ifi->ifi_index, namebuf) &&
     994          16 :                     linux_iface_up(drv->global->ioctl_sock, namebuf) == 0) {
     995           5 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
     996             :                                    "event since interface %s is down",
     997             :                                    namebuf);
     998          16 :                 } else if (if_nametoindex(drv->first_bss->ifname) == 0) {
     999           5 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
    1000             :                                    "event since interface %s does not exist",
    1001           5 :                                    drv->first_bss->ifname);
    1002          11 :                 } else if (drv->if_removed) {
    1003           0 :                         wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
    1004             :                                    "event since interface %s is marked "
    1005           0 :                                    "removed", drv->first_bss->ifname);
    1006             :                 } else {
    1007             :                         struct i802_bss *bss;
    1008             :                         u8 addr[ETH_ALEN];
    1009             : 
    1010             :                         /* Re-read MAC address as it may have changed */
    1011          11 :                         bss = get_bss_ifindex(drv, ifi->ifi_index);
    1012          22 :                         if (bss &&
    1013          11 :                             linux_get_ifhwaddr(drv->global->ioctl_sock,
    1014          11 :                                                bss->ifname, addr) < 0) {
    1015           0 :                                 wpa_printf(MSG_DEBUG,
    1016             :                                            "nl80211: %s: failed to re-read MAC address",
    1017           0 :                                            bss->ifname);
    1018          22 :                         } else if (bss &&
    1019          11 :                                    os_memcmp(addr, bss->addr, ETH_ALEN) != 0) {
    1020          26 :                                 wpa_printf(MSG_DEBUG,
    1021             :                                            "nl80211: Own MAC address on ifindex %d (%s) changed from "
    1022             :                                            MACSTR " to " MACSTR,
    1023           2 :                                            ifi->ifi_index, bss->ifname,
    1024          12 :                                            MAC2STR(bss->addr),
    1025          12 :                                            MAC2STR(addr));
    1026           2 :                                 os_memcpy(bss->addr, addr, ETH_ALEN);
    1027             :                         }
    1028             : 
    1029          11 :                         wpa_printf(MSG_DEBUG, "nl80211: Interface up");
    1030          11 :                         drv->if_disabled = 0;
    1031          11 :                         wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
    1032             :                                              NULL);
    1033             :                 }
    1034             :         }
    1035             : 
    1036             :         /*
    1037             :          * Some drivers send the association event before the operup event--in
    1038             :          * this case, lifting operstate in wpa_driver_nl80211_set_operstate()
    1039             :          * fails. This will hit us when wpa_supplicant does not need to do
    1040             :          * IEEE 802.1X authentication
    1041             :          */
    1042       26843 :         if (drv->operstate == 1 &&
    1043       10576 :             (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
    1044        4540 :             !(ifi->ifi_flags & IFF_RUNNING)) {
    1045         748 :                 wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate");
    1046         748 :                 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
    1047             :                                        -1, IF_OPER_UP);
    1048             :         }
    1049             : 
    1050       20807 :         if (ifname[0])
    1051       20807 :                 wpa_driver_nl80211_event_newlink(drv, ifname);
    1052             : 
    1053       20807 :         if (ifi->ifi_family == AF_BRIDGE && brid) {
    1054             :                 struct i802_bss *bss;
    1055             : 
    1056             :                 /* device has been added to bridge */
    1057         202 :                 if (!if_indextoname(brid, namebuf)) {
    1058          11 :                         wpa_printf(MSG_DEBUG,
    1059             :                                    "nl80211: Could not find bridge ifname for ifindex %u",
    1060             :                                    brid);
    1061          11 :                         return;
    1062             :                 }
    1063         191 :                 wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
    1064             :                            brid, namebuf);
    1065         191 :                 add_ifidx(drv, brid);
    1066             : 
    1067         247 :                 for (bss = drv->first_bss; bss; bss = bss->next) {
    1068         191 :                         if (os_strcmp(ifname, bss->ifname) == 0) {
    1069         135 :                                 os_strlcpy(bss->brname, namebuf, IFNAMSIZ);
    1070         135 :                                 break;
    1071             :                         }
    1072             :                 }
    1073             :         }
    1074             : }
    1075             : 
    1076             : 
    1077        1337 : static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
    1078             :                                                  struct ifinfomsg *ifi,
    1079             :                                                  u8 *buf, size_t len)
    1080             : {
    1081        1337 :         struct nl80211_global *global = ctx;
    1082             :         struct wpa_driver_nl80211_data *drv;
    1083             :         int attrlen;
    1084             :         struct rtattr *attr;
    1085        1337 :         u32 brid = 0;
    1086             :         char ifname[IFNAMSIZ + 1];
    1087             :         char extra[100], *pos, *end;
    1088             : 
    1089        1337 :         drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
    1090        1337 :         if (!drv) {
    1091        1298 :                 wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d",
    1092             :                            ifi->ifi_index);
    1093        2635 :                 return;
    1094             :         }
    1095             : 
    1096          39 :         extra[0] = '\0';
    1097          39 :         pos = extra;
    1098          39 :         end = pos + sizeof(extra);
    1099          39 :         ifname[0] = '\0';
    1100             : 
    1101          39 :         attrlen = len;
    1102          39 :         attr = (struct rtattr *) buf;
    1103         495 :         while (RTA_OK(attr, attrlen)) {
    1104         417 :                 switch (attr->rta_type) {
    1105             :                 case IFLA_IFNAME:
    1106          39 :                         if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
    1107           0 :                                 break;
    1108          39 :                         os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
    1109          39 :                         ifname[RTA_PAYLOAD(attr)] = '\0';
    1110          39 :                         break;
    1111             :                 case IFLA_MASTER:
    1112          22 :                         brid = nla_get_u32((struct nlattr *) attr);
    1113          22 :                         pos += os_snprintf(pos, end - pos, " master=%u", brid);
    1114          22 :                         break;
    1115             :                 case IFLA_OPERSTATE:
    1116          39 :                         pos += os_snprintf(pos, end - pos, " operstate=%u",
    1117             :                                            nla_get_u32((struct nlattr *) attr));
    1118          39 :                         break;
    1119             :                 case IFLA_LINKMODE:
    1120          17 :                         pos += os_snprintf(pos, end - pos, " linkmode=%u",
    1121             :                                            nla_get_u32((struct nlattr *) attr));
    1122          17 :                         break;
    1123             :                 }
    1124         417 :                 attr = RTA_NEXT(attr, attrlen);
    1125             :         }
    1126          39 :         extra[sizeof(extra) - 1] = '\0';
    1127             : 
    1128         195 :         wpa_printf(MSG_DEBUG, "RTM_DELLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
    1129          39 :                    ifi->ifi_index, ifname, extra, ifi->ifi_family,
    1130             :                    ifi->ifi_flags,
    1131          39 :                    (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
    1132          39 :                    (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
    1133          39 :                    (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
    1134          39 :                    (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
    1135             : 
    1136          39 :         if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid))
    1137          17 :                 wpa_driver_nl80211_event_dellink(drv, ifname);
    1138             : 
    1139          39 :         if (ifi->ifi_family == AF_BRIDGE && brid) {
    1140             :                 /* device has been removed from bridge */
    1141             :                 char namebuf[IFNAMSIZ];
    1142             : 
    1143          22 :                 if (!if_indextoname(brid, namebuf)) {
    1144          12 :                         wpa_printf(MSG_DEBUG,
    1145             :                                    "nl80211: Could not find bridge ifname for ifindex %u",
    1146             :                                    brid);
    1147             :                 } else {
    1148          10 :                         wpa_printf(MSG_DEBUG,
    1149             :                                    "nl80211: Remove ifindex %u for bridge %s",
    1150             :                                    brid, namebuf);
    1151             :                 }
    1152          22 :                 del_ifidx(drv, brid);
    1153             :         }
    1154             : }
    1155             : 
    1156             : 
    1157          59 : unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
    1158             : {
    1159             :         struct nl_msg *msg;
    1160             :         int ret;
    1161             :         struct nl80211_bss_info_arg arg;
    1162             : 
    1163          59 :         msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
    1164          59 :         os_memset(&arg, 0, sizeof(arg));
    1165          59 :         arg.drv = drv;
    1166          59 :         ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
    1167          59 :         if (ret == 0) {
    1168         118 :                 unsigned int freq = drv->nlmode == NL80211_IFTYPE_ADHOC ?
    1169          59 :                         arg.ibss_freq : arg.assoc_freq;
    1170          59 :                 wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
    1171             :                            "associated BSS from scan results: %u MHz", freq);
    1172          59 :                 if (freq)
    1173          58 :                         drv->assoc_freq = freq;
    1174          59 :                 return drv->assoc_freq;
    1175             :         }
    1176           0 :         wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
    1177             :                    "(%s)", ret, strerror(-ret));
    1178           0 :         return drv->assoc_freq;
    1179             : }
    1180             : 
    1181             : 
    1182          50 : static int get_link_signal(struct nl_msg *msg, void *arg)
    1183             : {
    1184             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    1185          50 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    1186             :         struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
    1187             :         static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
    1188             :                 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
    1189             :                 [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
    1190             :         };
    1191             :         struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
    1192             :         static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
    1193             :                 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
    1194             :                 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
    1195             :                 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
    1196             :                 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
    1197             :         };
    1198          50 :         struct wpa_signal_info *sig_change = arg;
    1199             : 
    1200          50 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    1201             :                   genlmsg_attrlen(gnlh, 0), NULL);
    1202         100 :         if (!tb[NL80211_ATTR_STA_INFO] ||
    1203          50 :             nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
    1204             :                              tb[NL80211_ATTR_STA_INFO], policy))
    1205           0 :                 return NL_SKIP;
    1206          50 :         if (!sinfo[NL80211_STA_INFO_SIGNAL])
    1207           0 :                 return NL_SKIP;
    1208             : 
    1209          50 :         sig_change->current_signal =
    1210          50 :                 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
    1211             : 
    1212          50 :         if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
    1213          50 :                 sig_change->avg_signal =
    1214          50 :                         (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
    1215             :         else
    1216           0 :                 sig_change->avg_signal = 0;
    1217             : 
    1218          50 :         if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
    1219          50 :                 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
    1220             :                                      sinfo[NL80211_STA_INFO_TX_BITRATE],
    1221             :                                      rate_policy)) {
    1222           0 :                         sig_change->current_txrate = 0;
    1223             :                 } else {
    1224          50 :                         if (rinfo[NL80211_RATE_INFO_BITRATE]) {
    1225          50 :                                 sig_change->current_txrate =
    1226          50 :                                         nla_get_u16(rinfo[
    1227          50 :                                              NL80211_RATE_INFO_BITRATE]) * 100;
    1228             :                         }
    1229             :                 }
    1230             :         }
    1231             : 
    1232          50 :         return NL_SKIP;
    1233             : }
    1234             : 
    1235             : 
    1236          50 : int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
    1237             :                             struct wpa_signal_info *sig)
    1238             : {
    1239             :         struct nl_msg *msg;
    1240             : 
    1241          50 :         sig->current_signal = -9999;
    1242          50 :         sig->current_txrate = 0;
    1243             : 
    1244         100 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_STATION)) ||
    1245          50 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid)) {
    1246           0 :                 nlmsg_free(msg);
    1247           0 :                 return -ENOBUFS;
    1248             :         }
    1249             : 
    1250          50 :         return send_and_recv_msgs(drv, msg, get_link_signal, sig);
    1251             : }
    1252             : 
    1253             : 
    1254          50 : static int get_link_noise(struct nl_msg *msg, void *arg)
    1255             : {
    1256             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    1257          50 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    1258             :         struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
    1259             :         static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
    1260             :                 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
    1261             :                 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
    1262             :         };
    1263          50 :         struct wpa_signal_info *sig_change = arg;
    1264             : 
    1265          50 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    1266             :                   genlmsg_attrlen(gnlh, 0), NULL);
    1267             : 
    1268          50 :         if (!tb[NL80211_ATTR_SURVEY_INFO]) {
    1269           0 :                 wpa_printf(MSG_DEBUG, "nl80211: survey data missing!");
    1270           0 :                 return NL_SKIP;
    1271             :         }
    1272             : 
    1273          50 :         if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
    1274             :                              tb[NL80211_ATTR_SURVEY_INFO],
    1275             :                              survey_policy)) {
    1276           0 :                 wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested "
    1277             :                            "attributes!");
    1278           0 :                 return NL_SKIP;
    1279             :         }
    1280             : 
    1281          50 :         if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
    1282           0 :                 return NL_SKIP;
    1283             : 
    1284         100 :         if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
    1285          50 :             sig_change->frequency)
    1286           0 :                 return NL_SKIP;
    1287             : 
    1288          50 :         if (!sinfo[NL80211_SURVEY_INFO_NOISE])
    1289           0 :                 return NL_SKIP;
    1290             : 
    1291          50 :         sig_change->current_noise =
    1292          50 :                 (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
    1293             : 
    1294          50 :         return NL_SKIP;
    1295             : }
    1296             : 
    1297             : 
    1298          50 : int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
    1299             :                            struct wpa_signal_info *sig_change)
    1300             : {
    1301             :         struct nl_msg *msg;
    1302             : 
    1303          50 :         sig_change->current_noise = 9999;
    1304          50 :         sig_change->frequency = drv->assoc_freq;
    1305             : 
    1306          50 :         msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
    1307          50 :         return send_and_recv_msgs(drv, msg, get_link_noise, sig_change);
    1308             : }
    1309             : 
    1310             : 
    1311      236230 : static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
    1312             :                                              void *handle)
    1313             : {
    1314      236230 :         struct nl_cb *cb = eloop_ctx;
    1315             :         int res;
    1316             : 
    1317      236230 :         wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");
    1318             : 
    1319      236230 :         res = nl_recvmsgs(handle, cb);
    1320      236230 :         if (res < 0) {
    1321           0 :                 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
    1322             :                            __func__, res);
    1323             :         }
    1324      236230 : }
    1325             : 
    1326             : 
    1327             : /**
    1328             :  * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
    1329             :  * @priv: driver_nl80211 private data
    1330             :  * @alpha2_arg: country to which to switch to
    1331             :  * Returns: 0 on success, -1 on failure
    1332             :  *
    1333             :  * This asks nl80211 to set the regulatory domain for given
    1334             :  * country ISO / IEC alpha2.
    1335             :  */
    1336          53 : static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
    1337             : {
    1338          53 :         struct i802_bss *bss = priv;
    1339          53 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    1340             :         char alpha2[3];
    1341             :         struct nl_msg *msg;
    1342             : 
    1343          53 :         msg = nlmsg_alloc();
    1344          53 :         if (!msg)
    1345           0 :                 return -ENOMEM;
    1346             : 
    1347          53 :         alpha2[0] = alpha2_arg[0];
    1348          53 :         alpha2[1] = alpha2_arg[1];
    1349          53 :         alpha2[2] = '\0';
    1350             : 
    1351         106 :         if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG) ||
    1352          53 :             nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, alpha2)) {
    1353           0 :                 nlmsg_free(msg);
    1354           0 :                 return -EINVAL;
    1355             :         }
    1356          53 :         if (send_and_recv_msgs(drv, msg, NULL, NULL))
    1357           0 :                 return -EINVAL;
    1358          53 :         return 0;
    1359             : }
    1360             : 
    1361             : 
    1362          46 : static int nl80211_get_country(struct nl_msg *msg, void *arg)
    1363             : {
    1364          46 :         char *alpha2 = arg;
    1365             :         struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
    1366          46 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    1367             : 
    1368          46 :         nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    1369             :                   genlmsg_attrlen(gnlh, 0), NULL);
    1370          46 :         if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) {
    1371           0 :                 wpa_printf(MSG_DEBUG, "nl80211: No country information available");
    1372           0 :                 return NL_SKIP;
    1373             :         }
    1374          46 :         os_strlcpy(alpha2, nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]), 3);
    1375          46 :         return NL_SKIP;
    1376             : }
    1377             : 
    1378             : 
    1379          46 : static int wpa_driver_nl80211_get_country(void *priv, char *alpha2)
    1380             : {
    1381          46 :         struct i802_bss *bss = priv;
    1382          46 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    1383             :         struct nl_msg *msg;
    1384             :         int ret;
    1385             : 
    1386          46 :         msg = nlmsg_alloc();
    1387          46 :         if (!msg)
    1388           0 :                 return -ENOMEM;
    1389             : 
    1390          46 :         nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
    1391          46 :         alpha2[0] = '\0';
    1392          46 :         ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2);
    1393          46 :         if (!alpha2[0])
    1394           0 :                 ret = -1;
    1395             : 
    1396          46 :         return ret;
    1397             : }
    1398             : 
    1399             : 
    1400          25 : static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
    1401             : {
    1402             :         int ret;
    1403             : 
    1404          25 :         global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
    1405          25 :         if (global->nl_cb == NULL) {
    1406           0 :                 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
    1407             :                            "callbacks");
    1408           0 :                 return -1;
    1409             :         }
    1410             : 
    1411          25 :         global->nl = nl_create_handle(global->nl_cb, "nl");
    1412          25 :         if (global->nl == NULL)
    1413           0 :                 goto err;
    1414             : 
    1415          25 :         global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
    1416          25 :         if (global->nl80211_id < 0) {
    1417           0 :                 wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
    1418             :                            "found");
    1419           0 :                 goto err;
    1420             :         }
    1421             : 
    1422          25 :         global->nl_event = nl_create_handle(global->nl_cb, "event");
    1423          25 :         if (global->nl_event == NULL)
    1424           0 :                 goto err;
    1425             : 
    1426          25 :         ret = nl_get_multicast_id(global, "nl80211", "scan");
    1427          25 :         if (ret >= 0)
    1428          25 :                 ret = nl_socket_add_membership(global->nl_event, ret);
    1429          25 :         if (ret < 0) {
    1430           0 :                 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
    1431             :                            "membership for scan events: %d (%s)",
    1432             :                            ret, strerror(-ret));
    1433           0 :                 goto err;
    1434             :         }
    1435             : 
    1436          25 :         ret = nl_get_multicast_id(global, "nl80211", "mlme");
    1437          25 :         if (ret >= 0)
    1438          25 :                 ret = nl_socket_add_membership(global->nl_event, ret);
    1439          25 :         if (ret < 0) {
    1440           0 :                 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
    1441             :                            "membership for mlme events: %d (%s)",
    1442             :                            ret, strerror(-ret));
    1443           0 :                 goto err;
    1444             :         }
    1445             : 
    1446          25 :         ret = nl_get_multicast_id(global, "nl80211", "regulatory");
    1447          25 :         if (ret >= 0)
    1448          25 :                 ret = nl_socket_add_membership(global->nl_event, ret);
    1449          25 :         if (ret < 0) {
    1450           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
    1451             :                            "membership for regulatory events: %d (%s)",
    1452             :                            ret, strerror(-ret));
    1453             :                 /* Continue without regulatory events */
    1454             :         }
    1455             : 
    1456          25 :         ret = nl_get_multicast_id(global, "nl80211", "vendor");
    1457          25 :         if (ret >= 0)
    1458          25 :                 ret = nl_socket_add_membership(global->nl_event, ret);
    1459          25 :         if (ret < 0) {
    1460           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
    1461             :                            "membership for vendor events: %d (%s)",
    1462             :                            ret, strerror(-ret));
    1463             :                 /* Continue without vendor events */
    1464             :         }
    1465             : 
    1466          25 :         nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
    1467             :                   no_seq_check, NULL);
    1468          25 :         nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
    1469             :                   process_global_event, global);
    1470             : 
    1471          25 :         nl80211_register_eloop_read(&global->nl_event,
    1472             :                                     wpa_driver_nl80211_event_receive,
    1473          25 :                                     global->nl_cb);
    1474             : 
    1475          25 :         return 0;
    1476             : 
    1477             : err:
    1478           0 :         nl_destroy_handles(&global->nl_event);
    1479           0 :         nl_destroy_handles(&global->nl);
    1480           0 :         nl_cb_put(global->nl_cb);
    1481           0 :         global->nl_cb = NULL;
    1482           0 :         return -1;
    1483             : }
    1484             : 
    1485             : 
    1486        1231 : static void nl80211_check_global(struct nl80211_global *global)
    1487             : {
    1488             :         struct nl_handle *handle;
    1489        1231 :         const char *groups[] = { "scan", "mlme", "regulatory", "vendor", NULL };
    1490             :         int ret;
    1491             :         unsigned int i;
    1492             : 
    1493             :         /*
    1494             :          * Try to re-add memberships to handle case of cfg80211 getting reloaded
    1495             :          * and all registration having been cleared.
    1496             :          */
    1497        1231 :         handle = (void *) (((intptr_t) global->nl_event) ^
    1498             :                            ELOOP_SOCKET_INVALID);
    1499             : 
    1500        6155 :         for (i = 0; groups[i]; i++) {
    1501        4924 :                 ret = nl_get_multicast_id(global, "nl80211", groups[i]);
    1502        4924 :                 if (ret >= 0)
    1503        4924 :                         ret = nl_socket_add_membership(handle, ret);
    1504        4924 :                 if (ret < 0) {
    1505           0 :                         wpa_printf(MSG_INFO,
    1506             :                                    "nl80211: Could not re-add multicast membership for %s events: %d (%s)",
    1507             :                                    groups[i], ret, strerror(-ret));
    1508             :                 }
    1509             :         }
    1510        1231 : }
    1511             : 
    1512             : 
    1513          27 : static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
    1514             : {
    1515          27 :         wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
    1516             :         /*
    1517             :          * This may be for any interface; use ifdown event to disable
    1518             :          * interface.
    1519             :          */
    1520          27 : }
    1521             : 
    1522             : 
    1523          26 : static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
    1524             : {
    1525          26 :         struct wpa_driver_nl80211_data *drv = ctx;
    1526          26 :         wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
    1527          26 :         if (i802_set_iface_flags(drv->first_bss, 1)) {
    1528           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
    1529             :                            "after rfkill unblock");
    1530           0 :                 return;
    1531             :         }
    1532             :         /* rtnetlink ifup handler will report interface as enabled */
    1533             : }
    1534             : 
    1535             : 
    1536        9440 : static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
    1537             :                                                       void *eloop_ctx,
    1538             :                                                       void *handle)
    1539             : {
    1540        9440 :         struct wpa_driver_nl80211_data *drv = eloop_ctx;
    1541             :         u8 data[2048];
    1542             :         struct msghdr msg;
    1543             :         struct iovec entry;
    1544             :         u8 control[512];
    1545             :         struct cmsghdr *cmsg;
    1546        9440 :         int res, found_ee = 0, found_wifi = 0, acked = 0;
    1547             :         union wpa_event_data event;
    1548             : 
    1549        9440 :         memset(&msg, 0, sizeof(msg));
    1550        9440 :         msg.msg_iov = &entry;
    1551        9440 :         msg.msg_iovlen = 1;
    1552        9440 :         entry.iov_base = data;
    1553        9440 :         entry.iov_len = sizeof(data);
    1554        9440 :         msg.msg_control = &control;
    1555        9440 :         msg.msg_controllen = sizeof(control);
    1556             : 
    1557        9440 :         res = recvmsg(sock, &msg, MSG_ERRQUEUE);
    1558             :         /* if error or not fitting 802.3 header, return */
    1559        9440 :         if (res < 14)
    1560           0 :                 return;
    1561             : 
    1562       28320 :         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
    1563             :         {
    1564       28320 :                 if (cmsg->cmsg_level == SOL_SOCKET &&
    1565        9440 :                     cmsg->cmsg_type == SCM_WIFI_STATUS) {
    1566             :                         int *ack;
    1567             : 
    1568        9440 :                         found_wifi = 1;
    1569        9440 :                         ack = (void *)CMSG_DATA(cmsg);
    1570        9440 :                         acked = *ack;
    1571             :                 }
    1572             : 
    1573       28320 :                 if (cmsg->cmsg_level == SOL_PACKET &&
    1574        9440 :                     cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
    1575        9440 :                         struct sock_extended_err *err =
    1576             :                                 (struct sock_extended_err *)CMSG_DATA(cmsg);
    1577             : 
    1578        9440 :                         if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
    1579        9440 :                                 found_ee = 1;
    1580             :                 }
    1581             :         }
    1582             : 
    1583        9440 :         if (!found_ee || !found_wifi)
    1584           0 :                 return;
    1585             : 
    1586        9440 :         memset(&event, 0, sizeof(event));
    1587        9440 :         event.eapol_tx_status.dst = data;
    1588        9440 :         event.eapol_tx_status.data = data + 14;
    1589        9440 :         event.eapol_tx_status.data_len = res - 14;
    1590        9440 :         event.eapol_tx_status.ack = acked;
    1591        9440 :         wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
    1592             : }
    1593             : 
    1594             : 
    1595        1280 : static int nl80211_init_bss(struct i802_bss *bss)
    1596             : {
    1597        1280 :         bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
    1598        1280 :         if (!bss->nl_cb)
    1599           0 :                 return -1;
    1600             : 
    1601        1280 :         nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
    1602             :                   no_seq_check, NULL);
    1603        1280 :         nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
    1604             :                   process_bss_event, bss);
    1605             : 
    1606        1280 :         return 0;
    1607             : }
    1608             : 
    1609             : 
    1610        1280 : static void nl80211_destroy_bss(struct i802_bss *bss)
    1611             : {
    1612        1280 :         nl_cb_put(bss->nl_cb);
    1613        1280 :         bss->nl_cb = NULL;
    1614        1280 : }
    1615             : 
    1616             : 
    1617        1246 : static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
    1618             :                                           void *global_priv, int hostapd,
    1619             :                                           const u8 *set_addr,
    1620             :                                           const char *driver_params)
    1621             : {
    1622             :         struct wpa_driver_nl80211_data *drv;
    1623             :         struct rfkill_config *rcfg;
    1624             :         struct i802_bss *bss;
    1625             : 
    1626        1246 :         if (global_priv == NULL)
    1627           0 :                 return NULL;
    1628        1246 :         drv = os_zalloc(sizeof(*drv));
    1629        1246 :         if (drv == NULL)
    1630           4 :                 return NULL;
    1631        1242 :         drv->global = global_priv;
    1632        1242 :         drv->ctx = ctx;
    1633        1242 :         drv->hostapd = !!hostapd;
    1634        1242 :         drv->eapol_sock = -1;
    1635             : 
    1636             :         /*
    1637             :          * There is no driver capability flag for this, so assume it is
    1638             :          * supported and disable this on first attempt to use if the driver
    1639             :          * rejects the command due to missing support.
    1640             :          */
    1641        1242 :         drv->set_rekey_offload = 1;
    1642             : 
    1643        1242 :         drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
    1644        1242 :         drv->if_indices = drv->default_if_indices;
    1645             : 
    1646        1242 :         drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
    1647        1242 :         if (!drv->first_bss) {
    1648           4 :                 os_free(drv);
    1649           4 :                 return NULL;
    1650             :         }
    1651        1238 :         bss = drv->first_bss;
    1652        1238 :         bss->drv = drv;
    1653        1238 :         bss->ctx = ctx;
    1654             : 
    1655        1238 :         os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
    1656        1238 :         drv->monitor_ifidx = -1;
    1657        1238 :         drv->monitor_sock = -1;
    1658        1238 :         drv->eapol_tx_sock = -1;
    1659        1238 :         drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
    1660             : 
    1661        1238 :         if (nl80211_init_bss(bss))
    1662           0 :                 goto failed;
    1663             : 
    1664        1238 :         rcfg = os_zalloc(sizeof(*rcfg));
    1665        1238 :         if (rcfg == NULL)
    1666           4 :                 goto failed;
    1667        1234 :         rcfg->ctx = drv;
    1668        1234 :         os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
    1669        1234 :         rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
    1670        1234 :         rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
    1671        1234 :         drv->rfkill = rfkill_init(rcfg);
    1672        1234 :         if (drv->rfkill == NULL) {
    1673           3 :                 wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
    1674           3 :                 os_free(rcfg);
    1675             :         }
    1676             : 
    1677        1234 :         if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0)
    1678           0 :                 drv->start_iface_up = 1;
    1679             : 
    1680        1234 :         if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))
    1681           3 :                 goto failed;
    1682             : 
    1683        1231 :         drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
    1684        1231 :         if (drv->eapol_tx_sock < 0)
    1685           0 :                 goto failed;
    1686             : 
    1687        1231 :         if (drv->data_tx_status) {
    1688        1231 :                 int enabled = 1;
    1689             : 
    1690        1231 :                 if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
    1691             :                                &enabled, sizeof(enabled)) < 0) {
    1692           0 :                         wpa_printf(MSG_DEBUG,
    1693             :                                 "nl80211: wifi status sockopt failed\n");
    1694           0 :                         drv->data_tx_status = 0;
    1695           0 :                         if (!drv->use_monitor)
    1696           0 :                                 drv->capa.flags &=
    1697             :                                         ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
    1698             :                 } else {
    1699        1231 :                         eloop_register_read_sock(drv->eapol_tx_sock,
    1700             :                                 wpa_driver_nl80211_handle_eapol_tx_status,
    1701             :                                 drv, NULL);
    1702             :                 }
    1703             :         }
    1704             : 
    1705        1231 :         if (drv->global) {
    1706        1231 :                 nl80211_check_global(drv->global);
    1707        1231 :                 dl_list_add(&drv->global->interfaces, &drv->list);
    1708        1231 :                 drv->in_interface_list = 1;
    1709             :         }
    1710             : 
    1711        1231 :         return bss;
    1712             : 
    1713             : failed:
    1714           7 :         wpa_driver_nl80211_deinit(bss);
    1715           7 :         return NULL;
    1716             : }
    1717             : 
    1718             : 
    1719             : /**
    1720             :  * wpa_driver_nl80211_init - Initialize nl80211 driver interface
    1721             :  * @ctx: context to be used when calling wpa_supplicant functions,
    1722             :  * e.g., wpa_supplicant_event()
    1723             :  * @ifname: interface name, e.g., wlan0
    1724             :  * @global_priv: private driver global data from global_init()
    1725             :  * Returns: Pointer to private data, %NULL on failure
    1726             :  */
    1727         232 : static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
    1728             :                                       void *global_priv)
    1729             : {
    1730         232 :         return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL,
    1731             :                                            NULL);
    1732             : }
    1733             : 
    1734             : 
    1735       27007 : static int nl80211_register_frame(struct i802_bss *bss,
    1736             :                                   struct nl_handle *nl_handle,
    1737             :                                   u16 type, const u8 *match, size_t match_len)
    1738             : {
    1739       27007 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    1740             :         struct nl_msg *msg;
    1741             :         int ret;
    1742             :         char buf[30];
    1743             : 
    1744       27007 :         buf[0] = '\0';
    1745       27007 :         wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
    1746       27007 :         wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s",
    1747             :                    type, fc2str(type), nl_handle, buf);
    1748             : 
    1749       54014 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REGISTER_ACTION)) ||
    1750       54014 :             nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, type) ||
    1751       27007 :             nla_put(msg, NL80211_ATTR_FRAME_MATCH, match_len, match)) {
    1752           0 :                 nlmsg_free(msg);
    1753           0 :                 return -1;
    1754             :         }
    1755             : 
    1756       27007 :         ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
    1757       27007 :         if (ret) {
    1758           3 :                 wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
    1759             :                            "failed (type=%u): ret=%d (%s)",
    1760             :                            type, ret, strerror(-ret));
    1761           3 :                 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
    1762             :                             match, match_len);
    1763             :         }
    1764       27007 :         return ret;
    1765             : }
    1766             : 
    1767             : 
    1768        2259 : static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
    1769             : {
    1770        2259 :         if (bss->nl_mgmt) {
    1771           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting "
    1772             :                            "already on! (nl_mgmt=%p)", bss->nl_mgmt);
    1773           0 :                 return -1;
    1774             :         }
    1775             : 
    1776        2259 :         bss->nl_mgmt = nl_create_handle(bss->nl_cb, "mgmt");
    1777        2259 :         if (bss->nl_mgmt == NULL)
    1778           0 :                 return -1;
    1779             : 
    1780        2259 :         return 0;
    1781             : }
    1782             : 
    1783             : 
    1784        2259 : static void nl80211_mgmt_handle_register_eloop(struct i802_bss *bss)
    1785             : {
    1786        2259 :         nl80211_register_eloop_read(&bss->nl_mgmt,
    1787             :                                     wpa_driver_nl80211_event_receive,
    1788        2259 :                                     bss->nl_cb);
    1789        2259 : }
    1790             : 
    1791             : 
    1792       15654 : static int nl80211_register_action_frame(struct i802_bss *bss,
    1793             :                                          const u8 *match, size_t match_len)
    1794             : {
    1795       15654 :         u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
    1796       15654 :         return nl80211_register_frame(bss, bss->nl_mgmt,
    1797             :                                       type, match, match_len);
    1798             : }
    1799             : 
    1800             : 
    1801         777 : static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
    1802             : {
    1803         777 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    1804         777 :         int ret = 0;
    1805             : 
    1806         777 :         if (nl80211_alloc_mgmt_handle(bss))
    1807           0 :                 return -1;
    1808         777 :         wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
    1809             :                    "handle %p", bss->nl_mgmt);
    1810             : 
    1811         777 :         if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
    1812          18 :                 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
    1813             : 
    1814             :                 /* register for any AUTH message */
    1815          18 :                 nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0);
    1816             :         }
    1817             : 
    1818             : #ifdef CONFIG_INTERWORKING
    1819             :         /* QoS Map Configure */
    1820         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
    1821           0 :                 ret = -1;
    1822             : #endif /* CONFIG_INTERWORKING */
    1823             : #if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
    1824             :         /* GAS Initial Request */
    1825         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
    1826           0 :                 ret = -1;
    1827             :         /* GAS Initial Response */
    1828         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
    1829           0 :                 ret = -1;
    1830             :         /* GAS Comeback Request */
    1831         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
    1832           0 :                 ret = -1;
    1833             :         /* GAS Comeback Response */
    1834         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
    1835           0 :                 ret = -1;
    1836             :         /* Protected GAS Initial Request */
    1837         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0)
    1838           0 :                 ret = -1;
    1839             :         /* Protected GAS Initial Response */
    1840         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0)
    1841           0 :                 ret = -1;
    1842             :         /* Protected GAS Comeback Request */
    1843         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0)
    1844           0 :                 ret = -1;
    1845             :         /* Protected GAS Comeback Response */
    1846         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0)
    1847           0 :                 ret = -1;
    1848             : #endif /* CONFIG_P2P || CONFIG_INTERWORKING */
    1849             : #ifdef CONFIG_P2P
    1850             :         /* P2P Public Action */
    1851         777 :         if (nl80211_register_action_frame(bss,
    1852             :                                           (u8 *) "\x04\x09\x50\x6f\x9a\x09",
    1853             :                                           6) < 0)
    1854           0 :                 ret = -1;
    1855             :         /* P2P Action */
    1856         777 :         if (nl80211_register_action_frame(bss,
    1857             :                                           (u8 *) "\x7f\x50\x6f\x9a\x09",
    1858             :                                           5) < 0)
    1859           0 :                 ret = -1;
    1860             : #endif /* CONFIG_P2P */
    1861             : #ifdef CONFIG_IEEE80211W
    1862             :         /* SA Query Response */
    1863         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
    1864           0 :                 ret = -1;
    1865             : #endif /* CONFIG_IEEE80211W */
    1866             : #ifdef CONFIG_TDLS
    1867         777 :         if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
    1868             :                 /* TDLS Discovery Response */
    1869         777 :                 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
    1870             :                     0)
    1871           0 :                         ret = -1;
    1872             :         }
    1873             : #endif /* CONFIG_TDLS */
    1874             : 
    1875             :         /* FT Action frames */
    1876         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
    1877           0 :                 ret = -1;
    1878             :         else
    1879         777 :                 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
    1880             :                         WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
    1881             : 
    1882             :         /* WNM - BSS Transition Management Request */
    1883         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
    1884           0 :                 ret = -1;
    1885             :         /* WNM-Sleep Mode Response */
    1886         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
    1887           0 :                 ret = -1;
    1888             : 
    1889             : #ifdef CONFIG_HS20
    1890             :         /* WNM-Notification */
    1891         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0)
    1892           0 :                 ret = -1;
    1893             : #endif /* CONFIG_HS20 */
    1894             : 
    1895             :         /* WMM-AC ADDTS Response */
    1896         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x11\x01", 2) < 0)
    1897           0 :                 ret = -1;
    1898             : 
    1899             :         /* WMM-AC DELTS */
    1900         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x11\x02", 2) < 0)
    1901           0 :                 ret = -1;
    1902             : 
    1903             :         /* Radio Measurement - Neighbor Report Response */
    1904         777 :         if (nl80211_register_action_frame(bss, (u8 *) "\x05\x05", 2) < 0)
    1905           0 :                 ret = -1;
    1906             : 
    1907             :         /* Radio Measurement - Link Measurement Request */
    1908         777 :         if ((drv->capa.rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION) &&
    1909           0 :             (nl80211_register_action_frame(bss, (u8 *) "\x05\x02", 2) < 0))
    1910           0 :                 ret = -1;
    1911             : 
    1912         777 :         nl80211_mgmt_handle_register_eloop(bss);
    1913             : 
    1914         777 :         return ret;
    1915             : }
    1916             : 
    1917             : 
    1918          38 : static int nl80211_mgmt_subscribe_mesh(struct i802_bss *bss)
    1919             : {
    1920          38 :         int ret = 0;
    1921             : 
    1922          38 :         if (nl80211_alloc_mgmt_handle(bss))
    1923           0 :                 return -1;
    1924             : 
    1925          38 :         wpa_printf(MSG_DEBUG,
    1926             :                    "nl80211: Subscribe to mgmt frames with mesh handle %p",
    1927             :                    bss->nl_mgmt);
    1928             : 
    1929             :         /* Auth frames for mesh SAE */
    1930          38 :         if (nl80211_register_frame(bss, bss->nl_mgmt,
    1931             :                                    (WLAN_FC_TYPE_MGMT << 2) |
    1932             :                                    (WLAN_FC_STYPE_AUTH << 4),
    1933             :                                    NULL, 0) < 0)
    1934           0 :                 ret = -1;
    1935             : 
    1936             :         /* Mesh peering open */
    1937          38 :         if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x01", 2) < 0)
    1938           0 :                 ret = -1;
    1939             :         /* Mesh peering confirm */
    1940          38 :         if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x02", 2) < 0)
    1941           0 :                 ret = -1;
    1942             :         /* Mesh peering close */
    1943          38 :         if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x03", 2) < 0)
    1944           0 :                 ret = -1;
    1945             : 
    1946          38 :         nl80211_mgmt_handle_register_eloop(bss);
    1947             : 
    1948          38 :         return ret;
    1949             : }
    1950             : 
    1951             : 
    1952        1444 : static int nl80211_register_spurious_class3(struct i802_bss *bss)
    1953             : {
    1954             :         struct nl_msg *msg;
    1955             :         int ret;
    1956             : 
    1957        1444 :         msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UNEXPECTED_FRAME);
    1958        1444 :         ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL);
    1959        1444 :         if (ret) {
    1960           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
    1961             :                            "failed: ret=%d (%s)",
    1962             :                            ret, strerror(-ret));
    1963             :         }
    1964        1444 :         return ret;
    1965             : }
    1966             : 
    1967             : 
    1968        1444 : static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
    1969             : {
    1970             :         static const int stypes[] = {
    1971             :                 WLAN_FC_STYPE_AUTH,
    1972             :                 WLAN_FC_STYPE_ASSOC_REQ,
    1973             :                 WLAN_FC_STYPE_REASSOC_REQ,
    1974             :                 WLAN_FC_STYPE_DISASSOC,
    1975             :                 WLAN_FC_STYPE_DEAUTH,
    1976             :                 WLAN_FC_STYPE_ACTION,
    1977             :                 WLAN_FC_STYPE_PROBE_REQ,
    1978             : /* Beacon doesn't work as mac80211 doesn't currently allow
    1979             :  * it, but it wouldn't really be the right thing anyway as
    1980             :  * it isn't per interface ... maybe just dump the scan
    1981             :  * results periodically for OLBC?
    1982             :  */
    1983             :                 /* WLAN_FC_STYPE_BEACON, */
    1984             :         };
    1985             :         unsigned int i;
    1986             : 
    1987        1444 :         if (nl80211_alloc_mgmt_handle(bss))
    1988           0 :                 return -1;
    1989        1444 :         wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
    1990             :                    "handle %p", bss->nl_mgmt);
    1991             : 
    1992       11552 :         for (i = 0; i < ARRAY_SIZE(stypes); i++) {
    1993       10108 :                 if (nl80211_register_frame(bss, bss->nl_mgmt,
    1994             :                                            (WLAN_FC_TYPE_MGMT << 2) |
    1995       10108 :                                            (stypes[i] << 4),
    1996             :                                            NULL, 0) < 0) {
    1997           0 :                         goto out_err;
    1998             :                 }
    1999             :         }
    2000             : 
    2001        1444 :         if (nl80211_register_spurious_class3(bss))
    2002           0 :                 goto out_err;
    2003             : 
    2004        1444 :         if (nl80211_get_wiphy_data_ap(bss) == NULL)
    2005           0 :                 goto out_err;
    2006             : 
    2007        1444 :         nl80211_mgmt_handle_register_eloop(bss);
    2008        1444 :         return 0;
    2009             : 
    2010             : out_err:
    2011           0 :         nl_destroy_handles(&bss->nl_mgmt);
    2012           0 :         return -1;
    2013             : }
    2014             : 
    2015             : 
    2016           0 : static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)
    2017             : {
    2018           0 :         if (nl80211_alloc_mgmt_handle(bss))
    2019           0 :                 return -1;
    2020           0 :         wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
    2021             :                    "handle %p (device SME)", bss->nl_mgmt);
    2022             : 
    2023           0 :         if (nl80211_register_frame(bss, bss->nl_mgmt,
    2024             :                                    (WLAN_FC_TYPE_MGMT << 2) |
    2025             :                                    (WLAN_FC_STYPE_ACTION << 4),
    2026             :                                    NULL, 0) < 0)
    2027           0 :                 goto out_err;
    2028             : 
    2029           0 :         nl80211_mgmt_handle_register_eloop(bss);
    2030           0 :         return 0;
    2031             : 
    2032             : out_err:
    2033           0 :         nl_destroy_handles(&bss->nl_mgmt);
    2034           0 :         return -1;
    2035             : }
    2036             : 
    2037             : 
    2038        4524 : static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
    2039             : {
    2040        4524 :         if (bss->nl_mgmt == NULL)
    2041        6789 :                 return;
    2042        2259 :         wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
    2043             :                    "(%s)", bss->nl_mgmt, reason);
    2044        2259 :         nl80211_destroy_eloop_handle(&bss->nl_mgmt);
    2045             : 
    2046        2259 :         nl80211_put_wiphy_data_ap(bss);
    2047             : }
    2048             : 
    2049             : 
    2050           1 : static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
    2051             : {
    2052           1 :         wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
    2053           1 : }
    2054             : 
    2055             : 
    2056           8 : static void nl80211_del_p2pdev(struct i802_bss *bss)
    2057             : {
    2058             :         struct nl_msg *msg;
    2059             :         int ret;
    2060             : 
    2061           8 :         msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_INTERFACE);
    2062           8 :         ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
    2063             : 
    2064          16 :         wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
    2065           8 :                    bss->ifname, (long long unsigned int) bss->wdev_id,
    2066             :                    strerror(-ret));
    2067           8 : }
    2068             : 
    2069             : 
    2070           8 : static int nl80211_set_p2pdev(struct i802_bss *bss, int start)
    2071             : {
    2072             :         struct nl_msg *msg;
    2073             :         int ret;
    2074             : 
    2075           8 :         msg = nl80211_cmd_msg(bss, 0, start ? NL80211_CMD_START_P2P_DEVICE :
    2076             :                               NL80211_CMD_STOP_P2P_DEVICE);
    2077           8 :         ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
    2078             : 
    2079          16 :         wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
    2080             :                    start ? "Start" : "Stop",
    2081           8 :                    bss->ifname, (long long unsigned int) bss->wdev_id,
    2082             :                    strerror(-ret));
    2083           8 :         return ret;
    2084             : }
    2085             : 
    2086             : 
    2087        2560 : static int i802_set_iface_flags(struct i802_bss *bss, int up)
    2088             : {
    2089             :         enum nl80211_iftype nlmode;
    2090             : 
    2091        2560 :         nlmode = nl80211_get_ifmode(bss);
    2092        2560 :         if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
    2093        2552 :                 return linux_set_iface_flags(bss->drv->global->ioctl_sock,
    2094        2552 :                                              bss->ifname, up);
    2095             :         }
    2096             : 
    2097             :         /* P2P Device has start/stop which is equivalent */
    2098           8 :         return nl80211_set_p2pdev(bss, up);
    2099             : }
    2100             : 
    2101             : 
    2102             : #ifdef CONFIG_TESTING_OPTIONS
    2103        1223 : static int qca_vendor_test_cmd_handler(struct nl_msg *msg, void *arg)
    2104             : {
    2105             :         /* struct wpa_driver_nl80211_data *drv = arg; */
    2106             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    2107        1223 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    2108             : 
    2109             : 
    2110        1223 :         wpa_printf(MSG_DEBUG,
    2111             :                    "nl80211: QCA vendor test command response received");
    2112             : 
    2113        1223 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    2114             :                   genlmsg_attrlen(gnlh, 0), NULL);
    2115        1223 :         if (!tb[NL80211_ATTR_VENDOR_DATA]) {
    2116           0 :                 wpa_printf(MSG_DEBUG, "nl80211: No vendor data attribute");
    2117           0 :                 return NL_SKIP;
    2118             :         }
    2119             : 
    2120        2446 :         wpa_hexdump(MSG_DEBUG,
    2121             :                     "nl80211: Received QCA vendor test command response",
    2122        1223 :                     nla_data(tb[NL80211_ATTR_VENDOR_DATA]),
    2123        1223 :                     nla_len(tb[NL80211_ATTR_VENDOR_DATA]));
    2124             : 
    2125        1223 :         return NL_SKIP;
    2126             : }
    2127             : #endif /* CONFIG_TESTING_OPTIONS */
    2128             : 
    2129             : 
    2130        1223 : static void qca_vendor_test(struct wpa_driver_nl80211_data *drv)
    2131             : {
    2132             : #ifdef CONFIG_TESTING_OPTIONS
    2133             :         struct nl_msg *msg;
    2134             :         struct nlattr *params;
    2135             :         int ret;
    2136             : 
    2137        2446 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
    2138        2446 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
    2139        1223 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
    2140        1223 :                         QCA_NL80211_VENDOR_SUBCMD_TEST) ||
    2141        1223 :             !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
    2142        1223 :             nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TEST, 123)) {
    2143           0 :                 nlmsg_free(msg);
    2144        1223 :                 return;
    2145             :         }
    2146        1223 :         nla_nest_end(msg, params);
    2147             : 
    2148        1223 :         ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv);
    2149        1223 :         wpa_printf(MSG_DEBUG,
    2150             :                    "nl80211: QCA vendor test command returned %d (%s)",
    2151             :                    ret, strerror(-ret));
    2152             : #endif /* CONFIG_TESTING_OPTIONS */
    2153             : }
    2154             : 
    2155             : 
    2156             : static int
    2157        1234 : wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
    2158             :                                    const u8 *set_addr, int first,
    2159             :                                    const char *driver_params)
    2160             : {
    2161        1234 :         struct i802_bss *bss = drv->first_bss;
    2162        1234 :         int send_rfkill_event = 0;
    2163             :         enum nl80211_iftype nlmode;
    2164             : 
    2165        1234 :         drv->ifindex = if_nametoindex(bss->ifname);
    2166        1234 :         bss->ifindex = drv->ifindex;
    2167        1234 :         bss->wdev_id = drv->global->if_add_wdevid;
    2168        1234 :         bss->wdev_id_set = drv->global->if_add_wdevid_set;
    2169             : 
    2170        1234 :         bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;
    2171        1234 :         bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
    2172        1234 :         drv->global->if_add_wdevid_set = 0;
    2173             : 
    2174        1234 :         if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
    2175         178 :                 bss->static_ap = 1;
    2176             : 
    2177        1234 :         if (wpa_driver_nl80211_capa(drv))
    2178           3 :                 return -1;
    2179             : 
    2180        1231 :         if (driver_params && nl80211_set_param(bss, driver_params) < 0)
    2181           0 :                 return -1;
    2182             : 
    2183        1231 :         wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
    2184        1231 :                    bss->ifname, drv->phyname);
    2185             : 
    2186        1279 :         if (set_addr &&
    2187          96 :             (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) ||
    2188          48 :              linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
    2189             :                                 set_addr)))
    2190           0 :                 return -1;
    2191             : 
    2192        1231 :         if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
    2193         178 :                 drv->start_mode_ap = 1;
    2194             : 
    2195        1231 :         if (drv->hostapd || bss->static_ap)
    2196        1002 :                 nlmode = NL80211_IFTYPE_AP;
    2197         229 :         else if (bss->if_dynamic)
    2198         143 :                 nlmode = nl80211_get_ifmode(bss);
    2199             :         else
    2200          86 :                 nlmode = NL80211_IFTYPE_STATION;
    2201             : 
    2202        1231 :         if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
    2203           0 :                 wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");
    2204           0 :                 return -1;
    2205             :         }
    2206             : 
    2207        1231 :         if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
    2208           8 :                 nl80211_get_macaddr(bss);
    2209             : 
    2210        1231 :         if (!rfkill_is_blocked(drv->rfkill)) {
    2211        1229 :                 int ret = i802_set_iface_flags(bss, 1);
    2212        1229 :                 if (ret) {
    2213           0 :                         wpa_printf(MSG_ERROR, "nl80211: Could not set "
    2214           0 :                                    "interface '%s' UP", bss->ifname);
    2215           0 :                         return ret;
    2216             :                 }
    2217        1229 :                 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
    2218           8 :                         return ret;
    2219             :         } else {
    2220           2 :                 wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
    2221           2 :                            "interface '%s' due to rfkill", bss->ifname);
    2222           2 :                 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
    2223           0 :                         return 0;
    2224           2 :                 drv->if_disabled = 1;
    2225           2 :                 send_rfkill_event = 1;
    2226             :         }
    2227             : 
    2228        1223 :         if (!drv->hostapd)
    2229         221 :                 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
    2230             :                                        1, IF_OPER_DORMANT);
    2231             : 
    2232        1223 :         if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
    2233        1223 :                                bss->addr))
    2234           0 :                 return -1;
    2235        1223 :         os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
    2236             : 
    2237        1223 :         if (send_rfkill_event) {
    2238           2 :                 eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
    2239             :                                        drv, drv->ctx);
    2240             :         }
    2241             : 
    2242        1223 :         if (drv->vendor_cmd_test_avail)
    2243        1223 :                 qca_vendor_test(drv);
    2244             : 
    2245        1223 :         return 0;
    2246             : }
    2247             : 
    2248             : 
    2249        1415 : static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
    2250             : {
    2251             :         struct nl_msg *msg;
    2252             : 
    2253        1415 :         wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
    2254             :                    drv->ifindex);
    2255        1415 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
    2256        1415 :         return send_and_recv_msgs(drv, msg, NULL, NULL);
    2257             : }
    2258             : 
    2259             : 
    2260             : /**
    2261             :  * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
    2262             :  * @bss: Pointer to private nl80211 data from wpa_driver_nl80211_init()
    2263             :  *
    2264             :  * Shut down driver interface and processing of driver events. Free
    2265             :  * private data buffer if one was allocated in wpa_driver_nl80211_init().
    2266             :  */
    2267        1238 : static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
    2268             : {
    2269        1238 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    2270             : 
    2271        2476 :         wpa_printf(MSG_INFO, "nl80211: deinit ifname=%s disabled_11b_rates=%d",
    2272        2476 :                    bss->ifname, drv->disabled_11b_rates);
    2273             : 
    2274        1238 :         bss->in_deinit = 1;
    2275        1238 :         if (drv->data_tx_status)
    2276        1231 :                 eloop_unregister_read_sock(drv->eapol_tx_sock);
    2277        1238 :         if (drv->eapol_tx_sock >= 0)
    2278        1231 :                 close(drv->eapol_tx_sock);
    2279             : 
    2280        1238 :         if (bss->nl_preq)
    2281           0 :                 wpa_driver_nl80211_probe_req_report(bss, 0);
    2282        1238 :         if (bss->added_if_into_bridge) {
    2283          15 :                 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
    2284          15 :                                     bss->ifname) < 0)
    2285          28 :                         wpa_printf(MSG_INFO, "nl80211: Failed to remove "
    2286             :                                    "interface %s from bridge %s: %s",
    2287          28 :                                    bss->ifname, bss->brname, strerror(errno));
    2288          15 :                 if (drv->rtnl_sk)
    2289          15 :                         nl80211_handle_destroy(drv->rtnl_sk);
    2290             :         }
    2291        1238 :         if (bss->added_bridge) {
    2292          10 :                 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->brname,
    2293             :                                           0) < 0)
    2294           9 :                         wpa_printf(MSG_INFO,
    2295             :                                    "nl80211: Could not set bridge %s down",
    2296           9 :                                    bss->brname);
    2297          10 :                 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
    2298          18 :                         wpa_printf(MSG_INFO, "nl80211: Failed to remove "
    2299             :                                    "bridge %s: %s",
    2300          18 :                                    bss->brname, strerror(errno));
    2301             :         }
    2302             : 
    2303        1238 :         nl80211_remove_monitor_interface(drv);
    2304             : 
    2305        1238 :         if (is_ap_interface(drv->nlmode))
    2306        1103 :                 wpa_driver_nl80211_del_beacon(drv);
    2307             : 
    2308        1238 :         if (drv->eapol_sock >= 0) {
    2309        1002 :                 eloop_unregister_read_sock(drv->eapol_sock);
    2310        1002 :                 close(drv->eapol_sock);
    2311             :         }
    2312             : 
    2313        1238 :         if (drv->if_indices != drv->default_if_indices)
    2314           1 :                 os_free(drv->if_indices);
    2315             : 
    2316        1238 :         if (drv->disabled_11b_rates)
    2317         101 :                 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
    2318             : 
    2319        1238 :         netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
    2320             :                                IF_OPER_UP);
    2321        1238 :         eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
    2322        1238 :         rfkill_deinit(drv->rfkill);
    2323             : 
    2324        1238 :         eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
    2325             : 
    2326        1238 :         if (!drv->start_iface_up)
    2327        1238 :                 (void) i802_set_iface_flags(bss, 0);
    2328             : 
    2329        1238 :         if (drv->addr_changed) {
    2330           3 :                 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
    2331             :                                           0) < 0) {
    2332           0 :                         wpa_printf(MSG_DEBUG,
    2333             :                                    "nl80211: Could not set interface down to restore permanent MAC address");
    2334             :                 }
    2335           3 :                 if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
    2336           3 :                                        drv->perm_addr) < 0) {
    2337           0 :                         wpa_printf(MSG_DEBUG,
    2338             :                                    "nl80211: Could not restore permanent MAC address");
    2339             :                 }
    2340             :         }
    2341             : 
    2342        1238 :         if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
    2343        1230 :                 if (!drv->hostapd || !drv->start_mode_ap)
    2344        1052 :                         wpa_driver_nl80211_set_mode(bss,
    2345             :                                                     NL80211_IFTYPE_STATION);
    2346        1230 :                 nl80211_mgmt_unsubscribe(bss, "deinit");
    2347             :         } else {
    2348           8 :                 nl80211_mgmt_unsubscribe(bss, "deinit");
    2349           8 :                 nl80211_del_p2pdev(bss);
    2350             :         }
    2351             : 
    2352        1238 :         nl80211_destroy_bss(drv->first_bss);
    2353             : 
    2354        1238 :         os_free(drv->filter_ssids);
    2355             : 
    2356        1238 :         os_free(drv->auth_ie);
    2357             : 
    2358        1238 :         if (drv->in_interface_list)
    2359        1231 :                 dl_list_del(&drv->list);
    2360             : 
    2361        1238 :         os_free(drv->extended_capa);
    2362        1238 :         os_free(drv->extended_capa_mask);
    2363        1238 :         os_free(drv->first_bss);
    2364        1238 :         os_free(drv);
    2365        1238 : }
    2366             : 
    2367             : 
    2368        7402 : static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len)
    2369             : {
    2370        7402 :         switch (alg) {
    2371             :         case WPA_ALG_WEP:
    2372         106 :                 if (key_len == 5)
    2373          46 :                         return WLAN_CIPHER_SUITE_WEP40;
    2374          60 :                 return WLAN_CIPHER_SUITE_WEP104;
    2375             :         case WPA_ALG_TKIP:
    2376         173 :                 return WLAN_CIPHER_SUITE_TKIP;
    2377             :         case WPA_ALG_CCMP:
    2378        6756 :                 return WLAN_CIPHER_SUITE_CCMP;
    2379             :         case WPA_ALG_GCMP:
    2380          13 :                 return WLAN_CIPHER_SUITE_GCMP;
    2381             :         case WPA_ALG_CCMP_256:
    2382           5 :                 return WLAN_CIPHER_SUITE_CCMP_256;
    2383             :         case WPA_ALG_GCMP_256:
    2384          13 :                 return WLAN_CIPHER_SUITE_GCMP_256;
    2385             :         case WPA_ALG_IGTK:
    2386         309 :                 return WLAN_CIPHER_SUITE_AES_CMAC;
    2387             :         case WPA_ALG_BIP_GMAC_128:
    2388           7 :                 return WLAN_CIPHER_SUITE_BIP_GMAC_128;
    2389             :         case WPA_ALG_BIP_GMAC_256:
    2390           7 :                 return WLAN_CIPHER_SUITE_BIP_GMAC_256;
    2391             :         case WPA_ALG_BIP_CMAC_256:
    2392           3 :                 return WLAN_CIPHER_SUITE_BIP_CMAC_256;
    2393             :         case WPA_ALG_SMS4:
    2394           0 :                 return WLAN_CIPHER_SUITE_SMS4;
    2395             :         case WPA_ALG_KRK:
    2396           0 :                 return WLAN_CIPHER_SUITE_KRK;
    2397             :         case WPA_ALG_NONE:
    2398             :         case WPA_ALG_PMK:
    2399           8 :                 wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d",
    2400             :                            alg);
    2401           8 :                 return 0;
    2402             :         }
    2403             : 
    2404           2 :         wpa_printf(MSG_ERROR, "nl80211: Unsupported encryption algorithm %d",
    2405             :                    alg);
    2406           2 :         return 0;
    2407             : }
    2408             : 
    2409             : 
    2410        6744 : static u32 wpa_cipher_to_cipher_suite(unsigned int cipher)
    2411             : {
    2412        6744 :         switch (cipher) {
    2413             :         case WPA_CIPHER_CCMP_256:
    2414           3 :                 return WLAN_CIPHER_SUITE_CCMP_256;
    2415             :         case WPA_CIPHER_GCMP_256:
    2416           8 :                 return WLAN_CIPHER_SUITE_GCMP_256;
    2417             :         case WPA_CIPHER_CCMP:
    2418        6043 :                 return WLAN_CIPHER_SUITE_CCMP;
    2419             :         case WPA_CIPHER_GCMP:
    2420           8 :                 return WLAN_CIPHER_SUITE_GCMP;
    2421             :         case WPA_CIPHER_TKIP:
    2422         174 :                 return WLAN_CIPHER_SUITE_TKIP;
    2423             :         case WPA_CIPHER_WEP104:
    2424          32 :                 return WLAN_CIPHER_SUITE_WEP104;
    2425             :         case WPA_CIPHER_WEP40:
    2426          49 :                 return WLAN_CIPHER_SUITE_WEP40;
    2427             :         case WPA_CIPHER_GTK_NOT_USED:
    2428           0 :                 return WLAN_CIPHER_SUITE_NO_GROUP_ADDR;
    2429             :         }
    2430             : 
    2431         427 :         return 0;
    2432             : }
    2433             : 
    2434             : 
    2435        2878 : static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[],
    2436             :                                        int max_suites)
    2437             : {
    2438        2878 :         int num_suites = 0;
    2439             : 
    2440        2878 :         if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP_256)
    2441           1 :                 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP_256;
    2442        2878 :         if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP_256)
    2443           2 :                 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP_256;
    2444        2878 :         if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP)
    2445        2362 :                 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
    2446        2878 :         if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP)
    2447           2 :                 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;
    2448        2878 :         if (num_suites < max_suites && ciphers & WPA_CIPHER_TKIP)
    2449         114 :                 suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
    2450        2878 :         if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP104)
    2451          16 :                 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
    2452        2878 :         if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP40)
    2453          27 :                 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
    2454             : 
    2455        2878 :         return num_suites;
    2456             : }
    2457             : 
    2458             : 
    2459           3 : static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
    2460             :                                   const u8 *key, size_t key_len)
    2461             : {
    2462             :         struct nl_msg *msg;
    2463             :         int ret;
    2464             : 
    2465           3 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD))
    2466           3 :                 return 0;
    2467             : 
    2468           0 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
    2469           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
    2470           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
    2471           0 :                         QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) ||
    2472           0 :             nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) {
    2473           0 :                 nl80211_nlmsg_clear(msg);
    2474           0 :                 nlmsg_free(msg);
    2475           0 :                 return -1;
    2476             :         }
    2477           0 :         ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
    2478           0 :         if (ret) {
    2479           0 :                 wpa_printf(MSG_DEBUG,
    2480             :                            "nl80211: Key management set key failed: ret=%d (%s)",
    2481             :                            ret, strerror(-ret));
    2482             :         }
    2483             : 
    2484           0 :         return ret;
    2485             : }
    2486             : 
    2487             : 
    2488       29081 : static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
    2489             :                                       enum wpa_alg alg, const u8 *addr,
    2490             :                                       int key_idx, int set_tx,
    2491             :                                       const u8 *seq, size_t seq_len,
    2492             :                                       const u8 *key, size_t key_len)
    2493             : {
    2494       29081 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    2495             :         int ifindex;
    2496             :         struct nl_msg *msg;
    2497             :         int ret;
    2498       29081 :         int tdls = 0;
    2499             : 
    2500             :         /* Ignore for P2P Device */
    2501       29081 :         if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
    2502          48 :                 return 0;
    2503             : 
    2504       29033 :         ifindex = if_nametoindex(ifname);
    2505       29033 :         wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
    2506             :                    "set_tx=%d seq_len=%lu key_len=%lu",
    2507             :                    __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
    2508             :                    (unsigned long) seq_len, (unsigned long) key_len);
    2509             : #ifdef CONFIG_TDLS
    2510       12414 :         if (key_idx == -1) {
    2511          74 :                 key_idx = 0;
    2512          74 :                 tdls = 1;
    2513             :         }
    2514             : #endif /* CONFIG_TDLS */
    2515             : 
    2516       29041 :         if (alg == WPA_ALG_PMK &&
    2517           8 :             (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
    2518           0 :                 wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key",
    2519             :                            __func__);
    2520           0 :                 ret = issue_key_mgmt_set_key(drv, key, key_len);
    2521           0 :                 return ret;
    2522             :         }
    2523             : 
    2524       29033 :         if (alg == WPA_ALG_NONE) {
    2525       21654 :                 msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY);
    2526       21654 :                 if (!msg)
    2527           0 :                         return -ENOBUFS;
    2528             :         } else {
    2529        7379 :                 msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY);
    2530       14758 :                 if (!msg ||
    2531       14758 :                     nla_put(msg, NL80211_ATTR_KEY_DATA, key_len, key) ||
    2532        7379 :                     nla_put_u32(msg, NL80211_ATTR_KEY_CIPHER,
    2533             :                                 wpa_alg_to_cipher_suite(alg, key_len)))
    2534             :                         goto fail;
    2535        7379 :                 wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len);
    2536             :         }
    2537             : 
    2538       29033 :         if (seq && seq_len) {
    2539        3573 :                 if (nla_put(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq))
    2540           0 :                         goto fail;
    2541        3573 :                 wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
    2542             :         }
    2543             : 
    2544       29033 :         if (addr && !is_broadcast_ether_addr(addr)) {
    2545       14799 :                 wpa_printf(MSG_DEBUG, "   addr=" MACSTR, MAC2STR(addr));
    2546       14799 :                 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
    2547           0 :                         goto fail;
    2548             : 
    2549       29598 :                 if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
    2550          28 :                         wpa_printf(MSG_DEBUG, "   RSN IBSS RX GTK");
    2551          28 :                         if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE,
    2552             :                                         NL80211_KEYTYPE_GROUP))
    2553           0 :                                 goto fail;
    2554             :                 }
    2555       14234 :         } else if (addr && is_broadcast_ether_addr(addr)) {
    2556             :                 struct nlattr *types;
    2557             : 
    2558        3582 :                 wpa_printf(MSG_DEBUG, "   broadcast key");
    2559             : 
    2560        3582 :                 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
    2561        7164 :                 if (!types ||
    2562        3582 :                     nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
    2563             :                         goto fail;
    2564        3582 :                 nla_nest_end(msg, types);
    2565             :         }
    2566       29033 :         if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
    2567           0 :                 goto fail;
    2568             : 
    2569       29033 :         ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL);
    2570       29033 :         if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
    2571       20275 :                 ret = 0;
    2572       29033 :         if (ret)
    2573         349 :                 wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)",
    2574             :                            ret, strerror(-ret));
    2575             : 
    2576             :         /*
    2577             :          * If we failed or don't need to set the default TX key (below),
    2578             :          * we're done here.
    2579             :          */
    2580       29033 :         if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
    2581       23664 :                 return ret;
    2582        9098 :         if (is_ap_interface(drv->nlmode) && addr &&
    2583        3729 :             !is_broadcast_ether_addr(addr))
    2584        1765 :                 return ret;
    2585             : 
    2586        3604 :         msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY);
    2587        7208 :         if (!msg ||
    2588        7208 :             nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) ||
    2589        3874 :             nla_put_flag(msg, (alg == WPA_ALG_IGTK ||
    2590        3340 :                                alg == WPA_ALG_BIP_GMAC_128 ||
    2591        3336 :                                alg == WPA_ALG_BIP_GMAC_256 ||
    2592             :                                alg == WPA_ALG_BIP_CMAC_256) ?
    2593             :                          NL80211_ATTR_KEY_DEFAULT_MGMT :
    2594             :                          NL80211_ATTR_KEY_DEFAULT))
    2595             :                 goto fail;
    2596        5580 :         if (addr && is_broadcast_ether_addr(addr)) {
    2597             :                 struct nlattr *types;
    2598             : 
    2599        1976 :                 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
    2600        3952 :                 if (!types ||
    2601        1976 :                     nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
    2602             :                         goto fail;
    2603        1976 :                 nla_nest_end(msg, types);
    2604        1628 :         } else if (addr) {
    2605             :                 struct nlattr *types;
    2606             : 
    2607        1564 :                 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
    2608        3128 :                 if (!types ||
    2609        1564 :                     nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST))
    2610             :                         goto fail;
    2611        1564 :                 nla_nest_end(msg, types);
    2612             :         }
    2613             : 
    2614        3604 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    2615        3604 :         if (ret == -ENOENT)
    2616           0 :                 ret = 0;
    2617        3604 :         if (ret)
    2618           0 :                 wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
    2619             :                            "err=%d %s)", ret, strerror(-ret));
    2620        3604 :         return ret;
    2621             : 
    2622             : fail:
    2623           0 :         nl80211_nlmsg_clear(msg);
    2624           0 :         nlmsg_free(msg);
    2625           0 :         return -ENOBUFS;
    2626             : }
    2627             : 
    2628             : 
    2629          23 : static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,
    2630             :                       int key_idx, int defkey,
    2631             :                       const u8 *seq, size_t seq_len,
    2632             :                       const u8 *key, size_t key_len)
    2633             : {
    2634          23 :         struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);
    2635          23 :         if (!key_attr)
    2636           0 :                 return -1;
    2637             : 
    2638          23 :         if (defkey && alg == WPA_ALG_IGTK) {
    2639           0 :                 if (nla_put_flag(msg, NL80211_KEY_DEFAULT_MGMT))
    2640           0 :                         return -1;
    2641          23 :         } else if (defkey) {
    2642          23 :                 if (nla_put_flag(msg, NL80211_KEY_DEFAULT))
    2643           0 :                         return -1;
    2644             :         }
    2645             : 
    2646          46 :         if (nla_put_u8(msg, NL80211_KEY_IDX, key_idx) ||
    2647          23 :             nla_put_u32(msg, NL80211_KEY_CIPHER,
    2648          23 :                         wpa_alg_to_cipher_suite(alg, key_len)) ||
    2649           0 :             (seq && seq_len &&
    2650          23 :              nla_put(msg, NL80211_KEY_SEQ, seq_len, seq)) ||
    2651          23 :             nla_put(msg, NL80211_KEY_DATA, key_len, key))
    2652           0 :                 return -1;
    2653             : 
    2654          23 :         nla_nest_end(msg, key_attr);
    2655             : 
    2656          23 :         return 0;
    2657             : }
    2658             : 
    2659             : 
    2660          46 : static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
    2661             :                                  struct nl_msg *msg)
    2662             : {
    2663          46 :         int i, privacy = 0;
    2664             :         struct nlattr *nl_keys, *nl_key;
    2665             : 
    2666         420 :         for (i = 0; i < 4; i++) {
    2667         169 :                 if (!params->wep_key[i])
    2668         164 :                         continue;
    2669           5 :                 privacy = 1;
    2670           5 :                 break;
    2671             :         }
    2672          46 :         if (params->wps == WPS_MODE_PRIVACY)
    2673           1 :                 privacy = 1;
    2674          92 :         if (params->pairwise_suite &&
    2675          46 :             params->pairwise_suite != WPA_CIPHER_NONE)
    2676          26 :                 privacy = 1;
    2677             : 
    2678          46 :         if (!privacy)
    2679          19 :                 return 0;
    2680             : 
    2681          27 :         if (nla_put_flag(msg, NL80211_ATTR_PRIVACY))
    2682           0 :                 return -ENOBUFS;
    2683             : 
    2684          27 :         nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
    2685          27 :         if (!nl_keys)
    2686           0 :                 return -ENOBUFS;
    2687             : 
    2688         135 :         for (i = 0; i < 4; i++) {
    2689         108 :                 if (!params->wep_key[i])
    2690         103 :                         continue;
    2691             : 
    2692           5 :                 nl_key = nla_nest_start(msg, i);
    2693          10 :                 if (!nl_key ||
    2694           5 :                     nla_put(msg, NL80211_KEY_DATA, params->wep_key_len[i],
    2695          10 :                             params->wep_key[i]) ||
    2696           5 :                     nla_put_u32(msg, NL80211_KEY_CIPHER,
    2697           5 :                                 params->wep_key_len[i] == 5 ?
    2698             :                                 WLAN_CIPHER_SUITE_WEP40 :
    2699           5 :                                 WLAN_CIPHER_SUITE_WEP104) ||
    2700          10 :                     nla_put_u8(msg, NL80211_KEY_IDX, i) ||
    2701          10 :                     (i == params->wep_tx_keyidx &&
    2702           5 :                      nla_put_flag(msg, NL80211_KEY_DEFAULT)))
    2703           0 :                         return -ENOBUFS;
    2704             : 
    2705           5 :                 nla_nest_end(msg, nl_key);
    2706             :         }
    2707          27 :         nla_nest_end(msg, nl_keys);
    2708             : 
    2709          27 :         return 0;
    2710             : }
    2711             : 
    2712             : 
    2713        2277 : int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
    2714             :                             const u8 *addr, int cmd, u16 reason_code,
    2715             :                             int local_state_change)
    2716             : {
    2717             :         int ret;
    2718             :         struct nl_msg *msg;
    2719             : 
    2720        4554 :         if (!(msg = nl80211_drv_msg(drv, 0, cmd)) ||
    2721        4554 :             nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) ||
    2722        2258 :             (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
    2723           0 :             (local_state_change &&
    2724           0 :              nla_put_flag(msg, NL80211_ATTR_LOCAL_STATE_CHANGE))) {
    2725           0 :                 nlmsg_free(msg);
    2726           0 :                 return -1;
    2727             :         }
    2728             : 
    2729        2277 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    2730        2277 :         if (ret) {
    2731         296 :                 wpa_dbg(drv->ctx, MSG_DEBUG,
    2732             :                         "nl80211: MLME command failed: reason=%u ret=%d (%s)",
    2733             :                         reason_code, ret, strerror(-ret));
    2734             :         }
    2735        2277 :         return ret;
    2736             : }
    2737             : 
    2738             : 
    2739          19 : static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
    2740             :                                          int reason_code)
    2741             : {
    2742             :         int ret;
    2743             : 
    2744          19 :         wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
    2745          19 :         nl80211_mark_disconnected(drv);
    2746             :         /* Disconnect command doesn't need BSSID - it uses cached value */
    2747          19 :         ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
    2748             :                                       reason_code, 0);
    2749             :         /*
    2750             :          * For locally generated disconnect, supplicant already generates a
    2751             :          * DEAUTH event, so ignore the event from NL80211.
    2752             :          */
    2753          19 :         drv->ignore_next_local_disconnect = ret == 0;
    2754             : 
    2755          19 :         return ret;
    2756             : }
    2757             : 
    2758             : 
    2759        2293 : static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
    2760             :                                              const u8 *addr, int reason_code)
    2761             : {
    2762        2293 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    2763             :         int ret;
    2764             : 
    2765        2293 :         if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
    2766          18 :                 nl80211_mark_disconnected(drv);
    2767          18 :                 return nl80211_leave_ibss(drv, 1);
    2768             :         }
    2769        2275 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
    2770          17 :                 return wpa_driver_nl80211_disconnect(drv, reason_code);
    2771       13548 :         wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
    2772       13548 :                    __func__, MAC2STR(addr), reason_code);
    2773        2258 :         nl80211_mark_disconnected(drv);
    2774        2258 :         ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
    2775             :                                       reason_code, 0);
    2776             :         /*
    2777             :          * For locally generated deauthenticate, supplicant already generates a
    2778             :          * DEAUTH event, so ignore the event from NL80211.
    2779             :          */
    2780        2258 :         drv->ignore_next_local_deauth = ret == 0;
    2781        2258 :         return ret;
    2782             : }
    2783             : 
    2784             : 
    2785           5 : static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
    2786             :                                      struct wpa_driver_auth_params *params)
    2787             : {
    2788             :         int i;
    2789             : 
    2790           5 :         drv->auth_freq = params->freq;
    2791           5 :         drv->auth_alg = params->auth_alg;
    2792           5 :         drv->auth_wep_tx_keyidx = params->wep_tx_keyidx;
    2793           5 :         drv->auth_local_state_change = params->local_state_change;
    2794           5 :         drv->auth_p2p = params->p2p;
    2795             : 
    2796           5 :         if (params->bssid)
    2797           5 :                 os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);
    2798             :         else
    2799           0 :                 os_memset(drv->auth_bssid_, 0, ETH_ALEN);
    2800             : 
    2801           5 :         if (params->ssid) {
    2802           5 :                 os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);
    2803           5 :                 drv->auth_ssid_len = params->ssid_len;
    2804             :         } else
    2805           0 :                 drv->auth_ssid_len = 0;
    2806             : 
    2807             : 
    2808           5 :         os_free(drv->auth_ie);
    2809           5 :         drv->auth_ie = NULL;
    2810           5 :         drv->auth_ie_len = 0;
    2811           5 :         if (params->ie) {
    2812           0 :                 drv->auth_ie = os_malloc(params->ie_len);
    2813           0 :                 if (drv->auth_ie) {
    2814           0 :                         os_memcpy(drv->auth_ie, params->ie, params->ie_len);
    2815           0 :                         drv->auth_ie_len = params->ie_len;
    2816             :                 }
    2817             :         }
    2818             : 
    2819          25 :         for (i = 0; i < 4; i++) {
    2820          21 :                 if (params->wep_key[i] && params->wep_key_len[i] &&
    2821           1 :                     params->wep_key_len[i] <= 16) {
    2822           1 :                         os_memcpy(drv->auth_wep_key[i], params->wep_key[i],
    2823             :                                   params->wep_key_len[i]);
    2824           1 :                         drv->auth_wep_key_len[i] = params->wep_key_len[i];
    2825             :                 } else
    2826          19 :                         drv->auth_wep_key_len[i] = 0;
    2827             :         }
    2828           5 : }
    2829             : 
    2830             : 
    2831        5596 : static void nl80211_unmask_11b_rates(struct i802_bss *bss)
    2832             : {
    2833        5596 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    2834             : 
    2835        5596 :         if (is_p2p_net_interface(drv->nlmode) || !drv->disabled_11b_rates)
    2836       11191 :                 return;
    2837             : 
    2838             :         /*
    2839             :          * Looks like we failed to unmask 11b rates previously. This could
    2840             :          * happen, e.g., if the interface was down at the point in time when a
    2841             :          * P2P group was terminated.
    2842             :          */
    2843           1 :         wpa_printf(MSG_DEBUG,
    2844             :                    "nl80211: Interface %s mode is for non-P2P, but 11b rates were disabled - re-enable them",
    2845           1 :                    bss->ifname);
    2846           1 :         nl80211_disable_11b_rates(drv, drv->ifindex, 0);
    2847             : }
    2848             : 
    2849             : 
    2850        2718 : static int wpa_driver_nl80211_authenticate(
    2851             :         struct i802_bss *bss, struct wpa_driver_auth_params *params)
    2852             : {
    2853        2718 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    2854        2718 :         int ret = -1, i;
    2855             :         struct nl_msg *msg;
    2856             :         enum nl80211_auth_type type;
    2857             :         enum nl80211_iftype nlmode;
    2858        2718 :         int count = 0;
    2859             :         int is_retry;
    2860             : 
    2861        2718 :         nl80211_unmask_11b_rates(bss);
    2862             : 
    2863        2718 :         is_retry = drv->retry_auth;
    2864        2718 :         drv->retry_auth = 0;
    2865        2718 :         drv->ignore_deauth_event = 0;
    2866             : 
    2867        2718 :         nl80211_mark_disconnected(drv);
    2868        2718 :         os_memset(drv->auth_bssid, 0, ETH_ALEN);
    2869        2718 :         if (params->bssid)
    2870        2718 :                 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
    2871             :         else
    2872           0 :                 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
    2873             :         /* FIX: IBSS mode */
    2874        2718 :         nlmode = params->p2p ?
    2875             :                 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
    2876        2889 :         if (drv->nlmode != nlmode &&
    2877         171 :             wpa_driver_nl80211_set_mode(bss, nlmode) < 0)
    2878           0 :                 return -1;
    2879             : 
    2880             : retry:
    2881        2762 :         wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
    2882             :                    drv->ifindex);
    2883             : 
    2884        2762 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_AUTHENTICATE);
    2885        2762 :         if (!msg)
    2886           0 :                 goto fail;
    2887             : 
    2888       13810 :         for (i = 0; i < 4; i++) {
    2889       11048 :                 if (!params->wep_key[i])
    2890       11019 :                         continue;
    2891          58 :                 wpa_driver_nl80211_set_key(bss->ifname, bss, WPA_ALG_WEP,
    2892             :                                            NULL, i,
    2893          29 :                                            i == params->wep_tx_keyidx, NULL, 0,
    2894             :                                            params->wep_key[i],
    2895             :                                            params->wep_key_len[i]);
    2896          29 :                 if (params->wep_tx_keyidx != i)
    2897           6 :                         continue;
    2898          23 :                 if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
    2899             :                                params->wep_key[i], params->wep_key_len[i]))
    2900           0 :                         goto fail;
    2901             :         }
    2902             : 
    2903        2762 :         if (params->bssid) {
    2904       16572 :                 wpa_printf(MSG_DEBUG, "  * bssid=" MACSTR,
    2905       16572 :                            MAC2STR(params->bssid));
    2906        2762 :                 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
    2907           0 :                         goto fail;
    2908             :         }
    2909        2762 :         if (params->freq) {
    2910        2762 :                 wpa_printf(MSG_DEBUG, "  * freq=%d", params->freq);
    2911        2762 :                 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq))
    2912           0 :                         goto fail;
    2913             :         }
    2914        2762 :         if (params->ssid) {
    2915        5524 :                 wpa_hexdump_ascii(MSG_DEBUG, "  * SSID",
    2916        2762 :                                   params->ssid, params->ssid_len);
    2917        2762 :                 if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len,
    2918        2762 :                             params->ssid))
    2919           0 :                         goto fail;
    2920             :         }
    2921        2762 :         wpa_hexdump(MSG_DEBUG, "  * IEs", params->ie, params->ie_len);
    2922        2875 :         if (params->ie &&
    2923         113 :             nla_put(msg, NL80211_ATTR_IE, params->ie_len, params->ie))
    2924           0 :                 goto fail;
    2925        2762 :         if (params->sae_data) {
    2926          62 :                 wpa_hexdump(MSG_DEBUG, "  * SAE data", params->sae_data,
    2927             :                             params->sae_data_len);
    2928          62 :                 if (nla_put(msg, NL80211_ATTR_SAE_DATA, params->sae_data_len,
    2929          62 :                             params->sae_data))
    2930           0 :                         goto fail;
    2931             :         }
    2932        2762 :         if (params->auth_alg & WPA_AUTH_ALG_OPEN)
    2933        2351 :                 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
    2934         411 :         else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
    2935          12 :                 type = NL80211_AUTHTYPE_SHARED_KEY;
    2936         399 :         else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
    2937           3 :                 type = NL80211_AUTHTYPE_NETWORK_EAP;
    2938         396 :         else if (params->auth_alg & WPA_AUTH_ALG_FT)
    2939         334 :                 type = NL80211_AUTHTYPE_FT;
    2940          62 :         else if (params->auth_alg & WPA_AUTH_ALG_SAE)
    2941          62 :                 type = NL80211_AUTHTYPE_SAE;
    2942             :         else
    2943           0 :                 goto fail;
    2944        2762 :         wpa_printf(MSG_DEBUG, "  * Auth Type %d", type);
    2945        2762 :         if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type))
    2946           0 :                 goto fail;
    2947        2762 :         if (params->local_state_change) {
    2948         221 :                 wpa_printf(MSG_DEBUG, "  * Local state change only");
    2949         221 :                 if (nla_put_flag(msg, NL80211_ATTR_LOCAL_STATE_CHANGE))
    2950           0 :                         goto fail;
    2951             :         }
    2952             : 
    2953        2762 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    2954        2762 :         msg = NULL;
    2955        2762 :         if (ret) {
    2956          51 :                 wpa_dbg(drv->ctx, MSG_DEBUG,
    2957             :                         "nl80211: MLME command failed (auth): ret=%d (%s)",
    2958             :                         ret, strerror(-ret));
    2959          51 :                 count++;
    2960          95 :                 if (ret == -EALREADY && count == 1 && params->bssid &&
    2961          44 :                     !params->local_state_change) {
    2962             :                         /*
    2963             :                          * mac80211 does not currently accept new
    2964             :                          * authentication if we are already authenticated. As a
    2965             :                          * workaround, force deauthentication and try again.
    2966             :                          */
    2967          44 :                         wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
    2968             :                                    "after forced deauthentication");
    2969          44 :                         drv->ignore_deauth_event = 1;
    2970          44 :                         wpa_driver_nl80211_deauthenticate(
    2971             :                                 bss, params->bssid,
    2972             :                                 WLAN_REASON_PREV_AUTH_NOT_VALID);
    2973          44 :                         nlmsg_free(msg);
    2974          44 :                         goto retry;
    2975             :                 }
    2976             : 
    2977          12 :                 if (ret == -ENOENT && params->freq && !is_retry) {
    2978             :                         /*
    2979             :                          * cfg80211 has likely expired the BSS entry even
    2980             :                          * though it was previously available in our internal
    2981             :                          * BSS table. To recover quickly, start a single
    2982             :                          * channel scan on the specified channel.
    2983             :                          */
    2984             :                         struct wpa_driver_scan_params scan;
    2985             :                         int freqs[2];
    2986             : 
    2987           5 :                         os_memset(&scan, 0, sizeof(scan));
    2988           5 :                         scan.num_ssids = 1;
    2989           5 :                         if (params->ssid) {
    2990           5 :                                 scan.ssids[0].ssid = params->ssid;
    2991           5 :                                 scan.ssids[0].ssid_len = params->ssid_len;
    2992             :                         }
    2993           5 :                         freqs[0] = params->freq;
    2994           5 :                         freqs[1] = 0;
    2995           5 :                         scan.freqs = freqs;
    2996           5 :                         wpa_printf(MSG_DEBUG, "nl80211: Trigger single "
    2997             :                                    "channel scan to refresh cfg80211 BSS "
    2998             :                                    "entry");
    2999           5 :                         ret = wpa_driver_nl80211_scan(bss, &scan);
    3000           5 :                         if (ret == 0) {
    3001           5 :                                 nl80211_copy_auth_params(drv, params);
    3002           5 :                                 drv->scan_for_auth = 1;
    3003             :                         }
    3004           2 :                 } else if (is_retry) {
    3005             :                         /*
    3006             :                          * Need to indicate this with an event since the return
    3007             :                          * value from the retry is not delivered to core code.
    3008             :                          */
    3009             :                         union wpa_event_data event;
    3010           2 :                         wpa_printf(MSG_DEBUG, "nl80211: Authentication retry "
    3011             :                                    "failed");
    3012           2 :                         os_memset(&event, 0, sizeof(event));
    3013           2 :                         os_memcpy(event.timeout_event.addr, drv->auth_bssid_,
    3014             :                                   ETH_ALEN);
    3015           2 :                         wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,
    3016             :                                              &event);
    3017             :                 }
    3018             :         } else {
    3019        2711 :                 wpa_printf(MSG_DEBUG,
    3020             :                            "nl80211: Authentication request send successfully");
    3021             :         }
    3022             : 
    3023             : fail:
    3024        2718 :         nlmsg_free(msg);
    3025        2718 :         return ret;
    3026             : }
    3027             : 
    3028             : 
    3029           5 : int wpa_driver_nl80211_authenticate_retry(struct wpa_driver_nl80211_data *drv)
    3030             : {
    3031             :         struct wpa_driver_auth_params params;
    3032           5 :         struct i802_bss *bss = drv->first_bss;
    3033             :         int i;
    3034             : 
    3035           5 :         wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
    3036             : 
    3037           5 :         os_memset(&params, 0, sizeof(params));
    3038           5 :         params.freq = drv->auth_freq;
    3039           5 :         params.auth_alg = drv->auth_alg;
    3040           5 :         params.wep_tx_keyidx = drv->auth_wep_tx_keyidx;
    3041           5 :         params.local_state_change = drv->auth_local_state_change;
    3042           5 :         params.p2p = drv->auth_p2p;
    3043             : 
    3044           5 :         if (!is_zero_ether_addr(drv->auth_bssid_))
    3045           5 :                 params.bssid = drv->auth_bssid_;
    3046             : 
    3047           5 :         if (drv->auth_ssid_len) {
    3048           5 :                 params.ssid = drv->auth_ssid;
    3049           5 :                 params.ssid_len = drv->auth_ssid_len;
    3050             :         }
    3051             : 
    3052           5 :         params.ie = drv->auth_ie;
    3053           5 :         params.ie_len = drv->auth_ie_len;
    3054             : 
    3055          25 :         for (i = 0; i < 4; i++) {
    3056          20 :                 if (drv->auth_wep_key_len[i]) {
    3057           1 :                         params.wep_key[i] = drv->auth_wep_key[i];
    3058           1 :                         params.wep_key_len[i] = drv->auth_wep_key_len[i];
    3059             :                 }
    3060             :         }
    3061             : 
    3062           5 :         drv->retry_auth = 1;
    3063           5 :         return wpa_driver_nl80211_authenticate(bss, &params);
    3064             : }
    3065             : 
    3066             : 
    3067       11657 : static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
    3068             :                                          const void *data, size_t len,
    3069             :                                          int encrypt, int noack,
    3070             :                                          unsigned int freq, int no_cck,
    3071             :                                          int offchanok, unsigned int wait_time)
    3072             : {
    3073       11657 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3074             :         u64 cookie;
    3075             :         int res;
    3076             : 
    3077       11657 :         if (freq == 0 && drv->nlmode == NL80211_IFTYPE_ADHOC) {
    3078          22 :                 freq = nl80211_get_assoc_freq(drv);
    3079          22 :                 wpa_printf(MSG_DEBUG,
    3080             :                            "nl80211: send_frame - Use assoc_freq=%u for IBSS",
    3081             :                            freq);
    3082             :         }
    3083       11657 :         if (freq == 0) {
    3084       11296 :                 wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u",
    3085             :                            bss->freq);
    3086       11296 :                 freq = bss->freq;
    3087             :         }
    3088             : 
    3089       11657 :         if (drv->use_monitor) {
    3090         102 :                 wpa_printf(MSG_DEBUG, "nl80211: send_frame(freq=%u bss->freq=%u) -> send_monitor",
    3091             :                            freq, bss->freq);
    3092         102 :                 return nl80211_send_monitor(drv, data, len, encrypt, noack);
    3093             :         }
    3094             : 
    3095       11555 :         wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
    3096       11555 :         res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
    3097             :                                      &cookie, no_cck, noack, offchanok);
    3098       11555 :         if (res == 0 && !noack) {
    3099             :                 const struct ieee80211_mgmt *mgmt;
    3100             :                 u16 fc;
    3101             : 
    3102        8508 :                 mgmt = (const struct ieee80211_mgmt *) data;
    3103        8508 :                 fc = le_to_host16(mgmt->frame_control);
    3104       17016 :                 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
    3105        8508 :                     WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
    3106        1500 :                         wpa_printf(MSG_MSGDUMP,
    3107             :                                    "nl80211: Update send_action_cookie from 0x%llx to 0x%llx",
    3108             :                                    (long long unsigned int)
    3109         750 :                                    drv->send_action_cookie,
    3110             :                                    (long long unsigned int) cookie);
    3111         750 :                         drv->send_action_cookie = cookie;
    3112             :                 }
    3113             :         }
    3114             : 
    3115       11555 :         return res;
    3116             : }
    3117             : 
    3118             : 
    3119       12257 : static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
    3120             :                                         size_t data_len, int noack,
    3121             :                                         unsigned int freq, int no_cck,
    3122             :                                         int offchanok,
    3123             :                                         unsigned int wait_time)
    3124             : {
    3125       12257 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3126             :         struct ieee80211_mgmt *mgmt;
    3127       12257 :         int encrypt = 1;
    3128             :         u16 fc;
    3129             : 
    3130       12257 :         mgmt = (struct ieee80211_mgmt *) data;
    3131       12257 :         fc = le_to_host16(mgmt->frame_control);
    3132       85799 :         wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR
    3133             :                    " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x (%s) nlmode=%d",
    3134       73542 :                    MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time,
    3135       12257 :                    fc, fc2str(fc), drv->nlmode);
    3136             : 
    3137       23817 :         if ((is_sta_interface(drv->nlmode) ||
    3138       12262 :              drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
    3139        1404 :             WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
    3140         702 :             WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
    3141             :                 /*
    3142             :                  * The use of last_mgmt_freq is a bit of a hack,
    3143             :                  * but it works due to the single-threaded nature
    3144             :                  * of wpa_supplicant.
    3145             :                  */
    3146         672 :                 if (freq == 0) {
    3147         672 :                         wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d",
    3148             :                                    drv->last_mgmt_freq);
    3149         672 :                         freq = drv->last_mgmt_freq;
    3150             :                 }
    3151         672 :                 return nl80211_send_frame_cmd(bss, freq, 0,
    3152             :                                               data, data_len, NULL, 1, noack,
    3153             :                                               1);
    3154             :         }
    3155             : 
    3156       11585 :         if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
    3157           0 :                 if (freq == 0) {
    3158           0 :                         wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d",
    3159             :                                    bss->freq);
    3160           0 :                         freq = bss->freq;
    3161             :                 }
    3162           0 :                 return nl80211_send_frame_cmd(bss, freq,
    3163           0 :                                               (int) freq == bss->freq ? 0 :
    3164             :                                               wait_time,
    3165             :                                               data, data_len,
    3166             :                                               &drv->send_action_cookie,
    3167             :                                               no_cck, noack, offchanok);
    3168             :         }
    3169             : 
    3170       23170 :         if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
    3171       11585 :             WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {
    3172             :                 /*
    3173             :                  * Only one of the authentication frame types is encrypted.
    3174             :                  * In order for static WEP encryption to work properly (i.e.,
    3175             :                  * to not encrypt the frame), we need to tell mac80211 about
    3176             :                  * the frames that must not be encrypted.
    3177             :                  */
    3178        2991 :                 u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
    3179        2991 :                 u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);
    3180        2991 :                 if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)
    3181        2991 :                         encrypt = 0;
    3182             :         }
    3183             : 
    3184       11585 :         wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame");
    3185       11585 :         return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
    3186             :                                              noack, freq, no_cck, offchanok,
    3187             :                                              wait_time);
    3188             : }
    3189             : 
    3190             : 
    3191        2902 : static int nl80211_put_basic_rates(struct nl_msg *msg, const int *basic_rates)
    3192             : {
    3193             :         u8 rates[NL80211_MAX_SUPP_RATES];
    3194        2902 :         u8 rates_len = 0;
    3195             :         int i;
    3196             : 
    3197        2902 :         if (!basic_rates)
    3198           0 :                 return 0;
    3199             : 
    3200       13040 :         for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++)
    3201       10138 :                 rates[rates_len++] = basic_rates[i] / 5;
    3202             : 
    3203        2902 :         return nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
    3204             : }
    3205             : 
    3206             : 
    3207        2869 : static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
    3208             :                            int slot, int ht_opmode, int ap_isolate,
    3209             :                            const int *basic_rates)
    3210             : {
    3211        2869 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3212             :         struct nl_msg *msg;
    3213             : 
    3214        2869 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_BSS)) ||
    3215        2869 :             (cts >= 0 &&
    3216        5738 :              nla_put_u8(msg, NL80211_ATTR_BSS_CTS_PROT, cts)) ||
    3217        2869 :             (preamble >= 0 &&
    3218        5738 :              nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble)) ||
    3219        2765 :             (slot >= 0 &&
    3220        5634 :              nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot)) ||
    3221        2775 :             (ht_opmode >= 0 &&
    3222        5644 :              nla_put_u16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode)) ||
    3223        2869 :             (ap_isolate >= 0 &&
    3224        5738 :              nla_put_u8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate)) ||
    3225        2869 :             nl80211_put_basic_rates(msg, basic_rates)) {
    3226           0 :                 nlmsg_free(msg);
    3227           0 :                 return -ENOBUFS;
    3228             :         }
    3229             : 
    3230        2869 :         return send_and_recv_msgs(drv, msg, NULL, NULL);
    3231             : }
    3232             : 
    3233             : 
    3234           0 : static int wpa_driver_nl80211_set_acl(void *priv,
    3235             :                                       struct hostapd_acl_params *params)
    3236             : {
    3237           0 :         struct i802_bss *bss = priv;
    3238           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3239             :         struct nl_msg *msg;
    3240             :         struct nlattr *acl;
    3241             :         unsigned int i;
    3242             :         int ret;
    3243             : 
    3244           0 :         if (!(drv->capa.max_acl_mac_addrs))
    3245           0 :                 return -ENOTSUP;
    3246             : 
    3247           0 :         if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
    3248           0 :                 return -ENOTSUP;
    3249             : 
    3250           0 :         wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
    3251           0 :                    params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
    3252             : 
    3253           0 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MAC_ACL)) ||
    3254           0 :             nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
    3255             :                         NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
    3256           0 :                         NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) ||
    3257             :             (acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS)) == NULL) {
    3258           0 :                 nlmsg_free(msg);
    3259           0 :                 return -ENOMEM;
    3260             :         }
    3261             : 
    3262           0 :         for (i = 0; i < params->num_mac_acl; i++) {
    3263           0 :                 if (nla_put(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr)) {
    3264           0 :                         nlmsg_free(msg);
    3265           0 :                         return -ENOMEM;
    3266             :                 }
    3267             :         }
    3268             : 
    3269           0 :         nla_nest_end(msg, acl);
    3270             : 
    3271           0 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    3272           0 :         if (ret) {
    3273           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
    3274             :                            ret, strerror(-ret));
    3275             :         }
    3276             : 
    3277           0 :         return ret;
    3278             : }
    3279             : 
    3280             : 
    3281        2930 : static int nl80211_put_beacon_int(struct nl_msg *msg, int beacon_int)
    3282             : {
    3283        2930 :         if (beacon_int > 0) {
    3284        2887 :                 wpa_printf(MSG_DEBUG, "  * beacon_int=%d", beacon_int);
    3285        2887 :                 return nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL,
    3286             :                                    beacon_int);
    3287             :         }
    3288             : 
    3289          43 :         return 0;
    3290             : }
    3291             : 
    3292             : 
    3293        2878 : static int wpa_driver_nl80211_set_ap(void *priv,
    3294             :                                      struct wpa_driver_ap_params *params)
    3295             : {
    3296        2878 :         struct i802_bss *bss = priv;
    3297        2878 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3298             :         struct nl_msg *msg;
    3299        2878 :         u8 cmd = NL80211_CMD_NEW_BEACON;
    3300             :         int ret;
    3301             :         int beacon_set;
    3302             :         int num_suites;
    3303             :         int smps_mode;
    3304             :         u32 suites[10], suite;
    3305             :         u32 ver;
    3306             : 
    3307        2878 :         beacon_set = params->reenable ? 0 : bss->beacon_set;
    3308             : 
    3309        2878 :         wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
    3310             :                    beacon_set);
    3311        2878 :         if (beacon_set)
    3312        1532 :                 cmd = NL80211_CMD_SET_BEACON;
    3313             : 
    3314        5756 :         wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
    3315        2878 :                     params->head, params->head_len);
    3316        5756 :         wpa_hexdump(MSG_DEBUG, "nl80211: Beacon tail",
    3317        2878 :                     params->tail, params->tail_len);
    3318        2878 :         wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", bss->ifindex);
    3319        2878 :         wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int);
    3320        2878 :         wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
    3321        5756 :         wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid",
    3322        2878 :                           params->ssid, params->ssid_len);
    3323        5756 :         if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
    3324        2878 :             nla_put(msg, NL80211_ATTR_BEACON_HEAD, params->head_len,
    3325        5756 :                     params->head) ||
    3326        2878 :             nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len,
    3327        5756 :                     params->tail) ||
    3328        5756 :             nl80211_put_beacon_int(msg, params->beacon_int) ||
    3329        5756 :             nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period) ||
    3330        2878 :             nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
    3331             :                 goto fail;
    3332        2878 :         if (params->proberesp && params->proberesp_len) {
    3333           0 :                 wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)",
    3334           0 :                             params->proberesp, params->proberesp_len);
    3335           0 :                 if (nla_put(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
    3336           0 :                             params->proberesp))
    3337           0 :                         goto fail;
    3338             :         }
    3339        2878 :         switch (params->hide_ssid) {
    3340             :         case NO_SSID_HIDING:
    3341        2869 :                 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID not in use");
    3342        2869 :                 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
    3343             :                                 NL80211_HIDDEN_SSID_NOT_IN_USE))
    3344           0 :                         goto fail;
    3345        2869 :                 break;
    3346             :         case HIDDEN_SSID_ZERO_LEN:
    3347           8 :                 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero len");
    3348           8 :                 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
    3349             :                                 NL80211_HIDDEN_SSID_ZERO_LEN))
    3350           0 :                         goto fail;
    3351           8 :                 break;
    3352             :         case HIDDEN_SSID_ZERO_CONTENTS:
    3353           1 :                 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero contents");
    3354           1 :                 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
    3355             :                                 NL80211_HIDDEN_SSID_ZERO_CONTENTS))
    3356           0 :                         goto fail;
    3357           1 :                 break;
    3358             :         }
    3359        2878 :         wpa_printf(MSG_DEBUG, "nl80211: privacy=%d", params->privacy);
    3360        5319 :         if (params->privacy &&
    3361        2441 :             nla_put_flag(msg, NL80211_ATTR_PRIVACY))
    3362           0 :                 goto fail;
    3363        2878 :         wpa_printf(MSG_DEBUG, "nl80211: auth_algs=0x%x", params->auth_algs);
    3364        2878 :         if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
    3365             :             (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
    3366             :                 /* Leave out the attribute */
    3367        1570 :         } else if (params->auth_algs & WPA_AUTH_ALG_SHARED) {
    3368          22 :                 if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE,
    3369             :                                 NL80211_AUTHTYPE_SHARED_KEY))
    3370           0 :                         goto fail;
    3371             :         } else {
    3372        1548 :                 if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE,
    3373             :                                 NL80211_AUTHTYPE_OPEN_SYSTEM))
    3374           0 :                         goto fail;
    3375             :         }
    3376             : 
    3377        2878 :         wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version);
    3378        2878 :         ver = 0;
    3379        2878 :         if (params->wpa_version & WPA_PROTO_WPA)
    3380          99 :                 ver |= NL80211_WPA_VERSION_1;
    3381        2878 :         if (params->wpa_version & WPA_PROTO_RSN)
    3382        2366 :                 ver |= NL80211_WPA_VERSION_2;
    3383        5275 :         if (ver &&
    3384        2397 :             nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver))
    3385           0 :                 goto fail;
    3386             : 
    3387        2878 :         wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x",
    3388             :                    params->key_mgmt_suites);
    3389        2878 :         num_suites = 0;
    3390        2878 :         if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
    3391         399 :                 suites[num_suites++] = WLAN_AKM_SUITE_8021X;
    3392        2878 :         if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
    3393        1962 :                 suites[num_suites++] = WLAN_AKM_SUITE_PSK;
    3394        5219 :         if (num_suites &&
    3395        2341 :             nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32),
    3396             :                     suites))
    3397           0 :                 goto fail;
    3398             : 
    3399        2886 :         if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
    3400          13 :             params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40) &&
    3401           5 :             nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
    3402           0 :                 goto fail;
    3403             : 
    3404        2878 :         wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
    3405             :                    params->pairwise_ciphers);
    3406        2878 :         num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers,
    3407             :                                                  suites, ARRAY_SIZE(suites));
    3408        5329 :         if (num_suites &&
    3409        2451 :             nla_put(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
    3410             :                     num_suites * sizeof(u32), suites))
    3411           0 :                 goto fail;
    3412             : 
    3413        2878 :         wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x",
    3414             :                    params->group_cipher);
    3415        2878 :         suite = wpa_cipher_to_cipher_suite(params->group_cipher);
    3416        5329 :         if (suite &&
    3417        2451 :             nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite))
    3418           0 :                 goto fail;
    3419             : 
    3420        2878 :         switch (params->smps_mode) {
    3421             :         case HT_CAP_INFO_SMPS_DYNAMIC:
    3422           1 :                 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - dynamic");
    3423           1 :                 smps_mode = NL80211_SMPS_DYNAMIC;
    3424           1 :                 break;
    3425             :         case HT_CAP_INFO_SMPS_STATIC:
    3426           1 :                 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - static");
    3427           1 :                 smps_mode = NL80211_SMPS_STATIC;
    3428           1 :                 break;
    3429             :         default:
    3430             :                 /* invalid - fallback to smps off */
    3431             :         case HT_CAP_INFO_SMPS_DISABLED:
    3432        2876 :                 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - off");
    3433        2876 :                 smps_mode = NL80211_SMPS_OFF;
    3434        2876 :                 break;
    3435             :         }
    3436        2878 :         if (nla_put_u32(msg, NL80211_ATTR_SMPS_MODE, smps_mode))
    3437           0 :                 goto fail;
    3438             : 
    3439        2878 :         if (params->beacon_ies) {
    3440        2878 :                 wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
    3441             :                                 params->beacon_ies);
    3442        5756 :                 if (nla_put(msg, NL80211_ATTR_IE,
    3443        2878 :                             wpabuf_len(params->beacon_ies),
    3444             :                             wpabuf_head(params->beacon_ies)))
    3445           0 :                         goto fail;
    3446             :         }
    3447        2878 :         if (params->proberesp_ies) {
    3448        2878 :                 wpa_hexdump_buf(MSG_DEBUG, "nl80211: proberesp_ies",
    3449             :                                 params->proberesp_ies);
    3450        5756 :                 if (nla_put(msg, NL80211_ATTR_IE_PROBE_RESP,
    3451        2878 :                             wpabuf_len(params->proberesp_ies),
    3452             :                             wpabuf_head(params->proberesp_ies)))
    3453           0 :                         goto fail;
    3454             :         }
    3455        2878 :         if (params->assocresp_ies) {
    3456        2878 :                 wpa_hexdump_buf(MSG_DEBUG, "nl80211: assocresp_ies",
    3457             :                                 params->assocresp_ies);
    3458        5756 :                 if (nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP,
    3459        2878 :                             wpabuf_len(params->assocresp_ies),
    3460             :                             wpabuf_head(params->assocresp_ies)))
    3461           0 :                         goto fail;
    3462             :         }
    3463             : 
    3464        2878 :         if (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)  {
    3465           0 :                 wpa_printf(MSG_DEBUG, "nl80211: ap_max_inactivity=%d",
    3466             :                            params->ap_max_inactivity);
    3467           0 :                 if (nla_put_u16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT,
    3468           0 :                                 params->ap_max_inactivity))
    3469           0 :                         goto fail;
    3470             :         }
    3471             : 
    3472             : #ifdef CONFIG_P2P
    3473        1528 :         if (params->p2p_go_ctwindow > 0) {
    3474           0 :                 if (drv->p2p_go_ctwindow_supported) {
    3475           0 :                         wpa_printf(MSG_DEBUG, "nl80211: P2P GO ctwindow=%d",
    3476           0 :                                    params->p2p_go_ctwindow);
    3477           0 :                         if (nla_put_u8(msg, NL80211_ATTR_P2P_CTWINDOW,
    3478           0 :                                        params->p2p_go_ctwindow))
    3479           0 :                                 goto fail;
    3480             :                 } else {
    3481           0 :                         wpa_printf(MSG_INFO,
    3482             :                                    "nl80211: Driver does not support CTWindow configuration - ignore this parameter");
    3483             :                 }
    3484             :         }
    3485             : #endif /* CONFIG_P2P */
    3486             : 
    3487        2878 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    3488        2878 :         if (ret) {
    3489           9 :                 wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
    3490             :                            ret, strerror(-ret));
    3491             :         } else {
    3492        2869 :                 bss->beacon_set = 1;
    3493        2869 :                 nl80211_set_bss(bss, params->cts_protect, params->preamble,
    3494             :                                 params->short_slot_time, params->ht_opmode,
    3495        2869 :                                 params->isolate, params->basic_rates);
    3496        4401 :                 if (beacon_set && params->freq &&
    3497        1532 :                     params->freq->bandwidth != bss->bandwidth) {
    3498          16 :                         wpa_printf(MSG_DEBUG,
    3499             :                                    "nl80211: Update BSS %s bandwidth: %d -> %d",
    3500           8 :                                    bss->ifname, bss->bandwidth,
    3501           8 :                                    params->freq->bandwidth);
    3502           8 :                         ret = nl80211_set_channel(bss, params->freq, 1);
    3503          16 :                         if (ret) {
    3504           0 :                                 wpa_printf(MSG_DEBUG,
    3505             :                                            "nl80211: Frequency set failed: %d (%s)",
    3506             :                                            ret, strerror(-ret));
    3507             :                         } else {
    3508           8 :                                 wpa_printf(MSG_DEBUG,
    3509             :                                            "nl80211: Frequency set succeeded for ht2040 coex");
    3510           8 :                                 bss->bandwidth = params->freq->bandwidth;
    3511             :                         }
    3512        2861 :                 } else if (!beacon_set) {
    3513             :                         /*
    3514             :                          * cfg80211 updates the driver on frequence change in AP
    3515             :                          * mode only at the point when beaconing is started, so
    3516             :                          * set the initial value here.
    3517             :                          */
    3518        1337 :                         bss->bandwidth = params->freq->bandwidth;
    3519             :                 }
    3520             :         }
    3521        2878 :         return ret;
    3522             : fail:
    3523           0 :         nlmsg_free(msg);
    3524           0 :         return -ENOBUFS;
    3525             : }
    3526             : 
    3527             : 
    3528        1710 : static int nl80211_put_freq_params(struct nl_msg *msg,
    3529             :                                    const struct hostapd_freq_params *freq)
    3530             : {
    3531        1710 :         wpa_printf(MSG_DEBUG, "  * freq=%d", freq->freq);
    3532        1710 :         if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
    3533           0 :                 return -ENOBUFS;
    3534             : 
    3535        1710 :         wpa_printf(MSG_DEBUG, "  * vht_enabled=%d", freq->vht_enabled);
    3536        1710 :         wpa_printf(MSG_DEBUG, "  * ht_enabled=%d", freq->ht_enabled);
    3537             : 
    3538        1710 :         if (freq->vht_enabled) {
    3539             :                 enum nl80211_chan_width cw;
    3540             : 
    3541          29 :                 wpa_printf(MSG_DEBUG, "  * bandwidth=%d", freq->bandwidth);
    3542          29 :                 switch (freq->bandwidth) {
    3543             :                 case 20:
    3544          12 :                         cw = NL80211_CHAN_WIDTH_20;
    3545          12 :                         break;
    3546             :                 case 40:
    3547           2 :                         cw = NL80211_CHAN_WIDTH_40;
    3548           2 :                         break;
    3549             :                 case 80:
    3550          10 :                         if (freq->center_freq2)
    3551           2 :                                 cw = NL80211_CHAN_WIDTH_80P80;
    3552             :                         else
    3553           8 :                                 cw = NL80211_CHAN_WIDTH_80;
    3554          10 :                         break;
    3555             :                 case 160:
    3556           4 :                         cw = NL80211_CHAN_WIDTH_160;
    3557           4 :                         break;
    3558             :                 default:
    3559           1 :                         return -EINVAL;
    3560             :                 }
    3561             : 
    3562          28 :                 wpa_printf(MSG_DEBUG, "  * channel_width=%d", cw);
    3563          28 :                 wpa_printf(MSG_DEBUG, "  * center_freq1=%d",
    3564             :                            freq->center_freq1);
    3565          28 :                 wpa_printf(MSG_DEBUG, "  * center_freq2=%d",
    3566             :                            freq->center_freq2);
    3567          56 :                 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cw) ||
    3568          28 :                     nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1,
    3569          56 :                                 freq->center_freq1) ||
    3570          30 :                     (freq->center_freq2 &&
    3571           2 :                      nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2,
    3572           2 :                                  freq->center_freq2)))
    3573           0 :                         return -ENOBUFS;
    3574        1681 :         } else if (freq->ht_enabled) {
    3575             :                 enum nl80211_channel_type ct;
    3576             : 
    3577        1335 :                 wpa_printf(MSG_DEBUG, "  * sec_channel_offset=%d",
    3578             :                            freq->sec_channel_offset);
    3579        1335 :                 switch (freq->sec_channel_offset) {
    3580             :                 case -1:
    3581          14 :                         ct = NL80211_CHAN_HT40MINUS;
    3582          14 :                         break;
    3583             :                 case 1:
    3584          30 :                         ct = NL80211_CHAN_HT40PLUS;
    3585          30 :                         break;
    3586             :                 default:
    3587        1291 :                         ct = NL80211_CHAN_HT20;
    3588        1291 :                         break;
    3589             :                 }
    3590             : 
    3591        1335 :                 wpa_printf(MSG_DEBUG, "  * channel_type=%d", ct);
    3592        1335 :                 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct))
    3593           0 :                         return -ENOBUFS;
    3594             :         }
    3595        1709 :         return 0;
    3596             : }
    3597             : 
    3598             : 
    3599        1621 : static int nl80211_set_channel(struct i802_bss *bss,
    3600             :                                struct hostapd_freq_params *freq, int set_chan)
    3601             : {
    3602        1621 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3603             :         struct nl_msg *msg;
    3604             :         int ret;
    3605             : 
    3606        1621 :         wpa_printf(MSG_DEBUG,
    3607             :                    "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
    3608             :                    freq->freq, freq->ht_enabled, freq->vht_enabled,
    3609             :                    freq->bandwidth, freq->center_freq1, freq->center_freq2);
    3610             : 
    3611        1621 :         msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
    3612             :                               NL80211_CMD_SET_WIPHY);
    3613        1621 :         if (!msg || nl80211_put_freq_params(msg, freq) < 0) {
    3614           0 :                 nlmsg_free(msg);
    3615           0 :                 return -1;
    3616             :         }
    3617             : 
    3618        1621 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    3619        1621 :         if (ret == 0) {
    3620        1620 :                 bss->freq = freq->freq;
    3621        1620 :                 return 0;
    3622             :         }
    3623           1 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
    3624             :                    "%d (%s)", freq->freq, ret, strerror(-ret));
    3625           1 :         return -1;
    3626             : }
    3627             : 
    3628             : 
    3629       19348 : static u32 sta_flags_nl80211(int flags)
    3630             : {
    3631       19348 :         u32 f = 0;
    3632             : 
    3633       19348 :         if (flags & WPA_STA_AUTHORIZED)
    3634        7462 :                 f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
    3635       19348 :         if (flags & WPA_STA_WMM)
    3636        7776 :                 f |= BIT(NL80211_STA_FLAG_WME);
    3637       19348 :         if (flags & WPA_STA_SHORT_PREAMBLE)
    3638        7571 :                 f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
    3639       19348 :         if (flags & WPA_STA_MFP)
    3640        2667 :                 f |= BIT(NL80211_STA_FLAG_MFP);
    3641       19348 :         if (flags & WPA_STA_TDLS_PEER)
    3642         107 :                 f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
    3643       19348 :         if (flags & WPA_STA_AUTHENTICATED)
    3644         100 :                 f |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
    3645             : 
    3646       19348 :         return f;
    3647             : }
    3648             : 
    3649             : 
    3650             : #ifdef CONFIG_MESH
    3651         211 : static u32 sta_plink_state_nl80211(enum mesh_plink_state state)
    3652             : {
    3653         211 :         switch (state) {
    3654             :         case PLINK_LISTEN:
    3655          55 :                 return NL80211_PLINK_LISTEN;
    3656             :         case PLINK_OPEN_SENT:
    3657          43 :                 return NL80211_PLINK_OPN_SNT;
    3658             :         case PLINK_OPEN_RCVD:
    3659          31 :                 return NL80211_PLINK_OPN_RCVD;
    3660             :         case PLINK_CNF_RCVD:
    3661           0 :                 return NL80211_PLINK_CNF_RCVD;
    3662             :         case PLINK_ESTAB:
    3663          26 :                 return NL80211_PLINK_ESTAB;
    3664             :         case PLINK_HOLDING:
    3665          54 :                 return NL80211_PLINK_HOLDING;
    3666             :         case PLINK_BLOCKED:
    3667           2 :                 return NL80211_PLINK_BLOCKED;
    3668             :         default:
    3669           0 :                 wpa_printf(MSG_ERROR, "nl80211: Invalid mesh plink state %d",
    3670             :                            state);
    3671             :         }
    3672           0 :         return -1;
    3673             : }
    3674             : #endif /* CONFIG_MESH */
    3675             : 
    3676             : 
    3677        2879 : static int wpa_driver_nl80211_sta_add(void *priv,
    3678             :                                       struct hostapd_sta_add_params *params)
    3679             : {
    3680        2879 :         struct i802_bss *bss = priv;
    3681        2879 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3682             :         struct nl_msg *msg;
    3683             :         struct nl80211_sta_flag_update upd;
    3684        2879 :         int ret = -ENOBUFS;
    3685             : 
    3686        2986 :         if ((params->flags & WPA_STA_TDLS_PEER) &&
    3687         107 :             !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
    3688           0 :                 return -EOPNOTSUPP;
    3689             : 
    3690       20153 :         wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR,
    3691       20153 :                    params->set ? "Set" : "Add", MAC2STR(params->addr));
    3692        2879 :         msg = nl80211_bss_msg(bss, 0, params->set ? NL80211_CMD_SET_STATION :
    3693             :                               NL80211_CMD_NEW_STATION);
    3694        2879 :         if (!msg || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr))
    3695             :                 goto fail;
    3696             : 
    3697        2879 :         if (!params->set || (params->flags & WPA_STA_TDLS_PEER)) {
    3698        5430 :                 wpa_hexdump(MSG_DEBUG, "  * supported rates",
    3699        2715 :                             params->supp_rates, params->supp_rates_len);
    3700        2715 :                 wpa_printf(MSG_DEBUG, "  * capability=0x%x",
    3701        2715 :                            params->capability);
    3702        2715 :                 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_RATES,
    3703        5430 :                             params->supp_rates_len, params->supp_rates) ||
    3704        2715 :                     nla_put_u16(msg, NL80211_ATTR_STA_CAPABILITY,
    3705        2715 :                                 params->capability))
    3706             :                         goto fail;
    3707             : 
    3708        2715 :                 if (params->ht_capabilities) {
    3709        2634 :                         wpa_hexdump(MSG_DEBUG, "  * ht_capabilities",
    3710        2634 :                                     (u8 *) params->ht_capabilities,
    3711             :                                     sizeof(*params->ht_capabilities));
    3712        2634 :                         if (nla_put(msg, NL80211_ATTR_HT_CAPABILITY,
    3713             :                                     sizeof(*params->ht_capabilities),
    3714        2634 :                                     params->ht_capabilities))
    3715           0 :                                 goto fail;
    3716             :                 }
    3717             : 
    3718        2715 :                 if (params->vht_capabilities) {
    3719          90 :                         wpa_hexdump(MSG_DEBUG, "  * vht_capabilities",
    3720          90 :                                     (u8 *) params->vht_capabilities,
    3721             :                                     sizeof(*params->vht_capabilities));
    3722          90 :                         if (nla_put(msg, NL80211_ATTR_VHT_CAPABILITY,
    3723             :                                     sizeof(*params->vht_capabilities),
    3724          90 :                                     params->vht_capabilities))
    3725           0 :                                 goto fail;
    3726             :                 }
    3727             : 
    3728        2715 :                 if (params->ext_capab) {
    3729         152 :                         wpa_hexdump(MSG_DEBUG, "  * ext_capab",
    3730          76 :                                     params->ext_capab, params->ext_capab_len);
    3731          76 :                         if (nla_put(msg, NL80211_ATTR_STA_EXT_CAPABILITY,
    3732          76 :                                     params->ext_capab_len, params->ext_capab))
    3733           0 :                                 goto fail;
    3734             :                 }
    3735             :         }
    3736        2879 :         if (!params->set) {
    3737        2666 :                 if (params->aid) {
    3738        2580 :                         wpa_printf(MSG_DEBUG, "  * aid=%u", params->aid);
    3739        2580 :                         if (nla_put_u16(msg, NL80211_ATTR_STA_AID, params->aid))
    3740           0 :                                 goto fail;
    3741             :                 } else {
    3742             :                         /*
    3743             :                          * cfg80211 validates that AID is non-zero, so we have
    3744             :                          * to make this a non-zero value for the TDLS case where
    3745             :                          * a dummy STA entry is used for now.
    3746             :                          */
    3747          86 :                         wpa_printf(MSG_DEBUG, "  * aid=1 (TDLS workaround)");
    3748          86 :                         if (nla_put_u16(msg, NL80211_ATTR_STA_AID, 1))
    3749           0 :                                 goto fail;
    3750             :                 }
    3751        2666 :                 wpa_printf(MSG_DEBUG, "  * listen_interval=%u",
    3752        2666 :                            params->listen_interval);
    3753        2666 :                 if (nla_put_u16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
    3754        2666 :                                 params->listen_interval))
    3755           0 :                         goto fail;
    3756         213 :         } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
    3757          48 :                 wpa_printf(MSG_DEBUG, "  * peer_aid=%u", params->aid);
    3758          48 :                 if (nla_put_u16(msg, NL80211_ATTR_PEER_AID, params->aid))
    3759           0 :                         goto fail;
    3760             :         }
    3761             : 
    3762        2879 :         if (params->vht_opmode_enabled) {
    3763           0 :                 wpa_printf(MSG_DEBUG, "  * opmode=%u", params->vht_opmode);
    3764           0 :                 if (nla_put_u8(msg, NL80211_ATTR_OPMODE_NOTIF,
    3765           0 :                                params->vht_opmode))
    3766           0 :                         goto fail;
    3767             :         }
    3768             : 
    3769        2879 :         if (params->supp_channels) {
    3770         152 :                 wpa_hexdump(MSG_DEBUG, "  * supported channels",
    3771          76 :                             params->supp_channels, params->supp_channels_len);
    3772          76 :                 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_CHANNELS,
    3773          76 :                             params->supp_channels_len, params->supp_channels))
    3774           0 :                         goto fail;
    3775             :         }
    3776             : 
    3777        2879 :         if (params->supp_oper_classes) {
    3778           0 :                 wpa_hexdump(MSG_DEBUG, "  * supported operating classes",
    3779           0 :                             params->supp_oper_classes,
    3780             :                             params->supp_oper_classes_len);
    3781           0 :                 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
    3782           0 :                             params->supp_oper_classes_len,
    3783           0 :                             params->supp_oper_classes))
    3784           0 :                         goto fail;
    3785             :         }
    3786             : 
    3787        2879 :         os_memset(&upd, 0, sizeof(upd));
    3788        2879 :         upd.set = sta_flags_nl80211(params->flags);
    3789        2879 :         upd.mask = upd.set | sta_flags_nl80211(params->flags_mask);
    3790        2879 :         wpa_printf(MSG_DEBUG, "  * flags set=0x%x mask=0x%x",
    3791             :                    upd.set, upd.mask);
    3792        2879 :         if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
    3793           0 :                 goto fail;
    3794             : 
    3795             : #ifdef CONFIG_MESH
    3796         943 :         if (params->plink_state &&
    3797         211 :             nla_put_u8(msg, NL80211_ATTR_STA_PLINK_STATE,
    3798         211 :                        sta_plink_state_nl80211(params->plink_state)))
    3799           0 :                 goto fail;
    3800             : #endif /* CONFIG_MESH */
    3801             : 
    3802        2879 :         if (params->flags & WPA_STA_WMM) {
    3803        2677 :                 struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME);
    3804             : 
    3805        2677 :                 wpa_printf(MSG_DEBUG, "  * qosinfo=0x%x", params->qosinfo);
    3806        5354 :                 if (!wme ||
    3807        2677 :                     nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
    3808        5354 :                                params->qosinfo & WMM_QOSINFO_STA_AC_MASK) ||
    3809        2677 :                     nla_put_u8(msg, NL80211_STA_WME_MAX_SP,
    3810        2677 :                                (params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &
    3811             :                                WMM_QOSINFO_STA_SP_MASK))
    3812             :                         goto fail;
    3813        2677 :                 nla_nest_end(msg, wme);
    3814             :         }
    3815             : 
    3816        2879 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    3817        2879 :         msg = NULL;
    3818        2879 :         if (ret)
    3819          26 :                 wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
    3820          13 :                            "result: %d (%s)", params->set ? "SET" : "NEW", ret,
    3821             :                            strerror(-ret));
    3822        2879 :         if (ret == -EEXIST)
    3823          13 :                 ret = 0;
    3824             : fail:
    3825        2879 :         nlmsg_free(msg);
    3826        2879 :         return ret;
    3827             : }
    3828             : 
    3829             : 
    3830          45 : static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
    3831             : {
    3832             : #ifdef CONFIG_LIBNL3_ROUTE
    3833          45 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3834             :         struct rtnl_neigh *rn;
    3835             :         struct nl_addr *nl_addr;
    3836             :         int err;
    3837             : 
    3838          45 :         rn = rtnl_neigh_alloc();
    3839          45 :         if (!rn)
    3840           0 :                 return;
    3841             : 
    3842          45 :         rtnl_neigh_set_family(rn, AF_BRIDGE);
    3843          45 :         rtnl_neigh_set_ifindex(rn, bss->ifindex);
    3844          45 :         nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
    3845          45 :         if (!nl_addr) {
    3846           0 :                 rtnl_neigh_put(rn);
    3847           0 :                 return;
    3848             :         }
    3849          45 :         rtnl_neigh_set_lladdr(rn, nl_addr);
    3850             : 
    3851          45 :         err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
    3852          45 :         if (err < 0) {
    3853         196 :                 wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
    3854         168 :                            MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
    3855             :                            bss->ifindex, nl_geterror(err));
    3856             :         } else {
    3857         102 :                 wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for "
    3858         102 :                            MACSTR, MAC2STR(addr));
    3859             :         }
    3860             : 
    3861          45 :         nl_addr_put(nl_addr);
    3862          45 :         rtnl_neigh_put(rn);
    3863             : #endif /* CONFIG_LIBNL3_ROUTE */
    3864           0 : }
    3865             : 
    3866             : 
    3867        4744 : static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr,
    3868             :                                          int deauth, u16 reason_code)
    3869             : {
    3870        4744 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    3871             :         struct nl_msg *msg;
    3872             :         int ret;
    3873             : 
    3874        9488 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION)) ||
    3875        9488 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
    3876           0 :             (deauth == 0 &&
    3877           0 :              nla_put_u8(msg, NL80211_ATTR_MGMT_SUBTYPE,
    3878        4744 :                         WLAN_FC_STYPE_DISASSOC)) ||
    3879           0 :             (deauth == 1 &&
    3880           0 :              nla_put_u8(msg, NL80211_ATTR_MGMT_SUBTYPE,
    3881        4744 :                         WLAN_FC_STYPE_DEAUTH)) ||
    3882           0 :             (reason_code &&
    3883           0 :              nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) {
    3884           0 :                 nlmsg_free(msg);
    3885           0 :                 return -ENOBUFS;
    3886             :         }
    3887             : 
    3888        4744 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    3889       37952 :         wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
    3890             :                    " --> %d (%s)",
    3891       33208 :                    bss->ifname, MAC2STR(addr), ret, strerror(-ret));
    3892             : 
    3893        4744 :         if (drv->rtnl_sk)
    3894          45 :                 rtnl_neigh_delete_fdb_entry(bss, addr);
    3895             : 
    3896        4744 :         if (ret == -ENOENT)
    3897        2332 :                 return 0;
    3898        2412 :         return ret;
    3899             : }
    3900             : 
    3901             : 
    3902         198 : void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx)
    3903             : {
    3904             :         struct nl_msg *msg;
    3905             :         struct wpa_driver_nl80211_data *drv2;
    3906             : 
    3907         198 :         wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx);
    3908             : 
    3909             :         /* stop listening for EAPOL on this interface */
    3910        2424 :         dl_list_for_each(drv2, &drv->global->interfaces,
    3911             :                          struct wpa_driver_nl80211_data, list)
    3912        2226 :                 del_ifidx(drv2, ifidx);
    3913             : 
    3914         198 :         msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
    3915         198 :         if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
    3916         396 :                 return;
    3917           0 :         wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
    3918             : }
    3919             : 
    3920             : 
    3921        3555 : static const char * nl80211_iftype_str(enum nl80211_iftype mode)
    3922             : {
    3923        3555 :         switch (mode) {
    3924             :         case NL80211_IFTYPE_ADHOC:
    3925          18 :                 return "ADHOC";
    3926             :         case NL80211_IFTYPE_STATION:
    3927        1631 :                 return "STATION";
    3928             :         case NL80211_IFTYPE_AP:
    3929        1058 :                 return "AP";
    3930             :         case NL80211_IFTYPE_AP_VLAN:
    3931          14 :                 return "AP_VLAN";
    3932             :         case NL80211_IFTYPE_WDS:
    3933           0 :                 return "WDS";
    3934             :         case NL80211_IFTYPE_MONITOR:
    3935           7 :                 return "MONITOR";
    3936             :         case NL80211_IFTYPE_MESH_POINT:
    3937          72 :                 return "MESH_POINT";
    3938             :         case NL80211_IFTYPE_P2P_CLIENT:
    3939         246 :                 return "P2P_CLIENT";
    3940             :         case NL80211_IFTYPE_P2P_GO:
    3941         493 :                 return "P2P_GO";
    3942             :         case NL80211_IFTYPE_P2P_DEVICE:
    3943          16 :                 return "P2P_DEVICE";
    3944             :         default:
    3945           0 :                 return "unknown";
    3946             :         }
    3947             : }
    3948             : 
    3949             : 
    3950         214 : static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
    3951             :                                      const char *ifname,
    3952             :                                      enum nl80211_iftype iftype,
    3953             :                                      const u8 *addr, int wds,
    3954             :                                      int (*handler)(struct nl_msg *, void *),
    3955             :                                      void *arg)
    3956             : {
    3957             :         struct nl_msg *msg;
    3958             :         int ifidx;
    3959         214 :         int ret = -ENOBUFS;
    3960             : 
    3961         214 :         wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)",
    3962             :                    iftype, nl80211_iftype_str(iftype));
    3963             : 
    3964         214 :         msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_NEW_INTERFACE);
    3965         428 :         if (!msg ||
    3966         428 :             nla_put_string(msg, NL80211_ATTR_IFNAME, ifname) ||
    3967         214 :             nla_put_u32(msg, NL80211_ATTR_IFTYPE, iftype))
    3968             :                 goto fail;
    3969             : 
    3970         214 :         if (iftype == NL80211_IFTYPE_MONITOR) {
    3971             :                 struct nlattr *flags;
    3972             : 
    3973           7 :                 flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS);
    3974          14 :                 if (!flags ||
    3975           7 :                     nla_put_flag(msg, NL80211_MNTR_FLAG_COOK_FRAMES))
    3976             :                         goto fail;
    3977             : 
    3978           7 :                 nla_nest_end(msg, flags);
    3979         207 :         } else if (wds) {
    3980           1 :                 if (nla_put_u8(msg, NL80211_ATTR_4ADDR, wds))
    3981           0 :                         goto fail;
    3982             :         }
    3983             : 
    3984             :         /*
    3985             :          * Tell cfg80211 that the interface belongs to the socket that created
    3986             :          * it, and the interface should be deleted when the socket is closed.
    3987             :          */
    3988         214 :         if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER))
    3989           0 :                 goto fail;
    3990             : 
    3991         214 :         ret = send_and_recv_msgs(drv, msg, handler, arg);
    3992         214 :         msg = NULL;
    3993         214 :         if (ret) {
    3994             :         fail:
    3995           2 :                 nlmsg_free(msg);
    3996           2 :                 wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)",
    3997             :                            ifname, ret, strerror(-ret));
    3998           2 :                 return ret;
    3999             :         }
    4000             : 
    4001         212 :         if (iftype == NL80211_IFTYPE_P2P_DEVICE)
    4002           8 :                 return 0;
    4003             : 
    4004         204 :         ifidx = if_nametoindex(ifname);
    4005         204 :         wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d",
    4006             :                    ifname, ifidx);
    4007             : 
    4008         204 :         if (ifidx <= 0)
    4009           0 :                 return -1;
    4010             : 
    4011             :         /*
    4012             :          * Some virtual interfaces need to process EAPOL packets and events on
    4013             :          * the parent interface. This is used mainly with hostapd.
    4014             :          */
    4015         204 :         if (drv->hostapd ||
    4016         147 :             iftype == NL80211_IFTYPE_AP_VLAN ||
    4017         147 :             iftype == NL80211_IFTYPE_WDS ||
    4018             :             iftype == NL80211_IFTYPE_MONITOR) {
    4019             :                 /* start listening for EAPOL on this interface */
    4020          62 :                 add_ifidx(drv, ifidx);
    4021             :         }
    4022             : 
    4023         259 :         if (addr && iftype != NL80211_IFTYPE_MONITOR &&
    4024          55 :             linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
    4025           0 :                 nl80211_remove_iface(drv, ifidx);
    4026           0 :                 return -1;
    4027             :         }
    4028             : 
    4029         204 :         return ifidx;
    4030             : }
    4031             : 
    4032             : 
    4033         213 : int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
    4034             :                          const char *ifname, enum nl80211_iftype iftype,
    4035             :                          const u8 *addr, int wds,
    4036             :                          int (*handler)(struct nl_msg *, void *),
    4037             :                          void *arg, int use_existing)
    4038             : {
    4039             :         int ret;
    4040             : 
    4041         213 :         ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler,
    4042             :                                         arg);
    4043             : 
    4044             :         /* if error occurred and interface exists already */
    4045         213 :         if (ret == -ENFILE && if_nametoindex(ifname)) {
    4046           2 :                 if (use_existing) {
    4047           1 :                         wpa_printf(MSG_DEBUG, "nl80211: Continue using existing interface %s",
    4048             :                                    ifname);
    4049           2 :                         if (addr && iftype != NL80211_IFTYPE_MONITOR &&
    4050           1 :                             linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
    4051           0 :                                                addr) < 0 &&
    4052           0 :                             (linux_set_iface_flags(drv->global->ioctl_sock,
    4053           0 :                                                    ifname, 0) < 0 ||
    4054           0 :                              linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
    4055           0 :                                                 addr) < 0 ||
    4056           0 :                              linux_set_iface_flags(drv->global->ioctl_sock,
    4057             :                                                    ifname, 1) < 0))
    4058           0 :                                         return -1;
    4059           1 :                         return -ENFILE;
    4060             :                 }
    4061           1 :                 wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname);
    4062             : 
    4063             :                 /* Try to remove the interface that was already there. */
    4064           1 :                 nl80211_remove_iface(drv, if_nametoindex(ifname));
    4065             : 
    4066             :                 /* Try to create the interface again */
    4067           1 :                 ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
    4068             :                                                 wds, handler, arg);
    4069             :         }
    4070             : 
    4071         212 :         if (ret >= 0 && is_p2p_net_interface(iftype)) {
    4072         138 :                 wpa_printf(MSG_DEBUG,
    4073             :                            "nl80211: Interface %s created for P2P - disable 11b rates",
    4074             :                            ifname);
    4075         138 :                 nl80211_disable_11b_rates(drv, ret, 1);
    4076             :         }
    4077             : 
    4078         212 :         return ret;
    4079             : }
    4080             : 
    4081             : 
    4082        1452 : static int nl80211_setup_ap(struct i802_bss *bss)
    4083             : {
    4084        1452 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    4085             : 
    4086        4356 :         wpa_printf(MSG_DEBUG, "nl80211: Setup AP(%s) - device_ap_sme=%d use_monitor=%d",
    4087        4356 :                    bss->ifname, drv->device_ap_sme, drv->use_monitor);
    4088             : 
    4089             :         /*
    4090             :          * Disable Probe Request reporting unless we need it in this way for
    4091             :          * devices that include the AP SME, in the other case (unless using
    4092             :          * monitor iface) we'll get it through the nl_mgmt socket instead.
    4093             :          */
    4094        1452 :         if (!drv->device_ap_sme)
    4095        1452 :                 wpa_driver_nl80211_probe_req_report(bss, 0);
    4096             : 
    4097        1452 :         if (!drv->device_ap_sme && !drv->use_monitor)
    4098        1444 :                 if (nl80211_mgmt_subscribe_ap(bss))
    4099           0 :                         return -1;
    4100             : 
    4101        1452 :         if (drv->device_ap_sme && !drv->use_monitor)
    4102           0 :                 if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
    4103           0 :                         return -1;
    4104             : 
    4105        1460 :         if (!drv->device_ap_sme && drv->use_monitor &&
    4106           8 :             nl80211_create_monitor_interface(drv) &&
    4107           0 :             !drv->device_ap_sme)
    4108           0 :                 return -1;
    4109             : 
    4110        1452 :         if (drv->device_ap_sme &&
    4111           0 :             wpa_driver_nl80211_probe_req_report(bss, 1) < 0) {
    4112           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Failed to enable "
    4113             :                            "Probe Request frame reporting in AP mode");
    4114             :                 /* Try to survive without this */
    4115             :         }
    4116             : 
    4117        1452 :         return 0;
    4118             : }
    4119             : 
    4120             : 
    4121        1176 : static void nl80211_teardown_ap(struct i802_bss *bss)
    4122             : {
    4123        1176 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    4124             : 
    4125        3528 :         wpa_printf(MSG_DEBUG, "nl80211: Teardown AP(%s) - device_ap_sme=%d use_monitor=%d",
    4126        3528 :                    bss->ifname, drv->device_ap_sme, drv->use_monitor);
    4127        1176 :         if (drv->device_ap_sme) {
    4128           0 :                 wpa_driver_nl80211_probe_req_report(bss, 0);
    4129           0 :                 if (!drv->use_monitor)
    4130           0 :                         nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)");
    4131        1176 :         } else if (drv->use_monitor)
    4132           7 :                 nl80211_remove_monitor_interface(drv);
    4133             :         else
    4134        1169 :                 nl80211_mgmt_unsubscribe(bss, "AP teardown");
    4135             : 
    4136        1176 :         bss->beacon_set = 0;
    4137        1176 : }
    4138             : 
    4139             : 
    4140        9440 : static int nl80211_send_eapol_data(struct i802_bss *bss,
    4141             :                                    const u8 *addr, const u8 *data,
    4142             :                                    size_t data_len)
    4143             : {
    4144             :         struct sockaddr_ll ll;
    4145             :         int ret;
    4146             : 
    4147        9440 :         if (bss->drv->eapol_tx_sock < 0) {
    4148           0 :                 wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL");
    4149           0 :                 return -1;
    4150             :         }
    4151             : 
    4152        9440 :         os_memset(&ll, 0, sizeof(ll));
    4153        9440 :         ll.sll_family = AF_PACKET;
    4154        9440 :         ll.sll_ifindex = bss->ifindex;
    4155        9440 :         ll.sll_protocol = htons(ETH_P_PAE);
    4156        9440 :         ll.sll_halen = ETH_ALEN;
    4157        9440 :         os_memcpy(ll.sll_addr, addr, ETH_ALEN);
    4158        9440 :         ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,
    4159             :                      (struct sockaddr *) &ll, sizeof(ll));
    4160        9440 :         if (ret < 0)
    4161           0 :                 wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s",
    4162           0 :                            strerror(errno));
    4163             : 
    4164        9440 :         return ret;
    4165             : }
    4166             : 
    4167             : 
    4168             : static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
    4169             : 
    4170        9452 : static int wpa_driver_nl80211_hapd_send_eapol(
    4171             :         void *priv, const u8 *addr, const u8 *data,
    4172             :         size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
    4173             : {
    4174        9452 :         struct i802_bss *bss = priv;
    4175        9452 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    4176             :         struct ieee80211_hdr *hdr;
    4177             :         size_t len;
    4178             :         u8 *pos;
    4179             :         int res;
    4180        9452 :         int qos = flags & WPA_STA_WMM;
    4181             : 
    4182        9452 :         if (drv->device_ap_sme || !drv->use_monitor)
    4183        9440 :                 return nl80211_send_eapol_data(bss, addr, data, data_len);
    4184             : 
    4185          12 :         len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
    4186             :                 data_len;
    4187          12 :         hdr = os_zalloc(len);
    4188          12 :         if (hdr == NULL) {
    4189           0 :                 wpa_printf(MSG_INFO, "nl80211: Failed to allocate EAPOL buffer(len=%lu)",
    4190             :                            (unsigned long) len);
    4191           0 :                 return -1;
    4192             :         }
    4193             : 
    4194          12 :         hdr->frame_control =
    4195             :                 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
    4196          12 :         hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
    4197          12 :         if (encrypt)
    4198           0 :                 hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
    4199          12 :         if (qos) {
    4200          12 :                 hdr->frame_control |=
    4201             :                         host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
    4202             :         }
    4203             : 
    4204          12 :         memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
    4205          12 :         memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
    4206          12 :         memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
    4207          12 :         pos = (u8 *) (hdr + 1);
    4208             : 
    4209          12 :         if (qos) {
    4210             :                 /* Set highest priority in QoS header */
    4211          12 :                 pos[0] = 7;
    4212          12 :                 pos[1] = 0;
    4213          12 :                 pos += 2;
    4214             :         }
    4215             : 
    4216          12 :         memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
    4217          12 :         pos += sizeof(rfc1042_header);
    4218          12 :         WPA_PUT_BE16(pos, ETH_P_PAE);
    4219          12 :         pos += 2;
    4220          12 :         memcpy(pos, data, data_len);
    4221             : 
    4222          12 :         res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
    4223             :                                             0, 0, 0, 0);
    4224          12 :         if (res < 0) {
    4225           0 :                 wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
    4226             :                            "failed: %d (%s)",
    4227           0 :                            (unsigned long) len, errno, strerror(errno));
    4228             :         }
    4229          12 :         os_free(hdr);
    4230             : 
    4231          12 :         return res;
    4232             : }
    4233             : 
    4234             : 
    4235        6795 : static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
    4236             :                                             int total_flags,
    4237             :                                             int flags_or, int flags_and)
    4238             : {
    4239        6795 :         struct i802_bss *bss = priv;
    4240             :         struct nl_msg *msg;
    4241             :         struct nlattr *flags;
    4242             :         struct nl80211_sta_flag_update upd;
    4243             : 
    4244       54360 :         wpa_printf(MSG_DEBUG, "nl80211: Set STA flags - ifname=%s addr=" MACSTR
    4245             :                    " total_flags=0x%x flags_or=0x%x flags_and=0x%x authorized=%d",
    4246       47565 :                    bss->ifname, MAC2STR(addr), total_flags, flags_or, flags_and,
    4247        6795 :                    !!(total_flags & WPA_STA_AUTHORIZED));
    4248             : 
    4249       13590 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
    4250        6795 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
    4251             :                 goto fail;
    4252             : 
    4253             :         /*
    4254             :          * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
    4255             :          * can be removed eventually.
    4256             :          */
    4257        6795 :         flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS);
    4258       13590 :         if (!flags ||
    4259        8725 :             ((total_flags & WPA_STA_AUTHORIZED) &&
    4260        8725 :              nla_put_flag(msg, NL80211_STA_FLAG_AUTHORIZED)) ||
    4261       13545 :             ((total_flags & WPA_STA_WMM) &&
    4262       13545 :              nla_put_flag(msg, NL80211_STA_FLAG_WME)) ||
    4263       13480 :             ((total_flags & WPA_STA_SHORT_PREAMBLE) &&
    4264       13480 :              nla_put_flag(msg, NL80211_STA_FLAG_SHORT_PREAMBLE)) ||
    4265        6946 :             ((total_flags & WPA_STA_MFP) &&
    4266        6946 :              nla_put_flag(msg, NL80211_STA_FLAG_MFP)) ||
    4267        6795 :             ((total_flags & WPA_STA_TDLS_PEER) &&
    4268           0 :              nla_put_flag(msg, NL80211_STA_FLAG_TDLS_PEER)))
    4269             :                 goto fail;
    4270             : 
    4271        6795 :         nla_nest_end(msg, flags);
    4272             : 
    4273        6795 :         os_memset(&upd, 0, sizeof(upd));
    4274        6795 :         upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
    4275        6795 :         upd.set = sta_flags_nl80211(flags_or);
    4276        6795 :         if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
    4277           0 :                 goto fail;
    4278             : 
    4279        6795 :         return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
    4280             : fail:
    4281           0 :         nlmsg_free(msg);
    4282           0 :         return -ENOBUFS;
    4283             : }
    4284             : 
    4285             : 
    4286         312 : static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
    4287             :                                  struct wpa_driver_associate_params *params)
    4288             : {
    4289             :         enum nl80211_iftype nlmode, old_mode;
    4290             : 
    4291         312 :         if (params->p2p) {
    4292         298 :                 wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
    4293             :                            "group (GO)");
    4294         298 :                 nlmode = NL80211_IFTYPE_P2P_GO;
    4295             :         } else
    4296          14 :                 nlmode = NL80211_IFTYPE_AP;
    4297             : 
    4298         312 :         old_mode = drv->nlmode;
    4299         312 :         if (wpa_driver_nl80211_set_mode(drv->first_bss, nlmode)) {
    4300           0 :                 nl80211_remove_monitor_interface(drv);
    4301           0 :                 return -1;
    4302             :         }
    4303             : 
    4304         623 :         if (params->freq.freq &&
    4305         311 :             nl80211_set_channel(drv->first_bss, &params->freq, 0)) {
    4306           1 :                 if (old_mode != nlmode)
    4307           1 :                         wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
    4308           1 :                 nl80211_remove_monitor_interface(drv);
    4309           1 :                 return -1;
    4310             :         }
    4311             : 
    4312         311 :         return 0;
    4313             : }
    4314             : 
    4315             : 
    4316          19 : static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
    4317             :                               int reset_mode)
    4318             : {
    4319             :         struct nl_msg *msg;
    4320             :         int ret;
    4321             : 
    4322          19 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
    4323          19 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    4324          19 :         if (ret) {
    4325           1 :                 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
    4326             :                            "(%s)", ret, strerror(-ret));
    4327             :         } else {
    4328          18 :                 wpa_printf(MSG_DEBUG,
    4329             :                            "nl80211: Leave IBSS request sent successfully");
    4330             :         }
    4331             : 
    4332          37 :         if (reset_mode &&
    4333          18 :             wpa_driver_nl80211_set_mode(drv->first_bss,
    4334             :                                         NL80211_IFTYPE_STATION)) {
    4335           0 :                 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
    4336             :                            "station mode");
    4337             :         }
    4338             : 
    4339          19 :         return ret;
    4340             : }
    4341             : 
    4342             : 
    4343        2569 : static int nl80211_ht_vht_overrides(struct nl_msg *msg,
    4344             :                                     struct wpa_driver_associate_params *params)
    4345             : {
    4346        2569 :         if (params->disable_ht && nla_put_flag(msg, NL80211_ATTR_DISABLE_HT))
    4347           0 :                 return -1;
    4348             : 
    4349        2569 :         if (params->htcaps && params->htcaps_mask) {
    4350        2569 :                 int sz = sizeof(struct ieee80211_ht_capabilities);
    4351        2569 :                 wpa_hexdump(MSG_DEBUG, "  * htcaps", params->htcaps, sz);
    4352        5138 :                 wpa_hexdump(MSG_DEBUG, "  * htcaps_mask",
    4353        2569 :                             params->htcaps_mask, sz);
    4354        2569 :                 if (nla_put(msg, NL80211_ATTR_HT_CAPABILITY, sz,
    4355        5138 :                             params->htcaps) ||
    4356        2569 :                     nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
    4357        2569 :                             params->htcaps_mask))
    4358           0 :                         return -1;
    4359             :         }
    4360             : 
    4361             : #ifdef CONFIG_VHT_OVERRIDES
    4362        2569 :         if (params->disable_vht) {
    4363           1 :                 wpa_printf(MSG_DEBUG, "  * VHT disabled");
    4364           1 :                 if (nla_put_flag(msg, NL80211_ATTR_DISABLE_VHT))
    4365           0 :                         return -1;
    4366             :         }
    4367             : 
    4368        2569 :         if (params->vhtcaps && params->vhtcaps_mask) {
    4369        2569 :                 int sz = sizeof(struct ieee80211_vht_capabilities);
    4370        2569 :                 wpa_hexdump(MSG_DEBUG, "  * vhtcaps", params->vhtcaps, sz);
    4371        5138 :                 wpa_hexdump(MSG_DEBUG, "  * vhtcaps_mask",
    4372        2569 :                             params->vhtcaps_mask, sz);
    4373        2569 :                 if (nla_put(msg, NL80211_ATTR_VHT_CAPABILITY, sz,
    4374        5138 :                             params->vhtcaps) ||
    4375        2569 :                     nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
    4376        2569 :                             params->vhtcaps_mask))
    4377           0 :                         return -1;
    4378             :         }
    4379             : #endif /* CONFIG_VHT_OVERRIDES */
    4380             : 
    4381        2569 :         return 0;
    4382             : }
    4383             : 
    4384             : 
    4385          18 : static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
    4386             :                                    struct wpa_driver_associate_params *params)
    4387             : {
    4388             :         struct nl_msg *msg;
    4389          18 :         int ret = -1;
    4390          18 :         int count = 0;
    4391             : 
    4392          18 :         wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
    4393             : 
    4394          18 :         if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, &params->freq)) {
    4395           0 :                 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
    4396             :                            "IBSS mode");
    4397           0 :                 return -1;
    4398             :         }
    4399             : 
    4400             : retry:
    4401          38 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_IBSS)) ||
    4402          38 :             params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
    4403             :                 goto fail;
    4404             : 
    4405          38 :         wpa_hexdump_ascii(MSG_DEBUG, "  * SSID",
    4406          19 :                           params->ssid, params->ssid_len);
    4407          19 :         if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
    4408           0 :                 goto fail;
    4409          19 :         os_memcpy(drv->ssid, params->ssid, params->ssid_len);
    4410          19 :         drv->ssid_len = params->ssid_len;
    4411             : 
    4412          38 :         if (nl80211_put_freq_params(msg, &params->freq) < 0 ||
    4413          19 :             nl80211_put_beacon_int(msg, params->beacon_int))
    4414             :                 goto fail;
    4415             : 
    4416          19 :         ret = nl80211_set_conn_keys(params, msg);
    4417          19 :         if (ret)
    4418           0 :                 goto fail;
    4419             : 
    4420          19 :         if (params->bssid && params->fixed_bssid) {
    4421          24 :                 wpa_printf(MSG_DEBUG, "  * BSSID=" MACSTR,
    4422          24 :                            MAC2STR(params->bssid));
    4423           4 :                 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
    4424           0 :                         goto fail;
    4425             :         }
    4426             : 
    4427          19 :         if (params->fixed_freq) {
    4428           0 :                 wpa_printf(MSG_DEBUG, "  * fixed_freq");
    4429           0 :                 if (nla_put_flag(msg, NL80211_ATTR_FREQ_FIXED))
    4430           0 :                         goto fail;
    4431             :         }
    4432             : 
    4433          38 :         if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
    4434          32 :             params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
    4435          26 :             params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
    4436          13 :             params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) {
    4437           6 :                 wpa_printf(MSG_DEBUG, "  * control port");
    4438           6 :                 if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
    4439           0 :                         goto fail;
    4440             :         }
    4441             : 
    4442          19 :         if (params->wpa_ie) {
    4443          38 :                 wpa_hexdump(MSG_DEBUG,
    4444             :                             "  * Extra IEs for Beacon/Probe Response frames",
    4445          19 :                             params->wpa_ie, params->wpa_ie_len);
    4446          19 :                 if (nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len,
    4447          19 :                             params->wpa_ie))
    4448           0 :                         goto fail;
    4449             :         }
    4450             : 
    4451          19 :         if (nl80211_ht_vht_overrides(msg, params) < 0)
    4452           0 :                 return -1;
    4453             : 
    4454          19 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    4455          19 :         msg = NULL;
    4456          19 :         if (ret) {
    4457           1 :                 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
    4458             :                            ret, strerror(-ret));
    4459           1 :                 count++;
    4460           1 :                 if (ret == -EALREADY && count == 1) {
    4461           1 :                         wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after "
    4462             :                                    "forced leave");
    4463           1 :                         nl80211_leave_ibss(drv, 0);
    4464           1 :                         nlmsg_free(msg);
    4465           1 :                         goto retry;
    4466             :                 }
    4467             :         } else {
    4468          18 :                 wpa_printf(MSG_DEBUG,
    4469             :                            "nl80211: Join IBSS request sent successfully");
    4470             :         }
    4471             : 
    4472             : fail:
    4473          18 :         nlmsg_free(msg);
    4474          18 :         return ret;
    4475             : }
    4476             : 
    4477             : 
    4478        2550 : static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
    4479             :                                   struct wpa_driver_associate_params *params,
    4480             :                                   struct nl_msg *msg)
    4481             : {
    4482        2550 :         if (params->bssid) {
    4483       15258 :                 wpa_printf(MSG_DEBUG, "  * bssid=" MACSTR,
    4484       15258 :                            MAC2STR(params->bssid));
    4485        2543 :                 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
    4486           0 :                         return -1;
    4487             :         }
    4488             : 
    4489        2550 :         if (params->bssid_hint) {
    4490         126 :                 wpa_printf(MSG_DEBUG, "  * bssid_hint=" MACSTR,
    4491         126 :                            MAC2STR(params->bssid_hint));
    4492          21 :                 if (nla_put(msg, NL80211_ATTR_MAC_HINT, ETH_ALEN,
    4493          21 :                             params->bssid_hint))
    4494           0 :                         return -1;
    4495             :         }
    4496             : 
    4497        2550 :         if (params->freq.freq) {
    4498        2543 :                 wpa_printf(MSG_DEBUG, "  * freq=%d", params->freq.freq);
    4499        2543 :                 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
    4500        2543 :                                 params->freq.freq))
    4501           0 :                         return -1;
    4502        2543 :                 drv->assoc_freq = params->freq.freq;
    4503             :         } else
    4504           7 :                 drv->assoc_freq = 0;
    4505             : 
    4506        2550 :         if (params->freq_hint) {
    4507          21 :                 wpa_printf(MSG_DEBUG, "  * freq_hint=%d", params->freq_hint);
    4508          21 :                 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_HINT,
    4509          21 :                                 params->freq_hint))
    4510           0 :                         return -1;
    4511             :         }
    4512             : 
    4513        2550 :         if (params->bg_scan_period >= 0) {
    4514           3 :                 wpa_printf(MSG_DEBUG, "  * bg scan period=%d",
    4515             :                            params->bg_scan_period);
    4516           3 :                 if (nla_put_u16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
    4517           3 :                                 params->bg_scan_period))
    4518           0 :                         return -1;
    4519             :         }
    4520             : 
    4521        2550 :         if (params->ssid) {
    4522        5100 :                 wpa_hexdump_ascii(MSG_DEBUG, "  * SSID",
    4523        2550 :                                   params->ssid, params->ssid_len);
    4524        2550 :                 if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len,
    4525        2550 :                             params->ssid))
    4526           0 :                         return -1;
    4527        2550 :                 if (params->ssid_len > sizeof(drv->ssid))
    4528           0 :                         return -1;
    4529        2550 :                 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
    4530        2550 :                 drv->ssid_len = params->ssid_len;
    4531             :         }
    4532             : 
    4533        2550 :         wpa_hexdump(MSG_DEBUG, "  * IEs", params->wpa_ie, params->wpa_ie_len);
    4534        5100 :         if (params->wpa_ie &&
    4535        2550 :             nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len, params->wpa_ie))
    4536           0 :                 return -1;
    4537             : 
    4538        2550 :         if (params->wpa_proto) {
    4539        2422 :                 enum nl80211_wpa_versions ver = 0;
    4540             : 
    4541        2422 :                 if (params->wpa_proto & WPA_PROTO_WPA)
    4542          23 :                         ver |= NL80211_WPA_VERSION_1;
    4543        2422 :                 if (params->wpa_proto & WPA_PROTO_RSN)
    4544        2397 :                         ver |= NL80211_WPA_VERSION_2;
    4545             : 
    4546        2422 :                 wpa_printf(MSG_DEBUG, "  * WPA Versions 0x%x", ver);
    4547        2422 :                 if (nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver))
    4548           0 :                         return -1;
    4549             :         }
    4550             : 
    4551        2550 :         if (params->pairwise_suite != WPA_CIPHER_NONE) {
    4552        1934 :                 u32 cipher = wpa_cipher_to_cipher_suite(params->pairwise_suite);
    4553        1934 :                 wpa_printf(MSG_DEBUG, "  * pairwise=0x%x", cipher);
    4554        1934 :                 if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
    4555             :                                 cipher))
    4556           0 :                         return -1;
    4557             :         }
    4558             : 
    4559        2552 :         if (params->group_suite == WPA_CIPHER_GTK_NOT_USED &&
    4560           2 :             !(drv->capa.enc & WPA_DRIVER_CAPA_ENC_GTK_NOT_USED)) {
    4561             :                 /*
    4562             :                  * This is likely to work even though many drivers do not
    4563             :                  * advertise support for operations without GTK.
    4564             :                  */
    4565           2 :                 wpa_printf(MSG_DEBUG, "  * skip group cipher configuration for GTK_NOT_USED due to missing driver support advertisement");
    4566        2548 :         } else if (params->group_suite != WPA_CIPHER_NONE) {
    4567        1932 :                 u32 cipher = wpa_cipher_to_cipher_suite(params->group_suite);
    4568        1932 :                 wpa_printf(MSG_DEBUG, "  * group=0x%x", cipher);
    4569        1932 :                 if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher))
    4570           0 :                         return -1;
    4571             :         }
    4572             : 
    4573        4111 :         if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
    4574        2498 :             params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
    4575        1866 :             params->key_mgmt_suite == WPA_KEY_MGMT_FT_IEEE8021X ||
    4576        1627 :             params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
    4577        1396 :             params->key_mgmt_suite == WPA_KEY_MGMT_CCKM ||
    4578        1394 :             params->key_mgmt_suite == WPA_KEY_MGMT_OSEN ||
    4579        1388 :             params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
    4580        1364 :             params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
    4581        1342 :             params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
    4582         670 :             params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
    4583        1882 :                 int mgmt = WLAN_AKM_SUITE_PSK;
    4584             : 
    4585        1882 :                 switch (params->key_mgmt_suite) {
    4586             :                 case WPA_KEY_MGMT_CCKM:
    4587           0 :                         mgmt = WLAN_AKM_SUITE_CCKM;
    4588           0 :                         break;
    4589             :                 case WPA_KEY_MGMT_IEEE8021X:
    4590         989 :                         mgmt = WLAN_AKM_SUITE_8021X;
    4591         989 :                         break;
    4592             :                 case WPA_KEY_MGMT_FT_IEEE8021X:
    4593           8 :                         mgmt = WLAN_AKM_SUITE_FT_8021X;
    4594           8 :                         break;
    4595             :                 case WPA_KEY_MGMT_FT_PSK:
    4596         231 :                         mgmt = WLAN_AKM_SUITE_FT_PSK;
    4597         231 :                         break;
    4598             :                 case WPA_KEY_MGMT_IEEE8021X_SHA256:
    4599           4 :                         mgmt = WLAN_AKM_SUITE_8021X_SHA256;
    4600           4 :                         break;
    4601             :                 case WPA_KEY_MGMT_PSK_SHA256:
    4602          20 :                         mgmt = WLAN_AKM_SUITE_PSK_SHA256;
    4603          20 :                         break;
    4604             :                 case WPA_KEY_MGMT_OSEN:
    4605           2 :                         mgmt = WLAN_AKM_SUITE_OSEN;
    4606           2 :                         break;
    4607             :                 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
    4608           2 :                         mgmt = WLAN_AKM_SUITE_8021X_SUITE_B;
    4609           2 :                         break;
    4610             :                 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
    4611           2 :                         mgmt = WLAN_AKM_SUITE_8021X_SUITE_B_192;
    4612           2 :                         break;
    4613             :                 case WPA_KEY_MGMT_PSK:
    4614             :                 default:
    4615         624 :                         mgmt = WLAN_AKM_SUITE_PSK;
    4616         624 :                         break;
    4617             :                 }
    4618        1882 :                 wpa_printf(MSG_DEBUG, "  * akm=0x%x", mgmt);
    4619        1882 :                 if (nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, mgmt))
    4620           0 :                         return -1;
    4621             :         }
    4622             : 
    4623        2550 :         if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
    4624           0 :                 return -1;
    4625             : 
    4626        2597 :         if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED &&
    4627          47 :             nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED))
    4628           0 :                 return -1;
    4629             : 
    4630        2550 :         if (params->rrm_used) {
    4631           1 :                 u32 drv_rrm_flags = drv->capa.rrm_flags;
    4632           1 :                 if (!(drv_rrm_flags &
    4633           1 :                       WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) ||
    4634           2 :                     !(drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET) ||
    4635           1 :                     nla_put_flag(msg, NL80211_ATTR_USE_RRM))
    4636           0 :                         return -1;
    4637             :         }
    4638             : 
    4639        2550 :         if (nl80211_ht_vht_overrides(msg, params) < 0)
    4640           0 :                 return -1;
    4641             : 
    4642        2550 :         if (params->p2p)
    4643         366 :                 wpa_printf(MSG_DEBUG, "  * P2P group");
    4644             : 
    4645        2550 :         return 0;
    4646             : }
    4647             : 
    4648             : 
    4649          27 : static int wpa_driver_nl80211_try_connect(
    4650             :         struct wpa_driver_nl80211_data *drv,
    4651             :         struct wpa_driver_associate_params *params)
    4652             : {
    4653             :         struct nl_msg *msg;
    4654             :         enum nl80211_auth_type type;
    4655             :         int ret;
    4656             :         int algs;
    4657             : 
    4658          30 :         if (params->req_key_mgmt_offload && params->psk &&
    4659           3 :             (params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
    4660           0 :              params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
    4661           0 :              params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
    4662           3 :                 wpa_printf(MSG_DEBUG, "nl80211: Key management set PSK");
    4663           3 :                 ret = issue_key_mgmt_set_key(drv, params->psk, 32);
    4664           3 :                 if (ret)
    4665           0 :                         return ret;
    4666             :         }
    4667             : 
    4668          27 :         wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
    4669          27 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_CONNECT);
    4670          27 :         if (!msg)
    4671           0 :                 return -1;
    4672             : 
    4673          27 :         ret = nl80211_connect_common(drv, params, msg);
    4674          27 :         if (ret)
    4675           0 :                 goto fail;
    4676             : 
    4677          27 :         algs = 0;
    4678          27 :         if (params->auth_alg & WPA_AUTH_ALG_OPEN)
    4679          26 :                 algs++;
    4680          27 :         if (params->auth_alg & WPA_AUTH_ALG_SHARED)
    4681           2 :                 algs++;
    4682          27 :         if (params->auth_alg & WPA_AUTH_ALG_LEAP)
    4683           0 :                 algs++;
    4684          27 :         if (algs > 1) {
    4685           1 :                 wpa_printf(MSG_DEBUG, "  * Leave out Auth Type for automatic "
    4686             :                            "selection");
    4687           1 :                 goto skip_auth_type;
    4688             :         }
    4689             : 
    4690          26 :         if (params->auth_alg & WPA_AUTH_ALG_OPEN)
    4691          25 :                 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
    4692           1 :         else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
    4693           1 :                 type = NL80211_AUTHTYPE_SHARED_KEY;
    4694           0 :         else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
    4695           0 :                 type = NL80211_AUTHTYPE_NETWORK_EAP;
    4696           0 :         else if (params->auth_alg & WPA_AUTH_ALG_FT)
    4697           0 :                 type = NL80211_AUTHTYPE_FT;
    4698             :         else
    4699           0 :                 goto fail;
    4700             : 
    4701          26 :         wpa_printf(MSG_DEBUG, "  * Auth Type %d", type);
    4702          26 :         if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type))
    4703           0 :                 goto fail;
    4704             : 
    4705             : skip_auth_type:
    4706          27 :         ret = nl80211_set_conn_keys(params, msg);
    4707          27 :         if (ret)
    4708           0 :                 goto fail;
    4709             : 
    4710          27 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    4711          27 :         msg = NULL;
    4712          27 :         if (ret) {
    4713           2 :                 wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
    4714             :                            "(%s)", ret, strerror(-ret));
    4715             :         } else {
    4716          25 :                 wpa_printf(MSG_DEBUG,
    4717             :                            "nl80211: Connect request send successfully");
    4718             :         }
    4719             : 
    4720             : fail:
    4721          27 :         nlmsg_free(msg);
    4722          27 :         return ret;
    4723             : 
    4724             : }
    4725             : 
    4726             : 
    4727          25 : static int wpa_driver_nl80211_connect(
    4728             :         struct wpa_driver_nl80211_data *drv,
    4729             :         struct wpa_driver_associate_params *params)
    4730             : {
    4731             :         int ret;
    4732             : 
    4733             :         /* Store the connection attempted bssid for future use */
    4734          25 :         if (params->bssid)
    4735          18 :                 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
    4736             :         else
    4737           7 :                 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
    4738             : 
    4739          25 :         ret = wpa_driver_nl80211_try_connect(drv, params);
    4740          25 :         if (ret == -EALREADY) {
    4741             :                 /*
    4742             :                  * cfg80211 does not currently accept new connections if
    4743             :                  * we are already connected. As a workaround, force
    4744             :                  * disconnection and try again.
    4745             :                  */
    4746           2 :                 wpa_printf(MSG_DEBUG, "nl80211: Explicitly "
    4747             :                            "disconnecting before reassociation "
    4748             :                            "attempt");
    4749           2 :                 if (wpa_driver_nl80211_disconnect(
    4750             :                             drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
    4751           0 :                         return -1;
    4752           2 :                 ret = wpa_driver_nl80211_try_connect(drv, params);
    4753             :         }
    4754          25 :         return ret;
    4755             : }
    4756             : 
    4757             : 
    4758        2878 : static int wpa_driver_nl80211_associate(
    4759             :         void *priv, struct wpa_driver_associate_params *params)
    4760             : {
    4761        2878 :         struct i802_bss *bss = priv;
    4762        2878 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    4763        2878 :         int ret = -1;
    4764             :         struct nl_msg *msg;
    4765             : 
    4766        2878 :         nl80211_unmask_11b_rates(bss);
    4767             : 
    4768        2878 :         if (params->mode == IEEE80211_MODE_AP)
    4769         312 :                 return wpa_driver_nl80211_ap(drv, params);
    4770             : 
    4771        2566 :         if (params->mode == IEEE80211_MODE_IBSS)
    4772          18 :                 return wpa_driver_nl80211_ibss(drv, params);
    4773             : 
    4774        2548 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
    4775          25 :                 enum nl80211_iftype nlmode = params->p2p ?
    4776             :                         NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
    4777             : 
    4778          25 :                 if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
    4779           0 :                         return -1;
    4780          25 :                 return wpa_driver_nl80211_connect(drv, params);
    4781             :         }
    4782             : 
    4783        2523 :         nl80211_mark_disconnected(drv);
    4784             : 
    4785        2523 :         wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)",
    4786             :                    drv->ifindex);
    4787        2523 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_ASSOCIATE);
    4788        2523 :         if (!msg)
    4789           0 :                 return -1;
    4790             : 
    4791        2523 :         ret = nl80211_connect_common(drv, params, msg);
    4792        2523 :         if (ret)
    4793           0 :                 goto fail;
    4794             : 
    4795        2523 :         if (params->prev_bssid) {
    4796        1824 :                 wpa_printf(MSG_DEBUG, "  * prev_bssid=" MACSTR,
    4797        1824 :                            MAC2STR(params->prev_bssid));
    4798         304 :                 if (nla_put(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
    4799         304 :                             params->prev_bssid))
    4800           0 :                         goto fail;
    4801             :         }
    4802             : 
    4803        2523 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    4804        2523 :         msg = NULL;
    4805        2523 :         if (ret) {
    4806           0 :                 wpa_dbg(drv->ctx, MSG_DEBUG,
    4807             :                         "nl80211: MLME command failed (assoc): ret=%d (%s)",
    4808             :                         ret, strerror(-ret));
    4809           0 :                 nl80211_dump_scan(drv);
    4810             :         } else {
    4811        2523 :                 wpa_printf(MSG_DEBUG,
    4812             :                            "nl80211: Association request send successfully");
    4813             :         }
    4814             : 
    4815             : fail:
    4816        2523 :         nlmsg_free(msg);
    4817        2523 :         return ret;
    4818             : }
    4819             : 
    4820             : 
    4821        3341 : static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
    4822             :                             int ifindex, enum nl80211_iftype mode)
    4823             : {
    4824             :         struct nl_msg *msg;
    4825        3341 :         int ret = -ENOBUFS;
    4826             : 
    4827        3341 :         wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)",
    4828             :                    ifindex, mode, nl80211_iftype_str(mode));
    4829             : 
    4830        3341 :         msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_SET_INTERFACE);
    4831        3341 :         if (!msg || nla_put_u32(msg, NL80211_ATTR_IFTYPE, mode))
    4832             :                 goto fail;
    4833             : 
    4834        3341 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    4835        3341 :         msg = NULL;
    4836        3341 :         if (!ret)
    4837        3243 :                 return 0;
    4838             : fail:
    4839          98 :         nlmsg_free(msg);
    4840          98 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
    4841             :                    " %d (%s)", ifindex, mode, ret, strerror(-ret));
    4842          98 :         return ret;
    4843             : }
    4844             : 
    4845             : 
    4846        3277 : static int wpa_driver_nl80211_set_mode_impl(
    4847             :                 struct i802_bss *bss,
    4848             :                 enum nl80211_iftype nlmode,
    4849             :                 struct hostapd_freq_params *desired_freq_params)
    4850             : {
    4851        3277 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    4852        3277 :         int ret = -1;
    4853             :         int i;
    4854        3277 :         int was_ap = is_ap_interface(drv->nlmode);
    4855             :         int res;
    4856             :         int mode_switch_res;
    4857             : 
    4858        3277 :         mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
    4859        3277 :         if (mode_switch_res && nlmode == nl80211_get_ifmode(bss))
    4860           8 :                 mode_switch_res = 0;
    4861             : 
    4862        3277 :         if (mode_switch_res == 0) {
    4863        3187 :                 drv->nlmode = nlmode;
    4864        3187 :                 ret = 0;
    4865        3187 :                 goto done;
    4866             :         }
    4867             : 
    4868          90 :         if (mode_switch_res == -ENODEV)
    4869          26 :                 return -1;
    4870             : 
    4871          64 :         if (nlmode == drv->nlmode) {
    4872           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
    4873             :                            "requested mode - ignore error");
    4874           0 :                 ret = 0;
    4875           0 :                 goto done; /* Already in the requested mode */
    4876             :         }
    4877             : 
    4878             :         /* mac80211 doesn't allow mode changes while the device is up, so
    4879             :          * take the device down, try to set the mode again, and bring the
    4880             :          * device back up.
    4881             :          */
    4882          64 :         wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
    4883             :                    "interface down");
    4884          64 :         for (i = 0; i < 10; i++) {
    4885          64 :                 res = i802_set_iface_flags(bss, 0);
    4886          64 :                 if (res == -EACCES || res == -ENODEV)
    4887             :                         break;
    4888          64 :                 if (res != 0) {
    4889           0 :                         wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
    4890             :                                    "interface down");
    4891           0 :                         os_sleep(0, 100000);
    4892           0 :                         continue;
    4893             :                 }
    4894             : 
    4895             :                 /*
    4896             :                  * Setting the mode will fail for some drivers if the phy is
    4897             :                  * on a frequency that the mode is disallowed in.
    4898             :                  */
    4899          64 :                 if (desired_freq_params) {
    4900           0 :                         res = nl80211_set_channel(bss, desired_freq_params, 0);
    4901           0 :                         if (res) {
    4902           0 :                                 wpa_printf(MSG_DEBUG,
    4903             :                                            "nl80211: Failed to set frequency on interface");
    4904             :                         }
    4905             :                 }
    4906             : 
    4907             :                 /* Try to set the mode again while the interface is down */
    4908          64 :                 mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
    4909          64 :                 if (mode_switch_res == -EBUSY) {
    4910           0 :                         wpa_printf(MSG_DEBUG,
    4911             :                                    "nl80211: Delaying mode set while interface going down");
    4912           0 :                         os_sleep(0, 100000);
    4913           0 :                         continue;
    4914             :                 }
    4915          64 :                 ret = mode_switch_res;
    4916          64 :                 break;
    4917             :         }
    4918             : 
    4919          64 :         if (!ret) {
    4920          64 :                 wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
    4921             :                            "interface is down");
    4922          64 :                 drv->nlmode = nlmode;
    4923          64 :                 drv->ignore_if_down_event = 1;
    4924             :         }
    4925             : 
    4926             :         /* Bring the interface back up */
    4927          64 :         res = linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
    4928          64 :         if (res != 0) {
    4929           0 :                 wpa_printf(MSG_DEBUG,
    4930             :                            "nl80211: Failed to set interface up after switching mode");
    4931           0 :                 ret = -1;
    4932             :         }
    4933             : 
    4934             : done:
    4935        3251 :         if (ret) {
    4936           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
    4937           0 :                            "from %d failed", nlmode, drv->nlmode);
    4938           0 :                 return ret;
    4939             :         }
    4940             : 
    4941        3251 :         if (is_p2p_net_interface(nlmode)) {
    4942         600 :                 wpa_printf(MSG_DEBUG,
    4943             :                            "nl80211: Interface %s mode change to P2P - disable 11b rates",
    4944         600 :                            bss->ifname);
    4945         600 :                 nl80211_disable_11b_rates(drv, drv->ifindex, 1);
    4946        2651 :         } else if (drv->disabled_11b_rates) {
    4947         370 :                 wpa_printf(MSG_DEBUG,
    4948             :                            "nl80211: Interface %s mode changed to non-P2P - re-enable 11b rates",
    4949         370 :                            bss->ifname);
    4950         370 :                 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
    4951             :         }
    4952             : 
    4953        3251 :         if (is_ap_interface(nlmode)) {
    4954        1410 :                 nl80211_mgmt_unsubscribe(bss, "start AP");
    4955             :                 /* Setup additional AP mode functionality if needed */
    4956        1410 :                 if (nl80211_setup_ap(bss))
    4957           0 :                         return -1;
    4958        1841 :         } else if (was_ap) {
    4959             :                 /* Remove additional AP mode functionality */
    4960        1134 :                 nl80211_teardown_ap(bss);
    4961             :         } else {
    4962         707 :                 nl80211_mgmt_unsubscribe(bss, "mode change");
    4963             :         }
    4964             : 
    4965        3289 :         if (is_mesh_interface(nlmode) &&
    4966          38 :             nl80211_mgmt_subscribe_mesh(bss))
    4967           0 :                 return -1;
    4968             : 
    4969        4066 :         if (!bss->in_deinit && !is_ap_interface(nlmode) &&
    4970        1592 :             !is_mesh_interface(nlmode) &&
    4971         777 :             nl80211_mgmt_subscribe_non_ap(bss) < 0)
    4972           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
    4973             :                            "frame processing - ignore for now");
    4974             : 
    4975        3251 :         return 0;
    4976             : }
    4977             : 
    4978             : 
    4979        3259 : int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
    4980             :                                 enum nl80211_iftype nlmode)
    4981             : {
    4982        3259 :         return wpa_driver_nl80211_set_mode_impl(bss, nlmode, NULL);
    4983             : }
    4984             : 
    4985             : 
    4986          18 : static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
    4987             :                                             struct hostapd_freq_params *freq)
    4988             : {
    4989          18 :         return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC,
    4990             :                                                 freq);
    4991             : }
    4992             : 
    4993             : 
    4994        1746 : static int wpa_driver_nl80211_get_capa(void *priv,
    4995             :                                        struct wpa_driver_capa *capa)
    4996             : {
    4997        1746 :         struct i802_bss *bss = priv;
    4998        1746 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    4999             : 
    5000        1746 :         if (!drv->has_capability)
    5001           0 :                 return -1;
    5002        1746 :         os_memcpy(capa, &drv->capa, sizeof(*capa));
    5003        1746 :         if (drv->extended_capa && drv->extended_capa_mask) {
    5004        1746 :                 capa->extended_capa = drv->extended_capa;
    5005        1746 :                 capa->extended_capa_mask = drv->extended_capa_mask;
    5006        1746 :                 capa->extended_capa_len = drv->extended_capa_len;
    5007             :         }
    5008             : 
    5009        1746 :         return 0;
    5010             : }
    5011             : 
    5012             : 
    5013       14329 : static int wpa_driver_nl80211_set_operstate(void *priv, int state)
    5014             : {
    5015       14329 :         struct i802_bss *bss = priv;
    5016       14329 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5017             : 
    5018       28658 :         wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)",
    5019       14329 :                    bss->ifname, drv->operstate, state,
    5020             :                    state ? "UP" : "DORMANT");
    5021       14329 :         drv->operstate = state;
    5022       14329 :         return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
    5023             :                                       state ? IF_OPER_UP : IF_OPER_DORMANT);
    5024             : }
    5025             : 
    5026             : 
    5027        5185 : static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
    5028             : {
    5029        5185 :         struct i802_bss *bss = priv;
    5030        5185 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5031             :         struct nl_msg *msg;
    5032             :         struct nl80211_sta_flag_update upd;
    5033             :         int ret;
    5034             : 
    5035        5185 :         if (!drv->associated && is_zero_ether_addr(drv->bssid) && !authorized) {
    5036        2475 :                 wpa_printf(MSG_DEBUG, "nl80211: Skip set_supp_port(unauthorized) while not associated");
    5037        2475 :                 return 0;
    5038             :         }
    5039             : 
    5040       16260 :         wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
    5041       16260 :                    MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
    5042             : 
    5043        2710 :         os_memset(&upd, 0, sizeof(upd));
    5044        2710 :         upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);
    5045        2710 :         if (authorized)
    5046        1834 :                 upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);
    5047             : 
    5048        5420 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
    5049        5420 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid) ||
    5050        2710 :             nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) {
    5051           0 :                 nlmsg_free(msg);
    5052           0 :                 return -ENOBUFS;
    5053             :         }
    5054             : 
    5055        2710 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    5056        2710 :         if (!ret)
    5057        2683 :                 return 0;
    5058          27 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)",
    5059             :                    ret, strerror(-ret));
    5060          27 :         return ret;
    5061             : }
    5062             : 
    5063             : 
    5064             : /* Set kernel driver on given frequency (MHz) */
    5065        1302 : static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)
    5066             : {
    5067        1302 :         struct i802_bss *bss = priv;
    5068        1302 :         return nl80211_set_channel(bss, freq, 0);
    5069             : }
    5070             : 
    5071             : 
    5072        1637 : static inline int min_int(int a, int b)
    5073             : {
    5074        1637 :         if (a < b)
    5075           0 :                 return a;
    5076        1637 :         return b;
    5077             : }
    5078             : 
    5079             : 
    5080        1637 : static int get_key_handler(struct nl_msg *msg, void *arg)
    5081             : {
    5082             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    5083        1637 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    5084             : 
    5085        1637 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    5086             :                   genlmsg_attrlen(gnlh, 0), NULL);
    5087             : 
    5088             :         /*
    5089             :          * TODO: validate the key index and mac address!
    5090             :          * Otherwise, there's a race condition as soon as
    5091             :          * the kernel starts sending key notifications.
    5092             :          */
    5093             : 
    5094        1637 :         if (tb[NL80211_ATTR_KEY_SEQ])
    5095        1637 :                 memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
    5096        1637 :                        min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
    5097        1637 :         return NL_SKIP;
    5098             : }
    5099             : 
    5100             : 
    5101        1637 : static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
    5102             :                            int idx, u8 *seq)
    5103             : {
    5104        1637 :         struct i802_bss *bss = priv;
    5105        1637 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5106             :         struct nl_msg *msg;
    5107             : 
    5108        1637 :         msg = nl80211_ifindex_msg(drv, if_nametoindex(iface), 0,
    5109             :                                   NL80211_CMD_GET_KEY);
    5110        1637 :         if (!msg ||
    5111        1637 :             (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
    5112        1637 :             nla_put_u8(msg, NL80211_ATTR_KEY_IDX, idx)) {
    5113           0 :                 nlmsg_free(msg);
    5114           0 :                 return -ENOBUFS;
    5115             :         }
    5116             : 
    5117        1637 :         memset(seq, 0, 6);
    5118             : 
    5119        1637 :         return send_and_recv_msgs(drv, msg, get_key_handler, seq);
    5120             : }
    5121             : 
    5122             : 
    5123           1 : static int i802_set_rts(void *priv, int rts)
    5124             : {
    5125           1 :         struct i802_bss *bss = priv;
    5126           1 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5127             :         struct nl_msg *msg;
    5128             :         int ret;
    5129             :         u32 val;
    5130             : 
    5131           1 :         if (rts >= 2347)
    5132           0 :                 val = (u32) -1;
    5133             :         else
    5134           1 :                 val = rts;
    5135             : 
    5136           2 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) ||
    5137           1 :             nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val)) {
    5138           0 :                 nlmsg_free(msg);
    5139           0 :                 return -ENOBUFS;
    5140             :         }
    5141             : 
    5142           1 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    5143           1 :         if (!ret)
    5144           1 :                 return 0;
    5145           0 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
    5146             :                    "%d (%s)", rts, ret, strerror(-ret));
    5147           0 :         return ret;
    5148             : }
    5149             : 
    5150             : 
    5151           3 : static int i802_set_frag(void *priv, int frag)
    5152             : {
    5153           3 :         struct i802_bss *bss = priv;
    5154           3 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5155             :         struct nl_msg *msg;
    5156             :         int ret;
    5157             :         u32 val;
    5158             : 
    5159           3 :         if (frag >= 2346)
    5160           0 :                 val = (u32) -1;
    5161             :         else
    5162           3 :                 val = frag;
    5163             : 
    5164           6 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) ||
    5165           3 :             nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val)) {
    5166           0 :                 nlmsg_free(msg);
    5167           0 :                 return -ENOBUFS;
    5168             :         }
    5169             : 
    5170           3 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    5171           3 :         if (!ret)
    5172           3 :                 return 0;
    5173           0 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
    5174             :                    "%d: %d (%s)", frag, ret, strerror(-ret));
    5175           0 :         return ret;
    5176             : }
    5177             : 
    5178             : 
    5179        1165 : static int i802_flush(void *priv)
    5180             : {
    5181        1165 :         struct i802_bss *bss = priv;
    5182             :         struct nl_msg *msg;
    5183             :         int res;
    5184             : 
    5185        1165 :         wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
    5186        1165 :                    bss->ifname);
    5187             : 
    5188             :         /*
    5189             :          * XXX: FIX! this needs to flush all VLANs too
    5190             :          */
    5191        1165 :         msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION);
    5192        1165 :         res = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
    5193        1165 :         if (res) {
    5194          32 :                 wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
    5195             :                            "(%s)", res, strerror(-res));
    5196             :         }
    5197        1165 :         return res;
    5198             : }
    5199             : 
    5200             : 
    5201         303 : static int get_sta_handler(struct nl_msg *msg, void *arg)
    5202             : {
    5203             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    5204         303 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    5205         303 :         struct hostap_sta_driver_data *data = arg;
    5206             :         struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
    5207             :         static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
    5208             :                 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
    5209             :                 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
    5210             :                 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
    5211             :                 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
    5212             :                 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
    5213             :                 [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
    5214             :         };
    5215             : 
    5216         303 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    5217             :                   genlmsg_attrlen(gnlh, 0), NULL);
    5218             : 
    5219             :         /*
    5220             :          * TODO: validate the interface and mac address!
    5221             :          * Otherwise, there's a race condition as soon as
    5222             :          * the kernel starts sending station notifications.
    5223             :          */
    5224             : 
    5225         303 :         if (!tb[NL80211_ATTR_STA_INFO]) {
    5226           0 :                 wpa_printf(MSG_DEBUG, "sta stats missing!");
    5227           0 :                 return NL_SKIP;
    5228             :         }
    5229         303 :         if (nla_parse_nested(stats, NL80211_STA_INFO_MAX,
    5230             :                              tb[NL80211_ATTR_STA_INFO],
    5231             :                              stats_policy)) {
    5232           0 :                 wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
    5233           0 :                 return NL_SKIP;
    5234             :         }
    5235             : 
    5236         303 :         if (stats[NL80211_STA_INFO_INACTIVE_TIME])
    5237         303 :                 data->inactive_msec =
    5238         303 :                         nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);
    5239         303 :         if (stats[NL80211_STA_INFO_RX_BYTES])
    5240         303 :                 data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
    5241         303 :         if (stats[NL80211_STA_INFO_TX_BYTES])
    5242         303 :                 data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
    5243         303 :         if (stats[NL80211_STA_INFO_RX_PACKETS])
    5244         303 :                 data->rx_packets =
    5245         303 :                         nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
    5246         303 :         if (stats[NL80211_STA_INFO_TX_PACKETS])
    5247         303 :                 data->tx_packets =
    5248         303 :                         nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
    5249         303 :         if (stats[NL80211_STA_INFO_TX_FAILED])
    5250         303 :                 data->tx_retry_failed =
    5251         303 :                         nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
    5252             : 
    5253         303 :         return NL_SKIP;
    5254             : }
    5255             : 
    5256         304 : static int i802_read_sta_data(struct i802_bss *bss,
    5257             :                               struct hostap_sta_driver_data *data,
    5258             :                               const u8 *addr)
    5259             : {
    5260             :         struct nl_msg *msg;
    5261             : 
    5262         304 :         os_memset(data, 0, sizeof(*data));
    5263             : 
    5264         608 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_GET_STATION)) ||
    5265         304 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
    5266           0 :                 nlmsg_free(msg);
    5267           0 :                 return -ENOBUFS;
    5268             :         }
    5269             : 
    5270         304 :         return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data);
    5271             : }
    5272             : 
    5273             : 
    5274        4064 : static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
    5275             :                                     int cw_min, int cw_max, int burst_time)
    5276             : {
    5277        4064 :         struct i802_bss *bss = priv;
    5278        4064 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5279             :         struct nl_msg *msg;
    5280             :         struct nlattr *txq, *params;
    5281             : 
    5282        4064 :         msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_WIPHY);
    5283        4064 :         if (!msg)
    5284           0 :                 return -1;
    5285             : 
    5286        4064 :         txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);
    5287        4064 :         if (!txq)
    5288           0 :                 goto fail;
    5289             : 
    5290             :         /* We are only sending parameters for a single TXQ at a time */
    5291        4064 :         params = nla_nest_start(msg, 1);
    5292        4064 :         if (!params)
    5293           0 :                 goto fail;
    5294             : 
    5295        4064 :         switch (queue) {
    5296             :         case 0:
    5297        1016 :                 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO))
    5298           0 :                         goto fail;
    5299        1016 :                 break;
    5300             :         case 1:
    5301        1016 :                 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI))
    5302           0 :                         goto fail;
    5303        1016 :                 break;
    5304             :         case 2:
    5305        1016 :                 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE))
    5306           0 :                         goto fail;
    5307        1016 :                 break;
    5308             :         case 3:
    5309        1016 :                 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK))
    5310           0 :                         goto fail;
    5311        1016 :                 break;
    5312             :         }
    5313             :         /* Burst time is configured in units of 0.1 msec and TXOP parameter in
    5314             :          * 32 usec, so need to convert the value here. */
    5315        4064 :         if (nla_put_u16(msg, NL80211_TXQ_ATTR_TXOP,
    5316        8128 :                         (burst_time * 100 + 16) / 32) ||
    5317        8128 :             nla_put_u16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min) ||
    5318        8128 :             nla_put_u16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max) ||
    5319        4064 :             nla_put_u8(msg, NL80211_TXQ_ATTR_AIFS, aifs))
    5320             :                 goto fail;
    5321             : 
    5322        4064 :         nla_nest_end(msg, params);
    5323             : 
    5324        4064 :         nla_nest_end(msg, txq);
    5325             : 
    5326        4064 :         if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
    5327        3928 :                 return 0;
    5328         136 :         msg = NULL;
    5329             : fail:
    5330         136 :         nlmsg_free(msg);
    5331         136 :         return -1;
    5332             : }
    5333             : 
    5334             : 
    5335          16 : static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,
    5336             :                              const char *ifname, int vlan_id)
    5337             : {
    5338          16 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5339             :         struct nl_msg *msg;
    5340             :         int ret;
    5341             : 
    5342         144 :         wpa_printf(MSG_DEBUG, "nl80211: %s[%d]: set_sta_vlan(" MACSTR
    5343             :                    ", ifname=%s[%d], vlan_id=%d)",
    5344          32 :                    bss->ifname, if_nametoindex(bss->ifname),
    5345          96 :                    MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id);
    5346          32 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
    5347          32 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
    5348          16 :             nla_put_u32(msg, NL80211_ATTR_STA_VLAN, if_nametoindex(ifname))) {
    5349           0 :                 nlmsg_free(msg);
    5350           0 :                 return -ENOBUFS;
    5351             :         }
    5352             : 
    5353          16 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    5354          16 :         if (ret < 0) {
    5355           0 :                 wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
    5356             :                            MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
    5357           0 :                            MAC2STR(addr), ifname, vlan_id, ret,
    5358             :                            strerror(-ret));
    5359             :         }
    5360          16 :         return ret;
    5361             : }
    5362             : 
    5363             : 
    5364           7 : static int i802_get_inact_sec(void *priv, const u8 *addr)
    5365             : {
    5366             :         struct hostap_sta_driver_data data;
    5367             :         int ret;
    5368             : 
    5369           7 :         data.inactive_msec = (unsigned long) -1;
    5370           7 :         ret = i802_read_sta_data(priv, &data, addr);
    5371           7 :         if (ret == -ENOENT)
    5372           0 :                 return -ENOENT;
    5373           7 :         if (ret || data.inactive_msec == (unsigned long) -1)
    5374           0 :                 return -1;
    5375           7 :         return data.inactive_msec / 1000;
    5376             : }
    5377             : 
    5378             : 
    5379        1474 : static int i802_sta_clear_stats(void *priv, const u8 *addr)
    5380             : {
    5381             : #if 0
    5382             :         /* TODO */
    5383             : #endif
    5384        1474 :         return 0;
    5385             : }
    5386             : 
    5387             : 
    5388        2922 : static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
    5389             :                            int reason)
    5390             : {
    5391        2922 :         struct i802_bss *bss = priv;
    5392        2922 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5393             :         struct ieee80211_mgmt mgmt;
    5394             : 
    5395        2922 :         if (is_mesh_interface(drv->nlmode))
    5396          38 :                 return -1;
    5397             : 
    5398        2884 :         if (drv->device_ap_sme)
    5399           0 :                 return wpa_driver_nl80211_sta_remove(bss, addr, 1, reason);
    5400             : 
    5401        2884 :         memset(&mgmt, 0, sizeof(mgmt));
    5402        2884 :         mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    5403             :                                           WLAN_FC_STYPE_DEAUTH);
    5404        2884 :         memcpy(mgmt.da, addr, ETH_ALEN);
    5405        2884 :         memcpy(mgmt.sa, own_addr, ETH_ALEN);
    5406        2884 :         memcpy(mgmt.bssid, own_addr, ETH_ALEN);
    5407        2884 :         mgmt.u.deauth.reason_code = host_to_le16(reason);
    5408        2884 :         return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
    5409             :                                             IEEE80211_HDRLEN +
    5410             :                                             sizeof(mgmt.u.deauth), 0, 0, 0, 0,
    5411             :                                             0);
    5412             : }
    5413             : 
    5414             : 
    5415           5 : static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
    5416             :                              int reason)
    5417             : {
    5418           5 :         struct i802_bss *bss = priv;
    5419           5 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5420             :         struct ieee80211_mgmt mgmt;
    5421             : 
    5422           5 :         if (is_mesh_interface(drv->nlmode))
    5423           0 :                 return -1;
    5424             : 
    5425           5 :         if (drv->device_ap_sme)
    5426           0 :                 return wpa_driver_nl80211_sta_remove(bss, addr, 0, reason);
    5427             : 
    5428           5 :         memset(&mgmt, 0, sizeof(mgmt));
    5429           5 :         mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    5430             :                                           WLAN_FC_STYPE_DISASSOC);
    5431           5 :         memcpy(mgmt.da, addr, ETH_ALEN);
    5432           5 :         memcpy(mgmt.sa, own_addr, ETH_ALEN);
    5433           5 :         memcpy(mgmt.bssid, own_addr, ETH_ALEN);
    5434           5 :         mgmt.u.disassoc.reason_code = host_to_le16(reason);
    5435           5 :         return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
    5436             :                                             IEEE80211_HDRLEN +
    5437             :                                             sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
    5438             :                                             0);
    5439             : }
    5440             : 
    5441             : 
    5442        3350 : static void dump_ifidx(struct wpa_driver_nl80211_data *drv)
    5443             : {
    5444             :         char buf[200], *pos, *end;
    5445             :         int i, res;
    5446             : 
    5447        3350 :         pos = buf;
    5448        3350 :         end = pos + sizeof(buf);
    5449             : 
    5450       56967 :         for (i = 0; i < drv->num_if_indices; i++) {
    5451       53617 :                 if (!drv->if_indices[i])
    5452       52012 :                         continue;
    5453        1605 :                 res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]);
    5454        1605 :                 if (os_snprintf_error(end - pos, res))
    5455           0 :                         break;
    5456        1605 :                 pos += res;
    5457             :         }
    5458        3350 :         *pos = '\0';
    5459             : 
    5460        3350 :         wpa_printf(MSG_DEBUG, "nl80211: if_indices[%d]:%s",
    5461             :                    drv->num_if_indices, buf);
    5462        3350 : }
    5463             : 
    5464             : 
    5465        1326 : static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
    5466             : {
    5467             :         int i;
    5468             :         int *old;
    5469             : 
    5470        1326 :         wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
    5471             :                    ifidx);
    5472        1326 :         if (have_ifidx(drv, ifidx)) {
    5473         225 :                 wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
    5474             :                            ifidx);
    5475         225 :                 return;
    5476             :         }
    5477        1357 :         for (i = 0; i < drv->num_if_indices; i++) {
    5478        1356 :                 if (drv->if_indices[i] == 0) {
    5479        1100 :                         drv->if_indices[i] = ifidx;
    5480        1100 :                         dump_ifidx(drv);
    5481        1100 :                         return;
    5482             :                 }
    5483             :         }
    5484             : 
    5485           1 :         if (drv->if_indices != drv->default_if_indices)
    5486           0 :                 old = drv->if_indices;
    5487             :         else
    5488           1 :                 old = NULL;
    5489             : 
    5490           1 :         drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
    5491             :                                            sizeof(int));
    5492           1 :         if (!drv->if_indices) {
    5493           0 :                 if (!old)
    5494           0 :                         drv->if_indices = drv->default_if_indices;
    5495             :                 else
    5496           0 :                         drv->if_indices = old;
    5497           0 :                 wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
    5498             :                            "interfaces");
    5499           0 :                 wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
    5500           0 :                 return;
    5501           1 :         } else if (!old)
    5502           1 :                 os_memcpy(drv->if_indices, drv->default_if_indices,
    5503             :                           sizeof(drv->default_if_indices));
    5504           1 :         drv->if_indices[drv->num_if_indices] = ifidx;
    5505           1 :         drv->num_if_indices++;
    5506           1 :         dump_ifidx(drv);
    5507             : }
    5508             : 
    5509             : 
    5510        2249 : static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
    5511             : {
    5512             :         int i;
    5513             : 
    5514       37086 :         for (i = 0; i < drv->num_if_indices; i++) {
    5515       34922 :                 if (drv->if_indices[i] == ifidx) {
    5516          85 :                         drv->if_indices[i] = 0;
    5517          85 :                         break;
    5518             :                 }
    5519             :         }
    5520        2249 :         dump_ifidx(drv);
    5521        2249 : }
    5522             : 
    5523             : 
    5524       99726 : static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
    5525             : {
    5526             :         int i;
    5527             : 
    5528     1578484 :         for (i = 0; i < drv->num_if_indices; i++)
    5529     1486165 :                 if (drv->if_indices[i] == ifidx)
    5530        7407 :                         return 1;
    5531             : 
    5532       92319 :         return 0;
    5533             : }
    5534             : 
    5535             : 
    5536           2 : static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
    5537             :                             const char *bridge_ifname, char *ifname_wds)
    5538             : {
    5539           2 :         struct i802_bss *bss = priv;
    5540           2 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5541             :         char name[IFNAMSIZ + 1];
    5542             : 
    5543           2 :         os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
    5544           2 :         if (ifname_wds)
    5545           1 :                 os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
    5546             : 
    5547          12 :         wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
    5548          12 :                    " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
    5549           2 :         if (val) {
    5550           1 :                 if (!if_nametoindex(name)) {
    5551           1 :                         if (nl80211_create_iface(drv, name,
    5552             :                                                  NL80211_IFTYPE_AP_VLAN,
    5553           1 :                                                  bss->addr, 1, NULL, NULL, 0) <
    5554             :                             0)
    5555           0 :                                 return -1;
    5556           2 :                         if (bridge_ifname &&
    5557           1 :                             linux_br_add_if(drv->global->ioctl_sock,
    5558             :                                             bridge_ifname, name) < 0)
    5559           0 :                                 return -1;
    5560             :                 }
    5561           1 :                 if (linux_set_iface_flags(drv->global->ioctl_sock, name, 1)) {
    5562           0 :                         wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA "
    5563             :                                    "interface %s up", name);
    5564             :                 }
    5565           1 :                 return i802_set_sta_vlan(priv, addr, name, 0);
    5566             :         } else {
    5567           1 :                 if (bridge_ifname)
    5568           1 :                         linux_br_del_if(drv->global->ioctl_sock, bridge_ifname,
    5569             :                                         name);
    5570             : 
    5571           1 :                 i802_set_sta_vlan(priv, addr, bss->ifname, 0);
    5572           1 :                 nl80211_remove_iface(drv, if_nametoindex(name));
    5573           1 :                 return 0;
    5574             :         }
    5575             : }
    5576             : 
    5577             : 
    5578       16172 : static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
    5579             : {
    5580       16172 :         struct wpa_driver_nl80211_data *drv = eloop_ctx;
    5581             :         struct sockaddr_ll lladdr;
    5582             :         unsigned char buf[3000];
    5583             :         int len;
    5584       16172 :         socklen_t fromlen = sizeof(lladdr);
    5585             : 
    5586       16172 :         len = recvfrom(sock, buf, sizeof(buf), 0,
    5587             :                        (struct sockaddr *)&lladdr, &fromlen);
    5588       16172 :         if (len < 0) {
    5589           0 :                 wpa_printf(MSG_ERROR, "nl80211: EAPOL recv failed: %s",
    5590           0 :                            strerror(errno));
    5591       16172 :                 return;
    5592             :         }
    5593             : 
    5594       16172 :         if (have_ifidx(drv, lladdr.sll_ifindex))
    5595        6775 :                 drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
    5596             : }
    5597             : 
    5598             : 
    5599          15 : static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
    5600             :                              struct i802_bss *bss,
    5601             :                              const char *brname, const char *ifname)
    5602             : {
    5603             :         int br_ifindex;
    5604             :         char in_br[IFNAMSIZ];
    5605             : 
    5606          15 :         os_strlcpy(bss->brname, brname, IFNAMSIZ);
    5607          15 :         br_ifindex = if_nametoindex(brname);
    5608          15 :         if (br_ifindex == 0) {
    5609             :                 /*
    5610             :                  * Bridge was configured, but the bridge device does
    5611             :                  * not exist. Try to add it now.
    5612             :                  */
    5613          10 :                 if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
    5614           0 :                         wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
    5615             :                                    "bridge interface %s: %s",
    5616           0 :                                    brname, strerror(errno));
    5617           0 :                         return -1;
    5618             :                 }
    5619          10 :                 bss->added_bridge = 1;
    5620          10 :                 br_ifindex = if_nametoindex(brname);
    5621          10 :                 add_ifidx(drv, br_ifindex);
    5622             :         }
    5623          15 :         bss->br_ifindex = br_ifindex;
    5624             : 
    5625          15 :         if (linux_br_get(in_br, ifname) == 0) {
    5626           1 :                 if (os_strcmp(in_br, brname) == 0)
    5627           0 :                         return 0; /* already in the bridge */
    5628             : 
    5629           1 :                 wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
    5630             :                            "bridge %s", ifname, in_br);
    5631           1 :                 if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
    5632             :                     0) {
    5633           0 :                         wpa_printf(MSG_ERROR, "nl80211: Failed to "
    5634             :                                    "remove interface %s from bridge "
    5635             :                                    "%s: %s",
    5636           0 :                                    ifname, brname, strerror(errno));
    5637           0 :                         return -1;
    5638             :                 }
    5639             :         }
    5640             : 
    5641          15 :         wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
    5642             :                    ifname, brname);
    5643          15 :         if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
    5644           0 :                 wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
    5645             :                            "into bridge %s: %s",
    5646           0 :                            ifname, brname, strerror(errno));
    5647           0 :                 return -1;
    5648             :         }
    5649          15 :         bss->added_if_into_bridge = 1;
    5650             : 
    5651          15 :         return 0;
    5652             : }
    5653             : 
    5654             : 
    5655        1014 : static void *i802_init(struct hostapd_data *hapd,
    5656             :                        struct wpa_init_params *params)
    5657             : {
    5658             :         struct wpa_driver_nl80211_data *drv;
    5659             :         struct i802_bss *bss;
    5660             :         size_t i;
    5661             :         char brname[IFNAMSIZ];
    5662             :         int ifindex, br_ifindex;
    5663        1014 :         int br_added = 0;
    5664             : 
    5665        1014 :         bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
    5666             :                                           params->global_priv, 1,
    5667             :                                           params->bssid, params->driver_params);
    5668        1014 :         if (bss == NULL)
    5669          12 :                 return NULL;
    5670             : 
    5671        1002 :         drv = bss->drv;
    5672             : 
    5673        1002 :         if (linux_br_get(brname, params->ifname) == 0) {
    5674           2 :                 wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
    5675             :                            params->ifname, brname);
    5676           2 :                 br_ifindex = if_nametoindex(brname);
    5677           2 :                 os_strlcpy(bss->brname, brname, IFNAMSIZ);
    5678             :         } else {
    5679        1000 :                 brname[0] = '\0';
    5680        1000 :                 br_ifindex = 0;
    5681             :         }
    5682        1002 :         bss->br_ifindex = br_ifindex;
    5683             : 
    5684        2011 :         for (i = 0; i < params->num_bridge; i++) {
    5685        1009 :                 if (params->bridge[i]) {
    5686          15 :                         ifindex = if_nametoindex(params->bridge[i]);
    5687          15 :                         if (ifindex)
    5688           5 :                                 add_ifidx(drv, ifindex);
    5689          15 :                         if (ifindex == br_ifindex)
    5690           9 :                                 br_added = 1;
    5691             :                 }
    5692             :         }
    5693             : 
    5694             :         /* start listening for EAPOL on the default AP interface */
    5695        1002 :         add_ifidx(drv, drv->ifindex);
    5696             : 
    5697        1002 :         if (params->num_bridge && params->bridge[0]) {
    5698          15 :                 if (i802_check_bridge(drv, bss, params->bridge[0],
    5699             :                                       params->ifname) < 0)
    5700           0 :                         goto failed;
    5701          15 :                 if (os_strcmp(params->bridge[0], brname) != 0)
    5702          15 :                         br_added = 1;
    5703             :         }
    5704             : 
    5705        1003 :         if (!br_added && br_ifindex &&
    5706           2 :             (params->num_bridge == 0 || !params->bridge[0]))
    5707           1 :                 add_ifidx(drv, br_ifindex);
    5708             : 
    5709             : #ifdef CONFIG_LIBNL3_ROUTE
    5710        1002 :         if (bss->added_if_into_bridge) {
    5711          15 :                 drv->rtnl_sk = nl_socket_alloc();
    5712          15 :                 if (drv->rtnl_sk == NULL) {
    5713           0 :                         wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
    5714           0 :                         goto failed;
    5715             :                 }
    5716             : 
    5717          15 :                 if (nl_connect(drv->rtnl_sk, NETLINK_ROUTE)) {
    5718           0 :                         wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
    5719           0 :                                    strerror(errno));
    5720           0 :                         goto failed;
    5721             :                 }
    5722             :         }
    5723             : #endif /* CONFIG_LIBNL3_ROUTE */
    5724             : 
    5725        1002 :         drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
    5726        1002 :         if (drv->eapol_sock < 0) {
    5727           0 :                 wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s",
    5728           0 :                            strerror(errno));
    5729           0 :                 goto failed;
    5730             :         }
    5731             : 
    5732        1002 :         if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
    5733             :         {
    5734           1 :                 wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol");
    5735           1 :                 goto failed;
    5736             :         }
    5737             : 
    5738        1001 :         if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
    5739             :                                params->own_addr))
    5740           0 :                 goto failed;
    5741        1001 :         os_memcpy(drv->perm_addr, params->own_addr, ETH_ALEN);
    5742             : 
    5743        1001 :         memcpy(bss->addr, params->own_addr, ETH_ALEN);
    5744             : 
    5745        1001 :         return bss;
    5746             : 
    5747             : failed:
    5748           1 :         wpa_driver_nl80211_deinit(bss);
    5749           1 :         return NULL;
    5750             : }
    5751             : 
    5752             : 
    5753        1001 : static void i802_deinit(void *priv)
    5754             : {
    5755        1001 :         struct i802_bss *bss = priv;
    5756        1001 :         wpa_driver_nl80211_deinit(bss);
    5757        1001 : }
    5758             : 
    5759             : 
    5760         205 : static enum nl80211_iftype wpa_driver_nl80211_if_type(
    5761             :         enum wpa_driver_if_type type)
    5762             : {
    5763         205 :         switch (type) {
    5764             :         case WPA_IF_STATION:
    5765           0 :                 return NL80211_IFTYPE_STATION;
    5766             :         case WPA_IF_P2P_CLIENT:
    5767             :         case WPA_IF_P2P_GROUP:
    5768          40 :                 return NL80211_IFTYPE_P2P_CLIENT;
    5769             :         case WPA_IF_AP_VLAN:
    5770          13 :                 return NL80211_IFTYPE_AP_VLAN;
    5771             :         case WPA_IF_AP_BSS:
    5772          42 :                 return NL80211_IFTYPE_AP;
    5773             :         case WPA_IF_P2P_GO:
    5774          98 :                 return NL80211_IFTYPE_P2P_GO;
    5775             :         case WPA_IF_P2P_DEVICE:
    5776           8 :                 return NL80211_IFTYPE_P2P_DEVICE;
    5777             :         case WPA_IF_MESH:
    5778           4 :                 return NL80211_IFTYPE_MESH_POINT;
    5779             :         }
    5780           0 :         return -1;
    5781             : }
    5782             : 
    5783             : 
    5784             : #if defined(CONFIG_P2P) || defined(CONFIG_MESH)
    5785             : 
    5786        2286 : static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr)
    5787             : {
    5788             :         struct wpa_driver_nl80211_data *drv;
    5789       49991 :         dl_list_for_each(drv, &global->interfaces,
    5790             :                          struct wpa_driver_nl80211_data, list) {
    5791       49850 :                 if (os_memcmp(addr, drv->first_bss->addr, ETH_ALEN) == 0)
    5792        2145 :                         return 1;
    5793             :         }
    5794         141 :         return 0;
    5795             : }
    5796             : 
    5797             : 
    5798          72 : static int nl80211_vif_addr(struct wpa_driver_nl80211_data *drv, u8 *new_addr)
    5799             : {
    5800             :         unsigned int idx;
    5801             : 
    5802          72 :         if (!drv->global)
    5803           0 :                 return -1;
    5804             : 
    5805          72 :         os_memcpy(new_addr, drv->first_bss->addr, ETH_ALEN);
    5806        2145 :         for (idx = 0; idx < 64; idx++) {
    5807        2144 :                 new_addr[0] = drv->first_bss->addr[0] | 0x02;
    5808        2144 :                 new_addr[0] ^= idx << 2;
    5809        2144 :                 if (!nl80211_addr_in_use(drv->global, new_addr))
    5810          71 :                         break;
    5811             :         }
    5812          72 :         if (idx == 64)
    5813           1 :                 return -1;
    5814             : 
    5815         426 :         wpa_printf(MSG_DEBUG, "nl80211: Assigned new virtual interface address "
    5816         426 :                    MACSTR, MAC2STR(new_addr));
    5817             : 
    5818          71 :         return 0;
    5819             : }
    5820             : 
    5821             : #endif /* CONFIG_P2P || CONFIG_MESH */
    5822             : 
    5823             : 
    5824             : struct wdev_info {
    5825             :         u64 wdev_id;
    5826             :         int wdev_id_set;
    5827             :         u8 macaddr[ETH_ALEN];
    5828             : };
    5829             : 
    5830           8 : static int nl80211_wdev_handler(struct nl_msg *msg, void *arg)
    5831             : {
    5832           8 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    5833             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    5834           8 :         struct wdev_info *wi = arg;
    5835             : 
    5836           8 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    5837             :                   genlmsg_attrlen(gnlh, 0), NULL);
    5838           8 :         if (tb[NL80211_ATTR_WDEV]) {
    5839           8 :                 wi->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
    5840           8 :                 wi->wdev_id_set = 1;
    5841             :         }
    5842             : 
    5843           8 :         if (tb[NL80211_ATTR_MAC])
    5844           8 :                 os_memcpy(wi->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
    5845             :                           ETH_ALEN);
    5846             : 
    5847           8 :         return NL_SKIP;
    5848             : }
    5849             : 
    5850             : 
    5851         205 : static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
    5852             :                                      const char *ifname, const u8 *addr,
    5853             :                                      void *bss_ctx, void **drv_priv,
    5854             :                                      char *force_ifname, u8 *if_addr,
    5855             :                                      const char *bridge, int use_existing)
    5856             : {
    5857             :         enum nl80211_iftype nlmode;
    5858         205 :         struct i802_bss *bss = priv;
    5859         205 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    5860             :         int ifidx;
    5861         205 :         int added = 1;
    5862             : 
    5863         205 :         if (addr)
    5864          55 :                 os_memcpy(if_addr, addr, ETH_ALEN);
    5865         205 :         nlmode = wpa_driver_nl80211_if_type(type);
    5866         205 :         if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
    5867             :                 struct wdev_info p2pdev_info;
    5868             : 
    5869           8 :                 os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
    5870           8 :                 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
    5871             :                                              0, nl80211_wdev_handler,
    5872             :                                              &p2pdev_info, use_existing);
    5873           8 :                 if (!p2pdev_info.wdev_id_set || ifidx != 0) {
    5874           0 :                         wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s",
    5875             :                                    ifname);
    5876           0 :                         return -1;
    5877             :                 }
    5878             : 
    5879           8 :                 drv->global->if_add_wdevid = p2pdev_info.wdev_id;
    5880           8 :                 drv->global->if_add_wdevid_set = p2pdev_info.wdev_id_set;
    5881           8 :                 if (!is_zero_ether_addr(p2pdev_info.macaddr))
    5882           8 :                         os_memcpy(if_addr, p2pdev_info.macaddr, ETH_ALEN);
    5883           8 :                 wpa_printf(MSG_DEBUG, "nl80211: New P2P Device interface %s (0x%llx) created",
    5884             :                            ifname,
    5885           8 :                            (long long unsigned int) p2pdev_info.wdev_id);
    5886             :         } else {
    5887         197 :                 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
    5888             :                                              0, NULL, NULL, use_existing);
    5889         197 :                 if (use_existing && ifidx == -ENFILE) {
    5890           1 :                         added = 0;
    5891           1 :                         ifidx = if_nametoindex(ifname);
    5892         196 :                 } else if (ifidx < 0) {
    5893           0 :                         return -1;
    5894             :                 }
    5895             :         }
    5896             : 
    5897         205 :         if (!addr) {
    5898         150 :                 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
    5899           7 :                         os_memcpy(if_addr, bss->addr, ETH_ALEN);
    5900         143 :                 else if (linux_get_ifhwaddr(drv->global->ioctl_sock,
    5901         143 :                                             bss->ifname, if_addr) < 0) {
    5902           0 :                         if (added)
    5903           0 :                                 nl80211_remove_iface(drv, ifidx);
    5904           0 :                         return -1;
    5905             :                 }
    5906             :         }
    5907             : 
    5908             : #if defined(CONFIG_P2P) || defined(CONFIG_MESH)
    5909         150 :         if (!addr &&
    5910         136 :             (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||
    5911          12 :              type == WPA_IF_P2P_GO || type == WPA_IF_MESH)) {
    5912             :                 /* Enforce unique P2P Interface Address */
    5913             :                 u8 new_addr[ETH_ALEN];
    5914             : 
    5915         142 :                 if (linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
    5916             :                                        new_addr) < 0) {
    5917           0 :                         if (added)
    5918           0 :                                 nl80211_remove_iface(drv, ifidx);
    5919           1 :                         return -1;
    5920             :                 }
    5921         142 :                 if (nl80211_addr_in_use(drv->global, new_addr)) {
    5922          72 :                         wpa_printf(MSG_DEBUG, "nl80211: Allocate new address "
    5923             :                                    "for %s interface", type == WPA_IF_MESH ?
    5924             :                                    "mesh" : "P2P group");
    5925          72 :                         if (nl80211_vif_addr(drv, new_addr) < 0) {
    5926           1 :                                 if (added)
    5927           1 :                                         nl80211_remove_iface(drv, ifidx);
    5928           1 :                                 return -1;
    5929             :                         }
    5930          71 :                         if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
    5931             :                                                new_addr) < 0) {
    5932           0 :                                 if (added)
    5933           0 :                                         nl80211_remove_iface(drv, ifidx);
    5934           0 :                                 return -1;
    5935             :                         }
    5936             :                 }
    5937         141 :                 os_memcpy(if_addr, new_addr, ETH_ALEN);
    5938             :         }
    5939             : #endif /* CONFIG_P2P || CONFIG_MESH */
    5940             : 
    5941         204 :         if (type == WPA_IF_AP_BSS) {
    5942          42 :                 struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
    5943          42 :                 if (new_bss == NULL) {
    5944           0 :                         if (added)
    5945           0 :                                 nl80211_remove_iface(drv, ifidx);
    5946           0 :                         return -1;
    5947             :                 }
    5948             : 
    5949          42 :                 if (bridge &&
    5950           0 :                     i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
    5951           0 :                         wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
    5952             :                                    "interface %s to a bridge %s",
    5953             :                                    ifname, bridge);
    5954           0 :                         if (added)
    5955           0 :                                 nl80211_remove_iface(drv, ifidx);
    5956           0 :                         os_free(new_bss);
    5957           0 :                         return -1;
    5958             :                 }
    5959             : 
    5960          42 :                 if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
    5961             :                 {
    5962           0 :                         if (added)
    5963           0 :                                 nl80211_remove_iface(drv, ifidx);
    5964           0 :                         os_free(new_bss);
    5965           0 :                         return -1;
    5966             :                 }
    5967          42 :                 os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
    5968          42 :                 os_memcpy(new_bss->addr, if_addr, ETH_ALEN);
    5969          42 :                 new_bss->ifindex = ifidx;
    5970          42 :                 new_bss->drv = drv;
    5971          42 :                 new_bss->next = drv->first_bss->next;
    5972          42 :                 new_bss->freq = drv->first_bss->freq;
    5973          42 :                 new_bss->ctx = bss_ctx;
    5974          42 :                 new_bss->added_if = added;
    5975          42 :                 drv->first_bss->next = new_bss;
    5976          42 :                 if (drv_priv)
    5977          42 :                         *drv_priv = new_bss;
    5978          42 :                 nl80211_init_bss(new_bss);
    5979             : 
    5980             :                 /* Subscribe management frames for this WPA_IF_AP_BSS */
    5981          42 :                 if (nl80211_setup_ap(new_bss))
    5982           0 :                         return -1;
    5983             :         }
    5984             : 
    5985         204 :         if (drv->global)
    5986         204 :                 drv->global->if_add_ifindex = ifidx;
    5987             : 
    5988             :         /*
    5989             :          * Some virtual interfaces need to process EAPOL packets and events on
    5990             :          * the parent interface. This is used mainly with hostapd.
    5991             :          */
    5992         400 :         if (ifidx > 0 &&
    5993         337 :             (drv->hostapd ||
    5994         141 :              nlmode == NL80211_IFTYPE_AP_VLAN ||
    5995         141 :              nlmode == NL80211_IFTYPE_WDS ||
    5996             :              nlmode == NL80211_IFTYPE_MONITOR))
    5997          55 :                 add_ifidx(drv, ifidx);
    5998             : 
    5999         204 :         return 0;
    6000             : }
    6001             : 
    6002             : 
    6003         194 : static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
    6004             :                                         enum wpa_driver_if_type type,
    6005             :                                         const char *ifname)
    6006             : {
    6007         194 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6008         194 :         int ifindex = if_nametoindex(ifname);
    6009             : 
    6010         194 :         wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d",
    6011         194 :                    __func__, type, ifname, ifindex, bss->added_if);
    6012         194 :         if (ifindex > 0 && (bss->added_if || bss->ifindex != ifindex))
    6013         188 :                 nl80211_remove_iface(drv, ifindex);
    6014           6 :         else if (ifindex > 0 && !bss->added_if) {
    6015             :                 struct wpa_driver_nl80211_data *drv2;
    6016           2 :                 dl_list_for_each(drv2, &drv->global->interfaces,
    6017             :                                  struct wpa_driver_nl80211_data, list)
    6018           1 :                         del_ifidx(drv2, ifindex);
    6019             :         }
    6020             : 
    6021         194 :         if (type != WPA_IF_AP_BSS)
    6022         152 :                 return 0;
    6023             : 
    6024          42 :         if (bss->added_if_into_bridge) {
    6025           0 :                 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
    6026           0 :                                     bss->ifname) < 0)
    6027           0 :                         wpa_printf(MSG_INFO, "nl80211: Failed to remove "
    6028             :                                    "interface %s from bridge %s: %s",
    6029           0 :                                    bss->ifname, bss->brname, strerror(errno));
    6030             :         }
    6031          42 :         if (bss->added_bridge) {
    6032           0 :                 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
    6033           0 :                         wpa_printf(MSG_INFO, "nl80211: Failed to remove "
    6034             :                                    "bridge %s: %s",
    6035           0 :                                    bss->brname, strerror(errno));
    6036             :         }
    6037             : 
    6038          42 :         if (bss != drv->first_bss) {
    6039             :                 struct i802_bss *tbss;
    6040             : 
    6041          42 :                 wpa_printf(MSG_DEBUG, "nl80211: Not the first BSS - remove it");
    6042         165 :                 for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
    6043         165 :                         if (tbss->next == bss) {
    6044          42 :                                 tbss->next = bss->next;
    6045             :                                 /* Unsubscribe management frames */
    6046          42 :                                 nl80211_teardown_ap(bss);
    6047          42 :                                 nl80211_destroy_bss(bss);
    6048          42 :                                 if (!bss->added_if)
    6049           1 :                                         i802_set_iface_flags(bss, 0);
    6050          42 :                                 os_free(bss);
    6051          42 :                                 bss = NULL;
    6052          42 :                                 break;
    6053             :                         }
    6054             :                 }
    6055          42 :                 if (bss)
    6056           0 :                         wpa_printf(MSG_INFO, "nl80211: %s - could not find "
    6057             :                                    "BSS %p in the list", __func__, bss);
    6058             :         } else {
    6059           0 :                 wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
    6060           0 :                 nl80211_teardown_ap(bss);
    6061           0 :                 if (!bss->added_if && !drv->first_bss->next)
    6062           0 :                         wpa_driver_nl80211_del_beacon(drv);
    6063           0 :                 nl80211_destroy_bss(bss);
    6064           0 :                 if (!bss->added_if)
    6065           0 :                         i802_set_iface_flags(bss, 0);
    6066           0 :                 if (drv->first_bss->next) {
    6067           0 :                         drv->first_bss = drv->first_bss->next;
    6068           0 :                         drv->ctx = drv->first_bss->ctx;
    6069           0 :                         os_free(bss);
    6070             :                 } else {
    6071           0 :                         wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
    6072             :                 }
    6073             :         }
    6074             : 
    6075          42 :         return 0;
    6076             : }
    6077             : 
    6078             : 
    6079       12016 : static int cookie_handler(struct nl_msg *msg, void *arg)
    6080             : {
    6081             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    6082       12016 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    6083       12016 :         u64 *cookie = arg;
    6084       12016 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    6085             :                   genlmsg_attrlen(gnlh, 0), NULL);
    6086       12016 :         if (tb[NL80211_ATTR_COOKIE])
    6087       12016 :                 *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
    6088       12016 :         return NL_SKIP;
    6089             : }
    6090             : 
    6091             : 
    6092       14136 : static int nl80211_send_frame_cmd(struct i802_bss *bss,
    6093             :                                   unsigned int freq, unsigned int wait,
    6094             :                                   const u8 *buf, size_t buf_len,
    6095             :                                   u64 *cookie_out, int no_cck, int no_ack,
    6096             :                                   int offchanok)
    6097             : {
    6098       14136 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6099             :         struct nl_msg *msg;
    6100             :         u64 cookie;
    6101       14136 :         int ret = -1;
    6102             : 
    6103       14136 :         wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
    6104             :                    "no_ack=%d offchanok=%d",
    6105             :                    freq, wait, no_cck, no_ack, offchanok);
    6106       14136 :         wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
    6107             : 
    6108       14136 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) ||
    6109       14120 :             (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
    6110        1658 :             (wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) ||
    6111        2920 :             (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
    6112        2920 :                            drv->test_use_roc_tx) &&
    6113       17056 :              nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) ||
    6114        1936 :             (no_cck && nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE)) ||
    6115       16768 :             (no_ack && nla_put_flag(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK)) ||
    6116       14136 :             nla_put(msg, NL80211_ATTR_FRAME, buf_len, buf))
    6117             :                 goto fail;
    6118             : 
    6119       14136 :         cookie = 0;
    6120       14136 :         ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
    6121       14136 :         msg = NULL;
    6122       14136 :         if (ret) {
    6123        1091 :                 wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
    6124             :                            "(%s) (freq=%u wait=%u)", ret, strerror(-ret),
    6125             :                            freq, wait);
    6126             :         } else {
    6127       13045 :                 wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; "
    6128             :                            "cookie 0x%llx", no_ack ? " (no ACK)" : "",
    6129             :                            (long long unsigned int) cookie);
    6130             : 
    6131       13045 :                 if (cookie_out)
    6132       12373 :                         *cookie_out = no_ack ? (u64) -1 : cookie;
    6133             :         }
    6134             : 
    6135             : fail:
    6136       14136 :         nlmsg_free(msg);
    6137       14136 :         return ret;
    6138             : }
    6139             : 
    6140             : 
    6141        2248 : static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
    6142             :                                           unsigned int freq,
    6143             :                                           unsigned int wait_time,
    6144             :                                           const u8 *dst, const u8 *src,
    6145             :                                           const u8 *bssid,
    6146             :                                           const u8 *data, size_t data_len,
    6147             :                                           int no_cck)
    6148             : {
    6149        2248 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6150        2248 :         int ret = -1;
    6151             :         u8 *buf;
    6152             :         struct ieee80211_hdr *hdr;
    6153             : 
    6154        2248 :         wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
    6155             :                    "freq=%u MHz wait=%d ms no_cck=%d)",
    6156             :                    drv->ifindex, freq, wait_time, no_cck);
    6157             : 
    6158        2248 :         buf = os_zalloc(24 + data_len);
    6159        2248 :         if (buf == NULL)
    6160           0 :                 return ret;
    6161        2248 :         os_memcpy(buf + 24, data, data_len);
    6162        2248 :         hdr = (struct ieee80211_hdr *) buf;
    6163        2248 :         hdr->frame_control =
    6164             :                 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);
    6165        2248 :         os_memcpy(hdr->addr1, dst, ETH_ALEN);
    6166        2248 :         os_memcpy(hdr->addr2, src, ETH_ALEN);
    6167        2248 :         os_memcpy(hdr->addr3, bssid, ETH_ALEN);
    6168             : 
    6169        2587 :         if (is_ap_interface(drv->nlmode) &&
    6170         678 :             (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
    6171         347 :              (int) freq == bss->freq || drv->device_ap_sme ||
    6172           4 :              !drv->use_monitor))
    6173         339 :                 ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
    6174             :                                                    0, freq, no_cck, 1,
    6175             :                                                    wait_time);
    6176             :         else
    6177        1909 :                 ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
    6178             :                                              24 + data_len,
    6179             :                                              &drv->send_action_cookie,
    6180             :                                              no_cck, 0, 1);
    6181             : 
    6182        2248 :         os_free(buf);
    6183        2248 :         return ret;
    6184             : }
    6185             : 
    6186             : 
    6187        1061 : static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
    6188             : {
    6189        1061 :         struct i802_bss *bss = priv;
    6190        1061 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6191             :         struct nl_msg *msg;
    6192             :         int ret;
    6193             : 
    6194        1061 :         wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx",
    6195        1061 :                    (long long unsigned int) drv->send_action_cookie);
    6196        2122 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME_WAIT_CANCEL)) ||
    6197        1061 :             nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie)) {
    6198           0 :                 nlmsg_free(msg);
    6199        1061 :                 return;
    6200             :         }
    6201             : 
    6202        1061 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    6203        1061 :         if (ret)
    6204         120 :                 wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
    6205             :                            "(%s)", ret, strerror(-ret));
    6206             : }
    6207             : 
    6208             : 
    6209        1599 : static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
    6210             :                                                 unsigned int duration)
    6211             : {
    6212        1599 :         struct i802_bss *bss = priv;
    6213        1599 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6214             :         struct nl_msg *msg;
    6215             :         int ret;
    6216             :         u64 cookie;
    6217             : 
    6218        3198 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REMAIN_ON_CHANNEL)) ||
    6219        3198 :             nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
    6220        1599 :             nla_put_u32(msg, NL80211_ATTR_DURATION, duration)) {
    6221           0 :                 nlmsg_free(msg);
    6222           0 :                 return -1;
    6223             :         }
    6224             : 
    6225        1599 :         cookie = 0;
    6226        1599 :         ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
    6227        1599 :         if (ret == 0) {
    6228        1599 :                 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
    6229             :                            "0x%llx for freq=%u MHz duration=%u",
    6230             :                            (long long unsigned int) cookie, freq, duration);
    6231        1599 :                 drv->remain_on_chan_cookie = cookie;
    6232        1599 :                 drv->pending_remain_on_chan = 1;
    6233        1599 :                 return 0;
    6234             :         }
    6235           0 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel "
    6236             :                    "(freq=%d duration=%u): %d (%s)",
    6237             :                    freq, duration, ret, strerror(-ret));
    6238           0 :         return -1;
    6239             : }
    6240             : 
    6241             : 
    6242         750 : static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
    6243             : {
    6244         750 :         struct i802_bss *bss = priv;
    6245         750 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6246             :         struct nl_msg *msg;
    6247             :         int ret;
    6248             : 
    6249         750 :         if (!drv->pending_remain_on_chan) {
    6250           0 :                 wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel "
    6251             :                            "to cancel");
    6252           0 :                 return -1;
    6253             :         }
    6254             : 
    6255         750 :         wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie "
    6256             :                    "0x%llx",
    6257         750 :                    (long long unsigned int) drv->remain_on_chan_cookie);
    6258             : 
    6259         750 :         msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
    6260        1500 :         if (!msg ||
    6261         750 :             nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie)) {
    6262           0 :                 nlmsg_free(msg);
    6263           0 :                 return -1;
    6264             :         }
    6265             : 
    6266         750 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    6267         750 :         if (ret == 0)
    6268         748 :                 return 0;
    6269           2 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
    6270             :                    "%d (%s)", ret, strerror(-ret));
    6271           2 :         return -1;
    6272             : }
    6273             : 
    6274             : 
    6275       15326 : static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report)
    6276             : {
    6277       15326 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6278             : 
    6279       15326 :         if (!report) {
    6280       13726 :                 if (bss->nl_preq && drv->device_ap_sme &&
    6281           0 :                     is_ap_interface(drv->nlmode) && !bss->in_deinit &&
    6282           0 :                     !bss->static_ap) {
    6283             :                         /*
    6284             :                          * Do not disable Probe Request reporting that was
    6285             :                          * enabled in nl80211_setup_ap().
    6286             :                          */
    6287           0 :                         wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of "
    6288             :                                    "Probe Request reporting nl_preq=%p while "
    6289             :                                    "in AP mode", bss->nl_preq);
    6290       13726 :                 } else if (bss->nl_preq) {
    6291        1186 :                         wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
    6292             :                                    "reporting nl_preq=%p", bss->nl_preq);
    6293        1186 :                         nl80211_destroy_eloop_handle(&bss->nl_preq);
    6294             :                 }
    6295       13726 :                 return 0;
    6296             :         }
    6297             : 
    6298        1600 :         if (bss->nl_preq) {
    6299         411 :                 wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
    6300             :                            "already on! nl_preq=%p", bss->nl_preq);
    6301         411 :                 return 0;
    6302             :         }
    6303             : 
    6304        1189 :         bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq");
    6305        1189 :         if (bss->nl_preq == NULL)
    6306           0 :                 return -1;
    6307        1189 :         wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request "
    6308             :                    "reporting nl_preq=%p", bss->nl_preq);
    6309             : 
    6310        1189 :         if (nl80211_register_frame(bss, bss->nl_preq,
    6311             :                                    (WLAN_FC_TYPE_MGMT << 2) |
    6312             :                                    (WLAN_FC_STYPE_PROBE_REQ << 4),
    6313             :                                    NULL, 0) < 0)
    6314           3 :                 goto out_err;
    6315             : 
    6316        1186 :         nl80211_register_eloop_read(&bss->nl_preq,
    6317             :                                     wpa_driver_nl80211_event_receive,
    6318        1186 :                                     bss->nl_cb);
    6319             : 
    6320        1186 :         return 0;
    6321             : 
    6322             :  out_err:
    6323           3 :         nl_destroy_handles(&bss->nl_preq);
    6324           3 :         return -1;
    6325             : }
    6326             : 
    6327             : 
    6328        1210 : static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
    6329             :                                      int ifindex, int disabled)
    6330             : {
    6331             :         struct nl_msg *msg;
    6332             :         struct nlattr *bands, *band;
    6333             :         int ret;
    6334             : 
    6335        1210 :         wpa_printf(MSG_DEBUG,
    6336             :                    "nl80211: NL80211_CMD_SET_TX_BITRATE_MASK (ifindex=%d %s)",
    6337             :                    ifindex, disabled ? "NL80211_TXRATE_LEGACY=OFDM-only" :
    6338             :                    "no NL80211_TXRATE_LEGACY constraint");
    6339             : 
    6340        1210 :         msg = nl80211_ifindex_msg(drv, ifindex, 0,
    6341             :                                   NL80211_CMD_SET_TX_BITRATE_MASK);
    6342        1210 :         if (!msg)
    6343           0 :                 return -1;
    6344             : 
    6345        1210 :         bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
    6346        1210 :         if (!bands)
    6347           0 :                 goto fail;
    6348             : 
    6349             :         /*
    6350             :          * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything
    6351             :          * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS
    6352             :          * rates. All 5 GHz rates are left enabled.
    6353             :          */
    6354        1210 :         band = nla_nest_start(msg, NL80211_BAND_2GHZ);
    6355        1210 :         if (!band ||
    6356         738 :             (disabled && nla_put(msg, NL80211_TXRATE_LEGACY, 8,
    6357             :                                  "\x0c\x12\x18\x24\x30\x48\x60\x6c")))
    6358             :                 goto fail;
    6359        1210 :         nla_nest_end(msg, band);
    6360             : 
    6361        1210 :         nla_nest_end(msg, bands);
    6362             : 
    6363        1210 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    6364        1210 :         if (ret) {
    6365         276 :                 wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
    6366             :                            "(%s)", ret, strerror(-ret));
    6367             :         } else
    6368         934 :                 drv->disabled_11b_rates = disabled;
    6369             : 
    6370        1210 :         return ret;
    6371             : 
    6372             : fail:
    6373           0 :         nlmsg_free(msg);
    6374           0 :         return -1;
    6375             : }
    6376             : 
    6377             : 
    6378         311 : static int wpa_driver_nl80211_deinit_ap(void *priv)
    6379             : {
    6380         311 :         struct i802_bss *bss = priv;
    6381         311 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6382         311 :         if (!is_ap_interface(drv->nlmode))
    6383           0 :                 return -1;
    6384         311 :         wpa_driver_nl80211_del_beacon(drv);
    6385         311 :         bss->beacon_set = 0;
    6386             : 
    6387             :         /*
    6388             :          * If the P2P GO interface was dynamically added, then it is
    6389             :          * possible that the interface change to station is not possible.
    6390             :          */
    6391         311 :         if (drv->nlmode == NL80211_IFTYPE_P2P_GO && bss->if_dynamic)
    6392         101 :                 return 0;
    6393             : 
    6394         210 :         return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
    6395             : }
    6396             : 
    6397             : 
    6398           1 : static int wpa_driver_nl80211_stop_ap(void *priv)
    6399             : {
    6400           1 :         struct i802_bss *bss = priv;
    6401           1 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6402           1 :         if (!is_ap_interface(drv->nlmode))
    6403           0 :                 return -1;
    6404           1 :         wpa_driver_nl80211_del_beacon(drv);
    6405           1 :         bss->beacon_set = 0;
    6406           1 :         return 0;
    6407             : }
    6408             : 
    6409             : 
    6410         172 : static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
    6411             : {
    6412         172 :         struct i802_bss *bss = priv;
    6413         172 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6414         172 :         if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)
    6415           1 :                 return -1;
    6416             : 
    6417             :         /*
    6418             :          * If the P2P Client interface was dynamically added, then it is
    6419             :          * possible that the interface change to station is not possible.
    6420             :          */
    6421         171 :         if (bss->if_dynamic)
    6422           0 :                 return 0;
    6423             : 
    6424         171 :         return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
    6425             : }
    6426             : 
    6427             : 
    6428           2 : static void wpa_driver_nl80211_resume(void *priv)
    6429             : {
    6430           2 :         struct i802_bss *bss = priv;
    6431             : 
    6432           2 :         if (i802_set_iface_flags(bss, 1))
    6433           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event");
    6434           2 : }
    6435             : 
    6436             : 
    6437          10 : static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
    6438             : {
    6439          10 :         struct i802_bss *bss = priv;
    6440          10 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6441             :         struct nl_msg *msg;
    6442             :         struct nlattr *cqm;
    6443             : 
    6444          10 :         wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
    6445             :                    "hysteresis=%d", threshold, hysteresis);
    6446             : 
    6447          10 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_CQM)) ||
    6448          10 :             !(cqm = nla_nest_start(msg, NL80211_ATTR_CQM)) ||
    6449          20 :             nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold) ||
    6450          10 :             nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis)) {
    6451           0 :                 nlmsg_free(msg);
    6452           0 :                 return -1;
    6453             :         }
    6454          10 :         nla_nest_end(msg, cqm);
    6455             : 
    6456          10 :         return send_and_recv_msgs(drv, msg, NULL, NULL);
    6457             : }
    6458             : 
    6459             : 
    6460          45 : static int get_channel_width(struct nl_msg *msg, void *arg)
    6461             : {
    6462             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    6463          45 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    6464          45 :         struct wpa_signal_info *sig_change = arg;
    6465             : 
    6466          45 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    6467             :                   genlmsg_attrlen(gnlh, 0), NULL);
    6468             : 
    6469          45 :         sig_change->center_frq1 = -1;
    6470          45 :         sig_change->center_frq2 = -1;
    6471          45 :         sig_change->chanwidth = CHAN_WIDTH_UNKNOWN;
    6472             : 
    6473          45 :         if (tb[NL80211_ATTR_CHANNEL_WIDTH]) {
    6474          45 :                 sig_change->chanwidth = convert2width(
    6475          45 :                         nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
    6476          45 :                 if (tb[NL80211_ATTR_CENTER_FREQ1])
    6477          45 :                         sig_change->center_frq1 =
    6478          45 :                                 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
    6479          45 :                 if (tb[NL80211_ATTR_CENTER_FREQ2])
    6480           1 :                         sig_change->center_frq2 =
    6481           1 :                                 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
    6482             :         }
    6483             : 
    6484          45 :         return NL_SKIP;
    6485             : }
    6486             : 
    6487             : 
    6488          45 : static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
    6489             :                                      struct wpa_signal_info *sig)
    6490             : {
    6491             :         struct nl_msg *msg;
    6492             : 
    6493          45 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
    6494          45 :         return send_and_recv_msgs(drv, msg, get_channel_width, sig);
    6495             : }
    6496             : 
    6497             : 
    6498          45 : static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
    6499             : {
    6500          45 :         struct i802_bss *bss = priv;
    6501          45 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6502             :         int res;
    6503             : 
    6504          45 :         os_memset(si, 0, sizeof(*si));
    6505          45 :         res = nl80211_get_link_signal(drv, si);
    6506          45 :         if (res != 0)
    6507           0 :                 return res;
    6508             : 
    6509          45 :         res = nl80211_get_channel_width(drv, si);
    6510          45 :         if (res != 0)
    6511           0 :                 return res;
    6512             : 
    6513          45 :         return nl80211_get_link_noise(drv, si);
    6514             : }
    6515             : 
    6516             : 
    6517           0 : static int wpa_driver_nl80211_shared_freq(void *priv)
    6518             : {
    6519           0 :         struct i802_bss *bss = priv;
    6520           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6521             :         struct wpa_driver_nl80211_data *driver;
    6522           0 :         int freq = 0;
    6523             : 
    6524             :         /*
    6525             :          * If the same PHY is in connected state with some other interface,
    6526             :          * then retrieve the assoc freq.
    6527             :          */
    6528           0 :         wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s",
    6529           0 :                    drv->phyname);
    6530             : 
    6531           0 :         dl_list_for_each(driver, &drv->global->interfaces,
    6532             :                          struct wpa_driver_nl80211_data, list) {
    6533           0 :                 if (drv == driver ||
    6534           0 :                     os_strcmp(drv->phyname, driver->phyname) != 0 ||
    6535           0 :                     !driver->associated)
    6536           0 :                         continue;
    6537             : 
    6538           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
    6539             :                            MACSTR,
    6540           0 :                            driver->phyname, driver->first_bss->ifname,
    6541           0 :                            MAC2STR(driver->first_bss->addr));
    6542           0 :                 if (is_ap_interface(driver->nlmode))
    6543           0 :                         freq = driver->first_bss->freq;
    6544             :                 else
    6545           0 :                         freq = nl80211_get_assoc_freq(driver);
    6546           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
    6547           0 :                            drv->phyname, freq);
    6548             :         }
    6549             : 
    6550           0 :         if (!freq)
    6551           0 :                 wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
    6552           0 :                            "PHY (%s) in associated state", drv->phyname);
    6553             : 
    6554           0 :         return freq;
    6555             : }
    6556             : 
    6557             : 
    6558          60 : static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
    6559             :                               int encrypt)
    6560             : {
    6561          60 :         struct i802_bss *bss = priv;
    6562          60 :         return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
    6563             :                                              0, 0, 0, 0);
    6564             : }
    6565             : 
    6566             : 
    6567         231 : static int nl80211_set_param(void *priv, const char *param)
    6568             : {
    6569         231 :         wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
    6570         231 :         if (param == NULL)
    6571         204 :                 return 0;
    6572             : 
    6573             : #ifdef CONFIG_P2P
    6574          25 :         if (os_strstr(param, "use_p2p_group_interface=1")) {
    6575           0 :                 struct i802_bss *bss = priv;
    6576           0 :                 struct wpa_driver_nl80211_data *drv = bss->drv;
    6577             : 
    6578           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
    6579             :                            "interface");
    6580           0 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
    6581           0 :                 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
    6582             :         }
    6583             : #endif /* CONFIG_P2P */
    6584             : 
    6585          27 :         if (os_strstr(param, "use_monitor=1")) {
    6586           7 :                 struct i802_bss *bss = priv;
    6587           7 :                 struct wpa_driver_nl80211_data *drv = bss->drv;
    6588           7 :                 drv->use_monitor = 1;
    6589             :         }
    6590             : 
    6591          27 :         if (os_strstr(param, "force_connect_cmd=1")) {
    6592          15 :                 struct i802_bss *bss = priv;
    6593          15 :                 struct wpa_driver_nl80211_data *drv = bss->drv;
    6594          15 :                 drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
    6595          15 :                 drv->force_connect_cmd = 1;
    6596             :         }
    6597             : 
    6598          27 :         if (os_strstr(param, "no_offchannel_tx=1")) {
    6599           5 :                 struct i802_bss *bss = priv;
    6600           5 :                 struct wpa_driver_nl80211_data *drv = bss->drv;
    6601           5 :                 drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
    6602           5 :                 drv->test_use_roc_tx = 1;
    6603             :         }
    6604             : 
    6605          27 :         return 0;
    6606             : }
    6607             : 
    6608             : 
    6609          25 : static void * nl80211_global_init(void)
    6610             : {
    6611             :         struct nl80211_global *global;
    6612             :         struct netlink_config *cfg;
    6613             : 
    6614          25 :         global = os_zalloc(sizeof(*global));
    6615          25 :         if (global == NULL)
    6616           0 :                 return NULL;
    6617          25 :         global->ioctl_sock = -1;
    6618          25 :         dl_list_init(&global->interfaces);
    6619          25 :         global->if_add_ifindex = -1;
    6620             : 
    6621          25 :         cfg = os_zalloc(sizeof(*cfg));
    6622          25 :         if (cfg == NULL)
    6623           0 :                 goto err;
    6624             : 
    6625          25 :         cfg->ctx = global;
    6626          25 :         cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
    6627          25 :         cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
    6628          25 :         global->netlink = netlink_init(cfg);
    6629          25 :         if (global->netlink == NULL) {
    6630           0 :                 os_free(cfg);
    6631           0 :                 goto err;
    6632             :         }
    6633             : 
    6634          25 :         if (wpa_driver_nl80211_init_nl_global(global) < 0)
    6635           0 :                 goto err;
    6636             : 
    6637          25 :         global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
    6638          25 :         if (global->ioctl_sock < 0) {
    6639           0 :                 wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",
    6640           0 :                            strerror(errno));
    6641           0 :                 goto err;
    6642             :         }
    6643             : 
    6644          25 :         return global;
    6645             : 
    6646             : err:
    6647           0 :         nl80211_global_deinit(global);
    6648           0 :         return NULL;
    6649             : }
    6650             : 
    6651             : 
    6652          25 : static void nl80211_global_deinit(void *priv)
    6653             : {
    6654          25 :         struct nl80211_global *global = priv;
    6655          25 :         if (global == NULL)
    6656          25 :                 return;
    6657          25 :         if (!dl_list_empty(&global->interfaces)) {
    6658           0 :                 wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at "
    6659             :                            "nl80211_global_deinit",
    6660             :                            dl_list_len(&global->interfaces));
    6661             :         }
    6662             : 
    6663          25 :         if (global->netlink)
    6664          25 :                 netlink_deinit(global->netlink);
    6665             : 
    6666          25 :         nl_destroy_handles(&global->nl);
    6667             : 
    6668          25 :         if (global->nl_event)
    6669          25 :                 nl80211_destroy_eloop_handle(&global->nl_event);
    6670             : 
    6671          25 :         nl_cb_put(global->nl_cb);
    6672             : 
    6673          25 :         if (global->ioctl_sock >= 0)
    6674          25 :                 close(global->ioctl_sock);
    6675             : 
    6676          25 :         os_free(global);
    6677             : }
    6678             : 
    6679             : 
    6680        1549 : static const char * nl80211_get_radio_name(void *priv)
    6681             : {
    6682        1549 :         struct i802_bss *bss = priv;
    6683        1549 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6684        1549 :         return drv->phyname;
    6685             : }
    6686             : 
    6687             : 
    6688        1534 : static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,
    6689             :                          const u8 *pmkid)
    6690             : {
    6691             :         struct nl_msg *msg;
    6692             : 
    6693        1534 :         if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
    6694        1306 :             (pmkid && nla_put(msg, NL80211_ATTR_PMKID, 16, pmkid)) ||
    6695        1306 :             (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))) {
    6696           0 :                 nlmsg_free(msg);
    6697           0 :                 return -ENOBUFS;
    6698             :         }
    6699             : 
    6700        1534 :         return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
    6701             : }
    6702             : 
    6703             : 
    6704         653 : static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
    6705             : {
    6706         653 :         struct i802_bss *bss = priv;
    6707         653 :         wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR, MAC2STR(bssid));
    6708         653 :         return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);
    6709             : }
    6710             : 
    6711             : 
    6712         653 : static int nl80211_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
    6713             : {
    6714         653 :         struct i802_bss *bss = priv;
    6715        3918 :         wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR,
    6716        3918 :                    MAC2STR(bssid));
    6717         653 :         return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);
    6718             : }
    6719             : 
    6720             : 
    6721         228 : static int nl80211_flush_pmkid(void *priv)
    6722             : {
    6723         228 :         struct i802_bss *bss = priv;
    6724         228 :         wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs");
    6725         228 :         return nl80211_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);
    6726             : }
    6727             : 
    6728             : 
    6729          45 : static void clean_survey_results(struct survey_results *survey_results)
    6730             : {
    6731             :         struct freq_survey *survey, *tmp;
    6732             : 
    6733          45 :         if (dl_list_empty(&survey_results->survey_list))
    6734          85 :                 return;
    6735             : 
    6736          10 :         dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
    6737             :                               struct freq_survey, list) {
    6738           5 :                 dl_list_del(&survey->list);
    6739           5 :                 os_free(survey);
    6740             :         }
    6741             : }
    6742             : 
    6743             : 
    6744          45 : static void add_survey(struct nlattr **sinfo, u32 ifidx,
    6745             :                        struct dl_list *survey_list)
    6746             : {
    6747             :         struct freq_survey *survey;
    6748             : 
    6749          45 :         survey = os_zalloc(sizeof(struct freq_survey));
    6750          45 :         if  (!survey)
    6751          45 :                 return;
    6752             : 
    6753          45 :         survey->ifidx = ifidx;
    6754          45 :         survey->freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
    6755          45 :         survey->filled = 0;
    6756             : 
    6757          45 :         if (sinfo[NL80211_SURVEY_INFO_NOISE]) {
    6758          45 :                 survey->nf = (int8_t)
    6759          45 :                         nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
    6760          45 :                 survey->filled |= SURVEY_HAS_NF;
    6761             :         }
    6762             : 
    6763          45 :         if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]) {
    6764           0 :                 survey->channel_time =
    6765           0 :                         nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]);
    6766           0 :                 survey->filled |= SURVEY_HAS_CHAN_TIME;
    6767             :         }
    6768             : 
    6769          45 :         if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]) {
    6770           0 :                 survey->channel_time_busy =
    6771           0 :                         nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]);
    6772           0 :                 survey->filled |= SURVEY_HAS_CHAN_TIME_BUSY;
    6773             :         }
    6774             : 
    6775          45 :         if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]) {
    6776           0 :                 survey->channel_time_rx =
    6777           0 :                         nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]);
    6778           0 :                 survey->filled |= SURVEY_HAS_CHAN_TIME_RX;
    6779             :         }
    6780             : 
    6781          45 :         if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]) {
    6782           0 :                 survey->channel_time_tx =
    6783           0 :                         nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]);
    6784           0 :                 survey->filled |= SURVEY_HAS_CHAN_TIME_TX;
    6785             :         }
    6786             : 
    6787          90 :         wpa_printf(MSG_DEBUG, "nl80211: Freq survey dump event (freq=%d MHz noise=%d channel_time=%ld busy_time=%ld tx_time=%ld rx_time=%ld filled=%04x)",
    6788             :                    survey->freq,
    6789          45 :                    survey->nf,
    6790             :                    (unsigned long int) survey->channel_time,
    6791             :                    (unsigned long int) survey->channel_time_busy,
    6792             :                    (unsigned long int) survey->channel_time_tx,
    6793             :                    (unsigned long int) survey->channel_time_rx,
    6794             :                    survey->filled);
    6795             : 
    6796          45 :         dl_list_add_tail(survey_list, &survey->list);
    6797             : }
    6798             : 
    6799             : 
    6800          45 : static int check_survey_ok(struct nlattr **sinfo, u32 surveyed_freq,
    6801             :                            unsigned int freq_filter)
    6802             : {
    6803          45 :         if (!freq_filter)
    6804          40 :                 return 1;
    6805             : 
    6806           5 :         return freq_filter == surveyed_freq;
    6807             : }
    6808             : 
    6809             : 
    6810          45 : static int survey_handler(struct nl_msg *msg, void *arg)
    6811             : {
    6812             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    6813          45 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    6814             :         struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
    6815             :         struct survey_results *survey_results;
    6816          45 :         u32 surveyed_freq = 0;
    6817             :         u32 ifidx;
    6818             : 
    6819             :         static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
    6820             :                 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
    6821             :                 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
    6822             :         };
    6823             : 
    6824          45 :         survey_results = (struct survey_results *) arg;
    6825             : 
    6826          45 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    6827             :                   genlmsg_attrlen(gnlh, 0), NULL);
    6828             : 
    6829          45 :         if (!tb[NL80211_ATTR_IFINDEX])
    6830           0 :                 return NL_SKIP;
    6831             : 
    6832          45 :         ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
    6833             : 
    6834          45 :         if (!tb[NL80211_ATTR_SURVEY_INFO])
    6835           0 :                 return NL_SKIP;
    6836             : 
    6837          45 :         if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
    6838             :                              tb[NL80211_ATTR_SURVEY_INFO],
    6839             :                              survey_policy))
    6840           0 :                 return NL_SKIP;
    6841             : 
    6842          45 :         if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) {
    6843           0 :                 wpa_printf(MSG_ERROR, "nl80211: Invalid survey data");
    6844           0 :                 return NL_SKIP;
    6845             :         }
    6846             : 
    6847          45 :         surveyed_freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
    6848             : 
    6849          45 :         if (!check_survey_ok(sinfo, surveyed_freq,
    6850             :                              survey_results->freq_filter))
    6851           0 :                 return NL_SKIP;
    6852             : 
    6853          50 :         if (survey_results->freq_filter &&
    6854           5 :             survey_results->freq_filter != surveyed_freq) {
    6855           0 :                 wpa_printf(MSG_EXCESSIVE, "nl80211: Ignoring survey data for freq %d MHz",
    6856             :                            surveyed_freq);
    6857           0 :                 return NL_SKIP;
    6858             :         }
    6859             : 
    6860          45 :         add_survey(sinfo, ifidx, &survey_results->survey_list);
    6861             : 
    6862          45 :         return NL_SKIP;
    6863             : }
    6864             : 
    6865             : 
    6866          45 : static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
    6867             : {
    6868          45 :         struct i802_bss *bss = priv;
    6869          45 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6870             :         struct nl_msg *msg;
    6871             :         int err;
    6872             :         union wpa_event_data data;
    6873             :         struct survey_results *survey_results;
    6874             : 
    6875          45 :         os_memset(&data, 0, sizeof(data));
    6876          45 :         survey_results = &data.survey_results;
    6877             : 
    6878          45 :         dl_list_init(&survey_results->survey_list);
    6879             : 
    6880          45 :         msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
    6881          45 :         if (!msg)
    6882           0 :                 return -ENOBUFS;
    6883             : 
    6884          45 :         if (freq)
    6885           5 :                 data.survey_results.freq_filter = freq;
    6886             : 
    6887             :         do {
    6888          45 :                 wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data");
    6889          45 :                 err = send_and_recv_msgs(drv, msg, survey_handler,
    6890             :                                          survey_results);
    6891          45 :         } while (err > 0);
    6892             : 
    6893          45 :         if (err)
    6894           0 :                 wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
    6895             :         else
    6896          45 :                 wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data);
    6897             : 
    6898          45 :         clean_survey_results(survey_results);
    6899          45 :         return err;
    6900             : }
    6901             : 
    6902             : 
    6903        1336 : static void nl80211_set_rekey_info(void *priv, const u8 *kek, size_t kek_len,
    6904             :                                    const u8 *kck, size_t kck_len,
    6905             :                                    const u8 *replay_ctr)
    6906             : {
    6907        1336 :         struct i802_bss *bss = priv;
    6908        1336 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6909             :         struct nlattr *replay_nested;
    6910             :         struct nl_msg *msg;
    6911             :         int ret;
    6912             : 
    6913        1336 :         if (!drv->set_rekey_offload)
    6914        1278 :                 return;
    6915             : 
    6916          58 :         wpa_printf(MSG_DEBUG, "nl80211: Set rekey offload");
    6917          58 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_REKEY_OFFLOAD)) ||
    6918          58 :             !(replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA)) ||
    6919         116 :             nla_put(msg, NL80211_REKEY_DATA_KEK, kek_len, kek) ||
    6920         116 :             nla_put(msg, NL80211_REKEY_DATA_KCK, kck_len, kck) ||
    6921          58 :             nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
    6922             :                     replay_ctr)) {
    6923           0 :                 nl80211_nlmsg_clear(msg);
    6924           0 :                 nlmsg_free(msg);
    6925           0 :                 return;
    6926             :         }
    6927             : 
    6928          58 :         nla_nest_end(msg, replay_nested);
    6929             : 
    6930          58 :         ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
    6931          58 :         if (ret == -EOPNOTSUPP) {
    6932          58 :                 wpa_printf(MSG_DEBUG,
    6933             :                            "nl80211: Driver does not support rekey offload");
    6934          58 :                 drv->set_rekey_offload = 0;
    6935             :         }
    6936             : }
    6937             : 
    6938             : 
    6939           0 : static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
    6940             :                                     const u8 *addr, int qos)
    6941             : {
    6942             :         /* send data frame to poll STA and check whether
    6943             :          * this frame is ACKed */
    6944             :         struct {
    6945             :                 struct ieee80211_hdr hdr;
    6946             :                 u16 qos_ctl;
    6947             :         } STRUCT_PACKED nulldata;
    6948             :         size_t size;
    6949             : 
    6950             :         /* Send data frame to poll STA and check whether this frame is ACKed */
    6951             : 
    6952           0 :         os_memset(&nulldata, 0, sizeof(nulldata));
    6953             : 
    6954           0 :         if (qos) {
    6955           0 :                 nulldata.hdr.frame_control =
    6956             :                         IEEE80211_FC(WLAN_FC_TYPE_DATA,
    6957             :                                      WLAN_FC_STYPE_QOS_NULL);
    6958           0 :                 size = sizeof(nulldata);
    6959             :         } else {
    6960           0 :                 nulldata.hdr.frame_control =
    6961             :                         IEEE80211_FC(WLAN_FC_TYPE_DATA,
    6962             :                                      WLAN_FC_STYPE_NULLFUNC);
    6963           0 :                 size = sizeof(struct ieee80211_hdr);
    6964             :         }
    6965             : 
    6966           0 :         nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
    6967           0 :         os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
    6968           0 :         os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
    6969           0 :         os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
    6970             : 
    6971           0 :         if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
    6972             :                                          0, 0) < 0)
    6973           0 :                 wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
    6974             :                            "send poll frame");
    6975           0 : }
    6976             : 
    6977           2 : static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
    6978             :                                 int qos)
    6979             : {
    6980           2 :         struct i802_bss *bss = priv;
    6981           2 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    6982             :         struct nl_msg *msg;
    6983             :         int ret;
    6984             : 
    6985           2 :         if (!drv->poll_command_supported) {
    6986           0 :                 nl80211_send_null_frame(bss, own_addr, addr, qos);
    6987           0 :                 return;
    6988             :         }
    6989             : 
    6990           4 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_PROBE_CLIENT)) ||
    6991           2 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
    6992           0 :                 nlmsg_free(msg);
    6993           0 :                 return;
    6994             :         }
    6995             : 
    6996           2 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    6997           2 :         if (ret < 0) {
    6998           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Client probe request for "
    6999             :                            MACSTR " failed: ret=%d (%s)",
    7000           0 :                            MAC2STR(addr), ret, strerror(-ret));
    7001             :         }
    7002             : }
    7003             : 
    7004             : 
    7005           3 : static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
    7006             : {
    7007             :         struct nl_msg *msg;
    7008             : 
    7009           6 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_POWER_SAVE)) ||
    7010           3 :             nla_put_u32(msg, NL80211_ATTR_PS_STATE,
    7011             :                         enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED)) {
    7012           0 :                 nlmsg_free(msg);
    7013           0 :                 return -ENOBUFS;
    7014             :         }
    7015           3 :         return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
    7016             : }
    7017             : 
    7018             : 
    7019           8 : static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,
    7020             :                                      int ctwindow)
    7021             : {
    7022           8 :         struct i802_bss *bss = priv;
    7023             : 
    7024           8 :         wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d "
    7025             :                    "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow);
    7026             : 
    7027           8 :         if (opp_ps != -1 || ctwindow != -1) {
    7028             : #ifdef ANDROID_P2P
    7029             :                 wpa_driver_set_p2p_ps(priv, legacy_ps, opp_ps, ctwindow);
    7030             : #else /* ANDROID_P2P */
    7031           2 :                 return -1; /* Not yet supported */
    7032             : #endif /* ANDROID_P2P */
    7033             :         }
    7034             : 
    7035           6 :         if (legacy_ps == -1)
    7036           1 :                 return 0;
    7037           5 :         if (legacy_ps != 0 && legacy_ps != 1)
    7038           2 :                 return -1; /* Not yet supported */
    7039             : 
    7040           3 :         return nl80211_set_power_save(bss, legacy_ps);
    7041             : }
    7042             : 
    7043             : 
    7044          13 : static int nl80211_start_radar_detection(void *priv,
    7045             :                                          struct hostapd_freq_params *freq)
    7046             : {
    7047          13 :         struct i802_bss *bss = priv;
    7048          13 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7049             :         struct nl_msg *msg;
    7050             :         int ret;
    7051             : 
    7052          13 :         wpa_printf(MSG_DEBUG, "nl80211: Start radar detection (CAC) %d MHz (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
    7053             :                    freq->freq, freq->ht_enabled, freq->vht_enabled,
    7054             :                    freq->bandwidth, freq->center_freq1, freq->center_freq2);
    7055             : 
    7056          13 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
    7057           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar "
    7058             :                            "detection");
    7059           0 :                 return -1;
    7060             :         }
    7061             : 
    7062          26 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_RADAR_DETECT)) ||
    7063          13 :             nl80211_put_freq_params(msg, freq) < 0) {
    7064           0 :                 nlmsg_free(msg);
    7065           0 :                 return -1;
    7066             :         }
    7067             : 
    7068          13 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    7069          13 :         if (ret == 0)
    7070          12 :                 return 0;
    7071           1 :         wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
    7072             :                    "%d (%s)", ret, strerror(-ret));
    7073           1 :         return -1;
    7074             : }
    7075             : 
    7076             : #ifdef CONFIG_TDLS
    7077             : 
    7078         128 : static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
    7079             :                                   u8 dialog_token, u16 status_code,
    7080             :                                   u32 peer_capab, int initiator, const u8 *buf,
    7081             :                                   size_t len)
    7082             : {
    7083         128 :         struct i802_bss *bss = priv;
    7084         128 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7085             :         struct nl_msg *msg;
    7086             : 
    7087         128 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
    7088           0 :                 return -EOPNOTSUPP;
    7089             : 
    7090         128 :         if (!dst)
    7091           0 :                 return -EINVAL;
    7092             : 
    7093         256 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_TDLS_MGMT)) ||
    7094         256 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
    7095         256 :             nla_put_u8(msg, NL80211_ATTR_TDLS_ACTION, action_code) ||
    7096         256 :             nla_put_u8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token) ||
    7097         128 :             nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status_code))
    7098             :                 goto fail;
    7099         128 :         if (peer_capab) {
    7100             :                 /*
    7101             :                  * The internal enum tdls_peer_capability definition is
    7102             :                  * currently identical with the nl80211 enum
    7103             :                  * nl80211_tdls_peer_capability, so no conversion is needed
    7104             :                  * here.
    7105             :                  */
    7106          25 :                 if (nla_put_u32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY,
    7107             :                                 peer_capab))
    7108           0 :                         goto fail;
    7109             :         }
    7110         211 :         if ((initiator &&
    7111         211 :              nla_put_flag(msg, NL80211_ATTR_TDLS_INITIATOR)) ||
    7112         128 :             nla_put(msg, NL80211_ATTR_IE, len, buf))
    7113             :                 goto fail;
    7114             : 
    7115         128 :         return send_and_recv_msgs(drv, msg, NULL, NULL);
    7116             : 
    7117             : fail:
    7118           0 :         nlmsg_free(msg);
    7119           0 :         return -ENOBUFS;
    7120             : }
    7121             : 
    7122             : 
    7123        3451 : static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
    7124             : {
    7125        3451 :         struct i802_bss *bss = priv;
    7126        3451 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7127             :         struct nl_msg *msg;
    7128             :         enum nl80211_tdls_operation nl80211_oper;
    7129             : 
    7130        3451 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
    7131           0 :                 return -EOPNOTSUPP;
    7132             : 
    7133        3451 :         switch (oper) {
    7134             :         case TDLS_DISCOVERY_REQ:
    7135           0 :                 nl80211_oper = NL80211_TDLS_DISCOVERY_REQ;
    7136           0 :                 break;
    7137             :         case TDLS_SETUP:
    7138           0 :                 nl80211_oper = NL80211_TDLS_SETUP;
    7139           0 :                 break;
    7140             :         case TDLS_TEARDOWN:
    7141           0 :                 nl80211_oper = NL80211_TDLS_TEARDOWN;
    7142           0 :                 break;
    7143             :         case TDLS_ENABLE_LINK:
    7144          49 :                 nl80211_oper = NL80211_TDLS_ENABLE_LINK;
    7145          49 :                 break;
    7146             :         case TDLS_DISABLE_LINK:
    7147          59 :                 nl80211_oper = NL80211_TDLS_DISABLE_LINK;
    7148          59 :                 break;
    7149             :         case TDLS_ENABLE:
    7150        3342 :                 return 0;
    7151             :         case TDLS_DISABLE:
    7152           1 :                 return 0;
    7153             :         default:
    7154           0 :                 return -EINVAL;
    7155             :         }
    7156             : 
    7157         216 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_TDLS_OPER)) ||
    7158         216 :             nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper) ||
    7159         108 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) {
    7160           0 :                 nlmsg_free(msg);
    7161           0 :                 return -ENOBUFS;
    7162             :         }
    7163             : 
    7164         108 :         return send_and_recv_msgs(drv, msg, NULL, NULL);
    7165             : }
    7166             : 
    7167             : 
    7168             : static int
    7169           1 : nl80211_tdls_enable_channel_switch(void *priv, const u8 *addr, u8 oper_class,
    7170             :                                    const struct hostapd_freq_params *params)
    7171             : {
    7172           1 :         struct i802_bss *bss = priv;
    7173           1 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7174             :         struct nl_msg *msg;
    7175           1 :         int ret = -ENOBUFS;
    7176             : 
    7177           2 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) ||
    7178           1 :             !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH))
    7179           0 :                 return -EOPNOTSUPP;
    7180             : 
    7181           7 :         wpa_printf(MSG_DEBUG, "nl80211: Enable TDLS channel switch " MACSTR
    7182             :                    " oper_class=%u freq=%u",
    7183           6 :                    MAC2STR(addr), oper_class, params->freq);
    7184           1 :         msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_TDLS_CHANNEL_SWITCH);
    7185           2 :         if (!msg ||
    7186           2 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
    7187           2 :             nla_put_u8(msg, NL80211_ATTR_OPER_CLASS, oper_class) ||
    7188             :             (ret = nl80211_put_freq_params(msg, params))) {
    7189           0 :                 nlmsg_free(msg);
    7190           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Could not build TDLS chan switch");
    7191           0 :                 return ret;
    7192             :         }
    7193             : 
    7194           1 :         return send_and_recv_msgs(drv, msg, NULL, NULL);
    7195             : }
    7196             : 
    7197             : 
    7198             : static int
    7199           1 : nl80211_tdls_disable_channel_switch(void *priv, const u8 *addr)
    7200             : {
    7201           1 :         struct i802_bss *bss = priv;
    7202           1 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7203             :         struct nl_msg *msg;
    7204             : 
    7205           2 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) ||
    7206           1 :             !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH))
    7207           0 :                 return -EOPNOTSUPP;
    7208             : 
    7209           6 :         wpa_printf(MSG_DEBUG, "nl80211: Disable TDLS channel switch " MACSTR,
    7210           6 :                    MAC2STR(addr));
    7211           1 :         msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH);
    7212           2 :         if (!msg ||
    7213           1 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
    7214           0 :                 nlmsg_free(msg);
    7215           0 :                 wpa_printf(MSG_DEBUG,
    7216             :                            "nl80211: Could not build TDLS cancel chan switch");
    7217           0 :                 return -ENOBUFS;
    7218             :         }
    7219             : 
    7220           1 :         return send_and_recv_msgs(drv, msg, NULL, NULL);
    7221             : }
    7222             : 
    7223             : #endif /* CONFIG TDLS */
    7224             : 
    7225             : 
    7226       29052 : static int driver_nl80211_set_key(const char *ifname, void *priv,
    7227             :                                   enum wpa_alg alg, const u8 *addr,
    7228             :                                   int key_idx, int set_tx,
    7229             :                                   const u8 *seq, size_t seq_len,
    7230             :                                   const u8 *key, size_t key_len)
    7231             : {
    7232       29052 :         struct i802_bss *bss = priv;
    7233       29052 :         return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx,
    7234             :                                           set_tx, seq, seq_len, key, key_len);
    7235             : }
    7236             : 
    7237             : 
    7238        2940 : static int driver_nl80211_scan2(void *priv,
    7239             :                                 struct wpa_driver_scan_params *params)
    7240             : {
    7241        2940 :         struct i802_bss *bss = priv;
    7242        2940 :         return wpa_driver_nl80211_scan(bss, params);
    7243             : }
    7244             : 
    7245             : 
    7246        2249 : static int driver_nl80211_deauthenticate(void *priv, const u8 *addr,
    7247             :                                          int reason_code)
    7248             : {
    7249        2249 :         struct i802_bss *bss = priv;
    7250        2249 :         return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code);
    7251             : }
    7252             : 
    7253             : 
    7254        2713 : static int driver_nl80211_authenticate(void *priv,
    7255             :                                        struct wpa_driver_auth_params *params)
    7256             : {
    7257        2713 :         struct i802_bss *bss = priv;
    7258        2713 :         return wpa_driver_nl80211_authenticate(bss, params);
    7259             : }
    7260             : 
    7261             : 
    7262         229 : static void driver_nl80211_deinit(void *priv)
    7263             : {
    7264         229 :         struct i802_bss *bss = priv;
    7265         229 :         wpa_driver_nl80211_deinit(bss);
    7266         229 : }
    7267             : 
    7268             : 
    7269         194 : static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
    7270             :                                     const char *ifname)
    7271             : {
    7272         194 :         struct i802_bss *bss = priv;
    7273         194 :         return wpa_driver_nl80211_if_remove(bss, type, ifname);
    7274             : }
    7275             : 
    7276             : 
    7277        9029 : static int driver_nl80211_send_mlme(void *priv, const u8 *data,
    7278             :                                     size_t data_len, int noack)
    7279             : {
    7280        9029 :         struct i802_bss *bss = priv;
    7281        9029 :         return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
    7282             :                                             0, 0, 0, 0);
    7283             : }
    7284             : 
    7285             : 
    7286        4744 : static int driver_nl80211_sta_remove(void *priv, const u8 *addr)
    7287             : {
    7288        4744 :         struct i802_bss *bss = priv;
    7289        4744 :         return wpa_driver_nl80211_sta_remove(bss, addr, -1, 0);
    7290             : }
    7291             : 
    7292             : 
    7293          14 : static int driver_nl80211_set_sta_vlan(void *priv, const u8 *addr,
    7294             :                                        const char *ifname, int vlan_id)
    7295             : {
    7296          14 :         struct i802_bss *bss = priv;
    7297          14 :         return i802_set_sta_vlan(bss, addr, ifname, vlan_id);
    7298             : }
    7299             : 
    7300             : 
    7301         297 : static int driver_nl80211_read_sta_data(void *priv,
    7302             :                                         struct hostap_sta_driver_data *data,
    7303             :                                         const u8 *addr)
    7304             : {
    7305         297 :         struct i802_bss *bss = priv;
    7306         297 :         return i802_read_sta_data(bss, data, addr);
    7307             : }
    7308             : 
    7309             : 
    7310        2248 : static int driver_nl80211_send_action(void *priv, unsigned int freq,
    7311             :                                       unsigned int wait_time,
    7312             :                                       const u8 *dst, const u8 *src,
    7313             :                                       const u8 *bssid,
    7314             :                                       const u8 *data, size_t data_len,
    7315             :                                       int no_cck)
    7316             : {
    7317        2248 :         struct i802_bss *bss = priv;
    7318        2248 :         return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src,
    7319             :                                               bssid, data, data_len, no_cck);
    7320             : }
    7321             : 
    7322             : 
    7323       13874 : static int driver_nl80211_probe_req_report(void *priv, int report)
    7324             : {
    7325       13874 :         struct i802_bss *bss = priv;
    7326       13874 :         return wpa_driver_nl80211_probe_req_report(bss, report);
    7327             : }
    7328             : 
    7329             : 
    7330           0 : static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
    7331             :                                             const u8 *ies, size_t ies_len)
    7332             : {
    7333             :         int ret;
    7334             :         struct nl_msg *msg;
    7335           0 :         struct i802_bss *bss = priv;
    7336           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7337           0 :         u16 mdid = WPA_GET_LE16(md);
    7338             : 
    7339           0 :         wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
    7340           0 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_UPDATE_FT_IES)) ||
    7341           0 :             nla_put(msg, NL80211_ATTR_IE, ies_len, ies) ||
    7342           0 :             nla_put_u16(msg, NL80211_ATTR_MDID, mdid)) {
    7343           0 :                 nlmsg_free(msg);
    7344           0 :                 return -ENOBUFS;
    7345             :         }
    7346             : 
    7347           0 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    7348           0 :         if (ret) {
    7349           0 :                 wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
    7350             :                            "err=%d (%s)", ret, strerror(-ret));
    7351             :         }
    7352             : 
    7353           0 :         return ret;
    7354             : }
    7355             : 
    7356             : 
    7357         250 : const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
    7358             : {
    7359         250 :         struct i802_bss *bss = priv;
    7360         250 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7361             : 
    7362         250 :         if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE)
    7363         242 :                 return NULL;
    7364             : 
    7365           8 :         return bss->addr;
    7366             : }
    7367             : 
    7368             : 
    7369        4252 : static const char * scan_state_str(enum scan_states scan_state)
    7370             : {
    7371        4252 :         switch (scan_state) {
    7372             :         case NO_SCAN:
    7373          85 :                 return "NO_SCAN";
    7374             :         case SCAN_REQUESTED:
    7375           2 :                 return "SCAN_REQUESTED";
    7376             :         case SCAN_STARTED:
    7377          22 :                 return "SCAN_STARTED";
    7378             :         case SCAN_COMPLETED:
    7379        4130 :                 return "SCAN_COMPLETED";
    7380             :         case SCAN_ABORTED:
    7381          13 :                 return "SCAN_ABORTED";
    7382             :         case SCHED_SCAN_STARTED:
    7383           0 :                 return "SCHED_SCAN_STARTED";
    7384             :         case SCHED_SCAN_STOPPED:
    7385           0 :                 return "SCHED_SCAN_STOPPED";
    7386             :         case SCHED_SCAN_RESULTS:
    7387           0 :                 return "SCHED_SCAN_RESULTS";
    7388             :         }
    7389             : 
    7390           0 :         return "??";
    7391             : }
    7392             : 
    7393             : 
    7394        4252 : static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
    7395             : {
    7396        4252 :         struct i802_bss *bss = priv;
    7397        4252 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7398             :         int res;
    7399             :         char *pos, *end;
    7400             : 
    7401        4252 :         pos = buf;
    7402        4252 :         end = buf + buflen;
    7403             : 
    7404       51024 :         res = os_snprintf(pos, end - pos,
    7405             :                           "ifindex=%d\n"
    7406             :                           "ifname=%s\n"
    7407             :                           "brname=%s\n"
    7408             :                           "addr=" MACSTR "\n"
    7409             :                           "freq=%d\n"
    7410             :                           "%s%s%s%s%s",
    7411             :                           bss->ifindex,
    7412        4252 :                           bss->ifname,
    7413        4252 :                           bss->brname,
    7414       25512 :                           MAC2STR(bss->addr),
    7415             :                           bss->freq,
    7416        4252 :                           bss->beacon_set ? "beacon_set=1\n" : "",
    7417        4252 :                           bss->added_if_into_bridge ?
    7418             :                           "added_if_into_bridge=1\n" : "",
    7419        4252 :                           bss->added_bridge ? "added_bridge=1\n" : "",
    7420        4252 :                           bss->in_deinit ? "in_deinit=1\n" : "",
    7421        4252 :                           bss->if_dynamic ? "if_dynamic=1\n" : "");
    7422        4252 :         if (os_snprintf_error(end - pos, res))
    7423           0 :                 return pos - buf;
    7424        4252 :         pos += res;
    7425             : 
    7426        4252 :         if (bss->wdev_id_set) {
    7427           1 :                 res = os_snprintf(pos, end - pos, "wdev_id=%llu\n",
    7428           1 :                                   (unsigned long long) bss->wdev_id);
    7429           1 :                 if (os_snprintf_error(end - pos, res))
    7430           0 :                         return pos - buf;
    7431           1 :                 pos += res;
    7432             :         }
    7433             : 
    7434      187088 :         res = os_snprintf(pos, end - pos,
    7435             :                           "phyname=%s\n"
    7436             :                           "perm_addr=" MACSTR "\n"
    7437             :                           "drv_ifindex=%d\n"
    7438             :                           "operstate=%d\n"
    7439             :                           "scan_state=%s\n"
    7440             :                           "auth_bssid=" MACSTR "\n"
    7441             :                           "auth_attempt_bssid=" MACSTR "\n"
    7442             :                           "bssid=" MACSTR "\n"
    7443             :                           "prev_bssid=" MACSTR "\n"
    7444             :                           "associated=%d\n"
    7445             :                           "assoc_freq=%u\n"
    7446             :                           "monitor_sock=%d\n"
    7447             :                           "monitor_ifidx=%d\n"
    7448             :                           "monitor_refcount=%d\n"
    7449             :                           "last_mgmt_freq=%u\n"
    7450             :                           "eapol_tx_sock=%d\n"
    7451             :                           "%s%s%s%s%s%s%s%s%s%s%s%s%s",
    7452        4252 :                           drv->phyname,
    7453       25512 :                           MAC2STR(drv->perm_addr),
    7454             :                           drv->ifindex,
    7455             :                           drv->operstate,
    7456             :                           scan_state_str(drv->scan_state),
    7457       25512 :                           MAC2STR(drv->auth_bssid),
    7458       25512 :                           MAC2STR(drv->auth_attempt_bssid),
    7459       25512 :                           MAC2STR(drv->bssid),
    7460       25512 :                           MAC2STR(drv->prev_bssid),
    7461             :                           drv->associated,
    7462             :                           drv->assoc_freq,
    7463             :                           drv->monitor_sock,
    7464             :                           drv->monitor_ifidx,
    7465             :                           drv->monitor_refcount,
    7466             :                           drv->last_mgmt_freq,
    7467             :                           drv->eapol_tx_sock,
    7468        4252 :                           drv->ignore_if_down_event ?
    7469             :                           "ignore_if_down_event=1\n" : "",
    7470        4252 :                           drv->scan_complete_events ?
    7471             :                           "scan_complete_events=1\n" : "",
    7472        4252 :                           drv->disabled_11b_rates ?
    7473             :                           "disabled_11b_rates=1\n" : "",
    7474        4252 :                           drv->pending_remain_on_chan ?
    7475             :                           "pending_remain_on_chan=1\n" : "",
    7476        4252 :                           drv->in_interface_list ? "in_interface_list=1\n" : "",
    7477        4252 :                           drv->device_ap_sme ? "device_ap_sme=1\n" : "",
    7478        4252 :                           drv->poll_command_supported ?
    7479             :                           "poll_command_supported=1\n" : "",
    7480        4252 :                           drv->data_tx_status ? "data_tx_status=1\n" : "",
    7481        4252 :                           drv->scan_for_auth ? "scan_for_auth=1\n" : "",
    7482        4252 :                           drv->retry_auth ? "retry_auth=1\n" : "",
    7483        4252 :                           drv->use_monitor ? "use_monitor=1\n" : "",
    7484        4252 :                           drv->ignore_next_local_disconnect ?
    7485             :                           "ignore_next_local_disconnect=1\n" : "",
    7486        4252 :                           drv->ignore_next_local_deauth ?
    7487             :                           "ignore_next_local_deauth=1\n" : "");
    7488        4252 :         if (os_snprintf_error(end - pos, res))
    7489           0 :                 return pos - buf;
    7490        4252 :         pos += res;
    7491             : 
    7492        4252 :         if (drv->has_capability) {
    7493       12756 :                 res = os_snprintf(pos, end - pos,
    7494             :                                   "capa.key_mgmt=0x%x\n"
    7495             :                                   "capa.enc=0x%x\n"
    7496             :                                   "capa.auth=0x%x\n"
    7497             :                                   "capa.flags=0x%llx\n"
    7498             :                                   "capa.rrm_flags=0x%x\n"
    7499             :                                   "capa.max_scan_ssids=%d\n"
    7500             :                                   "capa.max_sched_scan_ssids=%d\n"
    7501             :                                   "capa.sched_scan_supported=%d\n"
    7502             :                                   "capa.max_match_sets=%d\n"
    7503             :                                   "capa.max_remain_on_chan=%u\n"
    7504             :                                   "capa.max_stations=%u\n"
    7505             :                                   "capa.probe_resp_offloads=0x%x\n"
    7506             :                                   "capa.max_acl_mac_addrs=%u\n"
    7507             :                                   "capa.num_multichan_concurrent=%u\n"
    7508             :                                   "capa.mac_addr_rand_sched_scan_supported=%d\n"
    7509             :                                   "capa.mac_addr_rand_scan_supported=%d\n",
    7510             :                                   drv->capa.key_mgmt,
    7511             :                                   drv->capa.enc,
    7512             :                                   drv->capa.auth,
    7513        4252 :                                   (unsigned long long) drv->capa.flags,
    7514             :                                   drv->capa.rrm_flags,
    7515             :                                   drv->capa.max_scan_ssids,
    7516             :                                   drv->capa.max_sched_scan_ssids,
    7517             :                                   drv->capa.sched_scan_supported,
    7518             :                                   drv->capa.max_match_sets,
    7519             :                                   drv->capa.max_remain_on_chan,
    7520             :                                   drv->capa.max_stations,
    7521             :                                   drv->capa.probe_resp_offloads,
    7522             :                                   drv->capa.max_acl_mac_addrs,
    7523             :                                   drv->capa.num_multichan_concurrent,
    7524        4252 :                                   drv->capa.mac_addr_rand_sched_scan_supported,
    7525        4252 :                                   drv->capa.mac_addr_rand_scan_supported);
    7526        4252 :                 if (os_snprintf_error(end - pos, res))
    7527           0 :                         return pos - buf;
    7528        4252 :                 pos += res;
    7529             :         }
    7530             : 
    7531        4252 :         return pos - buf;
    7532             : }
    7533             : 
    7534             : 
    7535          44 : static int set_beacon_data(struct nl_msg *msg, struct beacon_data *settings)
    7536             : {
    7537          88 :         if ((settings->head &&
    7538          44 :              nla_put(msg, NL80211_ATTR_BEACON_HEAD,
    7539          88 :                      settings->head_len, settings->head)) ||
    7540          88 :             (settings->tail &&
    7541          44 :              nla_put(msg, NL80211_ATTR_BEACON_TAIL,
    7542          88 :                      settings->tail_len, settings->tail)) ||
    7543          88 :             (settings->beacon_ies &&
    7544          44 :              nla_put(msg, NL80211_ATTR_IE,
    7545          88 :                      settings->beacon_ies_len, settings->beacon_ies)) ||
    7546          88 :             (settings->proberesp_ies &&
    7547          44 :              nla_put(msg, NL80211_ATTR_IE_PROBE_RESP,
    7548          88 :                      settings->proberesp_ies_len, settings->proberesp_ies)) ||
    7549          88 :             (settings->assocresp_ies &&
    7550          44 :              nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP,
    7551          88 :                      settings->assocresp_ies_len, settings->assocresp_ies)) ||
    7552          44 :             (settings->probe_resp &&
    7553           0 :              nla_put(msg, NL80211_ATTR_PROBE_RESP,
    7554           0 :                      settings->probe_resp_len, settings->probe_resp)))
    7555           0 :                 return -ENOBUFS;
    7556             : 
    7557          44 :         return 0;
    7558             : }
    7559             : 
    7560             : 
    7561          23 : static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
    7562             : {
    7563             :         struct nl_msg *msg;
    7564          23 :         struct i802_bss *bss = priv;
    7565          23 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7566             :         struct nlattr *beacon_csa;
    7567          23 :         int ret = -ENOBUFS;
    7568             : 
    7569          69 :         wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d width=%d cf1=%d cf2=%d)",
    7570          46 :                    settings->cs_count, settings->block_tx,
    7571             :                    settings->freq_params.freq, settings->freq_params.bandwidth,
    7572             :                    settings->freq_params.center_freq1,
    7573             :                    settings->freq_params.center_freq2);
    7574             : 
    7575          23 :         if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) {
    7576           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command");
    7577           0 :                 return -EOPNOTSUPP;
    7578             :         }
    7579             : 
    7580          24 :         if ((drv->nlmode != NL80211_IFTYPE_AP) &&
    7581           1 :             (drv->nlmode != NL80211_IFTYPE_P2P_GO))
    7582           0 :                 return -EOPNOTSUPP;
    7583             : 
    7584             :         /* check settings validity */
    7585          46 :         if (!settings->beacon_csa.tail ||
    7586          46 :             ((settings->beacon_csa.tail_len <=
    7587          46 :               settings->counter_offset_beacon) ||
    7588          23 :              (settings->beacon_csa.tail[settings->counter_offset_beacon] !=
    7589          23 :               settings->cs_count)))
    7590           0 :                 return -EINVAL;
    7591             : 
    7592          23 :         if (settings->beacon_csa.probe_resp &&
    7593           0 :             ((settings->beacon_csa.probe_resp_len <=
    7594           0 :               settings->counter_offset_presp) ||
    7595           0 :              (settings->beacon_csa.probe_resp[settings->counter_offset_presp] !=
    7596           0 :               settings->cs_count)))
    7597           0 :                 return -EINVAL;
    7598             : 
    7599          46 :         if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_CHANNEL_SWITCH)) ||
    7600          23 :             nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT,
    7601          46 :                         settings->cs_count) ||
    7602          45 :             (ret = nl80211_put_freq_params(msg, &settings->freq_params)) ||
    7603          25 :             (settings->block_tx &&
    7604           3 :              nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX)))
    7605             :                 goto error;
    7606             : 
    7607             :         /* beacon_after params */
    7608          22 :         ret = set_beacon_data(msg, &settings->beacon_after);
    7609          22 :         if (ret)
    7610           0 :                 goto error;
    7611             : 
    7612             :         /* beacon_csa params */
    7613          22 :         beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
    7614          22 :         if (!beacon_csa)
    7615           0 :                 goto fail;
    7616             : 
    7617          22 :         ret = set_beacon_data(msg, &settings->beacon_csa);
    7618          22 :         if (ret)
    7619           0 :                 goto error;
    7620             : 
    7621          22 :         if (nla_put_u16(msg, NL80211_ATTR_CSA_C_OFF_BEACON,
    7622          44 :                         settings->counter_offset_beacon) ||
    7623          22 :             (settings->beacon_csa.probe_resp &&
    7624           0 :              nla_put_u16(msg, NL80211_ATTR_CSA_C_OFF_PRESP,
    7625           0 :                          settings->counter_offset_presp)))
    7626             :                 goto fail;
    7627             : 
    7628          22 :         nla_nest_end(msg, beacon_csa);
    7629          22 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    7630          22 :         if (ret) {
    7631           1 :                 wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)",
    7632             :                            ret, strerror(-ret));
    7633             :         }
    7634          22 :         return ret;
    7635             : 
    7636             : fail:
    7637           0 :         ret = -ENOBUFS;
    7638             : error:
    7639           1 :         nlmsg_free(msg);
    7640           1 :         wpa_printf(MSG_DEBUG, "nl80211: Could not build channel switch request");
    7641           1 :         return ret;
    7642             : }
    7643             : 
    7644             : 
    7645           0 : static int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr,
    7646             :                           u8 user_priority, u16 admitted_time)
    7647             : {
    7648           0 :         struct i802_bss *bss = priv;
    7649           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7650             :         struct nl_msg *msg;
    7651             :         int ret;
    7652             : 
    7653           0 :         wpa_printf(MSG_DEBUG,
    7654             :                    "nl80211: add_ts request: tsid=%u admitted_time=%u up=%d",
    7655             :                    tsid, admitted_time, user_priority);
    7656             : 
    7657           0 :         if (!is_sta_interface(drv->nlmode))
    7658           0 :                 return -ENOTSUP;
    7659             : 
    7660           0 :         msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ADD_TX_TS);
    7661           0 :         if (!msg ||
    7662           0 :             nla_put_u8(msg, NL80211_ATTR_TSID, tsid) ||
    7663           0 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
    7664           0 :             nla_put_u8(msg, NL80211_ATTR_USER_PRIO, user_priority) ||
    7665           0 :             nla_put_u16(msg, NL80211_ATTR_ADMITTED_TIME, admitted_time)) {
    7666           0 :                 nlmsg_free(msg);
    7667           0 :                 return -ENOBUFS;
    7668             :         }
    7669             : 
    7670           0 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    7671           0 :         if (ret)
    7672           0 :                 wpa_printf(MSG_DEBUG, "nl80211: add_ts failed err=%d (%s)",
    7673             :                            ret, strerror(-ret));
    7674           0 :         return ret;
    7675             : }
    7676             : 
    7677             : 
    7678           0 : static int nl80211_del_ts(void *priv, u8 tsid, const u8 *addr)
    7679             : {
    7680           0 :         struct i802_bss *bss = priv;
    7681           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7682             :         struct nl_msg *msg;
    7683             :         int ret;
    7684             : 
    7685           0 :         wpa_printf(MSG_DEBUG, "nl80211: del_ts request: tsid=%u", tsid);
    7686             : 
    7687           0 :         if (!is_sta_interface(drv->nlmode))
    7688           0 :                 return -ENOTSUP;
    7689             : 
    7690           0 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_TX_TS)) ||
    7691           0 :             nla_put_u8(msg, NL80211_ATTR_TSID, tsid) ||
    7692           0 :             nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
    7693           0 :                 nlmsg_free(msg);
    7694           0 :                 return -ENOBUFS;
    7695             :         }
    7696             : 
    7697           0 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    7698           0 :         if (ret)
    7699           0 :                 wpa_printf(MSG_DEBUG, "nl80211: del_ts failed err=%d (%s)",
    7700             :                            ret, strerror(-ret));
    7701           0 :         return ret;
    7702             : }
    7703             : 
    7704             : 
    7705             : #ifdef CONFIG_TESTING_OPTIONS
    7706           2 : static int cmd_reply_handler(struct nl_msg *msg, void *arg)
    7707             : {
    7708           2 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    7709           2 :         struct wpabuf *buf = arg;
    7710             : 
    7711           2 :         if (!buf)
    7712           0 :                 return NL_SKIP;
    7713             : 
    7714           2 :         if ((size_t) genlmsg_attrlen(gnlh, 0) > wpabuf_tailroom(buf)) {
    7715           0 :                 wpa_printf(MSG_INFO, "nl80211: insufficient buffer space for reply");
    7716           0 :                 return NL_SKIP;
    7717             :         }
    7718             : 
    7719           2 :         wpabuf_put_data(buf, genlmsg_attrdata(gnlh, 0),
    7720           2 :                         genlmsg_attrlen(gnlh, 0));
    7721             : 
    7722           2 :         return NL_SKIP;
    7723             : }
    7724             : #endif /* CONFIG_TESTING_OPTIONS */
    7725             : 
    7726             : 
    7727           0 : static int vendor_reply_handler(struct nl_msg *msg, void *arg)
    7728             : {
    7729             :         struct nlattr *tb[NL80211_ATTR_MAX + 1];
    7730             :         struct nlattr *nl_vendor_reply, *nl;
    7731           0 :         struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    7732           0 :         struct wpabuf *buf = arg;
    7733             :         int rem;
    7734             : 
    7735           0 :         if (!buf)
    7736           0 :                 return NL_SKIP;
    7737             : 
    7738           0 :         nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    7739             :                   genlmsg_attrlen(gnlh, 0), NULL);
    7740           0 :         nl_vendor_reply = tb[NL80211_ATTR_VENDOR_DATA];
    7741             : 
    7742           0 :         if (!nl_vendor_reply)
    7743           0 :                 return NL_SKIP;
    7744             : 
    7745           0 :         if ((size_t) nla_len(nl_vendor_reply) > wpabuf_tailroom(buf)) {
    7746           0 :                 wpa_printf(MSG_INFO, "nl80211: Vendor command: insufficient buffer space for reply");
    7747           0 :                 return NL_SKIP;
    7748             :         }
    7749             : 
    7750           0 :         nla_for_each_nested(nl, nl_vendor_reply, rem) {
    7751           0 :                 wpabuf_put_data(buf, nla_data(nl), nla_len(nl));
    7752             :         }
    7753             : 
    7754           0 :         return NL_SKIP;
    7755             : }
    7756             : 
    7757             : 
    7758           5 : static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
    7759             :                               unsigned int subcmd, const u8 *data,
    7760             :                               size_t data_len, struct wpabuf *buf)
    7761             : {
    7762           5 :         struct i802_bss *bss = priv;
    7763           5 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7764             :         struct nl_msg *msg;
    7765             :         int ret;
    7766             : 
    7767             : #ifdef CONFIG_TESTING_OPTIONS
    7768           5 :         if (vendor_id == 0xffffffff) {
    7769           5 :                 msg = nlmsg_alloc();
    7770           5 :                 if (!msg)
    7771           0 :                         return -ENOMEM;
    7772             : 
    7773           5 :                 nl80211_cmd(drv, msg, 0, subcmd);
    7774           5 :                 if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) <
    7775             :                     0)
    7776           0 :                         goto fail;
    7777           5 :                 ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf);
    7778           5 :                 if (ret)
    7779           0 :                         wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
    7780             :                                    ret);
    7781           5 :                 return ret;
    7782             :         }
    7783             : #endif /* CONFIG_TESTING_OPTIONS */
    7784             : 
    7785           0 :         if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_VENDOR)) ||
    7786           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, vendor_id) ||
    7787           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd) ||
    7788           0 :             (data &&
    7789           0 :              nla_put(msg, NL80211_ATTR_VENDOR_DATA, data_len, data)))
    7790             :                 goto fail;
    7791             : 
    7792           0 :         ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf);
    7793           0 :         if (ret)
    7794           0 :                 wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d",
    7795             :                            ret);
    7796           0 :         return ret;
    7797             : 
    7798             : fail:
    7799           0 :         nlmsg_free(msg);
    7800           0 :         return -ENOBUFS;
    7801             : }
    7802             : 
    7803             : 
    7804           5 : static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set,
    7805             :                                u8 qos_map_set_len)
    7806             : {
    7807           5 :         struct i802_bss *bss = priv;
    7808           5 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7809             :         struct nl_msg *msg;
    7810             :         int ret;
    7811             : 
    7812           5 :         wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map",
    7813             :                     qos_map_set, qos_map_set_len);
    7814             : 
    7815          10 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_QOS_MAP)) ||
    7816           5 :             nla_put(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set)) {
    7817           0 :                 nlmsg_free(msg);
    7818           0 :                 return -ENOBUFS;
    7819             :         }
    7820             : 
    7821           5 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    7822           5 :         if (ret)
    7823           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed");
    7824             : 
    7825           5 :         return ret;
    7826             : }
    7827             : 
    7828             : 
    7829           0 : static int nl80211_set_wowlan(void *priv,
    7830             :                               const struct wowlan_triggers *triggers)
    7831             : {
    7832           0 :         struct i802_bss *bss = priv;
    7833           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7834             :         struct nl_msg *msg;
    7835             :         struct nlattr *wowlan_triggers;
    7836             :         int ret;
    7837             : 
    7838           0 :         wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan");
    7839             : 
    7840           0 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WOWLAN)) ||
    7841             :             !(wowlan_triggers = nla_nest_start(msg,
    7842           0 :                                                NL80211_ATTR_WOWLAN_TRIGGERS)) ||
    7843           0 :             (triggers->any &&
    7844           0 :              nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
    7845           0 :             (triggers->disconnect &&
    7846           0 :              nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
    7847           0 :             (triggers->magic_pkt &&
    7848           0 :              nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
    7849           0 :             (triggers->gtk_rekey_failure &&
    7850           0 :              nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
    7851           0 :             (triggers->eap_identity_req &&
    7852           0 :              nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
    7853           0 :             (triggers->four_way_handshake &&
    7854           0 :              nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
    7855           0 :             (triggers->rfkill_release &&
    7856           0 :              nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) {
    7857           0 :                 nlmsg_free(msg);
    7858           0 :                 return -ENOBUFS;
    7859             :         }
    7860             : 
    7861           0 :         nla_nest_end(msg, wowlan_triggers);
    7862             : 
    7863           0 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    7864           0 :         if (ret)
    7865           0 :                 wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed");
    7866             : 
    7867           0 :         return ret;
    7868             : }
    7869             : 
    7870             : 
    7871           3 : static int nl80211_roaming(void *priv, int allowed, const u8 *bssid)
    7872             : {
    7873           3 :         struct i802_bss *bss = priv;
    7874           3 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7875             :         struct nl_msg *msg;
    7876             :         struct nlattr *params;
    7877             : 
    7878           3 :         wpa_printf(MSG_DEBUG, "nl80211: Roaming policy: allowed=%d", allowed);
    7879             : 
    7880           3 :         if (!drv->roaming_vendor_cmd_avail) {
    7881           3 :                 wpa_printf(MSG_DEBUG,
    7882             :                            "nl80211: Ignore roaming policy change since driver does not provide command for setting it");
    7883           3 :                 return -1;
    7884             :         }
    7885             : 
    7886           0 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
    7887           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
    7888           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
    7889           0 :                         QCA_NL80211_VENDOR_SUBCMD_ROAMING) ||
    7890           0 :             !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
    7891           0 :             nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY,
    7892             :                         allowed ? QCA_ROAMING_ALLOWED_WITHIN_ESS :
    7893           0 :                         QCA_ROAMING_NOT_ALLOWED) ||
    7894           0 :             (bssid &&
    7895           0 :              nla_put(msg, QCA_WLAN_VENDOR_ATTR_MAC_ADDR, ETH_ALEN, bssid))) {
    7896           0 :                 nlmsg_free(msg);
    7897           0 :                 return -1;
    7898             :         }
    7899           0 :         nla_nest_end(msg, params);
    7900             : 
    7901           0 :         return send_and_recv_msgs(drv, msg, NULL, NULL);
    7902             : }
    7903             : 
    7904             : 
    7905          11 : static int nl80211_set_mac_addr(void *priv, const u8 *addr)
    7906             : {
    7907          11 :         struct i802_bss *bss = priv;
    7908          11 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7909          11 :         int new_addr = addr != NULL;
    7910             : 
    7911          11 :         if (!addr)
    7912           2 :                 addr = drv->perm_addr;
    7913             : 
    7914          11 :         if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0)
    7915           0 :                 return -1;
    7916             : 
    7917          11 :         if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr) < 0)
    7918             :         {
    7919           0 :                 wpa_printf(MSG_DEBUG,
    7920             :                            "nl80211: failed to set_mac_addr for %s to " MACSTR,
    7921           0 :                            bss->ifname, MAC2STR(addr));
    7922           0 :                 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
    7923             :                                           1) < 0) {
    7924           0 :                         wpa_printf(MSG_DEBUG,
    7925             :                                    "nl80211: Could not restore interface UP after failed set_mac_addr");
    7926             :                 }
    7927           0 :                 return -1;
    7928             :         }
    7929             : 
    7930          77 :         wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR,
    7931          77 :                    bss->ifname, MAC2STR(addr));
    7932          11 :         drv->addr_changed = new_addr;
    7933          11 :         os_memcpy(bss->addr, addr, ETH_ALEN);
    7934             : 
    7935          11 :         if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0)
    7936             :         {
    7937           0 :                 wpa_printf(MSG_DEBUG,
    7938             :                            "nl80211: Could not restore interface UP after set_mac_addr");
    7939             :         }
    7940             : 
    7941          11 :         return 0;
    7942             : }
    7943             : 
    7944             : 
    7945             : #ifdef CONFIG_MESH
    7946             : 
    7947          34 : static int wpa_driver_nl80211_init_mesh(void *priv)
    7948             : {
    7949          34 :         if (wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_MESH_POINT)) {
    7950           0 :                 wpa_printf(MSG_INFO,
    7951             :                            "nl80211: Failed to set interface into mesh mode");
    7952           0 :                 return -1;
    7953             :         }
    7954          34 :         return 0;
    7955             : }
    7956             : 
    7957             : 
    7958          33 : static int nl80211_put_mesh_id(struct nl_msg *msg, const u8 *mesh_id,
    7959             :                                size_t mesh_id_len)
    7960             : {
    7961          33 :         if (mesh_id) {
    7962          33 :                 wpa_hexdump_ascii(MSG_DEBUG, "  * Mesh ID (SSID)",
    7963             :                                   mesh_id, mesh_id_len);
    7964          33 :                 return nla_put(msg, NL80211_ATTR_MESH_ID, mesh_id_len, mesh_id);
    7965             :         }
    7966             : 
    7967           0 :         return 0;
    7968             : }
    7969             : 
    7970             : 
    7971          33 : static int nl80211_join_mesh(struct i802_bss *bss,
    7972             :                              struct wpa_driver_mesh_join_params *params)
    7973             : {
    7974          33 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    7975             :         struct nl_msg *msg;
    7976             :         struct nlattr *container;
    7977          33 :         int ret = -1;
    7978             : 
    7979          33 :         wpa_printf(MSG_DEBUG, "nl80211: mesh join (ifindex=%d)", drv->ifindex);
    7980          33 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_MESH);
    7981          66 :         if (!msg ||
    7982          66 :             nl80211_put_freq_params(msg, &params->freq) ||
    7983          66 :             nl80211_put_basic_rates(msg, params->basic_rates) ||
    7984          66 :             nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
    7985          33 :             nl80211_put_beacon_int(msg, params->beacon_int))
    7986             :                 goto fail;
    7987             : 
    7988          33 :         wpa_printf(MSG_DEBUG, "  * flags=%08X", params->flags);
    7989             : 
    7990          33 :         container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP);
    7991          33 :         if (!container)
    7992           0 :                 goto fail;
    7993             : 
    7994          33 :         if (params->ies) {
    7995          12 :                 wpa_hexdump(MSG_DEBUG, "  * IEs", params->ies, params->ie_len);
    7996          12 :                 if (nla_put(msg, NL80211_MESH_SETUP_IE, params->ie_len,
    7997          12 :                             params->ies))
    7998           0 :                         goto fail;
    7999             :         }
    8000             :         /* WPA_DRIVER_MESH_FLAG_OPEN_AUTH is treated as default by nl80211 */
    8001          33 :         if (params->flags & WPA_DRIVER_MESH_FLAG_SAE_AUTH) {
    8002          24 :                 if (nla_put_u8(msg, NL80211_MESH_SETUP_AUTH_PROTOCOL, 0x1) ||
    8003          12 :                     nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_AUTH))
    8004             :                         goto fail;
    8005             :         }
    8006          45 :         if ((params->flags & WPA_DRIVER_MESH_FLAG_AMPE) &&
    8007          12 :             nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_AMPE))
    8008           0 :                 goto fail;
    8009          66 :         if ((params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM) &&
    8010          33 :             nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_MPM))
    8011           0 :                 goto fail;
    8012          33 :         nla_nest_end(msg, container);
    8013             : 
    8014          33 :         container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
    8015          33 :         if (!container)
    8016           0 :                 goto fail;
    8017             : 
    8018          66 :         if (!(params->conf.flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
    8019          33 :             nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 0))
    8020           0 :                 goto fail;
    8021          33 :         if ((params->conf.flags & WPA_DRIVER_MESH_FLAG_DRIVER_MPM) &&
    8022           0 :             nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
    8023           0 :                         params->max_peer_links))
    8024           0 :                 goto fail;
    8025             : 
    8026             :         /*
    8027             :          * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because
    8028             :          * the timer could disconnect stations even in that case.
    8029             :          */
    8030          33 :         if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
    8031          33 :                         params->conf.peer_link_timeout)) {
    8032           0 :                 wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT");
    8033           0 :                 goto fail;
    8034             :         }
    8035             : 
    8036          33 :         nla_nest_end(msg, container);
    8037             : 
    8038          33 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    8039          33 :         msg = NULL;
    8040          33 :         if (ret) {
    8041           0 :                 wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
    8042             :                            ret, strerror(-ret));
    8043           0 :                 goto fail;
    8044             :         }
    8045          33 :         ret = 0;
    8046          33 :         bss->freq = params->freq.freq;
    8047          33 :         wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully");
    8048             : 
    8049             : fail:
    8050          33 :         nlmsg_free(msg);
    8051          33 :         return ret;
    8052             : }
    8053             : 
    8054             : 
    8055             : static int
    8056          33 : wpa_driver_nl80211_join_mesh(void *priv,
    8057             :                              struct wpa_driver_mesh_join_params *params)
    8058             : {
    8059          33 :         struct i802_bss *bss = priv;
    8060             :         int ret, timeout;
    8061             : 
    8062          33 :         timeout = params->conf.peer_link_timeout;
    8063             : 
    8064             :         /* Disable kernel inactivity timer */
    8065          33 :         if (params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM)
    8066          33 :                 params->conf.peer_link_timeout = 0;
    8067             : 
    8068          33 :         ret = nl80211_join_mesh(bss, params);
    8069          33 :         if (ret == -EINVAL && params->conf.peer_link_timeout == 0) {
    8070           0 :                 wpa_printf(MSG_DEBUG,
    8071             :                            "nl80211: Mesh join retry for peer_link_timeout");
    8072             :                 /*
    8073             :                  * Old kernel does not support setting
    8074             :                  * NL80211_MESHCONF_PLINK_TIMEOUT to zero, so set 60 seconds
    8075             :                  * into future from peer_link_timeout.
    8076             :                  */
    8077           0 :                 params->conf.peer_link_timeout = timeout + 60;
    8078           0 :                 ret = nl80211_join_mesh(priv, params);
    8079             :         }
    8080             : 
    8081          33 :         params->conf.peer_link_timeout = timeout;
    8082          33 :         return ret;
    8083             : }
    8084             : 
    8085             : 
    8086          34 : static int wpa_driver_nl80211_leave_mesh(void *priv)
    8087             : {
    8088          34 :         struct i802_bss *bss = priv;
    8089          34 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    8090             :         struct nl_msg *msg;
    8091             :         int ret;
    8092             : 
    8093          34 :         wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
    8094          34 :         msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
    8095          34 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    8096          34 :         if (ret) {
    8097           1 :                 wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
    8098             :                            ret, strerror(-ret));
    8099             :         } else {
    8100          33 :                 wpa_printf(MSG_DEBUG,
    8101             :                            "nl80211: mesh leave request send successfully");
    8102             :         }
    8103             : 
    8104          34 :         if (wpa_driver_nl80211_set_mode(drv->first_bss,
    8105             :                                         NL80211_IFTYPE_STATION)) {
    8106           0 :                 wpa_printf(MSG_INFO,
    8107             :                            "nl80211: Failed to set interface into station mode");
    8108             :         }
    8109          34 :         return ret;
    8110             : }
    8111             : 
    8112             : #endif /* CONFIG_MESH */
    8113             : 
    8114             : 
    8115          17 : static int wpa_driver_br_add_ip_neigh(void *priv, u8 version,
    8116             :                                       const u8 *ipaddr, int prefixlen,
    8117             :                                       const u8 *addr)
    8118             : {
    8119             : #ifdef CONFIG_LIBNL3_ROUTE
    8120          17 :         struct i802_bss *bss = priv;
    8121          17 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    8122             :         struct rtnl_neigh *rn;
    8123          17 :         struct nl_addr *nl_ipaddr = NULL;
    8124          17 :         struct nl_addr *nl_lladdr = NULL;
    8125             :         int family, addrsize;
    8126             :         int res;
    8127             : 
    8128          17 :         if (!ipaddr || prefixlen == 0 || !addr)
    8129           0 :                 return -EINVAL;
    8130             : 
    8131          17 :         if (bss->br_ifindex == 0) {
    8132           0 :                 wpa_printf(MSG_DEBUG,
    8133             :                            "nl80211: bridge must be set before adding an ip neigh to it");
    8134           0 :                 return -1;
    8135             :         }
    8136             : 
    8137          17 :         if (!drv->rtnl_sk) {
    8138           0 :                 wpa_printf(MSG_DEBUG,
    8139             :                            "nl80211: nl_sock for NETLINK_ROUTE is not initialized");
    8140           0 :                 return -1;
    8141             :         }
    8142             : 
    8143          17 :         if (version == 4) {
    8144           6 :                 family = AF_INET;
    8145           6 :                 addrsize = 4;
    8146          11 :         } else if (version == 6) {
    8147          11 :                 family = AF_INET6;
    8148          11 :                 addrsize = 16;
    8149             :         } else {
    8150           0 :                 return -EINVAL;
    8151             :         }
    8152             : 
    8153          17 :         rn = rtnl_neigh_alloc();
    8154          17 :         if (rn == NULL)
    8155           0 :                 return -ENOMEM;
    8156             : 
    8157             :         /* set the destination ip address for neigh */
    8158          17 :         nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
    8159          17 :         if (nl_ipaddr == NULL) {
    8160           0 :                 wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
    8161           0 :                 res = -ENOMEM;
    8162           0 :                 goto errout;
    8163             :         }
    8164          17 :         nl_addr_set_prefixlen(nl_ipaddr, prefixlen);
    8165          17 :         res = rtnl_neigh_set_dst(rn, nl_ipaddr);
    8166          17 :         if (res) {
    8167           0 :                 wpa_printf(MSG_DEBUG,
    8168             :                            "nl80211: neigh set destination addr failed");
    8169           0 :                 goto errout;
    8170             :         }
    8171             : 
    8172             :         /* set the corresponding lladdr for neigh */
    8173          17 :         nl_lladdr = nl_addr_build(AF_BRIDGE, (u8 *) addr, ETH_ALEN);
    8174          17 :         if (nl_lladdr == NULL) {
    8175           0 :                 wpa_printf(MSG_DEBUG, "nl80211: neigh set lladdr failed");
    8176           0 :                 res = -ENOMEM;
    8177           0 :                 goto errout;
    8178             :         }
    8179          17 :         rtnl_neigh_set_lladdr(rn, nl_lladdr);
    8180             : 
    8181          17 :         rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
    8182          17 :         rtnl_neigh_set_state(rn, NUD_PERMANENT);
    8183             : 
    8184          17 :         res = rtnl_neigh_add(drv->rtnl_sk, rn, NLM_F_CREATE);
    8185          17 :         if (res) {
    8186           0 :                 wpa_printf(MSG_DEBUG,
    8187             :                            "nl80211: Adding bridge ip neigh failed: %s",
    8188           0 :                            strerror(errno));
    8189             :         }
    8190             : errout:
    8191          17 :         if (nl_lladdr)
    8192          17 :                 nl_addr_put(nl_lladdr);
    8193          17 :         if (nl_ipaddr)
    8194          17 :                 nl_addr_put(nl_ipaddr);
    8195          17 :         if (rn)
    8196          17 :                 rtnl_neigh_put(rn);
    8197          17 :         return res;
    8198             : #else /* CONFIG_LIBNL3_ROUTE */
    8199           0 :         return -1;
    8200             : #endif /* CONFIG_LIBNL3_ROUTE */
    8201             : }
    8202             : 
    8203             : 
    8204          28 : static int wpa_driver_br_delete_ip_neigh(void *priv, u8 version,
    8205             :                                          const u8 *ipaddr)
    8206             : {
    8207             : #ifdef CONFIG_LIBNL3_ROUTE
    8208          28 :         struct i802_bss *bss = priv;
    8209          28 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    8210             :         struct rtnl_neigh *rn;
    8211             :         struct nl_addr *nl_ipaddr;
    8212             :         int family, addrsize;
    8213             :         int res;
    8214             : 
    8215          28 :         if (!ipaddr)
    8216           0 :                 return -EINVAL;
    8217             : 
    8218          28 :         if (version == 4) {
    8219           6 :                 family = AF_INET;
    8220           6 :                 addrsize = 4;
    8221          22 :         } else if (version == 6) {
    8222          22 :                 family = AF_INET6;
    8223          22 :                 addrsize = 16;
    8224             :         } else {
    8225           0 :                 return -EINVAL;
    8226             :         }
    8227             : 
    8228          28 :         if (bss->br_ifindex == 0) {
    8229           0 :                 wpa_printf(MSG_DEBUG,
    8230             :                            "nl80211: bridge must be set to delete an ip neigh");
    8231           0 :                 return -1;
    8232             :         }
    8233             : 
    8234          28 :         if (!drv->rtnl_sk) {
    8235           0 :                 wpa_printf(MSG_DEBUG,
    8236             :                            "nl80211: nl_sock for NETLINK_ROUTE is not initialized");
    8237           0 :                 return -1;
    8238             :         }
    8239             : 
    8240          28 :         rn = rtnl_neigh_alloc();
    8241          28 :         if (rn == NULL)
    8242           0 :                 return -ENOMEM;
    8243             : 
    8244             :         /* set the destination ip address for neigh */
    8245          28 :         nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
    8246          28 :         if (nl_ipaddr == NULL) {
    8247           0 :                 wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
    8248           0 :                 res = -ENOMEM;
    8249           0 :                 goto errout;
    8250             :         }
    8251          28 :         res = rtnl_neigh_set_dst(rn, nl_ipaddr);
    8252          28 :         if (res) {
    8253           0 :                 wpa_printf(MSG_DEBUG,
    8254             :                            "nl80211: neigh set destination addr failed");
    8255           0 :                 goto errout;
    8256             :         }
    8257             : 
    8258          28 :         rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
    8259             : 
    8260          28 :         res = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
    8261          28 :         if (res) {
    8262          11 :                 wpa_printf(MSG_DEBUG,
    8263             :                            "nl80211: Deleting bridge ip neigh failed: %s",
    8264          11 :                            strerror(errno));
    8265             :         }
    8266             : errout:
    8267          28 :         if (nl_ipaddr)
    8268          28 :                 nl_addr_put(nl_ipaddr);
    8269          28 :         if (rn)
    8270          28 :                 rtnl_neigh_put(rn);
    8271          28 :         return res;
    8272             : #else /* CONFIG_LIBNL3_ROUTE */
    8273           0 :         return -1;
    8274             : #endif /* CONFIG_LIBNL3_ROUTE */
    8275             : }
    8276             : 
    8277             : 
    8278        2988 : static int linux_write_system_file(const char *path, unsigned int val)
    8279             : {
    8280             :         char buf[50];
    8281             :         int fd, len;
    8282             : 
    8283        2988 :         len = os_snprintf(buf, sizeof(buf), "%u\n", val);
    8284        2988 :         if (os_snprintf_error(sizeof(buf), len))
    8285           0 :                 return -1;
    8286             : 
    8287        2988 :         fd = open(path, O_WRONLY);
    8288        2988 :         if (fd < 0)
    8289        2970 :                 return -1;
    8290             : 
    8291          18 :         if (write(fd, buf, len) < 0) {
    8292           0 :                 wpa_printf(MSG_DEBUG,
    8293             :                            "nl80211: Failed to write Linux system file: %s with the value of %d",
    8294             :                            path, val);
    8295           0 :                 close(fd);
    8296           0 :                 return -1;
    8297             :         }
    8298          18 :         close(fd);
    8299             : 
    8300          18 :         return 0;
    8301             : }
    8302             : 
    8303             : 
    8304        1992 : static const char * drv_br_port_attr_str(enum drv_br_port_attr attr)
    8305             : {
    8306        1992 :         switch (attr) {
    8307             :         case DRV_BR_PORT_ATTR_PROXYARP:
    8308         996 :                 return "proxyarp_wifi";
    8309             :         case DRV_BR_PORT_ATTR_HAIRPIN_MODE:
    8310         996 :                 return "hairpin_mode";
    8311             :         }
    8312             : 
    8313           0 :         return NULL;
    8314             : }
    8315             : 
    8316             : 
    8317        1992 : static int wpa_driver_br_port_set_attr(void *priv, enum drv_br_port_attr attr,
    8318             :                                        unsigned int val)
    8319             : {
    8320        1992 :         struct i802_bss *bss = priv;
    8321             :         char path[128];
    8322             :         const char *attr_txt;
    8323             : 
    8324        1992 :         attr_txt = drv_br_port_attr_str(attr);
    8325        1992 :         if (attr_txt == NULL)
    8326           0 :                 return -EINVAL;
    8327             : 
    8328        1992 :         os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/%s",
    8329        1992 :                     bss->ifname, attr_txt);
    8330             : 
    8331        1992 :         if (linux_write_system_file(path, val))
    8332        1980 :                 return -1;
    8333             : 
    8334          12 :         return 0;
    8335             : }
    8336             : 
    8337             : 
    8338         996 : static const char * drv_br_net_param_str(enum drv_br_net_param param)
    8339             : {
    8340         996 :         switch (param) {
    8341             :         case DRV_BR_NET_PARAM_GARP_ACCEPT:
    8342         996 :                 return "arp_accept";
    8343             :         }
    8344             : 
    8345           0 :         return NULL;
    8346             : }
    8347             : 
    8348             : 
    8349         996 : static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
    8350             :                                        unsigned int val)
    8351             : {
    8352         996 :         struct i802_bss *bss = priv;
    8353             :         char path[128];
    8354             :         const char *param_txt;
    8355         996 :         int ip_version = 4;
    8356             : 
    8357         996 :         param_txt = drv_br_net_param_str(param);
    8358         996 :         if (param_txt == NULL)
    8359           0 :                 return -EINVAL;
    8360             : 
    8361         996 :         switch (param) {
    8362             :                 case DRV_BR_NET_PARAM_GARP_ACCEPT:
    8363         996 :                         ip_version = 4;
    8364         996 :                         break;
    8365             :                 default:
    8366           0 :                         return -EINVAL;
    8367             :         }
    8368             : 
    8369         996 :         os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s",
    8370         996 :                     ip_version, bss->brname, param_txt);
    8371             : 
    8372         996 :         if (linux_write_system_file(path, val))
    8373         990 :                 return -1;
    8374             : 
    8375           6 :         return 0;
    8376             : }
    8377             : 
    8378             : 
    8379           0 : static int hw_mode_to_qca_acs(enum hostapd_hw_mode hw_mode)
    8380             : {
    8381           0 :         switch (hw_mode) {
    8382             :         case HOSTAPD_MODE_IEEE80211B:
    8383           0 :                 return QCA_ACS_MODE_IEEE80211B;
    8384             :         case HOSTAPD_MODE_IEEE80211G:
    8385           0 :                 return QCA_ACS_MODE_IEEE80211G;
    8386             :         case HOSTAPD_MODE_IEEE80211A:
    8387           0 :                 return QCA_ACS_MODE_IEEE80211A;
    8388             :         case HOSTAPD_MODE_IEEE80211AD:
    8389           0 :                 return QCA_ACS_MODE_IEEE80211AD;
    8390             :         default:
    8391           0 :                 return -1;
    8392             :         }
    8393             : }
    8394             : 
    8395             : 
    8396           0 : static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
    8397             : {
    8398           0 :         struct i802_bss *bss = priv;
    8399           0 :         struct wpa_driver_nl80211_data *drv = bss->drv;
    8400             :         struct nl_msg *msg;
    8401             :         struct nlattr *data;
    8402             :         int ret;
    8403             :         int mode;
    8404             : 
    8405           0 :         mode = hw_mode_to_qca_acs(params->hw_mode);
    8406           0 :         if (mode < 0)
    8407           0 :                 return -1;
    8408             : 
    8409           0 :         if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
    8410           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
    8411           0 :             nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
    8412           0 :                         QCA_NL80211_VENDOR_SUBCMD_DO_ACS) ||
    8413           0 :             !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
    8414           0 :             nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE, mode) ||
    8415           0 :             (params->ht_enabled &&
    8416           0 :              nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED)) ||
    8417           0 :             (params->ht40_enabled &&
    8418           0 :              nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED))) {
    8419           0 :                 nlmsg_free(msg);
    8420           0 :                 return -ENOBUFS;
    8421             :         }
    8422           0 :         nla_nest_end(msg, data);
    8423             : 
    8424           0 :         ret = send_and_recv_msgs(drv, msg, NULL, NULL);
    8425           0 :         if (ret) {
    8426           0 :                 wpa_printf(MSG_DEBUG,
    8427             :                            "nl80211: Failed to invoke driver ACS function: %s",
    8428           0 :                            strerror(errno));
    8429             :         }
    8430           0 :         return ret;
    8431             : }
    8432             : 
    8433             : 
    8434             : const struct wpa_driver_ops wpa_driver_nl80211_ops = {
    8435             :         .name = "nl80211",
    8436             :         .desc = "Linux nl80211/cfg80211",
    8437             :         .get_bssid = wpa_driver_nl80211_get_bssid,
    8438             :         .get_ssid = wpa_driver_nl80211_get_ssid,
    8439             :         .set_key = driver_nl80211_set_key,
    8440             :         .scan2 = driver_nl80211_scan2,
    8441             :         .sched_scan = wpa_driver_nl80211_sched_scan,
    8442             :         .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
    8443             :         .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
    8444             :         .deauthenticate = driver_nl80211_deauthenticate,
    8445             :         .authenticate = driver_nl80211_authenticate,
    8446             :         .associate = wpa_driver_nl80211_associate,
    8447             :         .global_init = nl80211_global_init,
    8448             :         .global_deinit = nl80211_global_deinit,
    8449             :         .init2 = wpa_driver_nl80211_init,
    8450             :         .deinit = driver_nl80211_deinit,
    8451             :         .get_capa = wpa_driver_nl80211_get_capa,
    8452             :         .set_operstate = wpa_driver_nl80211_set_operstate,
    8453             :         .set_supp_port = wpa_driver_nl80211_set_supp_port,
    8454             :         .set_country = wpa_driver_nl80211_set_country,
    8455             :         .get_country = wpa_driver_nl80211_get_country,
    8456             :         .set_ap = wpa_driver_nl80211_set_ap,
    8457             :         .set_acl = wpa_driver_nl80211_set_acl,
    8458             :         .if_add = wpa_driver_nl80211_if_add,
    8459             :         .if_remove = driver_nl80211_if_remove,
    8460             :         .send_mlme = driver_nl80211_send_mlme,
    8461             :         .get_hw_feature_data = nl80211_get_hw_feature_data,
    8462             :         .sta_add = wpa_driver_nl80211_sta_add,
    8463             :         .sta_remove = driver_nl80211_sta_remove,
    8464             :         .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
    8465             :         .sta_set_flags = wpa_driver_nl80211_sta_set_flags,
    8466             :         .hapd_init = i802_init,
    8467             :         .hapd_deinit = i802_deinit,
    8468             :         .set_wds_sta = i802_set_wds_sta,
    8469             :         .get_seqnum = i802_get_seqnum,
    8470             :         .flush = i802_flush,
    8471             :         .get_inact_sec = i802_get_inact_sec,
    8472             :         .sta_clear_stats = i802_sta_clear_stats,
    8473             :         .set_rts = i802_set_rts,
    8474             :         .set_frag = i802_set_frag,
    8475             :         .set_tx_queue_params = i802_set_tx_queue_params,
    8476             :         .set_sta_vlan = driver_nl80211_set_sta_vlan,
    8477             :         .sta_deauth = i802_sta_deauth,
    8478             :         .sta_disassoc = i802_sta_disassoc,
    8479             :         .read_sta_data = driver_nl80211_read_sta_data,
    8480             :         .set_freq = i802_set_freq,
    8481             :         .send_action = driver_nl80211_send_action,
    8482             :         .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
    8483             :         .remain_on_channel = wpa_driver_nl80211_remain_on_channel,
    8484             :         .cancel_remain_on_channel =
    8485             :         wpa_driver_nl80211_cancel_remain_on_channel,
    8486             :         .probe_req_report = driver_nl80211_probe_req_report,
    8487             :         .deinit_ap = wpa_driver_nl80211_deinit_ap,
    8488             :         .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
    8489             :         .resume = wpa_driver_nl80211_resume,
    8490             :         .signal_monitor = nl80211_signal_monitor,
    8491             :         .signal_poll = nl80211_signal_poll,
    8492             :         .send_frame = nl80211_send_frame,
    8493             :         .shared_freq = wpa_driver_nl80211_shared_freq,
    8494             :         .set_param = nl80211_set_param,
    8495             :         .get_radio_name = nl80211_get_radio_name,
    8496             :         .add_pmkid = nl80211_add_pmkid,
    8497             :         .remove_pmkid = nl80211_remove_pmkid,
    8498             :         .flush_pmkid = nl80211_flush_pmkid,
    8499             :         .set_rekey_info = nl80211_set_rekey_info,
    8500             :         .poll_client = nl80211_poll_client,
    8501             :         .set_p2p_powersave = nl80211_set_p2p_powersave,
    8502             :         .start_dfs_cac = nl80211_start_radar_detection,
    8503             :         .stop_ap = wpa_driver_nl80211_stop_ap,
    8504             : #ifdef CONFIG_TDLS
    8505             :         .send_tdls_mgmt = nl80211_send_tdls_mgmt,
    8506             :         .tdls_oper = nl80211_tdls_oper,
    8507             :         .tdls_enable_channel_switch = nl80211_tdls_enable_channel_switch,
    8508             :         .tdls_disable_channel_switch = nl80211_tdls_disable_channel_switch,
    8509             : #endif /* CONFIG_TDLS */
    8510             :         .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
    8511             :         .get_mac_addr = wpa_driver_nl80211_get_macaddr,
    8512             :         .get_survey = wpa_driver_nl80211_get_survey,
    8513             :         .status = wpa_driver_nl80211_status,
    8514             :         .switch_channel = nl80211_switch_channel,
    8515             : #ifdef ANDROID_P2P
    8516             :         .set_noa = wpa_driver_set_p2p_noa,
    8517             :         .get_noa = wpa_driver_get_p2p_noa,
    8518             :         .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
    8519             : #endif /* ANDROID_P2P */
    8520             : #ifdef ANDROID
    8521             :         .driver_cmd = wpa_driver_nl80211_driver_cmd,
    8522             : #endif /* ANDROID */
    8523             :         .vendor_cmd = nl80211_vendor_cmd,
    8524             :         .set_qos_map = nl80211_set_qos_map,
    8525             :         .set_wowlan = nl80211_set_wowlan,
    8526             :         .roaming = nl80211_roaming,
    8527             :         .set_mac_addr = nl80211_set_mac_addr,
    8528             : #ifdef CONFIG_MESH
    8529             :         .init_mesh = wpa_driver_nl80211_init_mesh,
    8530             :         .join_mesh = wpa_driver_nl80211_join_mesh,
    8531             :         .leave_mesh = wpa_driver_nl80211_leave_mesh,
    8532             : #endif /* CONFIG_MESH */
    8533             :         .br_add_ip_neigh = wpa_driver_br_add_ip_neigh,
    8534             :         .br_delete_ip_neigh = wpa_driver_br_delete_ip_neigh,
    8535             :         .br_port_set_attr = wpa_driver_br_port_set_attr,
    8536             :         .br_set_net_param = wpa_driver_br_set_net_param,
    8537             :         .add_tx_ts = nl80211_add_ts,
    8538             :         .del_tx_ts = nl80211_del_ts,
    8539             :         .do_acs = wpa_driver_do_acs,
    8540             : };

Generated by: LCOV version 1.10