blob: 260ec4a64427276ae9bb03500c1386ad33e41614 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Driver interaction with Linux nl80211/cfg80211
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003 * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 * 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 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009 * This software may be distributed under the terms of the BSD license.
10 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011 */
12
13#include "includes.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#include <sys/types.h>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070015#include <fcntl.h>
16#include <net/if.h>
17#include <netlink/genl/genl.h>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018#include <netlink/genl/ctrl.h>
Dmitry Shmidt661b4f72014-09-29 14:58:27 -070019#ifdef CONFIG_LIBNL3_ROUTE
20#include <netlink/route/neighbour.h>
21#endif /* CONFIG_LIBNL3_ROUTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include <linux/rtnetlink.h>
23#include <netpacket/packet.h>
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080024#include <linux/errqueue.h>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025
26#include "common.h"
27#include "eloop.h"
Dmitry Shmidtcf32e602014-01-28 10:57:39 -080028#include "common/qca-vendor.h"
Dmitry Shmidt7832adb2014-04-29 10:53:02 -070029#include "common/qca-vendor-attr.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "common/ieee802_11_defs.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080031#include "common/ieee802_11_common.h"
Paul Stewart092955c2017-02-06 09:13:09 -080032#include "common/wpa_common.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080033#include "l2_packet/l2_packet.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034#include "netlink.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080035#include "linux_defines.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070036#include "linux_ioctl.h"
37#include "radiotap.h"
38#include "radiotap_iter.h"
39#include "rfkill.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080040#include "driver_nl80211.h"
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080041
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080042
Hai Shalom0f8669c2019-02-26 16:17:45 -080043#ifndef NETLINK_CAP_ACK
44#define NETLINK_CAP_ACK 10
45#endif /* NETLINK_CAP_ACK */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080046#ifndef CONFIG_LIBNL20
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070047/*
48 * libnl 1.1 has a bug, it tries to allocate socket numbers densely
49 * but when you free a socket again it will mess up its bitmap and
50 * and use the wrong number the next time it needs a socket ID.
51 * Therefore, we wrap the handle alloc/destroy and add our own pid
52 * accounting.
53 */
54static uint32_t port_bitmap[32] = { 0 };
55
56static struct nl_handle *nl80211_handle_alloc(void *cb)
57{
58 struct nl_handle *handle;
59 uint32_t pid = getpid() & 0x3FFFFF;
60 int i;
61
62 handle = nl_handle_alloc_cb(cb);
63
64 for (i = 0; i < 1024; i++) {
65 if (port_bitmap[i / 32] & (1 << (i % 32)))
66 continue;
67 port_bitmap[i / 32] |= 1 << (i % 32);
68 pid += i << 22;
69 break;
70 }
71
72 nl_socket_set_local_port(handle, pid);
73
74 return handle;
75}
76
77static void nl80211_handle_destroy(struct nl_handle *handle)
78{
79 uint32_t port = nl_socket_get_local_port(handle);
80
81 port >>= 22;
82 port_bitmap[port / 32] &= ~(1 << (port % 32));
83
84 nl_handle_destroy(handle);
85}
86#endif /* CONFIG_LIBNL20 */
87
88
Dmitry Shmidt54605472013-11-08 11:10:19 -080089#ifdef ANDROID
90/* system/core/libnl_2 does not include nl_socket_set_nonblocking() */
Dmitry Shmidt54605472013-11-08 11:10:19 -080091#undef nl_socket_set_nonblocking
92#define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080093
Dmitry Shmidt54605472013-11-08 11:10:19 -080094#endif /* ANDROID */
95
96
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080097static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
98{
99 struct nl_handle *handle;
100
101 handle = nl80211_handle_alloc(cb);
102 if (handle == NULL) {
103 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
104 "callbacks (%s)", dbg);
105 return NULL;
106 }
107
108 if (genl_connect(handle)) {
109 wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
110 "netlink (%s)", dbg);
111 nl80211_handle_destroy(handle);
112 return NULL;
113 }
114
115 return handle;
116}
117
118
119static void nl_destroy_handles(struct nl_handle **handle)
120{
121 if (*handle == NULL)
122 return;
123 nl80211_handle_destroy(*handle);
124 *handle = NULL;
125}
126
127
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700128#if __WORDSIZE == 64
129#define ELOOP_SOCKET_INVALID (intptr_t) 0x8888888888888889ULL
130#else
131#define ELOOP_SOCKET_INVALID (intptr_t) 0x88888889ULL
132#endif
133
134static void nl80211_register_eloop_read(struct nl_handle **handle,
135 eloop_sock_handler handler,
136 void *eloop_data)
137{
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800138#ifdef CONFIG_LIBNL20
139 /*
140 * libnl uses a pretty small buffer (32 kB that gets converted to 64 kB)
141 * by default. It is possible to hit that limit in some cases where
142 * operations are blocked, e.g., with a burst of Deauthentication frames
143 * to hostapd and STA entry deletion. Try to increase the buffer to make
144 * this less likely to occur.
145 */
146 if (nl_socket_set_buffer_size(*handle, 262144, 0) < 0) {
147 wpa_printf(MSG_DEBUG,
148 "nl80211: Could not set nl_socket RX buffer size: %s",
149 strerror(errno));
150 /* continue anyway with the default (smaller) buffer */
151 }
152#endif /* CONFIG_LIBNL20 */
153
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700154 nl_socket_set_nonblocking(*handle);
155 eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
156 eloop_data, *handle);
157 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
158}
159
160
161static void nl80211_destroy_eloop_handle(struct nl_handle **handle)
162{
163 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
164 eloop_unregister_read_sock(nl_socket_get_fd(*handle));
165 nl_destroy_handles(handle);
166}
167
168
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800169static void nl80211_global_deinit(void *priv);
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800170static void nl80211_check_global(struct nl80211_global *global);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800171
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800172static void wpa_driver_nl80211_deinit(struct i802_bss *bss);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700173static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
174 struct hostapd_freq_params *freq);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700176static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800177wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800178 const u8 *set_addr, int first,
179 const char *driver_params);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800180static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700181 unsigned int freq, unsigned int wait,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800182 const u8 *buf, size_t buf_len, u64 *cookie,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800183 int no_cck, int no_ack, int offchanok,
184 const u16 *csa_offs, size_t csa_offs_len);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800185static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
186 int report);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700187
Dmitry Shmidt9c175262016-03-03 10:20:07 -0800188#define IFIDX_ANY -1
189
190static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
191 int ifidx_reason);
192static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
193 int ifidx_reason);
194static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
195 int ifidx_reason);
Dmitry Shmidt738a26e2011-07-07 14:22:14 -0700196
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700197static int nl80211_set_channel(struct i802_bss *bss,
198 struct hostapd_freq_params *freq, int set_chan);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700199static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
200 int ifindex, int disabled);
201
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800202static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
203 int reset_mode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800204
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -0700205static int i802_set_iface_flags(struct i802_bss *bss, int up);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800206static int nl80211_set_param(void *priv, const char *param);
Dmitry Shmidtd13095b2016-08-22 14:02:19 -0700207#ifdef CONFIG_MESH
208static int nl80211_put_mesh_config(struct nl_msg *msg,
209 struct wpa_driver_mesh_bss_params *params);
210#endif /* CONFIG_MESH */
Dmitry Shmidt29333592017-01-09 12:27:11 -0800211static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
212 int reason);
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700213
214
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800215/* Converts nl80211_chan_width to a common format */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800216enum chan_width convert2width(int width)
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800217{
218 switch (width) {
219 case NL80211_CHAN_WIDTH_20_NOHT:
220 return CHAN_WIDTH_20_NOHT;
221 case NL80211_CHAN_WIDTH_20:
222 return CHAN_WIDTH_20;
223 case NL80211_CHAN_WIDTH_40:
224 return CHAN_WIDTH_40;
225 case NL80211_CHAN_WIDTH_80:
226 return CHAN_WIDTH_80;
227 case NL80211_CHAN_WIDTH_80P80:
228 return CHAN_WIDTH_80P80;
229 case NL80211_CHAN_WIDTH_160:
230 return CHAN_WIDTH_160;
231 }
232 return CHAN_WIDTH_UNKNOWN;
233}
234
235
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800236int is_ap_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800237{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700238 return nlmode == NL80211_IFTYPE_AP ||
239 nlmode == NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800240}
241
242
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800243int is_sta_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800244{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700245 return nlmode == NL80211_IFTYPE_STATION ||
246 nlmode == NL80211_IFTYPE_P2P_CLIENT;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800247}
248
249
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700250static int is_p2p_net_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800251{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700252 return nlmode == NL80211_IFTYPE_P2P_CLIENT ||
253 nlmode == NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800254}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700255
256
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800257struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv,
258 int ifindex)
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700259{
260 struct i802_bss *bss;
261
262 for (bss = drv->first_bss; bss; bss = bss->next) {
263 if (bss->ifindex == ifindex)
264 return bss;
265 }
266
267 return NULL;
268}
269
270
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800271static int is_mesh_interface(enum nl80211_iftype nlmode)
272{
273 return nlmode == NL80211_IFTYPE_MESH_POINT;
274}
275
276
277void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700278{
279 if (drv->associated)
280 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
281 drv->associated = 0;
282 os_memset(drv->bssid, 0, ETH_ALEN);
283}
284
285
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700286/* nl80211 code */
287static int ack_handler(struct nl_msg *msg, void *arg)
288{
289 int *err = arg;
290 *err = 0;
291 return NL_STOP;
292}
293
294static int finish_handler(struct nl_msg *msg, void *arg)
295{
296 int *ret = arg;
297 *ret = 0;
298 return NL_SKIP;
299}
300
301static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
302 void *arg)
303{
304 int *ret = arg;
305 *ret = err->error;
306 return NL_SKIP;
307}
308
309
310static int no_seq_check(struct nl_msg *msg, void *arg)
311{
312 return NL_OK;
313}
314
315
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800316static void nl80211_nlmsg_clear(struct nl_msg *msg)
317{
318 /*
319 * Clear nlmsg data, e.g., to make sure key material is not left in
320 * heap memory for unnecessarily long time.
321 */
322 if (msg) {
323 struct nlmsghdr *hdr = nlmsg_hdr(msg);
324 void *data = nlmsg_data(hdr);
325 /*
326 * This would use nlmsg_datalen() or the older nlmsg_len() if
327 * only libnl were to maintain a stable API.. Neither will work
328 * with all released versions, so just calculate the length
329 * here.
330 */
331 int len = hdr->nlmsg_len - NLMSG_HDRLEN;
332
333 os_memset(data, 0, len);
334 }
335}
336
337
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800338static int send_and_recv(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700339 struct nl_handle *nl_handle, struct nl_msg *msg,
340 int (*valid_handler)(struct nl_msg *, void *),
341 void *valid_data)
342{
343 struct nl_cb *cb;
344 int err = -ENOMEM;
Hai Shalom0f8669c2019-02-26 16:17:45 -0800345 int opt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700346
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800347 if (!msg)
348 return -ENOMEM;
349
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800350 cb = nl_cb_clone(global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700351 if (!cb)
352 goto out;
353
Hai Shalom0f8669c2019-02-26 16:17:45 -0800354 /* try to set NETLINK_CAP_ACK to 1, ignoring errors */
355 opt = 1;
356 setsockopt(nl_socket_get_fd(nl_handle), SOL_NETLINK,
357 NETLINK_CAP_ACK, &opt, sizeof(opt));
358
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700359 err = nl_send_auto_complete(nl_handle, msg);
360 if (err < 0)
361 goto out;
362
363 err = 1;
364
365 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
366 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
367 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
368
369 if (valid_handler)
370 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
371 valid_handler, valid_data);
372
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700373 while (err > 0) {
374 int res = nl_recvmsgs(nl_handle, cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -0700375 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700376 wpa_printf(MSG_INFO,
377 "nl80211: %s->nl_recvmsgs failed: %d",
378 __func__, res);
379 }
380 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700381 out:
382 nl_cb_put(cb);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800383 if (!valid_handler && valid_data == (void *) -1)
384 nl80211_nlmsg_clear(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700385 nlmsg_free(msg);
386 return err;
387}
388
389
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800390int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
391 struct nl_msg *msg,
392 int (*valid_handler)(struct nl_msg *, void *),
393 void *valid_data)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700394{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800395 return send_and_recv(drv->global, drv->global->nl, msg,
396 valid_handler, valid_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700397}
398
399
400struct family_data {
401 const char *group;
402 int id;
403};
404
405
406static int family_handler(struct nl_msg *msg, void *arg)
407{
408 struct family_data *res = arg;
409 struct nlattr *tb[CTRL_ATTR_MAX + 1];
410 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
411 struct nlattr *mcgrp;
412 int i;
413
414 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
415 genlmsg_attrlen(gnlh, 0), NULL);
416 if (!tb[CTRL_ATTR_MCAST_GROUPS])
417 return NL_SKIP;
418
419 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
420 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
421 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
422 nla_len(mcgrp), NULL);
423 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
424 !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
425 os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
426 res->group,
427 nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
428 continue;
429 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
430 break;
431 };
432
433 return NL_SKIP;
434}
435
436
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800437static int nl_get_multicast_id(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700438 const char *family, const char *group)
439{
440 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800441 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 struct family_data res = { group, -ENOENT };
443
444 msg = nlmsg_alloc();
445 if (!msg)
446 return -ENOMEM;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800447 if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
448 0, 0, CTRL_CMD_GETFAMILY, 0) ||
449 nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
450 nlmsg_free(msg);
451 return -1;
452 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700453
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800454 ret = send_and_recv(global, global->nl, msg, family_handler, &res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700455 if (ret == 0)
456 ret = res.id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457 return ret;
458}
459
460
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800461void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
462 struct nl_msg *msg, int flags, uint8_t cmd)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800463{
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700464 if (TEST_FAIL())
465 return NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800466 return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
467 0, flags, cmd, 0);
468}
469
470
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800471static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss)
472{
473 if (bss->wdev_id_set)
474 return nla_put_u64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
475 return nla_put_u32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
476}
477
478
479struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
480{
481 struct nl_msg *msg;
482
483 msg = nlmsg_alloc();
484 if (!msg)
485 return NULL;
486
487 if (!nl80211_cmd(bss->drv, msg, flags, cmd) ||
488 nl80211_set_iface_id(msg, bss) < 0) {
489 nlmsg_free(msg);
490 return NULL;
491 }
492
493 return msg;
494}
495
496
497static struct nl_msg *
498nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
499 int flags, uint8_t cmd)
500{
501 struct nl_msg *msg;
502
503 msg = nlmsg_alloc();
504 if (!msg)
505 return NULL;
506
507 if (!nl80211_cmd(drv, msg, flags, cmd) ||
508 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
509 nlmsg_free(msg);
510 return NULL;
511 }
512
513 return msg;
514}
515
516
517struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
518 uint8_t cmd)
519{
520 return nl80211_ifindex_msg(drv, drv->ifindex, flags, cmd);
521}
522
523
524struct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd)
525{
526 return nl80211_ifindex_msg(bss->drv, bss->ifindex, flags, cmd);
527}
528
529
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800530struct wiphy_idx_data {
531 int wiphy_idx;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700532 enum nl80211_iftype nlmode;
533 u8 *macaddr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800534};
535
536
537static int netdev_info_handler(struct nl_msg *msg, void *arg)
538{
539 struct nlattr *tb[NL80211_ATTR_MAX + 1];
540 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
541 struct wiphy_idx_data *info = arg;
542
543 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
544 genlmsg_attrlen(gnlh, 0), NULL);
545
546 if (tb[NL80211_ATTR_WIPHY])
547 info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
548
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700549 if (tb[NL80211_ATTR_IFTYPE])
550 info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
551
552 if (tb[NL80211_ATTR_MAC] && info->macaddr)
553 os_memcpy(info->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
554 ETH_ALEN);
555
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800556 return NL_SKIP;
557}
558
559
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800560int nl80211_get_wiphy_index(struct i802_bss *bss)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800561{
562 struct nl_msg *msg;
563 struct wiphy_idx_data data = {
564 .wiphy_idx = -1,
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700565 .macaddr = NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800566 };
567
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800568 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
569 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800570
571 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
572 return data.wiphy_idx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800573 return -1;
574}
575
576
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700577static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
578{
579 struct nl_msg *msg;
580 struct wiphy_idx_data data = {
581 .nlmode = NL80211_IFTYPE_UNSPECIFIED,
582 .macaddr = NULL,
583 };
584
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800585 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
586 return NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700587
588 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
589 return data.nlmode;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700590 return NL80211_IFTYPE_UNSPECIFIED;
591}
592
593
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700594static int nl80211_get_macaddr(struct i802_bss *bss)
595{
596 struct nl_msg *msg;
597 struct wiphy_idx_data data = {
598 .macaddr = bss->addr,
599 };
600
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800601 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
602 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700603
604 return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data);
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700605}
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700606
607
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800608static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
609 struct nl80211_wiphy_data *w)
610{
611 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800612 int ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800613
614 msg = nlmsg_alloc();
615 if (!msg)
616 return -1;
617
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800618 if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS) ||
619 nla_put_u32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx)) {
620 nlmsg_free(msg);
621 return -1;
622 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800623
624 ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800625 if (ret) {
626 wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
627 "failed: ret=%d (%s)",
628 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800629 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800630 return ret;
631}
632
633
634static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle)
635{
636 struct nl80211_wiphy_data *w = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700637 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800638
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800639 wpa_printf(MSG_EXCESSIVE, "nl80211: Beacon event message available");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800640
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700641 res = nl_recvmsgs(handle, w->nl_cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -0700642 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700643 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
644 __func__, res);
645 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800646}
647
648
649static int process_beacon_event(struct nl_msg *msg, void *arg)
650{
651 struct nl80211_wiphy_data *w = arg;
652 struct wpa_driver_nl80211_data *drv;
653 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
654 struct nlattr *tb[NL80211_ATTR_MAX + 1];
655 union wpa_event_data event;
656
657 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
658 genlmsg_attrlen(gnlh, 0), NULL);
659
660 if (gnlh->cmd != NL80211_CMD_FRAME) {
661 wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)",
662 gnlh->cmd);
663 return NL_SKIP;
664 }
665
666 if (!tb[NL80211_ATTR_FRAME])
667 return NL_SKIP;
668
669 dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data,
670 wiphy_list) {
671 os_memset(&event, 0, sizeof(event));
672 event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);
673 event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);
674 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
675 }
676
677 return NL_SKIP;
678}
679
680
681static struct nl80211_wiphy_data *
682nl80211_get_wiphy_data_ap(struct i802_bss *bss)
683{
684 static DEFINE_DL_LIST(nl80211_wiphys);
685 struct nl80211_wiphy_data *w;
686 int wiphy_idx, found = 0;
687 struct i802_bss *tmp_bss;
Paul Stewart092955c2017-02-06 09:13:09 -0800688 u8 channel;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800689
690 if (bss->wiphy_data != NULL)
691 return bss->wiphy_data;
692
693 wiphy_idx = nl80211_get_wiphy_index(bss);
694
695 dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) {
696 if (w->wiphy_idx == wiphy_idx)
697 goto add;
698 }
699
700 /* alloc new one */
701 w = os_zalloc(sizeof(*w));
702 if (w == NULL)
703 return NULL;
704 w->wiphy_idx = wiphy_idx;
705 dl_list_init(&w->bsss);
706 dl_list_init(&w->drvs);
707
Paul Stewart092955c2017-02-06 09:13:09 -0800708 /* Beacon frames not supported in IEEE 802.11ad */
709 if (ieee80211_freq_to_chan(bss->freq, &channel) !=
710 HOSTAPD_MODE_IEEE80211AD) {
711 w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
712 if (!w->nl_cb) {
713 os_free(w);
714 return NULL;
715 }
716 nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
717 no_seq_check, NULL);
718 nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
719 process_beacon_event, w);
Rebecca Silberstein055a67c2017-02-01 23:05:56 +0000720
Paul Stewart092955c2017-02-06 09:13:09 -0800721 w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
722 "wiphy beacons");
723 if (w->nl_beacons == NULL) {
724 os_free(w);
725 return NULL;
726 }
Rebecca Silberstein055a67c2017-02-01 23:05:56 +0000727
Paul Stewart092955c2017-02-06 09:13:09 -0800728 if (nl80211_register_beacons(bss->drv, w)) {
729 nl_destroy_handles(&w->nl_beacons);
730 os_free(w);
731 return NULL;
732 }
Rebecca Silberstein055a67c2017-02-01 23:05:56 +0000733
Paul Stewart092955c2017-02-06 09:13:09 -0800734 nl80211_register_eloop_read(&w->nl_beacons,
735 nl80211_recv_beacons, w);
736 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800737
738 dl_list_add(&nl80211_wiphys, &w->list);
739
740add:
741 /* drv entry for this bss already there? */
742 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
743 if (tmp_bss->drv == bss->drv) {
744 found = 1;
745 break;
746 }
747 }
748 /* if not add it */
749 if (!found)
750 dl_list_add(&w->drvs, &bss->drv->wiphy_list);
751
752 dl_list_add(&w->bsss, &bss->wiphy_list);
753 bss->wiphy_data = w;
754 return w;
755}
756
757
758static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
759{
760 struct nl80211_wiphy_data *w = bss->wiphy_data;
761 struct i802_bss *tmp_bss;
762 int found = 0;
763
764 if (w == NULL)
765 return;
766 bss->wiphy_data = NULL;
767 dl_list_del(&bss->wiphy_list);
768
769 /* still any for this drv present? */
770 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
771 if (tmp_bss->drv == bss->drv) {
772 found = 1;
773 break;
774 }
775 }
776 /* if not remove it */
777 if (!found)
778 dl_list_del(&bss->drv->wiphy_list);
779
780 if (!dl_list_empty(&w->bsss))
781 return;
782
Paul Stewart092955c2017-02-06 09:13:09 -0800783 if (w->nl_beacons)
784 nl80211_destroy_eloop_handle(&w->nl_beacons);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800785
786 nl_cb_put(w->nl_cb);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800787 dl_list_del(&w->list);
788 os_free(w);
789}
790
791
Dmitry Shmidte4663042016-04-04 10:07:49 -0700792static unsigned int nl80211_get_ifindex(void *priv)
793{
794 struct i802_bss *bss = priv;
795 struct wpa_driver_nl80211_data *drv = bss->drv;
796
797 return drv->ifindex;
798}
799
800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
802{
803 struct i802_bss *bss = priv;
804 struct wpa_driver_nl80211_data *drv = bss->drv;
805 if (!drv->associated)
806 return -1;
807 os_memcpy(bssid, drv->bssid, ETH_ALEN);
808 return 0;
809}
810
811
812static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
813{
814 struct i802_bss *bss = priv;
815 struct wpa_driver_nl80211_data *drv = bss->drv;
816 if (!drv->associated)
817 return -1;
818 os_memcpy(ssid, drv->ssid, drv->ssid_len);
819 return drv->ssid_len;
820}
821
822
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800823static void wpa_driver_nl80211_event_newlink(
Dmitry Shmidte4663042016-04-04 10:07:49 -0700824 struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
825 int ifindex, const char *ifname)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700826{
827 union wpa_event_data event;
828
Dmitry Shmidte4663042016-04-04 10:07:49 -0700829 if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800830 if (if_nametoindex(drv->first_bss->ifname) == 0) {
831 wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
832 drv->first_bss->ifname);
833 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700834 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800835 if (!drv->if_removed)
836 return;
837 wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event",
838 drv->first_bss->ifname);
839 drv->if_removed = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700840 }
841
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800842 os_memset(&event, 0, sizeof(event));
Dmitry Shmidte4663042016-04-04 10:07:49 -0700843 event.interface_status.ifindex = ifindex;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800844 os_strlcpy(event.interface_status.ifname, ifname,
845 sizeof(event.interface_status.ifname));
846 event.interface_status.ievent = EVENT_INTERFACE_ADDED;
Dmitry Shmidte4663042016-04-04 10:07:49 -0700847 if (drv)
848 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
849 else
850 wpa_supplicant_event_global(global->ctx, EVENT_INTERFACE_STATUS,
851 &event);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800852}
853
854
855static void wpa_driver_nl80211_event_dellink(
Dmitry Shmidte4663042016-04-04 10:07:49 -0700856 struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
857 int ifindex, const char *ifname)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800858{
859 union wpa_event_data event;
860
Dmitry Shmidte4663042016-04-04 10:07:49 -0700861 if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800862 if (drv->if_removed) {
863 wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
864 ifname);
865 return;
866 }
867 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1",
868 ifname);
869 drv->if_removed = 1;
870 } else {
871 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed",
872 ifname);
873 }
874
875 os_memset(&event, 0, sizeof(event));
Dmitry Shmidte4663042016-04-04 10:07:49 -0700876 event.interface_status.ifindex = ifindex;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800877 os_strlcpy(event.interface_status.ifname, ifname,
878 sizeof(event.interface_status.ifname));
879 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
Dmitry Shmidte4663042016-04-04 10:07:49 -0700880 if (drv)
881 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
882 else
883 wpa_supplicant_event_global(global->ctx, EVENT_INTERFACE_STATUS,
884 &event);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885}
886
887
888static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
889 u8 *buf, size_t len)
890{
891 int attrlen, rta_len;
892 struct rtattr *attr;
893
894 attrlen = len;
895 attr = (struct rtattr *) buf;
896
897 rta_len = RTA_ALIGN(sizeof(struct rtattr));
898 while (RTA_OK(attr, attrlen)) {
899 if (attr->rta_type == IFLA_IFNAME) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800900 if (os_strcmp(((char *) attr) + rta_len,
901 drv->first_bss->ifname) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902 return 1;
903 else
904 break;
905 }
906 attr = RTA_NEXT(attr, attrlen);
907 }
908
909 return 0;
910}
911
912
913static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
914 int ifindex, u8 *buf, size_t len)
915{
916 if (drv->ifindex == ifindex)
917 return 1;
918
919 if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800920 nl80211_check_global(drv->global);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700921 wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
922 "interface");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700923 if (wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL) < 0)
924 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925 return 1;
926 }
927
928 return 0;
929}
930
931
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800932static struct wpa_driver_nl80211_data *
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700933nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len,
934 int *init_failed)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800935{
936 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700937 int res;
938
939 if (init_failed)
940 *init_failed = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800941 dl_list_for_each(drv, &global->interfaces,
942 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700943 res = wpa_driver_nl80211_own_ifindex(drv, idx, buf, len);
944 if (res < 0) {
945 wpa_printf(MSG_DEBUG,
946 "nl80211: Found matching own interface, but failed to complete reinitialization");
947 if (init_failed)
948 *init_failed = 1;
949 return drv;
950 }
951 if (res > 0 || have_ifidx(drv, idx, IFIDX_ANY))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800952 return drv;
953 }
954 return NULL;
955}
956
957
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700958static void nl80211_refresh_mac(struct wpa_driver_nl80211_data *drv,
959 int ifindex)
960{
961 struct i802_bss *bss;
962 u8 addr[ETH_ALEN];
963
964 bss = get_bss_ifindex(drv, ifindex);
965 if (bss &&
966 linux_get_ifhwaddr(drv->global->ioctl_sock,
967 bss->ifname, addr) < 0) {
968 wpa_printf(MSG_DEBUG,
969 "nl80211: %s: failed to re-read MAC address",
970 bss->ifname);
971 } else if (bss && os_memcmp(addr, bss->addr, ETH_ALEN) != 0) {
972 wpa_printf(MSG_DEBUG,
973 "nl80211: Own MAC address on ifindex %d (%s) changed from "
974 MACSTR " to " MACSTR,
975 ifindex, bss->ifname,
976 MAC2STR(bss->addr), MAC2STR(addr));
977 os_memcpy(bss->addr, addr, ETH_ALEN);
978 }
979}
980
981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700982static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
983 struct ifinfomsg *ifi,
984 u8 *buf, size_t len)
985{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800986 struct nl80211_global *global = ctx;
987 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800988 int attrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 struct rtattr *attr;
990 u32 brid = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800991 char namebuf[IFNAMSIZ];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800992 char ifname[IFNAMSIZ + 1];
993 char extra[100], *pos, *end;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700994 int init_failed;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700995
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800996 extra[0] = '\0';
997 pos = extra;
998 end = pos + sizeof(extra);
999 ifname[0] = '\0';
1000
1001 attrlen = len;
1002 attr = (struct rtattr *) buf;
1003 while (RTA_OK(attr, attrlen)) {
1004 switch (attr->rta_type) {
1005 case IFLA_IFNAME:
1006 if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
1007 break;
1008 os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
1009 ifname[RTA_PAYLOAD(attr)] = '\0';
1010 break;
1011 case IFLA_MASTER:
1012 brid = nla_get_u32((struct nlattr *) attr);
1013 pos += os_snprintf(pos, end - pos, " master=%u", brid);
1014 break;
1015 case IFLA_WIRELESS:
1016 pos += os_snprintf(pos, end - pos, " wext");
1017 break;
1018 case IFLA_OPERSTATE:
1019 pos += os_snprintf(pos, end - pos, " operstate=%u",
1020 nla_get_u32((struct nlattr *) attr));
1021 break;
1022 case IFLA_LINKMODE:
1023 pos += os_snprintf(pos, end - pos, " linkmode=%u",
1024 nla_get_u32((struct nlattr *) attr));
1025 break;
1026 }
1027 attr = RTA_NEXT(attr, attrlen);
1028 }
1029 extra[sizeof(extra) - 1] = '\0';
1030
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001031 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
1032 ifi->ifi_index, ifname, extra, ifi->ifi_family,
1033 ifi->ifi_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
1035 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
1036 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
1037 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
1038
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001039 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len, &init_failed);
Dmitry Shmidte4663042016-04-04 10:07:49 -07001040 if (!drv)
1041 goto event_newlink;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001042 if (init_failed)
1043 return; /* do not update interface state */
Dmitry Shmidte4663042016-04-04 10:07:49 -07001044
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045 if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001046 namebuf[0] = '\0';
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001047 if (if_indextoname(ifi->ifi_index, namebuf) &&
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001048 linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001049 /* Re-read MAC address as it may have changed */
1050 nl80211_refresh_mac(drv, ifi->ifi_index);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001051 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
1052 "event since interface %s is up", namebuf);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001053 drv->ignore_if_down_event = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001054 return;
1055 }
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001056 wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
1057 namebuf, ifname);
1058 if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
1059 wpa_printf(MSG_DEBUG,
1060 "nl80211: Not the main interface (%s) - do not indicate interface down",
1061 drv->first_bss->ifname);
1062 } else if (drv->ignore_if_down_event) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001063 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
1064 "event generated by mode change");
1065 drv->ignore_if_down_event = 0;
1066 } else {
1067 drv->if_disabled = 1;
1068 wpa_supplicant_event(drv->ctx,
1069 EVENT_INTERFACE_DISABLED, NULL);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08001070
1071 /*
1072 * Try to get drv again, since it may be removed as
1073 * part of the EVENT_INTERFACE_DISABLED handling for
1074 * dynamic interfaces
1075 */
1076 drv = nl80211_find_drv(global, ifi->ifi_index,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001077 buf, len, NULL);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08001078 if (!drv)
1079 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001080 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001081 }
1082
1083 if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001084 if (if_indextoname(ifi->ifi_index, namebuf) &&
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001085 linux_iface_up(drv->global->ioctl_sock, namebuf) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001086 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1087 "event since interface %s is down",
1088 namebuf);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001089 } else if (if_nametoindex(drv->first_bss->ifname) == 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001090 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1091 "event since interface %s does not exist",
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001092 drv->first_bss->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001093 } else if (drv->if_removed) {
1094 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1095 "event since interface %s is marked "
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001096 "removed", drv->first_bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001097 } else {
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001098 /* Re-read MAC address as it may have changed */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001099 nl80211_refresh_mac(drv, ifi->ifi_index);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001100
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001101 wpa_printf(MSG_DEBUG, "nl80211: Interface up");
1102 drv->if_disabled = 0;
1103 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
1104 NULL);
1105 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001106 }
1107
1108 /*
1109 * Some drivers send the association event before the operup event--in
1110 * this case, lifting operstate in wpa_driver_nl80211_set_operstate()
1111 * fails. This will hit us when wpa_supplicant does not need to do
1112 * IEEE 802.1X authentication
1113 */
1114 if (drv->operstate == 1 &&
1115 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001116 !(ifi->ifi_flags & IFF_RUNNING)) {
1117 wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001118 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119 -1, IF_OPER_UP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120 }
1121
Dmitry Shmidte4663042016-04-04 10:07:49 -07001122event_newlink:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001123 if (ifname[0])
Dmitry Shmidte4663042016-04-04 10:07:49 -07001124 wpa_driver_nl80211_event_newlink(global, drv, ifi->ifi_index,
1125 ifname);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001126
Dmitry Shmidte4663042016-04-04 10:07:49 -07001127 if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001128 struct i802_bss *bss;
1129
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130 /* device has been added to bridge */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001131 if (!if_indextoname(brid, namebuf)) {
1132 wpa_printf(MSG_DEBUG,
1133 "nl80211: Could not find bridge ifname for ifindex %u",
1134 brid);
1135 return;
1136 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001137 wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
1138 brid, namebuf);
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001139 add_ifidx(drv, brid, ifi->ifi_index);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001140
1141 for (bss = drv->first_bss; bss; bss = bss->next) {
1142 if (os_strcmp(ifname, bss->ifname) == 0) {
1143 os_strlcpy(bss->brname, namebuf, IFNAMSIZ);
1144 break;
1145 }
1146 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001147 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001148}
1149
1150
1151static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
1152 struct ifinfomsg *ifi,
1153 u8 *buf, size_t len)
1154{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001155 struct nl80211_global *global = ctx;
1156 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001157 int attrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001158 struct rtattr *attr;
1159 u32 brid = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001160 char ifname[IFNAMSIZ + 1];
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001161 char extra[100], *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001163 extra[0] = '\0';
1164 pos = extra;
1165 end = pos + sizeof(extra);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001166 ifname[0] = '\0';
1167
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001168 attrlen = len;
1169 attr = (struct rtattr *) buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170 while (RTA_OK(attr, attrlen)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001171 switch (attr->rta_type) {
1172 case IFLA_IFNAME:
1173 if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
1174 break;
1175 os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
1176 ifname[RTA_PAYLOAD(attr)] = '\0';
1177 break;
1178 case IFLA_MASTER:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001179 brid = nla_get_u32((struct nlattr *) attr);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001180 pos += os_snprintf(pos, end - pos, " master=%u", brid);
1181 break;
1182 case IFLA_OPERSTATE:
1183 pos += os_snprintf(pos, end - pos, " operstate=%u",
1184 nla_get_u32((struct nlattr *) attr));
1185 break;
1186 case IFLA_LINKMODE:
1187 pos += os_snprintf(pos, end - pos, " linkmode=%u",
1188 nla_get_u32((struct nlattr *) attr));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001189 break;
1190 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001191 attr = RTA_NEXT(attr, attrlen);
1192 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001193 extra[sizeof(extra) - 1] = '\0';
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001194
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001195 wpa_printf(MSG_DEBUG, "RTM_DELLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
1196 ifi->ifi_index, ifname, extra, ifi->ifi_family,
1197 ifi->ifi_flags,
1198 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
1199 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
1200 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
1201 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
1202
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001203 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001204
Dmitry Shmidte4663042016-04-04 10:07:49 -07001205 if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001206 /* device has been removed from bridge */
1207 char namebuf[IFNAMSIZ];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001208
1209 if (!if_indextoname(brid, namebuf)) {
1210 wpa_printf(MSG_DEBUG,
1211 "nl80211: Could not find bridge ifname for ifindex %u",
1212 brid);
1213 } else {
1214 wpa_printf(MSG_DEBUG,
1215 "nl80211: Remove ifindex %u for bridge %s",
1216 brid, namebuf);
1217 }
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001218 del_ifidx(drv, brid, ifi->ifi_index);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001219 }
Dmitry Shmidte4663042016-04-04 10:07:49 -07001220
1221 if (ifi->ifi_family != AF_BRIDGE || !brid)
1222 wpa_driver_nl80211_event_dellink(global, drv, ifi->ifi_index,
1223 ifname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001224}
1225
1226
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08001227struct nl80211_get_assoc_freq_arg {
1228 struct wpa_driver_nl80211_data *drv;
1229 unsigned int assoc_freq;
1230 unsigned int ibss_freq;
1231 u8 assoc_bssid[ETH_ALEN];
1232 u8 assoc_ssid[SSID_MAX_LEN];
1233 u8 assoc_ssid_len;
1234};
1235
1236static int nl80211_get_assoc_freq_handler(struct nl_msg *msg, void *arg)
1237{
1238 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1239 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1240 struct nlattr *bss[NL80211_BSS_MAX + 1];
1241 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
1242 [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
1243 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
1244 [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
1245 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
1246 };
1247 struct nl80211_get_assoc_freq_arg *ctx = arg;
1248 enum nl80211_bss_status status;
1249
1250 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1251 genlmsg_attrlen(gnlh, 0), NULL);
1252 if (!tb[NL80211_ATTR_BSS] ||
1253 nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
1254 bss_policy) ||
1255 !bss[NL80211_BSS_STATUS])
1256 return NL_SKIP;
1257
1258 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
1259 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
1260 bss[NL80211_BSS_FREQUENCY]) {
1261 ctx->assoc_freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
1262 wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
1263 ctx->assoc_freq);
1264 }
1265 if (status == NL80211_BSS_STATUS_IBSS_JOINED &&
1266 bss[NL80211_BSS_FREQUENCY]) {
1267 ctx->ibss_freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
1268 wpa_printf(MSG_DEBUG, "nl80211: IBSS-joined on %u MHz",
1269 ctx->ibss_freq);
1270 }
1271 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
1272 bss[NL80211_BSS_BSSID]) {
1273 os_memcpy(ctx->assoc_bssid,
1274 nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
1275 wpa_printf(MSG_DEBUG, "nl80211: Associated with "
1276 MACSTR, MAC2STR(ctx->assoc_bssid));
1277 }
1278
1279 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
1280 bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
1281 const u8 *ie, *ssid;
1282 size_t ie_len;
1283
1284 ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
1285 ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
1286 ssid = get_ie(ie, ie_len, WLAN_EID_SSID);
1287 if (ssid && ssid[1] > 0 && ssid[1] <= SSID_MAX_LEN) {
1288 ctx->assoc_ssid_len = ssid[1];
1289 os_memcpy(ctx->assoc_ssid, ssid + 2, ssid[1]);
1290 }
1291 }
1292
1293 return NL_SKIP;
1294}
1295
1296
1297int nl80211_get_assoc_ssid(struct wpa_driver_nl80211_data *drv, u8 *ssid)
Jouni Malinen87fd2792011-05-16 18:35:42 +03001298{
1299 struct nl_msg *msg;
1300 int ret;
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08001301 struct nl80211_get_assoc_freq_arg arg;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001302
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001303 msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Jouni Malinen87fd2792011-05-16 18:35:42 +03001304 os_memset(&arg, 0, sizeof(arg));
Jouni Malinen87fd2792011-05-16 18:35:42 +03001305 arg.drv = drv;
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08001306 ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler,
1307 &arg);
1308 if (ret == 0) {
1309 os_memcpy(ssid, arg.assoc_ssid, arg.assoc_ssid_len);
1310 return arg.assoc_ssid_len;
1311 }
1312 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d (%s)",
1313 ret, strerror(-ret));
1314 return ret;
1315}
1316
1317
1318unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
1319{
1320 struct nl_msg *msg;
1321 int ret;
1322 struct nl80211_get_assoc_freq_arg arg;
1323
1324 msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
1325 os_memset(&arg, 0, sizeof(arg));
1326 arg.drv = drv;
1327 ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler,
1328 &arg);
Jouni Malinen87fd2792011-05-16 18:35:42 +03001329 if (ret == 0) {
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001330 unsigned int freq = drv->nlmode == NL80211_IFTYPE_ADHOC ?
1331 arg.ibss_freq : arg.assoc_freq;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001332 wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001333 "associated BSS from scan results: %u MHz", freq);
1334 if (freq)
1335 drv->assoc_freq = freq;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07001336 return drv->assoc_freq;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001337 }
1338 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
1339 "(%s)", ret, strerror(-ret));
Jouni Malinen87fd2792011-05-16 18:35:42 +03001340 return drv->assoc_freq;
1341}
1342
1343
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344static int get_link_signal(struct nl_msg *msg, void *arg)
1345{
1346 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1347 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1348 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
1349 static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
1350 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001351 [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07001352 [NL80211_STA_INFO_BEACON_SIGNAL_AVG] = { .type = NLA_U8 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353 };
1354 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
1355 static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
1356 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
1357 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
1358 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
1359 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
1360 };
1361 struct wpa_signal_info *sig_change = arg;
1362
1363 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1364 genlmsg_attrlen(gnlh, 0), NULL);
1365 if (!tb[NL80211_ATTR_STA_INFO] ||
1366 nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
1367 tb[NL80211_ATTR_STA_INFO], policy))
1368 return NL_SKIP;
1369 if (!sinfo[NL80211_STA_INFO_SIGNAL])
1370 return NL_SKIP;
1371
1372 sig_change->current_signal =
1373 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
1374
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001375 if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
1376 sig_change->avg_signal =
1377 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
1378 else
1379 sig_change->avg_signal = 0;
1380
Dmitry Shmidtf73259c2015-03-17 11:00:54 -07001381 if (sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG])
1382 sig_change->avg_beacon_signal =
1383 (s8)
1384 nla_get_u8(sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]);
1385 else
1386 sig_change->avg_beacon_signal = 0;
1387
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001388 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
1389 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
1390 sinfo[NL80211_STA_INFO_TX_BITRATE],
1391 rate_policy)) {
1392 sig_change->current_txrate = 0;
1393 } else {
1394 if (rinfo[NL80211_RATE_INFO_BITRATE]) {
1395 sig_change->current_txrate =
1396 nla_get_u16(rinfo[
1397 NL80211_RATE_INFO_BITRATE]) * 100;
1398 }
1399 }
1400 }
1401
1402 return NL_SKIP;
1403}
1404
1405
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001406int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
1407 struct wpa_signal_info *sig)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001408{
1409 struct nl_msg *msg;
1410
1411 sig->current_signal = -9999;
1412 sig->current_txrate = 0;
1413
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001414 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_STATION)) ||
1415 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid)) {
1416 nlmsg_free(msg);
1417 return -ENOBUFS;
1418 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001419
1420 return send_and_recv_msgs(drv, msg, get_link_signal, sig);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001421}
1422
1423
1424static int get_link_noise(struct nl_msg *msg, void *arg)
1425{
1426 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1427 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1428 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
1429 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
1430 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
1431 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
1432 };
1433 struct wpa_signal_info *sig_change = arg;
1434
1435 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1436 genlmsg_attrlen(gnlh, 0), NULL);
1437
1438 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
1439 wpa_printf(MSG_DEBUG, "nl80211: survey data missing!");
1440 return NL_SKIP;
1441 }
1442
1443 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
1444 tb[NL80211_ATTR_SURVEY_INFO],
1445 survey_policy)) {
1446 wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested "
1447 "attributes!");
1448 return NL_SKIP;
1449 }
1450
1451 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
1452 return NL_SKIP;
1453
1454 if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
1455 sig_change->frequency)
1456 return NL_SKIP;
1457
1458 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
1459 return NL_SKIP;
1460
1461 sig_change->current_noise =
1462 (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
1463
1464 return NL_SKIP;
1465}
1466
1467
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001468int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
1469 struct wpa_signal_info *sig_change)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001470{
1471 struct nl_msg *msg;
1472
1473 sig_change->current_noise = 9999;
1474 sig_change->frequency = drv->assoc_freq;
1475
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001476 msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001477 return send_and_recv_msgs(drv, msg, get_link_noise, sig_change);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478}
1479
1480
1481static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
1482 void *handle)
1483{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001484 struct nl_cb *cb = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001485 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001486
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001487 wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001488
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001489 res = nl_recvmsgs(handle, cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -07001490 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001491 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
1492 __func__, res);
1493 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001494}
1495
1496
1497/**
1498 * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
1499 * @priv: driver_nl80211 private data
1500 * @alpha2_arg: country to which to switch to
1501 * Returns: 0 on success, -1 on failure
1502 *
1503 * This asks nl80211 to set the regulatory domain for given
1504 * country ISO / IEC alpha2.
1505 */
1506static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
1507{
1508 struct i802_bss *bss = priv;
1509 struct wpa_driver_nl80211_data *drv = bss->drv;
1510 char alpha2[3];
1511 struct nl_msg *msg;
1512
1513 msg = nlmsg_alloc();
1514 if (!msg)
1515 return -ENOMEM;
1516
1517 alpha2[0] = alpha2_arg[0];
1518 alpha2[1] = alpha2_arg[1];
1519 alpha2[2] = '\0';
1520
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001521 if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG) ||
1522 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, alpha2)) {
1523 nlmsg_free(msg);
1524 return -EINVAL;
1525 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001526 if (send_and_recv_msgs(drv, msg, NULL, NULL))
1527 return -EINVAL;
1528 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529}
1530
1531
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001532static int nl80211_get_country(struct nl_msg *msg, void *arg)
1533{
1534 char *alpha2 = arg;
1535 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
1536 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1537
1538 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1539 genlmsg_attrlen(gnlh, 0), NULL);
1540 if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) {
1541 wpa_printf(MSG_DEBUG, "nl80211: No country information available");
1542 return NL_SKIP;
1543 }
1544 os_strlcpy(alpha2, nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]), 3);
1545 return NL_SKIP;
1546}
1547
1548
1549static int wpa_driver_nl80211_get_country(void *priv, char *alpha2)
1550{
1551 struct i802_bss *bss = priv;
1552 struct wpa_driver_nl80211_data *drv = bss->drv;
1553 struct nl_msg *msg;
1554 int ret;
1555
1556 msg = nlmsg_alloc();
1557 if (!msg)
1558 return -ENOMEM;
1559
1560 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
1561 alpha2[0] = '\0';
1562 ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2);
1563 if (!alpha2[0])
1564 ret = -1;
1565
1566 return ret;
1567}
1568
1569
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001570static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001571{
1572 int ret;
1573
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001574 global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
1575 if (global->nl_cb == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001576 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
1577 "callbacks");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001578 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001579 }
1580
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001581 global->nl = nl_create_handle(global->nl_cb, "nl");
1582 if (global->nl == NULL)
1583 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001584
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001585 global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
1586 if (global->nl80211_id < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001587 wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
1588 "found");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001589 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001590 }
1591
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001592 global->nl_event = nl_create_handle(global->nl_cb, "event");
1593 if (global->nl_event == NULL)
1594 goto err;
1595
1596 ret = nl_get_multicast_id(global, "nl80211", "scan");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001597 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001598 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001599 if (ret < 0) {
1600 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
1601 "membership for scan events: %d (%s)",
1602 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001603 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604 }
1605
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001606 ret = nl_get_multicast_id(global, "nl80211", "mlme");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001608 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609 if (ret < 0) {
1610 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
1611 "membership for mlme events: %d (%s)",
1612 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001613 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614 }
1615
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001616 ret = nl_get_multicast_id(global, "nl80211", "regulatory");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001617 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001618 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001619 if (ret < 0) {
1620 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
1621 "membership for regulatory events: %d (%s)",
1622 ret, strerror(-ret));
1623 /* Continue without regulatory events */
1624 }
1625
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001626 ret = nl_get_multicast_id(global, "nl80211", "vendor");
1627 if (ret >= 0)
1628 ret = nl_socket_add_membership(global->nl_event, ret);
1629 if (ret < 0) {
1630 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
1631 "membership for vendor events: %d (%s)",
1632 ret, strerror(-ret));
1633 /* Continue without vendor events */
1634 }
1635
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001636 nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
1637 no_seq_check, NULL);
1638 nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
1639 process_global_event, global);
1640
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001641 nl80211_register_eloop_read(&global->nl_event,
1642 wpa_driver_nl80211_event_receive,
1643 global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001644
1645 return 0;
1646
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001647err:
1648 nl_destroy_handles(&global->nl_event);
1649 nl_destroy_handles(&global->nl);
1650 nl_cb_put(global->nl_cb);
1651 global->nl_cb = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001652 return -1;
1653}
1654
1655
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001656static void nl80211_check_global(struct nl80211_global *global)
1657{
1658 struct nl_handle *handle;
1659 const char *groups[] = { "scan", "mlme", "regulatory", "vendor", NULL };
1660 int ret;
1661 unsigned int i;
1662
1663 /*
1664 * Try to re-add memberships to handle case of cfg80211 getting reloaded
1665 * and all registration having been cleared.
1666 */
1667 handle = (void *) (((intptr_t) global->nl_event) ^
1668 ELOOP_SOCKET_INVALID);
1669
1670 for (i = 0; groups[i]; i++) {
1671 ret = nl_get_multicast_id(global, "nl80211", groups[i]);
1672 if (ret >= 0)
1673 ret = nl_socket_add_membership(handle, ret);
1674 if (ret < 0) {
1675 wpa_printf(MSG_INFO,
1676 "nl80211: Could not re-add multicast membership for %s events: %d (%s)",
1677 groups[i], ret, strerror(-ret));
1678 }
1679 }
1680}
1681
1682
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001683static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
1684{
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001685 struct wpa_driver_nl80211_data *drv = ctx;
1686
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001687 wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001688
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001689 /*
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001690 * rtnetlink ifdown handler will report interfaces other than the P2P
1691 * Device interface as disabled.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001692 */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001693 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
1694 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001695}
1696
1697
1698static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
1699{
1700 struct wpa_driver_nl80211_data *drv = ctx;
1701 wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001702 if (i802_set_iface_flags(drv->first_bss, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001703 wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
1704 "after rfkill unblock");
1705 return;
1706 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001707
1708 if (is_p2p_net_interface(drv->nlmode))
1709 nl80211_disable_11b_rates(drv, drv->ifindex, 1);
1710
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001711 /*
1712 * rtnetlink ifup handler will report interfaces other than the P2P
1713 * Device interface as enabled.
1714 */
1715 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
1716 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001717}
1718
1719
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001720static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
1721 void *eloop_ctx,
1722 void *handle)
1723{
1724 struct wpa_driver_nl80211_data *drv = eloop_ctx;
1725 u8 data[2048];
1726 struct msghdr msg;
1727 struct iovec entry;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001728 u8 control[512];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001729 struct cmsghdr *cmsg;
1730 int res, found_ee = 0, found_wifi = 0, acked = 0;
1731 union wpa_event_data event;
1732
1733 memset(&msg, 0, sizeof(msg));
1734 msg.msg_iov = &entry;
1735 msg.msg_iovlen = 1;
1736 entry.iov_base = data;
1737 entry.iov_len = sizeof(data);
1738 msg.msg_control = &control;
1739 msg.msg_controllen = sizeof(control);
1740
1741 res = recvmsg(sock, &msg, MSG_ERRQUEUE);
1742 /* if error or not fitting 802.3 header, return */
1743 if (res < 14)
1744 return;
1745
1746 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
1747 {
1748 if (cmsg->cmsg_level == SOL_SOCKET &&
1749 cmsg->cmsg_type == SCM_WIFI_STATUS) {
1750 int *ack;
1751
1752 found_wifi = 1;
1753 ack = (void *)CMSG_DATA(cmsg);
1754 acked = *ack;
1755 }
1756
1757 if (cmsg->cmsg_level == SOL_PACKET &&
1758 cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
1759 struct sock_extended_err *err =
1760 (struct sock_extended_err *)CMSG_DATA(cmsg);
1761
1762 if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
1763 found_ee = 1;
1764 }
1765 }
1766
1767 if (!found_ee || !found_wifi)
1768 return;
1769
1770 memset(&event, 0, sizeof(event));
1771 event.eapol_tx_status.dst = data;
1772 event.eapol_tx_status.data = data + 14;
1773 event.eapol_tx_status.data_len = res - 14;
1774 event.eapol_tx_status.ack = acked;
1775 wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
1776}
1777
1778
1779static int nl80211_init_bss(struct i802_bss *bss)
1780{
1781 bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
1782 if (!bss->nl_cb)
1783 return -1;
1784
1785 nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
1786 no_seq_check, NULL);
1787 nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
1788 process_bss_event, bss);
1789
1790 return 0;
1791}
1792
1793
1794static void nl80211_destroy_bss(struct i802_bss *bss)
1795{
1796 nl_cb_put(bss->nl_cb);
1797 bss->nl_cb = NULL;
1798}
1799
1800
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08001801static void
1802wpa_driver_nl80211_drv_init_rfkill(struct wpa_driver_nl80211_data *drv)
1803{
1804 struct rfkill_config *rcfg;
1805
1806 if (drv->rfkill)
1807 return;
1808
1809 rcfg = os_zalloc(sizeof(*rcfg));
1810 if (!rcfg)
1811 return;
1812
1813 rcfg->ctx = drv;
1814
1815 /* rfkill uses netdev sysfs for initialization. However, P2P Device is
1816 * not associated with a netdev, so use the name of some other interface
1817 * sharing the same wiphy as the P2P Device interface.
1818 *
1819 * Note: This is valid, as a P2P Device interface is always dynamically
1820 * created and is created only once another wpa_s interface was added.
1821 */
1822 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) {
1823 struct nl80211_global *global = drv->global;
1824 struct wpa_driver_nl80211_data *tmp1;
1825
1826 dl_list_for_each(tmp1, &global->interfaces,
1827 struct wpa_driver_nl80211_data, list) {
1828 if (drv == tmp1 || drv->wiphy_idx != tmp1->wiphy_idx ||
1829 !tmp1->rfkill)
1830 continue;
1831
1832 wpa_printf(MSG_DEBUG,
1833 "nl80211: Use (%s) to initialize P2P Device rfkill",
1834 tmp1->first_bss->ifname);
1835 os_strlcpy(rcfg->ifname, tmp1->first_bss->ifname,
1836 sizeof(rcfg->ifname));
1837 break;
1838 }
1839 } else {
1840 os_strlcpy(rcfg->ifname, drv->first_bss->ifname,
1841 sizeof(rcfg->ifname));
1842 }
1843
1844 rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
1845 rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
1846 drv->rfkill = rfkill_init(rcfg);
1847 if (!drv->rfkill) {
1848 wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
1849 os_free(rcfg);
1850 }
1851}
1852
1853
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001854static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
1855 void *global_priv, int hostapd,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001856 const u8 *set_addr,
1857 const char *driver_params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001858{
1859 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001860 struct i802_bss *bss;
1861
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001862 if (global_priv == NULL)
1863 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001864 drv = os_zalloc(sizeof(*drv));
1865 if (drv == NULL)
1866 return NULL;
1867 drv->global = global_priv;
1868 drv->ctx = ctx;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001869 drv->hostapd = !!hostapd;
1870 drv->eapol_sock = -1;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001871
1872 /*
1873 * There is no driver capability flag for this, so assume it is
1874 * supported and disable this on first attempt to use if the driver
1875 * rejects the command due to missing support.
1876 */
1877 drv->set_rekey_offload = 1;
1878
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001879 drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
1880 drv->if_indices = drv->default_if_indices;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001881 drv->if_indices_reason = drv->default_if_indices_reason;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001882
1883 drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
1884 if (!drv->first_bss) {
1885 os_free(drv);
1886 return NULL;
1887 }
1888 bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001889 bss->drv = drv;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001890 bss->ctx = ctx;
1891
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001892 os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
1893 drv->monitor_ifidx = -1;
1894 drv->monitor_sock = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001895 drv->eapol_tx_sock = -1;
1896 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001897
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001898 if (nl80211_init_bss(bss))
1899 goto failed;
1900
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001901 if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001902 goto failed;
1903
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001904 drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
1905 if (drv->eapol_tx_sock < 0)
1906 goto failed;
1907
1908 if (drv->data_tx_status) {
1909 int enabled = 1;
1910
1911 if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
1912 &enabled, sizeof(enabled)) < 0) {
1913 wpa_printf(MSG_DEBUG,
1914 "nl80211: wifi status sockopt failed\n");
1915 drv->data_tx_status = 0;
1916 if (!drv->use_monitor)
1917 drv->capa.flags &=
1918 ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
1919 } else {
1920 eloop_register_read_sock(drv->eapol_tx_sock,
1921 wpa_driver_nl80211_handle_eapol_tx_status,
1922 drv, NULL);
1923 }
1924 }
1925
1926 if (drv->global) {
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001927 nl80211_check_global(drv->global);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928 dl_list_add(&drv->global->interfaces, &drv->list);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001929 drv->in_interface_list = 1;
1930 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001931
1932 return bss;
1933
1934failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001935 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936 return NULL;
1937}
1938
1939
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001940/**
1941 * wpa_driver_nl80211_init - Initialize nl80211 driver interface
1942 * @ctx: context to be used when calling wpa_supplicant functions,
1943 * e.g., wpa_supplicant_event()
1944 * @ifname: interface name, e.g., wlan0
1945 * @global_priv: private driver global data from global_init()
1946 * Returns: Pointer to private data, %NULL on failure
1947 */
1948static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
1949 void *global_priv)
1950{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001951 return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL,
1952 NULL);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001953}
1954
1955
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001956static int nl80211_register_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001957 struct nl_handle *nl_handle,
1958 u16 type, const u8 *match, size_t match_len)
1959{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001960 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001961 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001962 int ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001963 char buf[30];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001964
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001965 buf[0] = '\0';
1966 wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07001967 wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s",
1968 type, fc2str(type), nl_handle, buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001970 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REGISTER_ACTION)) ||
1971 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, type) ||
1972 nla_put(msg, NL80211_ATTR_FRAME_MATCH, match_len, match)) {
1973 nlmsg_free(msg);
1974 return -1;
1975 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001976
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001977 ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978 if (ret) {
1979 wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
1980 "failed (type=%u): ret=%d (%s)",
1981 type, ret, strerror(-ret));
1982 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
1983 match, match_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001985 return ret;
1986}
1987
1988
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001989static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
1990{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001991 if (bss->nl_mgmt) {
1992 wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting "
1993 "already on! (nl_mgmt=%p)", bss->nl_mgmt);
1994 return -1;
1995 }
1996
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001997 bss->nl_mgmt = nl_create_handle(bss->nl_cb, "mgmt");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001998 if (bss->nl_mgmt == NULL)
1999 return -1;
2000
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002001 return 0;
2002}
2003
2004
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002005static void nl80211_mgmt_handle_register_eloop(struct i802_bss *bss)
2006{
2007 nl80211_register_eloop_read(&bss->nl_mgmt,
2008 wpa_driver_nl80211_event_receive,
2009 bss->nl_cb);
2010}
2011
2012
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002013static int nl80211_register_action_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002014 const u8 *match, size_t match_len)
2015{
2016 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002017 return nl80211_register_frame(bss, bss->nl_mgmt,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018 type, match, match_len);
2019}
2020
2021
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002022static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002023{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002024 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002025 int ret = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002026
2027 if (nl80211_alloc_mgmt_handle(bss))
2028 return -1;
2029 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
2030 "handle %p", bss->nl_mgmt);
2031
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002032 if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
2033 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
2034
2035 /* register for any AUTH message */
2036 nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0);
2037 }
2038
Dmitry Shmidt051af732013-10-22 13:52:46 -07002039#ifdef CONFIG_INTERWORKING
2040 /* QoS Map Configure */
2041 if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002042 ret = -1;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002043#endif /* CONFIG_INTERWORKING */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002044#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING) || defined(CONFIG_DPP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045 /* GAS Initial Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002046 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002047 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002048 /* GAS Initial Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002049 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002050 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002051 /* GAS Comeback Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002052 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002053 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054 /* GAS Comeback Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002055 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002056 ret = -1;
Dmitry Shmidt18463232014-01-24 12:29:41 -08002057 /* Protected GAS Initial Request */
2058 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0)
2059 ret = -1;
2060 /* Protected GAS Initial Response */
2061 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0)
2062 ret = -1;
2063 /* Protected GAS Comeback Request */
2064 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0)
2065 ret = -1;
2066 /* Protected GAS Comeback Response */
2067 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0)
2068 ret = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002069#endif /* CONFIG_P2P || CONFIG_INTERWORKING || CONFIG_DPP */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002070#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002071 /* P2P Public Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002072 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073 (u8 *) "\x04\x09\x50\x6f\x9a\x09",
2074 6) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002075 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076 /* P2P Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002077 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002078 (u8 *) "\x7f\x50\x6f\x9a\x09",
2079 5) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002080 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002081#endif /* CONFIG_P2P */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002082#ifdef CONFIG_DPP
2083 /* DPP Public Action */
2084 if (nl80211_register_action_frame(bss,
2085 (u8 *) "\x04\x09\x50\x6f\x9a\x1a",
2086 6) < 0)
2087 ret = -1;
2088#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089#ifdef CONFIG_IEEE80211W
2090 /* SA Query Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002091 if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002092 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002094#ifdef CONFIG_TDLS
2095 if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
2096 /* TDLS Discovery Response */
2097 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
2098 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002099 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002100 }
2101#endif /* CONFIG_TDLS */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002102#ifdef CONFIG_FST
2103 /* FST Action frames */
2104 if (nl80211_register_action_frame(bss, (u8 *) "\x12", 1) < 0)
2105 ret = -1;
2106#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107
2108 /* FT Action frames */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002109 if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002110 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002111 else
2112 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
2113 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
2114
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002115 /* WNM - BSS Transition Management Request */
2116 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002117 ret = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002118 /* WNM-Sleep Mode Response */
2119 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002120 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002121
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002122#ifdef CONFIG_HS20
2123 /* WNM-Notification */
2124 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002125 ret = -1;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002126#endif /* CONFIG_HS20 */
2127
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002128 /* WMM-AC ADDTS Response */
2129 if (nl80211_register_action_frame(bss, (u8 *) "\x11\x01", 2) < 0)
2130 ret = -1;
2131
2132 /* WMM-AC DELTS */
2133 if (nl80211_register_action_frame(bss, (u8 *) "\x11\x02", 2) < 0)
2134 ret = -1;
2135
2136 /* Radio Measurement - Neighbor Report Response */
2137 if (nl80211_register_action_frame(bss, (u8 *) "\x05\x05", 2) < 0)
2138 ret = -1;
2139
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002140 /* Radio Measurement - Radio Measurement Request */
2141 if (nl80211_register_action_frame(bss, (u8 *) "\x05\x00", 2) < 0)
2142 ret = -1;
2143
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002144 /* Radio Measurement - Link Measurement Request */
2145 if ((drv->capa.rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION) &&
2146 (nl80211_register_action_frame(bss, (u8 *) "\x05\x02", 2) < 0))
2147 ret = -1;
2148
2149 nl80211_mgmt_handle_register_eloop(bss);
2150
2151 return ret;
2152}
2153
2154
2155static int nl80211_mgmt_subscribe_mesh(struct i802_bss *bss)
2156{
2157 int ret = 0;
2158
2159 if (nl80211_alloc_mgmt_handle(bss))
2160 return -1;
2161
2162 wpa_printf(MSG_DEBUG,
2163 "nl80211: Subscribe to mgmt frames with mesh handle %p",
2164 bss->nl_mgmt);
2165
2166 /* Auth frames for mesh SAE */
2167 if (nl80211_register_frame(bss, bss->nl_mgmt,
2168 (WLAN_FC_TYPE_MGMT << 2) |
2169 (WLAN_FC_STYPE_AUTH << 4),
2170 NULL, 0) < 0)
2171 ret = -1;
2172
2173 /* Mesh peering open */
2174 if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x01", 2) < 0)
2175 ret = -1;
2176 /* Mesh peering confirm */
2177 if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x02", 2) < 0)
2178 ret = -1;
2179 /* Mesh peering close */
2180 if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x03", 2) < 0)
2181 ret = -1;
2182
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002183 nl80211_mgmt_handle_register_eloop(bss);
2184
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002185 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002186}
2187
2188
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002189static int nl80211_register_spurious_class3(struct i802_bss *bss)
2190{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002191 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002192 int ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002193
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002194 msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UNEXPECTED_FRAME);
2195 ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002196 if (ret) {
2197 wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
2198 "failed: ret=%d (%s)",
2199 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002200 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002201 return ret;
2202}
2203
2204
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002205static int nl80211_action_subscribe_ap(struct i802_bss *bss)
2206{
2207 int ret = 0;
2208
2209 /* Public Action frames */
2210 if (nl80211_register_action_frame(bss, (u8 *) "\x04", 1) < 0)
2211 ret = -1;
2212 /* RRM Measurement Report */
2213 if (nl80211_register_action_frame(bss, (u8 *) "\x05\x01", 2) < 0)
2214 ret = -1;
Paul Stewart092955c2017-02-06 09:13:09 -08002215 /* RRM Link Measurement Report */
2216 if (nl80211_register_action_frame(bss, (u8 *) "\x05\x03", 2) < 0)
2217 ret = -1;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002218 /* RRM Neighbor Report Request */
2219 if (nl80211_register_action_frame(bss, (u8 *) "\x05\x04", 2) < 0)
2220 ret = -1;
2221 /* FT Action frames */
2222 if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
2223 ret = -1;
2224#ifdef CONFIG_IEEE80211W
2225 /* SA Query */
2226 if (nl80211_register_action_frame(bss, (u8 *) "\x08", 1) < 0)
2227 ret = -1;
2228#endif /* CONFIG_IEEE80211W */
2229 /* Protected Dual of Public Action */
2230 if (nl80211_register_action_frame(bss, (u8 *) "\x09", 1) < 0)
2231 ret = -1;
2232 /* WNM */
2233 if (nl80211_register_action_frame(bss, (u8 *) "\x0a", 1) < 0)
2234 ret = -1;
2235 /* WMM */
2236 if (nl80211_register_action_frame(bss, (u8 *) "\x11", 1) < 0)
2237 ret = -1;
2238#ifdef CONFIG_FST
2239 /* FST Action frames */
2240 if (nl80211_register_action_frame(bss, (u8 *) "\x12", 1) < 0)
2241 ret = -1;
2242#endif /* CONFIG_FST */
2243 /* Vendor-specific */
2244 if (nl80211_register_action_frame(bss, (u8 *) "\x7f", 1) < 0)
2245 ret = -1;
2246
2247 return ret;
2248}
2249
2250
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002251static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
2252{
2253 static const int stypes[] = {
2254 WLAN_FC_STYPE_AUTH,
2255 WLAN_FC_STYPE_ASSOC_REQ,
2256 WLAN_FC_STYPE_REASSOC_REQ,
2257 WLAN_FC_STYPE_DISASSOC,
2258 WLAN_FC_STYPE_DEAUTH,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002259 WLAN_FC_STYPE_PROBE_REQ,
2260/* Beacon doesn't work as mac80211 doesn't currently allow
2261 * it, but it wouldn't really be the right thing anyway as
2262 * it isn't per interface ... maybe just dump the scan
2263 * results periodically for OLBC?
2264 */
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002265 /* WLAN_FC_STYPE_BEACON, */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002266 };
2267 unsigned int i;
2268
2269 if (nl80211_alloc_mgmt_handle(bss))
2270 return -1;
2271 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
2272 "handle %p", bss->nl_mgmt);
2273
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002274 for (i = 0; i < ARRAY_SIZE(stypes); i++) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002275 if (nl80211_register_frame(bss, bss->nl_mgmt,
2276 (WLAN_FC_TYPE_MGMT << 2) |
2277 (stypes[i] << 4),
2278 NULL, 0) < 0) {
2279 goto out_err;
2280 }
2281 }
2282
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002283 if (nl80211_action_subscribe_ap(bss))
2284 goto out_err;
2285
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002286 if (nl80211_register_spurious_class3(bss))
2287 goto out_err;
2288
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002289 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002290 return 0;
2291
2292out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002293 nl_destroy_handles(&bss->nl_mgmt);
2294 return -1;
2295}
2296
2297
2298static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)
2299{
2300 if (nl80211_alloc_mgmt_handle(bss))
2301 return -1;
2302 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
2303 "handle %p (device SME)", bss->nl_mgmt);
2304
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002305 if (nl80211_action_subscribe_ap(bss))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002306 goto out_err;
2307
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002308 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002309 return 0;
2310
2311out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002312 nl_destroy_handles(&bss->nl_mgmt);
2313 return -1;
2314}
2315
2316
2317static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
2318{
2319 if (bss->nl_mgmt == NULL)
2320 return;
2321 wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
2322 "(%s)", bss->nl_mgmt, reason);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002323 nl80211_destroy_eloop_handle(&bss->nl_mgmt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002324
2325 nl80211_put_wiphy_data_ap(bss);
2326}
2327
2328
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002329static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
2330{
2331 wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
2332}
2333
2334
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002335static void nl80211_del_p2pdev(struct i802_bss *bss)
2336{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002337 struct nl_msg *msg;
2338 int ret;
2339
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002340 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_INTERFACE);
2341 ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002342
2343 wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
2344 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002345 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002346}
2347
2348
2349static int nl80211_set_p2pdev(struct i802_bss *bss, int start)
2350{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002351 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002352 int ret;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002353
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002354 msg = nl80211_cmd_msg(bss, 0, start ? NL80211_CMD_START_P2P_DEVICE :
2355 NL80211_CMD_STOP_P2P_DEVICE);
2356 ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002357
2358 wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
2359 start ? "Start" : "Stop",
2360 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002361 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002362 return ret;
2363}
2364
2365
2366static int i802_set_iface_flags(struct i802_bss *bss, int up)
2367{
2368 enum nl80211_iftype nlmode;
2369
2370 nlmode = nl80211_get_ifmode(bss);
2371 if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
2372 return linux_set_iface_flags(bss->drv->global->ioctl_sock,
2373 bss->ifname, up);
2374 }
2375
2376 /* P2P Device has start/stop which is equivalent */
2377 return nl80211_set_p2pdev(bss, up);
2378}
2379
2380
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002381#ifdef CONFIG_TESTING_OPTIONS
2382static int qca_vendor_test_cmd_handler(struct nl_msg *msg, void *arg)
2383{
2384 /* struct wpa_driver_nl80211_data *drv = arg; */
2385 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2386 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2387
2388
2389 wpa_printf(MSG_DEBUG,
2390 "nl80211: QCA vendor test command response received");
2391
2392 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2393 genlmsg_attrlen(gnlh, 0), NULL);
2394 if (!tb[NL80211_ATTR_VENDOR_DATA]) {
2395 wpa_printf(MSG_DEBUG, "nl80211: No vendor data attribute");
2396 return NL_SKIP;
2397 }
2398
2399 wpa_hexdump(MSG_DEBUG,
2400 "nl80211: Received QCA vendor test command response",
2401 nla_data(tb[NL80211_ATTR_VENDOR_DATA]),
2402 nla_len(tb[NL80211_ATTR_VENDOR_DATA]));
2403
2404 return NL_SKIP;
2405}
2406#endif /* CONFIG_TESTING_OPTIONS */
2407
2408
2409static void qca_vendor_test(struct wpa_driver_nl80211_data *drv)
2410{
2411#ifdef CONFIG_TESTING_OPTIONS
2412 struct nl_msg *msg;
2413 struct nlattr *params;
2414 int ret;
2415
2416 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
2417 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
2418 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
2419 QCA_NL80211_VENDOR_SUBCMD_TEST) ||
2420 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
2421 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TEST, 123)) {
2422 nlmsg_free(msg);
2423 return;
2424 }
2425 nla_nest_end(msg, params);
2426
2427 ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv);
2428 wpa_printf(MSG_DEBUG,
2429 "nl80211: QCA vendor test command returned %d (%s)",
2430 ret, strerror(-ret));
2431#endif /* CONFIG_TESTING_OPTIONS */
2432}
2433
2434
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002435static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002436wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002437 const u8 *set_addr, int first,
2438 const char *driver_params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439{
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002440 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441 int send_rfkill_event = 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002442 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002443
2444 drv->ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002445 bss->ifindex = drv->ifindex;
2446 bss->wdev_id = drv->global->if_add_wdevid;
2447 bss->wdev_id_set = drv->global->if_add_wdevid_set;
2448
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002449 bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;
2450 bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002451 drv->global->if_add_wdevid_set = 0;
2452
Dmitry Shmidt03658832014-08-13 11:03:49 -07002453 if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
2454 bss->static_ap = 1;
2455
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08002456 if (first &&
2457 nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
2458 linux_iface_up(drv->global->ioctl_sock, bss->ifname) > 0)
2459 drv->start_iface_up = 1;
2460
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002461 if (wpa_driver_nl80211_capa(drv))
2462 return -1;
2463
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002464 if (driver_params && nl80211_set_param(bss, driver_params) < 0)
2465 return -1;
2466
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002467 wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
2468 bss->ifname, drv->phyname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002470 if (set_addr &&
2471 (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) ||
2472 linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
2473 set_addr)))
2474 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002475
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002476 if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
2477 drv->start_mode_ap = 1;
2478
Dmitry Shmidt03658832014-08-13 11:03:49 -07002479 if (drv->hostapd || bss->static_ap)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002480 nlmode = NL80211_IFTYPE_AP;
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07002481 else if (bss->if_dynamic ||
2482 nl80211_get_ifmode(bss) == NL80211_IFTYPE_MESH_POINT)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002483 nlmode = nl80211_get_ifmode(bss);
2484 else
2485 nlmode = NL80211_IFTYPE_STATION;
2486
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002487 if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002488 wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002489 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002490 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002491
Dmitry Shmidt98660862014-03-11 17:26:21 -07002492 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002493 nl80211_get_macaddr(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002494
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002495 wpa_driver_nl80211_drv_init_rfkill(drv);
2496
Dmitry Shmidt98660862014-03-11 17:26:21 -07002497 if (!rfkill_is_blocked(drv->rfkill)) {
2498 int ret = i802_set_iface_flags(bss, 1);
2499 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002500 wpa_printf(MSG_ERROR, "nl80211: Could not set "
2501 "interface '%s' UP", bss->ifname);
Dmitry Shmidt98660862014-03-11 17:26:21 -07002502 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002503 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002504
2505 if (is_p2p_net_interface(nlmode))
2506 nl80211_disable_11b_rates(bss->drv,
2507 bss->drv->ifindex, 1);
2508
Dmitry Shmidt98660862014-03-11 17:26:21 -07002509 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
2510 return ret;
2511 } else {
2512 wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
2513 "interface '%s' due to rfkill", bss->ifname);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002514 if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
2515 drv->if_disabled = 1;
2516
Dmitry Shmidt98660862014-03-11 17:26:21 -07002517 send_rfkill_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 }
2519
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002520 if (!drv->hostapd && nlmode != NL80211_IFTYPE_P2P_DEVICE)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002521 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
2522 1, IF_OPER_DORMANT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002524 if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
2525 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
2526 bss->addr))
2527 return -1;
2528 os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
2529 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 if (send_rfkill_event) {
2532 eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
2533 drv, drv->ctx);
2534 }
2535
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002536 if (drv->vendor_cmd_test_avail)
2537 qca_vendor_test(drv);
2538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539 return 0;
2540}
2541
2542
Paul Stewart092955c2017-02-06 09:13:09 -08002543static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544{
2545 struct nl_msg *msg;
Paul Stewart092955c2017-02-06 09:13:09 -08002546 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002547
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002548 wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
2549 drv->ifindex);
Paul Stewart092955c2017-02-06 09:13:09 -08002550 nl80211_put_wiphy_data_ap(bss);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002551 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002553}
2554
2555
2556/**
2557 * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002558 * @bss: Pointer to private nl80211 data from wpa_driver_nl80211_init()
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559 *
2560 * Shut down driver interface and processing of driver events. Free
2561 * private data buffer if one was allocated in wpa_driver_nl80211_init().
2562 */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002563static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002566 unsigned int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002568 wpa_printf(MSG_INFO, "nl80211: deinit ifname=%s disabled_11b_rates=%d",
2569 bss->ifname, drv->disabled_11b_rates);
2570
Dmitry Shmidt04949592012-07-19 12:16:46 -07002571 bss->in_deinit = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002572 if (drv->data_tx_status)
2573 eloop_unregister_read_sock(drv->eapol_tx_sock);
2574 if (drv->eapol_tx_sock >= 0)
2575 close(drv->eapol_tx_sock);
2576
2577 if (bss->nl_preq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 wpa_driver_nl80211_probe_req_report(bss, 0);
2579 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002580 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
2581 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002582 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
2583 "interface %s from bridge %s: %s",
2584 bss->ifname, bss->brname, strerror(errno));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002585 if (drv->rtnl_sk)
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002586 nl80211_handle_destroy(drv->rtnl_sk);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 }
2588 if (bss->added_bridge) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002589 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->brname,
2590 0) < 0)
2591 wpa_printf(MSG_INFO,
2592 "nl80211: Could not set bridge %s down",
2593 bss->brname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002594 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
2596 "bridge %s: %s",
2597 bss->brname, strerror(errno));
2598 }
2599
2600 nl80211_remove_monitor_interface(drv);
2601
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002602 if (is_ap_interface(drv->nlmode))
Paul Stewart092955c2017-02-06 09:13:09 -08002603 wpa_driver_nl80211_del_beacon(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 if (drv->eapol_sock >= 0) {
2606 eloop_unregister_read_sock(drv->eapol_sock);
2607 close(drv->eapol_sock);
2608 }
2609
2610 if (drv->if_indices != drv->default_if_indices)
2611 os_free(drv->if_indices);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002613 if (drv->if_indices_reason != drv->default_if_indices_reason)
2614 os_free(drv->if_indices_reason);
2615
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002616 if (drv->disabled_11b_rates)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
2618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002619 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
2620 IF_OPER_UP);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07002621 eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 rfkill_deinit(drv->rfkill);
2623
2624 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
2625
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002626 if (!drv->start_iface_up)
2627 (void) i802_set_iface_flags(bss, 0);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002628
2629 if (drv->addr_changed) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002630 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
2631 0) < 0) {
2632 wpa_printf(MSG_DEBUG,
2633 "nl80211: Could not set interface down to restore permanent MAC address");
2634 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002635 if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
2636 drv->perm_addr) < 0) {
2637 wpa_printf(MSG_DEBUG,
2638 "nl80211: Could not restore permanent MAC address");
2639 }
2640 }
2641
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002642 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002643 if (!drv->hostapd || !drv->start_mode_ap)
2644 wpa_driver_nl80211_set_mode(bss,
2645 NL80211_IFTYPE_STATION);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002646 nl80211_mgmt_unsubscribe(bss, "deinit");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002647 } else {
2648 nl80211_mgmt_unsubscribe(bss, "deinit");
2649 nl80211_del_p2pdev(bss);
2650 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002652 nl80211_destroy_bss(drv->first_bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002653
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 os_free(drv->filter_ssids);
2655
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002656 os_free(drv->auth_ie);
2657
2658 if (drv->in_interface_list)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 dl_list_del(&drv->list);
2660
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002661 os_free(drv->extended_capa);
2662 os_free(drv->extended_capa_mask);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07002663 for (i = 0; i < drv->num_iface_ext_capa; i++) {
2664 os_free(drv->iface_ext_capa[i].ext_capa);
2665 os_free(drv->iface_ext_capa[i].ext_capa_mask);
2666 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002667 os_free(drv->first_bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668 os_free(drv);
2669}
2670
2671
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002672static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len)
2673{
2674 switch (alg) {
2675 case WPA_ALG_WEP:
2676 if (key_len == 5)
Paul Stewart092955c2017-02-06 09:13:09 -08002677 return RSN_CIPHER_SUITE_WEP40;
2678 return RSN_CIPHER_SUITE_WEP104;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002679 case WPA_ALG_TKIP:
Paul Stewart092955c2017-02-06 09:13:09 -08002680 return RSN_CIPHER_SUITE_TKIP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002681 case WPA_ALG_CCMP:
Paul Stewart092955c2017-02-06 09:13:09 -08002682 return RSN_CIPHER_SUITE_CCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002683 case WPA_ALG_GCMP:
Paul Stewart092955c2017-02-06 09:13:09 -08002684 return RSN_CIPHER_SUITE_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002685 case WPA_ALG_CCMP_256:
Paul Stewart092955c2017-02-06 09:13:09 -08002686 return RSN_CIPHER_SUITE_CCMP_256;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002687 case WPA_ALG_GCMP_256:
Paul Stewart092955c2017-02-06 09:13:09 -08002688 return RSN_CIPHER_SUITE_GCMP_256;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002689 case WPA_ALG_IGTK:
Paul Stewart092955c2017-02-06 09:13:09 -08002690 return RSN_CIPHER_SUITE_AES_128_CMAC;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002691 case WPA_ALG_BIP_GMAC_128:
Paul Stewart092955c2017-02-06 09:13:09 -08002692 return RSN_CIPHER_SUITE_BIP_GMAC_128;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002693 case WPA_ALG_BIP_GMAC_256:
Paul Stewart092955c2017-02-06 09:13:09 -08002694 return RSN_CIPHER_SUITE_BIP_GMAC_256;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002695 case WPA_ALG_BIP_CMAC_256:
Paul Stewart092955c2017-02-06 09:13:09 -08002696 return RSN_CIPHER_SUITE_BIP_CMAC_256;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002697 case WPA_ALG_SMS4:
Paul Stewart092955c2017-02-06 09:13:09 -08002698 return RSN_CIPHER_SUITE_SMS4;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002699 case WPA_ALG_KRK:
Paul Stewart092955c2017-02-06 09:13:09 -08002700 return RSN_CIPHER_SUITE_KRK;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002701 case WPA_ALG_NONE:
2702 case WPA_ALG_PMK:
2703 wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d",
2704 alg);
2705 return 0;
2706 }
2707
2708 wpa_printf(MSG_ERROR, "nl80211: Unsupported encryption algorithm %d",
2709 alg);
2710 return 0;
2711}
2712
2713
2714static u32 wpa_cipher_to_cipher_suite(unsigned int cipher)
2715{
2716 switch (cipher) {
2717 case WPA_CIPHER_CCMP_256:
Paul Stewart092955c2017-02-06 09:13:09 -08002718 return RSN_CIPHER_SUITE_CCMP_256;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002719 case WPA_CIPHER_GCMP_256:
Paul Stewart092955c2017-02-06 09:13:09 -08002720 return RSN_CIPHER_SUITE_GCMP_256;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002721 case WPA_CIPHER_CCMP:
Paul Stewart092955c2017-02-06 09:13:09 -08002722 return RSN_CIPHER_SUITE_CCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002723 case WPA_CIPHER_GCMP:
Paul Stewart092955c2017-02-06 09:13:09 -08002724 return RSN_CIPHER_SUITE_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002725 case WPA_CIPHER_TKIP:
Paul Stewart092955c2017-02-06 09:13:09 -08002726 return RSN_CIPHER_SUITE_TKIP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002727 case WPA_CIPHER_WEP104:
Paul Stewart092955c2017-02-06 09:13:09 -08002728 return RSN_CIPHER_SUITE_WEP104;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002729 case WPA_CIPHER_WEP40:
Paul Stewart092955c2017-02-06 09:13:09 -08002730 return RSN_CIPHER_SUITE_WEP40;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002731 case WPA_CIPHER_GTK_NOT_USED:
Paul Stewart092955c2017-02-06 09:13:09 -08002732 return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002733 }
2734
2735 return 0;
2736}
2737
2738
2739static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[],
2740 int max_suites)
2741{
2742 int num_suites = 0;
2743
2744 if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP_256)
Paul Stewart092955c2017-02-06 09:13:09 -08002745 suites[num_suites++] = RSN_CIPHER_SUITE_CCMP_256;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002746 if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP_256)
Paul Stewart092955c2017-02-06 09:13:09 -08002747 suites[num_suites++] = RSN_CIPHER_SUITE_GCMP_256;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002748 if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP)
Paul Stewart092955c2017-02-06 09:13:09 -08002749 suites[num_suites++] = RSN_CIPHER_SUITE_CCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002750 if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP)
Paul Stewart092955c2017-02-06 09:13:09 -08002751 suites[num_suites++] = RSN_CIPHER_SUITE_GCMP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002752 if (num_suites < max_suites && ciphers & WPA_CIPHER_TKIP)
Paul Stewart092955c2017-02-06 09:13:09 -08002753 suites[num_suites++] = RSN_CIPHER_SUITE_TKIP;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002754 if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP104)
Paul Stewart092955c2017-02-06 09:13:09 -08002755 suites[num_suites++] = RSN_CIPHER_SUITE_WEP104;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002756 if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP40)
Paul Stewart092955c2017-02-06 09:13:09 -08002757 suites[num_suites++] = RSN_CIPHER_SUITE_WEP40;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002758
2759 return num_suites;
2760}
2761
2762
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002763#ifdef CONFIG_DRIVER_NL80211_QCA
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002764static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
2765 const u8 *key, size_t key_len)
2766{
2767 struct nl_msg *msg;
2768 int ret;
2769
2770 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD))
2771 return 0;
2772
2773 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
2774 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
2775 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
2776 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) ||
2777 nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) {
2778 nl80211_nlmsg_clear(msg);
2779 nlmsg_free(msg);
2780 return -1;
2781 }
2782 ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
2783 if (ret) {
2784 wpa_printf(MSG_DEBUG,
2785 "nl80211: Key management set key failed: ret=%d (%s)",
2786 ret, strerror(-ret));
2787 }
2788
2789 return ret;
2790}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002791#endif /* CONFIG_DRIVER_NL80211_QCA */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002792
2793
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002794static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002795 enum wpa_alg alg, const u8 *addr,
2796 int key_idx, int set_tx,
2797 const u8 *seq, size_t seq_len,
2798 const u8 *key, size_t key_len)
2799{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002800 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002801 int ifindex;
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07002802 struct nl_msg *msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 int ret;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07002804 int tdls = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002806 /* Ignore for P2P Device */
2807 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
2808 return 0;
2809
2810 ifindex = if_nametoindex(ifname);
2811 wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002812 "set_tx=%d seq_len=%lu key_len=%lu",
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002813 __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002814 (unsigned long) seq_len, (unsigned long) key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002815#ifdef CONFIG_TDLS
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07002816 if (key_idx == -1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002817 key_idx = 0;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07002818 tdls = 1;
2819 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002820#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002821
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002822#ifdef CONFIG_DRIVER_NL80211_QCA
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002823 if (alg == WPA_ALG_PMK &&
2824 (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
2825 wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key",
2826 __func__);
2827 ret = issue_key_mgmt_set_key(drv, key, key_len);
2828 return ret;
2829 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002830#endif /* CONFIG_DRIVER_NL80211_QCA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002831
2832 if (alg == WPA_ALG_NONE) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002833 msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY);
2834 if (!msg)
2835 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002836 } else {
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07002837 u32 suite;
2838
2839 suite = wpa_alg_to_cipher_suite(alg, key_len);
2840 if (!suite)
2841 goto fail;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002842 msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY);
2843 if (!msg ||
2844 nla_put(msg, NL80211_ATTR_KEY_DATA, key_len, key) ||
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07002845 nla_put_u32(msg, NL80211_ATTR_KEY_CIPHER, suite))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002846 goto fail;
Dmitry Shmidt98660862014-03-11 17:26:21 -07002847 wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002848 }
2849
Dmitry Shmidt98660862014-03-11 17:26:21 -07002850 if (seq && seq_len) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002851 if (nla_put(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq))
2852 goto fail;
Dmitry Shmidt98660862014-03-11 17:26:21 -07002853 wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
2854 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002855
2856 if (addr && !is_broadcast_ether_addr(addr)) {
2857 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002858 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
2859 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002860
2861 if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
2862 wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002863 if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE,
2864 NL80211_KEYTYPE_GROUP))
2865 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866 }
2867 } else if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002868 struct nlattr *types;
2869
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002870 wpa_printf(MSG_DEBUG, " broadcast key");
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002871
2872 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002873 if (!types ||
2874 nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
2875 goto fail;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002876 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002878 if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
2879 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002881 ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002882 if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
2883 ret = 0;
2884 if (ret)
2885 wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)",
2886 ret, strerror(-ret));
2887
2888 /*
2889 * If we failed or don't need to set the default TX key (below),
2890 * we're done here.
2891 */
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07002892 if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893 return ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002894 if (is_ap_interface(drv->nlmode) && addr &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002895 !is_broadcast_ether_addr(addr))
2896 return ret;
2897
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002898 msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY);
2899 if (!msg ||
2900 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002901 nla_put_flag(msg, (alg == WPA_ALG_IGTK ||
2902 alg == WPA_ALG_BIP_GMAC_128 ||
2903 alg == WPA_ALG_BIP_GMAC_256 ||
2904 alg == WPA_ALG_BIP_CMAC_256) ?
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002905 NL80211_ATTR_KEY_DEFAULT_MGMT :
2906 NL80211_ATTR_KEY_DEFAULT))
2907 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002909 struct nlattr *types;
2910
2911 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002912 if (!types ||
2913 nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
2914 goto fail;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002915 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002916 } else if (addr) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002917 struct nlattr *types;
2918
2919 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002920 if (!types ||
2921 nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST))
2922 goto fail;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002923 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 }
2925
2926 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
2927 if (ret == -ENOENT)
2928 ret = 0;
2929 if (ret)
2930 wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
2931 "err=%d %s)", ret, strerror(-ret));
2932 return ret;
2933
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002934fail:
2935 nl80211_nlmsg_clear(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002936 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002937 return -ENOBUFS;
2938}
2939
2940
2941static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,
2942 int key_idx, int defkey,
2943 const u8 *seq, size_t seq_len,
2944 const u8 *key, size_t key_len)
2945{
2946 struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07002947 u32 suite;
2948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 if (!key_attr)
2950 return -1;
2951
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07002952 suite = wpa_alg_to_cipher_suite(alg, key_len);
2953 if (!suite)
2954 return -1;
2955
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002956 if (defkey && alg == WPA_ALG_IGTK) {
2957 if (nla_put_flag(msg, NL80211_KEY_DEFAULT_MGMT))
2958 return -1;
2959 } else if (defkey) {
2960 if (nla_put_flag(msg, NL80211_KEY_DEFAULT))
2961 return -1;
2962 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002963
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002964 if (nla_put_u8(msg, NL80211_KEY_IDX, key_idx) ||
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07002965 nla_put_u32(msg, NL80211_KEY_CIPHER, suite) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002966 (seq && seq_len &&
2967 nla_put(msg, NL80211_KEY_SEQ, seq_len, seq)) ||
2968 nla_put(msg, NL80211_KEY_DATA, key_len, key))
2969 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002970
2971 nla_nest_end(msg, key_attr);
2972
2973 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002974}
2975
2976
2977static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
2978 struct nl_msg *msg)
2979{
2980 int i, privacy = 0;
2981 struct nlattr *nl_keys, *nl_key;
2982
2983 for (i = 0; i < 4; i++) {
2984 if (!params->wep_key[i])
2985 continue;
2986 privacy = 1;
2987 break;
2988 }
2989 if (params->wps == WPS_MODE_PRIVACY)
2990 privacy = 1;
2991 if (params->pairwise_suite &&
2992 params->pairwise_suite != WPA_CIPHER_NONE)
2993 privacy = 1;
2994
2995 if (!privacy)
2996 return 0;
2997
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002998 if (nla_put_flag(msg, NL80211_ATTR_PRIVACY))
2999 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003000
3001 nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
3002 if (!nl_keys)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003003 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003004
3005 for (i = 0; i < 4; i++) {
3006 if (!params->wep_key[i])
3007 continue;
3008
3009 nl_key = nla_nest_start(msg, i);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003010 if (!nl_key ||
3011 nla_put(msg, NL80211_KEY_DATA, params->wep_key_len[i],
3012 params->wep_key[i]) ||
3013 nla_put_u32(msg, NL80211_KEY_CIPHER,
3014 params->wep_key_len[i] == 5 ?
Paul Stewart092955c2017-02-06 09:13:09 -08003015 RSN_CIPHER_SUITE_WEP40 :
3016 RSN_CIPHER_SUITE_WEP104) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003017 nla_put_u8(msg, NL80211_KEY_IDX, i) ||
3018 (i == params->wep_tx_keyidx &&
3019 nla_put_flag(msg, NL80211_KEY_DEFAULT)))
3020 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003021
3022 nla_nest_end(msg, nl_key);
3023 }
3024 nla_nest_end(msg, nl_keys);
3025
3026 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003027}
3028
3029
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003030int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
3031 const u8 *addr, int cmd, u16 reason_code,
3032 int local_state_change)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003033{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003034 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003035 struct nl_msg *msg;
3036
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003037 if (!(msg = nl80211_drv_msg(drv, 0, cmd)) ||
3038 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) ||
3039 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
3040 (local_state_change &&
3041 nla_put_flag(msg, NL80211_ATTR_LOCAL_STATE_CHANGE))) {
3042 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003043 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003044 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003045
3046 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003047 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003048 wpa_dbg(drv->ctx, MSG_DEBUG,
3049 "nl80211: MLME command failed: reason=%u ret=%d (%s)",
3050 reason_code, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003051 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052 return ret;
3053}
3054
3055
3056static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003057 int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003059 int ret;
3060
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003061 wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003062 nl80211_mark_disconnected(drv);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003063 /* Disconnect command doesn't need BSSID - it uses cached value */
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003064 ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
3065 reason_code, 0);
3066 /*
3067 * For locally generated disconnect, supplicant already generates a
3068 * DEAUTH event, so ignore the event from NL80211.
3069 */
3070 drv->ignore_next_local_disconnect = ret == 0;
3071
3072 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003073}
3074
3075
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003076static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
3077 const u8 *addr, int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003078{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003079 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07003080 int ret;
Dmitry Shmidt413dde72014-04-11 10:23:22 -07003081
3082 if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
3083 nl80211_mark_disconnected(drv);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003084 return nl80211_leave_ibss(drv, 1);
Dmitry Shmidt413dde72014-04-11 10:23:22 -07003085 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003086 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003087 return wpa_driver_nl80211_disconnect(drv, reason_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003088 wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
3089 __func__, MAC2STR(addr), reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003090 nl80211_mark_disconnected(drv);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07003091 ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
3092 reason_code, 0);
3093 /*
3094 * For locally generated deauthenticate, supplicant already generates a
3095 * DEAUTH event, so ignore the event from NL80211.
3096 */
3097 drv->ignore_next_local_deauth = ret == 0;
3098 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003099}
3100
3101
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003102static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
3103 struct wpa_driver_auth_params *params)
3104{
3105 int i;
3106
3107 drv->auth_freq = params->freq;
3108 drv->auth_alg = params->auth_alg;
3109 drv->auth_wep_tx_keyidx = params->wep_tx_keyidx;
3110 drv->auth_local_state_change = params->local_state_change;
3111 drv->auth_p2p = params->p2p;
3112
3113 if (params->bssid)
3114 os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);
3115 else
3116 os_memset(drv->auth_bssid_, 0, ETH_ALEN);
3117
3118 if (params->ssid) {
3119 os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);
3120 drv->auth_ssid_len = params->ssid_len;
3121 } else
3122 drv->auth_ssid_len = 0;
3123
3124
3125 os_free(drv->auth_ie);
3126 drv->auth_ie = NULL;
3127 drv->auth_ie_len = 0;
3128 if (params->ie) {
3129 drv->auth_ie = os_malloc(params->ie_len);
3130 if (drv->auth_ie) {
3131 os_memcpy(drv->auth_ie, params->ie, params->ie_len);
3132 drv->auth_ie_len = params->ie_len;
3133 }
3134 }
3135
3136 for (i = 0; i < 4; i++) {
3137 if (params->wep_key[i] && params->wep_key_len[i] &&
3138 params->wep_key_len[i] <= 16) {
3139 os_memcpy(drv->auth_wep_key[i], params->wep_key[i],
3140 params->wep_key_len[i]);
3141 drv->auth_wep_key_len[i] = params->wep_key_len[i];
3142 } else
3143 drv->auth_wep_key_len[i] = 0;
3144 }
3145}
3146
3147
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003148static void nl80211_unmask_11b_rates(struct i802_bss *bss)
3149{
3150 struct wpa_driver_nl80211_data *drv = bss->drv;
3151
3152 if (is_p2p_net_interface(drv->nlmode) || !drv->disabled_11b_rates)
3153 return;
3154
3155 /*
3156 * Looks like we failed to unmask 11b rates previously. This could
3157 * happen, e.g., if the interface was down at the point in time when a
3158 * P2P group was terminated.
3159 */
3160 wpa_printf(MSG_DEBUG,
3161 "nl80211: Interface %s mode is for non-P2P, but 11b rates were disabled - re-enable them",
3162 bss->ifname);
3163 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
3164}
3165
3166
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003167static enum nl80211_auth_type get_nl_auth_type(int wpa_auth_alg)
3168{
3169 if (wpa_auth_alg & WPA_AUTH_ALG_OPEN)
3170 return NL80211_AUTHTYPE_OPEN_SYSTEM;
3171 if (wpa_auth_alg & WPA_AUTH_ALG_SHARED)
3172 return NL80211_AUTHTYPE_SHARED_KEY;
3173 if (wpa_auth_alg & WPA_AUTH_ALG_LEAP)
3174 return NL80211_AUTHTYPE_NETWORK_EAP;
3175 if (wpa_auth_alg & WPA_AUTH_ALG_FT)
3176 return NL80211_AUTHTYPE_FT;
3177 if (wpa_auth_alg & WPA_AUTH_ALG_SAE)
3178 return NL80211_AUTHTYPE_SAE;
3179 if (wpa_auth_alg & WPA_AUTH_ALG_FILS)
3180 return NL80211_AUTHTYPE_FILS_SK;
3181 if (wpa_auth_alg & WPA_AUTH_ALG_FILS_SK_PFS)
3182 return NL80211_AUTHTYPE_FILS_SK_PFS;
3183
3184 return NL80211_AUTHTYPE_MAX;
3185}
3186
3187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003188static int wpa_driver_nl80211_authenticate(
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003189 struct i802_bss *bss, struct wpa_driver_auth_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003190{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003191 struct wpa_driver_nl80211_data *drv = bss->drv;
3192 int ret = -1, i;
3193 struct nl_msg *msg;
3194 enum nl80211_auth_type type;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003195 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003196 int count = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003197 int is_retry;
3198
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003199 nl80211_unmask_11b_rates(bss);
3200
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003201 is_retry = drv->retry_auth;
3202 drv->retry_auth = 0;
Dmitry Shmidt98660862014-03-11 17:26:21 -07003203 drv->ignore_deauth_event = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003204
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003205 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003206 os_memset(drv->auth_bssid, 0, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003207 if (params->bssid)
3208 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
3209 else
3210 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003211 /* FIX: IBSS mode */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003212 nlmode = params->p2p ?
3213 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
3214 if (drv->nlmode != nlmode &&
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003215 wpa_driver_nl80211_set_mode(bss, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003216 return -1;
3217
3218retry:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003219 wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
3220 drv->ifindex);
3221
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003222 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_AUTHENTICATE);
3223 if (!msg)
3224 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003225
3226 for (i = 0; i < 4; i++) {
3227 if (!params->wep_key[i])
3228 continue;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003229 wpa_driver_nl80211_set_key(bss->ifname, bss, WPA_ALG_WEP,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003230 NULL, i,
3231 i == params->wep_tx_keyidx, NULL, 0,
3232 params->wep_key[i],
3233 params->wep_key_len[i]);
3234 if (params->wep_tx_keyidx != i)
3235 continue;
3236 if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003237 params->wep_key[i], params->wep_key_len[i]))
3238 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003239 }
3240
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003241 if (params->bssid) {
3242 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
3243 MAC2STR(params->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003244 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
3245 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003246 }
3247 if (params->freq) {
3248 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003249 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq))
3250 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003251 }
3252 if (params->ssid) {
3253 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
3254 params->ssid, params->ssid_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003255 if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len,
3256 params->ssid))
3257 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003258 }
3259 wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003260 if (params->ie &&
3261 nla_put(msg, NL80211_ATTR_IE, params->ie_len, params->ie))
3262 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003263 if (params->auth_data) {
3264 wpa_hexdump(MSG_DEBUG, " * auth_data", params->auth_data,
3265 params->auth_data_len);
3266 if (nla_put(msg, NL80211_ATTR_SAE_DATA, params->auth_data_len,
3267 params->auth_data))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003268 goto fail;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003269 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003270 type = get_nl_auth_type(params->auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003271 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003272 if (type == NL80211_AUTHTYPE_MAX ||
3273 nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003274 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003275 if (params->local_state_change) {
3276 wpa_printf(MSG_DEBUG, " * Local state change only");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003277 if (nla_put_flag(msg, NL80211_ATTR_LOCAL_STATE_CHANGE))
3278 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003279 }
3280
3281 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
3282 msg = NULL;
3283 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003284 wpa_dbg(drv->ctx, MSG_DEBUG,
3285 "nl80211: MLME command failed (auth): ret=%d (%s)",
3286 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003287 count++;
3288 if (ret == -EALREADY && count == 1 && params->bssid &&
3289 !params->local_state_change) {
3290 /*
3291 * mac80211 does not currently accept new
3292 * authentication if we are already authenticated. As a
3293 * workaround, force deauthentication and try again.
3294 */
3295 wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
3296 "after forced deauthentication");
Dmitry Shmidt98660862014-03-11 17:26:21 -07003297 drv->ignore_deauth_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298 wpa_driver_nl80211_deauthenticate(
3299 bss, params->bssid,
3300 WLAN_REASON_PREV_AUTH_NOT_VALID);
3301 nlmsg_free(msg);
3302 goto retry;
3303 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003304
3305 if (ret == -ENOENT && params->freq && !is_retry) {
3306 /*
3307 * cfg80211 has likely expired the BSS entry even
3308 * though it was previously available in our internal
3309 * BSS table. To recover quickly, start a single
3310 * channel scan on the specified channel.
3311 */
3312 struct wpa_driver_scan_params scan;
3313 int freqs[2];
3314
3315 os_memset(&scan, 0, sizeof(scan));
3316 scan.num_ssids = 1;
3317 if (params->ssid) {
3318 scan.ssids[0].ssid = params->ssid;
3319 scan.ssids[0].ssid_len = params->ssid_len;
3320 }
3321 freqs[0] = params->freq;
3322 freqs[1] = 0;
3323 scan.freqs = freqs;
3324 wpa_printf(MSG_DEBUG, "nl80211: Trigger single "
3325 "channel scan to refresh cfg80211 BSS "
3326 "entry");
3327 ret = wpa_driver_nl80211_scan(bss, &scan);
3328 if (ret == 0) {
3329 nl80211_copy_auth_params(drv, params);
3330 drv->scan_for_auth = 1;
3331 }
3332 } else if (is_retry) {
3333 /*
3334 * Need to indicate this with an event since the return
3335 * value from the retry is not delivered to core code.
3336 */
3337 union wpa_event_data event;
3338 wpa_printf(MSG_DEBUG, "nl80211: Authentication retry "
3339 "failed");
3340 os_memset(&event, 0, sizeof(event));
3341 os_memcpy(event.timeout_event.addr, drv->auth_bssid_,
3342 ETH_ALEN);
3343 wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,
3344 &event);
3345 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003346 } else {
3347 wpa_printf(MSG_DEBUG,
3348 "nl80211: Authentication request send successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003349 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003350
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003351fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003352 nlmsg_free(msg);
3353 return ret;
3354}
3355
3356
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003357int wpa_driver_nl80211_authenticate_retry(struct wpa_driver_nl80211_data *drv)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003358{
3359 struct wpa_driver_auth_params params;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003360 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003361 int i;
3362
3363 wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
3364
3365 os_memset(&params, 0, sizeof(params));
3366 params.freq = drv->auth_freq;
3367 params.auth_alg = drv->auth_alg;
3368 params.wep_tx_keyidx = drv->auth_wep_tx_keyidx;
3369 params.local_state_change = drv->auth_local_state_change;
3370 params.p2p = drv->auth_p2p;
3371
3372 if (!is_zero_ether_addr(drv->auth_bssid_))
3373 params.bssid = drv->auth_bssid_;
3374
3375 if (drv->auth_ssid_len) {
3376 params.ssid = drv->auth_ssid;
3377 params.ssid_len = drv->auth_ssid_len;
3378 }
3379
3380 params.ie = drv->auth_ie;
3381 params.ie_len = drv->auth_ie_len;
3382
3383 for (i = 0; i < 4; i++) {
3384 if (drv->auth_wep_key_len[i]) {
3385 params.wep_key[i] = drv->auth_wep_key[i];
3386 params.wep_key_len[i] = drv->auth_wep_key_len[i];
3387 }
3388 }
3389
3390 drv->retry_auth = 1;
3391 return wpa_driver_nl80211_authenticate(bss, &params);
3392}
3393
3394
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003395static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
3396 const void *data, size_t len,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003397 int encrypt, int noack,
3398 unsigned int freq, int no_cck,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003399 int offchanok, unsigned int wait_time,
3400 const u16 *csa_offs,
3401 size_t csa_offs_len)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003402{
3403 struct wpa_driver_nl80211_data *drv = bss->drv;
3404 u64 cookie;
Dmitry Shmidt051af732013-10-22 13:52:46 -07003405 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003406
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07003407 if (freq == 0 && drv->nlmode == NL80211_IFTYPE_ADHOC) {
3408 freq = nl80211_get_assoc_freq(drv);
3409 wpa_printf(MSG_DEBUG,
3410 "nl80211: send_frame - Use assoc_freq=%u for IBSS",
3411 freq);
3412 }
Dmitry Shmidt56052862013-10-04 10:23:25 -07003413 if (freq == 0) {
3414 wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u",
3415 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003416 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07003417 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003418
Dmitry Shmidt56052862013-10-04 10:23:25 -07003419 if (drv->use_monitor) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003420 wpa_printf(MSG_DEBUG, "nl80211: send_frame(freq=%u bss->freq=%u) -> send_monitor",
Dmitry Shmidt56052862013-10-04 10:23:25 -07003421 freq, bss->freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003422 return nl80211_send_monitor(drv, data, len, encrypt, noack);
Dmitry Shmidt56052862013-10-04 10:23:25 -07003423 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003424
Dmitry Shmidt56052862013-10-04 10:23:25 -07003425 wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
Dmitry Shmidt051af732013-10-22 13:52:46 -07003426 res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003427 &cookie, no_cck, noack, offchanok,
3428 csa_offs, csa_offs_len);
Dmitry Shmidt051af732013-10-22 13:52:46 -07003429 if (res == 0 && !noack) {
3430 const struct ieee80211_mgmt *mgmt;
3431 u16 fc;
3432
3433 mgmt = (const struct ieee80211_mgmt *) data;
3434 fc = le_to_host16(mgmt->frame_control);
3435 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
3436 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
3437 wpa_printf(MSG_MSGDUMP,
3438 "nl80211: Update send_action_cookie from 0x%llx to 0x%llx",
3439 (long long unsigned int)
3440 drv->send_action_cookie,
3441 (long long unsigned int) cookie);
3442 drv->send_action_cookie = cookie;
3443 }
3444 }
3445
3446 return res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003447}
3448
3449
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003450static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
3451 size_t data_len, int noack,
3452 unsigned int freq, int no_cck,
3453 int offchanok,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003454 unsigned int wait_time,
3455 const u16 *csa_offs,
3456 size_t csa_offs_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003457{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003458 struct wpa_driver_nl80211_data *drv = bss->drv;
3459 struct ieee80211_mgmt *mgmt;
3460 int encrypt = 1;
3461 u16 fc;
3462
3463 mgmt = (struct ieee80211_mgmt *) data;
3464 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003465 wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR
3466 " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x (%s) nlmode=%d",
3467 MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time,
3468 fc, fc2str(fc), drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003469
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003470 if ((is_sta_interface(drv->nlmode) ||
3471 drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003472 WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
3473 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
3474 /*
3475 * The use of last_mgmt_freq is a bit of a hack,
3476 * but it works due to the single-threaded nature
3477 * of wpa_supplicant.
3478 */
Dmitry Shmidt56052862013-10-04 10:23:25 -07003479 if (freq == 0) {
3480 wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d",
3481 drv->last_mgmt_freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003482 freq = drv->last_mgmt_freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07003483 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003484 return nl80211_send_frame_cmd(bss, freq, 0,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003485 data, data_len, NULL, 1, noack,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003486 1, csa_offs, csa_offs_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003487 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003488
3489 if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
Dmitry Shmidt56052862013-10-04 10:23:25 -07003490 if (freq == 0) {
3491 wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d",
3492 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003493 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07003494 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003495 return nl80211_send_frame_cmd(bss, freq,
3496 (int) freq == bss->freq ? 0 :
3497 wait_time,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003498 data, data_len,
3499 &drv->send_action_cookie,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003500 no_cck, noack, offchanok,
3501 csa_offs, csa_offs_len);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07003502 }
Dmitry Shmidtb638fe72012-03-20 12:51:25 -07003503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003504 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
3505 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {
3506 /*
3507 * Only one of the authentication frame types is encrypted.
3508 * In order for static WEP encryption to work properly (i.e.,
3509 * to not encrypt the frame), we need to tell mac80211 about
3510 * the frames that must not be encrypted.
3511 */
3512 u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
3513 u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);
3514 if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)
3515 encrypt = 0;
3516 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003517
Dmitry Shmidt56052862013-10-04 10:23:25 -07003518 wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003519 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003520 noack, freq, no_cck, offchanok,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003521 wait_time, csa_offs,
3522 csa_offs_len);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003523}
3524
3525
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003526static int nl80211_put_basic_rates(struct nl_msg *msg, const int *basic_rates)
3527{
3528 u8 rates[NL80211_MAX_SUPP_RATES];
3529 u8 rates_len = 0;
3530 int i;
3531
3532 if (!basic_rates)
3533 return 0;
3534
3535 for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++)
3536 rates[rates_len++] = basic_rates[i] / 5;
3537
3538 return nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
3539}
3540
3541
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003542static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
3543 int slot, int ht_opmode, int ap_isolate,
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003544 const int *basic_rates)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003545{
3546 struct wpa_driver_nl80211_data *drv = bss->drv;
3547 struct nl_msg *msg;
3548
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003549 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_BSS)) ||
3550 (cts >= 0 &&
3551 nla_put_u8(msg, NL80211_ATTR_BSS_CTS_PROT, cts)) ||
3552 (preamble >= 0 &&
3553 nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble)) ||
3554 (slot >= 0 &&
3555 nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot)) ||
3556 (ht_opmode >= 0 &&
3557 nla_put_u16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode)) ||
3558 (ap_isolate >= 0 &&
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003559 nla_put_u8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate)) ||
3560 nl80211_put_basic_rates(msg, basic_rates)) {
3561 nlmsg_free(msg);
3562 return -ENOBUFS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003563 }
3564
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003565 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003566}
3567
3568
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003569static int wpa_driver_nl80211_set_acl(void *priv,
3570 struct hostapd_acl_params *params)
3571{
3572 struct i802_bss *bss = priv;
3573 struct wpa_driver_nl80211_data *drv = bss->drv;
3574 struct nl_msg *msg;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003575 struct nl_msg *acl;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003576 unsigned int i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003577 int ret;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003578
3579 if (!(drv->capa.max_acl_mac_addrs))
3580 return -ENOTSUP;
3581
3582 if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
3583 return -ENOTSUP;
3584
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003585 wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
3586 params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
3587
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003588 acl = nlmsg_alloc();
3589 if (!acl)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003590 return -ENOMEM;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003591 for (i = 0; i < params->num_mac_acl; i++) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003592 if (nla_put(acl, i + 1, ETH_ALEN, params->mac_acl[i].addr)) {
3593 nlmsg_free(acl);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003594 return -ENOMEM;
3595 }
3596 }
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003597
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003598 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MAC_ACL)) ||
3599 nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
3600 NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
3601 NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) ||
3602 nla_put_nested(msg, NL80211_ATTR_MAC_ADDRS, acl)) {
3603 nlmsg_free(msg);
3604 nlmsg_free(acl);
3605 return -ENOMEM;
3606 }
3607 nlmsg_free(acl);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003608
3609 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003610 if (ret) {
3611 wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
3612 ret, strerror(-ret));
3613 }
3614
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003615 return ret;
3616}
3617
3618
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003619static int nl80211_put_beacon_int(struct nl_msg *msg, int beacon_int)
3620{
3621 if (beacon_int > 0) {
3622 wpa_printf(MSG_DEBUG, " * beacon_int=%d", beacon_int);
3623 return nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL,
3624 beacon_int);
3625 }
3626
3627 return 0;
3628}
3629
3630
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003631static int nl80211_put_dtim_period(struct nl_msg *msg, int dtim_period)
3632{
3633 if (dtim_period > 0) {
3634 wpa_printf(MSG_DEBUG, " * dtim_period=%d", dtim_period);
3635 return nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period);
3636 }
3637
3638 return 0;
3639}
3640
3641
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003642#ifdef CONFIG_MESH
3643static int nl80211_set_mesh_config(void *priv,
3644 struct wpa_driver_mesh_bss_params *params)
3645{
3646 struct i802_bss *bss = priv;
3647 struct wpa_driver_nl80211_data *drv = bss->drv;
3648 struct nl_msg *msg;
3649 int ret;
3650
3651 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MESH_CONFIG);
3652 if (!msg)
3653 return -1;
3654
3655 ret = nl80211_put_mesh_config(msg, params);
3656 if (ret < 0) {
3657 nlmsg_free(msg);
3658 return ret;
3659 }
3660
3661 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
3662 if (ret) {
3663 wpa_printf(MSG_ERROR,
3664 "nl80211: Mesh config set failed: %d (%s)",
3665 ret, strerror(-ret));
3666 return ret;
3667 }
3668 return 0;
3669}
3670#endif /* CONFIG_MESH */
3671
3672
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08003673static int nl80211_put_beacon_rate(struct nl_msg *msg, const u64 flags,
3674 struct wpa_driver_ap_params *params)
3675{
3676 struct nlattr *bands, *band;
3677 struct nl80211_txrate_vht vht_rate;
3678
3679 if (!params->freq ||
3680 (params->beacon_rate == 0 &&
3681 params->rate_type == BEACON_RATE_LEGACY))
3682 return 0;
3683
3684 bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
3685 if (!bands)
3686 return -1;
3687
3688 switch (params->freq->mode) {
3689 case HOSTAPD_MODE_IEEE80211B:
3690 case HOSTAPD_MODE_IEEE80211G:
3691 band = nla_nest_start(msg, NL80211_BAND_2GHZ);
3692 break;
3693 case HOSTAPD_MODE_IEEE80211A:
3694 band = nla_nest_start(msg, NL80211_BAND_5GHZ);
3695 break;
3696 case HOSTAPD_MODE_IEEE80211AD:
3697 band = nla_nest_start(msg, NL80211_BAND_60GHZ);
3698 break;
3699 default:
3700 return 0;
3701 }
3702
3703 if (!band)
3704 return -1;
3705
3706 os_memset(&vht_rate, 0, sizeof(vht_rate));
3707
3708 switch (params->rate_type) {
3709 case BEACON_RATE_LEGACY:
3710 if (!(flags & WPA_DRIVER_FLAGS_BEACON_RATE_LEGACY)) {
3711 wpa_printf(MSG_INFO,
3712 "nl80211: Driver does not support setting Beacon frame rate (legacy)");
3713 return -1;
3714 }
3715
3716 if (nla_put_u8(msg, NL80211_TXRATE_LEGACY,
3717 (u8) params->beacon_rate / 5) ||
3718 nla_put(msg, NL80211_TXRATE_HT, 0, NULL) ||
3719 (params->freq->vht_enabled &&
3720 nla_put(msg, NL80211_TXRATE_VHT, sizeof(vht_rate),
3721 &vht_rate)))
3722 return -1;
3723
3724 wpa_printf(MSG_DEBUG, " * beacon_rate = legacy:%u (* 100 kbps)",
3725 params->beacon_rate);
3726 break;
3727 case BEACON_RATE_HT:
3728 if (!(flags & WPA_DRIVER_FLAGS_BEACON_RATE_HT)) {
3729 wpa_printf(MSG_INFO,
3730 "nl80211: Driver does not support setting Beacon frame rate (HT)");
3731 return -1;
3732 }
3733 if (nla_put(msg, NL80211_TXRATE_LEGACY, 0, NULL) ||
3734 nla_put_u8(msg, NL80211_TXRATE_HT, params->beacon_rate) ||
3735 (params->freq->vht_enabled &&
3736 nla_put(msg, NL80211_TXRATE_VHT, sizeof(vht_rate),
3737 &vht_rate)))
3738 return -1;
3739 wpa_printf(MSG_DEBUG, " * beacon_rate = HT-MCS %u",
3740 params->beacon_rate);
3741 break;
3742 case BEACON_RATE_VHT:
3743 if (!(flags & WPA_DRIVER_FLAGS_BEACON_RATE_VHT)) {
3744 wpa_printf(MSG_INFO,
3745 "nl80211: Driver does not support setting Beacon frame rate (VHT)");
3746 return -1;
3747 }
3748 vht_rate.mcs[0] = BIT(params->beacon_rate);
3749 if (nla_put(msg, NL80211_TXRATE_LEGACY, 0, NULL))
3750 return -1;
3751 if (nla_put(msg, NL80211_TXRATE_HT, 0, NULL))
3752 return -1;
3753 if (nla_put(msg, NL80211_TXRATE_VHT, sizeof(vht_rate),
3754 &vht_rate))
3755 return -1;
3756 wpa_printf(MSG_DEBUG, " * beacon_rate = VHT-MCS %u",
3757 params->beacon_rate);
3758 break;
3759 }
3760
3761 nla_nest_end(msg, band);
3762 nla_nest_end(msg, bands);
3763
3764 return 0;
3765}
3766
3767
3768static int nl80211_set_multicast_to_unicast(struct i802_bss *bss,
3769 int multicast_to_unicast)
3770{
3771 struct wpa_driver_nl80211_data *drv = bss->drv;
3772 struct nl_msg *msg;
3773 int ret;
3774
3775 msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_MULTICAST_TO_UNICAST);
3776 if (!msg ||
3777 (multicast_to_unicast &&
3778 nla_put_flag(msg, NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED))) {
3779 wpa_printf(MSG_ERROR,
3780 "nl80211: Failed to build NL80211_CMD_SET_MULTICAST_TO_UNICAST msg for %s",
3781 bss->ifname);
3782 nlmsg_free(msg);
3783 return -ENOBUFS;
3784 }
3785
3786 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
3787
3788 switch (ret) {
3789 case 0:
3790 wpa_printf(MSG_DEBUG,
3791 "nl80211: multicast to unicast %s on interface %s",
3792 multicast_to_unicast ? "enabled" : "disabled",
3793 bss->ifname);
3794 break;
3795 case -EOPNOTSUPP:
3796 if (!multicast_to_unicast)
3797 break;
3798 wpa_printf(MSG_INFO,
3799 "nl80211: multicast to unicast not supported on interface %s",
3800 bss->ifname);
3801 break;
3802 default:
3803 wpa_printf(MSG_ERROR,
3804 "nl80211: %s multicast to unicast failed with %d (%s) on interface %s",
3805 multicast_to_unicast ? "enabling" : "disabling",
3806 ret, strerror(-ret), bss->ifname);
3807 break;
3808 }
3809
3810 return ret;
3811}
3812
3813
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003814static int wpa_driver_nl80211_set_ap(void *priv,
3815 struct wpa_driver_ap_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003816{
3817 struct i802_bss *bss = priv;
3818 struct wpa_driver_nl80211_data *drv = bss->drv;
3819 struct nl_msg *msg;
3820 u8 cmd = NL80211_CMD_NEW_BEACON;
3821 int ret;
3822 int beacon_set;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003823 int num_suites;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003824 int smps_mode;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003825 u32 suites[10], suite;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003826 u32 ver;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003827#ifdef CONFIG_MESH
3828 struct wpa_driver_mesh_bss_params mesh_params;
3829#endif /* CONFIG_MESH */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003830
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003831 beacon_set = params->reenable ? 0 : bss->beacon_set;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003833 wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
3834 beacon_set);
3835 if (beacon_set)
3836 cmd = NL80211_CMD_SET_BEACON;
Paul Stewart092955c2017-02-06 09:13:09 -08003837 else if (!drv->device_ap_sme && !drv->use_monitor &&
3838 !nl80211_get_wiphy_data_ap(bss))
3839 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003840
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003841 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
3842 params->head, params->head_len);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003843 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon tail",
3844 params->tail, params->tail_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003845 wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", bss->ifindex);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003846 wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int);
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08003847 wpa_printf(MSG_DEBUG, "nl80211: beacon_rate=%u", params->beacon_rate);
3848 wpa_printf(MSG_DEBUG, "nl80211: rate_type=%d", params->rate_type);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003849 wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003850 wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid",
3851 params->ssid, params->ssid_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003852 if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
3853 nla_put(msg, NL80211_ATTR_BEACON_HEAD, params->head_len,
3854 params->head) ||
3855 nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len,
3856 params->tail) ||
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003857 nl80211_put_beacon_int(msg, params->beacon_int) ||
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08003858 nl80211_put_beacon_rate(msg, drv->capa.flags, params) ||
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003859 nl80211_put_dtim_period(msg, params->dtim_period) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003860 nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
3861 goto fail;
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003862 if (params->proberesp && params->proberesp_len) {
3863 wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)",
3864 params->proberesp, params->proberesp_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003865 if (nla_put(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
3866 params->proberesp))
3867 goto fail;
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003868 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003869 switch (params->hide_ssid) {
3870 case NO_SSID_HIDING:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003871 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID not in use");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003872 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
3873 NL80211_HIDDEN_SSID_NOT_IN_USE))
3874 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003875 break;
3876 case HIDDEN_SSID_ZERO_LEN:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003877 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero len");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003878 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
3879 NL80211_HIDDEN_SSID_ZERO_LEN))
3880 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003881 break;
3882 case HIDDEN_SSID_ZERO_CONTENTS:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003883 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero contents");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003884 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
3885 NL80211_HIDDEN_SSID_ZERO_CONTENTS))
3886 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003887 break;
3888 }
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003889 wpa_printf(MSG_DEBUG, "nl80211: privacy=%d", params->privacy);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003890 if (params->privacy &&
3891 nla_put_flag(msg, NL80211_ATTR_PRIVACY))
3892 goto fail;
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003893 wpa_printf(MSG_DEBUG, "nl80211: auth_algs=0x%x", params->auth_algs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003894 if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
3895 (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
3896 /* Leave out the attribute */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003897 } else if (params->auth_algs & WPA_AUTH_ALG_SHARED) {
3898 if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE,
3899 NL80211_AUTHTYPE_SHARED_KEY))
3900 goto fail;
3901 } else {
3902 if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE,
3903 NL80211_AUTHTYPE_OPEN_SYSTEM))
3904 goto fail;
3905 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003906
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003907 wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003908 ver = 0;
3909 if (params->wpa_version & WPA_PROTO_WPA)
3910 ver |= NL80211_WPA_VERSION_1;
3911 if (params->wpa_version & WPA_PROTO_RSN)
3912 ver |= NL80211_WPA_VERSION_2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003913 if (ver &&
3914 nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver))
3915 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003916
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003917 wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x",
3918 params->key_mgmt_suites);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003919 num_suites = 0;
3920 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
Paul Stewart092955c2017-02-06 09:13:09 -08003921 suites[num_suites++] = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003922 if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
Paul Stewart092955c2017-02-06 09:13:09 -08003923 suites[num_suites++] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003924 if (num_suites &&
3925 nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32),
3926 suites))
3927 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003928
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003929 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003930 (!params->pairwise_ciphers ||
3931 params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) &&
3932 (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
3933 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003934 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003935
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003936 wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
3937 params->pairwise_ciphers);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003938 num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers,
3939 suites, ARRAY_SIZE(suites));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003940 if (num_suites &&
3941 nla_put(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
3942 num_suites * sizeof(u32), suites))
3943 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003944
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003945 wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x",
3946 params->group_cipher);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003947 suite = wpa_cipher_to_cipher_suite(params->group_cipher);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003948 if (suite &&
3949 nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite))
3950 goto fail;
3951
Dmitry Shmidte4663042016-04-04 10:07:49 -07003952 if (params->ht_opmode != -1) {
3953 switch (params->smps_mode) {
3954 case HT_CAP_INFO_SMPS_DYNAMIC:
3955 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - dynamic");
3956 smps_mode = NL80211_SMPS_DYNAMIC;
3957 break;
3958 case HT_CAP_INFO_SMPS_STATIC:
3959 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - static");
3960 smps_mode = NL80211_SMPS_STATIC;
3961 break;
3962 default:
3963 /* invalid - fallback to smps off */
3964 case HT_CAP_INFO_SMPS_DISABLED:
3965 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - off");
3966 smps_mode = NL80211_SMPS_OFF;
3967 break;
3968 }
3969 if (nla_put_u32(msg, NL80211_ATTR_SMPS_MODE, smps_mode))
3970 goto fail;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003971 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003972
3973 if (params->beacon_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003974 wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
3975 params->beacon_ies);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003976 if (nla_put(msg, NL80211_ATTR_IE,
3977 wpabuf_len(params->beacon_ies),
3978 wpabuf_head(params->beacon_ies)))
3979 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003980 }
3981 if (params->proberesp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003982 wpa_hexdump_buf(MSG_DEBUG, "nl80211: proberesp_ies",
3983 params->proberesp_ies);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003984 if (nla_put(msg, NL80211_ATTR_IE_PROBE_RESP,
3985 wpabuf_len(params->proberesp_ies),
3986 wpabuf_head(params->proberesp_ies)))
3987 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003988 }
3989 if (params->assocresp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003990 wpa_hexdump_buf(MSG_DEBUG, "nl80211: assocresp_ies",
3991 params->assocresp_ies);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003992 if (nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP,
3993 wpabuf_len(params->assocresp_ies),
3994 wpabuf_head(params->assocresp_ies)))
3995 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003996 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003997
Dmitry Shmidt04949592012-07-19 12:16:46 -07003998 if (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003999 wpa_printf(MSG_DEBUG, "nl80211: ap_max_inactivity=%d",
4000 params->ap_max_inactivity);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004001 if (nla_put_u16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT,
4002 params->ap_max_inactivity))
4003 goto fail;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004004 }
4005
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004006#ifdef CONFIG_P2P
4007 if (params->p2p_go_ctwindow > 0) {
4008 if (drv->p2p_go_ctwindow_supported) {
4009 wpa_printf(MSG_DEBUG, "nl80211: P2P GO ctwindow=%d",
4010 params->p2p_go_ctwindow);
4011 if (nla_put_u8(msg, NL80211_ATTR_P2P_CTWINDOW,
4012 params->p2p_go_ctwindow))
4013 goto fail;
4014 } else {
4015 wpa_printf(MSG_INFO,
4016 "nl80211: Driver does not support CTWindow configuration - ignore this parameter");
4017 }
4018 }
4019#endif /* CONFIG_P2P */
4020
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004021 if (params->pbss) {
4022 wpa_printf(MSG_DEBUG, "nl80211: PBSS");
4023 if (nla_put_flag(msg, NL80211_ATTR_PBSS))
4024 goto fail;
4025 }
4026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004027 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4028 if (ret) {
4029 wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
4030 ret, strerror(-ret));
4031 } else {
4032 bss->beacon_set = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004033 nl80211_set_bss(bss, params->cts_protect, params->preamble,
4034 params->short_slot_time, params->ht_opmode,
4035 params->isolate, params->basic_rates);
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08004036 nl80211_set_multicast_to_unicast(bss,
4037 params->multicast_to_unicast);
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004038 if (beacon_set && params->freq &&
4039 params->freq->bandwidth != bss->bandwidth) {
4040 wpa_printf(MSG_DEBUG,
4041 "nl80211: Update BSS %s bandwidth: %d -> %d",
4042 bss->ifname, bss->bandwidth,
4043 params->freq->bandwidth);
4044 ret = nl80211_set_channel(bss, params->freq, 1);
4045 if (ret) {
4046 wpa_printf(MSG_DEBUG,
4047 "nl80211: Frequency set failed: %d (%s)",
4048 ret, strerror(-ret));
4049 } else {
4050 wpa_printf(MSG_DEBUG,
4051 "nl80211: Frequency set succeeded for ht2040 coex");
4052 bss->bandwidth = params->freq->bandwidth;
4053 }
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07004054 } else if (!beacon_set && params->freq) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004055 /*
4056 * cfg80211 updates the driver on frequence change in AP
4057 * mode only at the point when beaconing is started, so
4058 * set the initial value here.
4059 */
4060 bss->bandwidth = params->freq->bandwidth;
4061 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004062 }
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004063
4064#ifdef CONFIG_MESH
4065 if (is_mesh_interface(drv->nlmode) && params->ht_opmode != -1) {
4066 os_memset(&mesh_params, 0, sizeof(mesh_params));
4067 mesh_params.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
4068 mesh_params.ht_opmode = params->ht_opmode;
4069 ret = nl80211_set_mesh_config(priv, &mesh_params);
4070 if (ret < 0)
4071 return ret;
4072 }
4073#endif /* CONFIG_MESH */
4074
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075 return ret;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004076fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004077 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004078 return -ENOBUFS;
4079}
4080
4081
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004082static int nl80211_put_freq_params(struct nl_msg *msg,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004083 const struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004084{
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004085 wpa_printf(MSG_DEBUG, " * freq=%d", freq->freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004086 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
4087 return -ENOBUFS;
4088
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004089 wpa_printf(MSG_DEBUG, " * vht_enabled=%d", freq->vht_enabled);
4090 wpa_printf(MSG_DEBUG, " * ht_enabled=%d", freq->ht_enabled);
4091
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004092 if (freq->vht_enabled) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004093 enum nl80211_chan_width cw;
4094
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004095 wpa_printf(MSG_DEBUG, " * bandwidth=%d", freq->bandwidth);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004096 switch (freq->bandwidth) {
4097 case 20:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004098 cw = NL80211_CHAN_WIDTH_20;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004099 break;
4100 case 40:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004101 cw = NL80211_CHAN_WIDTH_40;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004102 break;
4103 case 80:
4104 if (freq->center_freq2)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004105 cw = NL80211_CHAN_WIDTH_80P80;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004106 else
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004107 cw = NL80211_CHAN_WIDTH_80;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004108 break;
4109 case 160:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004110 cw = NL80211_CHAN_WIDTH_160;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004111 break;
4112 default:
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004113 return -EINVAL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004114 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004115
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004116 wpa_printf(MSG_DEBUG, " * channel_width=%d", cw);
4117 wpa_printf(MSG_DEBUG, " * center_freq1=%d",
4118 freq->center_freq1);
4119 wpa_printf(MSG_DEBUG, " * center_freq2=%d",
4120 freq->center_freq2);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004121 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cw) ||
4122 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1,
4123 freq->center_freq1) ||
4124 (freq->center_freq2 &&
4125 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2,
4126 freq->center_freq2)))
4127 return -ENOBUFS;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004128 } else if (freq->ht_enabled) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004129 enum nl80211_channel_type ct;
4130
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004131 wpa_printf(MSG_DEBUG, " * sec_channel_offset=%d",
4132 freq->sec_channel_offset);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004133 switch (freq->sec_channel_offset) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004134 case -1:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004135 ct = NL80211_CHAN_HT40MINUS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004136 break;
4137 case 1:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004138 ct = NL80211_CHAN_HT40PLUS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004139 break;
4140 default:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004141 ct = NL80211_CHAN_HT20;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004142 break;
4143 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004144
Dmitry Shmidtff787d52015-01-12 13:01:47 -08004145 wpa_printf(MSG_DEBUG, " * channel_type=%d", ct);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004146 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct))
4147 return -ENOBUFS;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07004148 } else {
4149 wpa_printf(MSG_DEBUG, " * channel_type=%d",
4150 NL80211_CHAN_NO_HT);
4151 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
4152 NL80211_CHAN_NO_HT))
4153 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004154 }
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004155 return 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004156}
4157
4158
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004159static int nl80211_set_channel(struct i802_bss *bss,
4160 struct hostapd_freq_params *freq, int set_chan)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004161{
4162 struct wpa_driver_nl80211_data *drv = bss->drv;
4163 struct nl_msg *msg;
4164 int ret;
4165
4166 wpa_printf(MSG_DEBUG,
4167 "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
4168 freq->freq, freq->ht_enabled, freq->vht_enabled,
4169 freq->bandwidth, freq->center_freq1, freq->center_freq2);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004170
4171 msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
4172 NL80211_CMD_SET_WIPHY);
4173 if (!msg || nl80211_put_freq_params(msg, freq) < 0) {
4174 nlmsg_free(msg);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004175 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004176 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004177
4178 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004179 if (ret == 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004180 bss->freq = freq->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004181 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004182 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004183 wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004184 "%d (%s)", freq->freq, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004185 return -1;
4186}
4187
4188
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004189static u32 sta_flags_nl80211(int flags)
4190{
4191 u32 f = 0;
4192
4193 if (flags & WPA_STA_AUTHORIZED)
4194 f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
4195 if (flags & WPA_STA_WMM)
4196 f |= BIT(NL80211_STA_FLAG_WME);
4197 if (flags & WPA_STA_SHORT_PREAMBLE)
4198 f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
4199 if (flags & WPA_STA_MFP)
4200 f |= BIT(NL80211_STA_FLAG_MFP);
4201 if (flags & WPA_STA_TDLS_PEER)
4202 f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004203 if (flags & WPA_STA_AUTHENTICATED)
4204 f |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004205 if (flags & WPA_STA_ASSOCIATED)
4206 f |= BIT(NL80211_STA_FLAG_ASSOCIATED);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004207
4208 return f;
4209}
4210
4211
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004212#ifdef CONFIG_MESH
4213static u32 sta_plink_state_nl80211(enum mesh_plink_state state)
4214{
4215 switch (state) {
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07004216 case PLINK_IDLE:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004217 return NL80211_PLINK_LISTEN;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07004218 case PLINK_OPN_SNT:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004219 return NL80211_PLINK_OPN_SNT;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07004220 case PLINK_OPN_RCVD:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004221 return NL80211_PLINK_OPN_RCVD;
4222 case PLINK_CNF_RCVD:
4223 return NL80211_PLINK_CNF_RCVD;
4224 case PLINK_ESTAB:
4225 return NL80211_PLINK_ESTAB;
4226 case PLINK_HOLDING:
4227 return NL80211_PLINK_HOLDING;
4228 case PLINK_BLOCKED:
4229 return NL80211_PLINK_BLOCKED;
4230 default:
4231 wpa_printf(MSG_ERROR, "nl80211: Invalid mesh plink state %d",
4232 state);
4233 }
4234 return -1;
4235}
4236#endif /* CONFIG_MESH */
4237
4238
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004239static int wpa_driver_nl80211_sta_add(void *priv,
4240 struct hostapd_sta_add_params *params)
4241{
4242 struct i802_bss *bss = priv;
4243 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004244 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004245 struct nl80211_sta_flag_update upd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004246 int ret = -ENOBUFS;
4247
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004248 if ((params->flags & WPA_STA_TDLS_PEER) &&
4249 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
4250 return -EOPNOTSUPP;
4251
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004252 wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR,
4253 params->set ? "Set" : "Add", MAC2STR(params->addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004254 msg = nl80211_bss_msg(bss, 0, params->set ? NL80211_CMD_SET_STATION :
4255 NL80211_CMD_NEW_STATION);
4256 if (!msg || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr))
4257 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004258
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004259 /*
4260 * Set the below properties only in one of the following cases:
4261 * 1. New station is added, already associated.
4262 * 2. Set WPA_STA_TDLS_PEER station.
4263 * 3. Set an already added unassociated station, if driver supports
4264 * full AP client state. (Set these properties after station became
4265 * associated will be rejected by the driver).
4266 */
4267 if (!params->set || (params->flags & WPA_STA_TDLS_PEER) ||
4268 (params->set && FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags) &&
4269 (params->flags & WPA_STA_ASSOCIATED))) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004270 wpa_hexdump(MSG_DEBUG, " * supported rates",
4271 params->supp_rates, params->supp_rates_len);
4272 wpa_printf(MSG_DEBUG, " * capability=0x%x",
4273 params->capability);
4274 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_RATES,
4275 params->supp_rates_len, params->supp_rates) ||
4276 nla_put_u16(msg, NL80211_ATTR_STA_CAPABILITY,
4277 params->capability))
4278 goto fail;
4279
4280 if (params->ht_capabilities) {
4281 wpa_hexdump(MSG_DEBUG, " * ht_capabilities",
4282 (u8 *) params->ht_capabilities,
4283 sizeof(*params->ht_capabilities));
4284 if (nla_put(msg, NL80211_ATTR_HT_CAPABILITY,
4285 sizeof(*params->ht_capabilities),
4286 params->ht_capabilities))
4287 goto fail;
4288 }
4289
4290 if (params->vht_capabilities) {
4291 wpa_hexdump(MSG_DEBUG, " * vht_capabilities",
4292 (u8 *) params->vht_capabilities,
4293 sizeof(*params->vht_capabilities));
4294 if (nla_put(msg, NL80211_ATTR_VHT_CAPABILITY,
4295 sizeof(*params->vht_capabilities),
4296 params->vht_capabilities))
4297 goto fail;
4298 }
4299
4300 if (params->ext_capab) {
4301 wpa_hexdump(MSG_DEBUG, " * ext_capab",
4302 params->ext_capab, params->ext_capab_len);
4303 if (nla_put(msg, NL80211_ATTR_STA_EXT_CAPABILITY,
4304 params->ext_capab_len, params->ext_capab))
4305 goto fail;
4306 }
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004307
4308 if (is_ap_interface(drv->nlmode) &&
4309 nla_put_u8(msg, NL80211_ATTR_STA_SUPPORT_P2P_PS,
4310 params->support_p2p_ps ?
4311 NL80211_P2P_PS_SUPPORTED :
4312 NL80211_P2P_PS_UNSUPPORTED))
4313 goto fail;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004314 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004315 if (!params->set) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004316 if (params->aid) {
4317 wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004318 if (nla_put_u16(msg, NL80211_ATTR_STA_AID, params->aid))
4319 goto fail;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004320 } else {
4321 /*
4322 * cfg80211 validates that AID is non-zero, so we have
4323 * to make this a non-zero value for the TDLS case where
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004324 * a dummy STA entry is used for now and for a station
4325 * that is still not associated.
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004326 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004327 wpa_printf(MSG_DEBUG, " * aid=1 (%s workaround)",
4328 (params->flags & WPA_STA_TDLS_PEER) ?
4329 "TDLS" : "UNASSOC_STA");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004330 if (nla_put_u16(msg, NL80211_ATTR_STA_AID, 1))
4331 goto fail;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07004332 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004333 wpa_printf(MSG_DEBUG, " * listen_interval=%u",
4334 params->listen_interval);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004335 if (nla_put_u16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
4336 params->listen_interval))
4337 goto fail;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004338 } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
4339 wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004340 if (nla_put_u16(msg, NL80211_ATTR_PEER_AID, params->aid))
4341 goto fail;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004342 } else if (FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags) &&
4343 (params->flags & WPA_STA_ASSOCIATED)) {
4344 wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
4345 wpa_printf(MSG_DEBUG, " * listen_interval=%u",
4346 params->listen_interval);
4347 if (nla_put_u16(msg, NL80211_ATTR_STA_AID, params->aid) ||
4348 nla_put_u16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
4349 params->listen_interval))
4350 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004351 }
4352
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08004353 if (params->vht_opmode_enabled) {
4354 wpa_printf(MSG_DEBUG, " * opmode=%u", params->vht_opmode);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004355 if (nla_put_u8(msg, NL80211_ATTR_OPMODE_NOTIF,
4356 params->vht_opmode))
4357 goto fail;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004358 }
4359
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004360 if (params->supp_channels) {
4361 wpa_hexdump(MSG_DEBUG, " * supported channels",
4362 params->supp_channels, params->supp_channels_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004363 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_CHANNELS,
4364 params->supp_channels_len, params->supp_channels))
4365 goto fail;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004366 }
4367
4368 if (params->supp_oper_classes) {
4369 wpa_hexdump(MSG_DEBUG, " * supported operating classes",
4370 params->supp_oper_classes,
4371 params->supp_oper_classes_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004372 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
4373 params->supp_oper_classes_len,
4374 params->supp_oper_classes))
4375 goto fail;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08004376 }
4377
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004378 os_memset(&upd, 0, sizeof(upd));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004379 upd.set = sta_flags_nl80211(params->flags);
4380 upd.mask = upd.set | sta_flags_nl80211(params->flags_mask);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004381
4382 /*
4383 * If the driver doesn't support full AP client state, ignore ASSOC/AUTH
4384 * flags, as nl80211 driver moves a new station, by default, into
4385 * associated state.
4386 *
4387 * On the other hand, if the driver supports that feature and the
4388 * station is added in unauthenticated state, set the
4389 * authenticated/associated bits in the mask to prevent moving this
4390 * station to associated state before it is actually associated.
4391 *
4392 * This is irrelevant for mesh mode where the station is added to the
4393 * driver as authenticated already, and ASSOCIATED isn't part of the
4394 * nl80211 API.
4395 */
4396 if (!is_mesh_interface(drv->nlmode)) {
4397 if (!FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags)) {
4398 wpa_printf(MSG_DEBUG,
4399 "nl80211: Ignore ASSOC/AUTH flags since driver doesn't support full AP client state");
4400 upd.mask &= ~(BIT(NL80211_STA_FLAG_ASSOCIATED) |
4401 BIT(NL80211_STA_FLAG_AUTHENTICATED));
4402 } else if (!params->set &&
4403 !(params->flags & WPA_STA_TDLS_PEER)) {
4404 if (!(params->flags & WPA_STA_AUTHENTICATED))
4405 upd.mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
4406 if (!(params->flags & WPA_STA_ASSOCIATED))
4407 upd.mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
4408 }
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07004409#ifdef CONFIG_MESH
4410 } else {
4411 if (params->plink_state == PLINK_ESTAB && params->peer_aid) {
4412 ret = nla_put_u16(msg, NL80211_ATTR_MESH_PEER_AID,
4413 params->peer_aid);
4414 if (ret)
4415 goto fail;
4416 }
4417#endif /* CONFIG_MESH */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004418 }
4419
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004420 wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x",
4421 upd.set, upd.mask);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004422 if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
4423 goto fail;
4424
4425#ifdef CONFIG_MESH
4426 if (params->plink_state &&
4427 nla_put_u8(msg, NL80211_ATTR_STA_PLINK_STATE,
4428 sta_plink_state_nl80211(params->plink_state)))
4429 goto fail;
4430#endif /* CONFIG_MESH */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004431
4432 if (params->flags & WPA_STA_WMM) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004433 struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME);
4434
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004435 wpa_printf(MSG_DEBUG, " * qosinfo=0x%x", params->qosinfo);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004436 if (!wme ||
4437 nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
4438 params->qosinfo & WMM_QOSINFO_STA_AC_MASK) ||
4439 nla_put_u8(msg, NL80211_STA_WME_MAX_SP,
4440 (params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &
4441 WMM_QOSINFO_STA_SP_MASK))
4442 goto fail;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004443 nla_nest_end(msg, wme);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004444 }
4445
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004446 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004447 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004448 if (ret)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004449 wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
4450 "result: %d (%s)", params->set ? "SET" : "NEW", ret,
4451 strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004452 if (ret == -EEXIST)
4453 ret = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004454fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004455 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004456 return ret;
4457}
4458
4459
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004460static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
4461{
4462#ifdef CONFIG_LIBNL3_ROUTE
4463 struct wpa_driver_nl80211_data *drv = bss->drv;
4464 struct rtnl_neigh *rn;
4465 struct nl_addr *nl_addr;
4466 int err;
4467
4468 rn = rtnl_neigh_alloc();
4469 if (!rn)
4470 return;
4471
4472 rtnl_neigh_set_family(rn, AF_BRIDGE);
4473 rtnl_neigh_set_ifindex(rn, bss->ifindex);
4474 nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
4475 if (!nl_addr) {
4476 rtnl_neigh_put(rn);
4477 return;
4478 }
4479 rtnl_neigh_set_lladdr(rn, nl_addr);
4480
4481 err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
4482 if (err < 0) {
4483 wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
4484 MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
4485 bss->ifindex, nl_geterror(err));
4486 } else {
4487 wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for "
4488 MACSTR, MAC2STR(addr));
4489 }
4490
4491 nl_addr_put(nl_addr);
4492 rtnl_neigh_put(rn);
4493#endif /* CONFIG_LIBNL3_ROUTE */
4494}
4495
4496
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004497static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr,
4498 int deauth, u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004499{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004500 struct wpa_driver_nl80211_data *drv = bss->drv;
4501 struct nl_msg *msg;
4502 int ret;
4503
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004504 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION)) ||
4505 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
4506 (deauth == 0 &&
4507 nla_put_u8(msg, NL80211_ATTR_MGMT_SUBTYPE,
4508 WLAN_FC_STYPE_DISASSOC)) ||
4509 (deauth == 1 &&
4510 nla_put_u8(msg, NL80211_ATTR_MGMT_SUBTYPE,
4511 WLAN_FC_STYPE_DEAUTH)) ||
4512 (reason_code &&
4513 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) {
4514 nlmsg_free(msg);
4515 return -ENOBUFS;
4516 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004517
4518 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004519 wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
4520 " --> %d (%s)",
4521 bss->ifname, MAC2STR(addr), ret, strerror(-ret));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004522
4523 if (drv->rtnl_sk)
4524 rtnl_neigh_delete_fdb_entry(bss, addr);
4525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004526 if (ret == -ENOENT)
4527 return 0;
4528 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004529}
4530
4531
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004532void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004533{
4534 struct nl_msg *msg;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07004535 struct wpa_driver_nl80211_data *drv2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004536
4537 wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx);
4538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004539 /* stop listening for EAPOL on this interface */
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07004540 dl_list_for_each(drv2, &drv->global->interfaces,
4541 struct wpa_driver_nl80211_data, list)
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004542 {
4543 del_ifidx(drv2, ifidx, IFIDX_ANY);
4544 /* Remove all bridges learned for this iface */
4545 del_ifidx(drv2, IFIDX_ANY, ifidx);
4546 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004547
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004548 msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004549 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
4550 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004551 wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
4552}
4553
4554
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07004555const char * nl80211_iftype_str(enum nl80211_iftype mode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004556{
4557 switch (mode) {
4558 case NL80211_IFTYPE_ADHOC:
4559 return "ADHOC";
4560 case NL80211_IFTYPE_STATION:
4561 return "STATION";
4562 case NL80211_IFTYPE_AP:
4563 return "AP";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004564 case NL80211_IFTYPE_AP_VLAN:
4565 return "AP_VLAN";
4566 case NL80211_IFTYPE_WDS:
4567 return "WDS";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004568 case NL80211_IFTYPE_MONITOR:
4569 return "MONITOR";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004570 case NL80211_IFTYPE_MESH_POINT:
4571 return "MESH_POINT";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004572 case NL80211_IFTYPE_P2P_CLIENT:
4573 return "P2P_CLIENT";
4574 case NL80211_IFTYPE_P2P_GO:
4575 return "P2P_GO";
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004576 case NL80211_IFTYPE_P2P_DEVICE:
4577 return "P2P_DEVICE";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004578 default:
4579 return "unknown";
4580 }
4581}
4582
4583
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004584static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
4585 const char *ifname,
4586 enum nl80211_iftype iftype,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004587 const u8 *addr, int wds,
4588 int (*handler)(struct nl_msg *, void *),
4589 void *arg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004590{
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004591 struct nl_msg *msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004592 int ifidx;
4593 int ret = -ENOBUFS;
4594
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004595 wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)",
4596 iftype, nl80211_iftype_str(iftype));
4597
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004598 msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_NEW_INTERFACE);
4599 if (!msg ||
4600 nla_put_string(msg, NL80211_ATTR_IFNAME, ifname) ||
4601 nla_put_u32(msg, NL80211_ATTR_IFTYPE, iftype))
4602 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004603
4604 if (iftype == NL80211_IFTYPE_MONITOR) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004605 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004606
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004607 flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004608 if (!flags ||
4609 nla_put_flag(msg, NL80211_MNTR_FLAG_COOK_FRAMES))
4610 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004611
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004612 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004613 } else if (wds) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004614 if (nla_put_u8(msg, NL80211_ATTR_4ADDR, wds))
4615 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004616 }
4617
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004618 /*
4619 * Tell cfg80211 that the interface belongs to the socket that created
4620 * it, and the interface should be deleted when the socket is closed.
4621 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004622 if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER))
4623 goto fail;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004624
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004625 ret = send_and_recv_msgs(drv, msg, handler, arg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004626 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004627 if (ret) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004628 fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004629 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004630 wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)",
4631 ifname, ret, strerror(-ret));
4632 return ret;
4633 }
4634
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004635 if (iftype == NL80211_IFTYPE_P2P_DEVICE)
4636 return 0;
4637
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004638 ifidx = if_nametoindex(ifname);
4639 wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d",
4640 ifname, ifidx);
4641
4642 if (ifidx <= 0)
4643 return -1;
4644
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07004645 /*
4646 * Some virtual interfaces need to process EAPOL packets and events on
4647 * the parent interface. This is used mainly with hostapd.
4648 */
4649 if (drv->hostapd ||
4650 iftype == NL80211_IFTYPE_AP_VLAN ||
4651 iftype == NL80211_IFTYPE_WDS ||
4652 iftype == NL80211_IFTYPE_MONITOR) {
4653 /* start listening for EAPOL on this interface */
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004654 add_ifidx(drv, ifidx, IFIDX_ANY);
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07004655 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004656
4657 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004658 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004659 nl80211_remove_iface(drv, ifidx);
4660 return -1;
4661 }
4662
4663 return ifidx;
4664}
4665
4666
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004667int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
4668 const char *ifname, enum nl80211_iftype iftype,
4669 const u8 *addr, int wds,
4670 int (*handler)(struct nl_msg *, void *),
4671 void *arg, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004672{
4673 int ret;
4674
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004675 ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler,
4676 arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004677
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004678 /* if error occurred and interface exists already */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004679 if (ret == -ENFILE && if_nametoindex(ifname)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004680 if (use_existing) {
4681 wpa_printf(MSG_DEBUG, "nl80211: Continue using existing interface %s",
4682 ifname);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07004683 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
4684 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
4685 addr) < 0 &&
4686 (linux_set_iface_flags(drv->global->ioctl_sock,
4687 ifname, 0) < 0 ||
4688 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
4689 addr) < 0 ||
4690 linux_set_iface_flags(drv->global->ioctl_sock,
4691 ifname, 1) < 0))
4692 return -1;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004693 return -ENFILE;
4694 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004695 wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname);
4696
4697 /* Try to remove the interface that was already there. */
4698 nl80211_remove_iface(drv, if_nametoindex(ifname));
4699
4700 /* Try to create the interface again */
4701 ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004702 wds, handler, arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004703 }
4704
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004705 if (ret >= 0 && is_p2p_net_interface(iftype)) {
4706 wpa_printf(MSG_DEBUG,
4707 "nl80211: Interface %s created for P2P - disable 11b rates",
4708 ifname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004709 nl80211_disable_11b_rates(drv, ret, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004710 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711
4712 return ret;
4713}
4714
4715
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004716static int nl80211_setup_ap(struct i802_bss *bss)
4717{
4718 struct wpa_driver_nl80211_data *drv = bss->drv;
4719
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004720 wpa_printf(MSG_DEBUG, "nl80211: Setup AP(%s) - device_ap_sme=%d use_monitor=%d",
4721 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004722
4723 /*
4724 * Disable Probe Request reporting unless we need it in this way for
4725 * devices that include the AP SME, in the other case (unless using
4726 * monitor iface) we'll get it through the nl_mgmt socket instead.
4727 */
4728 if (!drv->device_ap_sme)
4729 wpa_driver_nl80211_probe_req_report(bss, 0);
4730
4731 if (!drv->device_ap_sme && !drv->use_monitor)
4732 if (nl80211_mgmt_subscribe_ap(bss))
4733 return -1;
4734
4735 if (drv->device_ap_sme && !drv->use_monitor)
4736 if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004737 wpa_printf(MSG_DEBUG,
4738 "nl80211: Failed to subscribe for mgmt frames from SME driver - trying to run without it");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004739
4740 if (!drv->device_ap_sme && drv->use_monitor &&
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004741 nl80211_create_monitor_interface(drv) &&
4742 !drv->device_ap_sme)
Dmitry Shmidt04949592012-07-19 12:16:46 -07004743 return -1;
4744
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004745 if (drv->device_ap_sme &&
4746 wpa_driver_nl80211_probe_req_report(bss, 1) < 0) {
4747 wpa_printf(MSG_DEBUG, "nl80211: Failed to enable "
4748 "Probe Request frame reporting in AP mode");
4749 /* Try to survive without this */
4750 }
4751
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004752 return 0;
4753}
4754
4755
4756static void nl80211_teardown_ap(struct i802_bss *bss)
4757{
4758 struct wpa_driver_nl80211_data *drv = bss->drv;
4759
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004760 wpa_printf(MSG_DEBUG, "nl80211: Teardown AP(%s) - device_ap_sme=%d use_monitor=%d",
4761 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004762 if (drv->device_ap_sme) {
4763 wpa_driver_nl80211_probe_req_report(bss, 0);
4764 if (!drv->use_monitor)
4765 nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)");
4766 } else if (drv->use_monitor)
4767 nl80211_remove_monitor_interface(drv);
4768 else
4769 nl80211_mgmt_unsubscribe(bss, "AP teardown");
4770
Paul Stewart092955c2017-02-06 09:13:09 -08004771 nl80211_put_wiphy_data_ap(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004772 bss->beacon_set = 0;
4773}
4774
4775
4776static int nl80211_send_eapol_data(struct i802_bss *bss,
4777 const u8 *addr, const u8 *data,
4778 size_t data_len)
4779{
4780 struct sockaddr_ll ll;
4781 int ret;
4782
4783 if (bss->drv->eapol_tx_sock < 0) {
4784 wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL");
4785 return -1;
4786 }
4787
4788 os_memset(&ll, 0, sizeof(ll));
4789 ll.sll_family = AF_PACKET;
4790 ll.sll_ifindex = bss->ifindex;
4791 ll.sll_protocol = htons(ETH_P_PAE);
4792 ll.sll_halen = ETH_ALEN;
4793 os_memcpy(ll.sll_addr, addr, ETH_ALEN);
4794 ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,
4795 (struct sockaddr *) &ll, sizeof(ll));
4796 if (ret < 0)
4797 wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s",
4798 strerror(errno));
4799
4800 return ret;
4801}
4802
4803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004804static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
4805
4806static int wpa_driver_nl80211_hapd_send_eapol(
4807 void *priv, const u8 *addr, const u8 *data,
4808 size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
4809{
4810 struct i802_bss *bss = priv;
4811 struct wpa_driver_nl80211_data *drv = bss->drv;
4812 struct ieee80211_hdr *hdr;
4813 size_t len;
4814 u8 *pos;
4815 int res;
4816 int qos = flags & WPA_STA_WMM;
Dmitry Shmidt641185e2013-11-06 15:17:13 -08004817
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004818 if (drv->device_ap_sme || !drv->use_monitor)
4819 return nl80211_send_eapol_data(bss, addr, data, data_len);
4820
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004821 len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
4822 data_len;
4823 hdr = os_zalloc(len);
4824 if (hdr == NULL) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004825 wpa_printf(MSG_INFO, "nl80211: Failed to allocate EAPOL buffer(len=%lu)",
4826 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004827 return -1;
4828 }
4829
4830 hdr->frame_control =
4831 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
4832 hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
4833 if (encrypt)
4834 hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
4835 if (qos) {
4836 hdr->frame_control |=
4837 host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
4838 }
4839
4840 memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
4841 memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
4842 memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
4843 pos = (u8 *) (hdr + 1);
4844
4845 if (qos) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004846 /* Set highest priority in QoS header */
4847 pos[0] = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004848 pos[1] = 0;
4849 pos += 2;
4850 }
4851
4852 memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
4853 pos += sizeof(rfc1042_header);
4854 WPA_PUT_BE16(pos, ETH_P_PAE);
4855 pos += 2;
4856 memcpy(pos, data, data_len);
4857
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004858 res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004859 0, 0, 0, 0, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004860 if (res < 0) {
4861 wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
4862 "failed: %d (%s)",
4863 (unsigned long) len, errno, strerror(errno));
4864 }
4865 os_free(hdr);
4866
4867 return res;
4868}
4869
4870
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004871static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004872 unsigned int total_flags,
4873 unsigned int flags_or,
4874 unsigned int flags_and)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004875{
4876 struct i802_bss *bss = priv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004877 struct nl_msg *msg;
4878 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004879 struct nl80211_sta_flag_update upd;
4880
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004881 wpa_printf(MSG_DEBUG, "nl80211: Set STA flags - ifname=%s addr=" MACSTR
4882 " total_flags=0x%x flags_or=0x%x flags_and=0x%x authorized=%d",
4883 bss->ifname, MAC2STR(addr), total_flags, flags_or, flags_and,
4884 !!(total_flags & WPA_STA_AUTHORIZED));
4885
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004886 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
4887 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
4888 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004889
4890 /*
4891 * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
4892 * can be removed eventually.
4893 */
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004894 flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004895 if (!flags ||
4896 ((total_flags & WPA_STA_AUTHORIZED) &&
4897 nla_put_flag(msg, NL80211_STA_FLAG_AUTHORIZED)) ||
4898 ((total_flags & WPA_STA_WMM) &&
4899 nla_put_flag(msg, NL80211_STA_FLAG_WME)) ||
4900 ((total_flags & WPA_STA_SHORT_PREAMBLE) &&
4901 nla_put_flag(msg, NL80211_STA_FLAG_SHORT_PREAMBLE)) ||
4902 ((total_flags & WPA_STA_MFP) &&
4903 nla_put_flag(msg, NL80211_STA_FLAG_MFP)) ||
4904 ((total_flags & WPA_STA_TDLS_PEER) &&
4905 nla_put_flag(msg, NL80211_STA_FLAG_TDLS_PEER)))
4906 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004907
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004908 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004909
4910 os_memset(&upd, 0, sizeof(upd));
4911 upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
4912 upd.set = sta_flags_nl80211(flags_or);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004913 if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
4914 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004915
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004916 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
4917fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004918 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004919 return -ENOBUFS;
4920}
4921
4922
4923static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
4924 struct wpa_driver_associate_params *params)
4925{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004926 enum nl80211_iftype nlmode, old_mode;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004927
4928 if (params->p2p) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004929 wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
4930 "group (GO)");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004931 nlmode = NL80211_IFTYPE_P2P_GO;
4932 } else
4933 nlmode = NL80211_IFTYPE_AP;
4934
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004935 old_mode = drv->nlmode;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004936 if (wpa_driver_nl80211_set_mode(drv->first_bss, nlmode)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004937 nl80211_remove_monitor_interface(drv);
4938 return -1;
4939 }
4940
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004941 if (params->freq.freq &&
4942 nl80211_set_channel(drv->first_bss, &params->freq, 0)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004943 if (old_mode != nlmode)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004944 wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004945 nl80211_remove_monitor_interface(drv);
4946 return -1;
4947 }
4948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004949 return 0;
4950}
4951
4952
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004953static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
4954 int reset_mode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004955{
4956 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004957 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004958
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004959 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004960 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004961 if (ret) {
4962 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
4963 "(%s)", ret, strerror(-ret));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004964 } else {
4965 wpa_printf(MSG_DEBUG,
4966 "nl80211: Leave IBSS request sent successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004967 }
4968
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004969 if (reset_mode &&
4970 wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt56052862013-10-04 10:23:25 -07004971 NL80211_IFTYPE_STATION)) {
4972 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
4973 "station mode");
4974 }
4975
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004976 return ret;
4977}
4978
4979
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08004980static int nl80211_ht_vht_overrides(struct nl_msg *msg,
4981 struct wpa_driver_associate_params *params)
4982{
4983 if (params->disable_ht && nla_put_flag(msg, NL80211_ATTR_DISABLE_HT))
4984 return -1;
4985
4986 if (params->htcaps && params->htcaps_mask) {
4987 int sz = sizeof(struct ieee80211_ht_capabilities);
4988 wpa_hexdump(MSG_DEBUG, " * htcaps", params->htcaps, sz);
4989 wpa_hexdump(MSG_DEBUG, " * htcaps_mask",
4990 params->htcaps_mask, sz);
4991 if (nla_put(msg, NL80211_ATTR_HT_CAPABILITY, sz,
4992 params->htcaps) ||
4993 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
4994 params->htcaps_mask))
4995 return -1;
4996 }
4997
4998#ifdef CONFIG_VHT_OVERRIDES
4999 if (params->disable_vht) {
5000 wpa_printf(MSG_DEBUG, " * VHT disabled");
5001 if (nla_put_flag(msg, NL80211_ATTR_DISABLE_VHT))
5002 return -1;
5003 }
5004
5005 if (params->vhtcaps && params->vhtcaps_mask) {
5006 int sz = sizeof(struct ieee80211_vht_capabilities);
5007 wpa_hexdump(MSG_DEBUG, " * vhtcaps", params->vhtcaps, sz);
5008 wpa_hexdump(MSG_DEBUG, " * vhtcaps_mask",
5009 params->vhtcaps_mask, sz);
5010 if (nla_put(msg, NL80211_ATTR_VHT_CAPABILITY, sz,
5011 params->vhtcaps) ||
5012 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
5013 params->vhtcaps_mask))
5014 return -1;
5015 }
5016#endif /* CONFIG_VHT_OVERRIDES */
5017
5018 return 0;
5019}
5020
5021
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005022static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
5023 struct wpa_driver_associate_params *params)
5024{
5025 struct nl_msg *msg;
5026 int ret = -1;
5027 int count = 0;
5028
5029 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
5030
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07005031 if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, &params->freq)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005032 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
5033 "IBSS mode");
5034 return -1;
5035 }
5036
5037retry:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005038 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_IBSS)) ||
5039 params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
5040 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005041
5042 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
5043 params->ssid, params->ssid_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005044 if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
5045 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005046 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
5047 drv->ssid_len = params->ssid_len;
5048
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005049 if (nl80211_put_freq_params(msg, &params->freq) < 0 ||
5050 nl80211_put_beacon_int(msg, params->beacon_int))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005051 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005052
5053 ret = nl80211_set_conn_keys(params, msg);
5054 if (ret)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005055 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005056
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005057 if (params->bssid && params->fixed_bssid) {
5058 wpa_printf(MSG_DEBUG, " * BSSID=" MACSTR,
5059 MAC2STR(params->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005060 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
5061 goto fail;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005062 }
5063
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005064 if (params->fixed_freq) {
5065 wpa_printf(MSG_DEBUG, " * fixed_freq");
5066 if (nla_put_flag(msg, NL80211_ATTR_FREQ_FIXED))
5067 goto fail;
5068 }
5069
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005070 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
5071 params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
5072 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
5073 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005074 wpa_printf(MSG_DEBUG, " * control port");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005075 if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
5076 goto fail;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005077 }
5078
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005079 if (params->wpa_ie) {
5080 wpa_hexdump(MSG_DEBUG,
5081 " * Extra IEs for Beacon/Probe Response frames",
5082 params->wpa_ie, params->wpa_ie_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005083 if (nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len,
5084 params->wpa_ie))
5085 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005086 }
5087
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -08005088 ret = nl80211_ht_vht_overrides(msg, params);
5089 if (ret < 0)
5090 goto fail;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005091
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005092 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5093 msg = NULL;
5094 if (ret) {
5095 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
5096 ret, strerror(-ret));
5097 count++;
5098 if (ret == -EALREADY && count == 1) {
5099 wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after "
5100 "forced leave");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005101 nl80211_leave_ibss(drv, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005102 nlmsg_free(msg);
5103 goto retry;
5104 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005105 } else {
5106 wpa_printf(MSG_DEBUG,
5107 "nl80211: Join IBSS request sent successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005108 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005109
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005110fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005111 nlmsg_free(msg);
5112 return ret;
5113}
5114
5115
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005116static int nl80211_put_fils_connect_params(struct wpa_driver_nl80211_data *drv,
5117 struct wpa_driver_associate_params *params,
5118 struct nl_msg *msg)
5119{
5120 if (params->fils_erp_username_len) {
5121 wpa_hexdump_ascii(MSG_DEBUG, " * FILS ERP EMSKname/username",
5122 params->fils_erp_username,
5123 params->fils_erp_username_len);
5124 if (nla_put(msg, NL80211_ATTR_FILS_ERP_USERNAME,
5125 params->fils_erp_username_len,
5126 params->fils_erp_username))
5127 return -1;
5128 }
5129
5130 if (params->fils_erp_realm_len) {
5131 wpa_hexdump_ascii(MSG_DEBUG, " * FILS ERP Realm",
5132 params->fils_erp_realm,
5133 params->fils_erp_realm_len);
5134 if (nla_put(msg, NL80211_ATTR_FILS_ERP_REALM,
5135 params->fils_erp_realm_len, params->fils_erp_realm))
5136 return -1;
5137 }
5138
5139 wpa_printf(MSG_DEBUG, " * FILS ERP next seq %u",
5140 params->fils_erp_next_seq_num);
5141 if (nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM,
5142 params->fils_erp_next_seq_num))
5143 return -1;
5144
5145 if (params->fils_erp_rrk_len) {
5146 wpa_printf(MSG_DEBUG, " * FILS ERP rRK (len=%lu)",
5147 (unsigned long) params->fils_erp_rrk_len);
5148 if (nla_put(msg, NL80211_ATTR_FILS_ERP_RRK,
5149 params->fils_erp_rrk_len, params->fils_erp_rrk))
5150 return -1;
5151 }
5152
5153 return 0;
5154}
5155
5156
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005157static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
5158 struct wpa_driver_associate_params *params,
5159 struct nl_msg *msg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005160{
Paul Stewart092955c2017-02-06 09:13:09 -08005161 if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER))
5162 return -1;
5163
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005164 if (params->bssid) {
5165 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
5166 MAC2STR(params->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005167 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
5168 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005169 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005170
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005171 if (params->bssid_hint) {
5172 wpa_printf(MSG_DEBUG, " * bssid_hint=" MACSTR,
5173 MAC2STR(params->bssid_hint));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005174 if (nla_put(msg, NL80211_ATTR_MAC_HINT, ETH_ALEN,
5175 params->bssid_hint))
5176 return -1;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005177 }
5178
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07005179 if (params->freq.freq) {
5180 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005181 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
5182 params->freq.freq))
5183 return -1;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07005184 drv->assoc_freq = params->freq.freq;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005185 } else
5186 drv->assoc_freq = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005187
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005188 if (params->freq_hint) {
5189 wpa_printf(MSG_DEBUG, " * freq_hint=%d", params->freq_hint);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005190 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_HINT,
5191 params->freq_hint))
5192 return -1;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08005193 }
5194
Dmitry Shmidt04949592012-07-19 12:16:46 -07005195 if (params->bg_scan_period >= 0) {
5196 wpa_printf(MSG_DEBUG, " * bg scan period=%d",
5197 params->bg_scan_period);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005198 if (nla_put_u16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
5199 params->bg_scan_period))
5200 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005201 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005202
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005203 if (params->ssid) {
5204 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
5205 params->ssid, params->ssid_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005206 if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len,
5207 params->ssid))
5208 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005209 if (params->ssid_len > sizeof(drv->ssid))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005210 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005211 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
5212 drv->ssid_len = params->ssid_len;
5213 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005214
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005215 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005216 if (params->wpa_ie &&
5217 nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len, params->wpa_ie))
5218 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005219
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005220 if (params->wpa_proto) {
5221 enum nl80211_wpa_versions ver = 0;
5222
5223 if (params->wpa_proto & WPA_PROTO_WPA)
5224 ver |= NL80211_WPA_VERSION_1;
5225 if (params->wpa_proto & WPA_PROTO_RSN)
5226 ver |= NL80211_WPA_VERSION_2;
5227
5228 wpa_printf(MSG_DEBUG, " * WPA Versions 0x%x", ver);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005229 if (nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver))
5230 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005231 }
5232
5233 if (params->pairwise_suite != WPA_CIPHER_NONE) {
5234 u32 cipher = wpa_cipher_to_cipher_suite(params->pairwise_suite);
5235 wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005236 if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
5237 cipher))
5238 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005239 }
5240
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005241 if (params->group_suite == WPA_CIPHER_GTK_NOT_USED &&
5242 !(drv->capa.enc & WPA_DRIVER_CAPA_ENC_GTK_NOT_USED)) {
5243 /*
5244 * This is likely to work even though many drivers do not
5245 * advertise support for operations without GTK.
5246 */
5247 wpa_printf(MSG_DEBUG, " * skip group cipher configuration for GTK_NOT_USED due to missing driver support advertisement");
5248 } else if (params->group_suite != WPA_CIPHER_NONE) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005249 u32 cipher = wpa_cipher_to_cipher_suite(params->group_suite);
5250 wpa_printf(MSG_DEBUG, " * group=0x%x", cipher);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005251 if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher))
5252 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005253 }
5254
5255 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
5256 params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
5257 params->key_mgmt_suite == WPA_KEY_MGMT_FT_IEEE8021X ||
5258 params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
Dmitry Shmidt15907092014-03-25 10:42:57 -07005259 params->key_mgmt_suite == WPA_KEY_MGMT_CCKM ||
Dmitry Shmidt3c57b3f2014-05-22 15:13:07 -07005260 params->key_mgmt_suite == WPA_KEY_MGMT_OSEN ||
5261 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005262 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005263 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005264 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 ||
5265 params->key_mgmt_suite == WPA_KEY_MGMT_FILS_SHA256 ||
5266 params->key_mgmt_suite == WPA_KEY_MGMT_FILS_SHA384 ||
5267 params->key_mgmt_suite == WPA_KEY_MGMT_FT_FILS_SHA256 ||
5268 params->key_mgmt_suite == WPA_KEY_MGMT_FT_FILS_SHA384) {
Paul Stewart092955c2017-02-06 09:13:09 -08005269 int mgmt = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005270
5271 switch (params->key_mgmt_suite) {
5272 case WPA_KEY_MGMT_CCKM:
Paul Stewart092955c2017-02-06 09:13:09 -08005273 mgmt = RSN_AUTH_KEY_MGMT_CCKM;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005274 break;
5275 case WPA_KEY_MGMT_IEEE8021X:
Paul Stewart092955c2017-02-06 09:13:09 -08005276 mgmt = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005277 break;
5278 case WPA_KEY_MGMT_FT_IEEE8021X:
Paul Stewart092955c2017-02-06 09:13:09 -08005279 mgmt = RSN_AUTH_KEY_MGMT_FT_802_1X;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005280 break;
5281 case WPA_KEY_MGMT_FT_PSK:
Paul Stewart092955c2017-02-06 09:13:09 -08005282 mgmt = RSN_AUTH_KEY_MGMT_FT_PSK;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005283 break;
Dmitry Shmidt3c57b3f2014-05-22 15:13:07 -07005284 case WPA_KEY_MGMT_IEEE8021X_SHA256:
Paul Stewart092955c2017-02-06 09:13:09 -08005285 mgmt = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
Dmitry Shmidt3c57b3f2014-05-22 15:13:07 -07005286 break;
5287 case WPA_KEY_MGMT_PSK_SHA256:
Paul Stewart092955c2017-02-06 09:13:09 -08005288 mgmt = RSN_AUTH_KEY_MGMT_PSK_SHA256;
Dmitry Shmidt3c57b3f2014-05-22 15:13:07 -07005289 break;
Dmitry Shmidt15907092014-03-25 10:42:57 -07005290 case WPA_KEY_MGMT_OSEN:
Paul Stewart092955c2017-02-06 09:13:09 -08005291 mgmt = RSN_AUTH_KEY_MGMT_OSEN;
Dmitry Shmidt15907092014-03-25 10:42:57 -07005292 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005293 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
Paul Stewart092955c2017-02-06 09:13:09 -08005294 mgmt = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005295 break;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005296 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
Paul Stewart092955c2017-02-06 09:13:09 -08005297 mgmt = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005298 break;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005299 case WPA_KEY_MGMT_FILS_SHA256:
5300 mgmt = RSN_AUTH_KEY_MGMT_FILS_SHA256;
5301 break;
5302 case WPA_KEY_MGMT_FILS_SHA384:
5303 mgmt = RSN_AUTH_KEY_MGMT_FILS_SHA384;
5304 break;
5305 case WPA_KEY_MGMT_FT_FILS_SHA256:
5306 mgmt = RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
5307 break;
5308 case WPA_KEY_MGMT_FT_FILS_SHA384:
5309 mgmt = RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
5310 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005311 case WPA_KEY_MGMT_PSK:
5312 default:
Paul Stewart092955c2017-02-06 09:13:09 -08005313 mgmt = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005314 break;
5315 }
Dmitry Shmidt15907092014-03-25 10:42:57 -07005316 wpa_printf(MSG_DEBUG, " * akm=0x%x", mgmt);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005317 if (nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, mgmt))
5318 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005319 }
5320
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005321 if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
5322 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005323
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07005324 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
5325 (params->pairwise_suite == WPA_CIPHER_NONE ||
5326 params->pairwise_suite == WPA_CIPHER_WEP104 ||
5327 params->pairwise_suite == WPA_CIPHER_WEP40) &&
5328 (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
5329 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
5330 return -1;
5331
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005332 if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED &&
5333 nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED))
5334 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005335
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005336 if (params->rrm_used) {
5337 u32 drv_rrm_flags = drv->capa.rrm_flags;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07005338 if ((!((drv_rrm_flags &
5339 WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
5340 (drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
5341 !(drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005342 nla_put_flag(msg, NL80211_ATTR_USE_RRM))
5343 return -1;
5344 }
5345
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005346 if (nl80211_ht_vht_overrides(msg, params) < 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005347 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005348
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005349 if (params->p2p)
5350 wpa_printf(MSG_DEBUG, " * P2P group");
5351
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005352 if (params->pbss) {
5353 wpa_printf(MSG_DEBUG, " * PBSS");
5354 if (nla_put_flag(msg, NL80211_ATTR_PBSS))
5355 return -1;
5356 }
5357
Dmitry Shmidte4663042016-04-04 10:07:49 -07005358 drv->connect_reassoc = 0;
5359 if (params->prev_bssid) {
5360 wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
5361 MAC2STR(params->prev_bssid));
5362 if (nla_put(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
5363 params->prev_bssid))
5364 return -1;
5365 drv->connect_reassoc = 1;
5366 }
5367
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005368 if ((params->auth_alg & WPA_AUTH_ALG_FILS) &&
5369 nl80211_put_fils_connect_params(drv, params, msg) != 0)
5370 return -1;
5371
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005372 return 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005373}
5374
5375
5376static int wpa_driver_nl80211_try_connect(
5377 struct wpa_driver_nl80211_data *drv,
5378 struct wpa_driver_associate_params *params)
5379{
5380 struct nl_msg *msg;
5381 enum nl80211_auth_type type;
5382 int ret;
5383 int algs;
5384
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005385#ifdef CONFIG_DRIVER_NL80211_QCA
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005386 if (params->req_key_mgmt_offload && params->psk &&
5387 (params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
5388 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
5389 params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
5390 wpa_printf(MSG_DEBUG, "nl80211: Key management set PSK");
5391 ret = issue_key_mgmt_set_key(drv, params->psk, 32);
5392 if (ret)
5393 return ret;
5394 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005395#endif /* CONFIG_DRIVER_NL80211_QCA */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005396
5397 wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
5398 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_CONNECT);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005399 if (!msg)
5400 return -1;
5401
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005402 ret = nl80211_connect_common(drv, params, msg);
5403 if (ret)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005404 goto fail;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005406 algs = 0;
5407 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
5408 algs++;
5409 if (params->auth_alg & WPA_AUTH_ALG_SHARED)
5410 algs++;
5411 if (params->auth_alg & WPA_AUTH_ALG_LEAP)
5412 algs++;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005413 if (params->auth_alg & WPA_AUTH_ALG_FILS)
5414 algs++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005415 if (algs > 1) {
5416 wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic "
5417 "selection");
5418 goto skip_auth_type;
5419 }
5420
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005421 type = get_nl_auth_type(params->auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005422 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005423 if (type == NL80211_AUTHTYPE_MAX ||
5424 nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005425 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005426
5427skip_auth_type:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005428 ret = nl80211_set_conn_keys(params, msg);
5429 if (ret)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005430 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005431
Hai Shalom0f8669c2019-02-26 16:17:45 -08005432 ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
5433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005434 msg = NULL;
5435 if (ret) {
5436 wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
5437 "(%s)", ret, strerror(-ret));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005438 } else {
5439 wpa_printf(MSG_DEBUG,
5440 "nl80211: Connect request send successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005441 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005442
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005443fail:
Hai Shalom0f8669c2019-02-26 16:17:45 -08005444 nl80211_nlmsg_clear(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005445 nlmsg_free(msg);
5446 return ret;
5447
5448}
5449
5450
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005451static int wpa_driver_nl80211_connect(
5452 struct wpa_driver_nl80211_data *drv,
5453 struct wpa_driver_associate_params *params)
5454{
Jithu Jancea7c60b42014-12-03 18:54:40 +05305455 int ret;
5456
5457 /* Store the connection attempted bssid for future use */
5458 if (params->bssid)
5459 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
5460 else
5461 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
5462
5463 ret = wpa_driver_nl80211_try_connect(drv, params);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005464 if (ret == -EALREADY) {
5465 /*
5466 * cfg80211 does not currently accept new connections if
5467 * we are already connected. As a workaround, force
5468 * disconnection and try again.
5469 */
5470 wpa_printf(MSG_DEBUG, "nl80211: Explicitly "
5471 "disconnecting before reassociation "
5472 "attempt");
5473 if (wpa_driver_nl80211_disconnect(
5474 drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
5475 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005476 ret = wpa_driver_nl80211_try_connect(drv, params);
5477 }
5478 return ret;
5479}
5480
5481
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005482static int wpa_driver_nl80211_associate(
5483 void *priv, struct wpa_driver_associate_params *params)
5484{
5485 struct i802_bss *bss = priv;
5486 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005487 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005488 struct nl_msg *msg;
5489
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005490 nl80211_unmask_11b_rates(bss);
5491
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005492 if (params->mode == IEEE80211_MODE_AP)
5493 return wpa_driver_nl80211_ap(drv, params);
5494
5495 if (params->mode == IEEE80211_MODE_IBSS)
5496 return wpa_driver_nl80211_ibss(drv, params);
5497
5498 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005499 enum nl80211_iftype nlmode = params->p2p ?
5500 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
5501
5502 if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005503 return -1;
5504 return wpa_driver_nl80211_connect(drv, params);
5505 }
5506
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005507 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005508
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005509 wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)",
5510 drv->ifindex);
5511 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_ASSOCIATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005512 if (!msg)
5513 return -1;
5514
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005515 ret = nl80211_connect_common(drv, params, msg);
5516 if (ret)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005517 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005518
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005519 if (params->fils_kek) {
5520 wpa_printf(MSG_DEBUG, " * FILS KEK (len=%u)",
5521 (unsigned int) params->fils_kek_len);
5522 if (nla_put(msg, NL80211_ATTR_FILS_KEK, params->fils_kek_len,
5523 params->fils_kek))
5524 goto fail;
5525 }
5526 if (params->fils_nonces) {
5527 wpa_hexdump(MSG_DEBUG, " * FILS nonces (for AAD)",
5528 params->fils_nonces,
5529 params->fils_nonces_len);
5530 if (nla_put(msg, NL80211_ATTR_FILS_NONCES,
5531 params->fils_nonces_len, params->fils_nonces))
5532 goto fail;
5533 }
5534
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005535 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5536 msg = NULL;
5537 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005538 wpa_dbg(drv->ctx, MSG_DEBUG,
5539 "nl80211: MLME command failed (assoc): ret=%d (%s)",
5540 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005541 nl80211_dump_scan(drv);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005542 } else {
5543 wpa_printf(MSG_DEBUG,
5544 "nl80211: Association request send successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005545 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005546
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005547fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005548 nlmsg_free(msg);
5549 return ret;
5550}
5551
5552
5553static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005554 int ifindex, enum nl80211_iftype mode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005555{
5556 struct nl_msg *msg;
5557 int ret = -ENOBUFS;
5558
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005559 wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)",
5560 ifindex, mode, nl80211_iftype_str(mode));
5561
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005562 msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_SET_INTERFACE);
5563 if (!msg || nla_put_u32(msg, NL80211_ATTR_IFTYPE, mode))
5564 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005565
5566 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005567 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005568 if (!ret)
5569 return 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005570fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005571 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005572 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
5573 " %d (%s)", ifindex, mode, ret, strerror(-ret));
5574 return ret;
5575}
5576
5577
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005578static int wpa_driver_nl80211_set_mode_impl(
5579 struct i802_bss *bss,
5580 enum nl80211_iftype nlmode,
5581 struct hostapd_freq_params *desired_freq_params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005582{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005583 struct wpa_driver_nl80211_data *drv = bss->drv;
5584 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005585 int i;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005586 int was_ap = is_ap_interface(drv->nlmode);
5587 int res;
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005588 int mode_switch_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005589
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07005590 if (TEST_FAIL())
5591 return -1;
5592
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005593 mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
5594 if (mode_switch_res && nlmode == nl80211_get_ifmode(bss))
5595 mode_switch_res = 0;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005596
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005597 if (mode_switch_res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005598 drv->nlmode = nlmode;
5599 ret = 0;
5600 goto done;
5601 }
5602
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005603 if (mode_switch_res == -ENODEV)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005604 return -1;
5605
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005606 if (nlmode == drv->nlmode) {
5607 wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
5608 "requested mode - ignore error");
5609 ret = 0;
5610 goto done; /* Already in the requested mode */
5611 }
5612
5613 /* mac80211 doesn't allow mode changes while the device is up, so
5614 * take the device down, try to set the mode again, and bring the
5615 * device back up.
5616 */
5617 wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
5618 "interface down");
5619 for (i = 0; i < 10; i++) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005620 res = i802_set_iface_flags(bss, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005621 if (res == -EACCES || res == -ENODEV)
5622 break;
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005623 if (res != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005624 wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
5625 "interface down");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005626 os_sleep(0, 100000);
5627 continue;
5628 }
5629
5630 /*
5631 * Setting the mode will fail for some drivers if the phy is
5632 * on a frequency that the mode is disallowed in.
5633 */
5634 if (desired_freq_params) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005635 res = nl80211_set_channel(bss, desired_freq_params, 0);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005636 if (res) {
5637 wpa_printf(MSG_DEBUG,
5638 "nl80211: Failed to set frequency on interface");
5639 }
5640 }
5641
5642 /* Try to set the mode again while the interface is down */
5643 mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
5644 if (mode_switch_res == -EBUSY) {
5645 wpa_printf(MSG_DEBUG,
5646 "nl80211: Delaying mode set while interface going down");
5647 os_sleep(0, 100000);
5648 continue;
5649 }
5650 ret = mode_switch_res;
5651 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005652 }
5653
5654 if (!ret) {
5655 wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
5656 "interface is down");
5657 drv->nlmode = nlmode;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005658 drv->ignore_if_down_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005659 }
5660
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005661 /* Bring the interface back up */
5662 res = linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
5663 if (res != 0) {
5664 wpa_printf(MSG_DEBUG,
5665 "nl80211: Failed to set interface up after switching mode");
5666 ret = -1;
5667 }
5668
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005669done:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005670 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005671 wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
5672 "from %d failed", nlmode, drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005673 return ret;
5674 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005675
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005676 if (is_p2p_net_interface(nlmode)) {
5677 wpa_printf(MSG_DEBUG,
5678 "nl80211: Interface %s mode change to P2P - disable 11b rates",
5679 bss->ifname);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005680 nl80211_disable_11b_rates(drv, drv->ifindex, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005681 } else if (drv->disabled_11b_rates) {
5682 wpa_printf(MSG_DEBUG,
5683 "nl80211: Interface %s mode changed to non-P2P - re-enable 11b rates",
5684 bss->ifname);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005685 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005686 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005687
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005688 if (is_ap_interface(nlmode)) {
5689 nl80211_mgmt_unsubscribe(bss, "start AP");
5690 /* Setup additional AP mode functionality if needed */
5691 if (nl80211_setup_ap(bss))
5692 return -1;
5693 } else if (was_ap) {
5694 /* Remove additional AP mode functionality */
5695 nl80211_teardown_ap(bss);
5696 } else {
5697 nl80211_mgmt_unsubscribe(bss, "mode change");
5698 }
5699
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005700 if (is_mesh_interface(nlmode) &&
5701 nl80211_mgmt_subscribe_mesh(bss))
5702 return -1;
5703
Dmitry Shmidt04949592012-07-19 12:16:46 -07005704 if (!bss->in_deinit && !is_ap_interface(nlmode) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005705 !is_mesh_interface(nlmode) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005706 nl80211_mgmt_subscribe_non_ap(bss) < 0)
5707 wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
5708 "frame processing - ignore for now");
5709
5710 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005711}
5712
5713
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005714int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
5715 enum nl80211_iftype nlmode)
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005716{
5717 return wpa_driver_nl80211_set_mode_impl(bss, nlmode, NULL);
5718}
5719
5720
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07005721static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
5722 struct hostapd_freq_params *freq)
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005723{
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005724 return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07005725 freq);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07005726}
5727
5728
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005729static int wpa_driver_nl80211_get_capa(void *priv,
5730 struct wpa_driver_capa *capa)
5731{
5732 struct i802_bss *bss = priv;
5733 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07005734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005735 if (!drv->has_capability)
5736 return -1;
5737 os_memcpy(capa, &drv->capa, sizeof(*capa));
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005738 if (drv->extended_capa && drv->extended_capa_mask) {
5739 capa->extended_capa = drv->extended_capa;
5740 capa->extended_capa_mask = drv->extended_capa_mask;
5741 capa->extended_capa_len = drv->extended_capa_len;
5742 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005743
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005744 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005745}
5746
5747
5748static int wpa_driver_nl80211_set_operstate(void *priv, int state)
5749{
5750 struct i802_bss *bss = priv;
5751 struct wpa_driver_nl80211_data *drv = bss->drv;
5752
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005753 wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)",
5754 bss->ifname, drv->operstate, state,
5755 state ? "UP" : "DORMANT");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005756 drv->operstate = state;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005757 return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005758 state ? IF_OPER_UP : IF_OPER_DORMANT);
5759}
5760
5761
5762static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
5763{
5764 struct i802_bss *bss = priv;
5765 struct wpa_driver_nl80211_data *drv = bss->drv;
5766 struct nl_msg *msg;
5767 struct nl80211_sta_flag_update upd;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005768 int ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005769
5770 if (!drv->associated && is_zero_ether_addr(drv->bssid) && !authorized) {
5771 wpa_printf(MSG_DEBUG, "nl80211: Skip set_supp_port(unauthorized) while not associated");
5772 return 0;
5773 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005774
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005775 wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
5776 MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
5777
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005778 os_memset(&upd, 0, sizeof(upd));
5779 upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);
5780 if (authorized)
5781 upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005782
5783 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
5784 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid) ||
5785 nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) {
5786 nlmsg_free(msg);
5787 return -ENOBUFS;
5788 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005789
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005790 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005791 if (!ret)
5792 return 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005793 wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)",
5794 ret, strerror(-ret));
5795 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005796}
5797
5798
Jouni Malinen75ecf522011-06-27 15:19:46 -07005799/* Set kernel driver on given frequency (MHz) */
5800static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005801{
Jouni Malinen75ecf522011-06-27 15:19:46 -07005802 struct i802_bss *bss = priv;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07005803 return nl80211_set_channel(bss, freq, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005804}
5805
5806
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005807static inline int min_int(int a, int b)
5808{
5809 if (a < b)
5810 return a;
5811 return b;
5812}
5813
5814
5815static int get_key_handler(struct nl_msg *msg, void *arg)
5816{
5817 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5818 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5819
5820 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5821 genlmsg_attrlen(gnlh, 0), NULL);
5822
5823 /*
5824 * TODO: validate the key index and mac address!
5825 * Otherwise, there's a race condition as soon as
5826 * the kernel starts sending key notifications.
5827 */
5828
5829 if (tb[NL80211_ATTR_KEY_SEQ])
5830 memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
5831 min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
5832 return NL_SKIP;
5833}
5834
5835
5836static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
5837 int idx, u8 *seq)
5838{
5839 struct i802_bss *bss = priv;
5840 struct wpa_driver_nl80211_data *drv = bss->drv;
5841 struct nl_msg *msg;
5842
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005843 msg = nl80211_ifindex_msg(drv, if_nametoindex(iface), 0,
5844 NL80211_CMD_GET_KEY);
5845 if (!msg ||
5846 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
5847 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, idx)) {
5848 nlmsg_free(msg);
5849 return -ENOBUFS;
5850 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005851
5852 memset(seq, 0, 6);
5853
5854 return send_and_recv_msgs(drv, msg, get_key_handler, seq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005855}
5856
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005857
5858static int i802_set_rts(void *priv, int rts)
5859{
5860 struct i802_bss *bss = priv;
5861 struct wpa_driver_nl80211_data *drv = bss->drv;
5862 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005863 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005864 u32 val;
5865
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005866 if (rts >= 2347)
5867 val = (u32) -1;
5868 else
5869 val = rts;
5870
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005871 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) ||
5872 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val)) {
5873 nlmsg_free(msg);
5874 return -ENOBUFS;
5875 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005876
5877 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5878 if (!ret)
5879 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005880 wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
5881 "%d (%s)", rts, ret, strerror(-ret));
5882 return ret;
5883}
5884
5885
5886static int i802_set_frag(void *priv, int frag)
5887{
5888 struct i802_bss *bss = priv;
5889 struct wpa_driver_nl80211_data *drv = bss->drv;
5890 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005891 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005892 u32 val;
5893
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005894 if (frag >= 2346)
5895 val = (u32) -1;
5896 else
5897 val = frag;
5898
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005899 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) ||
5900 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val)) {
5901 nlmsg_free(msg);
5902 return -ENOBUFS;
5903 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005904
5905 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5906 if (!ret)
5907 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005908 wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
5909 "%d: %d (%s)", frag, ret, strerror(-ret));
5910 return ret;
5911}
5912
5913
5914static int i802_flush(void *priv)
5915{
5916 struct i802_bss *bss = priv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005917 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005918 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005919
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005920 wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
5921 bss->ifname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005922
5923 /*
5924 * XXX: FIX! this needs to flush all VLANs too
5925 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005926 msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION);
5927 res = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005928 if (res) {
5929 wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
5930 "(%s)", res, strerror(-res));
5931 }
5932 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005933}
5934
5935
5936static int get_sta_handler(struct nl_msg *msg, void *arg)
5937{
5938 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5939 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5940 struct hostap_sta_driver_data *data = arg;
5941 struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
5942 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
5943 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
5944 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
5945 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
5946 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
5947 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03005948 [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005949 [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
5950 [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005951 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
5952 };
5953 struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
5954 static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
5955 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
5956 [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
5957 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
5958 [NL80211_RATE_INFO_VHT_MCS] = { .type = NLA_U8 },
5959 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
5960 [NL80211_RATE_INFO_VHT_NSS] = { .type = NLA_U8 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005961 };
5962
5963 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5964 genlmsg_attrlen(gnlh, 0), NULL);
5965
5966 /*
5967 * TODO: validate the interface and mac address!
5968 * Otherwise, there's a race condition as soon as
5969 * the kernel starts sending station notifications.
5970 */
5971
5972 if (!tb[NL80211_ATTR_STA_INFO]) {
5973 wpa_printf(MSG_DEBUG, "sta stats missing!");
5974 return NL_SKIP;
5975 }
5976 if (nla_parse_nested(stats, NL80211_STA_INFO_MAX,
5977 tb[NL80211_ATTR_STA_INFO],
5978 stats_policy)) {
5979 wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
5980 return NL_SKIP;
5981 }
5982
5983 if (stats[NL80211_STA_INFO_INACTIVE_TIME])
5984 data->inactive_msec =
5985 nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005986 /* For backwards compatibility, fetch the 32-bit counters first. */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005987 if (stats[NL80211_STA_INFO_RX_BYTES])
5988 data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
5989 if (stats[NL80211_STA_INFO_TX_BYTES])
5990 data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005991 if (stats[NL80211_STA_INFO_RX_BYTES64] &&
5992 stats[NL80211_STA_INFO_TX_BYTES64]) {
5993 /*
5994 * The driver supports 64-bit counters, so use them to override
5995 * the 32-bit values.
5996 */
5997 data->rx_bytes =
5998 nla_get_u64(stats[NL80211_STA_INFO_RX_BYTES64]);
5999 data->tx_bytes =
6000 nla_get_u64(stats[NL80211_STA_INFO_TX_BYTES64]);
6001 data->bytes_64bit = 1;
6002 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006003 if (stats[NL80211_STA_INFO_RX_PACKETS])
6004 data->rx_packets =
6005 nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
6006 if (stats[NL80211_STA_INFO_TX_PACKETS])
6007 data->tx_packets =
6008 nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03006009 if (stats[NL80211_STA_INFO_TX_FAILED])
6010 data->tx_retry_failed =
6011 nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006012 if (stats[NL80211_STA_INFO_SIGNAL])
6013 data->signal = nla_get_u8(stats[NL80211_STA_INFO_SIGNAL]);
6014
6015 if (stats[NL80211_STA_INFO_TX_BITRATE] &&
6016 nla_parse_nested(rate, NL80211_RATE_INFO_MAX,
6017 stats[NL80211_STA_INFO_TX_BITRATE],
6018 rate_policy) == 0) {
6019 if (rate[NL80211_RATE_INFO_BITRATE32])
6020 data->current_tx_rate =
6021 nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
6022 else if (rate[NL80211_RATE_INFO_BITRATE])
6023 data->current_tx_rate =
6024 nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
6025
6026 if (rate[NL80211_RATE_INFO_MCS]) {
6027 data->tx_mcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
6028 data->flags |= STA_DRV_DATA_TX_MCS;
6029 }
6030 if (rate[NL80211_RATE_INFO_VHT_MCS]) {
6031 data->tx_vhtmcs =
6032 nla_get_u8(rate[NL80211_RATE_INFO_VHT_MCS]);
6033 data->flags |= STA_DRV_DATA_TX_VHT_MCS;
6034 }
6035 if (rate[NL80211_RATE_INFO_SHORT_GI])
6036 data->flags |= STA_DRV_DATA_TX_SHORT_GI;
6037 if (rate[NL80211_RATE_INFO_VHT_NSS]) {
6038 data->tx_vht_nss =
6039 nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
6040 data->flags |= STA_DRV_DATA_TX_VHT_NSS;
6041 }
6042 }
6043
6044 if (stats[NL80211_STA_INFO_RX_BITRATE] &&
6045 nla_parse_nested(rate, NL80211_RATE_INFO_MAX,
6046 stats[NL80211_STA_INFO_RX_BITRATE],
6047 rate_policy) == 0) {
6048 if (rate[NL80211_RATE_INFO_BITRATE32])
6049 data->current_rx_rate =
6050 nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
6051 else if (rate[NL80211_RATE_INFO_BITRATE])
6052 data->current_rx_rate =
6053 nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
6054
6055 if (rate[NL80211_RATE_INFO_MCS]) {
6056 data->rx_mcs =
6057 nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
6058 data->flags |= STA_DRV_DATA_RX_MCS;
6059 }
6060 if (rate[NL80211_RATE_INFO_VHT_MCS]) {
6061 data->rx_vhtmcs =
6062 nla_get_u8(rate[NL80211_RATE_INFO_VHT_MCS]);
6063 data->flags |= STA_DRV_DATA_RX_VHT_MCS;
6064 }
6065 if (rate[NL80211_RATE_INFO_SHORT_GI])
6066 data->flags |= STA_DRV_DATA_RX_SHORT_GI;
6067 if (rate[NL80211_RATE_INFO_VHT_NSS]) {
6068 data->rx_vht_nss =
6069 nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
6070 data->flags |= STA_DRV_DATA_RX_VHT_NSS;
6071 }
6072 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006073
6074 return NL_SKIP;
6075}
6076
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006077static int i802_read_sta_data(struct i802_bss *bss,
6078 struct hostap_sta_driver_data *data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006079 const u8 *addr)
6080{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006081 struct nl_msg *msg;
6082
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006083 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_GET_STATION)) ||
6084 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
6085 nlmsg_free(msg);
6086 return -ENOBUFS;
6087 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006088
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006089 return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006090}
6091
6092
6093static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
6094 int cw_min, int cw_max, int burst_time)
6095{
6096 struct i802_bss *bss = priv;
6097 struct wpa_driver_nl80211_data *drv = bss->drv;
6098 struct nl_msg *msg;
6099 struct nlattr *txq, *params;
6100
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006101 msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006102 if (!msg)
6103 return -1;
6104
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006105 txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);
6106 if (!txq)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006107 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006108
6109 /* We are only sending parameters for a single TXQ at a time */
6110 params = nla_nest_start(msg, 1);
6111 if (!params)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006112 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006113
6114 switch (queue) {
6115 case 0:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006116 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO))
6117 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006118 break;
6119 case 1:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006120 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI))
6121 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006122 break;
6123 case 2:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006124 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE))
6125 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006126 break;
6127 case 3:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006128 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK))
6129 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006130 break;
6131 }
6132 /* Burst time is configured in units of 0.1 msec and TXOP parameter in
6133 * 32 usec, so need to convert the value here. */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006134 if (nla_put_u16(msg, NL80211_TXQ_ATTR_TXOP,
6135 (burst_time * 100 + 16) / 32) ||
6136 nla_put_u16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min) ||
6137 nla_put_u16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max) ||
6138 nla_put_u8(msg, NL80211_TXQ_ATTR_AIFS, aifs))
6139 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006140
6141 nla_nest_end(msg, params);
6142
6143 nla_nest_end(msg, txq);
6144
6145 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
6146 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006147 msg = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006148fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006149 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006150 return -1;
6151}
6152
6153
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006154static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006155 const char *ifname, int vlan_id)
6156{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006157 struct wpa_driver_nl80211_data *drv = bss->drv;
6158 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006159 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006160
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006161 wpa_printf(MSG_DEBUG, "nl80211: %s[%d]: set_sta_vlan(" MACSTR
6162 ", ifname=%s[%d], vlan_id=%d)",
6163 bss->ifname, if_nametoindex(bss->ifname),
6164 MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006165 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
6166 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6167 nla_put_u32(msg, NL80211_ATTR_STA_VLAN, if_nametoindex(ifname))) {
6168 nlmsg_free(msg);
6169 return -ENOBUFS;
6170 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006171
6172 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6173 if (ret < 0) {
6174 wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
6175 MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
6176 MAC2STR(addr), ifname, vlan_id, ret,
6177 strerror(-ret));
6178 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006179 return ret;
6180}
6181
6182
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006183static int i802_get_inact_sec(void *priv, const u8 *addr)
6184{
6185 struct hostap_sta_driver_data data;
6186 int ret;
6187
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08006188 os_memset(&data, 0, sizeof(data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006189 data.inactive_msec = (unsigned long) -1;
6190 ret = i802_read_sta_data(priv, &data, addr);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08006191 if (ret == -ENOENT)
6192 return -ENOENT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006193 if (ret || data.inactive_msec == (unsigned long) -1)
6194 return -1;
6195 return data.inactive_msec / 1000;
6196}
6197
6198
6199static int i802_sta_clear_stats(void *priv, const u8 *addr)
6200{
6201#if 0
6202 /* TODO */
6203#endif
6204 return 0;
6205}
6206
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006207
6208static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
6209 int reason)
6210{
6211 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006212 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006213 struct ieee80211_mgmt mgmt;
Dmitry Shmidt29333592017-01-09 12:27:11 -08006214 u8 channel;
6215
6216 if (ieee80211_freq_to_chan(bss->freq, &channel) ==
6217 HOSTAPD_MODE_IEEE80211AD) {
6218 /* Deauthentication is not used in DMG/IEEE 802.11ad;
6219 * disassociate the STA instead. */
6220 return i802_sta_disassoc(priv, own_addr, addr, reason);
6221 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006222
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006223 if (is_mesh_interface(drv->nlmode))
6224 return -1;
6225
Dmitry Shmidt04949592012-07-19 12:16:46 -07006226 if (drv->device_ap_sme)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006227 return wpa_driver_nl80211_sta_remove(bss, addr, 1, reason);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006228
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006229 memset(&mgmt, 0, sizeof(mgmt));
6230 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
6231 WLAN_FC_STYPE_DEAUTH);
6232 memcpy(mgmt.da, addr, ETH_ALEN);
6233 memcpy(mgmt.sa, own_addr, ETH_ALEN);
6234 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
6235 mgmt.u.deauth.reason_code = host_to_le16(reason);
6236 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
6237 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006238 sizeof(mgmt.u.deauth), 0, 0, 0, 0,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006239 0, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006240}
6241
6242
6243static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
6244 int reason)
6245{
6246 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006247 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006248 struct ieee80211_mgmt mgmt;
6249
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006250 if (is_mesh_interface(drv->nlmode))
6251 return -1;
6252
Dmitry Shmidt04949592012-07-19 12:16:46 -07006253 if (drv->device_ap_sme)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006254 return wpa_driver_nl80211_sta_remove(bss, addr, 0, reason);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006255
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006256 memset(&mgmt, 0, sizeof(mgmt));
6257 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
6258 WLAN_FC_STYPE_DISASSOC);
6259 memcpy(mgmt.da, addr, ETH_ALEN);
6260 memcpy(mgmt.sa, own_addr, ETH_ALEN);
6261 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
6262 mgmt.u.disassoc.reason_code = host_to_le16(reason);
6263 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
6264 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006265 sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006266 0, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006267}
6268
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006269
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006270static void dump_ifidx(struct wpa_driver_nl80211_data *drv)
6271{
6272 char buf[200], *pos, *end;
6273 int i, res;
6274
6275 pos = buf;
6276 end = pos + sizeof(buf);
6277
6278 for (i = 0; i < drv->num_if_indices; i++) {
6279 if (!drv->if_indices[i])
6280 continue;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006281 res = os_snprintf(pos, end - pos, " %d(%d)",
6282 drv->if_indices[i],
6283 drv->if_indices_reason[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006284 if (os_snprintf_error(end - pos, res))
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006285 break;
6286 pos += res;
6287 }
6288 *pos = '\0';
6289
6290 wpa_printf(MSG_DEBUG, "nl80211: if_indices[%d]:%s",
6291 drv->num_if_indices, buf);
6292}
6293
6294
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006295static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
6296 int ifidx_reason)
Jouni Malinen75ecf522011-06-27 15:19:46 -07006297{
6298 int i;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006299 int *old, *old_reason;
Jouni Malinen75ecf522011-06-27 15:19:46 -07006300
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006301 wpa_printf(MSG_DEBUG,
6302 "nl80211: Add own interface ifindex %d (ifidx_reason %d)",
6303 ifidx, ifidx_reason);
6304 if (have_ifidx(drv, ifidx, ifidx_reason)) {
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006305 wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
6306 ifidx);
6307 return;
6308 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07006309 for (i = 0; i < drv->num_if_indices; i++) {
6310 if (drv->if_indices[i] == 0) {
6311 drv->if_indices[i] = ifidx;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006312 drv->if_indices_reason[i] = ifidx_reason;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006313 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07006314 return;
6315 }
6316 }
6317
6318 if (drv->if_indices != drv->default_if_indices)
6319 old = drv->if_indices;
6320 else
6321 old = NULL;
6322
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006323 if (drv->if_indices_reason != drv->default_if_indices_reason)
6324 old_reason = drv->if_indices_reason;
6325 else
6326 old_reason = NULL;
6327
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006328 drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
6329 sizeof(int));
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006330 drv->if_indices_reason = os_realloc_array(old_reason,
6331 drv->num_if_indices + 1,
6332 sizeof(int));
Jouni Malinen75ecf522011-06-27 15:19:46 -07006333 if (!drv->if_indices) {
6334 if (!old)
6335 drv->if_indices = drv->default_if_indices;
6336 else
6337 drv->if_indices = old;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006338 }
6339 if (!drv->if_indices_reason) {
6340 if (!old_reason)
6341 drv->if_indices_reason = drv->default_if_indices_reason;
6342 else
Dmitry Shmidte4663042016-04-04 10:07:49 -07006343 drv->if_indices_reason = old_reason;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006344 }
6345 if (!drv->if_indices || !drv->if_indices_reason) {
Jouni Malinen75ecf522011-06-27 15:19:46 -07006346 wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
6347 "interfaces");
6348 wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
6349 return;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006350 }
6351 if (!old)
Jouni Malinen75ecf522011-06-27 15:19:46 -07006352 os_memcpy(drv->if_indices, drv->default_if_indices,
6353 sizeof(drv->default_if_indices));
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006354 if (!old_reason)
6355 os_memcpy(drv->if_indices_reason,
6356 drv->default_if_indices_reason,
6357 sizeof(drv->default_if_indices_reason));
Jouni Malinen75ecf522011-06-27 15:19:46 -07006358 drv->if_indices[drv->num_if_indices] = ifidx;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006359 drv->if_indices_reason[drv->num_if_indices] = ifidx_reason;
Jouni Malinen75ecf522011-06-27 15:19:46 -07006360 drv->num_if_indices++;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006361 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07006362}
6363
6364
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006365static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
6366 int ifidx_reason)
Jouni Malinen75ecf522011-06-27 15:19:46 -07006367{
6368 int i;
6369
6370 for (i = 0; i < drv->num_if_indices; i++) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006371 if ((drv->if_indices[i] == ifidx || ifidx == IFIDX_ANY) &&
6372 (drv->if_indices_reason[i] == ifidx_reason ||
6373 ifidx_reason == IFIDX_ANY)) {
Jouni Malinen75ecf522011-06-27 15:19:46 -07006374 drv->if_indices[i] = 0;
6375 break;
6376 }
6377 }
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006378 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07006379}
6380
6381
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006382static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
6383 int ifidx_reason)
Jouni Malinen75ecf522011-06-27 15:19:46 -07006384{
6385 int i;
6386
6387 for (i = 0; i < drv->num_if_indices; i++)
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006388 if (drv->if_indices[i] == ifidx &&
6389 (drv->if_indices_reason[i] == ifidx_reason ||
6390 ifidx_reason == IFIDX_ANY))
Jouni Malinen75ecf522011-06-27 15:19:46 -07006391 return 1;
6392
6393 return 0;
6394}
6395
6396
6397static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07006398 const char *bridge_ifname, char *ifname_wds)
Jouni Malinen75ecf522011-06-27 15:19:46 -07006399{
6400 struct i802_bss *bss = priv;
6401 struct wpa_driver_nl80211_data *drv = bss->drv;
6402 char name[IFNAMSIZ + 1];
6403
6404 os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006405 if (ifname_wds)
6406 os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
6407
Jouni Malinen75ecf522011-06-27 15:19:46 -07006408 wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
6409 " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
6410 if (val) {
6411 if (!if_nametoindex(name)) {
6412 if (nl80211_create_iface(drv, name,
6413 NL80211_IFTYPE_AP_VLAN,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006414 bss->addr, 1, NULL, NULL, 0) <
6415 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07006416 return -1;
6417 if (bridge_ifname &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006418 linux_br_add_if(drv->global->ioctl_sock,
6419 bridge_ifname, name) < 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07006420 return -1;
6421 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006422 if (linux_set_iface_flags(drv->global->ioctl_sock, name, 1)) {
6423 wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA "
6424 "interface %s up", name);
6425 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07006426 return i802_set_sta_vlan(priv, addr, name, 0);
6427 } else {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006428 if (bridge_ifname)
6429 linux_br_del_if(drv->global->ioctl_sock, bridge_ifname,
6430 name);
6431
Jouni Malinen75ecf522011-06-27 15:19:46 -07006432 i802_set_sta_vlan(priv, addr, bss->ifname, 0);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08006433 nl80211_remove_iface(drv, if_nametoindex(name));
6434 return 0;
Jouni Malinen75ecf522011-06-27 15:19:46 -07006435 }
6436}
6437
6438
6439static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
6440{
6441 struct wpa_driver_nl80211_data *drv = eloop_ctx;
6442 struct sockaddr_ll lladdr;
6443 unsigned char buf[3000];
6444 int len;
6445 socklen_t fromlen = sizeof(lladdr);
6446
6447 len = recvfrom(sock, buf, sizeof(buf), 0,
6448 (struct sockaddr *)&lladdr, &fromlen);
6449 if (len < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006450 wpa_printf(MSG_ERROR, "nl80211: EAPOL recv failed: %s",
6451 strerror(errno));
Jouni Malinen75ecf522011-06-27 15:19:46 -07006452 return;
6453 }
6454
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006455 if (have_ifidx(drv, lladdr.sll_ifindex, IFIDX_ANY))
Jouni Malinen75ecf522011-06-27 15:19:46 -07006456 drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
6457}
6458
6459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006460static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
6461 struct i802_bss *bss,
6462 const char *brname, const char *ifname)
6463{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006464 int br_ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006465 char in_br[IFNAMSIZ];
6466
6467 os_strlcpy(bss->brname, brname, IFNAMSIZ);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006468 br_ifindex = if_nametoindex(brname);
6469 if (br_ifindex == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006470 /*
6471 * Bridge was configured, but the bridge device does
6472 * not exist. Try to add it now.
6473 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006474 if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006475 wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
6476 "bridge interface %s: %s",
6477 brname, strerror(errno));
6478 return -1;
6479 }
6480 bss->added_bridge = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006481 br_ifindex = if_nametoindex(brname);
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006482 add_ifidx(drv, br_ifindex, drv->ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006483 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006484 bss->br_ifindex = br_ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006485
6486 if (linux_br_get(in_br, ifname) == 0) {
6487 if (os_strcmp(in_br, brname) == 0)
6488 return 0; /* already in the bridge */
6489
6490 wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
6491 "bridge %s", ifname, in_br);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006492 if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
6493 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006494 wpa_printf(MSG_ERROR, "nl80211: Failed to "
6495 "remove interface %s from bridge "
6496 "%s: %s",
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006497 ifname, in_br, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006498 return -1;
6499 }
6500 }
6501
6502 wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
6503 ifname, brname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006504 if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006505 wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
6506 "into bridge %s: %s",
6507 ifname, brname, strerror(errno));
6508 return -1;
6509 }
6510 bss->added_if_into_bridge = 1;
6511
6512 return 0;
6513}
6514
6515
6516static void *i802_init(struct hostapd_data *hapd,
6517 struct wpa_init_params *params)
6518{
6519 struct wpa_driver_nl80211_data *drv;
6520 struct i802_bss *bss;
6521 size_t i;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006522 char master_ifname[IFNAMSIZ];
6523 int ifindex, br_ifindex = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006524 int br_added = 0;
6525
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006526 bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
6527 params->global_priv, 1,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006528 params->bssid, params->driver_params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006529 if (bss == NULL)
6530 return NULL;
6531
6532 drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006533
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006534 if (linux_br_get(master_ifname, params->ifname) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006535 wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006536 params->ifname, master_ifname);
6537 br_ifindex = if_nametoindex(master_ifname);
6538 os_strlcpy(bss->brname, master_ifname, IFNAMSIZ);
6539 } else if ((params->num_bridge == 0 || !params->bridge[0]) &&
6540 linux_master_get(master_ifname, params->ifname) == 0) {
6541 wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in master %s",
6542 params->ifname, master_ifname);
6543 /* start listening for EAPOL on the master interface */
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006544 add_ifidx(drv, if_nametoindex(master_ifname), drv->ifindex);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08006545
6546 /* check if master itself is under bridge */
6547 if (linux_br_get(master_ifname, master_ifname) == 0) {
6548 wpa_printf(MSG_DEBUG, "nl80211: which is in bridge %s",
6549 master_ifname);
6550 br_ifindex = if_nametoindex(master_ifname);
6551 os_strlcpy(bss->brname, master_ifname, IFNAMSIZ);
6552 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006553 } else {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006554 master_ifname[0] = '\0';
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006555 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006556
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006557 bss->br_ifindex = br_ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006558
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006559 for (i = 0; i < params->num_bridge; i++) {
6560 if (params->bridge[i]) {
6561 ifindex = if_nametoindex(params->bridge[i]);
6562 if (ifindex)
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006563 add_ifidx(drv, ifindex, drv->ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006564 if (ifindex == br_ifindex)
6565 br_added = 1;
6566 }
6567 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006568
6569 /* start listening for EAPOL on the default AP interface */
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006570 add_ifidx(drv, drv->ifindex, IFIDX_ANY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006571
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006572 if (params->num_bridge && params->bridge[0]) {
6573 if (i802_check_bridge(drv, bss, params->bridge[0],
6574 params->ifname) < 0)
6575 goto failed;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006576 if (os_strcmp(params->bridge[0], master_ifname) != 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006577 br_added = 1;
6578 }
6579
6580 if (!br_added && br_ifindex &&
6581 (params->num_bridge == 0 || !params->bridge[0]))
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006582 add_ifidx(drv, br_ifindex, drv->ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006583
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006584#ifdef CONFIG_LIBNL3_ROUTE
6585 if (bss->added_if_into_bridge) {
6586 drv->rtnl_sk = nl_socket_alloc();
6587 if (drv->rtnl_sk == NULL) {
6588 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
6589 goto failed;
6590 }
6591
6592 if (nl_connect(drv->rtnl_sk, NETLINK_ROUTE)) {
6593 wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
6594 strerror(errno));
6595 goto failed;
6596 }
6597 }
6598#endif /* CONFIG_LIBNL3_ROUTE */
6599
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006600 drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
6601 if (drv->eapol_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006602 wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s",
6603 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006604 goto failed;
6605 }
6606
6607 if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
6608 {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006609 wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006610 goto failed;
6611 }
6612
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006613 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
6614 params->own_addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006615 goto failed;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006616 os_memcpy(drv->perm_addr, params->own_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006617
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006618 memcpy(bss->addr, params->own_addr, ETH_ALEN);
6619
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006620 return bss;
6621
6622failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006623 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006624 return NULL;
6625}
6626
6627
6628static void i802_deinit(void *priv)
6629{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006630 struct i802_bss *bss = priv;
6631 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006632}
6633
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006634
6635static enum nl80211_iftype wpa_driver_nl80211_if_type(
6636 enum wpa_driver_if_type type)
6637{
6638 switch (type) {
6639 case WPA_IF_STATION:
6640 return NL80211_IFTYPE_STATION;
6641 case WPA_IF_P2P_CLIENT:
6642 case WPA_IF_P2P_GROUP:
6643 return NL80211_IFTYPE_P2P_CLIENT;
6644 case WPA_IF_AP_VLAN:
6645 return NL80211_IFTYPE_AP_VLAN;
6646 case WPA_IF_AP_BSS:
6647 return NL80211_IFTYPE_AP;
6648 case WPA_IF_P2P_GO:
6649 return NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006650 case WPA_IF_P2P_DEVICE:
6651 return NL80211_IFTYPE_P2P_DEVICE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006652 case WPA_IF_MESH:
6653 return NL80211_IFTYPE_MESH_POINT;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006654 default:
6655 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006656 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006657}
6658
6659
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006660static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr)
6661{
6662 struct wpa_driver_nl80211_data *drv;
6663 dl_list_for_each(drv, &global->interfaces,
6664 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006665 if (os_memcmp(addr, drv->first_bss->addr, ETH_ALEN) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006666 return 1;
6667 }
6668 return 0;
6669}
6670
6671
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006672static int nl80211_vif_addr(struct wpa_driver_nl80211_data *drv, u8 *new_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006673{
6674 unsigned int idx;
6675
6676 if (!drv->global)
6677 return -1;
6678
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006679 os_memcpy(new_addr, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006680 for (idx = 0; idx < 64; idx++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006681 new_addr[0] = drv->first_bss->addr[0] | 0x02;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006682 new_addr[0] ^= idx << 2;
6683 if (!nl80211_addr_in_use(drv->global, new_addr))
6684 break;
6685 }
6686 if (idx == 64)
6687 return -1;
6688
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006689 wpa_printf(MSG_DEBUG, "nl80211: Assigned new virtual interface address "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006690 MACSTR, MAC2STR(new_addr));
6691
6692 return 0;
6693}
6694
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006695
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006696struct wdev_info {
6697 u64 wdev_id;
6698 int wdev_id_set;
6699 u8 macaddr[ETH_ALEN];
6700};
6701
6702static int nl80211_wdev_handler(struct nl_msg *msg, void *arg)
6703{
6704 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6705 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6706 struct wdev_info *wi = arg;
6707
6708 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6709 genlmsg_attrlen(gnlh, 0), NULL);
6710 if (tb[NL80211_ATTR_WDEV]) {
6711 wi->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
6712 wi->wdev_id_set = 1;
6713 }
6714
6715 if (tb[NL80211_ATTR_MAC])
6716 os_memcpy(wi->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
6717 ETH_ALEN);
6718
6719 return NL_SKIP;
6720}
6721
6722
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006723static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
6724 const char *ifname, const u8 *addr,
6725 void *bss_ctx, void **drv_priv,
6726 char *force_ifname, u8 *if_addr,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006727 const char *bridge, int use_existing,
6728 int setup_ap)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006729{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006730 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006731 struct i802_bss *bss = priv;
6732 struct wpa_driver_nl80211_data *drv = bss->drv;
6733 int ifidx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006734 int added = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006735
6736 if (addr)
6737 os_memcpy(if_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006738 nlmode = wpa_driver_nl80211_if_type(type);
6739 if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
6740 struct wdev_info p2pdev_info;
6741
6742 os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
6743 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
6744 0, nl80211_wdev_handler,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006745 &p2pdev_info, use_existing);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006746 if (!p2pdev_info.wdev_id_set || ifidx != 0) {
6747 wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s",
6748 ifname);
6749 return -1;
6750 }
6751
6752 drv->global->if_add_wdevid = p2pdev_info.wdev_id;
6753 drv->global->if_add_wdevid_set = p2pdev_info.wdev_id_set;
6754 if (!is_zero_ether_addr(p2pdev_info.macaddr))
6755 os_memcpy(if_addr, p2pdev_info.macaddr, ETH_ALEN);
6756 wpa_printf(MSG_DEBUG, "nl80211: New P2P Device interface %s (0x%llx) created",
6757 ifname,
6758 (long long unsigned int) p2pdev_info.wdev_id);
6759 } else {
6760 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006761 0, NULL, NULL, use_existing);
6762 if (use_existing && ifidx == -ENFILE) {
6763 added = 0;
6764 ifidx = if_nametoindex(ifname);
6765 } else if (ifidx < 0) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006766 return -1;
6767 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006768 }
6769
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006770 if (!addr) {
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006771 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006772 os_memcpy(if_addr, bss->addr, ETH_ALEN);
6773 else if (linux_get_ifhwaddr(drv->global->ioctl_sock,
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006774 ifname, if_addr) < 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006775 if (added)
6776 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006777 return -1;
6778 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006779 }
6780
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006781 if (!addr &&
6782 (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006783 type == WPA_IF_P2P_GO || type == WPA_IF_MESH ||
6784 type == WPA_IF_STATION)) {
6785 /* Enforce unique address */
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006786 u8 new_addr[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006787
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006788 if (linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006789 new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -07006790 if (added)
6791 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006792 return -1;
6793 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006794 if (nl80211_addr_in_use(drv->global, new_addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006795 wpa_printf(MSG_DEBUG, "nl80211: Allocate new address "
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07006796 "for interface %s type %d", ifname, type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006797 if (nl80211_vif_addr(drv, new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -07006798 if (added)
6799 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006800 return -1;
6801 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006802 if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006803 new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -07006804 if (added)
6805 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006806 return -1;
6807 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006808 }
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07006809 os_memcpy(if_addr, new_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006810 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006811
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006812 if (type == WPA_IF_AP_BSS && setup_ap) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006813 struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
6814 if (new_bss == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006815 if (added)
6816 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006817 return -1;
6818 }
6819
6820 if (bridge &&
6821 i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
6822 wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
6823 "interface %s to a bridge %s",
6824 ifname, bridge);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006825 if (added)
6826 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006827 os_free(new_bss);
6828 return -1;
6829 }
6830
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006831 if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
6832 {
Dmitry Shmidt71757432014-06-02 13:50:35 -07006833 if (added)
6834 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006835 os_free(new_bss);
6836 return -1;
6837 }
6838 os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006839 os_memcpy(new_bss->addr, if_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006840 new_bss->ifindex = ifidx;
6841 new_bss->drv = drv;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006842 new_bss->next = drv->first_bss->next;
6843 new_bss->freq = drv->first_bss->freq;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006844 new_bss->ctx = bss_ctx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006845 new_bss->added_if = added;
6846 drv->first_bss->next = new_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006847 if (drv_priv)
6848 *drv_priv = new_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006849 nl80211_init_bss(new_bss);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006850
6851 /* Subscribe management frames for this WPA_IF_AP_BSS */
6852 if (nl80211_setup_ap(new_bss))
6853 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006854 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006855
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006856 if (drv->global)
6857 drv->global->if_add_ifindex = ifidx;
6858
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006859 /*
6860 * Some virtual interfaces need to process EAPOL packets and events on
6861 * the parent interface. This is used mainly with hostapd.
6862 */
6863 if (ifidx > 0 &&
6864 (drv->hostapd ||
6865 nlmode == NL80211_IFTYPE_AP_VLAN ||
6866 nlmode == NL80211_IFTYPE_WDS ||
6867 nlmode == NL80211_IFTYPE_MONITOR))
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006868 add_ifidx(drv, ifidx, IFIDX_ANY);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006869
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006870 return 0;
6871}
6872
6873
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006874static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006875 enum wpa_driver_if_type type,
6876 const char *ifname)
6877{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006878 struct wpa_driver_nl80211_data *drv = bss->drv;
6879 int ifindex = if_nametoindex(ifname);
6880
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006881 wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d",
6882 __func__, type, ifname, ifindex, bss->added_if);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08006883 if (ifindex > 0 && (bss->added_if || bss->ifindex != ifindex))
Dmitry Shmidt051af732013-10-22 13:52:46 -07006884 nl80211_remove_iface(drv, ifindex);
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07006885 else if (ifindex > 0 && !bss->added_if) {
6886 struct wpa_driver_nl80211_data *drv2;
6887 dl_list_for_each(drv2, &drv->global->interfaces,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006888 struct wpa_driver_nl80211_data, list) {
6889 del_ifidx(drv2, ifindex, IFIDX_ANY);
6890 del_ifidx(drv2, IFIDX_ANY, ifindex);
6891 }
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07006892 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006893
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006894 if (type != WPA_IF_AP_BSS)
6895 return 0;
6896
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006897 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006898 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
6899 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006900 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
6901 "interface %s from bridge %s: %s",
6902 bss->ifname, bss->brname, strerror(errno));
6903 }
6904 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006905 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006906 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
6907 "bridge %s: %s",
6908 bss->brname, strerror(errno));
6909 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006910
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006911 if (bss != drv->first_bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006912 struct i802_bss *tbss;
6913
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006914 wpa_printf(MSG_DEBUG, "nl80211: Not the first BSS - remove it");
6915 for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006916 if (tbss->next == bss) {
6917 tbss->next = bss->next;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006918 /* Unsubscribe management frames */
6919 nl80211_teardown_ap(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006920 nl80211_destroy_bss(bss);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006921 if (!bss->added_if)
6922 i802_set_iface_flags(bss, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006923 os_free(bss);
6924 bss = NULL;
6925 break;
6926 }
6927 }
6928 if (bss)
6929 wpa_printf(MSG_INFO, "nl80211: %s - could not find "
6930 "BSS %p in the list", __func__, bss);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006931 } else {
6932 wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
6933 nl80211_teardown_ap(bss);
6934 if (!bss->added_if && !drv->first_bss->next)
Paul Stewart092955c2017-02-06 09:13:09 -08006935 wpa_driver_nl80211_del_beacon(bss);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006936 nl80211_destroy_bss(bss);
6937 if (!bss->added_if)
6938 i802_set_iface_flags(bss, 0);
6939 if (drv->first_bss->next) {
6940 drv->first_bss = drv->first_bss->next;
6941 drv->ctx = drv->first_bss->ctx;
6942 os_free(bss);
6943 } else {
6944 wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
6945 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006946 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006947
6948 return 0;
6949}
6950
6951
6952static int cookie_handler(struct nl_msg *msg, void *arg)
6953{
6954 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6955 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6956 u64 *cookie = arg;
6957 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6958 genlmsg_attrlen(gnlh, 0), NULL);
6959 if (tb[NL80211_ATTR_COOKIE])
6960 *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
6961 return NL_SKIP;
6962}
6963
6964
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006965static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006966 unsigned int freq, unsigned int wait,
6967 const u8 *buf, size_t buf_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006968 u64 *cookie_out, int no_cck, int no_ack,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006969 int offchanok, const u16 *csa_offs,
6970 size_t csa_offs_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006971{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006972 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006973 struct nl_msg *msg;
6974 u64 cookie;
6975 int ret = -1;
6976
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006977 wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
Dmitry Shmidt04949592012-07-19 12:16:46 -07006978 "no_ack=%d offchanok=%d",
6979 freq, wait, no_cck, no_ack, offchanok);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006980 wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006981
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006982 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) ||
6983 (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
6984 (wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) ||
6985 (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
6986 drv->test_use_roc_tx) &&
6987 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) ||
6988 (no_cck && nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE)) ||
6989 (no_ack && nla_put_flag(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK)) ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006990 (csa_offs && nla_put(msg, NL80211_ATTR_CSA_C_OFFSETS_TX,
6991 csa_offs_len * sizeof(u16), csa_offs)) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006992 nla_put(msg, NL80211_ATTR_FRAME, buf_len, buf))
6993 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006994
6995 cookie = 0;
6996 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
6997 msg = NULL;
6998 if (ret) {
6999 wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07007000 "(%s) (freq=%u wait=%u)", ret, strerror(-ret),
7001 freq, wait);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007002 } else {
7003 wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; "
7004 "cookie 0x%llx", no_ack ? " (no ACK)" : "",
7005 (long long unsigned int) cookie);
7006
7007 if (cookie_out)
7008 *cookie_out = no_ack ? (u64) -1 : cookie;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007009
7010 if (drv->num_send_action_cookies == MAX_SEND_ACTION_COOKIES) {
7011 wpa_printf(MSG_DEBUG,
7012 "nl80211: Drop oldest pending send action cookie 0x%llx",
7013 (long long unsigned int)
7014 drv->send_action_cookies[0]);
7015 os_memmove(&drv->send_action_cookies[0],
7016 &drv->send_action_cookies[1],
7017 (MAX_SEND_ACTION_COOKIES - 1) *
7018 sizeof(u64));
7019 drv->num_send_action_cookies--;
7020 }
7021 drv->send_action_cookies[drv->num_send_action_cookies] = cookie;
7022 drv->num_send_action_cookies++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007023 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007024
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007025fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007026 nlmsg_free(msg);
7027 return ret;
7028}
7029
7030
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007031static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
7032 unsigned int freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007033 unsigned int wait_time,
7034 const u8 *dst, const u8 *src,
7035 const u8 *bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007036 const u8 *data, size_t data_len,
7037 int no_cck)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007038{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007039 struct wpa_driver_nl80211_data *drv = bss->drv;
7040 int ret = -1;
7041 u8 *buf;
7042 struct ieee80211_hdr *hdr;
7043
7044 wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007045 "freq=%u MHz wait=%d ms no_cck=%d)",
7046 drv->ifindex, freq, wait_time, no_cck);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007047
7048 buf = os_zalloc(24 + data_len);
7049 if (buf == NULL)
7050 return ret;
7051 os_memcpy(buf + 24, data, data_len);
7052 hdr = (struct ieee80211_hdr *) buf;
7053 hdr->frame_control =
7054 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);
7055 os_memcpy(hdr->addr1, dst, ETH_ALEN);
7056 os_memcpy(hdr->addr2, src, ETH_ALEN);
7057 os_memcpy(hdr->addr3, bssid, ETH_ALEN);
7058
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08007059 if (os_memcmp(bss->addr, src, ETH_ALEN) != 0) {
7060 wpa_printf(MSG_DEBUG, "nl80211: Use random TA " MACSTR,
7061 MAC2STR(src));
7062 os_memcpy(bss->rand_addr, src, ETH_ALEN);
7063 } else {
7064 os_memset(bss->rand_addr, 0, ETH_ALEN);
7065 }
7066
Dmitry Shmidt56052862013-10-04 10:23:25 -07007067 if (is_ap_interface(drv->nlmode) &&
7068 (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
7069 (int) freq == bss->freq || drv->device_ap_sme ||
7070 !drv->use_monitor))
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007071 ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
7072 0, freq, no_cck, 1,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007073 wait_time, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007074 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007075 ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007076 24 + data_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007077 &drv->send_action_cookie,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007078 no_cck, 0, 1, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007079
7080 os_free(buf);
7081 return ret;
7082}
7083
7084
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007085static void nl80211_frame_wait_cancel(struct i802_bss *bss, u64 cookie)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007086{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007087 struct wpa_driver_nl80211_data *drv = bss->drv;
7088 struct nl_msg *msg;
7089 int ret;
7090
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08007091 wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx",
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007092 (long long unsigned int) cookie);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007093 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME_WAIT_CANCEL)) ||
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007094 nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007095 nlmsg_free(msg);
7096 return;
7097 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007098
7099 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007100 if (ret)
7101 wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
7102 "(%s)", ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007103}
7104
7105
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007106static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
7107{
7108 struct i802_bss *bss = priv;
7109 struct wpa_driver_nl80211_data *drv = bss->drv;
7110 unsigned int i;
7111 u64 cookie;
7112
7113 /* Cancel the last pending TX cookie */
7114 nl80211_frame_wait_cancel(bss, drv->send_action_cookie);
7115
7116 /*
7117 * Cancel the other pending TX cookies, if any. This is needed since
7118 * the driver may keep a list of all pending offchannel TX operations
7119 * and free up the radio only once they have expired or cancelled.
7120 */
7121 for (i = drv->num_send_action_cookies; i > 0; i--) {
7122 cookie = drv->send_action_cookies[i - 1];
7123 if (cookie != drv->send_action_cookie)
7124 nl80211_frame_wait_cancel(bss, cookie);
7125 }
7126 drv->num_send_action_cookies = 0;
7127}
7128
7129
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007130static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
7131 unsigned int duration)
7132{
7133 struct i802_bss *bss = priv;
7134 struct wpa_driver_nl80211_data *drv = bss->drv;
7135 struct nl_msg *msg;
7136 int ret;
7137 u64 cookie;
7138
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007139 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REMAIN_ON_CHANNEL)) ||
7140 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
7141 nla_put_u32(msg, NL80211_ATTR_DURATION, duration)) {
7142 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007143 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007144 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007145
7146 cookie = 0;
7147 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
7148 if (ret == 0) {
7149 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
7150 "0x%llx for freq=%u MHz duration=%u",
7151 (long long unsigned int) cookie, freq, duration);
7152 drv->remain_on_chan_cookie = cookie;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007153 drv->pending_remain_on_chan = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007154 return 0;
7155 }
7156 wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel "
7157 "(freq=%d duration=%u): %d (%s)",
7158 freq, duration, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007159 return -1;
7160}
7161
7162
7163static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
7164{
7165 struct i802_bss *bss = priv;
7166 struct wpa_driver_nl80211_data *drv = bss->drv;
7167 struct nl_msg *msg;
7168 int ret;
7169
7170 if (!drv->pending_remain_on_chan) {
7171 wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel "
7172 "to cancel");
7173 return -1;
7174 }
7175
7176 wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie "
7177 "0x%llx",
7178 (long long unsigned int) drv->remain_on_chan_cookie);
7179
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007180 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
7181 if (!msg ||
7182 nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie)) {
7183 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007184 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007185 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007186
7187 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7188 if (ret == 0)
7189 return 0;
7190 wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
7191 "%d (%s)", ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007192 return -1;
7193}
7194
7195
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007196static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007197{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007198 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07007199
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007200 if (!report) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007201 if (bss->nl_preq && drv->device_ap_sme &&
Dmitry Shmidt03658832014-08-13 11:03:49 -07007202 is_ap_interface(drv->nlmode) && !bss->in_deinit &&
7203 !bss->static_ap) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007204 /*
7205 * Do not disable Probe Request reporting that was
7206 * enabled in nl80211_setup_ap().
7207 */
7208 wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of "
7209 "Probe Request reporting nl_preq=%p while "
7210 "in AP mode", bss->nl_preq);
7211 } else if (bss->nl_preq) {
7212 wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
7213 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007214 nl80211_destroy_eloop_handle(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007215 }
7216 return 0;
7217 }
7218
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007219 if (bss->nl_preq) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007220 wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007221 "already on! nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007222 return 0;
7223 }
7224
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007225 bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq");
7226 if (bss->nl_preq == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007227 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007228 wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request "
7229 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007230
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007231 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007232 (WLAN_FC_TYPE_MGMT << 2) |
7233 (WLAN_FC_STYPE_PROBE_REQ << 4),
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007234 NULL, 0) < 0)
7235 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07007236
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007237 nl80211_register_eloop_read(&bss->nl_preq,
7238 wpa_driver_nl80211_event_receive,
7239 bss->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007240
7241 return 0;
7242
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007243 out_err:
7244 nl_destroy_handles(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007245 return -1;
7246}
7247
7248
7249static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
7250 int ifindex, int disabled)
7251{
7252 struct nl_msg *msg;
7253 struct nlattr *bands, *band;
7254 int ret;
7255
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007256 wpa_printf(MSG_DEBUG,
7257 "nl80211: NL80211_CMD_SET_TX_BITRATE_MASK (ifindex=%d %s)",
7258 ifindex, disabled ? "NL80211_TXRATE_LEGACY=OFDM-only" :
7259 "no NL80211_TXRATE_LEGACY constraint");
7260
7261 msg = nl80211_ifindex_msg(drv, ifindex, 0,
7262 NL80211_CMD_SET_TX_BITRATE_MASK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007263 if (!msg)
7264 return -1;
7265
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007266 bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
7267 if (!bands)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007268 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007269
7270 /*
7271 * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything
7272 * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS
7273 * rates. All 5 GHz rates are left enabled.
7274 */
7275 band = nla_nest_start(msg, NL80211_BAND_2GHZ);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007276 if (!band ||
7277 (disabled && nla_put(msg, NL80211_TXRATE_LEGACY, 8,
7278 "\x0c\x12\x18\x24\x30\x48\x60\x6c")))
7279 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007280 nla_nest_end(msg, band);
7281
7282 nla_nest_end(msg, bands);
7283
7284 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007285 if (ret) {
7286 wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
7287 "(%s)", ret, strerror(-ret));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007288 } else
7289 drv->disabled_11b_rates = disabled;
7290
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007291 return ret;
7292
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007293fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007294 nlmsg_free(msg);
7295 return -1;
7296}
7297
7298
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007299static int wpa_driver_nl80211_deinit_ap(void *priv)
7300{
7301 struct i802_bss *bss = priv;
7302 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007303 if (!is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007304 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -08007305 wpa_driver_nl80211_del_beacon(bss);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007306 bss->beacon_set = 0;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007307
7308 /*
7309 * If the P2P GO interface was dynamically added, then it is
7310 * possible that the interface change to station is not possible.
7311 */
7312 if (drv->nlmode == NL80211_IFTYPE_P2P_GO && bss->if_dynamic)
7313 return 0;
7314
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007315 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007316}
7317
7318
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007319static int wpa_driver_nl80211_stop_ap(void *priv)
7320{
7321 struct i802_bss *bss = priv;
7322 struct wpa_driver_nl80211_data *drv = bss->drv;
7323 if (!is_ap_interface(drv->nlmode))
7324 return -1;
Paul Stewart092955c2017-02-06 09:13:09 -08007325 wpa_driver_nl80211_del_beacon(bss);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007326 bss->beacon_set = 0;
7327 return 0;
7328}
7329
7330
Dmitry Shmidt04949592012-07-19 12:16:46 -07007331static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
7332{
7333 struct i802_bss *bss = priv;
7334 struct wpa_driver_nl80211_data *drv = bss->drv;
7335 if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)
7336 return -1;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007337
7338 /*
7339 * If the P2P Client interface was dynamically added, then it is
7340 * possible that the interface change to station is not possible.
7341 */
7342 if (bss->if_dynamic)
7343 return 0;
7344
Dmitry Shmidt04949592012-07-19 12:16:46 -07007345 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
7346}
7347
7348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007349static void wpa_driver_nl80211_resume(void *priv)
7350{
7351 struct i802_bss *bss = priv;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007352 enum nl80211_iftype nlmode = nl80211_get_ifmode(bss);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007353
7354 if (i802_set_iface_flags(bss, 1))
7355 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007356
7357 if (is_p2p_net_interface(nlmode))
7358 nl80211_disable_11b_rates(bss->drv, bss->drv->ifindex, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007359}
7360
7361
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007362static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
7363{
7364 struct i802_bss *bss = priv;
7365 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007366 struct nl_msg *msg;
7367 struct nlattr *cqm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007368
7369 wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
7370 "hysteresis=%d", threshold, hysteresis);
7371
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007372 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_CQM)) ||
7373 !(cqm = nla_nest_start(msg, NL80211_ATTR_CQM)) ||
7374 nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold) ||
7375 nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis)) {
7376 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007377 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007378 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007379 nla_nest_end(msg, cqm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007380
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007381 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007382}
7383
7384
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007385static int get_channel_width(struct nl_msg *msg, void *arg)
7386{
7387 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7388 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7389 struct wpa_signal_info *sig_change = arg;
7390
7391 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7392 genlmsg_attrlen(gnlh, 0), NULL);
7393
7394 sig_change->center_frq1 = -1;
7395 sig_change->center_frq2 = -1;
7396 sig_change->chanwidth = CHAN_WIDTH_UNKNOWN;
7397
7398 if (tb[NL80211_ATTR_CHANNEL_WIDTH]) {
7399 sig_change->chanwidth = convert2width(
7400 nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
7401 if (tb[NL80211_ATTR_CENTER_FREQ1])
7402 sig_change->center_frq1 =
7403 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
7404 if (tb[NL80211_ATTR_CENTER_FREQ2])
7405 sig_change->center_frq2 =
7406 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
7407 }
7408
7409 return NL_SKIP;
7410}
7411
7412
7413static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
7414 struct wpa_signal_info *sig)
7415{
7416 struct nl_msg *msg;
7417
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007418 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007419 return send_and_recv_msgs(drv, msg, get_channel_width, sig);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007420}
7421
7422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007423static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
7424{
7425 struct i802_bss *bss = priv;
7426 struct wpa_driver_nl80211_data *drv = bss->drv;
7427 int res;
7428
7429 os_memset(si, 0, sizeof(*si));
7430 res = nl80211_get_link_signal(drv, si);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007431 if (res) {
7432 if (drv->nlmode != NL80211_IFTYPE_ADHOC &&
7433 drv->nlmode != NL80211_IFTYPE_MESH_POINT)
7434 return res;
7435 si->current_signal = 0;
7436 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007437
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007438 res = nl80211_get_channel_width(drv, si);
7439 if (res != 0)
7440 return res;
7441
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007442 return nl80211_get_link_noise(drv, si);
7443}
7444
7445
7446static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
7447 int encrypt)
7448{
7449 struct i802_bss *bss = priv;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007450 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007451 0, 0, 0, 0, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007452}
7453
7454
7455static int nl80211_set_param(void *priv, const char *param)
7456{
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07007457 struct i802_bss *bss = priv;
7458 struct wpa_driver_nl80211_data *drv = bss->drv;
7459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007460 if (param == NULL)
7461 return 0;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08007462 wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007463
7464#ifdef CONFIG_P2P
7465 if (os_strstr(param, "use_p2p_group_interface=1")) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007466 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
7467 "interface");
7468 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
7469 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
7470 }
7471#endif /* CONFIG_P2P */
7472
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07007473 if (os_strstr(param, "use_monitor=1"))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007474 drv->use_monitor = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007475
7476 if (os_strstr(param, "force_connect_cmd=1")) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007477 drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07007478 drv->force_connect_cmd = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007479 }
7480
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07007481 if (os_strstr(param, "force_bss_selection=1"))
7482 drv->capa.flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
7483
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08007484 if (os_strstr(param, "no_offchannel_tx=1")) {
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08007485 drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
7486 drv->test_use_roc_tx = 1;
7487 }
7488
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007489 return 0;
7490}
7491
7492
Dmitry Shmidte4663042016-04-04 10:07:49 -07007493static void * nl80211_global_init(void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007494{
7495 struct nl80211_global *global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007496 struct netlink_config *cfg;
7497
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007498 global = os_zalloc(sizeof(*global));
7499 if (global == NULL)
7500 return NULL;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007501 global->ctx = ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007502 global->ioctl_sock = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007503 dl_list_init(&global->interfaces);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007504 global->if_add_ifindex = -1;
7505
7506 cfg = os_zalloc(sizeof(*cfg));
7507 if (cfg == NULL)
7508 goto err;
7509
7510 cfg->ctx = global;
7511 cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
7512 cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
7513 global->netlink = netlink_init(cfg);
7514 if (global->netlink == NULL) {
7515 os_free(cfg);
7516 goto err;
7517 }
7518
7519 if (wpa_driver_nl80211_init_nl_global(global) < 0)
7520 goto err;
7521
7522 global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
7523 if (global->ioctl_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007524 wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",
7525 strerror(errno));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007526 goto err;
7527 }
7528
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007529 return global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007530
7531err:
7532 nl80211_global_deinit(global);
7533 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007534}
7535
7536
7537static void nl80211_global_deinit(void *priv)
7538{
7539 struct nl80211_global *global = priv;
7540 if (global == NULL)
7541 return;
7542 if (!dl_list_empty(&global->interfaces)) {
7543 wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at "
7544 "nl80211_global_deinit",
7545 dl_list_len(&global->interfaces));
7546 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007547
7548 if (global->netlink)
7549 netlink_deinit(global->netlink);
7550
7551 nl_destroy_handles(&global->nl);
7552
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007553 if (global->nl_event)
7554 nl80211_destroy_eloop_handle(&global->nl_event);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007555
7556 nl_cb_put(global->nl_cb);
7557
7558 if (global->ioctl_sock >= 0)
7559 close(global->ioctl_sock);
7560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007561 os_free(global);
7562}
7563
7564
7565static const char * nl80211_get_radio_name(void *priv)
7566{
7567 struct i802_bss *bss = priv;
7568 struct wpa_driver_nl80211_data *drv = bss->drv;
7569 return drv->phyname;
7570}
7571
7572
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007573static int nl80211_pmkid(struct i802_bss *bss, int cmd,
7574 struct wpa_pmkid_params *params)
Jouni Malinen75ecf522011-06-27 15:19:46 -07007575{
7576 struct nl_msg *msg;
7577
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007578 if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007579 (params->pmkid &&
7580 nla_put(msg, NL80211_ATTR_PMKID, 16, params->pmkid)) ||
7581 (params->bssid &&
7582 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid)) ||
7583 (params->ssid_len &&
7584 nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid)) ||
7585 (params->fils_cache_id &&
7586 nla_put(msg, NL80211_ATTR_FILS_CACHE_ID, 2,
7587 params->fils_cache_id)) ||
7588 (params->pmk_len &&
7589 nla_put(msg, NL80211_ATTR_PMK, params->pmk_len, params->pmk))) {
Hai Shalom0f8669c2019-02-26 16:17:45 -08007590 nl80211_nlmsg_clear(msg);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007591 nlmsg_free(msg);
7592 return -ENOBUFS;
7593 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07007594
Hai Shalom0f8669c2019-02-26 16:17:45 -08007595 return send_and_recv_msgs(bss->drv, msg, NULL, (void *) -1);
Jouni Malinen75ecf522011-06-27 15:19:46 -07007596}
7597
7598
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007599static int nl80211_add_pmkid(void *priv, struct wpa_pmkid_params *params)
Jouni Malinen75ecf522011-06-27 15:19:46 -07007600{
7601 struct i802_bss *bss = priv;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007602
7603 if (params->bssid)
7604 wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR,
7605 MAC2STR(params->bssid));
7606 else if (params->fils_cache_id && params->ssid_len) {
7607 wpa_printf(MSG_DEBUG,
7608 "nl80211: Add PMKSA for cache id %02x%02x SSID %s",
7609 params->fils_cache_id[0], params->fils_cache_id[1],
7610 wpa_ssid_txt(params->ssid, params->ssid_len));
7611 }
7612
7613 return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, params);
Jouni Malinen75ecf522011-06-27 15:19:46 -07007614}
7615
7616
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007617static int nl80211_remove_pmkid(void *priv, struct wpa_pmkid_params *params)
Jouni Malinen75ecf522011-06-27 15:19:46 -07007618{
7619 struct i802_bss *bss = priv;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007620
7621 if (params->bssid)
7622 wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR,
7623 MAC2STR(params->bssid));
7624 else if (params->fils_cache_id && params->ssid_len) {
7625 wpa_printf(MSG_DEBUG,
7626 "nl80211: Delete PMKSA for cache id %02x%02x SSID %s",
7627 params->fils_cache_id[0], params->fils_cache_id[1],
7628 wpa_ssid_txt(params->ssid, params->ssid_len));
7629 }
7630
7631 return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, params);
Jouni Malinen75ecf522011-06-27 15:19:46 -07007632}
7633
7634
7635static int nl80211_flush_pmkid(void *priv)
7636{
7637 struct i802_bss *bss = priv;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007638 struct nl_msg *msg;
7639
Jouni Malinen75ecf522011-06-27 15:19:46 -07007640 wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007641 msg = nl80211_bss_msg(bss, 0, NL80211_CMD_FLUSH_PMKSA);
7642 if (!msg)
7643 return -ENOBUFS;
7644 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Jouni Malinen75ecf522011-06-27 15:19:46 -07007645}
7646
7647
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007648static void clean_survey_results(struct survey_results *survey_results)
7649{
7650 struct freq_survey *survey, *tmp;
7651
7652 if (dl_list_empty(&survey_results->survey_list))
7653 return;
7654
7655 dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
7656 struct freq_survey, list) {
7657 dl_list_del(&survey->list);
7658 os_free(survey);
7659 }
7660}
7661
7662
7663static void add_survey(struct nlattr **sinfo, u32 ifidx,
7664 struct dl_list *survey_list)
7665{
7666 struct freq_survey *survey;
7667
7668 survey = os_zalloc(sizeof(struct freq_survey));
7669 if (!survey)
7670 return;
7671
7672 survey->ifidx = ifidx;
7673 survey->freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
7674 survey->filled = 0;
7675
7676 if (sinfo[NL80211_SURVEY_INFO_NOISE]) {
7677 survey->nf = (int8_t)
7678 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
7679 survey->filled |= SURVEY_HAS_NF;
7680 }
7681
7682 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]) {
7683 survey->channel_time =
7684 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]);
7685 survey->filled |= SURVEY_HAS_CHAN_TIME;
7686 }
7687
7688 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]) {
7689 survey->channel_time_busy =
7690 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]);
7691 survey->filled |= SURVEY_HAS_CHAN_TIME_BUSY;
7692 }
7693
7694 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]) {
7695 survey->channel_time_rx =
7696 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]);
7697 survey->filled |= SURVEY_HAS_CHAN_TIME_RX;
7698 }
7699
7700 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]) {
7701 survey->channel_time_tx =
7702 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]);
7703 survey->filled |= SURVEY_HAS_CHAN_TIME_TX;
7704 }
7705
7706 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)",
7707 survey->freq,
7708 survey->nf,
7709 (unsigned long int) survey->channel_time,
7710 (unsigned long int) survey->channel_time_busy,
7711 (unsigned long int) survey->channel_time_tx,
7712 (unsigned long int) survey->channel_time_rx,
7713 survey->filled);
7714
7715 dl_list_add_tail(survey_list, &survey->list);
7716}
7717
7718
7719static int check_survey_ok(struct nlattr **sinfo, u32 surveyed_freq,
7720 unsigned int freq_filter)
7721{
7722 if (!freq_filter)
7723 return 1;
7724
7725 return freq_filter == surveyed_freq;
7726}
7727
7728
7729static int survey_handler(struct nl_msg *msg, void *arg)
7730{
7731 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7732 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7733 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
7734 struct survey_results *survey_results;
7735 u32 surveyed_freq = 0;
7736 u32 ifidx;
7737
7738 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
7739 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
7740 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
7741 };
7742
7743 survey_results = (struct survey_results *) arg;
7744
7745 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7746 genlmsg_attrlen(gnlh, 0), NULL);
7747
Dmitry Shmidt97672262014-02-03 13:02:54 -08007748 if (!tb[NL80211_ATTR_IFINDEX])
7749 return NL_SKIP;
7750
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007751 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
7752
7753 if (!tb[NL80211_ATTR_SURVEY_INFO])
7754 return NL_SKIP;
7755
7756 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
7757 tb[NL80211_ATTR_SURVEY_INFO],
7758 survey_policy))
7759 return NL_SKIP;
7760
7761 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) {
7762 wpa_printf(MSG_ERROR, "nl80211: Invalid survey data");
7763 return NL_SKIP;
7764 }
7765
7766 surveyed_freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
7767
7768 if (!check_survey_ok(sinfo, surveyed_freq,
7769 survey_results->freq_filter))
7770 return NL_SKIP;
7771
7772 if (survey_results->freq_filter &&
7773 survey_results->freq_filter != surveyed_freq) {
7774 wpa_printf(MSG_EXCESSIVE, "nl80211: Ignoring survey data for freq %d MHz",
7775 surveyed_freq);
7776 return NL_SKIP;
7777 }
7778
7779 add_survey(sinfo, ifidx, &survey_results->survey_list);
7780
7781 return NL_SKIP;
7782}
7783
7784
7785static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
7786{
7787 struct i802_bss *bss = priv;
7788 struct wpa_driver_nl80211_data *drv = bss->drv;
7789 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007790 int err;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007791 union wpa_event_data data;
7792 struct survey_results *survey_results;
7793
7794 os_memset(&data, 0, sizeof(data));
7795 survey_results = &data.survey_results;
7796
7797 dl_list_init(&survey_results->survey_list);
7798
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007799 msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007800 if (!msg)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007801 return -ENOBUFS;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007802
7803 if (freq)
7804 data.survey_results.freq_filter = freq;
7805
7806 do {
7807 wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data");
7808 err = send_and_recv_msgs(drv, msg, survey_handler,
7809 survey_results);
7810 } while (err > 0);
7811
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007812 if (err)
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007813 wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007814 else
7815 wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007816
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007817 clean_survey_results(survey_results);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007818 return err;
7819}
7820
7821
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007822static void nl80211_set_rekey_info(void *priv, const u8 *kek, size_t kek_len,
7823 const u8 *kck, size_t kck_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007824 const u8 *replay_ctr)
7825{
7826 struct i802_bss *bss = priv;
7827 struct wpa_driver_nl80211_data *drv = bss->drv;
7828 struct nlattr *replay_nested;
7829 struct nl_msg *msg;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08007830 int ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007831
Dmitry Shmidtff787d52015-01-12 13:01:47 -08007832 if (!drv->set_rekey_offload)
7833 return;
7834
7835 wpa_printf(MSG_DEBUG, "nl80211: Set rekey offload");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007836 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_REKEY_OFFLOAD)) ||
7837 !(replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA)) ||
Dmitry Shmidt807291d2015-01-27 13:40:23 -08007838 nla_put(msg, NL80211_REKEY_DATA_KEK, kek_len, kek) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007839 (kck_len && nla_put(msg, NL80211_REKEY_DATA_KCK, kck_len, kck)) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007840 nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
7841 replay_ctr)) {
7842 nl80211_nlmsg_clear(msg);
7843 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007844 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007845 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007846
7847 nla_nest_end(msg, replay_nested);
7848
Dmitry Shmidtff787d52015-01-12 13:01:47 -08007849 ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
7850 if (ret == -EOPNOTSUPP) {
7851 wpa_printf(MSG_DEBUG,
7852 "nl80211: Driver does not support rekey offload");
7853 drv->set_rekey_offload = 0;
7854 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007855}
7856
7857
7858static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
7859 const u8 *addr, int qos)
7860{
7861 /* send data frame to poll STA and check whether
7862 * this frame is ACKed */
7863 struct {
7864 struct ieee80211_hdr hdr;
7865 u16 qos_ctl;
7866 } STRUCT_PACKED nulldata;
7867 size_t size;
7868
7869 /* Send data frame to poll STA and check whether this frame is ACKed */
7870
7871 os_memset(&nulldata, 0, sizeof(nulldata));
7872
7873 if (qos) {
7874 nulldata.hdr.frame_control =
7875 IEEE80211_FC(WLAN_FC_TYPE_DATA,
7876 WLAN_FC_STYPE_QOS_NULL);
7877 size = sizeof(nulldata);
7878 } else {
7879 nulldata.hdr.frame_control =
7880 IEEE80211_FC(WLAN_FC_TYPE_DATA,
7881 WLAN_FC_STYPE_NULLFUNC);
7882 size = sizeof(struct ieee80211_hdr);
7883 }
7884
7885 nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
7886 os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
7887 os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
7888 os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
7889
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007890 if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007891 0, 0, NULL, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007892 wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
7893 "send poll frame");
7894}
7895
7896static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
7897 int qos)
7898{
7899 struct i802_bss *bss = priv;
7900 struct wpa_driver_nl80211_data *drv = bss->drv;
7901 struct nl_msg *msg;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007902 int ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007903
7904 if (!drv->poll_command_supported) {
7905 nl80211_send_null_frame(bss, own_addr, addr, qos);
7906 return;
7907 }
7908
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007909 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_PROBE_CLIENT)) ||
7910 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
7911 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007912 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007913 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007914
Dmitry Shmidt7f656022015-02-25 14:36:37 -08007915 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7916 if (ret < 0) {
7917 wpa_printf(MSG_DEBUG, "nl80211: Client probe request for "
7918 MACSTR " failed: ret=%d (%s)",
7919 MAC2STR(addr), ret, strerror(-ret));
7920 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007921}
7922
7923
7924static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
7925{
7926 struct nl_msg *msg;
7927
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007928 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_POWER_SAVE)) ||
7929 nla_put_u32(msg, NL80211_ATTR_PS_STATE,
7930 enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED)) {
7931 nlmsg_free(msg);
7932 return -ENOBUFS;
7933 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007934 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007935}
7936
7937
7938static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,
7939 int ctwindow)
7940{
7941 struct i802_bss *bss = priv;
7942
7943 wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d "
7944 "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow);
7945
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08007946 if (opp_ps != -1 || ctwindow != -1) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007947#ifdef ANDROID_P2P
7948 wpa_driver_set_p2p_ps(priv, legacy_ps, opp_ps, ctwindow);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08007949#else /* ANDROID_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007950 return -1; /* Not yet supported */
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08007951#endif /* ANDROID_P2P */
7952 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007953
7954 if (legacy_ps == -1)
7955 return 0;
7956 if (legacy_ps != 0 && legacy_ps != 1)
7957 return -1; /* Not yet supported */
7958
7959 return nl80211_set_power_save(bss, legacy_ps);
7960}
7961
7962
Dmitry Shmidt051af732013-10-22 13:52:46 -07007963static int nl80211_start_radar_detection(void *priv,
7964 struct hostapd_freq_params *freq)
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007965{
7966 struct i802_bss *bss = priv;
7967 struct wpa_driver_nl80211_data *drv = bss->drv;
7968 struct nl_msg *msg;
7969 int ret;
7970
Dmitry Shmidt051af732013-10-22 13:52:46 -07007971 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)",
7972 freq->freq, freq->ht_enabled, freq->vht_enabled,
7973 freq->bandwidth, freq->center_freq1, freq->center_freq2);
7974
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007975 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
7976 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar "
7977 "detection");
7978 return -1;
7979 }
7980
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007981 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_RADAR_DETECT)) ||
7982 nl80211_put_freq_params(msg, freq) < 0) {
7983 nlmsg_free(msg);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007984 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007985 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007986
7987 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7988 if (ret == 0)
7989 return 0;
7990 wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
7991 "%d (%s)", ret, strerror(-ret));
Dmitry Shmidtea69e842013-05-13 14:52:28 -07007992 return -1;
7993}
7994
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007995#ifdef CONFIG_TDLS
7996
7997static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
7998 u8 dialog_token, u16 status_code,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07007999 u32 peer_capab, int initiator, const u8 *buf,
8000 size_t len)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008001{
8002 struct i802_bss *bss = priv;
8003 struct wpa_driver_nl80211_data *drv = bss->drv;
8004 struct nl_msg *msg;
8005
8006 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
8007 return -EOPNOTSUPP;
8008
8009 if (!dst)
8010 return -EINVAL;
8011
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008012 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_TDLS_MGMT)) ||
8013 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
8014 nla_put_u8(msg, NL80211_ATTR_TDLS_ACTION, action_code) ||
8015 nla_put_u8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token) ||
8016 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status_code))
8017 goto fail;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07008018 if (peer_capab) {
8019 /*
8020 * The internal enum tdls_peer_capability definition is
8021 * currently identical with the nl80211 enum
8022 * nl80211_tdls_peer_capability, so no conversion is needed
8023 * here.
8024 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008025 if (nla_put_u32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY,
8026 peer_capab))
8027 goto fail;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07008028 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008029 if ((initiator &&
8030 nla_put_flag(msg, NL80211_ATTR_TDLS_INITIATOR)) ||
8031 nla_put(msg, NL80211_ATTR_IE, len, buf))
8032 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008033
8034 return send_and_recv_msgs(drv, msg, NULL, NULL);
8035
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008036fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008037 nlmsg_free(msg);
8038 return -ENOBUFS;
8039}
8040
8041
8042static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
8043{
8044 struct i802_bss *bss = priv;
8045 struct wpa_driver_nl80211_data *drv = bss->drv;
8046 struct nl_msg *msg;
8047 enum nl80211_tdls_operation nl80211_oper;
Paul Stewart092955c2017-02-06 09:13:09 -08008048 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008049
8050 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
8051 return -EOPNOTSUPP;
8052
8053 switch (oper) {
8054 case TDLS_DISCOVERY_REQ:
8055 nl80211_oper = NL80211_TDLS_DISCOVERY_REQ;
8056 break;
8057 case TDLS_SETUP:
8058 nl80211_oper = NL80211_TDLS_SETUP;
8059 break;
8060 case TDLS_TEARDOWN:
8061 nl80211_oper = NL80211_TDLS_TEARDOWN;
8062 break;
8063 case TDLS_ENABLE_LINK:
8064 nl80211_oper = NL80211_TDLS_ENABLE_LINK;
8065 break;
8066 case TDLS_DISABLE_LINK:
8067 nl80211_oper = NL80211_TDLS_DISABLE_LINK;
8068 break;
8069 case TDLS_ENABLE:
8070 return 0;
8071 case TDLS_DISABLE:
8072 return 0;
8073 default:
8074 return -EINVAL;
8075 }
8076
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008077 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_TDLS_OPER)) ||
8078 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper) ||
8079 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) {
8080 nlmsg_free(msg);
8081 return -ENOBUFS;
8082 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008083
Paul Stewart092955c2017-02-06 09:13:09 -08008084 res = send_and_recv_msgs(drv, msg, NULL, NULL);
8085 wpa_printf(MSG_DEBUG, "nl80211: TDLS_OPER: oper=%d mac=" MACSTR
8086 " --> res=%d (%s)", nl80211_oper, MAC2STR(peer), res,
8087 strerror(-res));
8088 return res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008089}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008090
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008091
8092static int
8093nl80211_tdls_enable_channel_switch(void *priv, const u8 *addr, u8 oper_class,
8094 const struct hostapd_freq_params *params)
8095{
8096 struct i802_bss *bss = priv;
8097 struct wpa_driver_nl80211_data *drv = bss->drv;
8098 struct nl_msg *msg;
8099 int ret = -ENOBUFS;
8100
8101 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) ||
8102 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH))
8103 return -EOPNOTSUPP;
8104
8105 wpa_printf(MSG_DEBUG, "nl80211: Enable TDLS channel switch " MACSTR
8106 " oper_class=%u freq=%u",
8107 MAC2STR(addr), oper_class, params->freq);
8108 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_TDLS_CHANNEL_SWITCH);
8109 if (!msg ||
8110 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
8111 nla_put_u8(msg, NL80211_ATTR_OPER_CLASS, oper_class) ||
8112 (ret = nl80211_put_freq_params(msg, params))) {
8113 nlmsg_free(msg);
8114 wpa_printf(MSG_DEBUG, "nl80211: Could not build TDLS chan switch");
8115 return ret;
8116 }
8117
8118 return send_and_recv_msgs(drv, msg, NULL, NULL);
8119}
8120
8121
8122static int
8123nl80211_tdls_disable_channel_switch(void *priv, const u8 *addr)
8124{
8125 struct i802_bss *bss = priv;
8126 struct wpa_driver_nl80211_data *drv = bss->drv;
8127 struct nl_msg *msg;
8128
8129 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) ||
8130 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH))
8131 return -EOPNOTSUPP;
8132
8133 wpa_printf(MSG_DEBUG, "nl80211: Disable TDLS channel switch " MACSTR,
8134 MAC2STR(addr));
8135 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH);
8136 if (!msg ||
8137 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
8138 nlmsg_free(msg);
8139 wpa_printf(MSG_DEBUG,
8140 "nl80211: Could not build TDLS cancel chan switch");
8141 return -ENOBUFS;
8142 }
8143
8144 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008145}
8146
8147#endif /* CONFIG TDLS */
8148
8149
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008150static int driver_nl80211_set_key(const char *ifname, void *priv,
8151 enum wpa_alg alg, const u8 *addr,
8152 int key_idx, int set_tx,
8153 const u8 *seq, size_t seq_len,
8154 const u8 *key, size_t key_len)
8155{
8156 struct i802_bss *bss = priv;
8157 return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx,
8158 set_tx, seq, seq_len, key, key_len);
8159}
8160
8161
8162static int driver_nl80211_scan2(void *priv,
8163 struct wpa_driver_scan_params *params)
8164{
8165 struct i802_bss *bss = priv;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008166#ifdef CONFIG_DRIVER_NL80211_QCA
8167 struct wpa_driver_nl80211_data *drv = bss->drv;
8168
8169 /*
8170 * Do a vendor specific scan if possible. If only_new_results is
8171 * set, do a normal scan since a kernel (cfg80211) BSS cache flush
8172 * cannot be achieved through a vendor scan. The below condition may
8173 * need to be modified if new scan flags are added in the future whose
8174 * functionality can only be achieved through a normal scan.
8175 */
8176 if (drv->scan_vendor_cmd_avail && !params->only_new_results)
8177 return wpa_driver_nl80211_vendor_scan(bss, params);
8178#endif /* CONFIG_DRIVER_NL80211_QCA */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008179 return wpa_driver_nl80211_scan(bss, params);
8180}
8181
8182
8183static int driver_nl80211_deauthenticate(void *priv, const u8 *addr,
8184 int reason_code)
8185{
8186 struct i802_bss *bss = priv;
8187 return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code);
8188}
8189
8190
8191static int driver_nl80211_authenticate(void *priv,
8192 struct wpa_driver_auth_params *params)
8193{
8194 struct i802_bss *bss = priv;
8195 return wpa_driver_nl80211_authenticate(bss, params);
8196}
8197
8198
8199static void driver_nl80211_deinit(void *priv)
8200{
8201 struct i802_bss *bss = priv;
8202 wpa_driver_nl80211_deinit(bss);
8203}
8204
8205
8206static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
8207 const char *ifname)
8208{
8209 struct i802_bss *bss = priv;
8210 return wpa_driver_nl80211_if_remove(bss, type, ifname);
8211}
8212
8213
8214static int driver_nl80211_send_mlme(void *priv, const u8 *data,
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07008215 size_t data_len, int noack,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008216 unsigned int freq,
8217 const u16 *csa_offs, size_t csa_offs_len)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008218{
8219 struct i802_bss *bss = priv;
8220 return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008221 freq, 0, 0, 0, csa_offs,
8222 csa_offs_len);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008223}
8224
8225
8226static int driver_nl80211_sta_remove(void *priv, const u8 *addr)
8227{
8228 struct i802_bss *bss = priv;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008229 return wpa_driver_nl80211_sta_remove(bss, addr, -1, 0);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008230}
8231
8232
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008233static int driver_nl80211_set_sta_vlan(void *priv, const u8 *addr,
8234 const char *ifname, int vlan_id)
8235{
8236 struct i802_bss *bss = priv;
8237 return i802_set_sta_vlan(bss, addr, ifname, vlan_id);
8238}
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008239
8240
8241static int driver_nl80211_read_sta_data(void *priv,
8242 struct hostap_sta_driver_data *data,
8243 const u8 *addr)
8244{
8245 struct i802_bss *bss = priv;
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08008246
8247 os_memset(data, 0, sizeof(*data));
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008248 return i802_read_sta_data(bss, data, addr);
8249}
8250
8251
8252static int driver_nl80211_send_action(void *priv, unsigned int freq,
8253 unsigned int wait_time,
8254 const u8 *dst, const u8 *src,
8255 const u8 *bssid,
8256 const u8 *data, size_t data_len,
8257 int no_cck)
8258{
8259 struct i802_bss *bss = priv;
8260 return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src,
8261 bssid, data, data_len, no_cck);
8262}
8263
8264
8265static int driver_nl80211_probe_req_report(void *priv, int report)
8266{
8267 struct i802_bss *bss = priv;
8268 return wpa_driver_nl80211_probe_req_report(bss, report);
8269}
8270
8271
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008272static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
8273 const u8 *ies, size_t ies_len)
8274{
8275 int ret;
8276 struct nl_msg *msg;
8277 struct i802_bss *bss = priv;
8278 struct wpa_driver_nl80211_data *drv = bss->drv;
8279 u16 mdid = WPA_GET_LE16(md);
8280
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008281 wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008282 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_UPDATE_FT_IES)) ||
8283 nla_put(msg, NL80211_ATTR_IE, ies_len, ies) ||
8284 nla_put_u16(msg, NL80211_ATTR_MDID, mdid)) {
8285 nlmsg_free(msg);
8286 return -ENOBUFS;
8287 }
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008288
8289 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8290 if (ret) {
8291 wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
8292 "err=%d (%s)", ret, strerror(-ret));
8293 }
8294
8295 return ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008296}
8297
8298
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07008299static const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008300{
8301 struct i802_bss *bss = priv;
8302 struct wpa_driver_nl80211_data *drv = bss->drv;
8303
8304 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE)
8305 return NULL;
8306
8307 return bss->addr;
8308}
8309
8310
Dmitry Shmidt56052862013-10-04 10:23:25 -07008311static const char * scan_state_str(enum scan_states scan_state)
8312{
8313 switch (scan_state) {
8314 case NO_SCAN:
8315 return "NO_SCAN";
8316 case SCAN_REQUESTED:
8317 return "SCAN_REQUESTED";
8318 case SCAN_STARTED:
8319 return "SCAN_STARTED";
8320 case SCAN_COMPLETED:
8321 return "SCAN_COMPLETED";
8322 case SCAN_ABORTED:
8323 return "SCAN_ABORTED";
8324 case SCHED_SCAN_STARTED:
8325 return "SCHED_SCAN_STARTED";
8326 case SCHED_SCAN_STOPPED:
8327 return "SCHED_SCAN_STOPPED";
8328 case SCHED_SCAN_RESULTS:
8329 return "SCHED_SCAN_RESULTS";
8330 }
8331
8332 return "??";
8333}
8334
8335
8336static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
8337{
8338 struct i802_bss *bss = priv;
8339 struct wpa_driver_nl80211_data *drv = bss->drv;
8340 int res;
8341 char *pos, *end;
8342
8343 pos = buf;
8344 end = buf + buflen;
8345
8346 res = os_snprintf(pos, end - pos,
8347 "ifindex=%d\n"
8348 "ifname=%s\n"
8349 "brname=%s\n"
8350 "addr=" MACSTR "\n"
8351 "freq=%d\n"
8352 "%s%s%s%s%s",
8353 bss->ifindex,
8354 bss->ifname,
8355 bss->brname,
8356 MAC2STR(bss->addr),
8357 bss->freq,
8358 bss->beacon_set ? "beacon_set=1\n" : "",
8359 bss->added_if_into_bridge ?
8360 "added_if_into_bridge=1\n" : "",
8361 bss->added_bridge ? "added_bridge=1\n" : "",
8362 bss->in_deinit ? "in_deinit=1\n" : "",
8363 bss->if_dynamic ? "if_dynamic=1\n" : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008364 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt56052862013-10-04 10:23:25 -07008365 return pos - buf;
8366 pos += res;
8367
8368 if (bss->wdev_id_set) {
8369 res = os_snprintf(pos, end - pos, "wdev_id=%llu\n",
8370 (unsigned long long) bss->wdev_id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008371 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt56052862013-10-04 10:23:25 -07008372 return pos - buf;
8373 pos += res;
8374 }
8375
8376 res = os_snprintf(pos, end - pos,
8377 "phyname=%s\n"
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008378 "perm_addr=" MACSTR "\n"
Dmitry Shmidt56052862013-10-04 10:23:25 -07008379 "drv_ifindex=%d\n"
8380 "operstate=%d\n"
8381 "scan_state=%s\n"
8382 "auth_bssid=" MACSTR "\n"
8383 "auth_attempt_bssid=" MACSTR "\n"
8384 "bssid=" MACSTR "\n"
8385 "prev_bssid=" MACSTR "\n"
8386 "associated=%d\n"
8387 "assoc_freq=%u\n"
8388 "monitor_sock=%d\n"
8389 "monitor_ifidx=%d\n"
8390 "monitor_refcount=%d\n"
8391 "last_mgmt_freq=%u\n"
8392 "eapol_tx_sock=%d\n"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008393 "%s%s%s%s%s%s%s%s%s%s%s%s%s",
Dmitry Shmidt56052862013-10-04 10:23:25 -07008394 drv->phyname,
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008395 MAC2STR(drv->perm_addr),
Dmitry Shmidt56052862013-10-04 10:23:25 -07008396 drv->ifindex,
8397 drv->operstate,
8398 scan_state_str(drv->scan_state),
8399 MAC2STR(drv->auth_bssid),
8400 MAC2STR(drv->auth_attempt_bssid),
8401 MAC2STR(drv->bssid),
8402 MAC2STR(drv->prev_bssid),
8403 drv->associated,
8404 drv->assoc_freq,
8405 drv->monitor_sock,
8406 drv->monitor_ifidx,
8407 drv->monitor_refcount,
8408 drv->last_mgmt_freq,
8409 drv->eapol_tx_sock,
8410 drv->ignore_if_down_event ?
8411 "ignore_if_down_event=1\n" : "",
8412 drv->scan_complete_events ?
8413 "scan_complete_events=1\n" : "",
8414 drv->disabled_11b_rates ?
8415 "disabled_11b_rates=1\n" : "",
8416 drv->pending_remain_on_chan ?
8417 "pending_remain_on_chan=1\n" : "",
8418 drv->in_interface_list ? "in_interface_list=1\n" : "",
8419 drv->device_ap_sme ? "device_ap_sme=1\n" : "",
8420 drv->poll_command_supported ?
8421 "poll_command_supported=1\n" : "",
8422 drv->data_tx_status ? "data_tx_status=1\n" : "",
8423 drv->scan_for_auth ? "scan_for_auth=1\n" : "",
8424 drv->retry_auth ? "retry_auth=1\n" : "",
8425 drv->use_monitor ? "use_monitor=1\n" : "",
8426 drv->ignore_next_local_disconnect ?
8427 "ignore_next_local_disconnect=1\n" : "",
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07008428 drv->ignore_next_local_deauth ?
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008429 "ignore_next_local_deauth=1\n" : "");
8430 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt56052862013-10-04 10:23:25 -07008431 return pos - buf;
8432 pos += res;
8433
8434 if (drv->has_capability) {
8435 res = os_snprintf(pos, end - pos,
8436 "capa.key_mgmt=0x%x\n"
8437 "capa.enc=0x%x\n"
8438 "capa.auth=0x%x\n"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008439 "capa.flags=0x%llx\n"
8440 "capa.rrm_flags=0x%x\n"
Dmitry Shmidt56052862013-10-04 10:23:25 -07008441 "capa.max_scan_ssids=%d\n"
8442 "capa.max_sched_scan_ssids=%d\n"
8443 "capa.sched_scan_supported=%d\n"
8444 "capa.max_match_sets=%d\n"
8445 "capa.max_remain_on_chan=%u\n"
8446 "capa.max_stations=%u\n"
8447 "capa.probe_resp_offloads=0x%x\n"
8448 "capa.max_acl_mac_addrs=%u\n"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008449 "capa.num_multichan_concurrent=%u\n"
8450 "capa.mac_addr_rand_sched_scan_supported=%d\n"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008451 "capa.mac_addr_rand_scan_supported=%d\n"
8452 "capa.conc_capab=%u\n"
8453 "capa.max_conc_chan_2_4=%u\n"
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008454 "capa.max_conc_chan_5_0=%u\n"
8455 "capa.max_sched_scan_plans=%u\n"
8456 "capa.max_sched_scan_plan_interval=%u\n"
8457 "capa.max_sched_scan_plan_iterations=%u\n",
Dmitry Shmidt56052862013-10-04 10:23:25 -07008458 drv->capa.key_mgmt,
8459 drv->capa.enc,
8460 drv->capa.auth,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008461 (unsigned long long) drv->capa.flags,
8462 drv->capa.rrm_flags,
Dmitry Shmidt56052862013-10-04 10:23:25 -07008463 drv->capa.max_scan_ssids,
8464 drv->capa.max_sched_scan_ssids,
8465 drv->capa.sched_scan_supported,
8466 drv->capa.max_match_sets,
8467 drv->capa.max_remain_on_chan,
8468 drv->capa.max_stations,
8469 drv->capa.probe_resp_offloads,
8470 drv->capa.max_acl_mac_addrs,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008471 drv->capa.num_multichan_concurrent,
8472 drv->capa.mac_addr_rand_sched_scan_supported,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008473 drv->capa.mac_addr_rand_scan_supported,
8474 drv->capa.conc_capab,
8475 drv->capa.max_conc_chan_2_4,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008476 drv->capa.max_conc_chan_5_0,
8477 drv->capa.max_sched_scan_plans,
8478 drv->capa.max_sched_scan_plan_interval,
8479 drv->capa.max_sched_scan_plan_iterations);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008480 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt56052862013-10-04 10:23:25 -07008481 return pos - buf;
8482 pos += res;
8483 }
8484
8485 return pos - buf;
8486}
8487
8488
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008489static int set_beacon_data(struct nl_msg *msg, struct beacon_data *settings)
8490{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008491 if ((settings->head &&
8492 nla_put(msg, NL80211_ATTR_BEACON_HEAD,
8493 settings->head_len, settings->head)) ||
8494 (settings->tail &&
8495 nla_put(msg, NL80211_ATTR_BEACON_TAIL,
8496 settings->tail_len, settings->tail)) ||
8497 (settings->beacon_ies &&
8498 nla_put(msg, NL80211_ATTR_IE,
8499 settings->beacon_ies_len, settings->beacon_ies)) ||
8500 (settings->proberesp_ies &&
8501 nla_put(msg, NL80211_ATTR_IE_PROBE_RESP,
8502 settings->proberesp_ies_len, settings->proberesp_ies)) ||
8503 (settings->assocresp_ies &&
8504 nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP,
8505 settings->assocresp_ies_len, settings->assocresp_ies)) ||
8506 (settings->probe_resp &&
8507 nla_put(msg, NL80211_ATTR_PROBE_RESP,
8508 settings->probe_resp_len, settings->probe_resp)))
8509 return -ENOBUFS;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008510
8511 return 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008512}
8513
8514
8515static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
8516{
8517 struct nl_msg *msg;
8518 struct i802_bss *bss = priv;
8519 struct wpa_driver_nl80211_data *drv = bss->drv;
8520 struct nlattr *beacon_csa;
8521 int ret = -ENOBUFS;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008522 int csa_off_len = 0;
8523 int i;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008524
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08008525 wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d width=%d cf1=%d cf2=%d)",
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008526 settings->cs_count, settings->block_tx,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08008527 settings->freq_params.freq, settings->freq_params.bandwidth,
8528 settings->freq_params.center_freq1,
8529 settings->freq_params.center_freq2);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008530
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008531 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008532 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command");
8533 return -EOPNOTSUPP;
8534 }
8535
8536 if ((drv->nlmode != NL80211_IFTYPE_AP) &&
8537 (drv->nlmode != NL80211_IFTYPE_P2P_GO))
8538 return -EOPNOTSUPP;
8539
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008540 /*
8541 * Remove empty counters, assuming Probe Response and Beacon frame
8542 * counters match. This implementation assumes that there are only two
8543 * counters.
8544 */
8545 if (settings->counter_offset_beacon[0] &&
8546 !settings->counter_offset_beacon[1]) {
8547 csa_off_len = 1;
8548 } else if (settings->counter_offset_beacon[1] &&
8549 !settings->counter_offset_beacon[0]) {
8550 csa_off_len = 1;
8551 settings->counter_offset_beacon[0] =
8552 settings->counter_offset_beacon[1];
8553 settings->counter_offset_presp[0] =
8554 settings->counter_offset_presp[1];
8555 } else if (settings->counter_offset_beacon[1] &&
8556 settings->counter_offset_beacon[0]) {
8557 csa_off_len = 2;
8558 } else {
8559 wpa_printf(MSG_ERROR, "nl80211: No CSA counters provided");
8560 return -EINVAL;
8561 }
8562
8563 /* Check CSA counters validity */
8564 if (drv->capa.max_csa_counters &&
8565 csa_off_len > drv->capa.max_csa_counters) {
8566 wpa_printf(MSG_ERROR,
8567 "nl80211: Too many CSA counters provided");
8568 return -EINVAL;
8569 }
8570
8571 if (!settings->beacon_csa.tail)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008572 return -EINVAL;
8573
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008574 for (i = 0; i < csa_off_len; i++) {
8575 u16 csa_c_off_bcn = settings->counter_offset_beacon[i];
8576 u16 csa_c_off_presp = settings->counter_offset_presp[i];
8577
8578 if ((settings->beacon_csa.tail_len <= csa_c_off_bcn) ||
8579 (settings->beacon_csa.tail[csa_c_off_bcn] !=
8580 settings->cs_count))
8581 return -EINVAL;
8582
8583 if (settings->beacon_csa.probe_resp &&
8584 ((settings->beacon_csa.probe_resp_len <=
8585 csa_c_off_presp) ||
8586 (settings->beacon_csa.probe_resp[csa_c_off_presp] !=
8587 settings->cs_count)))
8588 return -EINVAL;
8589 }
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008590
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008591 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_CHANNEL_SWITCH)) ||
8592 nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT,
8593 settings->cs_count) ||
8594 (ret = nl80211_put_freq_params(msg, &settings->freq_params)) ||
8595 (settings->block_tx &&
8596 nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX)))
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008597 goto error;
8598
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008599 /* beacon_after params */
8600 ret = set_beacon_data(msg, &settings->beacon_after);
8601 if (ret)
8602 goto error;
8603
8604 /* beacon_csa params */
8605 beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
8606 if (!beacon_csa)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008607 goto fail;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008608
8609 ret = set_beacon_data(msg, &settings->beacon_csa);
8610 if (ret)
8611 goto error;
8612
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008613 if (nla_put(msg, NL80211_ATTR_CSA_C_OFF_BEACON,
8614 csa_off_len * sizeof(u16),
8615 settings->counter_offset_beacon) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008616 (settings->beacon_csa.probe_resp &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008617 nla_put(msg, NL80211_ATTR_CSA_C_OFF_PRESP,
8618 csa_off_len * sizeof(u16),
8619 settings->counter_offset_presp)))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008620 goto fail;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008621
8622 nla_nest_end(msg, beacon_csa);
8623 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8624 if (ret) {
8625 wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)",
8626 ret, strerror(-ret));
8627 }
8628 return ret;
8629
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008630fail:
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008631 ret = -ENOBUFS;
8632error:
8633 nlmsg_free(msg);
8634 wpa_printf(MSG_DEBUG, "nl80211: Could not build channel switch request");
8635 return ret;
8636}
8637
8638
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008639static int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr,
8640 u8 user_priority, u16 admitted_time)
8641{
8642 struct i802_bss *bss = priv;
8643 struct wpa_driver_nl80211_data *drv = bss->drv;
8644 struct nl_msg *msg;
8645 int ret;
8646
8647 wpa_printf(MSG_DEBUG,
8648 "nl80211: add_ts request: tsid=%u admitted_time=%u up=%d",
8649 tsid, admitted_time, user_priority);
8650
8651 if (!is_sta_interface(drv->nlmode))
8652 return -ENOTSUP;
8653
8654 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ADD_TX_TS);
8655 if (!msg ||
8656 nla_put_u8(msg, NL80211_ATTR_TSID, tsid) ||
8657 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
8658 nla_put_u8(msg, NL80211_ATTR_USER_PRIO, user_priority) ||
8659 nla_put_u16(msg, NL80211_ATTR_ADMITTED_TIME, admitted_time)) {
8660 nlmsg_free(msg);
8661 return -ENOBUFS;
8662 }
8663
8664 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8665 if (ret)
8666 wpa_printf(MSG_DEBUG, "nl80211: add_ts failed err=%d (%s)",
8667 ret, strerror(-ret));
8668 return ret;
8669}
8670
8671
8672static int nl80211_del_ts(void *priv, u8 tsid, const u8 *addr)
8673{
8674 struct i802_bss *bss = priv;
8675 struct wpa_driver_nl80211_data *drv = bss->drv;
8676 struct nl_msg *msg;
8677 int ret;
8678
8679 wpa_printf(MSG_DEBUG, "nl80211: del_ts request: tsid=%u", tsid);
8680
8681 if (!is_sta_interface(drv->nlmode))
8682 return -ENOTSUP;
8683
8684 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_TX_TS)) ||
8685 nla_put_u8(msg, NL80211_ATTR_TSID, tsid) ||
8686 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
8687 nlmsg_free(msg);
8688 return -ENOBUFS;
8689 }
8690
8691 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8692 if (ret)
8693 wpa_printf(MSG_DEBUG, "nl80211: del_ts failed err=%d (%s)",
8694 ret, strerror(-ret));
8695 return ret;
8696}
8697
8698
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008699#ifdef CONFIG_TESTING_OPTIONS
8700static int cmd_reply_handler(struct nl_msg *msg, void *arg)
8701{
8702 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8703 struct wpabuf *buf = arg;
8704
8705 if (!buf)
8706 return NL_SKIP;
8707
8708 if ((size_t) genlmsg_attrlen(gnlh, 0) > wpabuf_tailroom(buf)) {
8709 wpa_printf(MSG_INFO, "nl80211: insufficient buffer space for reply");
8710 return NL_SKIP;
8711 }
8712
8713 wpabuf_put_data(buf, genlmsg_attrdata(gnlh, 0),
8714 genlmsg_attrlen(gnlh, 0));
8715
8716 return NL_SKIP;
8717}
8718#endif /* CONFIG_TESTING_OPTIONS */
8719
8720
8721static int vendor_reply_handler(struct nl_msg *msg, void *arg)
8722{
8723 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8724 struct nlattr *nl_vendor_reply, *nl;
8725 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8726 struct wpabuf *buf = arg;
8727 int rem;
8728
8729 if (!buf)
8730 return NL_SKIP;
8731
8732 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8733 genlmsg_attrlen(gnlh, 0), NULL);
8734 nl_vendor_reply = tb[NL80211_ATTR_VENDOR_DATA];
8735
8736 if (!nl_vendor_reply)
8737 return NL_SKIP;
8738
8739 if ((size_t) nla_len(nl_vendor_reply) > wpabuf_tailroom(buf)) {
8740 wpa_printf(MSG_INFO, "nl80211: Vendor command: insufficient buffer space for reply");
8741 return NL_SKIP;
8742 }
8743
8744 nla_for_each_nested(nl, nl_vendor_reply, rem) {
8745 wpabuf_put_data(buf, nla_data(nl), nla_len(nl));
8746 }
8747
8748 return NL_SKIP;
8749}
8750
8751
8752static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
8753 unsigned int subcmd, const u8 *data,
8754 size_t data_len, struct wpabuf *buf)
8755{
8756 struct i802_bss *bss = priv;
8757 struct wpa_driver_nl80211_data *drv = bss->drv;
8758 struct nl_msg *msg;
8759 int ret;
8760
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008761#ifdef CONFIG_TESTING_OPTIONS
8762 if (vendor_id == 0xffffffff) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008763 msg = nlmsg_alloc();
8764 if (!msg)
8765 return -ENOMEM;
8766
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008767 nl80211_cmd(drv, msg, 0, subcmd);
8768 if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) <
8769 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008770 goto fail;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008771 ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf);
8772 if (ret)
8773 wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
8774 ret);
8775 return ret;
8776 }
8777#endif /* CONFIG_TESTING_OPTIONS */
8778
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008779 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_VENDOR)) ||
8780 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, vendor_id) ||
8781 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd) ||
8782 (data &&
8783 nla_put(msg, NL80211_ATTR_VENDOR_DATA, data_len, data)))
8784 goto fail;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008785
8786 ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf);
8787 if (ret)
8788 wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d",
8789 ret);
8790 return ret;
8791
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008792fail:
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008793 nlmsg_free(msg);
8794 return -ENOBUFS;
8795}
8796
8797
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008798static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set,
8799 u8 qos_map_set_len)
8800{
8801 struct i802_bss *bss = priv;
8802 struct wpa_driver_nl80211_data *drv = bss->drv;
8803 struct nl_msg *msg;
8804 int ret;
8805
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008806 wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map",
8807 qos_map_set, qos_map_set_len);
8808
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008809 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_QOS_MAP)) ||
8810 nla_put(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set)) {
8811 nlmsg_free(msg);
8812 return -ENOBUFS;
8813 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008814
8815 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8816 if (ret)
8817 wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed");
8818
8819 return ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008820}
8821
8822
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008823static int nl80211_set_wowlan(void *priv,
8824 const struct wowlan_triggers *triggers)
8825{
8826 struct i802_bss *bss = priv;
8827 struct wpa_driver_nl80211_data *drv = bss->drv;
8828 struct nl_msg *msg;
8829 struct nlattr *wowlan_triggers;
8830 int ret;
8831
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008832 wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan");
8833
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07008834 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_SET_WOWLAN)) ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008835 !(wowlan_triggers = nla_nest_start(msg,
8836 NL80211_ATTR_WOWLAN_TRIGGERS)) ||
8837 (triggers->any &&
8838 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
8839 (triggers->disconnect &&
8840 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
8841 (triggers->magic_pkt &&
8842 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
8843 (triggers->gtk_rekey_failure &&
8844 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
8845 (triggers->eap_identity_req &&
8846 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
8847 (triggers->four_way_handshake &&
8848 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
8849 (triggers->rfkill_release &&
8850 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) {
8851 nlmsg_free(msg);
8852 return -ENOBUFS;
8853 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008854
8855 nla_nest_end(msg, wowlan_triggers);
8856
8857 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8858 if (ret)
8859 wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed");
8860
8861 return ret;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008862}
8863
8864
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008865#ifdef CONFIG_DRIVER_NL80211_QCA
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008866static int nl80211_roaming(void *priv, int allowed, const u8 *bssid)
8867{
8868 struct i802_bss *bss = priv;
8869 struct wpa_driver_nl80211_data *drv = bss->drv;
8870 struct nl_msg *msg;
8871 struct nlattr *params;
8872
8873 wpa_printf(MSG_DEBUG, "nl80211: Roaming policy: allowed=%d", allowed);
8874
8875 if (!drv->roaming_vendor_cmd_avail) {
8876 wpa_printf(MSG_DEBUG,
8877 "nl80211: Ignore roaming policy change since driver does not provide command for setting it");
8878 return -1;
8879 }
8880
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008881 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
8882 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8883 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8884 QCA_NL80211_VENDOR_SUBCMD_ROAMING) ||
8885 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8886 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY,
8887 allowed ? QCA_ROAMING_ALLOWED_WITHIN_ESS :
8888 QCA_ROAMING_NOT_ALLOWED) ||
8889 (bssid &&
8890 nla_put(msg, QCA_WLAN_VENDOR_ATTR_MAC_ADDR, ETH_ALEN, bssid))) {
8891 nlmsg_free(msg);
8892 return -1;
8893 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008894 nla_nest_end(msg, params);
8895
8896 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008897}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07008898
8899
8900/* Reserved QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID value for wpa_supplicant */
8901#define WPA_SUPPLICANT_CLIENT_ID 1
8902
8903static int nl80211_set_bssid_blacklist(void *priv, unsigned int num_bssid,
8904 const u8 *bssid)
8905{
8906 struct i802_bss *bss = priv;
8907 struct wpa_driver_nl80211_data *drv = bss->drv;
8908 struct nl_msg *msg;
8909 struct nlattr *params, *nlbssids, *attr;
8910 unsigned int i;
8911
8912 wpa_printf(MSG_DEBUG, "nl80211: Set blacklist BSSID (num=%u)",
8913 num_bssid);
8914
8915 if (!drv->roam_vendor_cmd_avail)
8916 return -1;
8917
8918 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
8919 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8920 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8921 QCA_NL80211_VENDOR_SUBCMD_ROAM) ||
8922 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8923 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD,
8924 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID) ||
8925 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID,
8926 WPA_SUPPLICANT_CLIENT_ID) ||
8927 nla_put_u32(msg,
8928 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID,
8929 num_bssid))
8930 goto fail;
8931
8932 nlbssids = nla_nest_start(
8933 msg, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS);
8934 if (!nlbssids)
8935 goto fail;
8936
8937 for (i = 0; i < num_bssid; i++) {
8938 attr = nla_nest_start(msg, i);
8939 if (!attr)
8940 goto fail;
8941 if (nla_put(msg,
8942 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID,
8943 ETH_ALEN, &bssid[i * ETH_ALEN]))
8944 goto fail;
8945 wpa_printf(MSG_DEBUG, "nl80211: BSSID[%u]: " MACSTR, i,
8946 MAC2STR(&bssid[i * ETH_ALEN]));
8947 nla_nest_end(msg, attr);
8948 }
8949 nla_nest_end(msg, nlbssids);
8950 nla_nest_end(msg, params);
8951
8952 return send_and_recv_msgs(drv, msg, NULL, NULL);
8953
8954fail:
8955 nlmsg_free(msg);
8956 return -1;
8957}
8958
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008959#endif /* CONFIG_DRIVER_NL80211_QCA */
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008960
8961
8962static int nl80211_set_mac_addr(void *priv, const u8 *addr)
8963{
8964 struct i802_bss *bss = priv;
8965 struct wpa_driver_nl80211_data *drv = bss->drv;
8966 int new_addr = addr != NULL;
8967
Dmitry Shmidt849734c2016-05-27 09:59:01 -07008968 if (TEST_FAIL())
8969 return -1;
8970
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008971 if (!addr)
8972 addr = drv->perm_addr;
8973
8974 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0)
8975 return -1;
8976
8977 if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr) < 0)
8978 {
8979 wpa_printf(MSG_DEBUG,
8980 "nl80211: failed to set_mac_addr for %s to " MACSTR,
8981 bss->ifname, MAC2STR(addr));
8982 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
8983 1) < 0) {
8984 wpa_printf(MSG_DEBUG,
8985 "nl80211: Could not restore interface UP after failed set_mac_addr");
8986 }
8987 return -1;
8988 }
8989
8990 wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR,
8991 bss->ifname, MAC2STR(addr));
8992 drv->addr_changed = new_addr;
8993 os_memcpy(bss->addr, addr, ETH_ALEN);
8994
8995 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0)
8996 {
8997 wpa_printf(MSG_DEBUG,
8998 "nl80211: Could not restore interface UP after set_mac_addr");
8999 }
9000
9001 return 0;
9002}
9003
9004
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009005#ifdef CONFIG_MESH
9006
9007static int wpa_driver_nl80211_init_mesh(void *priv)
9008{
9009 if (wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_MESH_POINT)) {
9010 wpa_printf(MSG_INFO,
9011 "nl80211: Failed to set interface into mesh mode");
9012 return -1;
9013 }
9014 return 0;
9015}
9016
9017
Dmitry Shmidtff787d52015-01-12 13:01:47 -08009018static int nl80211_put_mesh_id(struct nl_msg *msg, const u8 *mesh_id,
9019 size_t mesh_id_len)
9020{
9021 if (mesh_id) {
9022 wpa_hexdump_ascii(MSG_DEBUG, " * Mesh ID (SSID)",
9023 mesh_id, mesh_id_len);
9024 return nla_put(msg, NL80211_ATTR_MESH_ID, mesh_id_len, mesh_id);
9025 }
9026
9027 return 0;
9028}
9029
9030
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07009031static int nl80211_put_mesh_config(struct nl_msg *msg,
9032 struct wpa_driver_mesh_bss_params *params)
9033{
9034 struct nlattr *container;
9035
9036 container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
9037 if (!container)
9038 return -1;
9039
9040 if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
9041 nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
9042 params->auto_plinks)) ||
9043 ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) &&
9044 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009045 params->max_peer_links)) ||
9046 ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD) &&
9047 nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
9048 params->rssi_threshold)))
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07009049 return -1;
9050
9051 /*
9052 * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because
9053 * the timer could disconnect stations even in that case.
9054 */
9055 if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT) &&
9056 nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
9057 params->peer_link_timeout)) {
9058 wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT");
9059 return -1;
9060 }
9061
9062 if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE) &&
9063 nla_put_u16(msg, NL80211_MESHCONF_HT_OPMODE, params->ht_opmode)) {
9064 wpa_printf(MSG_ERROR, "nl80211: Failed to set HT_OP_MODE");
9065 return -1;
9066 }
9067
9068 nla_nest_end(msg, container);
9069
9070 return 0;
9071}
9072
9073
Dmitry Shmidt7f656022015-02-25 14:36:37 -08009074static int nl80211_join_mesh(struct i802_bss *bss,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009075 struct wpa_driver_mesh_join_params *params)
9076{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009077 struct wpa_driver_nl80211_data *drv = bss->drv;
9078 struct nl_msg *msg;
9079 struct nlattr *container;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08009080 int ret = -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009081
9082 wpa_printf(MSG_DEBUG, "nl80211: mesh join (ifindex=%d)", drv->ifindex);
9083 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_MESH);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08009084 if (!msg ||
9085 nl80211_put_freq_params(msg, &params->freq) ||
9086 nl80211_put_basic_rates(msg, params->basic_rates) ||
9087 nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07009088 nl80211_put_beacon_int(msg, params->beacon_int) ||
9089 nl80211_put_dtim_period(msg, params->dtim_period))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009090 goto fail;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009091
9092 wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags);
9093
9094 container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP);
9095 if (!container)
9096 goto fail;
9097
9098 if (params->ies) {
9099 wpa_hexdump(MSG_DEBUG, " * IEs", params->ies, params->ie_len);
9100 if (nla_put(msg, NL80211_MESH_SETUP_IE, params->ie_len,
9101 params->ies))
9102 goto fail;
9103 }
9104 /* WPA_DRIVER_MESH_FLAG_OPEN_AUTH is treated as default by nl80211 */
9105 if (params->flags & WPA_DRIVER_MESH_FLAG_SAE_AUTH) {
9106 if (nla_put_u8(msg, NL80211_MESH_SETUP_AUTH_PROTOCOL, 0x1) ||
9107 nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_AUTH))
9108 goto fail;
9109 }
9110 if ((params->flags & WPA_DRIVER_MESH_FLAG_AMPE) &&
9111 nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_AMPE))
9112 goto fail;
9113 if ((params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM) &&
9114 nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_MPM))
9115 goto fail;
9116 nla_nest_end(msg, container);
9117
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07009118 params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
9119 params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT;
9120 params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS;
9121 if (nl80211_put_mesh_config(msg, &params->conf) < 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009122 goto fail;
9123
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009124 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9125 msg = NULL;
9126 if (ret) {
9127 wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
9128 ret, strerror(-ret));
9129 goto fail;
9130 }
9131 ret = 0;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07009132 drv->assoc_freq = bss->freq = params->freq.freq;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009133 wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully");
9134
9135fail:
9136 nlmsg_free(msg);
9137 return ret;
9138}
9139
9140
Dmitry Shmidt7f656022015-02-25 14:36:37 -08009141static int
9142wpa_driver_nl80211_join_mesh(void *priv,
9143 struct wpa_driver_mesh_join_params *params)
9144{
9145 struct i802_bss *bss = priv;
9146 int ret, timeout;
9147
9148 timeout = params->conf.peer_link_timeout;
9149
9150 /* Disable kernel inactivity timer */
9151 if (params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM)
9152 params->conf.peer_link_timeout = 0;
9153
9154 ret = nl80211_join_mesh(bss, params);
9155 if (ret == -EINVAL && params->conf.peer_link_timeout == 0) {
9156 wpa_printf(MSG_DEBUG,
9157 "nl80211: Mesh join retry for peer_link_timeout");
9158 /*
9159 * Old kernel does not support setting
9160 * NL80211_MESHCONF_PLINK_TIMEOUT to zero, so set 60 seconds
9161 * into future from peer_link_timeout.
9162 */
9163 params->conf.peer_link_timeout = timeout + 60;
9164 ret = nl80211_join_mesh(priv, params);
9165 }
9166
9167 params->conf.peer_link_timeout = timeout;
9168 return ret;
9169}
9170
9171
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009172static int wpa_driver_nl80211_leave_mesh(void *priv)
9173{
9174 struct i802_bss *bss = priv;
9175 struct wpa_driver_nl80211_data *drv = bss->drv;
9176 struct nl_msg *msg;
9177 int ret;
9178
9179 wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
9180 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
9181 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9182 if (ret) {
9183 wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
9184 ret, strerror(-ret));
9185 } else {
9186 wpa_printf(MSG_DEBUG,
9187 "nl80211: mesh leave request send successfully");
9188 }
9189
9190 if (wpa_driver_nl80211_set_mode(drv->first_bss,
9191 NL80211_IFTYPE_STATION)) {
9192 wpa_printf(MSG_INFO,
9193 "nl80211: Failed to set interface into station mode");
9194 }
9195 return ret;
9196}
9197
9198#endif /* CONFIG_MESH */
9199
9200
9201static int wpa_driver_br_add_ip_neigh(void *priv, u8 version,
9202 const u8 *ipaddr, int prefixlen,
9203 const u8 *addr)
9204{
9205#ifdef CONFIG_LIBNL3_ROUTE
9206 struct i802_bss *bss = priv;
9207 struct wpa_driver_nl80211_data *drv = bss->drv;
9208 struct rtnl_neigh *rn;
9209 struct nl_addr *nl_ipaddr = NULL;
9210 struct nl_addr *nl_lladdr = NULL;
9211 int family, addrsize;
9212 int res;
9213
9214 if (!ipaddr || prefixlen == 0 || !addr)
9215 return -EINVAL;
9216
9217 if (bss->br_ifindex == 0) {
9218 wpa_printf(MSG_DEBUG,
9219 "nl80211: bridge must be set before adding an ip neigh to it");
9220 return -1;
9221 }
9222
9223 if (!drv->rtnl_sk) {
9224 wpa_printf(MSG_DEBUG,
9225 "nl80211: nl_sock for NETLINK_ROUTE is not initialized");
9226 return -1;
9227 }
9228
9229 if (version == 4) {
9230 family = AF_INET;
9231 addrsize = 4;
9232 } else if (version == 6) {
9233 family = AF_INET6;
9234 addrsize = 16;
9235 } else {
9236 return -EINVAL;
9237 }
9238
9239 rn = rtnl_neigh_alloc();
9240 if (rn == NULL)
9241 return -ENOMEM;
9242
9243 /* set the destination ip address for neigh */
9244 nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
9245 if (nl_ipaddr == NULL) {
9246 wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
9247 res = -ENOMEM;
9248 goto errout;
9249 }
9250 nl_addr_set_prefixlen(nl_ipaddr, prefixlen);
9251 res = rtnl_neigh_set_dst(rn, nl_ipaddr);
9252 if (res) {
9253 wpa_printf(MSG_DEBUG,
9254 "nl80211: neigh set destination addr failed");
9255 goto errout;
9256 }
9257
9258 /* set the corresponding lladdr for neigh */
9259 nl_lladdr = nl_addr_build(AF_BRIDGE, (u8 *) addr, ETH_ALEN);
9260 if (nl_lladdr == NULL) {
9261 wpa_printf(MSG_DEBUG, "nl80211: neigh set lladdr failed");
9262 res = -ENOMEM;
9263 goto errout;
9264 }
9265 rtnl_neigh_set_lladdr(rn, nl_lladdr);
9266
9267 rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
9268 rtnl_neigh_set_state(rn, NUD_PERMANENT);
9269
9270 res = rtnl_neigh_add(drv->rtnl_sk, rn, NLM_F_CREATE);
9271 if (res) {
9272 wpa_printf(MSG_DEBUG,
9273 "nl80211: Adding bridge ip neigh failed: %s",
9274 strerror(errno));
9275 }
9276errout:
9277 if (nl_lladdr)
9278 nl_addr_put(nl_lladdr);
9279 if (nl_ipaddr)
9280 nl_addr_put(nl_ipaddr);
9281 if (rn)
9282 rtnl_neigh_put(rn);
9283 return res;
9284#else /* CONFIG_LIBNL3_ROUTE */
9285 return -1;
9286#endif /* CONFIG_LIBNL3_ROUTE */
9287}
9288
9289
9290static int wpa_driver_br_delete_ip_neigh(void *priv, u8 version,
9291 const u8 *ipaddr)
9292{
9293#ifdef CONFIG_LIBNL3_ROUTE
9294 struct i802_bss *bss = priv;
9295 struct wpa_driver_nl80211_data *drv = bss->drv;
9296 struct rtnl_neigh *rn;
9297 struct nl_addr *nl_ipaddr;
9298 int family, addrsize;
9299 int res;
9300
9301 if (!ipaddr)
9302 return -EINVAL;
9303
9304 if (version == 4) {
9305 family = AF_INET;
9306 addrsize = 4;
9307 } else if (version == 6) {
9308 family = AF_INET6;
9309 addrsize = 16;
9310 } else {
9311 return -EINVAL;
9312 }
9313
9314 if (bss->br_ifindex == 0) {
9315 wpa_printf(MSG_DEBUG,
9316 "nl80211: bridge must be set to delete an ip neigh");
9317 return -1;
9318 }
9319
9320 if (!drv->rtnl_sk) {
9321 wpa_printf(MSG_DEBUG,
9322 "nl80211: nl_sock for NETLINK_ROUTE is not initialized");
9323 return -1;
9324 }
9325
9326 rn = rtnl_neigh_alloc();
9327 if (rn == NULL)
9328 return -ENOMEM;
9329
9330 /* set the destination ip address for neigh */
9331 nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
9332 if (nl_ipaddr == NULL) {
9333 wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
9334 res = -ENOMEM;
9335 goto errout;
9336 }
9337 res = rtnl_neigh_set_dst(rn, nl_ipaddr);
9338 if (res) {
9339 wpa_printf(MSG_DEBUG,
9340 "nl80211: neigh set destination addr failed");
9341 goto errout;
9342 }
9343
9344 rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
9345
9346 res = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
9347 if (res) {
9348 wpa_printf(MSG_DEBUG,
9349 "nl80211: Deleting bridge ip neigh failed: %s",
9350 strerror(errno));
9351 }
9352errout:
9353 if (nl_ipaddr)
9354 nl_addr_put(nl_ipaddr);
9355 if (rn)
9356 rtnl_neigh_put(rn);
9357 return res;
9358#else /* CONFIG_LIBNL3_ROUTE */
9359 return -1;
9360#endif /* CONFIG_LIBNL3_ROUTE */
9361}
9362
9363
9364static int linux_write_system_file(const char *path, unsigned int val)
9365{
9366 char buf[50];
9367 int fd, len;
9368
9369 len = os_snprintf(buf, sizeof(buf), "%u\n", val);
9370 if (os_snprintf_error(sizeof(buf), len))
9371 return -1;
9372
9373 fd = open(path, O_WRONLY);
9374 if (fd < 0)
9375 return -1;
9376
9377 if (write(fd, buf, len) < 0) {
9378 wpa_printf(MSG_DEBUG,
9379 "nl80211: Failed to write Linux system file: %s with the value of %d",
9380 path, val);
9381 close(fd);
9382 return -1;
9383 }
9384 close(fd);
9385
9386 return 0;
9387}
9388
9389
9390static const char * drv_br_port_attr_str(enum drv_br_port_attr attr)
9391{
9392 switch (attr) {
9393 case DRV_BR_PORT_ATTR_PROXYARP:
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07009394 return "proxyarp_wifi";
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009395 case DRV_BR_PORT_ATTR_HAIRPIN_MODE:
9396 return "hairpin_mode";
9397 }
9398
9399 return NULL;
9400}
9401
9402
9403static int wpa_driver_br_port_set_attr(void *priv, enum drv_br_port_attr attr,
9404 unsigned int val)
9405{
9406 struct i802_bss *bss = priv;
9407 char path[128];
9408 const char *attr_txt;
9409
9410 attr_txt = drv_br_port_attr_str(attr);
9411 if (attr_txt == NULL)
9412 return -EINVAL;
9413
9414 os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/%s",
9415 bss->ifname, attr_txt);
9416
9417 if (linux_write_system_file(path, val))
9418 return -1;
9419
9420 return 0;
9421}
9422
9423
9424static const char * drv_br_net_param_str(enum drv_br_net_param param)
9425{
9426 switch (param) {
9427 case DRV_BR_NET_PARAM_GARP_ACCEPT:
9428 return "arp_accept";
Dmitry Shmidt83474442015-04-15 13:47:09 -07009429 default:
9430 return NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009431 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009432}
9433
9434
9435static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
9436 unsigned int val)
9437{
9438 struct i802_bss *bss = priv;
9439 char path[128];
9440 const char *param_txt;
9441 int ip_version = 4;
9442
Dmitry Shmidt83474442015-04-15 13:47:09 -07009443 if (param == DRV_BR_MULTICAST_SNOOPING) {
9444 os_snprintf(path, sizeof(path),
9445 "/sys/devices/virtual/net/%s/bridge/multicast_snooping",
9446 bss->brname);
9447 goto set_val;
9448 }
9449
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009450 param_txt = drv_br_net_param_str(param);
9451 if (param_txt == NULL)
9452 return -EINVAL;
9453
9454 switch (param) {
9455 case DRV_BR_NET_PARAM_GARP_ACCEPT:
9456 ip_version = 4;
9457 break;
9458 default:
9459 return -EINVAL;
9460 }
9461
9462 os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s",
9463 ip_version, bss->brname, param_txt);
9464
Dmitry Shmidt83474442015-04-15 13:47:09 -07009465set_val:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009466 if (linux_write_system_file(path, val))
9467 return -1;
9468
9469 return 0;
9470}
9471
9472
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009473#ifdef CONFIG_DRIVER_NL80211_QCA
9474
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009475static int hw_mode_to_qca_acs(enum hostapd_hw_mode hw_mode)
9476{
9477 switch (hw_mode) {
9478 case HOSTAPD_MODE_IEEE80211B:
9479 return QCA_ACS_MODE_IEEE80211B;
9480 case HOSTAPD_MODE_IEEE80211G:
9481 return QCA_ACS_MODE_IEEE80211G;
9482 case HOSTAPD_MODE_IEEE80211A:
9483 return QCA_ACS_MODE_IEEE80211A;
9484 case HOSTAPD_MODE_IEEE80211AD:
9485 return QCA_ACS_MODE_IEEE80211AD;
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07009486 case HOSTAPD_MODE_IEEE80211ANY:
9487 return QCA_ACS_MODE_IEEE80211ANY;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009488 default:
9489 return -1;
9490 }
9491}
9492
9493
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009494static int add_acs_freq_list(struct nl_msg *msg, const int *freq_list)
9495{
9496 int i, len, ret;
9497 u32 *freqs;
9498
9499 if (!freq_list)
9500 return 0;
9501 len = int_array_len(freq_list);
9502 freqs = os_malloc(sizeof(u32) * len);
9503 if (!freqs)
9504 return -1;
9505 for (i = 0; i < len; i++)
9506 freqs[i] = freq_list[i];
9507 ret = nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST,
9508 sizeof(u32) * len, freqs);
9509 os_free(freqs);
9510 return ret;
9511}
9512
9513
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009514static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
9515{
9516 struct i802_bss *bss = priv;
9517 struct wpa_driver_nl80211_data *drv = bss->drv;
9518 struct nl_msg *msg;
9519 struct nlattr *data;
9520 int ret;
9521 int mode;
9522
9523 mode = hw_mode_to_qca_acs(params->hw_mode);
9524 if (mode < 0)
9525 return -1;
9526
9527 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
9528 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
9529 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9530 QCA_NL80211_VENDOR_SUBCMD_DO_ACS) ||
9531 !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
9532 nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE, mode) ||
9533 (params->ht_enabled &&
9534 nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED)) ||
9535 (params->ht40_enabled &&
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07009536 nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED)) ||
9537 (params->vht_enabled &&
9538 nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED)) ||
9539 nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
9540 params->ch_width) ||
9541 (params->ch_list_len &&
9542 nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, params->ch_list_len,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009543 params->ch_list)) ||
9544 add_acs_freq_list(msg, params->freq_list)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009545 nlmsg_free(msg);
9546 return -ENOBUFS;
9547 }
9548 nla_nest_end(msg, data);
9549
Dmitry Shmidtdda10c22015-03-24 16:05:01 -07009550 wpa_printf(MSG_DEBUG,
9551 "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d CH_LIST_LEN: %u",
9552 params->hw_mode, params->ht_enabled, params->ht40_enabled,
9553 params->vht_enabled, params->ch_width, params->ch_list_len);
9554
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009555 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9556 if (ret) {
9557 wpa_printf(MSG_DEBUG,
9558 "nl80211: Failed to invoke driver ACS function: %s",
9559 strerror(errno));
9560 }
9561 return ret;
9562}
9563
9564
Ravi Joshie6ccb162015-07-16 17:45:41 -07009565static int nl80211_set_band(void *priv, enum set_band band)
9566{
9567 struct i802_bss *bss = priv;
9568 struct wpa_driver_nl80211_data *drv = bss->drv;
9569 struct nl_msg *msg;
9570 struct nlattr *data;
9571 int ret;
9572 enum qca_set_band qca_band;
9573
9574 if (!drv->setband_vendor_cmd_avail)
9575 return -1;
9576
9577 switch (band) {
9578 case WPA_SETBAND_AUTO:
9579 qca_band = QCA_SETBAND_AUTO;
9580 break;
9581 case WPA_SETBAND_5G:
9582 qca_band = QCA_SETBAND_5G;
9583 break;
9584 case WPA_SETBAND_2G:
9585 qca_band = QCA_SETBAND_2G;
9586 break;
9587 default:
9588 return -1;
9589 }
9590
9591 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
9592 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
9593 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9594 QCA_NL80211_VENDOR_SUBCMD_SETBAND) ||
9595 !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
9596 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, qca_band)) {
9597 nlmsg_free(msg);
9598 return -ENOBUFS;
9599 }
9600 nla_nest_end(msg, data);
9601
9602 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9603 if (ret) {
9604 wpa_printf(MSG_DEBUG,
9605 "nl80211: Driver setband function failed: %s",
9606 strerror(errno));
9607 }
9608 return ret;
9609}
9610
9611
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009612struct nl80211_pcl {
9613 unsigned int num;
9614 unsigned int *freq_list;
9615};
9616
9617static int preferred_freq_info_handler(struct nl_msg *msg, void *arg)
9618{
9619 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9620 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9621 struct nl80211_pcl *param = arg;
9622 struct nlattr *nl_vend, *attr;
9623 enum qca_iface_type iface_type;
9624 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9625 unsigned int num, max_num;
9626 u32 *freqs;
9627
9628 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9629 genlmsg_attrlen(gnlh, 0), NULL);
9630
9631 nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
9632 if (!nl_vend)
9633 return NL_SKIP;
9634
9635 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
9636 nla_data(nl_vend), nla_len(nl_vend), NULL);
9637
9638 attr = tb_vendor[
9639 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE];
9640 if (!attr) {
9641 wpa_printf(MSG_ERROR, "nl80211: iface_type couldn't be found");
9642 param->num = 0;
9643 return NL_SKIP;
9644 }
9645
9646 iface_type = (enum qca_iface_type) nla_get_u32(attr);
9647 wpa_printf(MSG_DEBUG, "nl80211: Driver returned iface_type=%d",
9648 iface_type);
9649
9650 attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST];
9651 if (!attr) {
9652 wpa_printf(MSG_ERROR,
9653 "nl80211: preferred_freq_list couldn't be found");
9654 param->num = 0;
9655 return NL_SKIP;
9656 }
9657
9658 /*
9659 * param->num has the maximum number of entries for which there
9660 * is room in the freq_list provided by the caller.
9661 */
9662 freqs = nla_data(attr);
9663 max_num = nla_len(attr) / sizeof(u32);
9664 if (max_num > param->num)
9665 max_num = param->num;
9666 for (num = 0; num < max_num; num++)
9667 param->freq_list[num] = freqs[num];
9668 param->num = num;
9669
9670 return NL_SKIP;
9671}
9672
9673
9674static int nl80211_get_pref_freq_list(void *priv,
9675 enum wpa_driver_if_type if_type,
9676 unsigned int *num,
9677 unsigned int *freq_list)
9678{
9679 struct i802_bss *bss = priv;
9680 struct wpa_driver_nl80211_data *drv = bss->drv;
9681 struct nl_msg *msg;
9682 int ret;
9683 unsigned int i;
9684 struct nlattr *params;
9685 struct nl80211_pcl param;
9686 enum qca_iface_type iface_type;
9687
9688 if (!drv->get_pref_freq_list)
9689 return -1;
9690
9691 switch (if_type) {
9692 case WPA_IF_STATION:
9693 iface_type = QCA_IFACE_TYPE_STA;
9694 break;
9695 case WPA_IF_AP_BSS:
9696 iface_type = QCA_IFACE_TYPE_AP;
9697 break;
9698 case WPA_IF_P2P_GO:
9699 iface_type = QCA_IFACE_TYPE_P2P_GO;
9700 break;
9701 case WPA_IF_P2P_CLIENT:
9702 iface_type = QCA_IFACE_TYPE_P2P_CLIENT;
9703 break;
9704 case WPA_IF_IBSS:
9705 iface_type = QCA_IFACE_TYPE_IBSS;
9706 break;
9707 case WPA_IF_TDLS:
9708 iface_type = QCA_IFACE_TYPE_TDLS;
9709 break;
9710 default:
9711 return -1;
9712 }
9713
9714 param.num = *num;
9715 param.freq_list = freq_list;
9716
9717 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
9718 nla_put_u32(msg, NL80211_ATTR_IFINDEX, drv->ifindex) ||
9719 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
9720 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9721 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST) ||
9722 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
9723 nla_put_u32(msg,
9724 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
9725 iface_type)) {
9726 wpa_printf(MSG_ERROR,
9727 "%s: err in adding vendor_cmd and vendor_data",
9728 __func__);
9729 nlmsg_free(msg);
9730 return -1;
9731 }
9732 nla_nest_end(msg, params);
9733
9734 os_memset(freq_list, 0, *num * sizeof(freq_list[0]));
9735 ret = send_and_recv_msgs(drv, msg, preferred_freq_info_handler, &param);
9736 if (ret) {
9737 wpa_printf(MSG_ERROR,
9738 "%s: err in send_and_recv_msgs", __func__);
9739 return ret;
9740 }
9741
9742 *num = param.num;
9743
9744 for (i = 0; i < *num; i++) {
9745 wpa_printf(MSG_DEBUG, "nl80211: preferred_channel_list[%d]=%d",
9746 i, freq_list[i]);
9747 }
9748
9749 return 0;
9750}
9751
9752
9753static int nl80211_set_prob_oper_freq(void *priv, unsigned int freq)
9754{
9755 struct i802_bss *bss = priv;
9756 struct wpa_driver_nl80211_data *drv = bss->drv;
9757 struct nl_msg *msg;
9758 int ret;
9759 struct nlattr *params;
9760
9761 if (!drv->set_prob_oper_freq)
9762 return -1;
9763
9764 wpa_printf(MSG_DEBUG,
9765 "nl80211: Set P2P probable operating freq %u for ifindex %d",
9766 freq, bss->ifindex);
9767
9768 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
9769 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
9770 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9771 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL) ||
9772 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
9773 nla_put_u32(msg,
9774 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE,
9775 QCA_IFACE_TYPE_P2P_CLIENT) ||
9776 nla_put_u32(msg,
9777 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ,
9778 freq)) {
9779 wpa_printf(MSG_ERROR,
9780 "%s: err in adding vendor_cmd and vendor_data",
9781 __func__);
9782 nlmsg_free(msg);
9783 return -1;
9784 }
9785 nla_nest_end(msg, params);
9786
9787 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9788 msg = NULL;
9789 if (ret) {
9790 wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs",
9791 __func__);
9792 return ret;
9793 }
9794 nlmsg_free(msg);
9795 return 0;
9796}
9797
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07009798
9799static int nl80211_p2p_lo_start(void *priv, unsigned int freq,
9800 unsigned int period, unsigned int interval,
9801 unsigned int count, const u8 *device_types,
9802 size_t dev_types_len,
9803 const u8 *ies, size_t ies_len)
9804{
9805 struct i802_bss *bss = priv;
9806 struct wpa_driver_nl80211_data *drv = bss->drv;
9807 struct nl_msg *msg;
9808 struct nlattr *container;
9809 int ret;
9810
9811 wpa_printf(MSG_DEBUG,
9812 "nl80211: Start P2P Listen offload: freq=%u, period=%u, interval=%u, count=%u",
9813 freq, period, interval, count);
9814
9815 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD))
9816 return -1;
9817
9818 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
9819 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
9820 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9821 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START))
9822 goto fail;
9823
9824 container = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
9825 if (!container)
9826 goto fail;
9827
9828 if (nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL,
9829 freq) ||
9830 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD,
9831 period) ||
9832 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL,
9833 interval) ||
9834 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT,
9835 count) ||
9836 nla_put(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES,
9837 dev_types_len, device_types) ||
9838 nla_put(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE,
9839 ies_len, ies))
9840 goto fail;
9841
9842 nla_nest_end(msg, container);
9843 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9844 msg = NULL;
9845 if (ret) {
9846 wpa_printf(MSG_DEBUG,
9847 "nl80211: Failed to send P2P Listen offload vendor command");
9848 goto fail;
9849 }
9850
9851 return 0;
9852
9853fail:
9854 nlmsg_free(msg);
9855 return -1;
9856}
9857
9858
9859static int nl80211_p2p_lo_stop(void *priv)
9860{
9861 struct i802_bss *bss = priv;
9862 struct wpa_driver_nl80211_data *drv = bss->drv;
9863 struct nl_msg *msg;
9864
9865 wpa_printf(MSG_DEBUG, "nl80211: Stop P2P Listen offload");
9866
9867 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD))
9868 return -1;
9869
9870 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
9871 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
9872 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9873 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP)) {
9874 nlmsg_free(msg);
9875 return -1;
9876 }
9877
9878 return send_and_recv_msgs(drv, msg, NULL, NULL);
9879}
9880
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08009881
9882static int nl80211_set_tdls_mode(void *priv, int tdls_external_control)
9883{
9884 struct i802_bss *bss = priv;
9885 struct wpa_driver_nl80211_data *drv = bss->drv;
9886 struct nl_msg *msg;
9887 struct nlattr *params;
9888 int ret;
9889 u32 tdls_mode;
9890
9891 wpa_printf(MSG_DEBUG,
9892 "nl80211: Set TDKS mode: tdls_external_control=%d",
9893 tdls_external_control);
9894
9895 if (tdls_external_control == 1)
9896 tdls_mode = QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT |
9897 QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL;
9898 else
9899 tdls_mode = QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT;
9900
9901 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
9902 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
9903 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9904 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS))
9905 goto fail;
9906
9907 params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
9908 if (!params)
9909 goto fail;
9910
9911 if (nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE,
9912 tdls_mode))
9913 goto fail;
9914
9915 nla_nest_end(msg, params);
9916
9917 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9918 msg = NULL;
9919 if (ret) {
9920 wpa_printf(MSG_ERROR,
9921 "nl80211: Set TDLS mode failed: ret=%d (%s)",
9922 ret, strerror(-ret));
9923 goto fail;
9924 }
9925 return 0;
9926fail:
9927 nlmsg_free(msg);
9928 return -1;
9929}
9930
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07009931
9932#ifdef CONFIG_MBO
9933
9934static enum mbo_transition_reject_reason
9935nl80211_mbo_reject_reason_mapping(enum qca_wlan_btm_candidate_status status)
9936{
9937 switch (status) {
9938 case QCA_STATUS_REJECT_EXCESSIVE_FRAME_LOSS_EXPECTED:
9939 return MBO_TRANSITION_REJECT_REASON_FRAME_LOSS;
9940 case QCA_STATUS_REJECT_EXCESSIVE_DELAY_EXPECTED:
9941 return MBO_TRANSITION_REJECT_REASON_DELAY;
9942 case QCA_STATUS_REJECT_INSUFFICIENT_QOS_CAPACITY:
9943 return MBO_TRANSITION_REJECT_REASON_QOS_CAPACITY;
9944 case QCA_STATUS_REJECT_LOW_RSSI:
9945 return MBO_TRANSITION_REJECT_REASON_RSSI;
9946 case QCA_STATUS_REJECT_HIGH_INTERFERENCE:
9947 return MBO_TRANSITION_REJECT_REASON_INTERFERENCE;
9948 case QCA_STATUS_REJECT_UNKNOWN:
9949 default:
9950 return MBO_TRANSITION_REJECT_REASON_UNSPECIFIED;
9951 }
9952}
9953
9954
9955static void nl80211_parse_btm_candidate_info(struct candidate_list *candidate,
9956 struct nlattr *tb[], int num)
9957{
9958 enum qca_wlan_btm_candidate_status status;
9959 char buf[50];
9960
9961 os_memcpy(candidate->bssid,
9962 nla_data(tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]),
9963 ETH_ALEN);
9964
9965 status = nla_get_u32(
9966 tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS]);
9967 candidate->is_accept = status == QCA_STATUS_ACCEPT;
9968 candidate->reject_reason = nl80211_mbo_reject_reason_mapping(status);
9969
9970 if (candidate->is_accept)
9971 os_snprintf(buf, sizeof(buf), "Accepted");
9972 else
9973 os_snprintf(buf, sizeof(buf),
9974 "Rejected, Reject_reason: %d",
9975 candidate->reject_reason);
9976 wpa_printf(MSG_DEBUG, "nl80211: BSSID[%d]: " MACSTR " %s",
9977 num, MAC2STR(candidate->bssid), buf);
9978}
9979
9980
9981static int
9982nl80211_get_bss_transition_status_handler(struct nl_msg *msg, void *arg)
9983{
9984 struct wpa_bss_candidate_info *info = arg;
9985 struct candidate_list *candidate = info->candidates;
9986 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
9987 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9988 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1];
9989 static struct nla_policy policy[
9990 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1] = {
9991 [QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID] = {
9992 .minlen = ETH_ALEN
9993 },
9994 [QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS] = {
9995 .type = NLA_U32,
9996 },
9997 };
9998 struct nlattr *attr;
9999 int rem;
10000 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10001 u8 num;
10002
10003 num = info->num; /* number of candidates sent to driver */
10004 info->num = 0;
10005 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10006 genlmsg_attrlen(gnlh, 0), NULL);
10007
10008 if (!tb_msg[NL80211_ATTR_VENDOR_DATA] ||
10009 nla_parse_nested(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
10010 tb_msg[NL80211_ATTR_VENDOR_DATA], NULL) ||
10011 !tb_vendor[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO])
10012 return NL_SKIP;
10013
10014 wpa_printf(MSG_DEBUG,
10015 "nl80211: WNM Candidate list received from driver");
10016 nla_for_each_nested(attr,
10017 tb_vendor[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO],
10018 rem) {
10019 if (info->num >= num ||
10020 nla_parse_nested(
10021 tb, QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX,
10022 attr, policy) ||
10023 !tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID] ||
10024 !tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS])
10025 break;
10026
10027 nl80211_parse_btm_candidate_info(candidate, tb, info->num);
10028
10029 candidate++;
10030 info->num++;
10031 }
10032
10033 return NL_SKIP;
10034}
10035
10036
10037static struct wpa_bss_candidate_info *
10038nl80211_get_bss_transition_status(void *priv, struct wpa_bss_trans_info *params)
10039{
10040 struct i802_bss *bss = priv;
10041 struct wpa_driver_nl80211_data *drv = bss->drv;
10042 struct nl_msg *msg;
10043 struct nlattr *attr, *attr1, *attr2;
10044 struct wpa_bss_candidate_info *info;
10045 u8 i;
10046 int ret;
10047 u8 *pos;
10048
10049 if (!drv->fetch_bss_trans_status)
10050 return NULL;
10051
10052 info = os_zalloc(sizeof(*info));
10053 if (!info)
10054 return NULL;
10055 /* Allocate memory for number of candidates sent to driver */
10056 info->candidates = os_calloc(params->n_candidates,
10057 sizeof(*info->candidates));
10058 if (!info->candidates) {
10059 os_free(info);
10060 return NULL;
10061 }
10062
10063 /* Copy the number of candidates being sent to driver. This is used in
10064 * nl80211_get_bss_transition_status_handler() to limit the number of
10065 * candidates that can be populated in info->candidates and will be
10066 * later overwritten with the actual number of candidates received from
10067 * the driver.
10068 */
10069 info->num = params->n_candidates;
10070
10071 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
10072 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
10073 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
10074 QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS))
10075 goto fail;
10076
10077 attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
10078 if (!attr)
10079 goto fail;
10080
10081 if (nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON,
10082 params->mbo_transition_reason))
10083 goto fail;
10084
10085 attr1 = nla_nest_start(msg, QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO);
10086 if (!attr1)
10087 goto fail;
10088
10089 wpa_printf(MSG_DEBUG,
10090 "nl80211: WNM Candidate list info sending to driver: mbo_transition_reason: %d n_candidates: %d",
10091 params->mbo_transition_reason, params->n_candidates);
10092 pos = params->bssid;
10093 for (i = 0; i < params->n_candidates; i++) {
10094 wpa_printf(MSG_DEBUG, "nl80211: BSSID[%d]: " MACSTR, i,
10095 MAC2STR(pos));
10096 attr2 = nla_nest_start(msg, i);
10097 if (!attr2 ||
10098 nla_put(msg, QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID,
10099 ETH_ALEN, pos))
10100 goto fail;
10101 pos += ETH_ALEN;
10102 nla_nest_end(msg, attr2);
10103 }
10104
10105 nla_nest_end(msg, attr1);
10106 nla_nest_end(msg, attr);
10107
10108 ret = send_and_recv_msgs(drv, msg,
10109 nl80211_get_bss_transition_status_handler,
10110 info);
10111 msg = NULL;
10112 if (ret) {
10113 wpa_printf(MSG_ERROR,
10114 "nl80211: WNM Get BSS transition status failed: ret=%d (%s)",
10115 ret, strerror(-ret));
10116 goto fail;
10117 }
10118 return info;
10119
10120fail:
10121 nlmsg_free(msg);
10122 os_free(info->candidates);
10123 os_free(info);
10124 return NULL;
10125}
10126
10127
10128/**
10129 * nl80211_ignore_assoc_disallow - Configure driver to ignore assoc_disallow
10130 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
10131 * @ignore_assoc_disallow: 0 to not ignore, 1 to ignore
10132 * Returns: 0 on success, -1 on failure
10133 */
10134static int nl80211_ignore_assoc_disallow(void *priv, int ignore_disallow)
10135{
10136 struct i802_bss *bss = priv;
10137 struct wpa_driver_nl80211_data *drv = bss->drv;
10138 struct nl_msg *msg;
10139 struct nlattr *attr;
10140 int ret = -1;
10141
10142 if (!drv->set_wifi_conf_vendor_cmd_avail)
10143 return -1;
10144
10145 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
10146 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
10147 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
10148 QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION))
10149 goto fail;
10150
10151 attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
10152 if (!attr)
10153 goto fail;
10154
10155 wpa_printf(MSG_DEBUG, "nl80211: Set ignore_assoc_disallow %d",
10156 ignore_disallow);
10157 if (nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED,
10158 ignore_disallow))
10159 goto fail;
10160
10161 nla_nest_end(msg, attr);
10162
10163 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
10164 msg = NULL;
10165 if (ret) {
10166 wpa_printf(MSG_ERROR,
10167 "nl80211: Set ignore_assoc_disallow failed: ret=%d (%s)",
10168 ret, strerror(-ret));
10169 goto fail;
10170 }
10171
10172fail:
10173 nlmsg_free(msg);
10174 return ret;
10175}
10176
10177#endif /* CONFIG_MBO */
10178
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010179#endif /* CONFIG_DRIVER_NL80211_QCA */
10180
10181
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010182static int nl80211_write_to_file(const char *name, unsigned int val)
10183{
10184 int fd, len;
10185 char tmp[128];
10186
10187 fd = open(name, O_RDWR);
10188 if (fd < 0) {
10189 wpa_printf(MSG_ERROR, "nl80211: Failed to open %s: %s",
10190 name, strerror(errno));
10191 return fd;
10192 }
10193
10194 len = os_snprintf(tmp, sizeof(tmp), "%u\n", val);
10195 len = write(fd, tmp, len);
10196 if (len < 0)
10197 wpa_printf(MSG_ERROR, "nl80211: Failed to write to %s: %s",
10198 name, strerror(errno));
10199 close(fd);
10200
10201 return 0;
10202}
10203
10204
10205static int nl80211_configure_data_frame_filters(void *priv, u32 filter_flags)
10206{
10207 struct i802_bss *bss = priv;
10208 char path[128];
10209 int ret;
10210
10211 wpa_printf(MSG_DEBUG, "nl80211: Data frame filter flags=0x%x",
10212 filter_flags);
10213
10214 /* Configure filtering of unicast frame encrypted using GTK */
10215 ret = os_snprintf(path, sizeof(path),
10216 "/proc/sys/net/ipv4/conf/%s/drop_unicast_in_l2_multicast",
10217 bss->ifname);
10218 if (os_snprintf_error(sizeof(path), ret))
10219 return -1;
10220
10221 ret = nl80211_write_to_file(path,
10222 !!(filter_flags &
10223 WPA_DATA_FRAME_FILTER_FLAG_GTK));
10224 if (ret) {
10225 wpa_printf(MSG_ERROR,
10226 "nl80211: Failed to set IPv4 unicast in multicast filter");
10227 return ret;
10228 }
10229
10230 os_snprintf(path, sizeof(path),
10231 "/proc/sys/net/ipv6/conf/%s/drop_unicast_in_l2_multicast",
10232 bss->ifname);
10233 ret = nl80211_write_to_file(path,
10234 !!(filter_flags &
10235 WPA_DATA_FRAME_FILTER_FLAG_GTK));
10236
10237 if (ret) {
10238 wpa_printf(MSG_ERROR,
10239 "nl80211: Failed to set IPv6 unicast in multicast filter");
10240 return ret;
10241 }
10242
10243 /* Configure filtering of unicast frame encrypted using GTK */
10244 os_snprintf(path, sizeof(path),
10245 "/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp",
10246 bss->ifname);
10247 ret = nl80211_write_to_file(path,
10248 !!(filter_flags &
10249 WPA_DATA_FRAME_FILTER_FLAG_ARP));
10250 if (ret) {
10251 wpa_printf(MSG_ERROR,
10252 "nl80211: Failed set gratuitous ARP filter");
10253 return ret;
10254 }
10255
10256 /* Configure filtering of IPv6 NA frames */
10257 os_snprintf(path, sizeof(path),
10258 "/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na",
10259 bss->ifname);
10260 ret = nl80211_write_to_file(path,
10261 !!(filter_flags &
10262 WPA_DATA_FRAME_FILTER_FLAG_NA));
10263 if (ret) {
10264 wpa_printf(MSG_ERROR,
10265 "nl80211: Failed to set unsolicited NA filter");
10266 return ret;
10267 }
10268
10269 return 0;
10270}
10271
10272
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -070010273static int nl80211_get_ext_capab(void *priv, enum wpa_driver_if_type type,
10274 const u8 **ext_capa, const u8 **ext_capa_mask,
10275 unsigned int *ext_capa_len)
10276{
10277 struct i802_bss *bss = priv;
10278 struct wpa_driver_nl80211_data *drv = bss->drv;
10279 enum nl80211_iftype nlmode;
10280 unsigned int i;
10281
10282 if (!ext_capa || !ext_capa_mask || !ext_capa_len)
10283 return -1;
10284
10285 nlmode = wpa_driver_nl80211_if_type(type);
10286
10287 /* By default, use the per-radio values */
10288 *ext_capa = drv->extended_capa;
10289 *ext_capa_mask = drv->extended_capa_mask;
10290 *ext_capa_len = drv->extended_capa_len;
10291
10292 /* Replace the default value if a per-interface type value exists */
10293 for (i = 0; i < drv->num_iface_ext_capa; i++) {
10294 if (nlmode == drv->iface_ext_capa[i].iftype) {
10295 *ext_capa = drv->iface_ext_capa[i].ext_capa;
10296 *ext_capa_mask = drv->iface_ext_capa[i].ext_capa_mask;
10297 *ext_capa_len = drv->iface_ext_capa[i].ext_capa_len;
10298 break;
10299 }
10300 }
10301
10302 return 0;
10303}
10304
10305
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010306static int nl80211_update_connection_params(
10307 void *priv, struct wpa_driver_associate_params *params,
10308 enum wpa_drv_update_connect_params_mask mask)
10309{
10310 struct i802_bss *bss = priv;
10311 struct wpa_driver_nl80211_data *drv = bss->drv;
10312 struct nl_msg *msg;
10313 int ret = -1;
10314 enum nl80211_auth_type type;
10315
10316 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_UPDATE_CONNECT_PARAMS);
10317 if (!msg)
10318 goto fail;
10319
10320 wpa_printf(MSG_DEBUG, "nl80211: Update connection params (ifindex=%d)",
10321 drv->ifindex);
10322
10323 if ((mask & WPA_DRV_UPDATE_ASSOC_IES) && params->wpa_ie) {
10324 if (nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len,
10325 params->wpa_ie))
10326 goto fail;
10327 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie,
10328 params->wpa_ie_len);
10329 }
10330
10331 if (mask & WPA_DRV_UPDATE_AUTH_TYPE) {
10332 type = get_nl_auth_type(params->auth_alg);
10333 if (type == NL80211_AUTHTYPE_MAX ||
10334 nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type))
10335 goto fail;
10336 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
10337 }
10338
10339 if ((mask & WPA_DRV_UPDATE_FILS_ERP_INFO) &&
10340 nl80211_put_fils_connect_params(drv, params, msg))
10341 goto fail;
10342
10343 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
10344 msg = NULL;
10345 if (ret)
10346 wpa_dbg(drv->ctx, MSG_DEBUG,
10347 "nl80211: Update connect params command failed: ret=%d (%s)",
10348 ret, strerror(-ret));
10349
10350fail:
10351 nlmsg_free(msg);
10352 return ret;
10353}
10354
10355
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010356const struct wpa_driver_ops wpa_driver_nl80211_ops = {
10357 .name = "nl80211",
10358 .desc = "Linux nl80211/cfg80211",
10359 .get_bssid = wpa_driver_nl80211_get_bssid,
10360 .get_ssid = wpa_driver_nl80211_get_ssid,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010361 .set_key = driver_nl80211_set_key,
10362 .scan2 = driver_nl80211_scan2,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010363 .sched_scan = wpa_driver_nl80211_sched_scan,
10364 .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010365 .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080010366 .abort_scan = wpa_driver_nl80211_abort_scan,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010367 .deauthenticate = driver_nl80211_deauthenticate,
10368 .authenticate = driver_nl80211_authenticate,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010369 .associate = wpa_driver_nl80211_associate,
10370 .global_init = nl80211_global_init,
10371 .global_deinit = nl80211_global_deinit,
10372 .init2 = wpa_driver_nl80211_init,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010373 .deinit = driver_nl80211_deinit,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010374 .get_capa = wpa_driver_nl80211_get_capa,
10375 .set_operstate = wpa_driver_nl80211_set_operstate,
10376 .set_supp_port = wpa_driver_nl80211_set_supp_port,
10377 .set_country = wpa_driver_nl80211_set_country,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010378 .get_country = wpa_driver_nl80211_get_country,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010379 .set_ap = wpa_driver_nl80211_set_ap,
Dmitry Shmidt8bae4132013-06-06 11:25:10 -070010380 .set_acl = wpa_driver_nl80211_set_acl,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010381 .if_add = wpa_driver_nl80211_if_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010382 .if_remove = driver_nl80211_if_remove,
10383 .send_mlme = driver_nl80211_send_mlme,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010384 .get_hw_feature_data = nl80211_get_hw_feature_data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010385 .sta_add = wpa_driver_nl80211_sta_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010386 .sta_remove = driver_nl80211_sta_remove,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010387 .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
10388 .sta_set_flags = wpa_driver_nl80211_sta_set_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010389 .hapd_init = i802_init,
10390 .hapd_deinit = i802_deinit,
Jouni Malinen75ecf522011-06-27 15:19:46 -070010391 .set_wds_sta = i802_set_wds_sta,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010392 .get_seqnum = i802_get_seqnum,
10393 .flush = i802_flush,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010394 .get_inact_sec = i802_get_inact_sec,
10395 .sta_clear_stats = i802_sta_clear_stats,
10396 .set_rts = i802_set_rts,
10397 .set_frag = i802_set_frag,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010398 .set_tx_queue_params = i802_set_tx_queue_params,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010399 .set_sta_vlan = driver_nl80211_set_sta_vlan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010400 .sta_deauth = i802_sta_deauth,
10401 .sta_disassoc = i802_sta_disassoc,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010402 .read_sta_data = driver_nl80211_read_sta_data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010403 .set_freq = i802_set_freq,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010404 .send_action = driver_nl80211_send_action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010405 .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
10406 .remain_on_channel = wpa_driver_nl80211_remain_on_channel,
10407 .cancel_remain_on_channel =
10408 wpa_driver_nl80211_cancel_remain_on_channel,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010409 .probe_req_report = driver_nl80211_probe_req_report,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010410 .deinit_ap = wpa_driver_nl80211_deinit_ap,
Dmitry Shmidt04949592012-07-19 12:16:46 -070010411 .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010412 .resume = wpa_driver_nl80211_resume,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010413 .signal_monitor = nl80211_signal_monitor,
10414 .signal_poll = nl80211_signal_poll,
10415 .send_frame = nl80211_send_frame,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010416 .set_param = nl80211_set_param,
10417 .get_radio_name = nl80211_get_radio_name,
Jouni Malinen75ecf522011-06-27 15:19:46 -070010418 .add_pmkid = nl80211_add_pmkid,
10419 .remove_pmkid = nl80211_remove_pmkid,
10420 .flush_pmkid = nl80211_flush_pmkid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010421 .set_rekey_info = nl80211_set_rekey_info,
10422 .poll_client = nl80211_poll_client,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010423 .set_p2p_powersave = nl80211_set_p2p_powersave,
Dmitry Shmidtea69e842013-05-13 14:52:28 -070010424 .start_dfs_cac = nl80211_start_radar_detection,
10425 .stop_ap = wpa_driver_nl80211_stop_ap,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010426#ifdef CONFIG_TDLS
10427 .send_tdls_mgmt = nl80211_send_tdls_mgmt,
10428 .tdls_oper = nl80211_tdls_oper,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010429 .tdls_enable_channel_switch = nl80211_tdls_enable_channel_switch,
10430 .tdls_disable_channel_switch = nl80211_tdls_disable_channel_switch,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010431#endif /* CONFIG_TDLS */
Dmitry Shmidt700a1372013-03-15 14:14:44 -070010432 .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010433 .get_mac_addr = wpa_driver_nl80211_get_macaddr,
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070010434 .get_survey = wpa_driver_nl80211_get_survey,
Dmitry Shmidt56052862013-10-04 10:23:25 -070010435 .status = wpa_driver_nl80211_status,
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080010436 .switch_channel = nl80211_switch_channel,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010437#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070010438 .set_noa = wpa_driver_set_p2p_noa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010439 .get_noa = wpa_driver_get_p2p_noa,
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070010440 .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080010441#endif /* ANDROID_P2P */
Dmitry Shmidt738a26e2011-07-07 14:22:14 -070010442#ifdef ANDROID
Dmitry Shmidt41712582015-06-29 11:02:15 -070010443#ifndef ANDROID_LIB_STUB
Dmitry Shmidt738a26e2011-07-07 14:22:14 -070010444 .driver_cmd = wpa_driver_nl80211_driver_cmd,
Dmitry Shmidt41712582015-06-29 11:02:15 -070010445#endif /* !ANDROID_LIB_STUB */
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080010446#endif /* ANDROID */
Dmitry Shmidta38abf92014-03-06 13:38:44 -080010447 .vendor_cmd = nl80211_vendor_cmd,
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080010448 .set_qos_map = nl80211_set_qos_map,
Dmitry Shmidtb58836e2014-04-29 14:35:56 -070010449 .set_wowlan = nl80211_set_wowlan,
Dmitry Shmidt661b4f72014-09-29 14:58:27 -070010450 .set_mac_addr = nl80211_set_mac_addr,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010451#ifdef CONFIG_MESH
10452 .init_mesh = wpa_driver_nl80211_init_mesh,
10453 .join_mesh = wpa_driver_nl80211_join_mesh,
10454 .leave_mesh = wpa_driver_nl80211_leave_mesh,
10455#endif /* CONFIG_MESH */
10456 .br_add_ip_neigh = wpa_driver_br_add_ip_neigh,
10457 .br_delete_ip_neigh = wpa_driver_br_delete_ip_neigh,
10458 .br_port_set_attr = wpa_driver_br_port_set_attr,
10459 .br_set_net_param = wpa_driver_br_set_net_param,
10460 .add_tx_ts = nl80211_add_ts,
10461 .del_tx_ts = nl80211_del_ts,
Dmitry Shmidte4663042016-04-04 10:07:49 -070010462 .get_ifindex = nl80211_get_ifindex,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010463#ifdef CONFIG_DRIVER_NL80211_QCA
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070010464 .roaming = nl80211_roaming,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080010465 .do_acs = wpa_driver_do_acs,
Ravi Joshie6ccb162015-07-16 17:45:41 -070010466 .set_band = nl80211_set_band,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010467 .get_pref_freq_list = nl80211_get_pref_freq_list,
10468 .set_prob_oper_freq = nl80211_set_prob_oper_freq,
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070010469 .p2p_lo_start = nl80211_p2p_lo_start,
10470 .p2p_lo_stop = nl80211_p2p_lo_stop,
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -070010471 .set_default_scan_ies = nl80211_set_default_scan_ies,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080010472 .set_tdls_mode = nl80211_set_tdls_mode,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010473#ifdef CONFIG_MBO
10474 .get_bss_transition_status = nl80211_get_bss_transition_status,
10475 .ignore_assoc_disallow = nl80211_ignore_assoc_disallow,
10476#endif /* CONFIG_MBO */
10477 .set_bssid_blacklist = nl80211_set_bssid_blacklist,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010478#endif /* CONFIG_DRIVER_NL80211_QCA */
Dmitry Shmidt849734c2016-05-27 09:59:01 -070010479 .configure_data_frame_filters = nl80211_configure_data_frame_filters,
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -070010480 .get_ext_capab = nl80211_get_ext_capab,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010481 .update_connect_params = nl80211_update_connection_params,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010482};