blob: 8527e90c2b967fe6506c0c3410b797ee83e1c7c0 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Driver interaction with Linux nl80211/cfg80211
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003 * Copyright (c) 2002-2014, 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"
32#include "l2_packet/l2_packet.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070033#include "netlink.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080034#include "linux_defines.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070035#include "linux_ioctl.h"
36#include "radiotap.h"
37#include "radiotap_iter.h"
38#include "rfkill.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080039#include "driver_nl80211.h"
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080040
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080041
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080042#ifndef CONFIG_LIBNL20
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043/*
44 * libnl 1.1 has a bug, it tries to allocate socket numbers densely
45 * but when you free a socket again it will mess up its bitmap and
46 * and use the wrong number the next time it needs a socket ID.
47 * Therefore, we wrap the handle alloc/destroy and add our own pid
48 * accounting.
49 */
50static uint32_t port_bitmap[32] = { 0 };
51
52static struct nl_handle *nl80211_handle_alloc(void *cb)
53{
54 struct nl_handle *handle;
55 uint32_t pid = getpid() & 0x3FFFFF;
56 int i;
57
58 handle = nl_handle_alloc_cb(cb);
59
60 for (i = 0; i < 1024; i++) {
61 if (port_bitmap[i / 32] & (1 << (i % 32)))
62 continue;
63 port_bitmap[i / 32] |= 1 << (i % 32);
64 pid += i << 22;
65 break;
66 }
67
68 nl_socket_set_local_port(handle, pid);
69
70 return handle;
71}
72
73static void nl80211_handle_destroy(struct nl_handle *handle)
74{
75 uint32_t port = nl_socket_get_local_port(handle);
76
77 port >>= 22;
78 port_bitmap[port / 32] &= ~(1 << (port % 32));
79
80 nl_handle_destroy(handle);
81}
82#endif /* CONFIG_LIBNL20 */
83
84
Dmitry Shmidt54605472013-11-08 11:10:19 -080085#ifdef ANDROID
86/* system/core/libnl_2 does not include nl_socket_set_nonblocking() */
Dmitry Shmidt54605472013-11-08 11:10:19 -080087#undef nl_socket_set_nonblocking
88#define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080089
90#define genl_ctrl_resolve android_genl_ctrl_resolve
Dmitry Shmidt54605472013-11-08 11:10:19 -080091#endif /* ANDROID */
92
93
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080094static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
95{
96 struct nl_handle *handle;
97
98 handle = nl80211_handle_alloc(cb);
99 if (handle == NULL) {
100 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
101 "callbacks (%s)", dbg);
102 return NULL;
103 }
104
105 if (genl_connect(handle)) {
106 wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
107 "netlink (%s)", dbg);
108 nl80211_handle_destroy(handle);
109 return NULL;
110 }
111
112 return handle;
113}
114
115
116static void nl_destroy_handles(struct nl_handle **handle)
117{
118 if (*handle == NULL)
119 return;
120 nl80211_handle_destroy(*handle);
121 *handle = NULL;
122}
123
124
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700125#if __WORDSIZE == 64
126#define ELOOP_SOCKET_INVALID (intptr_t) 0x8888888888888889ULL
127#else
128#define ELOOP_SOCKET_INVALID (intptr_t) 0x88888889ULL
129#endif
130
131static void nl80211_register_eloop_read(struct nl_handle **handle,
132 eloop_sock_handler handler,
133 void *eloop_data)
134{
135 nl_socket_set_nonblocking(*handle);
136 eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
137 eloop_data, *handle);
138 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
139}
140
141
142static void nl80211_destroy_eloop_handle(struct nl_handle **handle)
143{
144 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
145 eloop_unregister_read_sock(nl_socket_get_fd(*handle));
146 nl_destroy_handles(handle);
147}
148
149
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800150static void nl80211_global_deinit(void *priv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800151
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800152static void wpa_driver_nl80211_deinit(struct i802_bss *bss);
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700153static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
154 struct hostapd_freq_params *freq);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700155
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700156static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800157wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800158 const u8 *set_addr, int first,
159 const char *driver_params);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800160static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700161 unsigned int freq, unsigned int wait,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800162 const u8 *buf, size_t buf_len, u64 *cookie,
163 int no_cck, int no_ack, int offchanok);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800164static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
165 int report);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700167static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
168static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
169static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
Dmitry Shmidt738a26e2011-07-07 14:22:14 -0700170
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700171static int nl80211_set_channel(struct i802_bss *bss,
172 struct hostapd_freq_params *freq, int set_chan);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700173static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
174 int ifindex, int disabled);
175
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800176static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
177 int reset_mode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800178
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -0700179static int i802_set_iface_flags(struct i802_bss *bss, int up);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800180static int nl80211_set_param(void *priv, const char *param);
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700181
182
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800183/* Converts nl80211_chan_width to a common format */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800184enum chan_width convert2width(int width)
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800185{
186 switch (width) {
187 case NL80211_CHAN_WIDTH_20_NOHT:
188 return CHAN_WIDTH_20_NOHT;
189 case NL80211_CHAN_WIDTH_20:
190 return CHAN_WIDTH_20;
191 case NL80211_CHAN_WIDTH_40:
192 return CHAN_WIDTH_40;
193 case NL80211_CHAN_WIDTH_80:
194 return CHAN_WIDTH_80;
195 case NL80211_CHAN_WIDTH_80P80:
196 return CHAN_WIDTH_80P80;
197 case NL80211_CHAN_WIDTH_160:
198 return CHAN_WIDTH_160;
199 }
200 return CHAN_WIDTH_UNKNOWN;
201}
202
203
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800204int is_ap_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800205{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700206 return nlmode == NL80211_IFTYPE_AP ||
207 nlmode == NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800208}
209
210
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800211int is_sta_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800212{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700213 return nlmode == NL80211_IFTYPE_STATION ||
214 nlmode == NL80211_IFTYPE_P2P_CLIENT;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800215}
216
217
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700218static int is_p2p_net_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800219{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700220 return nlmode == NL80211_IFTYPE_P2P_CLIENT ||
221 nlmode == NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800222}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700223
224
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800225struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv,
226 int ifindex)
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700227{
228 struct i802_bss *bss;
229
230 for (bss = drv->first_bss; bss; bss = bss->next) {
231 if (bss->ifindex == ifindex)
232 return bss;
233 }
234
235 return NULL;
236}
237
238
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800239static int is_mesh_interface(enum nl80211_iftype nlmode)
240{
241 return nlmode == NL80211_IFTYPE_MESH_POINT;
242}
243
244
245void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700246{
247 if (drv->associated)
248 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
249 drv->associated = 0;
250 os_memset(drv->bssid, 0, ETH_ALEN);
251}
252
253
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254/* nl80211 code */
255static int ack_handler(struct nl_msg *msg, void *arg)
256{
257 int *err = arg;
258 *err = 0;
259 return NL_STOP;
260}
261
262static int finish_handler(struct nl_msg *msg, void *arg)
263{
264 int *ret = arg;
265 *ret = 0;
266 return NL_SKIP;
267}
268
269static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
270 void *arg)
271{
272 int *ret = arg;
273 *ret = err->error;
274 return NL_SKIP;
275}
276
277
278static int no_seq_check(struct nl_msg *msg, void *arg)
279{
280 return NL_OK;
281}
282
283
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800284static void nl80211_nlmsg_clear(struct nl_msg *msg)
285{
286 /*
287 * Clear nlmsg data, e.g., to make sure key material is not left in
288 * heap memory for unnecessarily long time.
289 */
290 if (msg) {
291 struct nlmsghdr *hdr = nlmsg_hdr(msg);
292 void *data = nlmsg_data(hdr);
293 /*
294 * This would use nlmsg_datalen() or the older nlmsg_len() if
295 * only libnl were to maintain a stable API.. Neither will work
296 * with all released versions, so just calculate the length
297 * here.
298 */
299 int len = hdr->nlmsg_len - NLMSG_HDRLEN;
300
301 os_memset(data, 0, len);
302 }
303}
304
305
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800306static int send_and_recv(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700307 struct nl_handle *nl_handle, struct nl_msg *msg,
308 int (*valid_handler)(struct nl_msg *, void *),
309 void *valid_data)
310{
311 struct nl_cb *cb;
312 int err = -ENOMEM;
313
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800314 if (!msg)
315 return -ENOMEM;
316
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800317 cb = nl_cb_clone(global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700318 if (!cb)
319 goto out;
320
321 err = nl_send_auto_complete(nl_handle, msg);
322 if (err < 0)
323 goto out;
324
325 err = 1;
326
327 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
328 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
329 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
330
331 if (valid_handler)
332 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
333 valid_handler, valid_data);
334
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700335 while (err > 0) {
336 int res = nl_recvmsgs(nl_handle, cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -0700337 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700338 wpa_printf(MSG_INFO,
339 "nl80211: %s->nl_recvmsgs failed: %d",
340 __func__, res);
341 }
342 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700343 out:
344 nl_cb_put(cb);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800345 if (!valid_handler && valid_data == (void *) -1)
346 nl80211_nlmsg_clear(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700347 nlmsg_free(msg);
348 return err;
349}
350
351
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800352int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
353 struct nl_msg *msg,
354 int (*valid_handler)(struct nl_msg *, void *),
355 void *valid_data)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700356{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800357 return send_and_recv(drv->global, drv->global->nl, msg,
358 valid_handler, valid_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700359}
360
361
362struct family_data {
363 const char *group;
364 int id;
365};
366
367
368static int family_handler(struct nl_msg *msg, void *arg)
369{
370 struct family_data *res = arg;
371 struct nlattr *tb[CTRL_ATTR_MAX + 1];
372 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
373 struct nlattr *mcgrp;
374 int i;
375
376 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
377 genlmsg_attrlen(gnlh, 0), NULL);
378 if (!tb[CTRL_ATTR_MCAST_GROUPS])
379 return NL_SKIP;
380
381 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
382 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
383 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
384 nla_len(mcgrp), NULL);
385 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
386 !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
387 os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
388 res->group,
389 nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
390 continue;
391 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
392 break;
393 };
394
395 return NL_SKIP;
396}
397
398
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800399static int nl_get_multicast_id(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700400 const char *family, const char *group)
401{
402 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800403 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404 struct family_data res = { group, -ENOENT };
405
406 msg = nlmsg_alloc();
407 if (!msg)
408 return -ENOMEM;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800409 if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
410 0, 0, CTRL_CMD_GETFAMILY, 0) ||
411 nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
412 nlmsg_free(msg);
413 return -1;
414 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800416 ret = send_and_recv(global, global->nl, msg, family_handler, &res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700417 if (ret == 0)
418 ret = res.id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419 return ret;
420}
421
422
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800423void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
424 struct nl_msg *msg, int flags, uint8_t cmd)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800425{
426 return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
427 0, flags, cmd, 0);
428}
429
430
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800431static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss)
432{
433 if (bss->wdev_id_set)
434 return nla_put_u64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
435 return nla_put_u32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
436}
437
438
439struct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd)
440{
441 struct nl_msg *msg;
442
443 msg = nlmsg_alloc();
444 if (!msg)
445 return NULL;
446
447 if (!nl80211_cmd(bss->drv, msg, flags, cmd) ||
448 nl80211_set_iface_id(msg, bss) < 0) {
449 nlmsg_free(msg);
450 return NULL;
451 }
452
453 return msg;
454}
455
456
457static struct nl_msg *
458nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
459 int flags, uint8_t cmd)
460{
461 struct nl_msg *msg;
462
463 msg = nlmsg_alloc();
464 if (!msg)
465 return NULL;
466
467 if (!nl80211_cmd(drv, msg, flags, cmd) ||
468 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
469 nlmsg_free(msg);
470 return NULL;
471 }
472
473 return msg;
474}
475
476
477struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
478 uint8_t cmd)
479{
480 return nl80211_ifindex_msg(drv, drv->ifindex, flags, cmd);
481}
482
483
484struct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd)
485{
486 return nl80211_ifindex_msg(bss->drv, bss->ifindex, flags, cmd);
487}
488
489
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800490struct wiphy_idx_data {
491 int wiphy_idx;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700492 enum nl80211_iftype nlmode;
493 u8 *macaddr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800494};
495
496
497static int netdev_info_handler(struct nl_msg *msg, void *arg)
498{
499 struct nlattr *tb[NL80211_ATTR_MAX + 1];
500 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
501 struct wiphy_idx_data *info = arg;
502
503 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
504 genlmsg_attrlen(gnlh, 0), NULL);
505
506 if (tb[NL80211_ATTR_WIPHY])
507 info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
508
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700509 if (tb[NL80211_ATTR_IFTYPE])
510 info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
511
512 if (tb[NL80211_ATTR_MAC] && info->macaddr)
513 os_memcpy(info->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
514 ETH_ALEN);
515
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800516 return NL_SKIP;
517}
518
519
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800520int nl80211_get_wiphy_index(struct i802_bss *bss)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800521{
522 struct nl_msg *msg;
523 struct wiphy_idx_data data = {
524 .wiphy_idx = -1,
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700525 .macaddr = NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800526 };
527
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800528 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
529 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800530
531 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
532 return data.wiphy_idx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800533 return -1;
534}
535
536
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700537static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
538{
539 struct nl_msg *msg;
540 struct wiphy_idx_data data = {
541 .nlmode = NL80211_IFTYPE_UNSPECIFIED,
542 .macaddr = NULL,
543 };
544
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800545 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
546 return NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700547
548 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
549 return data.nlmode;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700550 return NL80211_IFTYPE_UNSPECIFIED;
551}
552
553
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700554static int nl80211_get_macaddr(struct i802_bss *bss)
555{
556 struct nl_msg *msg;
557 struct wiphy_idx_data data = {
558 .macaddr = bss->addr,
559 };
560
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800561 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE)))
562 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700563
564 return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data);
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700565}
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700566
567
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800568static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
569 struct nl80211_wiphy_data *w)
570{
571 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800572 int ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800573
574 msg = nlmsg_alloc();
575 if (!msg)
576 return -1;
577
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800578 if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS) ||
579 nla_put_u32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx)) {
580 nlmsg_free(msg);
581 return -1;
582 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800583
584 ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800585 if (ret) {
586 wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
587 "failed: ret=%d (%s)",
588 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800589 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800590 return ret;
591}
592
593
594static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle)
595{
596 struct nl80211_wiphy_data *w = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700597 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800598
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800599 wpa_printf(MSG_EXCESSIVE, "nl80211: Beacon event message available");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800600
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700601 res = nl_recvmsgs(handle, w->nl_cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -0700602 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700603 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
604 __func__, res);
605 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800606}
607
608
609static int process_beacon_event(struct nl_msg *msg, void *arg)
610{
611 struct nl80211_wiphy_data *w = arg;
612 struct wpa_driver_nl80211_data *drv;
613 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
614 struct nlattr *tb[NL80211_ATTR_MAX + 1];
615 union wpa_event_data event;
616
617 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
618 genlmsg_attrlen(gnlh, 0), NULL);
619
620 if (gnlh->cmd != NL80211_CMD_FRAME) {
621 wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)",
622 gnlh->cmd);
623 return NL_SKIP;
624 }
625
626 if (!tb[NL80211_ATTR_FRAME])
627 return NL_SKIP;
628
629 dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data,
630 wiphy_list) {
631 os_memset(&event, 0, sizeof(event));
632 event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);
633 event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);
634 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
635 }
636
637 return NL_SKIP;
638}
639
640
641static struct nl80211_wiphy_data *
642nl80211_get_wiphy_data_ap(struct i802_bss *bss)
643{
644 static DEFINE_DL_LIST(nl80211_wiphys);
645 struct nl80211_wiphy_data *w;
646 int wiphy_idx, found = 0;
647 struct i802_bss *tmp_bss;
648
649 if (bss->wiphy_data != NULL)
650 return bss->wiphy_data;
651
652 wiphy_idx = nl80211_get_wiphy_index(bss);
653
654 dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) {
655 if (w->wiphy_idx == wiphy_idx)
656 goto add;
657 }
658
659 /* alloc new one */
660 w = os_zalloc(sizeof(*w));
661 if (w == NULL)
662 return NULL;
663 w->wiphy_idx = wiphy_idx;
664 dl_list_init(&w->bsss);
665 dl_list_init(&w->drvs);
666
667 w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
668 if (!w->nl_cb) {
669 os_free(w);
670 return NULL;
671 }
672 nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
673 nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,
674 w);
675
676 w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
677 "wiphy beacons");
678 if (w->nl_beacons == NULL) {
679 os_free(w);
680 return NULL;
681 }
682
683 if (nl80211_register_beacons(bss->drv, w)) {
684 nl_destroy_handles(&w->nl_beacons);
685 os_free(w);
686 return NULL;
687 }
688
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700689 nl80211_register_eloop_read(&w->nl_beacons, nl80211_recv_beacons, w);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800690
691 dl_list_add(&nl80211_wiphys, &w->list);
692
693add:
694 /* drv entry for this bss already there? */
695 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
696 if (tmp_bss->drv == bss->drv) {
697 found = 1;
698 break;
699 }
700 }
701 /* if not add it */
702 if (!found)
703 dl_list_add(&w->drvs, &bss->drv->wiphy_list);
704
705 dl_list_add(&w->bsss, &bss->wiphy_list);
706 bss->wiphy_data = w;
707 return w;
708}
709
710
711static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
712{
713 struct nl80211_wiphy_data *w = bss->wiphy_data;
714 struct i802_bss *tmp_bss;
715 int found = 0;
716
717 if (w == NULL)
718 return;
719 bss->wiphy_data = NULL;
720 dl_list_del(&bss->wiphy_list);
721
722 /* still any for this drv present? */
723 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
724 if (tmp_bss->drv == bss->drv) {
725 found = 1;
726 break;
727 }
728 }
729 /* if not remove it */
730 if (!found)
731 dl_list_del(&bss->drv->wiphy_list);
732
733 if (!dl_list_empty(&w->bsss))
734 return;
735
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700736 nl80211_destroy_eloop_handle(&w->nl_beacons);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800737
738 nl_cb_put(w->nl_cb);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800739 dl_list_del(&w->list);
740 os_free(w);
741}
742
743
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
745{
746 struct i802_bss *bss = priv;
747 struct wpa_driver_nl80211_data *drv = bss->drv;
748 if (!drv->associated)
749 return -1;
750 os_memcpy(bssid, drv->bssid, ETH_ALEN);
751 return 0;
752}
753
754
755static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
756{
757 struct i802_bss *bss = priv;
758 struct wpa_driver_nl80211_data *drv = bss->drv;
759 if (!drv->associated)
760 return -1;
761 os_memcpy(ssid, drv->ssid, drv->ssid_len);
762 return drv->ssid_len;
763}
764
765
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800766static void wpa_driver_nl80211_event_newlink(
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800767 struct wpa_driver_nl80211_data *drv, const char *ifname)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700768{
769 union wpa_event_data event;
770
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800771 if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
772 if (if_nametoindex(drv->first_bss->ifname) == 0) {
773 wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
774 drv->first_bss->ifname);
775 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700776 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800777 if (!drv->if_removed)
778 return;
779 wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event",
780 drv->first_bss->ifname);
781 drv->if_removed = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700782 }
783
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800784 os_memset(&event, 0, sizeof(event));
785 os_strlcpy(event.interface_status.ifname, ifname,
786 sizeof(event.interface_status.ifname));
787 event.interface_status.ievent = EVENT_INTERFACE_ADDED;
788 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
789}
790
791
792static void wpa_driver_nl80211_event_dellink(
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800793 struct wpa_driver_nl80211_data *drv, const char *ifname)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800794{
795 union wpa_event_data event;
796
797 if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
798 if (drv->if_removed) {
799 wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
800 ifname);
801 return;
802 }
803 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1",
804 ifname);
805 drv->if_removed = 1;
806 } else {
807 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed",
808 ifname);
809 }
810
811 os_memset(&event, 0, sizeof(event));
812 os_strlcpy(event.interface_status.ifname, ifname,
813 sizeof(event.interface_status.ifname));
814 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700815 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
816}
817
818
819static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
820 u8 *buf, size_t len)
821{
822 int attrlen, rta_len;
823 struct rtattr *attr;
824
825 attrlen = len;
826 attr = (struct rtattr *) buf;
827
828 rta_len = RTA_ALIGN(sizeof(struct rtattr));
829 while (RTA_OK(attr, attrlen)) {
830 if (attr->rta_type == IFLA_IFNAME) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800831 if (os_strcmp(((char *) attr) + rta_len,
832 drv->first_bss->ifname) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833 return 1;
834 else
835 break;
836 }
837 attr = RTA_NEXT(attr, attrlen);
838 }
839
840 return 0;
841}
842
843
844static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
845 int ifindex, u8 *buf, size_t len)
846{
847 if (drv->ifindex == ifindex)
848 return 1;
849
850 if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700851 wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
852 "interface");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800853 wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854 return 1;
855 }
856
857 return 0;
858}
859
860
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800861static struct wpa_driver_nl80211_data *
862nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
863{
864 struct wpa_driver_nl80211_data *drv;
865 dl_list_for_each(drv, &global->interfaces,
866 struct wpa_driver_nl80211_data, list) {
867 if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
868 have_ifidx(drv, idx))
869 return drv;
870 }
871 return NULL;
872}
873
874
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700875static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
876 struct ifinfomsg *ifi,
877 u8 *buf, size_t len)
878{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800879 struct nl80211_global *global = ctx;
880 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800881 int attrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700882 struct rtattr *attr;
883 u32 brid = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800884 char namebuf[IFNAMSIZ];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800885 char ifname[IFNAMSIZ + 1];
886 char extra[100], *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700887
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800888 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
889 if (!drv) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800890 wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d",
891 ifi->ifi_index);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892 return;
893 }
894
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800895 extra[0] = '\0';
896 pos = extra;
897 end = pos + sizeof(extra);
898 ifname[0] = '\0';
899
900 attrlen = len;
901 attr = (struct rtattr *) buf;
902 while (RTA_OK(attr, attrlen)) {
903 switch (attr->rta_type) {
904 case IFLA_IFNAME:
905 if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
906 break;
907 os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
908 ifname[RTA_PAYLOAD(attr)] = '\0';
909 break;
910 case IFLA_MASTER:
911 brid = nla_get_u32((struct nlattr *) attr);
912 pos += os_snprintf(pos, end - pos, " master=%u", brid);
913 break;
914 case IFLA_WIRELESS:
915 pos += os_snprintf(pos, end - pos, " wext");
916 break;
917 case IFLA_OPERSTATE:
918 pos += os_snprintf(pos, end - pos, " operstate=%u",
919 nla_get_u32((struct nlattr *) attr));
920 break;
921 case IFLA_LINKMODE:
922 pos += os_snprintf(pos, end - pos, " linkmode=%u",
923 nla_get_u32((struct nlattr *) attr));
924 break;
925 }
926 attr = RTA_NEXT(attr, attrlen);
927 }
928 extra[sizeof(extra) - 1] = '\0';
929
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700930 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
931 ifi->ifi_index, ifname, extra, ifi->ifi_family,
932 ifi->ifi_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
934 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
935 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
936 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
937
938 if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800939 if (if_indextoname(ifi->ifi_index, namebuf) &&
940 linux_iface_up(drv->global->ioctl_sock,
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800941 drv->first_bss->ifname) > 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800942 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
943 "event since interface %s is up", namebuf);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800944 drv->ignore_if_down_event = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800945 return;
946 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700947 wpa_printf(MSG_DEBUG, "nl80211: Interface down");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800948 if (drv->ignore_if_down_event) {
949 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
950 "event generated by mode change");
951 drv->ignore_if_down_event = 0;
952 } else {
953 drv->if_disabled = 1;
954 wpa_supplicant_event(drv->ctx,
955 EVENT_INTERFACE_DISABLED, NULL);
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800956
957 /*
958 * Try to get drv again, since it may be removed as
959 * part of the EVENT_INTERFACE_DISABLED handling for
960 * dynamic interfaces
961 */
962 drv = nl80211_find_drv(global, ifi->ifi_index,
963 buf, len);
964 if (!drv)
965 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800966 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700967 }
968
969 if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800970 if (if_indextoname(ifi->ifi_index, namebuf) &&
971 linux_iface_up(drv->global->ioctl_sock,
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800972 drv->first_bss->ifname) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800973 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
974 "event since interface %s is down",
975 namebuf);
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800976 } else if (if_nametoindex(drv->first_bss->ifname) == 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700977 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
978 "event since interface %s does not exist",
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800979 drv->first_bss->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700980 } else if (drv->if_removed) {
981 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
982 "event since interface %s is marked "
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800983 "removed", drv->first_bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800984 } else {
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700985 struct i802_bss *bss;
986 u8 addr[ETH_ALEN];
987
988 /* Re-read MAC address as it may have changed */
989 bss = get_bss_ifindex(drv, ifi->ifi_index);
990 if (bss &&
991 linux_get_ifhwaddr(drv->global->ioctl_sock,
992 bss->ifname, addr) < 0) {
993 wpa_printf(MSG_DEBUG,
994 "nl80211: %s: failed to re-read MAC address",
995 bss->ifname);
996 } else if (bss &&
997 os_memcmp(addr, bss->addr, ETH_ALEN) != 0) {
998 wpa_printf(MSG_DEBUG,
999 "nl80211: Own MAC address on ifindex %d (%s) changed from "
1000 MACSTR " to " MACSTR,
1001 ifi->ifi_index, bss->ifname,
1002 MAC2STR(bss->addr),
1003 MAC2STR(addr));
1004 os_memcpy(bss->addr, addr, ETH_ALEN);
1005 }
1006
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001007 wpa_printf(MSG_DEBUG, "nl80211: Interface up");
1008 drv->if_disabled = 0;
1009 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
1010 NULL);
1011 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012 }
1013
1014 /*
1015 * Some drivers send the association event before the operup event--in
1016 * this case, lifting operstate in wpa_driver_nl80211_set_operstate()
1017 * fails. This will hit us when wpa_supplicant does not need to do
1018 * IEEE 802.1X authentication
1019 */
1020 if (drv->operstate == 1 &&
1021 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001022 !(ifi->ifi_flags & IFF_RUNNING)) {
1023 wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001024 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 -1, IF_OPER_UP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001026 }
1027
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001028 if (ifname[0])
1029 wpa_driver_nl80211_event_newlink(drv, ifname);
1030
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031 if (ifi->ifi_family == AF_BRIDGE && brid) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001032 struct i802_bss *bss;
1033
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 /* device has been added to bridge */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001035 if (!if_indextoname(brid, namebuf)) {
1036 wpa_printf(MSG_DEBUG,
1037 "nl80211: Could not find bridge ifname for ifindex %u",
1038 brid);
1039 return;
1040 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001041 wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
1042 brid, namebuf);
1043 add_ifidx(drv, brid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001044
1045 for (bss = drv->first_bss; bss; bss = bss->next) {
1046 if (os_strcmp(ifname, bss->ifname) == 0) {
1047 os_strlcpy(bss->brname, namebuf, IFNAMSIZ);
1048 break;
1049 }
1050 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001051 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001052}
1053
1054
1055static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
1056 struct ifinfomsg *ifi,
1057 u8 *buf, size_t len)
1058{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001059 struct nl80211_global *global = ctx;
1060 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001061 int attrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001062 struct rtattr *attr;
1063 u32 brid = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001064 char ifname[IFNAMSIZ + 1];
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001065 char extra[100], *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001067 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
1068 if (!drv) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001069 wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d",
1070 ifi->ifi_index);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001071 return;
1072 }
1073
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001074 extra[0] = '\0';
1075 pos = extra;
1076 end = pos + sizeof(extra);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001077 ifname[0] = '\0';
1078
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001079 attrlen = len;
1080 attr = (struct rtattr *) buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001081 while (RTA_OK(attr, attrlen)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001082 switch (attr->rta_type) {
1083 case IFLA_IFNAME:
1084 if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
1085 break;
1086 os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
1087 ifname[RTA_PAYLOAD(attr)] = '\0';
1088 break;
1089 case IFLA_MASTER:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090 brid = nla_get_u32((struct nlattr *) attr);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001091 pos += os_snprintf(pos, end - pos, " master=%u", brid);
1092 break;
1093 case IFLA_OPERSTATE:
1094 pos += os_snprintf(pos, end - pos, " operstate=%u",
1095 nla_get_u32((struct nlattr *) attr));
1096 break;
1097 case IFLA_LINKMODE:
1098 pos += os_snprintf(pos, end - pos, " linkmode=%u",
1099 nla_get_u32((struct nlattr *) attr));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001100 break;
1101 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001102 attr = RTA_NEXT(attr, attrlen);
1103 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001104 extra[sizeof(extra) - 1] = '\0';
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001106 wpa_printf(MSG_DEBUG, "RTM_DELLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
1107 ifi->ifi_index, ifname, extra, ifi->ifi_family,
1108 ifi->ifi_flags,
1109 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
1110 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
1111 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
1112 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
1113
1114 if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid))
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001115 wpa_driver_nl80211_event_dellink(drv, ifname);
1116
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117 if (ifi->ifi_family == AF_BRIDGE && brid) {
1118 /* device has been removed from bridge */
1119 char namebuf[IFNAMSIZ];
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001120
1121 if (!if_indextoname(brid, namebuf)) {
1122 wpa_printf(MSG_DEBUG,
1123 "nl80211: Could not find bridge ifname for ifindex %u",
1124 brid);
1125 } else {
1126 wpa_printf(MSG_DEBUG,
1127 "nl80211: Remove ifindex %u for bridge %s",
1128 brid, namebuf);
1129 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130 del_ifidx(drv, brid);
1131 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132}
1133
1134
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001135unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
Jouni Malinen87fd2792011-05-16 18:35:42 +03001136{
1137 struct nl_msg *msg;
1138 int ret;
1139 struct nl80211_bss_info_arg arg;
1140
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001141 msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Jouni Malinen87fd2792011-05-16 18:35:42 +03001142 os_memset(&arg, 0, sizeof(arg));
Jouni Malinen87fd2792011-05-16 18:35:42 +03001143 arg.drv = drv;
1144 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
Jouni Malinen87fd2792011-05-16 18:35:42 +03001145 if (ret == 0) {
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001146 unsigned int freq = drv->nlmode == NL80211_IFTYPE_ADHOC ?
1147 arg.ibss_freq : arg.assoc_freq;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001148 wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001149 "associated BSS from scan results: %u MHz", freq);
1150 if (freq)
1151 drv->assoc_freq = freq;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07001152 return drv->assoc_freq;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001153 }
1154 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
1155 "(%s)", ret, strerror(-ret));
Jouni Malinen87fd2792011-05-16 18:35:42 +03001156 return drv->assoc_freq;
1157}
1158
1159
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160static int get_link_signal(struct nl_msg *msg, void *arg)
1161{
1162 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1163 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1164 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
1165 static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
1166 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001167 [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001168 };
1169 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
1170 static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
1171 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
1172 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
1173 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
1174 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
1175 };
1176 struct wpa_signal_info *sig_change = arg;
1177
1178 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1179 genlmsg_attrlen(gnlh, 0), NULL);
1180 if (!tb[NL80211_ATTR_STA_INFO] ||
1181 nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
1182 tb[NL80211_ATTR_STA_INFO], policy))
1183 return NL_SKIP;
1184 if (!sinfo[NL80211_STA_INFO_SIGNAL])
1185 return NL_SKIP;
1186
1187 sig_change->current_signal =
1188 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
1189
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001190 if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
1191 sig_change->avg_signal =
1192 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
1193 else
1194 sig_change->avg_signal = 0;
1195
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001196 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
1197 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
1198 sinfo[NL80211_STA_INFO_TX_BITRATE],
1199 rate_policy)) {
1200 sig_change->current_txrate = 0;
1201 } else {
1202 if (rinfo[NL80211_RATE_INFO_BITRATE]) {
1203 sig_change->current_txrate =
1204 nla_get_u16(rinfo[
1205 NL80211_RATE_INFO_BITRATE]) * 100;
1206 }
1207 }
1208 }
1209
1210 return NL_SKIP;
1211}
1212
1213
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001214int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
1215 struct wpa_signal_info *sig)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001216{
1217 struct nl_msg *msg;
1218
1219 sig->current_signal = -9999;
1220 sig->current_txrate = 0;
1221
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001222 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_STATION)) ||
1223 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid)) {
1224 nlmsg_free(msg);
1225 return -ENOBUFS;
1226 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001227
1228 return send_and_recv_msgs(drv, msg, get_link_signal, sig);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001229}
1230
1231
1232static int get_link_noise(struct nl_msg *msg, void *arg)
1233{
1234 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1235 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1236 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
1237 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
1238 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
1239 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
1240 };
1241 struct wpa_signal_info *sig_change = arg;
1242
1243 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1244 genlmsg_attrlen(gnlh, 0), NULL);
1245
1246 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
1247 wpa_printf(MSG_DEBUG, "nl80211: survey data missing!");
1248 return NL_SKIP;
1249 }
1250
1251 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
1252 tb[NL80211_ATTR_SURVEY_INFO],
1253 survey_policy)) {
1254 wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested "
1255 "attributes!");
1256 return NL_SKIP;
1257 }
1258
1259 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
1260 return NL_SKIP;
1261
1262 if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
1263 sig_change->frequency)
1264 return NL_SKIP;
1265
1266 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
1267 return NL_SKIP;
1268
1269 sig_change->current_noise =
1270 (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
1271
1272 return NL_SKIP;
1273}
1274
1275
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001276int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
1277 struct wpa_signal_info *sig_change)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001278{
1279 struct nl_msg *msg;
1280
1281 sig_change->current_noise = 9999;
1282 sig_change->frequency = drv->assoc_freq;
1283
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001284 msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001285 return send_and_recv_msgs(drv, msg, get_link_noise, sig_change);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001286}
1287
1288
1289static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
1290 void *handle)
1291{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001292 struct nl_cb *cb = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001293 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001294
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001295 wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001297 res = nl_recvmsgs(handle, cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -07001298 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001299 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
1300 __func__, res);
1301 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001302}
1303
1304
1305/**
1306 * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
1307 * @priv: driver_nl80211 private data
1308 * @alpha2_arg: country to which to switch to
1309 * Returns: 0 on success, -1 on failure
1310 *
1311 * This asks nl80211 to set the regulatory domain for given
1312 * country ISO / IEC alpha2.
1313 */
1314static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
1315{
1316 struct i802_bss *bss = priv;
1317 struct wpa_driver_nl80211_data *drv = bss->drv;
1318 char alpha2[3];
1319 struct nl_msg *msg;
1320
1321 msg = nlmsg_alloc();
1322 if (!msg)
1323 return -ENOMEM;
1324
1325 alpha2[0] = alpha2_arg[0];
1326 alpha2[1] = alpha2_arg[1];
1327 alpha2[2] = '\0';
1328
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001329 if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG) ||
1330 nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, alpha2)) {
1331 nlmsg_free(msg);
1332 return -EINVAL;
1333 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001334 if (send_and_recv_msgs(drv, msg, NULL, NULL))
1335 return -EINVAL;
1336 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001337}
1338
1339
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001340static int nl80211_get_country(struct nl_msg *msg, void *arg)
1341{
1342 char *alpha2 = arg;
1343 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
1344 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1345
1346 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1347 genlmsg_attrlen(gnlh, 0), NULL);
1348 if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) {
1349 wpa_printf(MSG_DEBUG, "nl80211: No country information available");
1350 return NL_SKIP;
1351 }
1352 os_strlcpy(alpha2, nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]), 3);
1353 return NL_SKIP;
1354}
1355
1356
1357static int wpa_driver_nl80211_get_country(void *priv, char *alpha2)
1358{
1359 struct i802_bss *bss = priv;
1360 struct wpa_driver_nl80211_data *drv = bss->drv;
1361 struct nl_msg *msg;
1362 int ret;
1363
1364 msg = nlmsg_alloc();
1365 if (!msg)
1366 return -ENOMEM;
1367
1368 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
1369 alpha2[0] = '\0';
1370 ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2);
1371 if (!alpha2[0])
1372 ret = -1;
1373
1374 return ret;
1375}
1376
1377
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001378static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379{
1380 int ret;
1381
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001382 global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
1383 if (global->nl_cb == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
1385 "callbacks");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001386 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001387 }
1388
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001389 global->nl = nl_create_handle(global->nl_cb, "nl");
1390 if (global->nl == NULL)
1391 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001393 global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
1394 if (global->nl80211_id < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001395 wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
1396 "found");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001397 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001398 }
1399
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001400 global->nl_event = nl_create_handle(global->nl_cb, "event");
1401 if (global->nl_event == NULL)
1402 goto err;
1403
1404 ret = nl_get_multicast_id(global, "nl80211", "scan");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001406 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001407 if (ret < 0) {
1408 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
1409 "membership for scan events: %d (%s)",
1410 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001411 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001412 }
1413
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001414 ret = nl_get_multicast_id(global, "nl80211", "mlme");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001415 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001416 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417 if (ret < 0) {
1418 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
1419 "membership for mlme events: %d (%s)",
1420 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001421 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422 }
1423
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001424 ret = nl_get_multicast_id(global, "nl80211", "regulatory");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001425 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001426 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001427 if (ret < 0) {
1428 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
1429 "membership for regulatory events: %d (%s)",
1430 ret, strerror(-ret));
1431 /* Continue without regulatory events */
1432 }
1433
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001434 ret = nl_get_multicast_id(global, "nl80211", "vendor");
1435 if (ret >= 0)
1436 ret = nl_socket_add_membership(global->nl_event, ret);
1437 if (ret < 0) {
1438 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
1439 "membership for vendor events: %d (%s)",
1440 ret, strerror(-ret));
1441 /* Continue without vendor events */
1442 }
1443
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001444 nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
1445 no_seq_check, NULL);
1446 nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
1447 process_global_event, global);
1448
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001449 nl80211_register_eloop_read(&global->nl_event,
1450 wpa_driver_nl80211_event_receive,
1451 global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452
1453 return 0;
1454
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001455err:
1456 nl_destroy_handles(&global->nl_event);
1457 nl_destroy_handles(&global->nl);
1458 nl_cb_put(global->nl_cb);
1459 global->nl_cb = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001460 return -1;
1461}
1462
1463
1464static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
1465{
1466 wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
1467 /*
1468 * This may be for any interface; use ifdown event to disable
1469 * interface.
1470 */
1471}
1472
1473
1474static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
1475{
1476 struct wpa_driver_nl80211_data *drv = ctx;
1477 wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001478 if (i802_set_iface_flags(drv->first_bss, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001479 wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
1480 "after rfkill unblock");
1481 return;
1482 }
1483 /* rtnetlink ifup handler will report interface as enabled */
1484}
1485
1486
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001487static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
1488 void *eloop_ctx,
1489 void *handle)
1490{
1491 struct wpa_driver_nl80211_data *drv = eloop_ctx;
1492 u8 data[2048];
1493 struct msghdr msg;
1494 struct iovec entry;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001495 u8 control[512];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001496 struct cmsghdr *cmsg;
1497 int res, found_ee = 0, found_wifi = 0, acked = 0;
1498 union wpa_event_data event;
1499
1500 memset(&msg, 0, sizeof(msg));
1501 msg.msg_iov = &entry;
1502 msg.msg_iovlen = 1;
1503 entry.iov_base = data;
1504 entry.iov_len = sizeof(data);
1505 msg.msg_control = &control;
1506 msg.msg_controllen = sizeof(control);
1507
1508 res = recvmsg(sock, &msg, MSG_ERRQUEUE);
1509 /* if error or not fitting 802.3 header, return */
1510 if (res < 14)
1511 return;
1512
1513 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
1514 {
1515 if (cmsg->cmsg_level == SOL_SOCKET &&
1516 cmsg->cmsg_type == SCM_WIFI_STATUS) {
1517 int *ack;
1518
1519 found_wifi = 1;
1520 ack = (void *)CMSG_DATA(cmsg);
1521 acked = *ack;
1522 }
1523
1524 if (cmsg->cmsg_level == SOL_PACKET &&
1525 cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
1526 struct sock_extended_err *err =
1527 (struct sock_extended_err *)CMSG_DATA(cmsg);
1528
1529 if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
1530 found_ee = 1;
1531 }
1532 }
1533
1534 if (!found_ee || !found_wifi)
1535 return;
1536
1537 memset(&event, 0, sizeof(event));
1538 event.eapol_tx_status.dst = data;
1539 event.eapol_tx_status.data = data + 14;
1540 event.eapol_tx_status.data_len = res - 14;
1541 event.eapol_tx_status.ack = acked;
1542 wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
1543}
1544
1545
1546static int nl80211_init_bss(struct i802_bss *bss)
1547{
1548 bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
1549 if (!bss->nl_cb)
1550 return -1;
1551
1552 nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
1553 no_seq_check, NULL);
1554 nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
1555 process_bss_event, bss);
1556
1557 return 0;
1558}
1559
1560
1561static void nl80211_destroy_bss(struct i802_bss *bss)
1562{
1563 nl_cb_put(bss->nl_cb);
1564 bss->nl_cb = NULL;
1565}
1566
1567
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001568static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
1569 void *global_priv, int hostapd,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001570 const u8 *set_addr,
1571 const char *driver_params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001572{
1573 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001574 struct rfkill_config *rcfg;
1575 struct i802_bss *bss;
1576
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001577 if (global_priv == NULL)
1578 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001579 drv = os_zalloc(sizeof(*drv));
1580 if (drv == NULL)
1581 return NULL;
1582 drv->global = global_priv;
1583 drv->ctx = ctx;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001584 drv->hostapd = !!hostapd;
1585 drv->eapol_sock = -1;
1586 drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
1587 drv->if_indices = drv->default_if_indices;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001588
1589 drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
1590 if (!drv->first_bss) {
1591 os_free(drv);
1592 return NULL;
1593 }
1594 bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001595 bss->drv = drv;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001596 bss->ctx = ctx;
1597
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001598 os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
1599 drv->monitor_ifidx = -1;
1600 drv->monitor_sock = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001601 drv->eapol_tx_sock = -1;
1602 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001603
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001604 if (nl80211_init_bss(bss))
1605 goto failed;
1606
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607 rcfg = os_zalloc(sizeof(*rcfg));
1608 if (rcfg == NULL)
1609 goto failed;
1610 rcfg->ctx = drv;
1611 os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
1612 rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
1613 rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
1614 drv->rfkill = rfkill_init(rcfg);
1615 if (drv->rfkill == NULL) {
1616 wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
1617 os_free(rcfg);
1618 }
1619
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001620 if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0)
1621 drv->start_iface_up = 1;
1622
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001623 if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001624 goto failed;
1625
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001626 drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
1627 if (drv->eapol_tx_sock < 0)
1628 goto failed;
1629
1630 if (drv->data_tx_status) {
1631 int enabled = 1;
1632
1633 if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
1634 &enabled, sizeof(enabled)) < 0) {
1635 wpa_printf(MSG_DEBUG,
1636 "nl80211: wifi status sockopt failed\n");
1637 drv->data_tx_status = 0;
1638 if (!drv->use_monitor)
1639 drv->capa.flags &=
1640 ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
1641 } else {
1642 eloop_register_read_sock(drv->eapol_tx_sock,
1643 wpa_driver_nl80211_handle_eapol_tx_status,
1644 drv, NULL);
1645 }
1646 }
1647
1648 if (drv->global) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001649 dl_list_add(&drv->global->interfaces, &drv->list);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001650 drv->in_interface_list = 1;
1651 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001652
1653 return bss;
1654
1655failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001656 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001657 return NULL;
1658}
1659
1660
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001661/**
1662 * wpa_driver_nl80211_init - Initialize nl80211 driver interface
1663 * @ctx: context to be used when calling wpa_supplicant functions,
1664 * e.g., wpa_supplicant_event()
1665 * @ifname: interface name, e.g., wlan0
1666 * @global_priv: private driver global data from global_init()
1667 * Returns: Pointer to private data, %NULL on failure
1668 */
1669static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
1670 void *global_priv)
1671{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001672 return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL,
1673 NULL);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001674}
1675
1676
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001677static int nl80211_register_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001678 struct nl_handle *nl_handle,
1679 u16 type, const u8 *match, size_t match_len)
1680{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001681 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001682 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001683 int ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001684 char buf[30];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001685
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001686 buf[0] = '\0';
1687 wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07001688 wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s",
1689 type, fc2str(type), nl_handle, buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001691 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REGISTER_ACTION)) ||
1692 nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, type) ||
1693 nla_put(msg, NL80211_ATTR_FRAME_MATCH, match_len, match)) {
1694 nlmsg_free(msg);
1695 return -1;
1696 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001697
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001698 ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001699 if (ret) {
1700 wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
1701 "failed (type=%u): ret=%d (%s)",
1702 type, ret, strerror(-ret));
1703 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
1704 match, match_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001705 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001706 return ret;
1707}
1708
1709
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001710static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
1711{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001712 if (bss->nl_mgmt) {
1713 wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting "
1714 "already on! (nl_mgmt=%p)", bss->nl_mgmt);
1715 return -1;
1716 }
1717
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001718 bss->nl_mgmt = nl_create_handle(bss->nl_cb, "mgmt");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001719 if (bss->nl_mgmt == NULL)
1720 return -1;
1721
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001722 return 0;
1723}
1724
1725
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001726static void nl80211_mgmt_handle_register_eloop(struct i802_bss *bss)
1727{
1728 nl80211_register_eloop_read(&bss->nl_mgmt,
1729 wpa_driver_nl80211_event_receive,
1730 bss->nl_cb);
1731}
1732
1733
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001734static int nl80211_register_action_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001735 const u8 *match, size_t match_len)
1736{
1737 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001738 return nl80211_register_frame(bss, bss->nl_mgmt,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001739 type, match, match_len);
1740}
1741
1742
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001743static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001745 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001746 int ret = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001747
1748 if (nl80211_alloc_mgmt_handle(bss))
1749 return -1;
1750 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
1751 "handle %p", bss->nl_mgmt);
1752
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001753 if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
1754 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
1755
1756 /* register for any AUTH message */
1757 nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0);
1758 }
1759
Dmitry Shmidt051af732013-10-22 13:52:46 -07001760#ifdef CONFIG_INTERWORKING
1761 /* QoS Map Configure */
1762 if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001763 ret = -1;
Dmitry Shmidt051af732013-10-22 13:52:46 -07001764#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001765#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766 /* GAS Initial Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001767 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001768 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001769 /* GAS Initial Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001770 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001771 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772 /* GAS Comeback Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001773 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001774 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001775 /* GAS Comeback Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001776 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001777 ret = -1;
Dmitry Shmidt18463232014-01-24 12:29:41 -08001778 /* Protected GAS Initial Request */
1779 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0)
1780 ret = -1;
1781 /* Protected GAS Initial Response */
1782 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0)
1783 ret = -1;
1784 /* Protected GAS Comeback Request */
1785 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0)
1786 ret = -1;
1787 /* Protected GAS Comeback Response */
1788 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0)
1789 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001790#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
1791#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001792 /* P2P Public Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001793 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001794 (u8 *) "\x04\x09\x50\x6f\x9a\x09",
1795 6) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001796 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 /* P2P Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001798 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001799 (u8 *) "\x7f\x50\x6f\x9a\x09",
1800 5) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001801 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001802#endif /* CONFIG_P2P */
1803#ifdef CONFIG_IEEE80211W
1804 /* SA Query Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001805 if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001806 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001807#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001808#ifdef CONFIG_TDLS
1809 if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
1810 /* TDLS Discovery Response */
1811 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
1812 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001813 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001814 }
1815#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001816
1817 /* FT Action frames */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001818 if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001819 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001820 else
1821 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
1822 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
1823
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001824 /* WNM - BSS Transition Management Request */
1825 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001826 ret = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001827 /* WNM-Sleep Mode Response */
1828 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001829 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001830
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001831#ifdef CONFIG_HS20
1832 /* WNM-Notification */
1833 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001834 ret = -1;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001835#endif /* CONFIG_HS20 */
1836
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001837 /* WMM-AC ADDTS Response */
1838 if (nl80211_register_action_frame(bss, (u8 *) "\x11\x01", 2) < 0)
1839 ret = -1;
1840
1841 /* WMM-AC DELTS */
1842 if (nl80211_register_action_frame(bss, (u8 *) "\x11\x02", 2) < 0)
1843 ret = -1;
1844
1845 /* Radio Measurement - Neighbor Report Response */
1846 if (nl80211_register_action_frame(bss, (u8 *) "\x05\x05", 2) < 0)
1847 ret = -1;
1848
1849 /* Radio Measurement - Link Measurement Request */
1850 if ((drv->capa.rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION) &&
1851 (nl80211_register_action_frame(bss, (u8 *) "\x05\x02", 2) < 0))
1852 ret = -1;
1853
1854 nl80211_mgmt_handle_register_eloop(bss);
1855
1856 return ret;
1857}
1858
1859
1860static int nl80211_mgmt_subscribe_mesh(struct i802_bss *bss)
1861{
1862 int ret = 0;
1863
1864 if (nl80211_alloc_mgmt_handle(bss))
1865 return -1;
1866
1867 wpa_printf(MSG_DEBUG,
1868 "nl80211: Subscribe to mgmt frames with mesh handle %p",
1869 bss->nl_mgmt);
1870
1871 /* Auth frames for mesh SAE */
1872 if (nl80211_register_frame(bss, bss->nl_mgmt,
1873 (WLAN_FC_TYPE_MGMT << 2) |
1874 (WLAN_FC_STYPE_AUTH << 4),
1875 NULL, 0) < 0)
1876 ret = -1;
1877
1878 /* Mesh peering open */
1879 if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x01", 2) < 0)
1880 ret = -1;
1881 /* Mesh peering confirm */
1882 if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x02", 2) < 0)
1883 ret = -1;
1884 /* Mesh peering close */
1885 if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x03", 2) < 0)
1886 ret = -1;
1887
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001888 nl80211_mgmt_handle_register_eloop(bss);
1889
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001890 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891}
1892
1893
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001894static int nl80211_register_spurious_class3(struct i802_bss *bss)
1895{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001896 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001897 int ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001898
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001899 msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UNEXPECTED_FRAME);
1900 ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001901 if (ret) {
1902 wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
1903 "failed: ret=%d (%s)",
1904 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001905 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001906 return ret;
1907}
1908
1909
1910static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
1911{
1912 static const int stypes[] = {
1913 WLAN_FC_STYPE_AUTH,
1914 WLAN_FC_STYPE_ASSOC_REQ,
1915 WLAN_FC_STYPE_REASSOC_REQ,
1916 WLAN_FC_STYPE_DISASSOC,
1917 WLAN_FC_STYPE_DEAUTH,
1918 WLAN_FC_STYPE_ACTION,
1919 WLAN_FC_STYPE_PROBE_REQ,
1920/* Beacon doesn't work as mac80211 doesn't currently allow
1921 * it, but it wouldn't really be the right thing anyway as
1922 * it isn't per interface ... maybe just dump the scan
1923 * results periodically for OLBC?
1924 */
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07001925 /* WLAN_FC_STYPE_BEACON, */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001926 };
1927 unsigned int i;
1928
1929 if (nl80211_alloc_mgmt_handle(bss))
1930 return -1;
1931 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
1932 "handle %p", bss->nl_mgmt);
1933
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001934 for (i = 0; i < ARRAY_SIZE(stypes); i++) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001935 if (nl80211_register_frame(bss, bss->nl_mgmt,
1936 (WLAN_FC_TYPE_MGMT << 2) |
1937 (stypes[i] << 4),
1938 NULL, 0) < 0) {
1939 goto out_err;
1940 }
1941 }
1942
1943 if (nl80211_register_spurious_class3(bss))
1944 goto out_err;
1945
1946 if (nl80211_get_wiphy_data_ap(bss) == NULL)
1947 goto out_err;
1948
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001949 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001950 return 0;
1951
1952out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001953 nl_destroy_handles(&bss->nl_mgmt);
1954 return -1;
1955}
1956
1957
1958static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)
1959{
1960 if (nl80211_alloc_mgmt_handle(bss))
1961 return -1;
1962 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
1963 "handle %p (device SME)", bss->nl_mgmt);
1964
1965 if (nl80211_register_frame(bss, bss->nl_mgmt,
1966 (WLAN_FC_TYPE_MGMT << 2) |
1967 (WLAN_FC_STYPE_ACTION << 4),
1968 NULL, 0) < 0)
1969 goto out_err;
1970
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001971 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001972 return 0;
1973
1974out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001975 nl_destroy_handles(&bss->nl_mgmt);
1976 return -1;
1977}
1978
1979
1980static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
1981{
1982 if (bss->nl_mgmt == NULL)
1983 return;
1984 wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
1985 "(%s)", bss->nl_mgmt, reason);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001986 nl80211_destroy_eloop_handle(&bss->nl_mgmt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001987
1988 nl80211_put_wiphy_data_ap(bss);
1989}
1990
1991
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001992static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
1993{
1994 wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
1995}
1996
1997
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001998static void nl80211_del_p2pdev(struct i802_bss *bss)
1999{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002000 struct nl_msg *msg;
2001 int ret;
2002
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002003 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_INTERFACE);
2004 ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002005
2006 wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
2007 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002008 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002009}
2010
2011
2012static int nl80211_set_p2pdev(struct i802_bss *bss, int start)
2013{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002014 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002015 int ret;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002016
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002017 msg = nl80211_cmd_msg(bss, 0, start ? NL80211_CMD_START_P2P_DEVICE :
2018 NL80211_CMD_STOP_P2P_DEVICE);
2019 ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002020
2021 wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
2022 start ? "Start" : "Stop",
2023 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002024 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002025 return ret;
2026}
2027
2028
2029static int i802_set_iface_flags(struct i802_bss *bss, int up)
2030{
2031 enum nl80211_iftype nlmode;
2032
2033 nlmode = nl80211_get_ifmode(bss);
2034 if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
2035 return linux_set_iface_flags(bss->drv->global->ioctl_sock,
2036 bss->ifname, up);
2037 }
2038
2039 /* P2P Device has start/stop which is equivalent */
2040 return nl80211_set_p2pdev(bss, up);
2041}
2042
2043
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002044static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002045wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002046 const u8 *set_addr, int first,
2047 const char *driver_params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002048{
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002049 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 int send_rfkill_event = 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002051 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002052
2053 drv->ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002054 bss->ifindex = drv->ifindex;
2055 bss->wdev_id = drv->global->if_add_wdevid;
2056 bss->wdev_id_set = drv->global->if_add_wdevid_set;
2057
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002058 bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;
2059 bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002060 drv->global->if_add_wdevid_set = 0;
2061
Dmitry Shmidt03658832014-08-13 11:03:49 -07002062 if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
2063 bss->static_ap = 1;
2064
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002065 if (wpa_driver_nl80211_capa(drv))
2066 return -1;
2067
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002068 if (driver_params && nl80211_set_param(bss, driver_params) < 0)
2069 return -1;
2070
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002071 wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
2072 bss->ifname, drv->phyname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002073
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002074 if (set_addr &&
2075 (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) ||
2076 linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
2077 set_addr)))
2078 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002079
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002080 if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
2081 drv->start_mode_ap = 1;
2082
Dmitry Shmidt03658832014-08-13 11:03:49 -07002083 if (drv->hostapd || bss->static_ap)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002084 nlmode = NL80211_IFTYPE_AP;
2085 else if (bss->if_dynamic)
2086 nlmode = nl80211_get_ifmode(bss);
2087 else
2088 nlmode = NL80211_IFTYPE_STATION;
2089
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002090 if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002091 wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002092 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002094
Dmitry Shmidt98660862014-03-11 17:26:21 -07002095 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002096 nl80211_get_macaddr(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097
Dmitry Shmidt98660862014-03-11 17:26:21 -07002098 if (!rfkill_is_blocked(drv->rfkill)) {
2099 int ret = i802_set_iface_flags(bss, 1);
2100 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002101 wpa_printf(MSG_ERROR, "nl80211: Could not set "
2102 "interface '%s' UP", bss->ifname);
Dmitry Shmidt98660862014-03-11 17:26:21 -07002103 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002104 }
Dmitry Shmidt98660862014-03-11 17:26:21 -07002105 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
2106 return ret;
2107 } else {
2108 wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
2109 "interface '%s' due to rfkill", bss->ifname);
2110 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
2111 return 0;
2112 drv->if_disabled = 1;
2113 send_rfkill_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002114 }
2115
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002116 if (!drv->hostapd)
2117 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
2118 1, IF_OPER_DORMANT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002119
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002120 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
2121 bss->addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002122 return -1;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002123 os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002124
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002125 if (send_rfkill_event) {
2126 eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
2127 drv, drv->ctx);
2128 }
2129
2130 return 0;
2131}
2132
2133
2134static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
2135{
2136 struct nl_msg *msg;
2137
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002138 wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
2139 drv->ifindex);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002140 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002141 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142}
2143
2144
2145/**
2146 * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002147 * @bss: Pointer to private nl80211 data from wpa_driver_nl80211_init()
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148 *
2149 * Shut down driver interface and processing of driver events. Free
2150 * private data buffer if one was allocated in wpa_driver_nl80211_init().
2151 */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002152static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002154 struct wpa_driver_nl80211_data *drv = bss->drv;
2155
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002156 wpa_printf(MSG_INFO, "nl80211: deinit ifname=%s disabled_11b_rates=%d",
2157 bss->ifname, drv->disabled_11b_rates);
2158
Dmitry Shmidt04949592012-07-19 12:16:46 -07002159 bss->in_deinit = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002160 if (drv->data_tx_status)
2161 eloop_unregister_read_sock(drv->eapol_tx_sock);
2162 if (drv->eapol_tx_sock >= 0)
2163 close(drv->eapol_tx_sock);
2164
2165 if (bss->nl_preq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002166 wpa_driver_nl80211_probe_req_report(bss, 0);
2167 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002168 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
2169 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002170 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
2171 "interface %s from bridge %s: %s",
2172 bss->ifname, bss->brname, strerror(errno));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002173 if (drv->rtnl_sk)
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002174 nl80211_handle_destroy(drv->rtnl_sk);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002175 }
2176 if (bss->added_bridge) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002177 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->brname,
2178 0) < 0)
2179 wpa_printf(MSG_INFO,
2180 "nl80211: Could not set bridge %s down",
2181 bss->brname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002182 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002183 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
2184 "bridge %s: %s",
2185 bss->brname, strerror(errno));
2186 }
2187
2188 nl80211_remove_monitor_interface(drv);
2189
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002190 if (is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002191 wpa_driver_nl80211_del_beacon(drv);
2192
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002193 if (drv->eapol_sock >= 0) {
2194 eloop_unregister_read_sock(drv->eapol_sock);
2195 close(drv->eapol_sock);
2196 }
2197
2198 if (drv->if_indices != drv->default_if_indices)
2199 os_free(drv->if_indices);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002200
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002201 if (drv->disabled_11b_rates)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002202 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
2203
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002204 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
2205 IF_OPER_UP);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07002206 eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002207 rfkill_deinit(drv->rfkill);
2208
2209 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
2210
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002211 if (!drv->start_iface_up)
2212 (void) i802_set_iface_flags(bss, 0);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002213
2214 if (drv->addr_changed) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002215 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
2216 0) < 0) {
2217 wpa_printf(MSG_DEBUG,
2218 "nl80211: Could not set interface down to restore permanent MAC address");
2219 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002220 if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
2221 drv->perm_addr) < 0) {
2222 wpa_printf(MSG_DEBUG,
2223 "nl80211: Could not restore permanent MAC address");
2224 }
2225 }
2226
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002227 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002228 if (!drv->hostapd || !drv->start_mode_ap)
2229 wpa_driver_nl80211_set_mode(bss,
2230 NL80211_IFTYPE_STATION);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002231 nl80211_mgmt_unsubscribe(bss, "deinit");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002232 } else {
2233 nl80211_mgmt_unsubscribe(bss, "deinit");
2234 nl80211_del_p2pdev(bss);
2235 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002236
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002237 nl80211_destroy_bss(drv->first_bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002238
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002239 os_free(drv->filter_ssids);
2240
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002241 os_free(drv->auth_ie);
2242
2243 if (drv->in_interface_list)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002244 dl_list_del(&drv->list);
2245
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002246 os_free(drv->extended_capa);
2247 os_free(drv->extended_capa_mask);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002248 os_free(drv->first_bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249 os_free(drv);
2250}
2251
2252
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002253static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len)
2254{
2255 switch (alg) {
2256 case WPA_ALG_WEP:
2257 if (key_len == 5)
2258 return WLAN_CIPHER_SUITE_WEP40;
2259 return WLAN_CIPHER_SUITE_WEP104;
2260 case WPA_ALG_TKIP:
2261 return WLAN_CIPHER_SUITE_TKIP;
2262 case WPA_ALG_CCMP:
2263 return WLAN_CIPHER_SUITE_CCMP;
2264 case WPA_ALG_GCMP:
2265 return WLAN_CIPHER_SUITE_GCMP;
2266 case WPA_ALG_CCMP_256:
2267 return WLAN_CIPHER_SUITE_CCMP_256;
2268 case WPA_ALG_GCMP_256:
2269 return WLAN_CIPHER_SUITE_GCMP_256;
2270 case WPA_ALG_IGTK:
2271 return WLAN_CIPHER_SUITE_AES_CMAC;
2272 case WPA_ALG_BIP_GMAC_128:
2273 return WLAN_CIPHER_SUITE_BIP_GMAC_128;
2274 case WPA_ALG_BIP_GMAC_256:
2275 return WLAN_CIPHER_SUITE_BIP_GMAC_256;
2276 case WPA_ALG_BIP_CMAC_256:
2277 return WLAN_CIPHER_SUITE_BIP_CMAC_256;
2278 case WPA_ALG_SMS4:
2279 return WLAN_CIPHER_SUITE_SMS4;
2280 case WPA_ALG_KRK:
2281 return WLAN_CIPHER_SUITE_KRK;
2282 case WPA_ALG_NONE:
2283 case WPA_ALG_PMK:
2284 wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d",
2285 alg);
2286 return 0;
2287 }
2288
2289 wpa_printf(MSG_ERROR, "nl80211: Unsupported encryption algorithm %d",
2290 alg);
2291 return 0;
2292}
2293
2294
2295static u32 wpa_cipher_to_cipher_suite(unsigned int cipher)
2296{
2297 switch (cipher) {
2298 case WPA_CIPHER_CCMP_256:
2299 return WLAN_CIPHER_SUITE_CCMP_256;
2300 case WPA_CIPHER_GCMP_256:
2301 return WLAN_CIPHER_SUITE_GCMP_256;
2302 case WPA_CIPHER_CCMP:
2303 return WLAN_CIPHER_SUITE_CCMP;
2304 case WPA_CIPHER_GCMP:
2305 return WLAN_CIPHER_SUITE_GCMP;
2306 case WPA_CIPHER_TKIP:
2307 return WLAN_CIPHER_SUITE_TKIP;
2308 case WPA_CIPHER_WEP104:
2309 return WLAN_CIPHER_SUITE_WEP104;
2310 case WPA_CIPHER_WEP40:
2311 return WLAN_CIPHER_SUITE_WEP40;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002312 case WPA_CIPHER_GTK_NOT_USED:
2313 return WLAN_CIPHER_SUITE_NO_GROUP_ADDR;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002314 }
2315
2316 return 0;
2317}
2318
2319
2320static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[],
2321 int max_suites)
2322{
2323 int num_suites = 0;
2324
2325 if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP_256)
2326 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP_256;
2327 if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP_256)
2328 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP_256;
2329 if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP)
2330 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
2331 if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP)
2332 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;
2333 if (num_suites < max_suites && ciphers & WPA_CIPHER_TKIP)
2334 suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
2335 if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP104)
2336 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
2337 if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP40)
2338 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
2339
2340 return num_suites;
2341}
2342
2343
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002344static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
2345 const u8 *key, size_t key_len)
2346{
2347 struct nl_msg *msg;
2348 int ret;
2349
2350 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD))
2351 return 0;
2352
2353 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
2354 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
2355 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
2356 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) ||
2357 nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) {
2358 nl80211_nlmsg_clear(msg);
2359 nlmsg_free(msg);
2360 return -1;
2361 }
2362 ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1);
2363 if (ret) {
2364 wpa_printf(MSG_DEBUG,
2365 "nl80211: Key management set key failed: ret=%d (%s)",
2366 ret, strerror(-ret));
2367 }
2368
2369 return ret;
2370}
2371
2372
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002373static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374 enum wpa_alg alg, const u8 *addr,
2375 int key_idx, int set_tx,
2376 const u8 *seq, size_t seq_len,
2377 const u8 *key, size_t key_len)
2378{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002379 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002380 int ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002381 struct nl_msg *msg;
2382 int ret;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07002383 int tdls = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002385 /* Ignore for P2P Device */
2386 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
2387 return 0;
2388
2389 ifindex = if_nametoindex(ifname);
2390 wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002391 "set_tx=%d seq_len=%lu key_len=%lu",
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002392 __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002393 (unsigned long) seq_len, (unsigned long) key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002394#ifdef CONFIG_TDLS
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07002395 if (key_idx == -1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002396 key_idx = 0;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07002397 tdls = 1;
2398 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002399#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002401 if (alg == WPA_ALG_PMK &&
2402 (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
2403 wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key",
2404 __func__);
2405 ret = issue_key_mgmt_set_key(drv, key, key_len);
2406 return ret;
2407 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002408
2409 if (alg == WPA_ALG_NONE) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002410 msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY);
2411 if (!msg)
2412 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002413 } else {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002414 msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY);
2415 if (!msg ||
2416 nla_put(msg, NL80211_ATTR_KEY_DATA, key_len, key) ||
2417 nla_put_u32(msg, NL80211_ATTR_KEY_CIPHER,
2418 wpa_alg_to_cipher_suite(alg, key_len)))
2419 goto fail;
Dmitry Shmidt98660862014-03-11 17:26:21 -07002420 wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002421 }
2422
Dmitry Shmidt98660862014-03-11 17:26:21 -07002423 if (seq && seq_len) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002424 if (nla_put(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq))
2425 goto fail;
Dmitry Shmidt98660862014-03-11 17:26:21 -07002426 wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
2427 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428
2429 if (addr && !is_broadcast_ether_addr(addr)) {
2430 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002431 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
2432 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433
2434 if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
2435 wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002436 if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE,
2437 NL80211_KEYTYPE_GROUP))
2438 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439 }
2440 } else if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002441 struct nlattr *types;
2442
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002443 wpa_printf(MSG_DEBUG, " broadcast key");
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002444
2445 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002446 if (!types ||
2447 nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
2448 goto fail;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002449 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002450 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002451 if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
2452 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002453
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002454 ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002455 if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
2456 ret = 0;
2457 if (ret)
2458 wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)",
2459 ret, strerror(-ret));
2460
2461 /*
2462 * If we failed or don't need to set the default TX key (below),
2463 * we're done here.
2464 */
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07002465 if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466 return ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002467 if (is_ap_interface(drv->nlmode) && addr &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 !is_broadcast_ether_addr(addr))
2469 return ret;
2470
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002471 msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY);
2472 if (!msg ||
2473 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) ||
2474 nla_put_flag(msg, alg == WPA_ALG_IGTK ?
2475 NL80211_ATTR_KEY_DEFAULT_MGMT :
2476 NL80211_ATTR_KEY_DEFAULT))
2477 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002479 struct nlattr *types;
2480
2481 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002482 if (!types ||
2483 nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
2484 goto fail;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002485 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 } else if (addr) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002487 struct nlattr *types;
2488
2489 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002490 if (!types ||
2491 nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST))
2492 goto fail;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002493 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002494 }
2495
2496 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
2497 if (ret == -ENOENT)
2498 ret = 0;
2499 if (ret)
2500 wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
2501 "err=%d %s)", ret, strerror(-ret));
2502 return ret;
2503
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002504fail:
2505 nl80211_nlmsg_clear(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002506 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 return -ENOBUFS;
2508}
2509
2510
2511static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,
2512 int key_idx, int defkey,
2513 const u8 *seq, size_t seq_len,
2514 const u8 *key, size_t key_len)
2515{
2516 struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);
2517 if (!key_attr)
2518 return -1;
2519
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002520 if (defkey && alg == WPA_ALG_IGTK) {
2521 if (nla_put_flag(msg, NL80211_KEY_DEFAULT_MGMT))
2522 return -1;
2523 } else if (defkey) {
2524 if (nla_put_flag(msg, NL80211_KEY_DEFAULT))
2525 return -1;
2526 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002528 if (nla_put_u8(msg, NL80211_KEY_IDX, key_idx) ||
2529 nla_put_u32(msg, NL80211_KEY_CIPHER,
2530 wpa_alg_to_cipher_suite(alg, key_len)) ||
2531 (seq && seq_len &&
2532 nla_put(msg, NL80211_KEY_SEQ, seq_len, seq)) ||
2533 nla_put(msg, NL80211_KEY_DATA, key_len, key))
2534 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535
2536 nla_nest_end(msg, key_attr);
2537
2538 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539}
2540
2541
2542static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
2543 struct nl_msg *msg)
2544{
2545 int i, privacy = 0;
2546 struct nlattr *nl_keys, *nl_key;
2547
2548 for (i = 0; i < 4; i++) {
2549 if (!params->wep_key[i])
2550 continue;
2551 privacy = 1;
2552 break;
2553 }
2554 if (params->wps == WPS_MODE_PRIVACY)
2555 privacy = 1;
2556 if (params->pairwise_suite &&
2557 params->pairwise_suite != WPA_CIPHER_NONE)
2558 privacy = 1;
2559
2560 if (!privacy)
2561 return 0;
2562
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002563 if (nla_put_flag(msg, NL80211_ATTR_PRIVACY))
2564 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565
2566 nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
2567 if (!nl_keys)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002568 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569
2570 for (i = 0; i < 4; i++) {
2571 if (!params->wep_key[i])
2572 continue;
2573
2574 nl_key = nla_nest_start(msg, i);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002575 if (!nl_key ||
2576 nla_put(msg, NL80211_KEY_DATA, params->wep_key_len[i],
2577 params->wep_key[i]) ||
2578 nla_put_u32(msg, NL80211_KEY_CIPHER,
2579 params->wep_key_len[i] == 5 ?
2580 WLAN_CIPHER_SUITE_WEP40 :
2581 WLAN_CIPHER_SUITE_WEP104) ||
2582 nla_put_u8(msg, NL80211_KEY_IDX, i) ||
2583 (i == params->wep_tx_keyidx &&
2584 nla_put_flag(msg, NL80211_KEY_DEFAULT)))
2585 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002586
2587 nla_nest_end(msg, nl_key);
2588 }
2589 nla_nest_end(msg, nl_keys);
2590
2591 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592}
2593
2594
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002595int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
2596 const u8 *addr, int cmd, u16 reason_code,
2597 int local_state_change)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002599 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002600 struct nl_msg *msg;
2601
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002602 if (!(msg = nl80211_drv_msg(drv, 0, cmd)) ||
2603 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) ||
2604 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
2605 (local_state_change &&
2606 nla_put_flag(msg, NL80211_ATTR_LOCAL_STATE_CHANGE))) {
2607 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002609 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002610
2611 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002613 wpa_dbg(drv->ctx, MSG_DEBUG,
2614 "nl80211: MLME command failed: reason=%u ret=%d (%s)",
2615 reason_code, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 return ret;
2618}
2619
2620
2621static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002622 int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002624 int ret;
2625
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002626 wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07002627 nl80211_mark_disconnected(drv);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002628 /* Disconnect command doesn't need BSSID - it uses cached value */
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002629 ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
2630 reason_code, 0);
2631 /*
2632 * For locally generated disconnect, supplicant already generates a
2633 * DEAUTH event, so ignore the event from NL80211.
2634 */
2635 drv->ignore_next_local_disconnect = ret == 0;
2636
2637 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638}
2639
2640
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002641static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
2642 const u8 *addr, int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002644 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002645 int ret;
Dmitry Shmidt413dde72014-04-11 10:23:22 -07002646
2647 if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
2648 nl80211_mark_disconnected(drv);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002649 return nl80211_leave_ibss(drv, 1);
Dmitry Shmidt413dde72014-04-11 10:23:22 -07002650 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002652 return wpa_driver_nl80211_disconnect(drv, reason_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653 wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
2654 __func__, MAC2STR(addr), reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07002655 nl80211_mark_disconnected(drv);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002656 ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
2657 reason_code, 0);
2658 /*
2659 * For locally generated deauthenticate, supplicant already generates a
2660 * DEAUTH event, so ignore the event from NL80211.
2661 */
2662 drv->ignore_next_local_deauth = ret == 0;
2663 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664}
2665
2666
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002667static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
2668 struct wpa_driver_auth_params *params)
2669{
2670 int i;
2671
2672 drv->auth_freq = params->freq;
2673 drv->auth_alg = params->auth_alg;
2674 drv->auth_wep_tx_keyidx = params->wep_tx_keyidx;
2675 drv->auth_local_state_change = params->local_state_change;
2676 drv->auth_p2p = params->p2p;
2677
2678 if (params->bssid)
2679 os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);
2680 else
2681 os_memset(drv->auth_bssid_, 0, ETH_ALEN);
2682
2683 if (params->ssid) {
2684 os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);
2685 drv->auth_ssid_len = params->ssid_len;
2686 } else
2687 drv->auth_ssid_len = 0;
2688
2689
2690 os_free(drv->auth_ie);
2691 drv->auth_ie = NULL;
2692 drv->auth_ie_len = 0;
2693 if (params->ie) {
2694 drv->auth_ie = os_malloc(params->ie_len);
2695 if (drv->auth_ie) {
2696 os_memcpy(drv->auth_ie, params->ie, params->ie_len);
2697 drv->auth_ie_len = params->ie_len;
2698 }
2699 }
2700
2701 for (i = 0; i < 4; i++) {
2702 if (params->wep_key[i] && params->wep_key_len[i] &&
2703 params->wep_key_len[i] <= 16) {
2704 os_memcpy(drv->auth_wep_key[i], params->wep_key[i],
2705 params->wep_key_len[i]);
2706 drv->auth_wep_key_len[i] = params->wep_key_len[i];
2707 } else
2708 drv->auth_wep_key_len[i] = 0;
2709 }
2710}
2711
2712
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002713static void nl80211_unmask_11b_rates(struct i802_bss *bss)
2714{
2715 struct wpa_driver_nl80211_data *drv = bss->drv;
2716
2717 if (is_p2p_net_interface(drv->nlmode) || !drv->disabled_11b_rates)
2718 return;
2719
2720 /*
2721 * Looks like we failed to unmask 11b rates previously. This could
2722 * happen, e.g., if the interface was down at the point in time when a
2723 * P2P group was terminated.
2724 */
2725 wpa_printf(MSG_DEBUG,
2726 "nl80211: Interface %s mode is for non-P2P, but 11b rates were disabled - re-enable them",
2727 bss->ifname);
2728 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
2729}
2730
2731
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732static int wpa_driver_nl80211_authenticate(
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002733 struct i802_bss *bss, struct wpa_driver_auth_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 struct wpa_driver_nl80211_data *drv = bss->drv;
2736 int ret = -1, i;
2737 struct nl_msg *msg;
2738 enum nl80211_auth_type type;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002739 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740 int count = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002741 int is_retry;
2742
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002743 nl80211_unmask_11b_rates(bss);
2744
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002745 is_retry = drv->retry_auth;
2746 drv->retry_auth = 0;
Dmitry Shmidt98660862014-03-11 17:26:21 -07002747 drv->ignore_deauth_event = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07002749 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750 os_memset(drv->auth_bssid, 0, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07002751 if (params->bssid)
2752 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
2753 else
2754 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 /* FIX: IBSS mode */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002756 nlmode = params->p2p ?
2757 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
2758 if (drv->nlmode != nlmode &&
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002759 wpa_driver_nl80211_set_mode(bss, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002760 return -1;
2761
2762retry:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002763 wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
2764 drv->ifindex);
2765
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002766 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_AUTHENTICATE);
2767 if (!msg)
2768 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002769
2770 for (i = 0; i < 4; i++) {
2771 if (!params->wep_key[i])
2772 continue;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002773 wpa_driver_nl80211_set_key(bss->ifname, bss, WPA_ALG_WEP,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002774 NULL, i,
2775 i == params->wep_tx_keyidx, NULL, 0,
2776 params->wep_key[i],
2777 params->wep_key_len[i]);
2778 if (params->wep_tx_keyidx != i)
2779 continue;
2780 if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002781 params->wep_key[i], params->wep_key_len[i]))
2782 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 }
2784
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002785 if (params->bssid) {
2786 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
2787 MAC2STR(params->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002788 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
2789 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002790 }
2791 if (params->freq) {
2792 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002793 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq))
2794 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002795 }
2796 if (params->ssid) {
2797 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
2798 params->ssid, params->ssid_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002799 if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len,
2800 params->ssid))
2801 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002802 }
2803 wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002804 if (params->ie &&
2805 nla_put(msg, NL80211_ATTR_IE, params->ie_len, params->ie))
2806 goto fail;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002807 if (params->sae_data) {
2808 wpa_hexdump(MSG_DEBUG, " * SAE data", params->sae_data,
2809 params->sae_data_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002810 if (nla_put(msg, NL80211_ATTR_SAE_DATA, params->sae_data_len,
2811 params->sae_data))
2812 goto fail;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002813 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002814 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
2815 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
2816 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
2817 type = NL80211_AUTHTYPE_SHARED_KEY;
2818 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
2819 type = NL80211_AUTHTYPE_NETWORK_EAP;
2820 else if (params->auth_alg & WPA_AUTH_ALG_FT)
2821 type = NL80211_AUTHTYPE_FT;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002822 else if (params->auth_alg & WPA_AUTH_ALG_SAE)
2823 type = NL80211_AUTHTYPE_SAE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 else
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002825 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002826 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002827 if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type))
2828 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002829 if (params->local_state_change) {
2830 wpa_printf(MSG_DEBUG, " * Local state change only");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002831 if (nla_put_flag(msg, NL80211_ATTR_LOCAL_STATE_CHANGE))
2832 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002833 }
2834
2835 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
2836 msg = NULL;
2837 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002838 wpa_dbg(drv->ctx, MSG_DEBUG,
2839 "nl80211: MLME command failed (auth): ret=%d (%s)",
2840 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002841 count++;
2842 if (ret == -EALREADY && count == 1 && params->bssid &&
2843 !params->local_state_change) {
2844 /*
2845 * mac80211 does not currently accept new
2846 * authentication if we are already authenticated. As a
2847 * workaround, force deauthentication and try again.
2848 */
2849 wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
2850 "after forced deauthentication");
Dmitry Shmidt98660862014-03-11 17:26:21 -07002851 drv->ignore_deauth_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002852 wpa_driver_nl80211_deauthenticate(
2853 bss, params->bssid,
2854 WLAN_REASON_PREV_AUTH_NOT_VALID);
2855 nlmsg_free(msg);
2856 goto retry;
2857 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002858
2859 if (ret == -ENOENT && params->freq && !is_retry) {
2860 /*
2861 * cfg80211 has likely expired the BSS entry even
2862 * though it was previously available in our internal
2863 * BSS table. To recover quickly, start a single
2864 * channel scan on the specified channel.
2865 */
2866 struct wpa_driver_scan_params scan;
2867 int freqs[2];
2868
2869 os_memset(&scan, 0, sizeof(scan));
2870 scan.num_ssids = 1;
2871 if (params->ssid) {
2872 scan.ssids[0].ssid = params->ssid;
2873 scan.ssids[0].ssid_len = params->ssid_len;
2874 }
2875 freqs[0] = params->freq;
2876 freqs[1] = 0;
2877 scan.freqs = freqs;
2878 wpa_printf(MSG_DEBUG, "nl80211: Trigger single "
2879 "channel scan to refresh cfg80211 BSS "
2880 "entry");
2881 ret = wpa_driver_nl80211_scan(bss, &scan);
2882 if (ret == 0) {
2883 nl80211_copy_auth_params(drv, params);
2884 drv->scan_for_auth = 1;
2885 }
2886 } else if (is_retry) {
2887 /*
2888 * Need to indicate this with an event since the return
2889 * value from the retry is not delivered to core code.
2890 */
2891 union wpa_event_data event;
2892 wpa_printf(MSG_DEBUG, "nl80211: Authentication retry "
2893 "failed");
2894 os_memset(&event, 0, sizeof(event));
2895 os_memcpy(event.timeout_event.addr, drv->auth_bssid_,
2896 ETH_ALEN);
2897 wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,
2898 &event);
2899 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002900 } else {
2901 wpa_printf(MSG_DEBUG,
2902 "nl80211: Authentication request send successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002903 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002905fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002906 nlmsg_free(msg);
2907 return ret;
2908}
2909
2910
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002911int wpa_driver_nl80211_authenticate_retry(struct wpa_driver_nl80211_data *drv)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002912{
2913 struct wpa_driver_auth_params params;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002914 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002915 int i;
2916
2917 wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
2918
2919 os_memset(&params, 0, sizeof(params));
2920 params.freq = drv->auth_freq;
2921 params.auth_alg = drv->auth_alg;
2922 params.wep_tx_keyidx = drv->auth_wep_tx_keyidx;
2923 params.local_state_change = drv->auth_local_state_change;
2924 params.p2p = drv->auth_p2p;
2925
2926 if (!is_zero_ether_addr(drv->auth_bssid_))
2927 params.bssid = drv->auth_bssid_;
2928
2929 if (drv->auth_ssid_len) {
2930 params.ssid = drv->auth_ssid;
2931 params.ssid_len = drv->auth_ssid_len;
2932 }
2933
2934 params.ie = drv->auth_ie;
2935 params.ie_len = drv->auth_ie_len;
2936
2937 for (i = 0; i < 4; i++) {
2938 if (drv->auth_wep_key_len[i]) {
2939 params.wep_key[i] = drv->auth_wep_key[i];
2940 params.wep_key_len[i] = drv->auth_wep_key_len[i];
2941 }
2942 }
2943
2944 drv->retry_auth = 1;
2945 return wpa_driver_nl80211_authenticate(bss, &params);
2946}
2947
2948
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002949static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
2950 const void *data, size_t len,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002951 int encrypt, int noack,
2952 unsigned int freq, int no_cck,
2953 int offchanok, unsigned int wait_time)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002954{
2955 struct wpa_driver_nl80211_data *drv = bss->drv;
2956 u64 cookie;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002957 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002958
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07002959 if (freq == 0 && drv->nlmode == NL80211_IFTYPE_ADHOC) {
2960 freq = nl80211_get_assoc_freq(drv);
2961 wpa_printf(MSG_DEBUG,
2962 "nl80211: send_frame - Use assoc_freq=%u for IBSS",
2963 freq);
2964 }
Dmitry Shmidt56052862013-10-04 10:23:25 -07002965 if (freq == 0) {
2966 wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u",
2967 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002968 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07002969 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002970
Dmitry Shmidt56052862013-10-04 10:23:25 -07002971 if (drv->use_monitor) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002972 wpa_printf(MSG_DEBUG, "nl80211: send_frame(freq=%u bss->freq=%u) -> send_monitor",
Dmitry Shmidt56052862013-10-04 10:23:25 -07002973 freq, bss->freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002974 return nl80211_send_monitor(drv, data, len, encrypt, noack);
Dmitry Shmidt56052862013-10-04 10:23:25 -07002975 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002976
Dmitry Shmidt56052862013-10-04 10:23:25 -07002977 wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
Dmitry Shmidt051af732013-10-22 13:52:46 -07002978 res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
2979 &cookie, no_cck, noack, offchanok);
2980 if (res == 0 && !noack) {
2981 const struct ieee80211_mgmt *mgmt;
2982 u16 fc;
2983
2984 mgmt = (const struct ieee80211_mgmt *) data;
2985 fc = le_to_host16(mgmt->frame_control);
2986 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
2987 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
2988 wpa_printf(MSG_MSGDUMP,
2989 "nl80211: Update send_action_cookie from 0x%llx to 0x%llx",
2990 (long long unsigned int)
2991 drv->send_action_cookie,
2992 (long long unsigned int) cookie);
2993 drv->send_action_cookie = cookie;
2994 }
2995 }
2996
2997 return res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002998}
2999
3000
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003001static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
3002 size_t data_len, int noack,
3003 unsigned int freq, int no_cck,
3004 int offchanok,
3005 unsigned int wait_time)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003006{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 struct wpa_driver_nl80211_data *drv = bss->drv;
3008 struct ieee80211_mgmt *mgmt;
3009 int encrypt = 1;
3010 u16 fc;
3011
3012 mgmt = (struct ieee80211_mgmt *) data;
3013 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003014 wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR
3015 " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x (%s) nlmode=%d",
3016 MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time,
3017 fc, fc2str(fc), drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003018
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003019 if ((is_sta_interface(drv->nlmode) ||
3020 drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003021 WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
3022 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
3023 /*
3024 * The use of last_mgmt_freq is a bit of a hack,
3025 * but it works due to the single-threaded nature
3026 * of wpa_supplicant.
3027 */
Dmitry Shmidt56052862013-10-04 10:23:25 -07003028 if (freq == 0) {
3029 wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d",
3030 drv->last_mgmt_freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003031 freq = drv->last_mgmt_freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07003032 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003033 return nl80211_send_frame_cmd(bss, freq, 0,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003034 data, data_len, NULL, 1, noack,
3035 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003036 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003037
3038 if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
Dmitry Shmidt56052862013-10-04 10:23:25 -07003039 if (freq == 0) {
3040 wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d",
3041 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003042 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07003043 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003044 return nl80211_send_frame_cmd(bss, freq,
3045 (int) freq == bss->freq ? 0 :
3046 wait_time,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003047 data, data_len,
3048 &drv->send_action_cookie,
3049 no_cck, noack, offchanok);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07003050 }
Dmitry Shmidtb638fe72012-03-20 12:51:25 -07003051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
3053 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {
3054 /*
3055 * Only one of the authentication frame types is encrypted.
3056 * In order for static WEP encryption to work properly (i.e.,
3057 * to not encrypt the frame), we need to tell mac80211 about
3058 * the frames that must not be encrypted.
3059 */
3060 u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
3061 u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);
3062 if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)
3063 encrypt = 0;
3064 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003065
Dmitry Shmidt56052862013-10-04 10:23:25 -07003066 wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003067 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003068 noack, freq, no_cck, offchanok,
3069 wait_time);
3070}
3071
3072
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003073static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
3074 int slot, int ht_opmode, int ap_isolate,
3075 int *basic_rates)
3076{
3077 struct wpa_driver_nl80211_data *drv = bss->drv;
3078 struct nl_msg *msg;
3079
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003080 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_BSS)) ||
3081 (cts >= 0 &&
3082 nla_put_u8(msg, NL80211_ATTR_BSS_CTS_PROT, cts)) ||
3083 (preamble >= 0 &&
3084 nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble)) ||
3085 (slot >= 0 &&
3086 nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot)) ||
3087 (ht_opmode >= 0 &&
3088 nla_put_u16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode)) ||
3089 (ap_isolate >= 0 &&
3090 nla_put_u8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate)))
3091 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003092
3093 if (basic_rates) {
3094 u8 rates[NL80211_MAX_SUPP_RATES];
3095 u8 rates_len = 0;
3096 int i;
3097
3098 for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0;
3099 i++)
3100 rates[rates_len++] = basic_rates[i] / 5;
3101
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003102 if (nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len,
3103 rates))
3104 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003105 }
3106
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003107 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003108fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003109 nlmsg_free(msg);
3110 return -ENOBUFS;
3111}
3112
3113
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003114static int wpa_driver_nl80211_set_acl(void *priv,
3115 struct hostapd_acl_params *params)
3116{
3117 struct i802_bss *bss = priv;
3118 struct wpa_driver_nl80211_data *drv = bss->drv;
3119 struct nl_msg *msg;
3120 struct nlattr *acl;
3121 unsigned int i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003122 int ret;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003123
3124 if (!(drv->capa.max_acl_mac_addrs))
3125 return -ENOTSUP;
3126
3127 if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
3128 return -ENOTSUP;
3129
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003130 wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
3131 params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
3132
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003133 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MAC_ACL)) ||
3134 nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
3135 NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
3136 NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) ||
3137 (acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS)) == NULL) {
3138 nlmsg_free(msg);
3139 return -ENOMEM;
3140 }
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003141
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003142 for (i = 0; i < params->num_mac_acl; i++) {
3143 if (nla_put(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr)) {
3144 nlmsg_free(msg);
3145 return -ENOMEM;
3146 }
3147 }
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003148
3149 nla_nest_end(msg, acl);
3150
3151 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003152 if (ret) {
3153 wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
3154 ret, strerror(-ret));
3155 }
3156
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003157 return ret;
3158}
3159
3160
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003161static int wpa_driver_nl80211_set_ap(void *priv,
3162 struct wpa_driver_ap_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003163{
3164 struct i802_bss *bss = priv;
3165 struct wpa_driver_nl80211_data *drv = bss->drv;
3166 struct nl_msg *msg;
3167 u8 cmd = NL80211_CMD_NEW_BEACON;
3168 int ret;
3169 int beacon_set;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003170 int num_suites;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003171 int smps_mode;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003172 u32 suites[10], suite;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003173 u32 ver;
3174
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07003175 beacon_set = bss->beacon_set;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003176
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003177 wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
3178 beacon_set);
3179 if (beacon_set)
3180 cmd = NL80211_CMD_SET_BEACON;
3181
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003182 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
3183 params->head, params->head_len);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003184 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon tail",
3185 params->tail, params->tail_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003186 wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", bss->ifindex);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003187 wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003188 wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003189 wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid",
3190 params->ssid, params->ssid_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003191 if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
3192 nla_put(msg, NL80211_ATTR_BEACON_HEAD, params->head_len,
3193 params->head) ||
3194 nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len,
3195 params->tail) ||
3196 nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL,
3197 params->beacon_int) ||
3198 nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period) ||
3199 nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
3200 goto fail;
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003201 if (params->proberesp && params->proberesp_len) {
3202 wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)",
3203 params->proberesp, params->proberesp_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003204 if (nla_put(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
3205 params->proberesp))
3206 goto fail;
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003207 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003208 switch (params->hide_ssid) {
3209 case NO_SSID_HIDING:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003210 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID not in use");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003211 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
3212 NL80211_HIDDEN_SSID_NOT_IN_USE))
3213 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003214 break;
3215 case HIDDEN_SSID_ZERO_LEN:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003216 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero len");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003217 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
3218 NL80211_HIDDEN_SSID_ZERO_LEN))
3219 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003220 break;
3221 case HIDDEN_SSID_ZERO_CONTENTS:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003222 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero contents");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003223 if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID,
3224 NL80211_HIDDEN_SSID_ZERO_CONTENTS))
3225 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003226 break;
3227 }
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003228 wpa_printf(MSG_DEBUG, "nl80211: privacy=%d", params->privacy);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003229 if (params->privacy &&
3230 nla_put_flag(msg, NL80211_ATTR_PRIVACY))
3231 goto fail;
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003232 wpa_printf(MSG_DEBUG, "nl80211: auth_algs=0x%x", params->auth_algs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003233 if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
3234 (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
3235 /* Leave out the attribute */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003236 } else if (params->auth_algs & WPA_AUTH_ALG_SHARED) {
3237 if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE,
3238 NL80211_AUTHTYPE_SHARED_KEY))
3239 goto fail;
3240 } else {
3241 if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE,
3242 NL80211_AUTHTYPE_OPEN_SYSTEM))
3243 goto fail;
3244 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003245
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003246 wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003247 ver = 0;
3248 if (params->wpa_version & WPA_PROTO_WPA)
3249 ver |= NL80211_WPA_VERSION_1;
3250 if (params->wpa_version & WPA_PROTO_RSN)
3251 ver |= NL80211_WPA_VERSION_2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003252 if (ver &&
3253 nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver))
3254 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003255
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003256 wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x",
3257 params->key_mgmt_suites);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003258 num_suites = 0;
3259 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
3260 suites[num_suites++] = WLAN_AKM_SUITE_8021X;
3261 if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
3262 suites[num_suites++] = WLAN_AKM_SUITE_PSK;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003263 if (num_suites &&
3264 nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32),
3265 suites))
3266 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003267
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003268 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
3269 params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40) &&
3270 nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
3271 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003272
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003273 wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
3274 params->pairwise_ciphers);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003275 num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers,
3276 suites, ARRAY_SIZE(suites));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003277 if (num_suites &&
3278 nla_put(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
3279 num_suites * sizeof(u32), suites))
3280 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003281
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003282 wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x",
3283 params->group_cipher);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003284 suite = wpa_cipher_to_cipher_suite(params->group_cipher);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003285 if (suite &&
3286 nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite))
3287 goto fail;
3288
3289 switch (params->smps_mode) {
3290 case HT_CAP_INFO_SMPS_DYNAMIC:
3291 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - dynamic");
3292 smps_mode = NL80211_SMPS_DYNAMIC;
3293 break;
3294 case HT_CAP_INFO_SMPS_STATIC:
3295 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - static");
3296 smps_mode = NL80211_SMPS_STATIC;
3297 break;
3298 default:
3299 /* invalid - fallback to smps off */
3300 case HT_CAP_INFO_SMPS_DISABLED:
3301 wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - off");
3302 smps_mode = NL80211_SMPS_OFF;
3303 break;
3304 }
3305 if (nla_put_u32(msg, NL80211_ATTR_SMPS_MODE, smps_mode))
3306 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003307
3308 if (params->beacon_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003309 wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
3310 params->beacon_ies);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003311 if (nla_put(msg, NL80211_ATTR_IE,
3312 wpabuf_len(params->beacon_ies),
3313 wpabuf_head(params->beacon_ies)))
3314 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003315 }
3316 if (params->proberesp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003317 wpa_hexdump_buf(MSG_DEBUG, "nl80211: proberesp_ies",
3318 params->proberesp_ies);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003319 if (nla_put(msg, NL80211_ATTR_IE_PROBE_RESP,
3320 wpabuf_len(params->proberesp_ies),
3321 wpabuf_head(params->proberesp_ies)))
3322 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003323 }
3324 if (params->assocresp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003325 wpa_hexdump_buf(MSG_DEBUG, "nl80211: assocresp_ies",
3326 params->assocresp_ies);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003327 if (nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP,
3328 wpabuf_len(params->assocresp_ies),
3329 wpabuf_head(params->assocresp_ies)))
3330 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003331 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003332
Dmitry Shmidt04949592012-07-19 12:16:46 -07003333 if (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07003334 wpa_printf(MSG_DEBUG, "nl80211: ap_max_inactivity=%d",
3335 params->ap_max_inactivity);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003336 if (nla_put_u16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT,
3337 params->ap_max_inactivity))
3338 goto fail;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003339 }
3340
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003341 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
3342 if (ret) {
3343 wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
3344 ret, strerror(-ret));
3345 } else {
3346 bss->beacon_set = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003347 nl80211_set_bss(bss, params->cts_protect, params->preamble,
3348 params->short_slot_time, params->ht_opmode,
3349 params->isolate, params->basic_rates);
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003350 if (beacon_set && params->freq &&
3351 params->freq->bandwidth != bss->bandwidth) {
3352 wpa_printf(MSG_DEBUG,
3353 "nl80211: Update BSS %s bandwidth: %d -> %d",
3354 bss->ifname, bss->bandwidth,
3355 params->freq->bandwidth);
3356 ret = nl80211_set_channel(bss, params->freq, 1);
3357 if (ret) {
3358 wpa_printf(MSG_DEBUG,
3359 "nl80211: Frequency set failed: %d (%s)",
3360 ret, strerror(-ret));
3361 } else {
3362 wpa_printf(MSG_DEBUG,
3363 "nl80211: Frequency set succeeded for ht2040 coex");
3364 bss->bandwidth = params->freq->bandwidth;
3365 }
3366 } else if (!beacon_set) {
3367 /*
3368 * cfg80211 updates the driver on frequence change in AP
3369 * mode only at the point when beaconing is started, so
3370 * set the initial value here.
3371 */
3372 bss->bandwidth = params->freq->bandwidth;
3373 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374 }
3375 return ret;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003376fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003377 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003378 return -ENOBUFS;
3379}
3380
3381
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003382static int nl80211_put_freq_params(struct nl_msg *msg,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003383 const struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003384{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003385 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq))
3386 return -ENOBUFS;
3387
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003388 if (freq->vht_enabled) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003389 enum nl80211_chan_width cw;
3390
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003391 switch (freq->bandwidth) {
3392 case 20:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003393 cw = NL80211_CHAN_WIDTH_20;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003394 break;
3395 case 40:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003396 cw = NL80211_CHAN_WIDTH_40;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003397 break;
3398 case 80:
3399 if (freq->center_freq2)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003400 cw = NL80211_CHAN_WIDTH_80P80;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003401 else
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003402 cw = NL80211_CHAN_WIDTH_80;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003403 break;
3404 case 160:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003405 cw = NL80211_CHAN_WIDTH_160;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003406 break;
3407 default:
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003408 return -EINVAL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003409 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003410
3411 if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cw) ||
3412 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1,
3413 freq->center_freq1) ||
3414 (freq->center_freq2 &&
3415 nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2,
3416 freq->center_freq2)))
3417 return -ENOBUFS;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003418 } else if (freq->ht_enabled) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003419 enum nl80211_channel_type ct;
3420
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003421 switch (freq->sec_channel_offset) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003422 case -1:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003423 ct = NL80211_CHAN_HT40MINUS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003424 break;
3425 case 1:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003426 ct = NL80211_CHAN_HT40PLUS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003427 break;
3428 default:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003429 ct = NL80211_CHAN_HT20;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003430 break;
3431 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003432
3433 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct))
3434 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003435 }
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003436 return 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003437}
3438
3439
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003440static int nl80211_set_channel(struct i802_bss *bss,
3441 struct hostapd_freq_params *freq, int set_chan)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003442{
3443 struct wpa_driver_nl80211_data *drv = bss->drv;
3444 struct nl_msg *msg;
3445 int ret;
3446
3447 wpa_printf(MSG_DEBUG,
3448 "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
3449 freq->freq, freq->ht_enabled, freq->vht_enabled,
3450 freq->bandwidth, freq->center_freq1, freq->center_freq2);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003451
3452 msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
3453 NL80211_CMD_SET_WIPHY);
3454 if (!msg || nl80211_put_freq_params(msg, freq) < 0) {
3455 nlmsg_free(msg);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003456 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003457 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003458
3459 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003460 if (ret == 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003461 bss->freq = freq->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003462 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003463 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003464 wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003465 "%d (%s)", freq->freq, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466 return -1;
3467}
3468
3469
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003470static u32 sta_flags_nl80211(int flags)
3471{
3472 u32 f = 0;
3473
3474 if (flags & WPA_STA_AUTHORIZED)
3475 f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
3476 if (flags & WPA_STA_WMM)
3477 f |= BIT(NL80211_STA_FLAG_WME);
3478 if (flags & WPA_STA_SHORT_PREAMBLE)
3479 f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
3480 if (flags & WPA_STA_MFP)
3481 f |= BIT(NL80211_STA_FLAG_MFP);
3482 if (flags & WPA_STA_TDLS_PEER)
3483 f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003484 if (flags & WPA_STA_AUTHENTICATED)
3485 f |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003486
3487 return f;
3488}
3489
3490
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003491#ifdef CONFIG_MESH
3492static u32 sta_plink_state_nl80211(enum mesh_plink_state state)
3493{
3494 switch (state) {
3495 case PLINK_LISTEN:
3496 return NL80211_PLINK_LISTEN;
3497 case PLINK_OPEN_SENT:
3498 return NL80211_PLINK_OPN_SNT;
3499 case PLINK_OPEN_RCVD:
3500 return NL80211_PLINK_OPN_RCVD;
3501 case PLINK_CNF_RCVD:
3502 return NL80211_PLINK_CNF_RCVD;
3503 case PLINK_ESTAB:
3504 return NL80211_PLINK_ESTAB;
3505 case PLINK_HOLDING:
3506 return NL80211_PLINK_HOLDING;
3507 case PLINK_BLOCKED:
3508 return NL80211_PLINK_BLOCKED;
3509 default:
3510 wpa_printf(MSG_ERROR, "nl80211: Invalid mesh plink state %d",
3511 state);
3512 }
3513 return -1;
3514}
3515#endif /* CONFIG_MESH */
3516
3517
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518static int wpa_driver_nl80211_sta_add(void *priv,
3519 struct hostapd_sta_add_params *params)
3520{
3521 struct i802_bss *bss = priv;
3522 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003523 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003524 struct nl80211_sta_flag_update upd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003525 int ret = -ENOBUFS;
3526
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003527 if ((params->flags & WPA_STA_TDLS_PEER) &&
3528 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
3529 return -EOPNOTSUPP;
3530
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003531 wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR,
3532 params->set ? "Set" : "Add", MAC2STR(params->addr));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003533 msg = nl80211_bss_msg(bss, 0, params->set ? NL80211_CMD_SET_STATION :
3534 NL80211_CMD_NEW_STATION);
3535 if (!msg || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr))
3536 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003537
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003538 if (!params->set || (params->flags & WPA_STA_TDLS_PEER)) {
3539 wpa_hexdump(MSG_DEBUG, " * supported rates",
3540 params->supp_rates, params->supp_rates_len);
3541 wpa_printf(MSG_DEBUG, " * capability=0x%x",
3542 params->capability);
3543 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_RATES,
3544 params->supp_rates_len, params->supp_rates) ||
3545 nla_put_u16(msg, NL80211_ATTR_STA_CAPABILITY,
3546 params->capability))
3547 goto fail;
3548
3549 if (params->ht_capabilities) {
3550 wpa_hexdump(MSG_DEBUG, " * ht_capabilities",
3551 (u8 *) params->ht_capabilities,
3552 sizeof(*params->ht_capabilities));
3553 if (nla_put(msg, NL80211_ATTR_HT_CAPABILITY,
3554 sizeof(*params->ht_capabilities),
3555 params->ht_capabilities))
3556 goto fail;
3557 }
3558
3559 if (params->vht_capabilities) {
3560 wpa_hexdump(MSG_DEBUG, " * vht_capabilities",
3561 (u8 *) params->vht_capabilities,
3562 sizeof(*params->vht_capabilities));
3563 if (nla_put(msg, NL80211_ATTR_VHT_CAPABILITY,
3564 sizeof(*params->vht_capabilities),
3565 params->vht_capabilities))
3566 goto fail;
3567 }
3568
3569 if (params->ext_capab) {
3570 wpa_hexdump(MSG_DEBUG, " * ext_capab",
3571 params->ext_capab, params->ext_capab_len);
3572 if (nla_put(msg, NL80211_ATTR_STA_EXT_CAPABILITY,
3573 params->ext_capab_len, params->ext_capab))
3574 goto fail;
3575 }
3576 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003577 if (!params->set) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003578 if (params->aid) {
3579 wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003580 if (nla_put_u16(msg, NL80211_ATTR_STA_AID, params->aid))
3581 goto fail;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003582 } else {
3583 /*
3584 * cfg80211 validates that AID is non-zero, so we have
3585 * to make this a non-zero value for the TDLS case where
3586 * a dummy STA entry is used for now.
3587 */
3588 wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003589 if (nla_put_u16(msg, NL80211_ATTR_STA_AID, 1))
3590 goto fail;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003591 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003592 wpa_printf(MSG_DEBUG, " * listen_interval=%u",
3593 params->listen_interval);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003594 if (nla_put_u16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
3595 params->listen_interval))
3596 goto fail;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003597 } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
3598 wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003599 if (nla_put_u16(msg, NL80211_ATTR_PEER_AID, params->aid))
3600 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003601 }
3602
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003603 if (params->vht_opmode_enabled) {
3604 wpa_printf(MSG_DEBUG, " * opmode=%u", params->vht_opmode);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003605 if (nla_put_u8(msg, NL80211_ATTR_OPMODE_NOTIF,
3606 params->vht_opmode))
3607 goto fail;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003608 }
3609
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003610 if (params->supp_channels) {
3611 wpa_hexdump(MSG_DEBUG, " * supported channels",
3612 params->supp_channels, params->supp_channels_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003613 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_CHANNELS,
3614 params->supp_channels_len, params->supp_channels))
3615 goto fail;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003616 }
3617
3618 if (params->supp_oper_classes) {
3619 wpa_hexdump(MSG_DEBUG, " * supported operating classes",
3620 params->supp_oper_classes,
3621 params->supp_oper_classes_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003622 if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
3623 params->supp_oper_classes_len,
3624 params->supp_oper_classes))
3625 goto fail;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003626 }
3627
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003628 os_memset(&upd, 0, sizeof(upd));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003629 upd.set = sta_flags_nl80211(params->flags);
3630 upd.mask = upd.set | sta_flags_nl80211(params->flags_mask);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003631 wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x",
3632 upd.set, upd.mask);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003633 if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
3634 goto fail;
3635
3636#ifdef CONFIG_MESH
3637 if (params->plink_state &&
3638 nla_put_u8(msg, NL80211_ATTR_STA_PLINK_STATE,
3639 sta_plink_state_nl80211(params->plink_state)))
3640 goto fail;
3641#endif /* CONFIG_MESH */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003642
3643 if (params->flags & WPA_STA_WMM) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003644 struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME);
3645
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003646 wpa_printf(MSG_DEBUG, " * qosinfo=0x%x", params->qosinfo);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003647 if (!wme ||
3648 nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
3649 params->qosinfo & WMM_QOSINFO_STA_AC_MASK) ||
3650 nla_put_u8(msg, NL80211_STA_WME_MAX_SP,
3651 (params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &
3652 WMM_QOSINFO_STA_SP_MASK))
3653 goto fail;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003654 nla_nest_end(msg, wme);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003655 }
3656
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003657 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003658 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003659 if (ret)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003660 wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
3661 "result: %d (%s)", params->set ? "SET" : "NEW", ret,
3662 strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663 if (ret == -EEXIST)
3664 ret = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003665fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003666 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003667 return ret;
3668}
3669
3670
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003671static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
3672{
3673#ifdef CONFIG_LIBNL3_ROUTE
3674 struct wpa_driver_nl80211_data *drv = bss->drv;
3675 struct rtnl_neigh *rn;
3676 struct nl_addr *nl_addr;
3677 int err;
3678
3679 rn = rtnl_neigh_alloc();
3680 if (!rn)
3681 return;
3682
3683 rtnl_neigh_set_family(rn, AF_BRIDGE);
3684 rtnl_neigh_set_ifindex(rn, bss->ifindex);
3685 nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
3686 if (!nl_addr) {
3687 rtnl_neigh_put(rn);
3688 return;
3689 }
3690 rtnl_neigh_set_lladdr(rn, nl_addr);
3691
3692 err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
3693 if (err < 0) {
3694 wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
3695 MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
3696 bss->ifindex, nl_geterror(err));
3697 } else {
3698 wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for "
3699 MACSTR, MAC2STR(addr));
3700 }
3701
3702 nl_addr_put(nl_addr);
3703 rtnl_neigh_put(rn);
3704#endif /* CONFIG_LIBNL3_ROUTE */
3705}
3706
3707
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003708static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr,
3709 int deauth, u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003710{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003711 struct wpa_driver_nl80211_data *drv = bss->drv;
3712 struct nl_msg *msg;
3713 int ret;
3714
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003715 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION)) ||
3716 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
3717 (deauth == 0 &&
3718 nla_put_u8(msg, NL80211_ATTR_MGMT_SUBTYPE,
3719 WLAN_FC_STYPE_DISASSOC)) ||
3720 (deauth == 1 &&
3721 nla_put_u8(msg, NL80211_ATTR_MGMT_SUBTYPE,
3722 WLAN_FC_STYPE_DEAUTH)) ||
3723 (reason_code &&
3724 nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) {
3725 nlmsg_free(msg);
3726 return -ENOBUFS;
3727 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728
3729 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07003730 wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
3731 " --> %d (%s)",
3732 bss->ifname, MAC2STR(addr), ret, strerror(-ret));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003733
3734 if (drv->rtnl_sk)
3735 rtnl_neigh_delete_fdb_entry(bss, addr);
3736
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003737 if (ret == -ENOENT)
3738 return 0;
3739 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003740}
3741
3742
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003743void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003744{
3745 struct nl_msg *msg;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003746 struct wpa_driver_nl80211_data *drv2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747
3748 wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx);
3749
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003750 /* stop listening for EAPOL on this interface */
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003751 dl_list_for_each(drv2, &drv->global->interfaces,
3752 struct wpa_driver_nl80211_data, list)
3753 del_ifidx(drv2, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003754
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003755 msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003756 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
3757 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003758 wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
3759}
3760
3761
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003762static const char * nl80211_iftype_str(enum nl80211_iftype mode)
3763{
3764 switch (mode) {
3765 case NL80211_IFTYPE_ADHOC:
3766 return "ADHOC";
3767 case NL80211_IFTYPE_STATION:
3768 return "STATION";
3769 case NL80211_IFTYPE_AP:
3770 return "AP";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003771 case NL80211_IFTYPE_AP_VLAN:
3772 return "AP_VLAN";
3773 case NL80211_IFTYPE_WDS:
3774 return "WDS";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003775 case NL80211_IFTYPE_MONITOR:
3776 return "MONITOR";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003777 case NL80211_IFTYPE_MESH_POINT:
3778 return "MESH_POINT";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003779 case NL80211_IFTYPE_P2P_CLIENT:
3780 return "P2P_CLIENT";
3781 case NL80211_IFTYPE_P2P_GO:
3782 return "P2P_GO";
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003783 case NL80211_IFTYPE_P2P_DEVICE:
3784 return "P2P_DEVICE";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003785 default:
3786 return "unknown";
3787 }
3788}
3789
3790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003791static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
3792 const char *ifname,
3793 enum nl80211_iftype iftype,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003794 const u8 *addr, int wds,
3795 int (*handler)(struct nl_msg *, void *),
3796 void *arg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003797{
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003798 struct nl_msg *msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003799 int ifidx;
3800 int ret = -ENOBUFS;
3801
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003802 wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)",
3803 iftype, nl80211_iftype_str(iftype));
3804
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003805 msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_NEW_INTERFACE);
3806 if (!msg ||
3807 nla_put_string(msg, NL80211_ATTR_IFNAME, ifname) ||
3808 nla_put_u32(msg, NL80211_ATTR_IFTYPE, iftype))
3809 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003810
3811 if (iftype == NL80211_IFTYPE_MONITOR) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003812 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003813
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003814 flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003815 if (!flags ||
3816 nla_put_flag(msg, NL80211_MNTR_FLAG_COOK_FRAMES))
3817 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003818
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003819 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003820 } else if (wds) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003821 if (nla_put_u8(msg, NL80211_ATTR_4ADDR, wds))
3822 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003823 }
3824
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003825 /*
3826 * Tell cfg80211 that the interface belongs to the socket that created
3827 * it, and the interface should be deleted when the socket is closed.
3828 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003829 if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER))
3830 goto fail;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003831
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003832 ret = send_and_recv_msgs(drv, msg, handler, arg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003833 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003834 if (ret) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003835 fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003836 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003837 wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)",
3838 ifname, ret, strerror(-ret));
3839 return ret;
3840 }
3841
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003842 if (iftype == NL80211_IFTYPE_P2P_DEVICE)
3843 return 0;
3844
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003845 ifidx = if_nametoindex(ifname);
3846 wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d",
3847 ifname, ifidx);
3848
3849 if (ifidx <= 0)
3850 return -1;
3851
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003852 /*
3853 * Some virtual interfaces need to process EAPOL packets and events on
3854 * the parent interface. This is used mainly with hostapd.
3855 */
3856 if (drv->hostapd ||
3857 iftype == NL80211_IFTYPE_AP_VLAN ||
3858 iftype == NL80211_IFTYPE_WDS ||
3859 iftype == NL80211_IFTYPE_MONITOR) {
3860 /* start listening for EAPOL on this interface */
3861 add_ifidx(drv, ifidx);
3862 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003863
3864 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003865 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003866 nl80211_remove_iface(drv, ifidx);
3867 return -1;
3868 }
3869
3870 return ifidx;
3871}
3872
3873
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003874int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
3875 const char *ifname, enum nl80211_iftype iftype,
3876 const u8 *addr, int wds,
3877 int (*handler)(struct nl_msg *, void *),
3878 void *arg, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003879{
3880 int ret;
3881
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003882 ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler,
3883 arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003884
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003885 /* if error occurred and interface exists already */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003886 if (ret == -ENFILE && if_nametoindex(ifname)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003887 if (use_existing) {
3888 wpa_printf(MSG_DEBUG, "nl80211: Continue using existing interface %s",
3889 ifname);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07003890 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
3891 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
3892 addr) < 0 &&
3893 (linux_set_iface_flags(drv->global->ioctl_sock,
3894 ifname, 0) < 0 ||
3895 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
3896 addr) < 0 ||
3897 linux_set_iface_flags(drv->global->ioctl_sock,
3898 ifname, 1) < 0))
3899 return -1;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003900 return -ENFILE;
3901 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003902 wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname);
3903
3904 /* Try to remove the interface that was already there. */
3905 nl80211_remove_iface(drv, if_nametoindex(ifname));
3906
3907 /* Try to create the interface again */
3908 ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003909 wds, handler, arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003910 }
3911
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003912 if (ret >= 0 && is_p2p_net_interface(iftype)) {
3913 wpa_printf(MSG_DEBUG,
3914 "nl80211: Interface %s created for P2P - disable 11b rates",
3915 ifname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916 nl80211_disable_11b_rates(drv, ret, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003917 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003918
3919 return ret;
3920}
3921
3922
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003923static int nl80211_setup_ap(struct i802_bss *bss)
3924{
3925 struct wpa_driver_nl80211_data *drv = bss->drv;
3926
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003927 wpa_printf(MSG_DEBUG, "nl80211: Setup AP(%s) - device_ap_sme=%d use_monitor=%d",
3928 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003929
3930 /*
3931 * Disable Probe Request reporting unless we need it in this way for
3932 * devices that include the AP SME, in the other case (unless using
3933 * monitor iface) we'll get it through the nl_mgmt socket instead.
3934 */
3935 if (!drv->device_ap_sme)
3936 wpa_driver_nl80211_probe_req_report(bss, 0);
3937
3938 if (!drv->device_ap_sme && !drv->use_monitor)
3939 if (nl80211_mgmt_subscribe_ap(bss))
3940 return -1;
3941
3942 if (drv->device_ap_sme && !drv->use_monitor)
3943 if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
3944 return -1;
3945
3946 if (!drv->device_ap_sme && drv->use_monitor &&
3947 nl80211_create_monitor_interface(drv) &&
3948 !drv->device_ap_sme)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003949 return -1;
3950
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003951 if (drv->device_ap_sme &&
3952 wpa_driver_nl80211_probe_req_report(bss, 1) < 0) {
3953 wpa_printf(MSG_DEBUG, "nl80211: Failed to enable "
3954 "Probe Request frame reporting in AP mode");
3955 /* Try to survive without this */
3956 }
3957
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003958 return 0;
3959}
3960
3961
3962static void nl80211_teardown_ap(struct i802_bss *bss)
3963{
3964 struct wpa_driver_nl80211_data *drv = bss->drv;
3965
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003966 wpa_printf(MSG_DEBUG, "nl80211: Teardown AP(%s) - device_ap_sme=%d use_monitor=%d",
3967 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003968 if (drv->device_ap_sme) {
3969 wpa_driver_nl80211_probe_req_report(bss, 0);
3970 if (!drv->use_monitor)
3971 nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)");
3972 } else if (drv->use_monitor)
3973 nl80211_remove_monitor_interface(drv);
3974 else
3975 nl80211_mgmt_unsubscribe(bss, "AP teardown");
3976
3977 bss->beacon_set = 0;
3978}
3979
3980
3981static int nl80211_send_eapol_data(struct i802_bss *bss,
3982 const u8 *addr, const u8 *data,
3983 size_t data_len)
3984{
3985 struct sockaddr_ll ll;
3986 int ret;
3987
3988 if (bss->drv->eapol_tx_sock < 0) {
3989 wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL");
3990 return -1;
3991 }
3992
3993 os_memset(&ll, 0, sizeof(ll));
3994 ll.sll_family = AF_PACKET;
3995 ll.sll_ifindex = bss->ifindex;
3996 ll.sll_protocol = htons(ETH_P_PAE);
3997 ll.sll_halen = ETH_ALEN;
3998 os_memcpy(ll.sll_addr, addr, ETH_ALEN);
3999 ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,
4000 (struct sockaddr *) &ll, sizeof(ll));
4001 if (ret < 0)
4002 wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s",
4003 strerror(errno));
4004
4005 return ret;
4006}
4007
4008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004009static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
4010
4011static int wpa_driver_nl80211_hapd_send_eapol(
4012 void *priv, const u8 *addr, const u8 *data,
4013 size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
4014{
4015 struct i802_bss *bss = priv;
4016 struct wpa_driver_nl80211_data *drv = bss->drv;
4017 struct ieee80211_hdr *hdr;
4018 size_t len;
4019 u8 *pos;
4020 int res;
4021 int qos = flags & WPA_STA_WMM;
Dmitry Shmidt641185e2013-11-06 15:17:13 -08004022
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004023 if (drv->device_ap_sme || !drv->use_monitor)
4024 return nl80211_send_eapol_data(bss, addr, data, data_len);
4025
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004026 len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
4027 data_len;
4028 hdr = os_zalloc(len);
4029 if (hdr == NULL) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004030 wpa_printf(MSG_INFO, "nl80211: Failed to allocate EAPOL buffer(len=%lu)",
4031 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004032 return -1;
4033 }
4034
4035 hdr->frame_control =
4036 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
4037 hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
4038 if (encrypt)
4039 hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
4040 if (qos) {
4041 hdr->frame_control |=
4042 host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
4043 }
4044
4045 memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
4046 memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
4047 memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
4048 pos = (u8 *) (hdr + 1);
4049
4050 if (qos) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004051 /* Set highest priority in QoS header */
4052 pos[0] = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004053 pos[1] = 0;
4054 pos += 2;
4055 }
4056
4057 memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
4058 pos += sizeof(rfc1042_header);
4059 WPA_PUT_BE16(pos, ETH_P_PAE);
4060 pos += 2;
4061 memcpy(pos, data, data_len);
4062
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004063 res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
4064 0, 0, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004065 if (res < 0) {
4066 wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
4067 "failed: %d (%s)",
4068 (unsigned long) len, errno, strerror(errno));
4069 }
4070 os_free(hdr);
4071
4072 return res;
4073}
4074
4075
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004076static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
4077 int total_flags,
4078 int flags_or, int flags_and)
4079{
4080 struct i802_bss *bss = priv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004081 struct nl_msg *msg;
4082 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004083 struct nl80211_sta_flag_update upd;
4084
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004085 wpa_printf(MSG_DEBUG, "nl80211: Set STA flags - ifname=%s addr=" MACSTR
4086 " total_flags=0x%x flags_or=0x%x flags_and=0x%x authorized=%d",
4087 bss->ifname, MAC2STR(addr), total_flags, flags_or, flags_and,
4088 !!(total_flags & WPA_STA_AUTHORIZED));
4089
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004090 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
4091 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
4092 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004093
4094 /*
4095 * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
4096 * can be removed eventually.
4097 */
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004098 flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004099 if (!flags ||
4100 ((total_flags & WPA_STA_AUTHORIZED) &&
4101 nla_put_flag(msg, NL80211_STA_FLAG_AUTHORIZED)) ||
4102 ((total_flags & WPA_STA_WMM) &&
4103 nla_put_flag(msg, NL80211_STA_FLAG_WME)) ||
4104 ((total_flags & WPA_STA_SHORT_PREAMBLE) &&
4105 nla_put_flag(msg, NL80211_STA_FLAG_SHORT_PREAMBLE)) ||
4106 ((total_flags & WPA_STA_MFP) &&
4107 nla_put_flag(msg, NL80211_STA_FLAG_MFP)) ||
4108 ((total_flags & WPA_STA_TDLS_PEER) &&
4109 nla_put_flag(msg, NL80211_STA_FLAG_TDLS_PEER)))
4110 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004111
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004112 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004113
4114 os_memset(&upd, 0, sizeof(upd));
4115 upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
4116 upd.set = sta_flags_nl80211(flags_or);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004117 if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
4118 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004119
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004120 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
4121fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004122 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004123 return -ENOBUFS;
4124}
4125
4126
4127static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
4128 struct wpa_driver_associate_params *params)
4129{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004130 enum nl80211_iftype nlmode, old_mode;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004131
4132 if (params->p2p) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004133 wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
4134 "group (GO)");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004135 nlmode = NL80211_IFTYPE_P2P_GO;
4136 } else
4137 nlmode = NL80211_IFTYPE_AP;
4138
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004139 old_mode = drv->nlmode;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004140 if (wpa_driver_nl80211_set_mode(drv->first_bss, nlmode)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004141 nl80211_remove_monitor_interface(drv);
4142 return -1;
4143 }
4144
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004145 if (nl80211_set_channel(drv->first_bss, &params->freq, 0)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004146 if (old_mode != nlmode)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004147 wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004148 nl80211_remove_monitor_interface(drv);
4149 return -1;
4150 }
4151
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152 return 0;
4153}
4154
4155
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004156static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
4157 int reset_mode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004158{
4159 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004160 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004161
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004162 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004163 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004164 if (ret) {
4165 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
4166 "(%s)", ret, strerror(-ret));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004167 } else {
4168 wpa_printf(MSG_DEBUG,
4169 "nl80211: Leave IBSS request sent successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004170 }
4171
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004172 if (reset_mode &&
4173 wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt56052862013-10-04 10:23:25 -07004174 NL80211_IFTYPE_STATION)) {
4175 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
4176 "station mode");
4177 }
4178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004179 return ret;
4180}
4181
4182
4183static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
4184 struct wpa_driver_associate_params *params)
4185{
4186 struct nl_msg *msg;
4187 int ret = -1;
4188 int count = 0;
4189
4190 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
4191
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004192 if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, &params->freq)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004193 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
4194 "IBSS mode");
4195 return -1;
4196 }
4197
4198retry:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004199 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_IBSS)) ||
4200 params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
4201 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004202
4203 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
4204 params->ssid, params->ssid_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004205 if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
4206 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004207 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
4208 drv->ssid_len = params->ssid_len;
4209
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004210 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq);
4211 wpa_printf(MSG_DEBUG, " * ht_enabled=%d", params->freq.ht_enabled);
4212 wpa_printf(MSG_DEBUG, " * sec_channel_offset=%d",
4213 params->freq.sec_channel_offset);
4214 wpa_printf(MSG_DEBUG, " * vht_enabled=%d", params->freq.vht_enabled);
4215 wpa_printf(MSG_DEBUG, " * center_freq1=%d", params->freq.center_freq1);
4216 wpa_printf(MSG_DEBUG, " * center_freq2=%d", params->freq.center_freq2);
4217 wpa_printf(MSG_DEBUG, " * bandwidth=%d", params->freq.bandwidth);
4218 if (nl80211_put_freq_params(msg, &params->freq) < 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004219 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004220
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004221 if (params->beacon_int > 0) {
4222 wpa_printf(MSG_DEBUG, " * beacon_int=%d", params->beacon_int);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004223 if (nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL,
4224 params->beacon_int))
4225 goto fail;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004226 }
4227
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004228 ret = nl80211_set_conn_keys(params, msg);
4229 if (ret)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004230 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004231
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004232 if (params->bssid && params->fixed_bssid) {
4233 wpa_printf(MSG_DEBUG, " * BSSID=" MACSTR,
4234 MAC2STR(params->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004235 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
4236 goto fail;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004237 }
4238
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004239 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4240 params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4241 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
4242 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004243 wpa_printf(MSG_DEBUG, " * control port");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004244 if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
4245 goto fail;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004246 }
4247
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004248 if (params->wpa_ie) {
4249 wpa_hexdump(MSG_DEBUG,
4250 " * Extra IEs for Beacon/Probe Response frames",
4251 params->wpa_ie, params->wpa_ie_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004252 if (nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len,
4253 params->wpa_ie))
4254 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004255 }
4256
4257 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4258 msg = NULL;
4259 if (ret) {
4260 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
4261 ret, strerror(-ret));
4262 count++;
4263 if (ret == -EALREADY && count == 1) {
4264 wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after "
4265 "forced leave");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004266 nl80211_leave_ibss(drv, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004267 nlmsg_free(msg);
4268 goto retry;
4269 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004270 } else {
4271 wpa_printf(MSG_DEBUG,
4272 "nl80211: Join IBSS request sent successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004273 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004274
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004275fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004276 nlmsg_free(msg);
4277 return ret;
4278}
4279
4280
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004281static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
4282 struct wpa_driver_associate_params *params,
4283 struct nl_msg *msg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004284{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 if (params->bssid) {
4286 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
4287 MAC2STR(params->bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004288 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
4289 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004290 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004291
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004292 if (params->bssid_hint) {
4293 wpa_printf(MSG_DEBUG, " * bssid_hint=" MACSTR,
4294 MAC2STR(params->bssid_hint));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004295 if (nla_put(msg, NL80211_ATTR_MAC_HINT, ETH_ALEN,
4296 params->bssid_hint))
4297 return -1;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004298 }
4299
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004300 if (params->freq.freq) {
4301 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004302 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
4303 params->freq.freq))
4304 return -1;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004305 drv->assoc_freq = params->freq.freq;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004306 } else
4307 drv->assoc_freq = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004308
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004309 if (params->freq_hint) {
4310 wpa_printf(MSG_DEBUG, " * freq_hint=%d", params->freq_hint);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004311 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_HINT,
4312 params->freq_hint))
4313 return -1;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08004314 }
4315
Dmitry Shmidt04949592012-07-19 12:16:46 -07004316 if (params->bg_scan_period >= 0) {
4317 wpa_printf(MSG_DEBUG, " * bg scan period=%d",
4318 params->bg_scan_period);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004319 if (nla_put_u16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
4320 params->bg_scan_period))
4321 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004322 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004323
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004324 if (params->ssid) {
4325 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
4326 params->ssid, params->ssid_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004327 if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len,
4328 params->ssid))
4329 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004330 if (params->ssid_len > sizeof(drv->ssid))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004331 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004332 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
4333 drv->ssid_len = params->ssid_len;
4334 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004335
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004336 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004337 if (params->wpa_ie &&
4338 nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len, params->wpa_ie))
4339 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004340
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004341 if (params->wpa_proto) {
4342 enum nl80211_wpa_versions ver = 0;
4343
4344 if (params->wpa_proto & WPA_PROTO_WPA)
4345 ver |= NL80211_WPA_VERSION_1;
4346 if (params->wpa_proto & WPA_PROTO_RSN)
4347 ver |= NL80211_WPA_VERSION_2;
4348
4349 wpa_printf(MSG_DEBUG, " * WPA Versions 0x%x", ver);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004350 if (nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver))
4351 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004352 }
4353
4354 if (params->pairwise_suite != WPA_CIPHER_NONE) {
4355 u32 cipher = wpa_cipher_to_cipher_suite(params->pairwise_suite);
4356 wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004357 if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
4358 cipher))
4359 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004360 }
4361
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004362 if (params->group_suite == WPA_CIPHER_GTK_NOT_USED &&
4363 !(drv->capa.enc & WPA_DRIVER_CAPA_ENC_GTK_NOT_USED)) {
4364 /*
4365 * This is likely to work even though many drivers do not
4366 * advertise support for operations without GTK.
4367 */
4368 wpa_printf(MSG_DEBUG, " * skip group cipher configuration for GTK_NOT_USED due to missing driver support advertisement");
4369 } else if (params->group_suite != WPA_CIPHER_NONE) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004370 u32 cipher = wpa_cipher_to_cipher_suite(params->group_suite);
4371 wpa_printf(MSG_DEBUG, " * group=0x%x", cipher);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004372 if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher))
4373 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004374 }
4375
4376 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
4377 params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4378 params->key_mgmt_suite == WPA_KEY_MGMT_FT_IEEE8021X ||
4379 params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
Dmitry Shmidt15907092014-03-25 10:42:57 -07004380 params->key_mgmt_suite == WPA_KEY_MGMT_CCKM ||
Dmitry Shmidt3c57b3f2014-05-22 15:13:07 -07004381 params->key_mgmt_suite == WPA_KEY_MGMT_OSEN ||
4382 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004383 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4384 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004385 int mgmt = WLAN_AKM_SUITE_PSK;
4386
4387 switch (params->key_mgmt_suite) {
4388 case WPA_KEY_MGMT_CCKM:
4389 mgmt = WLAN_AKM_SUITE_CCKM;
4390 break;
4391 case WPA_KEY_MGMT_IEEE8021X:
4392 mgmt = WLAN_AKM_SUITE_8021X;
4393 break;
4394 case WPA_KEY_MGMT_FT_IEEE8021X:
4395 mgmt = WLAN_AKM_SUITE_FT_8021X;
4396 break;
4397 case WPA_KEY_MGMT_FT_PSK:
4398 mgmt = WLAN_AKM_SUITE_FT_PSK;
4399 break;
Dmitry Shmidt3c57b3f2014-05-22 15:13:07 -07004400 case WPA_KEY_MGMT_IEEE8021X_SHA256:
4401 mgmt = WLAN_AKM_SUITE_8021X_SHA256;
4402 break;
4403 case WPA_KEY_MGMT_PSK_SHA256:
4404 mgmt = WLAN_AKM_SUITE_PSK_SHA256;
4405 break;
Dmitry Shmidt15907092014-03-25 10:42:57 -07004406 case WPA_KEY_MGMT_OSEN:
4407 mgmt = WLAN_AKM_SUITE_OSEN;
4408 break;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004409 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
4410 mgmt = WLAN_AKM_SUITE_8021X_SUITE_B;
4411 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004412 case WPA_KEY_MGMT_PSK:
4413 default:
4414 mgmt = WLAN_AKM_SUITE_PSK;
4415 break;
4416 }
Dmitry Shmidt15907092014-03-25 10:42:57 -07004417 wpa_printf(MSG_DEBUG, " * akm=0x%x", mgmt);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004418 if (nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, mgmt))
4419 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004420 }
4421
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004422 if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
4423 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004424
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004425 if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED &&
4426 nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED))
4427 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004428
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004429 if (params->rrm_used) {
4430 u32 drv_rrm_flags = drv->capa.rrm_flags;
4431 if (!(drv_rrm_flags &
4432 WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) ||
4433 !(drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET) ||
4434 nla_put_flag(msg, NL80211_ATTR_USE_RRM))
4435 return -1;
4436 }
4437
4438 if (params->disable_ht && nla_put_flag(msg, NL80211_ATTR_DISABLE_HT))
4439 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004440
4441 if (params->htcaps && params->htcaps_mask) {
4442 int sz = sizeof(struct ieee80211_ht_capabilities);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004443 wpa_hexdump(MSG_DEBUG, " * htcaps", params->htcaps, sz);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004444 wpa_hexdump(MSG_DEBUG, " * htcaps_mask",
4445 params->htcaps_mask, sz);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004446 if (nla_put(msg, NL80211_ATTR_HT_CAPABILITY, sz,
4447 params->htcaps) ||
4448 nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
4449 params->htcaps_mask))
4450 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004451 }
4452
4453#ifdef CONFIG_VHT_OVERRIDES
4454 if (params->disable_vht) {
4455 wpa_printf(MSG_DEBUG, " * VHT disabled");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004456 if (nla_put_flag(msg, NL80211_ATTR_DISABLE_VHT))
4457 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004458 }
4459
4460 if (params->vhtcaps && params->vhtcaps_mask) {
4461 int sz = sizeof(struct ieee80211_vht_capabilities);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004462 wpa_hexdump(MSG_DEBUG, " * vhtcaps", params->vhtcaps, sz);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07004463 wpa_hexdump(MSG_DEBUG, " * vhtcaps_mask",
4464 params->vhtcaps_mask, sz);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004465 if (nla_put(msg, NL80211_ATTR_VHT_CAPABILITY, sz,
4466 params->vhtcaps) ||
4467 nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
4468 params->vhtcaps_mask))
4469 return -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004470 }
4471#endif /* CONFIG_VHT_OVERRIDES */
4472
4473 if (params->p2p)
4474 wpa_printf(MSG_DEBUG, " * P2P group");
4475
4476 return 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004477}
4478
4479
4480static int wpa_driver_nl80211_try_connect(
4481 struct wpa_driver_nl80211_data *drv,
4482 struct wpa_driver_associate_params *params)
4483{
4484 struct nl_msg *msg;
4485 enum nl80211_auth_type type;
4486 int ret;
4487 int algs;
4488
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004489 if (params->req_key_mgmt_offload && params->psk &&
4490 (params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
4491 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
4492 params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
4493 wpa_printf(MSG_DEBUG, "nl80211: Key management set PSK");
4494 ret = issue_key_mgmt_set_key(drv, params->psk, 32);
4495 if (ret)
4496 return ret;
4497 }
4498
4499 wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
4500 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_CONNECT);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004501 if (!msg)
4502 return -1;
4503
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004504 ret = nl80211_connect_common(drv, params, msg);
4505 if (ret)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004506 goto fail;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004507
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004508 algs = 0;
4509 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
4510 algs++;
4511 if (params->auth_alg & WPA_AUTH_ALG_SHARED)
4512 algs++;
4513 if (params->auth_alg & WPA_AUTH_ALG_LEAP)
4514 algs++;
4515 if (algs > 1) {
4516 wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic "
4517 "selection");
4518 goto skip_auth_type;
4519 }
4520
4521 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
4522 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
4523 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
4524 type = NL80211_AUTHTYPE_SHARED_KEY;
4525 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
4526 type = NL80211_AUTHTYPE_NETWORK_EAP;
4527 else if (params->auth_alg & WPA_AUTH_ALG_FT)
4528 type = NL80211_AUTHTYPE_FT;
4529 else
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004530 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004531
4532 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004533 if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type))
4534 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004535
4536skip_auth_type:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004537 ret = nl80211_set_conn_keys(params, msg);
4538 if (ret)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004539 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004540
4541 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4542 msg = NULL;
4543 if (ret) {
4544 wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
4545 "(%s)", ret, strerror(-ret));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004546 } else {
4547 wpa_printf(MSG_DEBUG,
4548 "nl80211: Connect request send successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004549 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004550
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004551fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004552 nlmsg_free(msg);
4553 return ret;
4554
4555}
4556
4557
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004558static int wpa_driver_nl80211_connect(
4559 struct wpa_driver_nl80211_data *drv,
4560 struct wpa_driver_associate_params *params)
4561{
Jithu Jancea7c60b42014-12-03 18:54:40 +05304562 int ret;
4563
4564 /* Store the connection attempted bssid for future use */
4565 if (params->bssid)
4566 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
4567 else
4568 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
4569
4570 ret = wpa_driver_nl80211_try_connect(drv, params);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004571 if (ret == -EALREADY) {
4572 /*
4573 * cfg80211 does not currently accept new connections if
4574 * we are already connected. As a workaround, force
4575 * disconnection and try again.
4576 */
4577 wpa_printf(MSG_DEBUG, "nl80211: Explicitly "
4578 "disconnecting before reassociation "
4579 "attempt");
4580 if (wpa_driver_nl80211_disconnect(
4581 drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
4582 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004583 ret = wpa_driver_nl80211_try_connect(drv, params);
4584 }
4585 return ret;
4586}
4587
4588
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004589static int wpa_driver_nl80211_associate(
4590 void *priv, struct wpa_driver_associate_params *params)
4591{
4592 struct i802_bss *bss = priv;
4593 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004594 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004595 struct nl_msg *msg;
4596
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004597 nl80211_unmask_11b_rates(bss);
4598
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004599 if (params->mode == IEEE80211_MODE_AP)
4600 return wpa_driver_nl80211_ap(drv, params);
4601
4602 if (params->mode == IEEE80211_MODE_IBSS)
4603 return wpa_driver_nl80211_ibss(drv, params);
4604
4605 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004606 enum nl80211_iftype nlmode = params->p2p ?
4607 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
4608
4609 if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004610 return -1;
4611 return wpa_driver_nl80211_connect(drv, params);
4612 }
4613
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004614 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004615
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004616 wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)",
4617 drv->ifindex);
4618 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_ASSOCIATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004619 if (!msg)
4620 return -1;
4621
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004622 ret = nl80211_connect_common(drv, params, msg);
4623 if (ret)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004624 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004625
4626 if (params->prev_bssid) {
4627 wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
4628 MAC2STR(params->prev_bssid));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004629 if (nla_put(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
4630 params->prev_bssid))
4631 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004632 }
4633
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004634 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4635 msg = NULL;
4636 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004637 wpa_dbg(drv->ctx, MSG_DEBUG,
4638 "nl80211: MLME command failed (assoc): ret=%d (%s)",
4639 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004640 nl80211_dump_scan(drv);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004641 } else {
4642 wpa_printf(MSG_DEBUG,
4643 "nl80211: Association request send successfully");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004644 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004645
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004646fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004647 nlmsg_free(msg);
4648 return ret;
4649}
4650
4651
4652static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004653 int ifindex, enum nl80211_iftype mode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004654{
4655 struct nl_msg *msg;
4656 int ret = -ENOBUFS;
4657
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004658 wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)",
4659 ifindex, mode, nl80211_iftype_str(mode));
4660
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004661 msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_SET_INTERFACE);
4662 if (!msg || nla_put_u32(msg, NL80211_ATTR_IFTYPE, mode))
4663 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004664
4665 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004666 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004667 if (!ret)
4668 return 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004669fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004670 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004671 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
4672 " %d (%s)", ifindex, mode, ret, strerror(-ret));
4673 return ret;
4674}
4675
4676
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004677static int wpa_driver_nl80211_set_mode_impl(
4678 struct i802_bss *bss,
4679 enum nl80211_iftype nlmode,
4680 struct hostapd_freq_params *desired_freq_params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004681{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004682 struct wpa_driver_nl80211_data *drv = bss->drv;
4683 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004684 int i;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004685 int was_ap = is_ap_interface(drv->nlmode);
4686 int res;
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004687 int mode_switch_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004688
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004689 mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
4690 if (mode_switch_res && nlmode == nl80211_get_ifmode(bss))
4691 mode_switch_res = 0;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004692
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004693 if (mode_switch_res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004694 drv->nlmode = nlmode;
4695 ret = 0;
4696 goto done;
4697 }
4698
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004699 if (mode_switch_res == -ENODEV)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004700 return -1;
4701
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004702 if (nlmode == drv->nlmode) {
4703 wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
4704 "requested mode - ignore error");
4705 ret = 0;
4706 goto done; /* Already in the requested mode */
4707 }
4708
4709 /* mac80211 doesn't allow mode changes while the device is up, so
4710 * take the device down, try to set the mode again, and bring the
4711 * device back up.
4712 */
4713 wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
4714 "interface down");
4715 for (i = 0; i < 10; i++) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004716 res = i802_set_iface_flags(bss, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004717 if (res == -EACCES || res == -ENODEV)
4718 break;
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004719 if (res != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004720 wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
4721 "interface down");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004722 os_sleep(0, 100000);
4723 continue;
4724 }
4725
4726 /*
4727 * Setting the mode will fail for some drivers if the phy is
4728 * on a frequency that the mode is disallowed in.
4729 */
4730 if (desired_freq_params) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004731 res = nl80211_set_channel(bss, desired_freq_params, 0);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004732 if (res) {
4733 wpa_printf(MSG_DEBUG,
4734 "nl80211: Failed to set frequency on interface");
4735 }
4736 }
4737
4738 /* Try to set the mode again while the interface is down */
4739 mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
4740 if (mode_switch_res == -EBUSY) {
4741 wpa_printf(MSG_DEBUG,
4742 "nl80211: Delaying mode set while interface going down");
4743 os_sleep(0, 100000);
4744 continue;
4745 }
4746 ret = mode_switch_res;
4747 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004748 }
4749
4750 if (!ret) {
4751 wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
4752 "interface is down");
4753 drv->nlmode = nlmode;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004754 drv->ignore_if_down_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004755 }
4756
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004757 /* Bring the interface back up */
4758 res = linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
4759 if (res != 0) {
4760 wpa_printf(MSG_DEBUG,
4761 "nl80211: Failed to set interface up after switching mode");
4762 ret = -1;
4763 }
4764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004765done:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004766 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004767 wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
4768 "from %d failed", nlmode, drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004769 return ret;
4770 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004771
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004772 if (is_p2p_net_interface(nlmode)) {
4773 wpa_printf(MSG_DEBUG,
4774 "nl80211: Interface %s mode change to P2P - disable 11b rates",
4775 bss->ifname);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004776 nl80211_disable_11b_rates(drv, drv->ifindex, 1);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004777 } else if (drv->disabled_11b_rates) {
4778 wpa_printf(MSG_DEBUG,
4779 "nl80211: Interface %s mode changed to non-P2P - re-enable 11b rates",
4780 bss->ifname);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004781 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004782 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004783
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004784 if (is_ap_interface(nlmode)) {
4785 nl80211_mgmt_unsubscribe(bss, "start AP");
4786 /* Setup additional AP mode functionality if needed */
4787 if (nl80211_setup_ap(bss))
4788 return -1;
4789 } else if (was_ap) {
4790 /* Remove additional AP mode functionality */
4791 nl80211_teardown_ap(bss);
4792 } else {
4793 nl80211_mgmt_unsubscribe(bss, "mode change");
4794 }
4795
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004796 if (is_mesh_interface(nlmode) &&
4797 nl80211_mgmt_subscribe_mesh(bss))
4798 return -1;
4799
Dmitry Shmidt04949592012-07-19 12:16:46 -07004800 if (!bss->in_deinit && !is_ap_interface(nlmode) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004801 !is_mesh_interface(nlmode) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004802 nl80211_mgmt_subscribe_non_ap(bss) < 0)
4803 wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
4804 "frame processing - ignore for now");
4805
4806 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004807}
4808
4809
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004810int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
4811 enum nl80211_iftype nlmode)
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004812{
4813 return wpa_driver_nl80211_set_mode_impl(bss, nlmode, NULL);
4814}
4815
4816
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004817static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
4818 struct hostapd_freq_params *freq)
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004819{
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004820 return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004821 freq);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004822}
4823
4824
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004825static int wpa_driver_nl80211_get_capa(void *priv,
4826 struct wpa_driver_capa *capa)
4827{
4828 struct i802_bss *bss = priv;
4829 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07004830
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004831 if (!drv->has_capability)
4832 return -1;
4833 os_memcpy(capa, &drv->capa, sizeof(*capa));
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004834 if (drv->extended_capa && drv->extended_capa_mask) {
4835 capa->extended_capa = drv->extended_capa;
4836 capa->extended_capa_mask = drv->extended_capa_mask;
4837 capa->extended_capa_len = drv->extended_capa_len;
4838 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004839
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004840 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004841}
4842
4843
4844static int wpa_driver_nl80211_set_operstate(void *priv, int state)
4845{
4846 struct i802_bss *bss = priv;
4847 struct wpa_driver_nl80211_data *drv = bss->drv;
4848
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004849 wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)",
4850 bss->ifname, drv->operstate, state,
4851 state ? "UP" : "DORMANT");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004852 drv->operstate = state;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004853 return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004854 state ? IF_OPER_UP : IF_OPER_DORMANT);
4855}
4856
4857
4858static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
4859{
4860 struct i802_bss *bss = priv;
4861 struct wpa_driver_nl80211_data *drv = bss->drv;
4862 struct nl_msg *msg;
4863 struct nl80211_sta_flag_update upd;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004864 int ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004865
4866 if (!drv->associated && is_zero_ether_addr(drv->bssid) && !authorized) {
4867 wpa_printf(MSG_DEBUG, "nl80211: Skip set_supp_port(unauthorized) while not associated");
4868 return 0;
4869 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004870
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07004871 wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
4872 MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
4873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004874 os_memset(&upd, 0, sizeof(upd));
4875 upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);
4876 if (authorized)
4877 upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004878
4879 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
4880 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid) ||
4881 nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) {
4882 nlmsg_free(msg);
4883 return -ENOBUFS;
4884 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004885
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004886 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004887 if (!ret)
4888 return 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004889 wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)",
4890 ret, strerror(-ret));
4891 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004892}
4893
4894
Jouni Malinen75ecf522011-06-27 15:19:46 -07004895/* Set kernel driver on given frequency (MHz) */
4896static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004897{
Jouni Malinen75ecf522011-06-27 15:19:46 -07004898 struct i802_bss *bss = priv;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004899 return nl80211_set_channel(bss, freq, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004900}
4901
4902
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004903static inline int min_int(int a, int b)
4904{
4905 if (a < b)
4906 return a;
4907 return b;
4908}
4909
4910
4911static int get_key_handler(struct nl_msg *msg, void *arg)
4912{
4913 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4914 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4915
4916 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
4917 genlmsg_attrlen(gnlh, 0), NULL);
4918
4919 /*
4920 * TODO: validate the key index and mac address!
4921 * Otherwise, there's a race condition as soon as
4922 * the kernel starts sending key notifications.
4923 */
4924
4925 if (tb[NL80211_ATTR_KEY_SEQ])
4926 memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
4927 min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
4928 return NL_SKIP;
4929}
4930
4931
4932static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
4933 int idx, u8 *seq)
4934{
4935 struct i802_bss *bss = priv;
4936 struct wpa_driver_nl80211_data *drv = bss->drv;
4937 struct nl_msg *msg;
4938
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004939 msg = nl80211_ifindex_msg(drv, if_nametoindex(iface), 0,
4940 NL80211_CMD_GET_KEY);
4941 if (!msg ||
4942 (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
4943 nla_put_u8(msg, NL80211_ATTR_KEY_IDX, idx)) {
4944 nlmsg_free(msg);
4945 return -ENOBUFS;
4946 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004947
4948 memset(seq, 0, 6);
4949
4950 return send_and_recv_msgs(drv, msg, get_key_handler, seq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004951}
4952
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004953
4954static int i802_set_rts(void *priv, int rts)
4955{
4956 struct i802_bss *bss = priv;
4957 struct wpa_driver_nl80211_data *drv = bss->drv;
4958 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004959 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004960 u32 val;
4961
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004962 if (rts >= 2347)
4963 val = (u32) -1;
4964 else
4965 val = rts;
4966
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004967 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) ||
4968 nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val)) {
4969 nlmsg_free(msg);
4970 return -ENOBUFS;
4971 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004972
4973 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4974 if (!ret)
4975 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004976 wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
4977 "%d (%s)", rts, ret, strerror(-ret));
4978 return ret;
4979}
4980
4981
4982static int i802_set_frag(void *priv, int frag)
4983{
4984 struct i802_bss *bss = priv;
4985 struct wpa_driver_nl80211_data *drv = bss->drv;
4986 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004987 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004988 u32 val;
4989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004990 if (frag >= 2346)
4991 val = (u32) -1;
4992 else
4993 val = frag;
4994
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004995 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) ||
4996 nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val)) {
4997 nlmsg_free(msg);
4998 return -ENOBUFS;
4999 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005000
5001 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5002 if (!ret)
5003 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005004 wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
5005 "%d: %d (%s)", frag, ret, strerror(-ret));
5006 return ret;
5007}
5008
5009
5010static int i802_flush(void *priv)
5011{
5012 struct i802_bss *bss = priv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005013 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005014 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005015
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005016 wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
5017 bss->ifname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005018
5019 /*
5020 * XXX: FIX! this needs to flush all VLANs too
5021 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005022 msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION);
5023 res = send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005024 if (res) {
5025 wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
5026 "(%s)", res, strerror(-res));
5027 }
5028 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005029}
5030
5031
5032static int get_sta_handler(struct nl_msg *msg, void *arg)
5033{
5034 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5035 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5036 struct hostap_sta_driver_data *data = arg;
5037 struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
5038 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
5039 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
5040 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
5041 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
5042 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
5043 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03005044 [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005045 };
5046
5047 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5048 genlmsg_attrlen(gnlh, 0), NULL);
5049
5050 /*
5051 * TODO: validate the interface and mac address!
5052 * Otherwise, there's a race condition as soon as
5053 * the kernel starts sending station notifications.
5054 */
5055
5056 if (!tb[NL80211_ATTR_STA_INFO]) {
5057 wpa_printf(MSG_DEBUG, "sta stats missing!");
5058 return NL_SKIP;
5059 }
5060 if (nla_parse_nested(stats, NL80211_STA_INFO_MAX,
5061 tb[NL80211_ATTR_STA_INFO],
5062 stats_policy)) {
5063 wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
5064 return NL_SKIP;
5065 }
5066
5067 if (stats[NL80211_STA_INFO_INACTIVE_TIME])
5068 data->inactive_msec =
5069 nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);
5070 if (stats[NL80211_STA_INFO_RX_BYTES])
5071 data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
5072 if (stats[NL80211_STA_INFO_TX_BYTES])
5073 data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
5074 if (stats[NL80211_STA_INFO_RX_PACKETS])
5075 data->rx_packets =
5076 nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
5077 if (stats[NL80211_STA_INFO_TX_PACKETS])
5078 data->tx_packets =
5079 nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03005080 if (stats[NL80211_STA_INFO_TX_FAILED])
5081 data->tx_retry_failed =
5082 nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005083
5084 return NL_SKIP;
5085}
5086
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005087static int i802_read_sta_data(struct i802_bss *bss,
5088 struct hostap_sta_driver_data *data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005089 const u8 *addr)
5090{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005091 struct nl_msg *msg;
5092
5093 os_memset(data, 0, sizeof(*data));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005094
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005095 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_GET_STATION)) ||
5096 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
5097 nlmsg_free(msg);
5098 return -ENOBUFS;
5099 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005100
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005101 return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005102}
5103
5104
5105static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
5106 int cw_min, int cw_max, int burst_time)
5107{
5108 struct i802_bss *bss = priv;
5109 struct wpa_driver_nl80211_data *drv = bss->drv;
5110 struct nl_msg *msg;
5111 struct nlattr *txq, *params;
5112
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005113 msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005114 if (!msg)
5115 return -1;
5116
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005117 txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);
5118 if (!txq)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005119 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005120
5121 /* We are only sending parameters for a single TXQ at a time */
5122 params = nla_nest_start(msg, 1);
5123 if (!params)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005124 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005125
5126 switch (queue) {
5127 case 0:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005128 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO))
5129 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005130 break;
5131 case 1:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005132 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI))
5133 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005134 break;
5135 case 2:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005136 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE))
5137 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005138 break;
5139 case 3:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005140 if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK))
5141 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005142 break;
5143 }
5144 /* Burst time is configured in units of 0.1 msec and TXOP parameter in
5145 * 32 usec, so need to convert the value here. */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005146 if (nla_put_u16(msg, NL80211_TXQ_ATTR_TXOP,
5147 (burst_time * 100 + 16) / 32) ||
5148 nla_put_u16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min) ||
5149 nla_put_u16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max) ||
5150 nla_put_u8(msg, NL80211_TXQ_ATTR_AIFS, aifs))
5151 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005152
5153 nla_nest_end(msg, params);
5154
5155 nla_nest_end(msg, txq);
5156
5157 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
5158 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005159 msg = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005160fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005161 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005162 return -1;
5163}
5164
5165
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005166static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005167 const char *ifname, int vlan_id)
5168{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005169 struct wpa_driver_nl80211_data *drv = bss->drv;
5170 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005171 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005172
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005173 wpa_printf(MSG_DEBUG, "nl80211: %s[%d]: set_sta_vlan(" MACSTR
5174 ", ifname=%s[%d], vlan_id=%d)",
5175 bss->ifname, if_nametoindex(bss->ifname),
5176 MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005177 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) ||
5178 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
5179 nla_put_u32(msg, NL80211_ATTR_STA_VLAN, if_nametoindex(ifname))) {
5180 nlmsg_free(msg);
5181 return -ENOBUFS;
5182 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005183
5184 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5185 if (ret < 0) {
5186 wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
5187 MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
5188 MAC2STR(addr), ifname, vlan_id, ret,
5189 strerror(-ret));
5190 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005191 return ret;
5192}
5193
5194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005195static int i802_get_inact_sec(void *priv, const u8 *addr)
5196{
5197 struct hostap_sta_driver_data data;
5198 int ret;
5199
5200 data.inactive_msec = (unsigned long) -1;
5201 ret = i802_read_sta_data(priv, &data, addr);
5202 if (ret || data.inactive_msec == (unsigned long) -1)
5203 return -1;
5204 return data.inactive_msec / 1000;
5205}
5206
5207
5208static int i802_sta_clear_stats(void *priv, const u8 *addr)
5209{
5210#if 0
5211 /* TODO */
5212#endif
5213 return 0;
5214}
5215
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005216
5217static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
5218 int reason)
5219{
5220 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005221 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005222 struct ieee80211_mgmt mgmt;
5223
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005224 if (is_mesh_interface(drv->nlmode))
5225 return -1;
5226
Dmitry Shmidt04949592012-07-19 12:16:46 -07005227 if (drv->device_ap_sme)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005228 return wpa_driver_nl80211_sta_remove(bss, addr, 1, reason);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005229
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005230 memset(&mgmt, 0, sizeof(mgmt));
5231 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
5232 WLAN_FC_STYPE_DEAUTH);
5233 memcpy(mgmt.da, addr, ETH_ALEN);
5234 memcpy(mgmt.sa, own_addr, ETH_ALEN);
5235 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
5236 mgmt.u.deauth.reason_code = host_to_le16(reason);
5237 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
5238 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005239 sizeof(mgmt.u.deauth), 0, 0, 0, 0,
5240 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005241}
5242
5243
5244static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
5245 int reason)
5246{
5247 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005248 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005249 struct ieee80211_mgmt mgmt;
5250
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005251 if (is_mesh_interface(drv->nlmode))
5252 return -1;
5253
Dmitry Shmidt04949592012-07-19 12:16:46 -07005254 if (drv->device_ap_sme)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005255 return wpa_driver_nl80211_sta_remove(bss, addr, 0, reason);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005257 memset(&mgmt, 0, sizeof(mgmt));
5258 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
5259 WLAN_FC_STYPE_DISASSOC);
5260 memcpy(mgmt.da, addr, ETH_ALEN);
5261 memcpy(mgmt.sa, own_addr, ETH_ALEN);
5262 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
5263 mgmt.u.disassoc.reason_code = host_to_le16(reason);
5264 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
5265 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005266 sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
5267 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005268}
5269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005270
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005271static void dump_ifidx(struct wpa_driver_nl80211_data *drv)
5272{
5273 char buf[200], *pos, *end;
5274 int i, res;
5275
5276 pos = buf;
5277 end = pos + sizeof(buf);
5278
5279 for (i = 0; i < drv->num_if_indices; i++) {
5280 if (!drv->if_indices[i])
5281 continue;
5282 res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005283 if (os_snprintf_error(end - pos, res))
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005284 break;
5285 pos += res;
5286 }
5287 *pos = '\0';
5288
5289 wpa_printf(MSG_DEBUG, "nl80211: if_indices[%d]:%s",
5290 drv->num_if_indices, buf);
5291}
5292
5293
Jouni Malinen75ecf522011-06-27 15:19:46 -07005294static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
5295{
5296 int i;
5297 int *old;
5298
5299 wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
5300 ifidx);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005301 if (have_ifidx(drv, ifidx)) {
5302 wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
5303 ifidx);
5304 return;
5305 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07005306 for (i = 0; i < drv->num_if_indices; i++) {
5307 if (drv->if_indices[i] == 0) {
5308 drv->if_indices[i] = ifidx;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005309 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07005310 return;
5311 }
5312 }
5313
5314 if (drv->if_indices != drv->default_if_indices)
5315 old = drv->if_indices;
5316 else
5317 old = NULL;
5318
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005319 drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
5320 sizeof(int));
Jouni Malinen75ecf522011-06-27 15:19:46 -07005321 if (!drv->if_indices) {
5322 if (!old)
5323 drv->if_indices = drv->default_if_indices;
5324 else
5325 drv->if_indices = old;
5326 wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
5327 "interfaces");
5328 wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
5329 return;
5330 } else if (!old)
5331 os_memcpy(drv->if_indices, drv->default_if_indices,
5332 sizeof(drv->default_if_indices));
5333 drv->if_indices[drv->num_if_indices] = ifidx;
5334 drv->num_if_indices++;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005335 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07005336}
5337
5338
5339static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
5340{
5341 int i;
5342
5343 for (i = 0; i < drv->num_if_indices; i++) {
5344 if (drv->if_indices[i] == ifidx) {
5345 drv->if_indices[i] = 0;
5346 break;
5347 }
5348 }
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005349 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07005350}
5351
5352
5353static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
5354{
5355 int i;
5356
5357 for (i = 0; i < drv->num_if_indices; i++)
5358 if (drv->if_indices[i] == ifidx)
5359 return 1;
5360
5361 return 0;
5362}
5363
5364
5365static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07005366 const char *bridge_ifname, char *ifname_wds)
Jouni Malinen75ecf522011-06-27 15:19:46 -07005367{
5368 struct i802_bss *bss = priv;
5369 struct wpa_driver_nl80211_data *drv = bss->drv;
5370 char name[IFNAMSIZ + 1];
5371
5372 os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005373 if (ifname_wds)
5374 os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
5375
Jouni Malinen75ecf522011-06-27 15:19:46 -07005376 wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
5377 " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
5378 if (val) {
5379 if (!if_nametoindex(name)) {
5380 if (nl80211_create_iface(drv, name,
5381 NL80211_IFTYPE_AP_VLAN,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005382 bss->addr, 1, NULL, NULL, 0) <
5383 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07005384 return -1;
5385 if (bridge_ifname &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005386 linux_br_add_if(drv->global->ioctl_sock,
5387 bridge_ifname, name) < 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07005388 return -1;
5389 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005390 if (linux_set_iface_flags(drv->global->ioctl_sock, name, 1)) {
5391 wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA "
5392 "interface %s up", name);
5393 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07005394 return i802_set_sta_vlan(priv, addr, name, 0);
5395 } else {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07005396 if (bridge_ifname)
5397 linux_br_del_if(drv->global->ioctl_sock, bridge_ifname,
5398 name);
5399
Jouni Malinen75ecf522011-06-27 15:19:46 -07005400 i802_set_sta_vlan(priv, addr, bss->ifname, 0);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08005401 nl80211_remove_iface(drv, if_nametoindex(name));
5402 return 0;
Jouni Malinen75ecf522011-06-27 15:19:46 -07005403 }
5404}
5405
5406
5407static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
5408{
5409 struct wpa_driver_nl80211_data *drv = eloop_ctx;
5410 struct sockaddr_ll lladdr;
5411 unsigned char buf[3000];
5412 int len;
5413 socklen_t fromlen = sizeof(lladdr);
5414
5415 len = recvfrom(sock, buf, sizeof(buf), 0,
5416 (struct sockaddr *)&lladdr, &fromlen);
5417 if (len < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005418 wpa_printf(MSG_ERROR, "nl80211: EAPOL recv failed: %s",
5419 strerror(errno));
Jouni Malinen75ecf522011-06-27 15:19:46 -07005420 return;
5421 }
5422
5423 if (have_ifidx(drv, lladdr.sll_ifindex))
5424 drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
5425}
5426
5427
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005428static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
5429 struct i802_bss *bss,
5430 const char *brname, const char *ifname)
5431{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005432 int br_ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005433 char in_br[IFNAMSIZ];
5434
5435 os_strlcpy(bss->brname, brname, IFNAMSIZ);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005436 br_ifindex = if_nametoindex(brname);
5437 if (br_ifindex == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005438 /*
5439 * Bridge was configured, but the bridge device does
5440 * not exist. Try to add it now.
5441 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005442 if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005443 wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
5444 "bridge interface %s: %s",
5445 brname, strerror(errno));
5446 return -1;
5447 }
5448 bss->added_bridge = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005449 br_ifindex = if_nametoindex(brname);
5450 add_ifidx(drv, br_ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005451 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005452 bss->br_ifindex = br_ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005453
5454 if (linux_br_get(in_br, ifname) == 0) {
5455 if (os_strcmp(in_br, brname) == 0)
5456 return 0; /* already in the bridge */
5457
5458 wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
5459 "bridge %s", ifname, in_br);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005460 if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
5461 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005462 wpa_printf(MSG_ERROR, "nl80211: Failed to "
5463 "remove interface %s from bridge "
5464 "%s: %s",
5465 ifname, brname, strerror(errno));
5466 return -1;
5467 }
5468 }
5469
5470 wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
5471 ifname, brname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005472 if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005473 wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
5474 "into bridge %s: %s",
5475 ifname, brname, strerror(errno));
5476 return -1;
5477 }
5478 bss->added_if_into_bridge = 1;
5479
5480 return 0;
5481}
5482
5483
5484static void *i802_init(struct hostapd_data *hapd,
5485 struct wpa_init_params *params)
5486{
5487 struct wpa_driver_nl80211_data *drv;
5488 struct i802_bss *bss;
5489 size_t i;
5490 char brname[IFNAMSIZ];
5491 int ifindex, br_ifindex;
5492 int br_added = 0;
5493
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005494 bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
5495 params->global_priv, 1,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005496 params->bssid, params->driver_params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005497 if (bss == NULL)
5498 return NULL;
5499
5500 drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005502 if (linux_br_get(brname, params->ifname) == 0) {
5503 wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
5504 params->ifname, brname);
5505 br_ifindex = if_nametoindex(brname);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005506 os_strlcpy(bss->brname, brname, IFNAMSIZ);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005507 } else {
5508 brname[0] = '\0';
5509 br_ifindex = 0;
5510 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005511 bss->br_ifindex = br_ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005513 for (i = 0; i < params->num_bridge; i++) {
5514 if (params->bridge[i]) {
5515 ifindex = if_nametoindex(params->bridge[i]);
5516 if (ifindex)
5517 add_ifidx(drv, ifindex);
5518 if (ifindex == br_ifindex)
5519 br_added = 1;
5520 }
5521 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005522
5523 /* start listening for EAPOL on the default AP interface */
5524 add_ifidx(drv, drv->ifindex);
5525
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005526 if (params->num_bridge && params->bridge[0]) {
5527 if (i802_check_bridge(drv, bss, params->bridge[0],
5528 params->ifname) < 0)
5529 goto failed;
5530 if (os_strcmp(params->bridge[0], brname) != 0)
5531 br_added = 1;
5532 }
5533
5534 if (!br_added && br_ifindex &&
5535 (params->num_bridge == 0 || !params->bridge[0]))
5536 add_ifidx(drv, br_ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005537
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005538#ifdef CONFIG_LIBNL3_ROUTE
5539 if (bss->added_if_into_bridge) {
5540 drv->rtnl_sk = nl_socket_alloc();
5541 if (drv->rtnl_sk == NULL) {
5542 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
5543 goto failed;
5544 }
5545
5546 if (nl_connect(drv->rtnl_sk, NETLINK_ROUTE)) {
5547 wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
5548 strerror(errno));
5549 goto failed;
5550 }
5551 }
5552#endif /* CONFIG_LIBNL3_ROUTE */
5553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005554 drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
5555 if (drv->eapol_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005556 wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s",
5557 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005558 goto failed;
5559 }
5560
5561 if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
5562 {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005563 wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005564 goto failed;
5565 }
5566
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005567 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
5568 params->own_addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005569 goto failed;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005570 os_memcpy(drv->perm_addr, params->own_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005571
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005572 memcpy(bss->addr, params->own_addr, ETH_ALEN);
5573
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005574 return bss;
5575
5576failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005577 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005578 return NULL;
5579}
5580
5581
5582static void i802_deinit(void *priv)
5583{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005584 struct i802_bss *bss = priv;
5585 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005586}
5587
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005588
5589static enum nl80211_iftype wpa_driver_nl80211_if_type(
5590 enum wpa_driver_if_type type)
5591{
5592 switch (type) {
5593 case WPA_IF_STATION:
5594 return NL80211_IFTYPE_STATION;
5595 case WPA_IF_P2P_CLIENT:
5596 case WPA_IF_P2P_GROUP:
5597 return NL80211_IFTYPE_P2P_CLIENT;
5598 case WPA_IF_AP_VLAN:
5599 return NL80211_IFTYPE_AP_VLAN;
5600 case WPA_IF_AP_BSS:
5601 return NL80211_IFTYPE_AP;
5602 case WPA_IF_P2P_GO:
5603 return NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005604 case WPA_IF_P2P_DEVICE:
5605 return NL80211_IFTYPE_P2P_DEVICE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005606 case WPA_IF_MESH:
5607 return NL80211_IFTYPE_MESH_POINT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005608 }
5609 return -1;
5610}
5611
5612
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005613#if defined(CONFIG_P2P) || defined(CONFIG_MESH)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614
5615static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr)
5616{
5617 struct wpa_driver_nl80211_data *drv;
5618 dl_list_for_each(drv, &global->interfaces,
5619 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005620 if (os_memcmp(addr, drv->first_bss->addr, ETH_ALEN) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005621 return 1;
5622 }
5623 return 0;
5624}
5625
5626
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005627static int nl80211_vif_addr(struct wpa_driver_nl80211_data *drv, u8 *new_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005628{
5629 unsigned int idx;
5630
5631 if (!drv->global)
5632 return -1;
5633
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005634 os_memcpy(new_addr, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005635 for (idx = 0; idx < 64; idx++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005636 new_addr[0] = drv->first_bss->addr[0] | 0x02;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005637 new_addr[0] ^= idx << 2;
5638 if (!nl80211_addr_in_use(drv->global, new_addr))
5639 break;
5640 }
5641 if (idx == 64)
5642 return -1;
5643
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005644 wpa_printf(MSG_DEBUG, "nl80211: Assigned new virtual interface address "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005645 MACSTR, MAC2STR(new_addr));
5646
5647 return 0;
5648}
5649
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005650#endif /* CONFIG_P2P || CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005651
5652
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005653struct wdev_info {
5654 u64 wdev_id;
5655 int wdev_id_set;
5656 u8 macaddr[ETH_ALEN];
5657};
5658
5659static int nl80211_wdev_handler(struct nl_msg *msg, void *arg)
5660{
5661 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5662 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5663 struct wdev_info *wi = arg;
5664
5665 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5666 genlmsg_attrlen(gnlh, 0), NULL);
5667 if (tb[NL80211_ATTR_WDEV]) {
5668 wi->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
5669 wi->wdev_id_set = 1;
5670 }
5671
5672 if (tb[NL80211_ATTR_MAC])
5673 os_memcpy(wi->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
5674 ETH_ALEN);
5675
5676 return NL_SKIP;
5677}
5678
5679
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005680static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
5681 const char *ifname, const u8 *addr,
5682 void *bss_ctx, void **drv_priv,
5683 char *force_ifname, u8 *if_addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005684 const char *bridge, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005685{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005686 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005687 struct i802_bss *bss = priv;
5688 struct wpa_driver_nl80211_data *drv = bss->drv;
5689 int ifidx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005690 int added = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005691
5692 if (addr)
5693 os_memcpy(if_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005694 nlmode = wpa_driver_nl80211_if_type(type);
5695 if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
5696 struct wdev_info p2pdev_info;
5697
5698 os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
5699 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
5700 0, nl80211_wdev_handler,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005701 &p2pdev_info, use_existing);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005702 if (!p2pdev_info.wdev_id_set || ifidx != 0) {
5703 wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s",
5704 ifname);
5705 return -1;
5706 }
5707
5708 drv->global->if_add_wdevid = p2pdev_info.wdev_id;
5709 drv->global->if_add_wdevid_set = p2pdev_info.wdev_id_set;
5710 if (!is_zero_ether_addr(p2pdev_info.macaddr))
5711 os_memcpy(if_addr, p2pdev_info.macaddr, ETH_ALEN);
5712 wpa_printf(MSG_DEBUG, "nl80211: New P2P Device interface %s (0x%llx) created",
5713 ifname,
5714 (long long unsigned int) p2pdev_info.wdev_id);
5715 } else {
5716 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005717 0, NULL, NULL, use_existing);
5718 if (use_existing && ifidx == -ENFILE) {
5719 added = 0;
5720 ifidx = if_nametoindex(ifname);
5721 } else if (ifidx < 0) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005722 return -1;
5723 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005724 }
5725
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005726 if (!addr) {
5727 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
5728 os_memcpy(if_addr, bss->addr, ETH_ALEN);
5729 else if (linux_get_ifhwaddr(drv->global->ioctl_sock,
5730 bss->ifname, if_addr) < 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005731 if (added)
5732 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005733 return -1;
5734 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005735 }
5736
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005737#if defined(CONFIG_P2P) || defined(CONFIG_MESH)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005738 if (!addr &&
5739 (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005740 type == WPA_IF_P2P_GO || type == WPA_IF_MESH)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005741 /* Enforce unique P2P Interface Address */
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005742 u8 new_addr[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005743
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005744 if (linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005745 new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -07005746 if (added)
5747 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005748 return -1;
5749 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005750 if (nl80211_addr_in_use(drv->global, new_addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005751 wpa_printf(MSG_DEBUG, "nl80211: Allocate new address "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005752 "for %s interface", type == WPA_IF_MESH ?
5753 "mesh" : "P2P group");
5754 if (nl80211_vif_addr(drv, new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -07005755 if (added)
5756 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005757 return -1;
5758 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005759 if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005760 new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -07005761 if (added)
5762 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005763 return -1;
5764 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005765 }
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07005766 os_memcpy(if_addr, new_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005767 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005768#endif /* CONFIG_P2P || CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005769
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005770 if (type == WPA_IF_AP_BSS) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005771 struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
5772 if (new_bss == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005773 if (added)
5774 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005775 return -1;
5776 }
5777
5778 if (bridge &&
5779 i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
5780 wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
5781 "interface %s to a bridge %s",
5782 ifname, bridge);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005783 if (added)
5784 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005785 os_free(new_bss);
5786 return -1;
5787 }
5788
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005789 if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
5790 {
Dmitry Shmidt71757432014-06-02 13:50:35 -07005791 if (added)
5792 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005793 os_free(new_bss);
5794 return -1;
5795 }
5796 os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005797 os_memcpy(new_bss->addr, if_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005798 new_bss->ifindex = ifidx;
5799 new_bss->drv = drv;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005800 new_bss->next = drv->first_bss->next;
5801 new_bss->freq = drv->first_bss->freq;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005802 new_bss->ctx = bss_ctx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005803 new_bss->added_if = added;
5804 drv->first_bss->next = new_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005805 if (drv_priv)
5806 *drv_priv = new_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005807 nl80211_init_bss(new_bss);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005808
5809 /* Subscribe management frames for this WPA_IF_AP_BSS */
5810 if (nl80211_setup_ap(new_bss))
5811 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005812 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005813
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005814 if (drv->global)
5815 drv->global->if_add_ifindex = ifidx;
5816
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005817 /*
5818 * Some virtual interfaces need to process EAPOL packets and events on
5819 * the parent interface. This is used mainly with hostapd.
5820 */
5821 if (ifidx > 0 &&
5822 (drv->hostapd ||
5823 nlmode == NL80211_IFTYPE_AP_VLAN ||
5824 nlmode == NL80211_IFTYPE_WDS ||
5825 nlmode == NL80211_IFTYPE_MONITOR))
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005826 add_ifidx(drv, ifidx);
5827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005828 return 0;
5829}
5830
5831
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005832static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005833 enum wpa_driver_if_type type,
5834 const char *ifname)
5835{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005836 struct wpa_driver_nl80211_data *drv = bss->drv;
5837 int ifindex = if_nametoindex(ifname);
5838
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005839 wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d",
5840 __func__, type, ifname, ifindex, bss->added_if);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08005841 if (ifindex > 0 && (bss->added_if || bss->ifindex != ifindex))
Dmitry Shmidt051af732013-10-22 13:52:46 -07005842 nl80211_remove_iface(drv, ifindex);
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07005843 else if (ifindex > 0 && !bss->added_if) {
5844 struct wpa_driver_nl80211_data *drv2;
5845 dl_list_for_each(drv2, &drv->global->interfaces,
5846 struct wpa_driver_nl80211_data, list)
5847 del_ifidx(drv2, ifindex);
5848 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07005849
Dmitry Shmidtaa532512012-09-24 10:35:31 -07005850 if (type != WPA_IF_AP_BSS)
5851 return 0;
5852
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005853 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005854 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
5855 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005856 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
5857 "interface %s from bridge %s: %s",
5858 bss->ifname, bss->brname, strerror(errno));
5859 }
5860 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005861 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005862 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
5863 "bridge %s: %s",
5864 bss->brname, strerror(errno));
5865 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005866
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005867 if (bss != drv->first_bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005868 struct i802_bss *tbss;
5869
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005870 wpa_printf(MSG_DEBUG, "nl80211: Not the first BSS - remove it");
5871 for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005872 if (tbss->next == bss) {
5873 tbss->next = bss->next;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005874 /* Unsubscribe management frames */
5875 nl80211_teardown_ap(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005876 nl80211_destroy_bss(bss);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07005877 if (!bss->added_if)
5878 i802_set_iface_flags(bss, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005879 os_free(bss);
5880 bss = NULL;
5881 break;
5882 }
5883 }
5884 if (bss)
5885 wpa_printf(MSG_INFO, "nl80211: %s - could not find "
5886 "BSS %p in the list", __func__, bss);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005887 } else {
5888 wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
5889 nl80211_teardown_ap(bss);
5890 if (!bss->added_if && !drv->first_bss->next)
5891 wpa_driver_nl80211_del_beacon(drv);
5892 nl80211_destroy_bss(bss);
5893 if (!bss->added_if)
5894 i802_set_iface_flags(bss, 0);
5895 if (drv->first_bss->next) {
5896 drv->first_bss = drv->first_bss->next;
5897 drv->ctx = drv->first_bss->ctx;
5898 os_free(bss);
5899 } else {
5900 wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
5901 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005902 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005903
5904 return 0;
5905}
5906
5907
5908static int cookie_handler(struct nl_msg *msg, void *arg)
5909{
5910 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5911 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5912 u64 *cookie = arg;
5913 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5914 genlmsg_attrlen(gnlh, 0), NULL);
5915 if (tb[NL80211_ATTR_COOKIE])
5916 *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
5917 return NL_SKIP;
5918}
5919
5920
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005921static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005922 unsigned int freq, unsigned int wait,
5923 const u8 *buf, size_t buf_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005924 u64 *cookie_out, int no_cck, int no_ack,
5925 int offchanok)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005926{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005927 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005928 struct nl_msg *msg;
5929 u64 cookie;
5930 int ret = -1;
5931
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005932 wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
Dmitry Shmidt04949592012-07-19 12:16:46 -07005933 "no_ack=%d offchanok=%d",
5934 freq, wait, no_cck, no_ack, offchanok);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005935 wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005936
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005937 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) ||
5938 (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) ||
5939 (wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) ||
5940 (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
5941 drv->test_use_roc_tx) &&
5942 nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) ||
5943 (no_cck && nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE)) ||
5944 (no_ack && nla_put_flag(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK)) ||
5945 nla_put(msg, NL80211_ATTR_FRAME, buf_len, buf))
5946 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005947
5948 cookie = 0;
5949 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
5950 msg = NULL;
5951 if (ret) {
5952 wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07005953 "(%s) (freq=%u wait=%u)", ret, strerror(-ret),
5954 freq, wait);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005955 } else {
5956 wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; "
5957 "cookie 0x%llx", no_ack ? " (no ACK)" : "",
5958 (long long unsigned int) cookie);
5959
5960 if (cookie_out)
5961 *cookie_out = no_ack ? (u64) -1 : cookie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005962 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005963
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005964fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005965 nlmsg_free(msg);
5966 return ret;
5967}
5968
5969
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005970static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
5971 unsigned int freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005972 unsigned int wait_time,
5973 const u8 *dst, const u8 *src,
5974 const u8 *bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005975 const u8 *data, size_t data_len,
5976 int no_cck)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005977{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005978 struct wpa_driver_nl80211_data *drv = bss->drv;
5979 int ret = -1;
5980 u8 *buf;
5981 struct ieee80211_hdr *hdr;
5982
5983 wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005984 "freq=%u MHz wait=%d ms no_cck=%d)",
5985 drv->ifindex, freq, wait_time, no_cck);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005986
5987 buf = os_zalloc(24 + data_len);
5988 if (buf == NULL)
5989 return ret;
5990 os_memcpy(buf + 24, data, data_len);
5991 hdr = (struct ieee80211_hdr *) buf;
5992 hdr->frame_control =
5993 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);
5994 os_memcpy(hdr->addr1, dst, ETH_ALEN);
5995 os_memcpy(hdr->addr2, src, ETH_ALEN);
5996 os_memcpy(hdr->addr3, bssid, ETH_ALEN);
5997
Dmitry Shmidt56052862013-10-04 10:23:25 -07005998 if (is_ap_interface(drv->nlmode) &&
5999 (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
6000 (int) freq == bss->freq || drv->device_ap_sme ||
6001 !drv->use_monitor))
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006002 ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
6003 0, freq, no_cck, 1,
6004 wait_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006005 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006006 ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006007 24 + data_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006008 &drv->send_action_cookie,
6009 no_cck, 0, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006010
6011 os_free(buf);
6012 return ret;
6013}
6014
6015
6016static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
6017{
6018 struct i802_bss *bss = priv;
6019 struct wpa_driver_nl80211_data *drv = bss->drv;
6020 struct nl_msg *msg;
6021 int ret;
6022
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08006023 wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx",
6024 (long long unsigned int) drv->send_action_cookie);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006025 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME_WAIT_CANCEL)) ||
6026 nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie)) {
6027 nlmsg_free(msg);
6028 return;
6029 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006030
6031 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006032 if (ret)
6033 wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
6034 "(%s)", ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006035}
6036
6037
6038static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
6039 unsigned int duration)
6040{
6041 struct i802_bss *bss = priv;
6042 struct wpa_driver_nl80211_data *drv = bss->drv;
6043 struct nl_msg *msg;
6044 int ret;
6045 u64 cookie;
6046
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006047 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REMAIN_ON_CHANNEL)) ||
6048 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
6049 nla_put_u32(msg, NL80211_ATTR_DURATION, duration)) {
6050 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006051 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006052 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006053
6054 cookie = 0;
6055 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
6056 if (ret == 0) {
6057 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
6058 "0x%llx for freq=%u MHz duration=%u",
6059 (long long unsigned int) cookie, freq, duration);
6060 drv->remain_on_chan_cookie = cookie;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006061 drv->pending_remain_on_chan = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006062 return 0;
6063 }
6064 wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel "
6065 "(freq=%d duration=%u): %d (%s)",
6066 freq, duration, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006067 return -1;
6068}
6069
6070
6071static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
6072{
6073 struct i802_bss *bss = priv;
6074 struct wpa_driver_nl80211_data *drv = bss->drv;
6075 struct nl_msg *msg;
6076 int ret;
6077
6078 if (!drv->pending_remain_on_chan) {
6079 wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel "
6080 "to cancel");
6081 return -1;
6082 }
6083
6084 wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie "
6085 "0x%llx",
6086 (long long unsigned int) drv->remain_on_chan_cookie);
6087
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006088 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
6089 if (!msg ||
6090 nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie)) {
6091 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006092 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006093 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006094
6095 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6096 if (ret == 0)
6097 return 0;
6098 wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
6099 "%d (%s)", ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006100 return -1;
6101}
6102
6103
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006104static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006105{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006106 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07006107
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006108 if (!report) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006109 if (bss->nl_preq && drv->device_ap_sme &&
Dmitry Shmidt03658832014-08-13 11:03:49 -07006110 is_ap_interface(drv->nlmode) && !bss->in_deinit &&
6111 !bss->static_ap) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006112 /*
6113 * Do not disable Probe Request reporting that was
6114 * enabled in nl80211_setup_ap().
6115 */
6116 wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of "
6117 "Probe Request reporting nl_preq=%p while "
6118 "in AP mode", bss->nl_preq);
6119 } else if (bss->nl_preq) {
6120 wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
6121 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006122 nl80211_destroy_eloop_handle(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006123 }
6124 return 0;
6125 }
6126
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006127 if (bss->nl_preq) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006128 wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006129 "already on! nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006130 return 0;
6131 }
6132
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006133 bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq");
6134 if (bss->nl_preq == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006135 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006136 wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request "
6137 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006138
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006139 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006140 (WLAN_FC_TYPE_MGMT << 2) |
6141 (WLAN_FC_STYPE_PROBE_REQ << 4),
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006142 NULL, 0) < 0)
6143 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07006144
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006145 nl80211_register_eloop_read(&bss->nl_preq,
6146 wpa_driver_nl80211_event_receive,
6147 bss->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006148
6149 return 0;
6150
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006151 out_err:
6152 nl_destroy_handles(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006153 return -1;
6154}
6155
6156
6157static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
6158 int ifindex, int disabled)
6159{
6160 struct nl_msg *msg;
6161 struct nlattr *bands, *band;
6162 int ret;
6163
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006164 wpa_printf(MSG_DEBUG,
6165 "nl80211: NL80211_CMD_SET_TX_BITRATE_MASK (ifindex=%d %s)",
6166 ifindex, disabled ? "NL80211_TXRATE_LEGACY=OFDM-only" :
6167 "no NL80211_TXRATE_LEGACY constraint");
6168
6169 msg = nl80211_ifindex_msg(drv, ifindex, 0,
6170 NL80211_CMD_SET_TX_BITRATE_MASK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006171 if (!msg)
6172 return -1;
6173
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006174 bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
6175 if (!bands)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006176 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006177
6178 /*
6179 * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything
6180 * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS
6181 * rates. All 5 GHz rates are left enabled.
6182 */
6183 band = nla_nest_start(msg, NL80211_BAND_2GHZ);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006184 if (!band ||
6185 (disabled && nla_put(msg, NL80211_TXRATE_LEGACY, 8,
6186 "\x0c\x12\x18\x24\x30\x48\x60\x6c")))
6187 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006188 nla_nest_end(msg, band);
6189
6190 nla_nest_end(msg, bands);
6191
6192 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006193 if (ret) {
6194 wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
6195 "(%s)", ret, strerror(-ret));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006196 } else
6197 drv->disabled_11b_rates = disabled;
6198
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006199 return ret;
6200
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006201fail:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006202 nlmsg_free(msg);
6203 return -1;
6204}
6205
6206
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006207static int wpa_driver_nl80211_deinit_ap(void *priv)
6208{
6209 struct i802_bss *bss = priv;
6210 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006211 if (!is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006212 return -1;
6213 wpa_driver_nl80211_del_beacon(drv);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006214 bss->beacon_set = 0;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006215
6216 /*
6217 * If the P2P GO interface was dynamically added, then it is
6218 * possible that the interface change to station is not possible.
6219 */
6220 if (drv->nlmode == NL80211_IFTYPE_P2P_GO && bss->if_dynamic)
6221 return 0;
6222
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006223 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006224}
6225
6226
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006227static int wpa_driver_nl80211_stop_ap(void *priv)
6228{
6229 struct i802_bss *bss = priv;
6230 struct wpa_driver_nl80211_data *drv = bss->drv;
6231 if (!is_ap_interface(drv->nlmode))
6232 return -1;
6233 wpa_driver_nl80211_del_beacon(drv);
6234 bss->beacon_set = 0;
6235 return 0;
6236}
6237
6238
Dmitry Shmidt04949592012-07-19 12:16:46 -07006239static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
6240{
6241 struct i802_bss *bss = priv;
6242 struct wpa_driver_nl80211_data *drv = bss->drv;
6243 if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)
6244 return -1;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006245
6246 /*
6247 * If the P2P Client interface was dynamically added, then it is
6248 * possible that the interface change to station is not possible.
6249 */
6250 if (bss->if_dynamic)
6251 return 0;
6252
Dmitry Shmidt04949592012-07-19 12:16:46 -07006253 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
6254}
6255
6256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006257static void wpa_driver_nl80211_resume(void *priv)
6258{
6259 struct i802_bss *bss = priv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006260
6261 if (i802_set_iface_flags(bss, 1))
6262 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006263}
6264
6265
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006266static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
6267{
6268 struct i802_bss *bss = priv;
6269 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006270 struct nl_msg *msg;
6271 struct nlattr *cqm;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006272
6273 wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
6274 "hysteresis=%d", threshold, hysteresis);
6275
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006276 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_CQM)) ||
6277 !(cqm = nla_nest_start(msg, NL80211_ATTR_CQM)) ||
6278 nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold) ||
6279 nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis)) {
6280 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006281 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006282 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006283 nla_nest_end(msg, cqm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006284
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006285 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006286}
6287
6288
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006289static int get_channel_width(struct nl_msg *msg, void *arg)
6290{
6291 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6292 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6293 struct wpa_signal_info *sig_change = arg;
6294
6295 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6296 genlmsg_attrlen(gnlh, 0), NULL);
6297
6298 sig_change->center_frq1 = -1;
6299 sig_change->center_frq2 = -1;
6300 sig_change->chanwidth = CHAN_WIDTH_UNKNOWN;
6301
6302 if (tb[NL80211_ATTR_CHANNEL_WIDTH]) {
6303 sig_change->chanwidth = convert2width(
6304 nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
6305 if (tb[NL80211_ATTR_CENTER_FREQ1])
6306 sig_change->center_frq1 =
6307 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
6308 if (tb[NL80211_ATTR_CENTER_FREQ2])
6309 sig_change->center_frq2 =
6310 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
6311 }
6312
6313 return NL_SKIP;
6314}
6315
6316
6317static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
6318 struct wpa_signal_info *sig)
6319{
6320 struct nl_msg *msg;
6321
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006322 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006323 return send_and_recv_msgs(drv, msg, get_channel_width, sig);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006324}
6325
6326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006327static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
6328{
6329 struct i802_bss *bss = priv;
6330 struct wpa_driver_nl80211_data *drv = bss->drv;
6331 int res;
6332
6333 os_memset(si, 0, sizeof(*si));
6334 res = nl80211_get_link_signal(drv, si);
6335 if (res != 0)
6336 return res;
6337
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006338 res = nl80211_get_channel_width(drv, si);
6339 if (res != 0)
6340 return res;
6341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006342 return nl80211_get_link_noise(drv, si);
6343}
6344
6345
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006346static int wpa_driver_nl80211_shared_freq(void *priv)
6347{
6348 struct i802_bss *bss = priv;
6349 struct wpa_driver_nl80211_data *drv = bss->drv;
6350 struct wpa_driver_nl80211_data *driver;
6351 int freq = 0;
6352
6353 /*
6354 * If the same PHY is in connected state with some other interface,
6355 * then retrieve the assoc freq.
6356 */
6357 wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s",
6358 drv->phyname);
6359
6360 dl_list_for_each(driver, &drv->global->interfaces,
6361 struct wpa_driver_nl80211_data, list) {
6362 if (drv == driver ||
6363 os_strcmp(drv->phyname, driver->phyname) != 0 ||
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006364 !driver->associated)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006365 continue;
6366
6367 wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
6368 MACSTR,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006369 driver->phyname, driver->first_bss->ifname,
6370 MAC2STR(driver->first_bss->addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -07006371 if (is_ap_interface(driver->nlmode))
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006372 freq = driver->first_bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006373 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006374 freq = nl80211_get_assoc_freq(driver);
6375 wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
6376 drv->phyname, freq);
6377 }
6378
6379 if (!freq)
6380 wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
6381 "PHY (%s) in associated state", drv->phyname);
6382
6383 return freq;
6384}
6385
6386
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006387static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
6388 int encrypt)
6389{
6390 struct i802_bss *bss = priv;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006391 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
6392 0, 0, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006393}
6394
6395
6396static int nl80211_set_param(void *priv, const char *param)
6397{
6398 wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
6399 if (param == NULL)
6400 return 0;
6401
6402#ifdef CONFIG_P2P
6403 if (os_strstr(param, "use_p2p_group_interface=1")) {
6404 struct i802_bss *bss = priv;
6405 struct wpa_driver_nl80211_data *drv = bss->drv;
6406
6407 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
6408 "interface");
6409 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
6410 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
6411 }
6412#endif /* CONFIG_P2P */
6413
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006414 if (os_strstr(param, "use_monitor=1")) {
6415 struct i802_bss *bss = priv;
6416 struct wpa_driver_nl80211_data *drv = bss->drv;
6417 drv->use_monitor = 1;
6418 }
6419
6420 if (os_strstr(param, "force_connect_cmd=1")) {
6421 struct i802_bss *bss = priv;
6422 struct wpa_driver_nl80211_data *drv = bss->drv;
6423 drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006424 drv->force_connect_cmd = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006425 }
6426
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08006427 if (os_strstr(param, "no_offchannel_tx=1")) {
6428 struct i802_bss *bss = priv;
6429 struct wpa_driver_nl80211_data *drv = bss->drv;
6430 drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
6431 drv->test_use_roc_tx = 1;
6432 }
6433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006434 return 0;
6435}
6436
6437
6438static void * nl80211_global_init(void)
6439{
6440 struct nl80211_global *global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006441 struct netlink_config *cfg;
6442
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006443 global = os_zalloc(sizeof(*global));
6444 if (global == NULL)
6445 return NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006446 global->ioctl_sock = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006447 dl_list_init(&global->interfaces);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006448 global->if_add_ifindex = -1;
6449
6450 cfg = os_zalloc(sizeof(*cfg));
6451 if (cfg == NULL)
6452 goto err;
6453
6454 cfg->ctx = global;
6455 cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
6456 cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
6457 global->netlink = netlink_init(cfg);
6458 if (global->netlink == NULL) {
6459 os_free(cfg);
6460 goto err;
6461 }
6462
6463 if (wpa_driver_nl80211_init_nl_global(global) < 0)
6464 goto err;
6465
6466 global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
6467 if (global->ioctl_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006468 wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",
6469 strerror(errno));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006470 goto err;
6471 }
6472
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006473 return global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006474
6475err:
6476 nl80211_global_deinit(global);
6477 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006478}
6479
6480
6481static void nl80211_global_deinit(void *priv)
6482{
6483 struct nl80211_global *global = priv;
6484 if (global == NULL)
6485 return;
6486 if (!dl_list_empty(&global->interfaces)) {
6487 wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at "
6488 "nl80211_global_deinit",
6489 dl_list_len(&global->interfaces));
6490 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006491
6492 if (global->netlink)
6493 netlink_deinit(global->netlink);
6494
6495 nl_destroy_handles(&global->nl);
6496
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006497 if (global->nl_event)
6498 nl80211_destroy_eloop_handle(&global->nl_event);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006499
6500 nl_cb_put(global->nl_cb);
6501
6502 if (global->ioctl_sock >= 0)
6503 close(global->ioctl_sock);
6504
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006505 os_free(global);
6506}
6507
6508
6509static const char * nl80211_get_radio_name(void *priv)
6510{
6511 struct i802_bss *bss = priv;
6512 struct wpa_driver_nl80211_data *drv = bss->drv;
6513 return drv->phyname;
6514}
6515
6516
Jouni Malinen75ecf522011-06-27 15:19:46 -07006517static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,
6518 const u8 *pmkid)
6519{
6520 struct nl_msg *msg;
6521
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006522 if (!(msg = nl80211_bss_msg(bss, 0, cmd)) ||
6523 (pmkid && nla_put(msg, NL80211_ATTR_PMKID, 16, pmkid)) ||
6524 (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))) {
6525 nlmsg_free(msg);
6526 return -ENOBUFS;
6527 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07006528
6529 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Jouni Malinen75ecf522011-06-27 15:19:46 -07006530}
6531
6532
6533static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
6534{
6535 struct i802_bss *bss = priv;
6536 wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR, MAC2STR(bssid));
6537 return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);
6538}
6539
6540
6541static int nl80211_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
6542{
6543 struct i802_bss *bss = priv;
6544 wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR,
6545 MAC2STR(bssid));
6546 return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);
6547}
6548
6549
6550static int nl80211_flush_pmkid(void *priv)
6551{
6552 struct i802_bss *bss = priv;
6553 wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs");
6554 return nl80211_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);
6555}
6556
6557
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006558static void clean_survey_results(struct survey_results *survey_results)
6559{
6560 struct freq_survey *survey, *tmp;
6561
6562 if (dl_list_empty(&survey_results->survey_list))
6563 return;
6564
6565 dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
6566 struct freq_survey, list) {
6567 dl_list_del(&survey->list);
6568 os_free(survey);
6569 }
6570}
6571
6572
6573static void add_survey(struct nlattr **sinfo, u32 ifidx,
6574 struct dl_list *survey_list)
6575{
6576 struct freq_survey *survey;
6577
6578 survey = os_zalloc(sizeof(struct freq_survey));
6579 if (!survey)
6580 return;
6581
6582 survey->ifidx = ifidx;
6583 survey->freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
6584 survey->filled = 0;
6585
6586 if (sinfo[NL80211_SURVEY_INFO_NOISE]) {
6587 survey->nf = (int8_t)
6588 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
6589 survey->filled |= SURVEY_HAS_NF;
6590 }
6591
6592 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]) {
6593 survey->channel_time =
6594 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]);
6595 survey->filled |= SURVEY_HAS_CHAN_TIME;
6596 }
6597
6598 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]) {
6599 survey->channel_time_busy =
6600 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]);
6601 survey->filled |= SURVEY_HAS_CHAN_TIME_BUSY;
6602 }
6603
6604 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]) {
6605 survey->channel_time_rx =
6606 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]);
6607 survey->filled |= SURVEY_HAS_CHAN_TIME_RX;
6608 }
6609
6610 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]) {
6611 survey->channel_time_tx =
6612 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]);
6613 survey->filled |= SURVEY_HAS_CHAN_TIME_TX;
6614 }
6615
6616 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)",
6617 survey->freq,
6618 survey->nf,
6619 (unsigned long int) survey->channel_time,
6620 (unsigned long int) survey->channel_time_busy,
6621 (unsigned long int) survey->channel_time_tx,
6622 (unsigned long int) survey->channel_time_rx,
6623 survey->filled);
6624
6625 dl_list_add_tail(survey_list, &survey->list);
6626}
6627
6628
6629static int check_survey_ok(struct nlattr **sinfo, u32 surveyed_freq,
6630 unsigned int freq_filter)
6631{
6632 if (!freq_filter)
6633 return 1;
6634
6635 return freq_filter == surveyed_freq;
6636}
6637
6638
6639static int survey_handler(struct nl_msg *msg, void *arg)
6640{
6641 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6642 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6643 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
6644 struct survey_results *survey_results;
6645 u32 surveyed_freq = 0;
6646 u32 ifidx;
6647
6648 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
6649 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
6650 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
6651 };
6652
6653 survey_results = (struct survey_results *) arg;
6654
6655 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6656 genlmsg_attrlen(gnlh, 0), NULL);
6657
Dmitry Shmidt97672262014-02-03 13:02:54 -08006658 if (!tb[NL80211_ATTR_IFINDEX])
6659 return NL_SKIP;
6660
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006661 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
6662
6663 if (!tb[NL80211_ATTR_SURVEY_INFO])
6664 return NL_SKIP;
6665
6666 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
6667 tb[NL80211_ATTR_SURVEY_INFO],
6668 survey_policy))
6669 return NL_SKIP;
6670
6671 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) {
6672 wpa_printf(MSG_ERROR, "nl80211: Invalid survey data");
6673 return NL_SKIP;
6674 }
6675
6676 surveyed_freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
6677
6678 if (!check_survey_ok(sinfo, surveyed_freq,
6679 survey_results->freq_filter))
6680 return NL_SKIP;
6681
6682 if (survey_results->freq_filter &&
6683 survey_results->freq_filter != surveyed_freq) {
6684 wpa_printf(MSG_EXCESSIVE, "nl80211: Ignoring survey data for freq %d MHz",
6685 surveyed_freq);
6686 return NL_SKIP;
6687 }
6688
6689 add_survey(sinfo, ifidx, &survey_results->survey_list);
6690
6691 return NL_SKIP;
6692}
6693
6694
6695static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
6696{
6697 struct i802_bss *bss = priv;
6698 struct wpa_driver_nl80211_data *drv = bss->drv;
6699 struct nl_msg *msg;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006700 int err;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006701 union wpa_event_data data;
6702 struct survey_results *survey_results;
6703
6704 os_memset(&data, 0, sizeof(data));
6705 survey_results = &data.survey_results;
6706
6707 dl_list_init(&survey_results->survey_list);
6708
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006709 msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006710 if (!msg)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006711 return -ENOBUFS;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006712
6713 if (freq)
6714 data.survey_results.freq_filter = freq;
6715
6716 do {
6717 wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data");
6718 err = send_and_recv_msgs(drv, msg, survey_handler,
6719 survey_results);
6720 } while (err > 0);
6721
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006722 if (err)
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006723 wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006724 else
6725 wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006726
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006727 clean_survey_results(survey_results);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006728 return err;
6729}
6730
6731
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006732static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
6733 const u8 *replay_ctr)
6734{
6735 struct i802_bss *bss = priv;
6736 struct wpa_driver_nl80211_data *drv = bss->drv;
6737 struct nlattr *replay_nested;
6738 struct nl_msg *msg;
6739
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006740 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_REKEY_OFFLOAD)) ||
6741 !(replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA)) ||
6742 nla_put(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek) ||
6743 nla_put(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck) ||
6744 nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
6745 replay_ctr)) {
6746 nl80211_nlmsg_clear(msg);
6747 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006748 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006749 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006750
6751 nla_nest_end(msg, replay_nested);
6752
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006753 send_and_recv_msgs(drv, msg, NULL, (void *) -1);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006754}
6755
6756
6757static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
6758 const u8 *addr, int qos)
6759{
6760 /* send data frame to poll STA and check whether
6761 * this frame is ACKed */
6762 struct {
6763 struct ieee80211_hdr hdr;
6764 u16 qos_ctl;
6765 } STRUCT_PACKED nulldata;
6766 size_t size;
6767
6768 /* Send data frame to poll STA and check whether this frame is ACKed */
6769
6770 os_memset(&nulldata, 0, sizeof(nulldata));
6771
6772 if (qos) {
6773 nulldata.hdr.frame_control =
6774 IEEE80211_FC(WLAN_FC_TYPE_DATA,
6775 WLAN_FC_STYPE_QOS_NULL);
6776 size = sizeof(nulldata);
6777 } else {
6778 nulldata.hdr.frame_control =
6779 IEEE80211_FC(WLAN_FC_TYPE_DATA,
6780 WLAN_FC_STYPE_NULLFUNC);
6781 size = sizeof(struct ieee80211_hdr);
6782 }
6783
6784 nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
6785 os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
6786 os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
6787 os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
6788
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006789 if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
6790 0, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006791 wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
6792 "send poll frame");
6793}
6794
6795static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
6796 int qos)
6797{
6798 struct i802_bss *bss = priv;
6799 struct wpa_driver_nl80211_data *drv = bss->drv;
6800 struct nl_msg *msg;
6801
6802 if (!drv->poll_command_supported) {
6803 nl80211_send_null_frame(bss, own_addr, addr, qos);
6804 return;
6805 }
6806
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006807 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_PROBE_CLIENT)) ||
6808 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
6809 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006810 return;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006811 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006812
6813 send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006814}
6815
6816
6817static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
6818{
6819 struct nl_msg *msg;
6820
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006821 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_POWER_SAVE)) ||
6822 nla_put_u32(msg, NL80211_ATTR_PS_STATE,
6823 enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED)) {
6824 nlmsg_free(msg);
6825 return -ENOBUFS;
6826 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006827 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006828}
6829
6830
6831static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,
6832 int ctwindow)
6833{
6834 struct i802_bss *bss = priv;
6835
6836 wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d "
6837 "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow);
6838
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08006839 if (opp_ps != -1 || ctwindow != -1) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006840#ifdef ANDROID_P2P
6841 wpa_driver_set_p2p_ps(priv, legacy_ps, opp_ps, ctwindow);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08006842#else /* ANDROID_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006843 return -1; /* Not yet supported */
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08006844#endif /* ANDROID_P2P */
6845 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006846
6847 if (legacy_ps == -1)
6848 return 0;
6849 if (legacy_ps != 0 && legacy_ps != 1)
6850 return -1; /* Not yet supported */
6851
6852 return nl80211_set_power_save(bss, legacy_ps);
6853}
6854
6855
Dmitry Shmidt051af732013-10-22 13:52:46 -07006856static int nl80211_start_radar_detection(void *priv,
6857 struct hostapd_freq_params *freq)
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006858{
6859 struct i802_bss *bss = priv;
6860 struct wpa_driver_nl80211_data *drv = bss->drv;
6861 struct nl_msg *msg;
6862 int ret;
6863
Dmitry Shmidt051af732013-10-22 13:52:46 -07006864 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)",
6865 freq->freq, freq->ht_enabled, freq->vht_enabled,
6866 freq->bandwidth, freq->center_freq1, freq->center_freq2);
6867
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006868 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
6869 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar "
6870 "detection");
6871 return -1;
6872 }
6873
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006874 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_RADAR_DETECT)) ||
6875 nl80211_put_freq_params(msg, freq) < 0) {
6876 nlmsg_free(msg);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006877 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006878 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006879
6880 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6881 if (ret == 0)
6882 return 0;
6883 wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
6884 "%d (%s)", ret, strerror(-ret));
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006885 return -1;
6886}
6887
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006888#ifdef CONFIG_TDLS
6889
6890static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
6891 u8 dialog_token, u16 status_code,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07006892 u32 peer_capab, int initiator, const u8 *buf,
6893 size_t len)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006894{
6895 struct i802_bss *bss = priv;
6896 struct wpa_driver_nl80211_data *drv = bss->drv;
6897 struct nl_msg *msg;
6898
6899 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
6900 return -EOPNOTSUPP;
6901
6902 if (!dst)
6903 return -EINVAL;
6904
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006905 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_TDLS_MGMT)) ||
6906 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) ||
6907 nla_put_u8(msg, NL80211_ATTR_TDLS_ACTION, action_code) ||
6908 nla_put_u8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token) ||
6909 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status_code))
6910 goto fail;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006911 if (peer_capab) {
6912 /*
6913 * The internal enum tdls_peer_capability definition is
6914 * currently identical with the nl80211 enum
6915 * nl80211_tdls_peer_capability, so no conversion is needed
6916 * here.
6917 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006918 if (nla_put_u32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY,
6919 peer_capab))
6920 goto fail;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006921 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006922 if ((initiator &&
6923 nla_put_flag(msg, NL80211_ATTR_TDLS_INITIATOR)) ||
6924 nla_put(msg, NL80211_ATTR_IE, len, buf))
6925 goto fail;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006926
6927 return send_and_recv_msgs(drv, msg, NULL, NULL);
6928
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006929fail:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006930 nlmsg_free(msg);
6931 return -ENOBUFS;
6932}
6933
6934
6935static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
6936{
6937 struct i802_bss *bss = priv;
6938 struct wpa_driver_nl80211_data *drv = bss->drv;
6939 struct nl_msg *msg;
6940 enum nl80211_tdls_operation nl80211_oper;
6941
6942 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
6943 return -EOPNOTSUPP;
6944
6945 switch (oper) {
6946 case TDLS_DISCOVERY_REQ:
6947 nl80211_oper = NL80211_TDLS_DISCOVERY_REQ;
6948 break;
6949 case TDLS_SETUP:
6950 nl80211_oper = NL80211_TDLS_SETUP;
6951 break;
6952 case TDLS_TEARDOWN:
6953 nl80211_oper = NL80211_TDLS_TEARDOWN;
6954 break;
6955 case TDLS_ENABLE_LINK:
6956 nl80211_oper = NL80211_TDLS_ENABLE_LINK;
6957 break;
6958 case TDLS_DISABLE_LINK:
6959 nl80211_oper = NL80211_TDLS_DISABLE_LINK;
6960 break;
6961 case TDLS_ENABLE:
6962 return 0;
6963 case TDLS_DISABLE:
6964 return 0;
6965 default:
6966 return -EINVAL;
6967 }
6968
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006969 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_TDLS_OPER)) ||
6970 nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper) ||
6971 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) {
6972 nlmsg_free(msg);
6973 return -ENOBUFS;
6974 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006975
6976 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006977}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006978
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006979
6980static int
6981nl80211_tdls_enable_channel_switch(void *priv, const u8 *addr, u8 oper_class,
6982 const struct hostapd_freq_params *params)
6983{
6984 struct i802_bss *bss = priv;
6985 struct wpa_driver_nl80211_data *drv = bss->drv;
6986 struct nl_msg *msg;
6987 int ret = -ENOBUFS;
6988
6989 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) ||
6990 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH))
6991 return -EOPNOTSUPP;
6992
6993 wpa_printf(MSG_DEBUG, "nl80211: Enable TDLS channel switch " MACSTR
6994 " oper_class=%u freq=%u",
6995 MAC2STR(addr), oper_class, params->freq);
6996 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_TDLS_CHANNEL_SWITCH);
6997 if (!msg ||
6998 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
6999 nla_put_u8(msg, NL80211_ATTR_OPER_CLASS, oper_class) ||
7000 (ret = nl80211_put_freq_params(msg, params))) {
7001 nlmsg_free(msg);
7002 wpa_printf(MSG_DEBUG, "nl80211: Could not build TDLS chan switch");
7003 return ret;
7004 }
7005
7006 return send_and_recv_msgs(drv, msg, NULL, NULL);
7007}
7008
7009
7010static int
7011nl80211_tdls_disable_channel_switch(void *priv, const u8 *addr)
7012{
7013 struct i802_bss *bss = priv;
7014 struct wpa_driver_nl80211_data *drv = bss->drv;
7015 struct nl_msg *msg;
7016
7017 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) ||
7018 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH))
7019 return -EOPNOTSUPP;
7020
7021 wpa_printf(MSG_DEBUG, "nl80211: Disable TDLS channel switch " MACSTR,
7022 MAC2STR(addr));
7023 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH);
7024 if (!msg ||
7025 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
7026 nlmsg_free(msg);
7027 wpa_printf(MSG_DEBUG,
7028 "nl80211: Could not build TDLS cancel chan switch");
7029 return -ENOBUFS;
7030 }
7031
7032 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007033}
7034
7035#endif /* CONFIG TDLS */
7036
7037
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007038static int driver_nl80211_set_key(const char *ifname, void *priv,
7039 enum wpa_alg alg, const u8 *addr,
7040 int key_idx, int set_tx,
7041 const u8 *seq, size_t seq_len,
7042 const u8 *key, size_t key_len)
7043{
7044 struct i802_bss *bss = priv;
7045 return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx,
7046 set_tx, seq, seq_len, key, key_len);
7047}
7048
7049
7050static int driver_nl80211_scan2(void *priv,
7051 struct wpa_driver_scan_params *params)
7052{
7053 struct i802_bss *bss = priv;
7054 return wpa_driver_nl80211_scan(bss, params);
7055}
7056
7057
7058static int driver_nl80211_deauthenticate(void *priv, const u8 *addr,
7059 int reason_code)
7060{
7061 struct i802_bss *bss = priv;
7062 return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code);
7063}
7064
7065
7066static int driver_nl80211_authenticate(void *priv,
7067 struct wpa_driver_auth_params *params)
7068{
7069 struct i802_bss *bss = priv;
7070 return wpa_driver_nl80211_authenticate(bss, params);
7071}
7072
7073
7074static void driver_nl80211_deinit(void *priv)
7075{
7076 struct i802_bss *bss = priv;
7077 wpa_driver_nl80211_deinit(bss);
7078}
7079
7080
7081static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
7082 const char *ifname)
7083{
7084 struct i802_bss *bss = priv;
7085 return wpa_driver_nl80211_if_remove(bss, type, ifname);
7086}
7087
7088
7089static int driver_nl80211_send_mlme(void *priv, const u8 *data,
7090 size_t data_len, int noack)
7091{
7092 struct i802_bss *bss = priv;
7093 return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
7094 0, 0, 0, 0);
7095}
7096
7097
7098static int driver_nl80211_sta_remove(void *priv, const u8 *addr)
7099{
7100 struct i802_bss *bss = priv;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007101 return wpa_driver_nl80211_sta_remove(bss, addr, -1, 0);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007102}
7103
7104
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007105static int driver_nl80211_set_sta_vlan(void *priv, const u8 *addr,
7106 const char *ifname, int vlan_id)
7107{
7108 struct i802_bss *bss = priv;
7109 return i802_set_sta_vlan(bss, addr, ifname, vlan_id);
7110}
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007111
7112
7113static int driver_nl80211_read_sta_data(void *priv,
7114 struct hostap_sta_driver_data *data,
7115 const u8 *addr)
7116{
7117 struct i802_bss *bss = priv;
7118 return i802_read_sta_data(bss, data, addr);
7119}
7120
7121
7122static int driver_nl80211_send_action(void *priv, unsigned int freq,
7123 unsigned int wait_time,
7124 const u8 *dst, const u8 *src,
7125 const u8 *bssid,
7126 const u8 *data, size_t data_len,
7127 int no_cck)
7128{
7129 struct i802_bss *bss = priv;
7130 return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src,
7131 bssid, data, data_len, no_cck);
7132}
7133
7134
7135static int driver_nl80211_probe_req_report(void *priv, int report)
7136{
7137 struct i802_bss *bss = priv;
7138 return wpa_driver_nl80211_probe_req_report(bss, report);
7139}
7140
7141
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007142static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
7143 const u8 *ies, size_t ies_len)
7144{
7145 int ret;
7146 struct nl_msg *msg;
7147 struct i802_bss *bss = priv;
7148 struct wpa_driver_nl80211_data *drv = bss->drv;
7149 u16 mdid = WPA_GET_LE16(md);
7150
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007151 wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007152 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_UPDATE_FT_IES)) ||
7153 nla_put(msg, NL80211_ATTR_IE, ies_len, ies) ||
7154 nla_put_u16(msg, NL80211_ATTR_MDID, mdid)) {
7155 nlmsg_free(msg);
7156 return -ENOBUFS;
7157 }
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007158
7159 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7160 if (ret) {
7161 wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
7162 "err=%d (%s)", ret, strerror(-ret));
7163 }
7164
7165 return ret;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007166}
7167
7168
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007169const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
7170{
7171 struct i802_bss *bss = priv;
7172 struct wpa_driver_nl80211_data *drv = bss->drv;
7173
7174 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE)
7175 return NULL;
7176
7177 return bss->addr;
7178}
7179
7180
Dmitry Shmidt56052862013-10-04 10:23:25 -07007181static const char * scan_state_str(enum scan_states scan_state)
7182{
7183 switch (scan_state) {
7184 case NO_SCAN:
7185 return "NO_SCAN";
7186 case SCAN_REQUESTED:
7187 return "SCAN_REQUESTED";
7188 case SCAN_STARTED:
7189 return "SCAN_STARTED";
7190 case SCAN_COMPLETED:
7191 return "SCAN_COMPLETED";
7192 case SCAN_ABORTED:
7193 return "SCAN_ABORTED";
7194 case SCHED_SCAN_STARTED:
7195 return "SCHED_SCAN_STARTED";
7196 case SCHED_SCAN_STOPPED:
7197 return "SCHED_SCAN_STOPPED";
7198 case SCHED_SCAN_RESULTS:
7199 return "SCHED_SCAN_RESULTS";
7200 }
7201
7202 return "??";
7203}
7204
7205
7206static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
7207{
7208 struct i802_bss *bss = priv;
7209 struct wpa_driver_nl80211_data *drv = bss->drv;
7210 int res;
7211 char *pos, *end;
7212
7213 pos = buf;
7214 end = buf + buflen;
7215
7216 res = os_snprintf(pos, end - pos,
7217 "ifindex=%d\n"
7218 "ifname=%s\n"
7219 "brname=%s\n"
7220 "addr=" MACSTR "\n"
7221 "freq=%d\n"
7222 "%s%s%s%s%s",
7223 bss->ifindex,
7224 bss->ifname,
7225 bss->brname,
7226 MAC2STR(bss->addr),
7227 bss->freq,
7228 bss->beacon_set ? "beacon_set=1\n" : "",
7229 bss->added_if_into_bridge ?
7230 "added_if_into_bridge=1\n" : "",
7231 bss->added_bridge ? "added_bridge=1\n" : "",
7232 bss->in_deinit ? "in_deinit=1\n" : "",
7233 bss->if_dynamic ? "if_dynamic=1\n" : "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007234 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt56052862013-10-04 10:23:25 -07007235 return pos - buf;
7236 pos += res;
7237
7238 if (bss->wdev_id_set) {
7239 res = os_snprintf(pos, end - pos, "wdev_id=%llu\n",
7240 (unsigned long long) bss->wdev_id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007241 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt56052862013-10-04 10:23:25 -07007242 return pos - buf;
7243 pos += res;
7244 }
7245
7246 res = os_snprintf(pos, end - pos,
7247 "phyname=%s\n"
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07007248 "perm_addr=" MACSTR "\n"
Dmitry Shmidt56052862013-10-04 10:23:25 -07007249 "drv_ifindex=%d\n"
7250 "operstate=%d\n"
7251 "scan_state=%s\n"
7252 "auth_bssid=" MACSTR "\n"
7253 "auth_attempt_bssid=" MACSTR "\n"
7254 "bssid=" MACSTR "\n"
7255 "prev_bssid=" MACSTR "\n"
7256 "associated=%d\n"
7257 "assoc_freq=%u\n"
7258 "monitor_sock=%d\n"
7259 "monitor_ifidx=%d\n"
7260 "monitor_refcount=%d\n"
7261 "last_mgmt_freq=%u\n"
7262 "eapol_tx_sock=%d\n"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007263 "%s%s%s%s%s%s%s%s%s%s%s%s%s",
Dmitry Shmidt56052862013-10-04 10:23:25 -07007264 drv->phyname,
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07007265 MAC2STR(drv->perm_addr),
Dmitry Shmidt56052862013-10-04 10:23:25 -07007266 drv->ifindex,
7267 drv->operstate,
7268 scan_state_str(drv->scan_state),
7269 MAC2STR(drv->auth_bssid),
7270 MAC2STR(drv->auth_attempt_bssid),
7271 MAC2STR(drv->bssid),
7272 MAC2STR(drv->prev_bssid),
7273 drv->associated,
7274 drv->assoc_freq,
7275 drv->monitor_sock,
7276 drv->monitor_ifidx,
7277 drv->monitor_refcount,
7278 drv->last_mgmt_freq,
7279 drv->eapol_tx_sock,
7280 drv->ignore_if_down_event ?
7281 "ignore_if_down_event=1\n" : "",
7282 drv->scan_complete_events ?
7283 "scan_complete_events=1\n" : "",
7284 drv->disabled_11b_rates ?
7285 "disabled_11b_rates=1\n" : "",
7286 drv->pending_remain_on_chan ?
7287 "pending_remain_on_chan=1\n" : "",
7288 drv->in_interface_list ? "in_interface_list=1\n" : "",
7289 drv->device_ap_sme ? "device_ap_sme=1\n" : "",
7290 drv->poll_command_supported ?
7291 "poll_command_supported=1\n" : "",
7292 drv->data_tx_status ? "data_tx_status=1\n" : "",
7293 drv->scan_for_auth ? "scan_for_auth=1\n" : "",
7294 drv->retry_auth ? "retry_auth=1\n" : "",
7295 drv->use_monitor ? "use_monitor=1\n" : "",
7296 drv->ignore_next_local_disconnect ?
7297 "ignore_next_local_disconnect=1\n" : "",
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07007298 drv->ignore_next_local_deauth ?
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007299 "ignore_next_local_deauth=1\n" : "");
7300 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt56052862013-10-04 10:23:25 -07007301 return pos - buf;
7302 pos += res;
7303
7304 if (drv->has_capability) {
7305 res = os_snprintf(pos, end - pos,
7306 "capa.key_mgmt=0x%x\n"
7307 "capa.enc=0x%x\n"
7308 "capa.auth=0x%x\n"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007309 "capa.flags=0x%llx\n"
7310 "capa.rrm_flags=0x%x\n"
Dmitry Shmidt56052862013-10-04 10:23:25 -07007311 "capa.max_scan_ssids=%d\n"
7312 "capa.max_sched_scan_ssids=%d\n"
7313 "capa.sched_scan_supported=%d\n"
7314 "capa.max_match_sets=%d\n"
7315 "capa.max_remain_on_chan=%u\n"
7316 "capa.max_stations=%u\n"
7317 "capa.probe_resp_offloads=0x%x\n"
7318 "capa.max_acl_mac_addrs=%u\n"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007319 "capa.num_multichan_concurrent=%u\n"
7320 "capa.mac_addr_rand_sched_scan_supported=%d\n"
7321 "capa.mac_addr_rand_scan_supported=%d\n",
Dmitry Shmidt56052862013-10-04 10:23:25 -07007322 drv->capa.key_mgmt,
7323 drv->capa.enc,
7324 drv->capa.auth,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007325 (unsigned long long) drv->capa.flags,
7326 drv->capa.rrm_flags,
Dmitry Shmidt56052862013-10-04 10:23:25 -07007327 drv->capa.max_scan_ssids,
7328 drv->capa.max_sched_scan_ssids,
7329 drv->capa.sched_scan_supported,
7330 drv->capa.max_match_sets,
7331 drv->capa.max_remain_on_chan,
7332 drv->capa.max_stations,
7333 drv->capa.probe_resp_offloads,
7334 drv->capa.max_acl_mac_addrs,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007335 drv->capa.num_multichan_concurrent,
7336 drv->capa.mac_addr_rand_sched_scan_supported,
7337 drv->capa.mac_addr_rand_scan_supported);
7338 if (os_snprintf_error(end - pos, res))
Dmitry Shmidt56052862013-10-04 10:23:25 -07007339 return pos - buf;
7340 pos += res;
7341 }
7342
7343 return pos - buf;
7344}
7345
7346
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007347static int set_beacon_data(struct nl_msg *msg, struct beacon_data *settings)
7348{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007349 if ((settings->head &&
7350 nla_put(msg, NL80211_ATTR_BEACON_HEAD,
7351 settings->head_len, settings->head)) ||
7352 (settings->tail &&
7353 nla_put(msg, NL80211_ATTR_BEACON_TAIL,
7354 settings->tail_len, settings->tail)) ||
7355 (settings->beacon_ies &&
7356 nla_put(msg, NL80211_ATTR_IE,
7357 settings->beacon_ies_len, settings->beacon_ies)) ||
7358 (settings->proberesp_ies &&
7359 nla_put(msg, NL80211_ATTR_IE_PROBE_RESP,
7360 settings->proberesp_ies_len, settings->proberesp_ies)) ||
7361 (settings->assocresp_ies &&
7362 nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP,
7363 settings->assocresp_ies_len, settings->assocresp_ies)) ||
7364 (settings->probe_resp &&
7365 nla_put(msg, NL80211_ATTR_PROBE_RESP,
7366 settings->probe_resp_len, settings->probe_resp)))
7367 return -ENOBUFS;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007368
7369 return 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007370}
7371
7372
7373static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
7374{
7375 struct nl_msg *msg;
7376 struct i802_bss *bss = priv;
7377 struct wpa_driver_nl80211_data *drv = bss->drv;
7378 struct nlattr *beacon_csa;
7379 int ret = -ENOBUFS;
7380
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08007381 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 -08007382 settings->cs_count, settings->block_tx,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08007383 settings->freq_params.freq, settings->freq_params.bandwidth,
7384 settings->freq_params.center_freq1,
7385 settings->freq_params.center_freq2);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007386
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007387 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007388 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command");
7389 return -EOPNOTSUPP;
7390 }
7391
7392 if ((drv->nlmode != NL80211_IFTYPE_AP) &&
7393 (drv->nlmode != NL80211_IFTYPE_P2P_GO))
7394 return -EOPNOTSUPP;
7395
7396 /* check settings validity */
7397 if (!settings->beacon_csa.tail ||
7398 ((settings->beacon_csa.tail_len <=
7399 settings->counter_offset_beacon) ||
7400 (settings->beacon_csa.tail[settings->counter_offset_beacon] !=
7401 settings->cs_count)))
7402 return -EINVAL;
7403
7404 if (settings->beacon_csa.probe_resp &&
7405 ((settings->beacon_csa.probe_resp_len <=
7406 settings->counter_offset_presp) ||
7407 (settings->beacon_csa.probe_resp[settings->counter_offset_presp] !=
7408 settings->cs_count)))
7409 return -EINVAL;
7410
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007411 if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_CHANNEL_SWITCH)) ||
7412 nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT,
7413 settings->cs_count) ||
7414 (ret = nl80211_put_freq_params(msg, &settings->freq_params)) ||
7415 (settings->block_tx &&
7416 nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX)))
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007417 goto error;
7418
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007419 /* beacon_after params */
7420 ret = set_beacon_data(msg, &settings->beacon_after);
7421 if (ret)
7422 goto error;
7423
7424 /* beacon_csa params */
7425 beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
7426 if (!beacon_csa)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007427 goto fail;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007428
7429 ret = set_beacon_data(msg, &settings->beacon_csa);
7430 if (ret)
7431 goto error;
7432
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007433 if (nla_put_u16(msg, NL80211_ATTR_CSA_C_OFF_BEACON,
7434 settings->counter_offset_beacon) ||
7435 (settings->beacon_csa.probe_resp &&
7436 nla_put_u16(msg, NL80211_ATTR_CSA_C_OFF_PRESP,
7437 settings->counter_offset_presp)))
7438 goto fail;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007439
7440 nla_nest_end(msg, beacon_csa);
7441 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7442 if (ret) {
7443 wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)",
7444 ret, strerror(-ret));
7445 }
7446 return ret;
7447
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007448fail:
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007449 ret = -ENOBUFS;
7450error:
7451 nlmsg_free(msg);
7452 wpa_printf(MSG_DEBUG, "nl80211: Could not build channel switch request");
7453 return ret;
7454}
7455
7456
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007457static int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr,
7458 u8 user_priority, u16 admitted_time)
7459{
7460 struct i802_bss *bss = priv;
7461 struct wpa_driver_nl80211_data *drv = bss->drv;
7462 struct nl_msg *msg;
7463 int ret;
7464
7465 wpa_printf(MSG_DEBUG,
7466 "nl80211: add_ts request: tsid=%u admitted_time=%u up=%d",
7467 tsid, admitted_time, user_priority);
7468
7469 if (!is_sta_interface(drv->nlmode))
7470 return -ENOTSUP;
7471
7472 msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ADD_TX_TS);
7473 if (!msg ||
7474 nla_put_u8(msg, NL80211_ATTR_TSID, tsid) ||
7475 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
7476 nla_put_u8(msg, NL80211_ATTR_USER_PRIO, user_priority) ||
7477 nla_put_u16(msg, NL80211_ATTR_ADMITTED_TIME, admitted_time)) {
7478 nlmsg_free(msg);
7479 return -ENOBUFS;
7480 }
7481
7482 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7483 if (ret)
7484 wpa_printf(MSG_DEBUG, "nl80211: add_ts failed err=%d (%s)",
7485 ret, strerror(-ret));
7486 return ret;
7487}
7488
7489
7490static int nl80211_del_ts(void *priv, u8 tsid, const u8 *addr)
7491{
7492 struct i802_bss *bss = priv;
7493 struct wpa_driver_nl80211_data *drv = bss->drv;
7494 struct nl_msg *msg;
7495 int ret;
7496
7497 wpa_printf(MSG_DEBUG, "nl80211: del_ts request: tsid=%u", tsid);
7498
7499 if (!is_sta_interface(drv->nlmode))
7500 return -ENOTSUP;
7501
7502 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_TX_TS)) ||
7503 nla_put_u8(msg, NL80211_ATTR_TSID, tsid) ||
7504 nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) {
7505 nlmsg_free(msg);
7506 return -ENOBUFS;
7507 }
7508
7509 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7510 if (ret)
7511 wpa_printf(MSG_DEBUG, "nl80211: del_ts failed err=%d (%s)",
7512 ret, strerror(-ret));
7513 return ret;
7514}
7515
7516
Dmitry Shmidta38abf92014-03-06 13:38:44 -08007517#ifdef CONFIG_TESTING_OPTIONS
7518static int cmd_reply_handler(struct nl_msg *msg, void *arg)
7519{
7520 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7521 struct wpabuf *buf = arg;
7522
7523 if (!buf)
7524 return NL_SKIP;
7525
7526 if ((size_t) genlmsg_attrlen(gnlh, 0) > wpabuf_tailroom(buf)) {
7527 wpa_printf(MSG_INFO, "nl80211: insufficient buffer space for reply");
7528 return NL_SKIP;
7529 }
7530
7531 wpabuf_put_data(buf, genlmsg_attrdata(gnlh, 0),
7532 genlmsg_attrlen(gnlh, 0));
7533
7534 return NL_SKIP;
7535}
7536#endif /* CONFIG_TESTING_OPTIONS */
7537
7538
7539static int vendor_reply_handler(struct nl_msg *msg, void *arg)
7540{
7541 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7542 struct nlattr *nl_vendor_reply, *nl;
7543 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7544 struct wpabuf *buf = arg;
7545 int rem;
7546
7547 if (!buf)
7548 return NL_SKIP;
7549
7550 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7551 genlmsg_attrlen(gnlh, 0), NULL);
7552 nl_vendor_reply = tb[NL80211_ATTR_VENDOR_DATA];
7553
7554 if (!nl_vendor_reply)
7555 return NL_SKIP;
7556
7557 if ((size_t) nla_len(nl_vendor_reply) > wpabuf_tailroom(buf)) {
7558 wpa_printf(MSG_INFO, "nl80211: Vendor command: insufficient buffer space for reply");
7559 return NL_SKIP;
7560 }
7561
7562 nla_for_each_nested(nl, nl_vendor_reply, rem) {
7563 wpabuf_put_data(buf, nla_data(nl), nla_len(nl));
7564 }
7565
7566 return NL_SKIP;
7567}
7568
7569
7570static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
7571 unsigned int subcmd, const u8 *data,
7572 size_t data_len, struct wpabuf *buf)
7573{
7574 struct i802_bss *bss = priv;
7575 struct wpa_driver_nl80211_data *drv = bss->drv;
7576 struct nl_msg *msg;
7577 int ret;
7578
Dmitry Shmidta38abf92014-03-06 13:38:44 -08007579#ifdef CONFIG_TESTING_OPTIONS
7580 if (vendor_id == 0xffffffff) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007581 msg = nlmsg_alloc();
7582 if (!msg)
7583 return -ENOMEM;
7584
Dmitry Shmidta38abf92014-03-06 13:38:44 -08007585 nl80211_cmd(drv, msg, 0, subcmd);
7586 if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) <
7587 0)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007588 goto fail;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08007589 ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf);
7590 if (ret)
7591 wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
7592 ret);
7593 return ret;
7594 }
7595#endif /* CONFIG_TESTING_OPTIONS */
7596
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007597 if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_VENDOR)) ||
7598 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, vendor_id) ||
7599 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd) ||
7600 (data &&
7601 nla_put(msg, NL80211_ATTR_VENDOR_DATA, data_len, data)))
7602 goto fail;
Dmitry Shmidta38abf92014-03-06 13:38:44 -08007603
7604 ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf);
7605 if (ret)
7606 wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d",
7607 ret);
7608 return ret;
7609
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007610fail:
Dmitry Shmidta38abf92014-03-06 13:38:44 -08007611 nlmsg_free(msg);
7612 return -ENOBUFS;
7613}
7614
7615
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007616static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set,
7617 u8 qos_map_set_len)
7618{
7619 struct i802_bss *bss = priv;
7620 struct wpa_driver_nl80211_data *drv = bss->drv;
7621 struct nl_msg *msg;
7622 int ret;
7623
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007624 wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map",
7625 qos_map_set, qos_map_set_len);
7626
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007627 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_QOS_MAP)) ||
7628 nla_put(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set)) {
7629 nlmsg_free(msg);
7630 return -ENOBUFS;
7631 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007632
7633 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7634 if (ret)
7635 wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed");
7636
7637 return ret;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007638}
7639
7640
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007641static int nl80211_set_wowlan(void *priv,
7642 const struct wowlan_triggers *triggers)
7643{
7644 struct i802_bss *bss = priv;
7645 struct wpa_driver_nl80211_data *drv = bss->drv;
7646 struct nl_msg *msg;
7647 struct nlattr *wowlan_triggers;
7648 int ret;
7649
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007650 wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan");
7651
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007652 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WOWLAN)) ||
7653 !(wowlan_triggers = nla_nest_start(msg,
7654 NL80211_ATTR_WOWLAN_TRIGGERS)) ||
7655 (triggers->any &&
7656 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||
7657 (triggers->disconnect &&
7658 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||
7659 (triggers->magic_pkt &&
7660 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||
7661 (triggers->gtk_rekey_failure &&
7662 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||
7663 (triggers->eap_identity_req &&
7664 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||
7665 (triggers->four_way_handshake &&
7666 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||
7667 (triggers->rfkill_release &&
7668 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) {
7669 nlmsg_free(msg);
7670 return -ENOBUFS;
7671 }
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007672
7673 nla_nest_end(msg, wowlan_triggers);
7674
7675 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7676 if (ret)
7677 wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed");
7678
7679 return ret;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007680}
7681
7682
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07007683static int nl80211_roaming(void *priv, int allowed, const u8 *bssid)
7684{
7685 struct i802_bss *bss = priv;
7686 struct wpa_driver_nl80211_data *drv = bss->drv;
7687 struct nl_msg *msg;
7688 struct nlattr *params;
7689
7690 wpa_printf(MSG_DEBUG, "nl80211: Roaming policy: allowed=%d", allowed);
7691
7692 if (!drv->roaming_vendor_cmd_avail) {
7693 wpa_printf(MSG_DEBUG,
7694 "nl80211: Ignore roaming policy change since driver does not provide command for setting it");
7695 return -1;
7696 }
7697
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007698 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
7699 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
7700 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
7701 QCA_NL80211_VENDOR_SUBCMD_ROAMING) ||
7702 !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
7703 nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY,
7704 allowed ? QCA_ROAMING_ALLOWED_WITHIN_ESS :
7705 QCA_ROAMING_NOT_ALLOWED) ||
7706 (bssid &&
7707 nla_put(msg, QCA_WLAN_VENDOR_ATTR_MAC_ADDR, ETH_ALEN, bssid))) {
7708 nlmsg_free(msg);
7709 return -1;
7710 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07007711 nla_nest_end(msg, params);
7712
7713 return send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07007714}
7715
7716
7717static int nl80211_set_mac_addr(void *priv, const u8 *addr)
7718{
7719 struct i802_bss *bss = priv;
7720 struct wpa_driver_nl80211_data *drv = bss->drv;
7721 int new_addr = addr != NULL;
7722
7723 if (!addr)
7724 addr = drv->perm_addr;
7725
7726 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0)
7727 return -1;
7728
7729 if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr) < 0)
7730 {
7731 wpa_printf(MSG_DEBUG,
7732 "nl80211: failed to set_mac_addr for %s to " MACSTR,
7733 bss->ifname, MAC2STR(addr));
7734 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
7735 1) < 0) {
7736 wpa_printf(MSG_DEBUG,
7737 "nl80211: Could not restore interface UP after failed set_mac_addr");
7738 }
7739 return -1;
7740 }
7741
7742 wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR,
7743 bss->ifname, MAC2STR(addr));
7744 drv->addr_changed = new_addr;
7745 os_memcpy(bss->addr, addr, ETH_ALEN);
7746
7747 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0)
7748 {
7749 wpa_printf(MSG_DEBUG,
7750 "nl80211: Could not restore interface UP after set_mac_addr");
7751 }
7752
7753 return 0;
7754}
7755
7756
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007757#ifdef CONFIG_MESH
7758
7759static int wpa_driver_nl80211_init_mesh(void *priv)
7760{
7761 if (wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_MESH_POINT)) {
7762 wpa_printf(MSG_INFO,
7763 "nl80211: Failed to set interface into mesh mode");
7764 return -1;
7765 }
7766 return 0;
7767}
7768
7769
7770static int
7771wpa_driver_nl80211_join_mesh(void *priv,
7772 struct wpa_driver_mesh_join_params *params)
7773{
7774 struct i802_bss *bss = priv;
7775 struct wpa_driver_nl80211_data *drv = bss->drv;
7776 struct nl_msg *msg;
7777 struct nlattr *container;
7778 int ret = 0;
7779
7780 wpa_printf(MSG_DEBUG, "nl80211: mesh join (ifindex=%d)", drv->ifindex);
7781 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_MESH);
7782 if (!msg)
7783 goto fail;
7784 if (params->freq) {
7785 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
7786 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq))
7787 goto fail;
7788 }
7789
7790 if (params->ht_mode) {
7791 unsigned int ht_value;
7792 char *ht_mode = "";
7793
7794 switch (params->ht_mode) {
7795 default:
7796 case CHAN_NO_HT:
7797 ht_value = NL80211_CHAN_NO_HT;
7798 ht_mode = "NOHT";
7799 break;
7800 case CHAN_HT20:
7801 ht_value = NL80211_CHAN_HT20;
7802 ht_mode = "HT20";
7803 break;
7804 case CHAN_HT40PLUS:
7805 ht_value = NL80211_CHAN_HT40PLUS;
7806 ht_mode = "HT40+";
7807 break;
7808 case CHAN_HT40MINUS:
7809 ht_value = NL80211_CHAN_HT40MINUS;
7810 ht_mode = "HT40-";
7811 break;
7812 }
7813 wpa_printf(MSG_DEBUG, " * ht_mode=%s", ht_mode);
7814 if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ht_value))
7815 goto fail;
7816 }
7817
7818 if (params->basic_rates) {
7819 u8 rates[NL80211_MAX_SUPP_RATES];
7820 u8 rates_len = 0;
7821 int i;
7822
7823 for (i = 0; i < NL80211_MAX_SUPP_RATES; i++) {
7824 if (params->basic_rates[i] < 0)
7825 break;
7826 rates[rates_len++] = params->basic_rates[i] / 5;
7827 }
7828
7829 if (nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len,
7830 rates))
7831 goto fail;
7832 }
7833
7834 if (params->meshid) {
7835 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
7836 params->meshid, params->meshid_len);
7837 if (nla_put(msg, NL80211_ATTR_MESH_ID, params->meshid_len,
7838 params->meshid))
7839 goto fail;
7840 }
7841
7842 if (params->beacon_int > 0) {
7843 wpa_printf(MSG_DEBUG, " * beacon_int=%d", params->beacon_int);
7844 if (nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL,
7845 params->beacon_int))
7846 goto fail;
7847 }
7848
7849 wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags);
7850
7851 container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP);
7852 if (!container)
7853 goto fail;
7854
7855 if (params->ies) {
7856 wpa_hexdump(MSG_DEBUG, " * IEs", params->ies, params->ie_len);
7857 if (nla_put(msg, NL80211_MESH_SETUP_IE, params->ie_len,
7858 params->ies))
7859 goto fail;
7860 }
7861 /* WPA_DRIVER_MESH_FLAG_OPEN_AUTH is treated as default by nl80211 */
7862 if (params->flags & WPA_DRIVER_MESH_FLAG_SAE_AUTH) {
7863 if (nla_put_u8(msg, NL80211_MESH_SETUP_AUTH_PROTOCOL, 0x1) ||
7864 nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_AUTH))
7865 goto fail;
7866 }
7867 if ((params->flags & WPA_DRIVER_MESH_FLAG_AMPE) &&
7868 nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_AMPE))
7869 goto fail;
7870 if ((params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM) &&
7871 nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_MPM))
7872 goto fail;
7873 nla_nest_end(msg, container);
7874
7875 container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
7876 if (!container)
7877 goto fail;
7878
7879 if (!(params->conf.flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
7880 nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 0))
7881 goto fail;
7882 if ((params->conf.flags & WPA_DRIVER_MESH_FLAG_DRIVER_MPM) &&
7883 nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
7884 params->max_peer_links))
7885 goto fail;
7886 nla_nest_end(msg, container);
7887
7888 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7889 msg = NULL;
7890 if (ret) {
7891 wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)",
7892 ret, strerror(-ret));
7893 goto fail;
7894 }
7895 ret = 0;
7896 bss->freq = params->freq;
7897 wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully");
7898
7899fail:
7900 nlmsg_free(msg);
7901 return ret;
7902}
7903
7904
7905static int wpa_driver_nl80211_leave_mesh(void *priv)
7906{
7907 struct i802_bss *bss = priv;
7908 struct wpa_driver_nl80211_data *drv = bss->drv;
7909 struct nl_msg *msg;
7910 int ret;
7911
7912 wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex);
7913 msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH);
7914 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7915 if (ret) {
7916 wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)",
7917 ret, strerror(-ret));
7918 } else {
7919 wpa_printf(MSG_DEBUG,
7920 "nl80211: mesh leave request send successfully");
7921 }
7922
7923 if (wpa_driver_nl80211_set_mode(drv->first_bss,
7924 NL80211_IFTYPE_STATION)) {
7925 wpa_printf(MSG_INFO,
7926 "nl80211: Failed to set interface into station mode");
7927 }
7928 return ret;
7929}
7930
7931#endif /* CONFIG_MESH */
7932
7933
7934static int wpa_driver_br_add_ip_neigh(void *priv, u8 version,
7935 const u8 *ipaddr, int prefixlen,
7936 const u8 *addr)
7937{
7938#ifdef CONFIG_LIBNL3_ROUTE
7939 struct i802_bss *bss = priv;
7940 struct wpa_driver_nl80211_data *drv = bss->drv;
7941 struct rtnl_neigh *rn;
7942 struct nl_addr *nl_ipaddr = NULL;
7943 struct nl_addr *nl_lladdr = NULL;
7944 int family, addrsize;
7945 int res;
7946
7947 if (!ipaddr || prefixlen == 0 || !addr)
7948 return -EINVAL;
7949
7950 if (bss->br_ifindex == 0) {
7951 wpa_printf(MSG_DEBUG,
7952 "nl80211: bridge must be set before adding an ip neigh to it");
7953 return -1;
7954 }
7955
7956 if (!drv->rtnl_sk) {
7957 wpa_printf(MSG_DEBUG,
7958 "nl80211: nl_sock for NETLINK_ROUTE is not initialized");
7959 return -1;
7960 }
7961
7962 if (version == 4) {
7963 family = AF_INET;
7964 addrsize = 4;
7965 } else if (version == 6) {
7966 family = AF_INET6;
7967 addrsize = 16;
7968 } else {
7969 return -EINVAL;
7970 }
7971
7972 rn = rtnl_neigh_alloc();
7973 if (rn == NULL)
7974 return -ENOMEM;
7975
7976 /* set the destination ip address for neigh */
7977 nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
7978 if (nl_ipaddr == NULL) {
7979 wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
7980 res = -ENOMEM;
7981 goto errout;
7982 }
7983 nl_addr_set_prefixlen(nl_ipaddr, prefixlen);
7984 res = rtnl_neigh_set_dst(rn, nl_ipaddr);
7985 if (res) {
7986 wpa_printf(MSG_DEBUG,
7987 "nl80211: neigh set destination addr failed");
7988 goto errout;
7989 }
7990
7991 /* set the corresponding lladdr for neigh */
7992 nl_lladdr = nl_addr_build(AF_BRIDGE, (u8 *) addr, ETH_ALEN);
7993 if (nl_lladdr == NULL) {
7994 wpa_printf(MSG_DEBUG, "nl80211: neigh set lladdr failed");
7995 res = -ENOMEM;
7996 goto errout;
7997 }
7998 rtnl_neigh_set_lladdr(rn, nl_lladdr);
7999
8000 rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
8001 rtnl_neigh_set_state(rn, NUD_PERMANENT);
8002
8003 res = rtnl_neigh_add(drv->rtnl_sk, rn, NLM_F_CREATE);
8004 if (res) {
8005 wpa_printf(MSG_DEBUG,
8006 "nl80211: Adding bridge ip neigh failed: %s",
8007 strerror(errno));
8008 }
8009errout:
8010 if (nl_lladdr)
8011 nl_addr_put(nl_lladdr);
8012 if (nl_ipaddr)
8013 nl_addr_put(nl_ipaddr);
8014 if (rn)
8015 rtnl_neigh_put(rn);
8016 return res;
8017#else /* CONFIG_LIBNL3_ROUTE */
8018 return -1;
8019#endif /* CONFIG_LIBNL3_ROUTE */
8020}
8021
8022
8023static int wpa_driver_br_delete_ip_neigh(void *priv, u8 version,
8024 const u8 *ipaddr)
8025{
8026#ifdef CONFIG_LIBNL3_ROUTE
8027 struct i802_bss *bss = priv;
8028 struct wpa_driver_nl80211_data *drv = bss->drv;
8029 struct rtnl_neigh *rn;
8030 struct nl_addr *nl_ipaddr;
8031 int family, addrsize;
8032 int res;
8033
8034 if (!ipaddr)
8035 return -EINVAL;
8036
8037 if (version == 4) {
8038 family = AF_INET;
8039 addrsize = 4;
8040 } else if (version == 6) {
8041 family = AF_INET6;
8042 addrsize = 16;
8043 } else {
8044 return -EINVAL;
8045 }
8046
8047 if (bss->br_ifindex == 0) {
8048 wpa_printf(MSG_DEBUG,
8049 "nl80211: bridge must be set to delete an ip neigh");
8050 return -1;
8051 }
8052
8053 if (!drv->rtnl_sk) {
8054 wpa_printf(MSG_DEBUG,
8055 "nl80211: nl_sock for NETLINK_ROUTE is not initialized");
8056 return -1;
8057 }
8058
8059 rn = rtnl_neigh_alloc();
8060 if (rn == NULL)
8061 return -ENOMEM;
8062
8063 /* set the destination ip address for neigh */
8064 nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
8065 if (nl_ipaddr == NULL) {
8066 wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
8067 res = -ENOMEM;
8068 goto errout;
8069 }
8070 res = rtnl_neigh_set_dst(rn, nl_ipaddr);
8071 if (res) {
8072 wpa_printf(MSG_DEBUG,
8073 "nl80211: neigh set destination addr failed");
8074 goto errout;
8075 }
8076
8077 rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
8078
8079 res = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
8080 if (res) {
8081 wpa_printf(MSG_DEBUG,
8082 "nl80211: Deleting bridge ip neigh failed: %s",
8083 strerror(errno));
8084 }
8085errout:
8086 if (nl_ipaddr)
8087 nl_addr_put(nl_ipaddr);
8088 if (rn)
8089 rtnl_neigh_put(rn);
8090 return res;
8091#else /* CONFIG_LIBNL3_ROUTE */
8092 return -1;
8093#endif /* CONFIG_LIBNL3_ROUTE */
8094}
8095
8096
8097static int linux_write_system_file(const char *path, unsigned int val)
8098{
8099 char buf[50];
8100 int fd, len;
8101
8102 len = os_snprintf(buf, sizeof(buf), "%u\n", val);
8103 if (os_snprintf_error(sizeof(buf), len))
8104 return -1;
8105
8106 fd = open(path, O_WRONLY);
8107 if (fd < 0)
8108 return -1;
8109
8110 if (write(fd, buf, len) < 0) {
8111 wpa_printf(MSG_DEBUG,
8112 "nl80211: Failed to write Linux system file: %s with the value of %d",
8113 path, val);
8114 close(fd);
8115 return -1;
8116 }
8117 close(fd);
8118
8119 return 0;
8120}
8121
8122
8123static const char * drv_br_port_attr_str(enum drv_br_port_attr attr)
8124{
8125 switch (attr) {
8126 case DRV_BR_PORT_ATTR_PROXYARP:
8127 return "proxyarp";
8128 case DRV_BR_PORT_ATTR_HAIRPIN_MODE:
8129 return "hairpin_mode";
8130 }
8131
8132 return NULL;
8133}
8134
8135
8136static int wpa_driver_br_port_set_attr(void *priv, enum drv_br_port_attr attr,
8137 unsigned int val)
8138{
8139 struct i802_bss *bss = priv;
8140 char path[128];
8141 const char *attr_txt;
8142
8143 attr_txt = drv_br_port_attr_str(attr);
8144 if (attr_txt == NULL)
8145 return -EINVAL;
8146
8147 os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/%s",
8148 bss->ifname, attr_txt);
8149
8150 if (linux_write_system_file(path, val))
8151 return -1;
8152
8153 return 0;
8154}
8155
8156
8157static const char * drv_br_net_param_str(enum drv_br_net_param param)
8158{
8159 switch (param) {
8160 case DRV_BR_NET_PARAM_GARP_ACCEPT:
8161 return "arp_accept";
8162 }
8163
8164 return NULL;
8165}
8166
8167
8168static int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param,
8169 unsigned int val)
8170{
8171 struct i802_bss *bss = priv;
8172 char path[128];
8173 const char *param_txt;
8174 int ip_version = 4;
8175
8176 param_txt = drv_br_net_param_str(param);
8177 if (param_txt == NULL)
8178 return -EINVAL;
8179
8180 switch (param) {
8181 case DRV_BR_NET_PARAM_GARP_ACCEPT:
8182 ip_version = 4;
8183 break;
8184 default:
8185 return -EINVAL;
8186 }
8187
8188 os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s",
8189 ip_version, bss->brname, param_txt);
8190
8191 if (linux_write_system_file(path, val))
8192 return -1;
8193
8194 return 0;
8195}
8196
8197
8198static int hw_mode_to_qca_acs(enum hostapd_hw_mode hw_mode)
8199{
8200 switch (hw_mode) {
8201 case HOSTAPD_MODE_IEEE80211B:
8202 return QCA_ACS_MODE_IEEE80211B;
8203 case HOSTAPD_MODE_IEEE80211G:
8204 return QCA_ACS_MODE_IEEE80211G;
8205 case HOSTAPD_MODE_IEEE80211A:
8206 return QCA_ACS_MODE_IEEE80211A;
8207 case HOSTAPD_MODE_IEEE80211AD:
8208 return QCA_ACS_MODE_IEEE80211AD;
8209 default:
8210 return -1;
8211 }
8212}
8213
8214
8215static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
8216{
8217 struct i802_bss *bss = priv;
8218 struct wpa_driver_nl80211_data *drv = bss->drv;
8219 struct nl_msg *msg;
8220 struct nlattr *data;
8221 int ret;
8222 int mode;
8223
8224 mode = hw_mode_to_qca_acs(params->hw_mode);
8225 if (mode < 0)
8226 return -1;
8227
8228 if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
8229 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
8230 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
8231 QCA_NL80211_VENDOR_SUBCMD_DO_ACS) ||
8232 !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
8233 nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE, mode) ||
8234 (params->ht_enabled &&
8235 nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED)) ||
8236 (params->ht40_enabled &&
8237 nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED))) {
8238 nlmsg_free(msg);
8239 return -ENOBUFS;
8240 }
8241 nla_nest_end(msg, data);
8242
8243 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8244 if (ret) {
8245 wpa_printf(MSG_DEBUG,
8246 "nl80211: Failed to invoke driver ACS function: %s",
8247 strerror(errno));
8248 }
8249 return ret;
8250}
8251
8252
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008253const struct wpa_driver_ops wpa_driver_nl80211_ops = {
8254 .name = "nl80211",
8255 .desc = "Linux nl80211/cfg80211",
8256 .get_bssid = wpa_driver_nl80211_get_bssid,
8257 .get_ssid = wpa_driver_nl80211_get_ssid,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008258 .set_key = driver_nl80211_set_key,
8259 .scan2 = driver_nl80211_scan2,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008260 .sched_scan = wpa_driver_nl80211_sched_scan,
8261 .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008262 .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008263 .deauthenticate = driver_nl80211_deauthenticate,
8264 .authenticate = driver_nl80211_authenticate,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008265 .associate = wpa_driver_nl80211_associate,
8266 .global_init = nl80211_global_init,
8267 .global_deinit = nl80211_global_deinit,
8268 .init2 = wpa_driver_nl80211_init,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008269 .deinit = driver_nl80211_deinit,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008270 .get_capa = wpa_driver_nl80211_get_capa,
8271 .set_operstate = wpa_driver_nl80211_set_operstate,
8272 .set_supp_port = wpa_driver_nl80211_set_supp_port,
8273 .set_country = wpa_driver_nl80211_set_country,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008274 .get_country = wpa_driver_nl80211_get_country,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008275 .set_ap = wpa_driver_nl80211_set_ap,
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008276 .set_acl = wpa_driver_nl80211_set_acl,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008277 .if_add = wpa_driver_nl80211_if_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008278 .if_remove = driver_nl80211_if_remove,
8279 .send_mlme = driver_nl80211_send_mlme,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008280 .get_hw_feature_data = nl80211_get_hw_feature_data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008281 .sta_add = wpa_driver_nl80211_sta_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008282 .sta_remove = driver_nl80211_sta_remove,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008283 .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
8284 .sta_set_flags = wpa_driver_nl80211_sta_set_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008285 .hapd_init = i802_init,
8286 .hapd_deinit = i802_deinit,
Jouni Malinen75ecf522011-06-27 15:19:46 -07008287 .set_wds_sta = i802_set_wds_sta,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008288 .get_seqnum = i802_get_seqnum,
8289 .flush = i802_flush,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008290 .get_inact_sec = i802_get_inact_sec,
8291 .sta_clear_stats = i802_sta_clear_stats,
8292 .set_rts = i802_set_rts,
8293 .set_frag = i802_set_frag,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008294 .set_tx_queue_params = i802_set_tx_queue_params,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008295 .set_sta_vlan = driver_nl80211_set_sta_vlan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008296 .sta_deauth = i802_sta_deauth,
8297 .sta_disassoc = i802_sta_disassoc,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008298 .read_sta_data = driver_nl80211_read_sta_data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008299 .set_freq = i802_set_freq,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008300 .send_action = driver_nl80211_send_action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008301 .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
8302 .remain_on_channel = wpa_driver_nl80211_remain_on_channel,
8303 .cancel_remain_on_channel =
8304 wpa_driver_nl80211_cancel_remain_on_channel,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008305 .probe_req_report = driver_nl80211_probe_req_report,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008306 .deinit_ap = wpa_driver_nl80211_deinit_ap,
Dmitry Shmidt04949592012-07-19 12:16:46 -07008307 .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008308 .resume = wpa_driver_nl80211_resume,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008309 .signal_monitor = nl80211_signal_monitor,
8310 .signal_poll = nl80211_signal_poll,
8311 .send_frame = nl80211_send_frame,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008312 .shared_freq = wpa_driver_nl80211_shared_freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008313 .set_param = nl80211_set_param,
8314 .get_radio_name = nl80211_get_radio_name,
Jouni Malinen75ecf522011-06-27 15:19:46 -07008315 .add_pmkid = nl80211_add_pmkid,
8316 .remove_pmkid = nl80211_remove_pmkid,
8317 .flush_pmkid = nl80211_flush_pmkid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008318 .set_rekey_info = nl80211_set_rekey_info,
8319 .poll_client = nl80211_poll_client,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008320 .set_p2p_powersave = nl80211_set_p2p_powersave,
Dmitry Shmidtea69e842013-05-13 14:52:28 -07008321 .start_dfs_cac = nl80211_start_radar_detection,
8322 .stop_ap = wpa_driver_nl80211_stop_ap,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008323#ifdef CONFIG_TDLS
8324 .send_tdls_mgmt = nl80211_send_tdls_mgmt,
8325 .tdls_oper = nl80211_tdls_oper,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008326 .tdls_enable_channel_switch = nl80211_tdls_enable_channel_switch,
8327 .tdls_disable_channel_switch = nl80211_tdls_disable_channel_switch,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008328#endif /* CONFIG_TDLS */
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008329 .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008330 .get_mac_addr = wpa_driver_nl80211_get_macaddr,
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07008331 .get_survey = wpa_driver_nl80211_get_survey,
Dmitry Shmidt56052862013-10-04 10:23:25 -07008332 .status = wpa_driver_nl80211_status,
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08008333 .switch_channel = nl80211_switch_channel,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008334#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07008335 .set_noa = wpa_driver_set_p2p_noa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008336 .get_noa = wpa_driver_get_p2p_noa,
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07008337 .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08008338#endif /* ANDROID_P2P */
Dmitry Shmidt738a26e2011-07-07 14:22:14 -07008339#ifdef ANDROID
8340 .driver_cmd = wpa_driver_nl80211_driver_cmd,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08008341#endif /* ANDROID */
Dmitry Shmidta38abf92014-03-06 13:38:44 -08008342 .vendor_cmd = nl80211_vendor_cmd,
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008343 .set_qos_map = nl80211_set_qos_map,
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07008344 .set_wowlan = nl80211_set_wowlan,
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008345 .roaming = nl80211_roaming,
8346 .set_mac_addr = nl80211_set_mac_addr,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008347#ifdef CONFIG_MESH
8348 .init_mesh = wpa_driver_nl80211_init_mesh,
8349 .join_mesh = wpa_driver_nl80211_join_mesh,
8350 .leave_mesh = wpa_driver_nl80211_leave_mesh,
8351#endif /* CONFIG_MESH */
8352 .br_add_ip_neigh = wpa_driver_br_add_ip_neigh,
8353 .br_delete_ip_neigh = wpa_driver_br_delete_ip_neigh,
8354 .br_port_set_attr = wpa_driver_br_port_set_attr,
8355 .br_set_net_param = wpa_driver_br_set_net_param,
8356 .add_tx_ts = nl80211_add_ts,
8357 .del_tx_ts = nl80211_del_ts,
8358 .do_acs = wpa_driver_do_acs,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008359};