18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Driver interaction with Linux nl80211/cfg80211 3807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2004, Instant802 Networks, Inc. 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2006, Devicescape Software, Inc. 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net> 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 10c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/types.h> 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <fcntl.h> 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <net/if.h> 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netlink/genl/genl.h> 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netlink/genl/ctrl.h> 19661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#ifdef CONFIG_LIBNL3_ROUTE 20661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#include <netlink/route/neighbour.h> 21661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#endif /* CONFIG_LIBNL3_ROUTE */ 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <linux/rtnetlink.h> 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netpacket/packet.h> 241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include <linux/errqueue.h> 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 28cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#include "common/qca-vendor.h" 297832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#include "common/qca-vendor-attr.h" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/ieee802_11_common.h" 321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "l2_packet/l2_packet.h" 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "netlink.h" 346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "linux_defines.h" 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "linux_ioctl.h" 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radiotap.h" 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radiotap_iter.h" 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rfkill.h" 396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#include "driver_nl80211.h" 401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifndef CONFIG_LIBNL20 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * libnl 1.1 has a bug, it tries to allocate socket numbers densely 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * but when you free a socket again it will mess up its bitmap and 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and use the wrong number the next time it needs a socket ID. 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Therefore, we wrap the handle alloc/destroy and add our own pid 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * accounting. 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic uint32_t port_bitmap[32] = { 0 }; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct nl_handle *nl80211_handle_alloc(void *cb) 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_handle *handle; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uint32_t pid = getpid() & 0x3FFFFF; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handle = nl_handle_alloc_cb(cb); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 1024; i++) { 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (port_bitmap[i / 32] & (1 << (i % 32))) 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt port_bitmap[i / 32] |= 1 << (i % 32); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pid += i << 22; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_socket_set_local_port(handle, pid); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return handle; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_handle_destroy(struct nl_handle *handle) 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uint32_t port = nl_socket_get_local_port(handle); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt port >>= 22; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt port_bitmap[port / 32] &= ~(1 << (port % 32)); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_handle_destroy(handle); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_LIBNL20 */ 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 855460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#ifdef ANDROID 865460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt/* system/core/libnl_2 does not include nl_socket_set_nonblocking() */ 875460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#undef nl_socket_set_nonblocking 885460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h) 896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 905460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#endif /* ANDROID */ 915460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 925460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt 931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg) 941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl_handle *handle; 961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt handle = nl80211_handle_alloc(cb); 981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (handle == NULL) { 991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " 1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "callbacks (%s)", dbg); 1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (genl_connect(handle)) { 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " 1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "netlink (%s)", dbg); 1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_handle_destroy(handle); 1081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return handle; 1121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nl_destroy_handles(struct nl_handle **handle) 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (*handle == NULL) 1181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_handle_destroy(*handle); 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *handle = NULL; 1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#if __WORDSIZE == 64 12568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define ELOOP_SOCKET_INVALID (intptr_t) 0x8888888888888889ULL 12668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#else 12768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define ELOOP_SOCKET_INVALID (intptr_t) 0x88888889ULL 12868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#endif 12968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 13068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic void nl80211_register_eloop_read(struct nl_handle **handle, 13168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt eloop_sock_handler handler, 13268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt void *eloop_data) 13368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 134807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt#ifdef CONFIG_LIBNL20 135807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt /* 136807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * libnl uses a pretty small buffer (32 kB that gets converted to 64 kB) 137807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * by default. It is possible to hit that limit in some cases where 138807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * operations are blocked, e.g., with a burst of Deauthentication frames 139807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * to hostapd and STA entry deletion. Try to increase the buffer to make 140807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt * this less likely to occur. 141807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt */ 142807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt if (nl_socket_set_buffer_size(*handle, 262144, 0) < 0) { 143807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt wpa_printf(MSG_DEBUG, 144807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt "nl80211: Could not set nl_socket RX buffer size: %s", 145807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt strerror(errno)); 146807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt /* continue anyway with the default (smaller) buffer */ 147807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt } 148807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt#endif /* CONFIG_LIBNL20 */ 149807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt 15068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt nl_socket_set_nonblocking(*handle); 15168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt eloop_register_read_sock(nl_socket_get_fd(*handle), handler, 15268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt eloop_data, *handle); 15368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID); 15468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 15568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 15668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 15768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic void nl80211_destroy_eloop_handle(struct nl_handle **handle) 15868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 15968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID); 16068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt eloop_unregister_read_sock(nl_socket_get_fd(*handle)); 16168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt nl_destroy_handles(handle); 16268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 16368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 16468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 1651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nl80211_global_deinit(void *priv); 1667f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic void nl80211_check_global(struct nl80211_global *global); 1671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1684b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic void wpa_driver_nl80211_deinit(struct i802_bss *bss); 1699ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidtstatic int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, 1709ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt struct hostapd_freq_params *freq); 171d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int 173e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtwpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, 1746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *set_addr, int first, 1756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const char *driver_params); 1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nl80211_send_frame_cmd(struct i802_bss *bss, 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int freq, unsigned int wait, 1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *buf, size_t buf_len, u64 *cookie, 1791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int no_cck, int no_ack, int offchanok); 1804b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, 1814b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt int report); 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); 186738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt 1877832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidtstatic int nl80211_set_channel(struct i802_bss *bss, 1887832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt struct hostapd_freq_params *freq, int set_chan); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, int disabled); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv, 1936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int reset_mode); 1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 195b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic int i802_set_iface_flags(struct i802_bss *bss, int up); 1966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_param(void *priv, const char *param); 19734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 19834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 19904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt/* Converts nl80211_chan_width to a common format */ 2006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtenum chan_width convert2width(int width) 20104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt{ 20204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt switch (width) { 20304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt case NL80211_CHAN_WIDTH_20_NOHT: 20404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return CHAN_WIDTH_20_NOHT; 20504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt case NL80211_CHAN_WIDTH_20: 20604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return CHAN_WIDTH_20; 20704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt case NL80211_CHAN_WIDTH_40: 20804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return CHAN_WIDTH_40; 20904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt case NL80211_CHAN_WIDTH_80: 21004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return CHAN_WIDTH_80; 21104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt case NL80211_CHAN_WIDTH_80P80: 21204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return CHAN_WIDTH_80P80; 21304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt case NL80211_CHAN_WIDTH_160: 21404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return CHAN_WIDTH_160; 21504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt } 21604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return CHAN_WIDTH_UNKNOWN; 21704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt} 21804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 21904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 2206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint is_ap_interface(enum nl80211_iftype nlmode) 2211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2227832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return nlmode == NL80211_IFTYPE_AP || 2237832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt nlmode == NL80211_IFTYPE_P2P_GO; 2241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint is_sta_interface(enum nl80211_iftype nlmode) 2281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2297832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return nlmode == NL80211_IFTYPE_STATION || 2307832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt nlmode == NL80211_IFTYPE_P2P_CLIENT; 2311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 23434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int is_p2p_net_interface(enum nl80211_iftype nlmode) 2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2367832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return nlmode == NL80211_IFTYPE_P2P_CLIENT || 2377832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt nlmode == NL80211_IFTYPE_P2P_GO; 2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv, 2426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ifindex) 2439ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt{ 2449ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt struct i802_bss *bss; 2459ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 2469ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt for (bss = drv->first_bss; bss; bss = bss->next) { 2479ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (bss->ifindex == ifindex) 2489ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt return bss; 2499ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt } 2509ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 2519ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt return NULL; 2529ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt} 2539ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 2549ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 2556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int is_mesh_interface(enum nl80211_iftype nlmode) 2566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 2576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nlmode == NL80211_IFTYPE_MESH_POINT; 2586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 2596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 2616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv) 2628bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt{ 2638bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt if (drv->associated) 2648bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN); 2658bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt drv->associated = 0; 2668bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt os_memset(drv->bssid, 0, ETH_ALEN); 2678bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt} 2688bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt 2698bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* nl80211 code */ 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ack_handler(struct nl_msg *msg, void *arg) 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *err = arg; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = 0; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_STOP; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int finish_handler(struct nl_msg *msg, void *arg) 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *ret = arg; 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ret = 0; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *arg) 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *ret = arg; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ret = err->error; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int no_seq_check(struct nl_msg *msg, void *arg) 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_OK; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_nlmsg_clear(struct nl_msg *msg) 3016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 3026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 3036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Clear nlmsg data, e.g., to make sure key material is not left in 3046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * heap memory for unnecessarily long time. 3056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (msg) { 3076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlmsghdr *hdr = nlmsg_hdr(msg); 3086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void *data = nlmsg_data(hdr); 3096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 3106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * This would use nlmsg_datalen() or the older nlmsg_len() if 3116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * only libnl were to maintain a stable API.. Neither will work 3126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * with all released versions, so just calculate the length 3136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * here. 3146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 3156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int len = hdr->nlmsg_len - NLMSG_HDRLEN; 3166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(data, 0, len); 3186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 3206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int send_and_recv(struct nl80211_global *global, 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_handle *nl_handle, struct nl_msg *msg, 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*valid_handler)(struct nl_msg *, void *), 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *valid_data) 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_cb *cb; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err = -ENOMEM; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 3316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOMEM; 3326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cb = nl_cb_clone(global->nl_cb); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!cb) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = nl_send_auto_complete(nl_handle, msg); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err < 0) 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = 1; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (valid_handler) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt valid_handler, valid_data); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt while (err > 0) { 35268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int res = nl_recvmsgs(nl_handle, cb); 353717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (res < 0) { 35468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_INFO, 35568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt "nl80211: %s->nl_recvmsgs failed: %d", 35668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt __func__, res); 35768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 35868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out: 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_put(cb); 3616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!valid_handler && valid_data == (void *) -1) 3626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_nlmsg_clear(msg); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return err; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, 3696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg, 3706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int (*valid_handler)(struct nl_msg *, void *), 3716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void *valid_data) 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return send_and_recv(drv->global, drv->global->nl, msg, 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt valid_handler, valid_data); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct family_data { 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *group; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int id; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int family_handler(struct nl_msg *msg, void *arg) 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct family_data *res = arg; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[CTRL_ATTR_MAX + 1]; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *mcgrp; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb[CTRL_ATTR_MCAST_GROUPS]) 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp), 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(mcgrp), NULL); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !tb2[CTRL_ATTR_MCAST_GRP_ID] || 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]), 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->group, 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0) 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nl_get_multicast_id(struct nl80211_global *global, 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *family, const char *group) 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 4196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct family_data res = { group, -ENOENT }; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 4256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"), 4266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 0, 0, CTRL_CMD_GETFAMILY, 0) || 4276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) { 4286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 4296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 4306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv(global, global->nl, msg, family_handler, &res); 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = res.id; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid * nl80211_cmd(struct wpa_driver_nl80211_data *drv, 4406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg, int flags, uint8_t cmd) 4411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 4421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return genlmsg_put(msg, 0, 0, drv->global->nl80211_id, 4431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0, flags, cmd, 0); 4441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 4451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss) 4486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 4496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->wdev_id_set) 4506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nla_put_u64(msg, NL80211_ATTR_WDEV, bss->wdev_id); 4516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nla_put_u32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); 4526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 4536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct nl_msg * nl80211_cmd_msg(struct i802_bss *bss, int flags, uint8_t cmd) 4566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 4576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 4586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nlmsg_alloc(); 4606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 4616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 4626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!nl80211_cmd(bss->drv, msg, flags, cmd) || 4646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_set_iface_id(msg, bss) < 0) { 4656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 4666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 4676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 4686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return msg; 4706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 4716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic struct nl_msg * 4746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtnl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex, 4756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int flags, uint8_t cmd) 4766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 4776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 4786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nlmsg_alloc(); 4806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 4816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 4826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!nl80211_cmd(drv, msg, flags, cmd) || 4846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) { 4856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 4866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 4876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 4886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return msg; 4906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 4916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags, 4946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt uint8_t cmd) 4956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 4966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_ifindex_msg(drv, drv->ifindex, flags, cmd); 4976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 4986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 4996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstruct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd) 5016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 5026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_ifindex_msg(bss->drv, bss->ifindex, flags, cmd); 5036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 5046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wiphy_idx_data { 5071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int wiphy_idx; 50834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt enum nl80211_iftype nlmode; 50934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 *macaddr; 5101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}; 5111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int netdev_info_handler(struct nl_msg *msg, void *arg) 5141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 5171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wiphy_idx_data *info = arg; 5181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 5201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 5211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tb[NL80211_ATTR_WIPHY]) 5231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]); 5241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 52534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (tb[NL80211_ATTR_IFTYPE]) 52634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]); 52734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 52834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (tb[NL80211_ATTR_MAC] && info->macaddr) 52934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(info->macaddr, nla_data(tb[NL80211_ATTR_MAC]), 53034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ETH_ALEN); 53134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 5321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NL_SKIP; 5331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint nl80211_get_wiphy_index(struct i802_bss *bss) 5371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl_msg *msg; 5391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wiphy_idx_data data = { 5401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .wiphy_idx = -1, 54134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt .macaddr = NULL, 5421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt }; 5431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) 5456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 5461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0) 5481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return data.wiphy_idx; 5491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 5501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 5511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 55334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss) 55434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 55534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct nl_msg *msg; 55634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wiphy_idx_data data = { 55734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt .nlmode = NL80211_IFTYPE_UNSPECIFIED, 55834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt .macaddr = NULL, 55934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt }; 56034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 5616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) 5626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_IFTYPE_UNSPECIFIED; 56334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 56434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0) 56534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return data.nlmode; 56634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NL80211_IFTYPE_UNSPECIFIED; 56734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 56834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 56934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 57034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int nl80211_get_macaddr(struct i802_bss *bss) 57134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 57234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct nl_msg *msg; 57334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wiphy_idx_data data = { 57434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt .macaddr = bss->addr, 57534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt }; 57634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 5776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) 5786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 57934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 58034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data); 58134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 58234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 58334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 5841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv, 5851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl80211_wiphy_data *w) 5861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl_msg *msg; 5886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt msg = nlmsg_alloc(); 5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!msg) 5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS) || 5956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx)) { 5966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 5976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 5986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL); 6011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret) { 6021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Register beacons command " 6031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "failed: ret=%d (%s)", 6041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret, strerror(-ret)); 6051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 6071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 6081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle) 6111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 6121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl80211_wiphy_data *w = eloop_ctx; 61368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int res; 6141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 615c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_EXCESSIVE, "nl80211: Beacon event message available"); 6161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 61768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt res = nl_recvmsgs(handle, w->nl_cb); 618717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (res < 0) { 61968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d", 62068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt __func__, res); 62168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int process_beacon_event(struct nl_msg *msg, void *arg) 6261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 6271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl80211_wiphy_data *w = arg; 6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv; 6291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 6301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 6311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt union wpa_event_data event; 6321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 6341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 6351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (gnlh->cmd != NL80211_CMD_FRAME) { 6371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)", 6381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gnlh->cmd); 6391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NL_SKIP; 6401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!tb[NL80211_ATTR_FRAME]) 6431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NL_SKIP; 6441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data, 6461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wiphy_list) { 6471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&event, 0, sizeof(event)); 6481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]); 6491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]); 6501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); 6511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NL_SKIP; 6541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 6551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct nl80211_wiphy_data * 6581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtnl80211_get_wiphy_data_ap(struct i802_bss *bss) 6591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 6601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt static DEFINE_DL_LIST(nl80211_wiphys); 6611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl80211_wiphy_data *w; 6621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int wiphy_idx, found = 0; 6631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct i802_bss *tmp_bss; 6641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (bss->wiphy_data != NULL) 6661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return bss->wiphy_data; 6671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wiphy_idx = nl80211_get_wiphy_index(bss); 6691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) { 6711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (w->wiphy_idx == wiphy_idx) 6721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto add; 6731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* alloc new one */ 6761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt w = os_zalloc(sizeof(*w)); 6771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (w == NULL) 6781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 6791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt w->wiphy_idx = wiphy_idx; 6801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_init(&w->bsss); 6811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_init(&w->drvs); 6821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); 6841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!w->nl_cb) { 6851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(w); 6861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 6871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); 6891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event, 6901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt w); 6911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb, 6931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "wiphy beacons"); 6941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (w->nl_beacons == NULL) { 6951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(w); 6961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 6971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (nl80211_register_beacons(bss->drv, w)) { 7001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl_destroy_handles(&w->nl_beacons); 7011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(w); 7021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 7031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 70568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt nl80211_register_eloop_read(&w->nl_beacons, nl80211_recv_beacons, w); 7061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_add(&nl80211_wiphys, &w->list); 7081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtadd: 7101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* drv entry for this bss already there? */ 7111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) { 7121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tmp_bss->drv == bss->drv) { 7131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt found = 1; 7141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 7151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* if not add it */ 7181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!found) 7191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_add(&w->drvs, &bss->drv->wiphy_list); 7201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_add(&w->bsss, &bss->wiphy_list); 7221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->wiphy_data = w; 7231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return w; 7241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 7251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nl80211_put_wiphy_data_ap(struct i802_bss *bss) 7281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 7291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl80211_wiphy_data *w = bss->wiphy_data; 7301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct i802_bss *tmp_bss; 7311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int found = 0; 7321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (w == NULL) 7341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 7351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->wiphy_data = NULL; 7361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_del(&bss->wiphy_list); 7371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* still any for this drv present? */ 7391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) { 7401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tmp_bss->drv == bss->drv) { 7411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt found = 1; 7421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 7431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 7451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* if not remove it */ 7461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!found) 7471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_del(&bss->drv->wiphy_list); 7481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!dl_list_empty(&w->bsss)) 7501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 7511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt nl80211_destroy_eloop_handle(&w->nl_beacons); 7531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl_cb_put(w->nl_cb); 7551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_del(&w->list); 7561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(w); 7571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 7581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid) 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->associated) 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(bssid, drv->bssid, ETH_ALEN); 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid) 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->associated) 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ssid, drv->ssid, drv->ssid_len); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return drv->ssid_len; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 782fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic void wpa_driver_nl80211_event_newlink( 7836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv, const char *ifname) 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 787fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (os_strcmp(drv->first_bss->ifname, ifname) == 0) { 788fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (if_nametoindex(drv->first_bss->ifname) == 0) { 789fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK", 790fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt drv->first_bss->ifname); 791fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 792fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 793fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (!drv->if_removed) 794fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 795fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event", 796fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt drv->first_bss->ifname); 797fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt drv->if_removed = 0; 798fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 799fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 801fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_strlcpy(event.interface_status.ifname, ifname, 802fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt sizeof(event.interface_status.ifname)); 803fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt event.interface_status.ievent = EVENT_INTERFACE_ADDED; 804fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 805fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 806fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 807fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 808fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic void wpa_driver_nl80211_event_dellink( 8096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv, const char *ifname) 810fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 811fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt union wpa_event_data event; 812fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 813fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (os_strcmp(drv->first_bss->ifname, ifname) == 0) { 814fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (drv->if_removed) { 815fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s", 816fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifname); 817fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 81804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 819fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1", 820fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifname); 821fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt drv->if_removed = 1; 822fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } else { 823fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed", 824fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifname); 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 827fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 828fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_strlcpy(event.interface_status.ifname, ifname, 829fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt sizeof(event.interface_status.ifname)); 830fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt event.interface_status.ievent = EVENT_INTERFACE_REMOVED; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv, 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attrlen, rta_len; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attrlen = len; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = (struct rtattr *) buf; 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rta_len = RTA_ALIGN(sizeof(struct rtattr)); 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->rta_type == IFLA_IFNAME) { 847cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (os_strcmp(((char *) attr) + rta_len, 848cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt drv->first_bss->ifname) == 0) 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv, 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, u8 *buf, size_t len) 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ifindex == ifindex) 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) { 8677f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nl80211_check_global(drv->global); 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed " 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface"); 8706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL); 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpa_driver_nl80211_data * 8791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtnl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len) 8801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 8811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv; 8821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt dl_list_for_each(drv, &global->interfaces, 8831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data, list) { 8841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) || 8851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt have_ifidx(drv, idx)) 8861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return drv; 8871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 8881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 8891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 8901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_event_rtm_newlink(void *ctx, 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ifinfomsg *ifi, 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl80211_global *global = ctx; 8971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv; 898fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int attrlen; 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 brid = 0; 9011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt char namebuf[IFNAMSIZ]; 902fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt char ifname[IFNAMSIZ + 1]; 903fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt char extra[100], *pos, *end; 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv = nl80211_find_drv(global, ifi->ifi_index, buf, len); 9061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!drv) { 907fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d", 908fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifi->ifi_index); 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 912fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt extra[0] = '\0'; 913fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos = extra; 914fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt end = pos + sizeof(extra); 915fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifname[0] = '\0'; 916fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 917fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt attrlen = len; 918fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt attr = (struct rtattr *) buf; 919fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 920fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt switch (attr->rta_type) { 921fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case IFLA_IFNAME: 922fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RTA_PAYLOAD(attr) >= IFNAMSIZ) 923fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 924fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr)); 925fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifname[RTA_PAYLOAD(attr)] = '\0'; 926fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 927fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case IFLA_MASTER: 928fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt brid = nla_get_u32((struct nlattr *) attr); 929fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += os_snprintf(pos, end - pos, " master=%u", brid); 930fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 931fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case IFLA_WIRELESS: 932fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += os_snprintf(pos, end - pos, " wext"); 933fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 934fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case IFLA_OPERSTATE: 935fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += os_snprintf(pos, end - pos, " operstate=%u", 936fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt nla_get_u32((struct nlattr *) attr)); 937fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 938fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case IFLA_LINKMODE: 939fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt pos += os_snprintf(pos, end - pos, " linkmode=%u", 940fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt nla_get_u32((struct nlattr *) attr)); 941fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 942fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 943fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 944fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 945fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt extra[sizeof(extra) - 1] = '\0'; 946fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 947661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)", 948661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt ifi->ifi_index, ifname, extra, ifi->ifi_family, 949661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt ifi->ifi_flags, 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) { 9567f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt namebuf[0] = '\0'; 9571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (if_indextoname(ifi->ifi_index, namebuf) && 9587f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) { 9591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down " 9601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "event since interface %s is up", namebuf); 9616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ignore_if_down_event = 0; 9621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 9631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 9647f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)", 9657f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt namebuf, ifname); 9667f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (os_strcmp(drv->first_bss->ifname, ifname) != 0) { 9677f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 9687f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "nl80211: Not the main interface (%s) - do not indicate interface down", 9697f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt drv->first_bss->ifname); 9707f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } else if (drv->ignore_if_down_event) { 9711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down " 9721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "event generated by mode change"); 9731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->ignore_if_down_event = 0; 9741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 9751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->if_disabled = 1; 9761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_event(drv->ctx, 9771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt EVENT_INTERFACE_DISABLED, NULL); 978a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 979a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt /* 980a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt * Try to get drv again, since it may be removed as 981a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt * part of the EVENT_INTERFACE_DISABLED handling for 982a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt * dynamic interfaces 983a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt */ 984a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt drv = nl80211_find_drv(global, ifi->ifi_index, 985a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt buf, len); 986a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt if (!drv) 987a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt return; 9881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) { 9921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (if_indextoname(ifi->ifi_index, namebuf) && 9937f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt linux_iface_up(drv->global->ioctl_sock, namebuf) == 0) { 9941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up " 9951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "event since interface %s is down", 9961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt namebuf); 997cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } else if (if_nametoindex(drv->first_bss->ifname) == 0) { 99804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up " 99904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "event since interface %s does not exist", 1000cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt drv->first_bss->ifname); 100104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } else if (drv->if_removed) { 100204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up " 100304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "event since interface %s is marked " 1004cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt "removed", drv->first_bss->ifname); 10051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 10069ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt struct i802_bss *bss; 10079ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt u8 addr[ETH_ALEN]; 10089ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 10099ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt /* Re-read MAC address as it may have changed */ 10109ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt bss = get_bss_ifindex(drv, ifi->ifi_index); 10119ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (bss && 10129ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt linux_get_ifhwaddr(drv->global->ioctl_sock, 10139ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt bss->ifname, addr) < 0) { 10149ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt wpa_printf(MSG_DEBUG, 10159ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt "nl80211: %s: failed to re-read MAC address", 10169ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt bss->ifname); 10179ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt } else if (bss && 10189ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt os_memcmp(addr, bss->addr, ETH_ALEN) != 0) { 10199ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt wpa_printf(MSG_DEBUG, 10209ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt "nl80211: Own MAC address on ifindex %d (%s) changed from " 10219ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt MACSTR " to " MACSTR, 10229ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt ifi->ifi_index, bss->ifname, 10239ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt MAC2STR(bss->addr), 10249ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt MAC2STR(addr)); 10259ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt os_memcpy(bss->addr, addr, ETH_ALEN); 10269ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt } 10279ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt 10281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface up"); 10291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->if_disabled = 0; 10301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, 10311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt NULL); 10321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Some drivers send the association event before the operup event--in 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this case, lifting operstate in wpa_driver_nl80211_set_operstate() 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fails. This will hit us when wpa_supplicant does not need to do 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.1X authentication 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->operstate == 1 && 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && 1043fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt !(ifi->ifi_flags & IFF_RUNNING)) { 1044fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate"); 10451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt -1, IF_OPER_UP); 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1049fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ifname[0]) 1050fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_driver_nl80211_event_newlink(drv, ifname); 1051fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifi->ifi_family == AF_BRIDGE && brid) { 10536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss; 10546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* device has been added to bridge */ 10566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!if_indextoname(brid, namebuf)) { 10576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 10586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Could not find bridge ifname for ifindex %u", 10596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt brid); 10606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 10616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s", 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brid, namebuf); 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, brid); 10656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 10666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (bss = drv->first_bss; bss; bss = bss->next) { 10676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_strcmp(ifname, bss->ifname) == 0) { 10686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_strlcpy(bss->brname, namebuf, IFNAMSIZ); 10696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 10706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 10716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_event_rtm_dellink(void *ctx, 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ifinfomsg *ifi, 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl80211_global *global = ctx; 10811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv; 1082fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int attrlen; 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 brid = 0; 1085fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt char ifname[IFNAMSIZ + 1]; 1086661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt char extra[100], *pos, *end; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv = nl80211_find_drv(global, ifi->ifi_index, buf, len); 10891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!drv) { 1090fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d", 1091fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifi->ifi_index); 10921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 10931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 10941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1095661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt extra[0] = '\0'; 1096661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos = extra; 1097661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt end = pos + sizeof(extra); 1098fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifname[0] = '\0'; 1099fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attrlen = len; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = (struct rtattr *) buf; 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 1103fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt switch (attr->rta_type) { 1104fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case IFLA_IFNAME: 1105fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (RTA_PAYLOAD(attr) >= IFNAMSIZ) 1106fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 1107fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr)); 1108fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ifname[RTA_PAYLOAD(attr)] = '\0'; 1109fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 1110fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case IFLA_MASTER: 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brid = nla_get_u32((struct nlattr *) attr); 1112661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += os_snprintf(pos, end - pos, " master=%u", brid); 1113661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt break; 1114661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt case IFLA_OPERSTATE: 1115661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += os_snprintf(pos, end - pos, " operstate=%u", 1116661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt nla_get_u32((struct nlattr *) attr)); 1117661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt break; 1118661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt case IFLA_LINKMODE: 1119661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt pos += os_snprintf(pos, end - pos, " linkmode=%u", 1120661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt nla_get_u32((struct nlattr *) attr)); 1121fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt break; 1122fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1125661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt extra[sizeof(extra) - 1] = '\0'; 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1127661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "RTM_DELLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)", 1128661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt ifi->ifi_index, ifname, extra, ifi->ifi_family, 1129661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt ifi->ifi_flags, 1130661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", 1131661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", 1132661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", 1133661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); 1134661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 1135661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid)) 1136fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_driver_nl80211_event_dellink(drv, ifname); 1137fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifi->ifi_family == AF_BRIDGE && brid) { 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* device has been removed from bridge */ 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char namebuf[IFNAMSIZ]; 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!if_indextoname(brid, namebuf)) { 11436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 11446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Could not find bridge ifname for ifindex %u", 11456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt brid); 11466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 11476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 11486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Remove ifindex %u for bridge %s", 11496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt brid, namebuf); 11506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 11516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt del_ifidx(drv, brid); 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtunsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv) 115787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen{ 115887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen struct nl_msg *msg; 115987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen int ret; 116087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen struct nl80211_bss_info_arg arg; 116187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 11626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SCAN); 116387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen os_memset(&arg, 0, sizeof(arg)); 116487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen arg.drv = drv; 116587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); 116687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if (ret == 0) { 11676dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt unsigned int freq = drv->nlmode == NL80211_IFTYPE_ADHOC ? 11686dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt arg.ibss_freq : arg.assoc_freq; 116987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the " 11706dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt "associated BSS from scan results: %u MHz", freq); 11716dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt if (freq) 11726dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt drv->assoc_freq = freq; 1173b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return drv->assoc_freq; 117487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen } 117587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " 117687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen "(%s)", ret, strerror(-ret)); 117787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen return drv->assoc_freq; 117887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen} 117987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 118087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 11816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int get_link_signal(struct nl_msg *msg, void *arg) 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 11846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 11856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1]; 11866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = { 11876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 }, 11886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 }, 1189f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt [NL80211_STA_INFO_BEACON_SIGNAL_AVG] = { .type = NLA_U8 }, 11906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt }; 11916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1]; 11926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = { 11936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 }, 11946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 }, 11956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG }, 11966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, 11976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt }; 11986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_signal_info *sig_change = arg; 1199661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 12006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 12016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 12026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb[NL80211_ATTR_STA_INFO] || 12036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse_nested(sinfo, NL80211_STA_INFO_MAX, 12046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tb[NL80211_ATTR_STA_INFO], policy)) 12056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 12066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sinfo[NL80211_STA_INFO_SIGNAL]) 12076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->current_signal = 12106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]); 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sinfo[NL80211_STA_INFO_SIGNAL_AVG]) 12136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->avg_signal = 12146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]); 12156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else 12166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->avg_signal = 0; 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt if (sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]) 1219f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt sig_change->avg_beacon_signal = 1220f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt (s8) 1221f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt nla_get_u8(sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]); 1222f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt else 1223f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt sig_change->avg_beacon_signal = 0; 1224f73259cc00af557e36add405799b7f2326587c13Dmitry Shmidt 12256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sinfo[NL80211_STA_INFO_TX_BITRATE]) { 12266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, 12276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sinfo[NL80211_STA_INFO_TX_BITRATE], 12286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rate_policy)) { 12296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->current_txrate = 0; 12306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 12316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (rinfo[NL80211_RATE_INFO_BITRATE]) { 12326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->current_txrate = 12336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_get_u16(rinfo[ 12346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_RATE_INFO_BITRATE]) * 100; 12356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 12366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv, 12446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_signal_info *sig) 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig->current_signal = -9999; 12496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig->current_txrate = 0; 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_STATION)) || 12526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid)) { 12536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 12546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, get_link_signal, sig); 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int get_link_noise(struct nl_msg *msg, void *arg) 12621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 12636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 12646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 12656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1]; 12666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = { 12676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 }, 12686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 }, 12696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt }; 12706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_signal_info *sig_change = arg; 12711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 12736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 12746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 12756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb[NL80211_ATTR_SURVEY_INFO]) { 12766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: survey data missing!"); 12776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 12781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 12791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 12806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX, 12816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tb[NL80211_ATTR_SURVEY_INFO], 12826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_policy)) { 12836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested " 12846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "attributes!"); 12856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 1286d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 1287d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 12886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) 12896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 129004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 12916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) != 12926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->frequency) 12936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 129404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 12956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_NOISE]) 12966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 12979767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt 12986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->current_noise = 12996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]); 13009767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt 13016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 13029767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt} 13039767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt 13049767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt 13056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv, 13066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_signal_info *sig_change) 130704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 13086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 130904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 13106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->current_noise = 9999; 13116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sig_change->frequency = drv->assoc_freq; 1312e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 13136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); 13146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, get_link_noise, sig_change); 13151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 13161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx, 13196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void *handle) 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_cb *cb = eloop_ctx; 13226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int res; 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_MSGDUMP, "nl80211: Event message available"); 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = nl_recvmsgs(handle, cb); 13276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res < 0) { 13286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d", 13296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt __func__, res); 13306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 13356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain 13366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @priv: driver_nl80211 private data 13376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @alpha2_arg: country to which to switch to 13386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: 0 on success, -1 on failure 13396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 13406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * This asks nl80211 to set the regulatory domain for given 13416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * country ISO / IEC alpha2. 13426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 13436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg) 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 13469866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 13476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char alpha2[3]; 13486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nlmsg_alloc(); 13516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 13526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOMEM; 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt alpha2[0] = alpha2_arg[0]; 13556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt alpha2[1] = alpha2_arg[1]; 13566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt alpha2[2] = '\0'; 135704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 13586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG) || 13596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, alpha2)) { 13606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 13616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (send_and_recv_msgs(drv, msg, NULL, NULL)) 13646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 13656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_get_country(struct nl_msg *msg, void *arg) 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char *alpha2 = arg; 13726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; 13736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 13741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 13756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 13766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 13776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) { 13786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No country information available"); 13796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 13801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 13816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_strlcpy(alpha2, nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]), 3); 13826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_get_country(void *priv, char *alpha2) 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 13896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 13906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 13916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nlmsg_alloc(); 13946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 13956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOMEM; 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG); 13986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt alpha2[0] = '\0'; 13996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2); 14006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!alpha2[0]) 14016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global) 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 1410d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 14116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); 14126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (global->nl_cb == NULL) { 14136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " 14146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "callbacks"); 14156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 14166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt global->nl = nl_create_handle(global->nl_cb, "nl"); 14196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (global->nl == NULL) 14206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto err; 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211"); 14236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (global->nl80211_id < 0) { 14246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not " 14256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "found"); 14266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto err; 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt global->nl_event = nl_create_handle(global->nl_cb, "event"); 14306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (global->nl_event == NULL) 14316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto err; 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = nl_get_multicast_id(global, "nl80211", "scan"); 14346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret >= 0) 14356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = nl_socket_add_membership(global->nl_event, ret); 14366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret < 0) { 14376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " 14386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "membership for scan events: %d (%s)", 14396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 14406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto err; 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = nl_get_multicast_id(global, "nl80211", "mlme"); 14446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret >= 0) 14456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = nl_socket_add_membership(global->nl_event, ret); 14466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret < 0) { 14476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " 14486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "membership for mlme events: %d (%s)", 14496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 14506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto err; 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = nl_get_multicast_id(global, "nl80211", "regulatory"); 14546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret >= 0) 14556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = nl_socket_add_membership(global->nl_event, ret); 14566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret < 0) { 14576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast " 14586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "membership for regulatory events: %d (%s)", 14596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 14606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Continue without regulatory events */ 14618da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt } 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = nl_get_multicast_id(global, "nl80211", "vendor"); 14646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret >= 0) 14656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = nl_socket_add_membership(global->nl_event, ret); 14666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret < 0) { 14676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast " 14686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "membership for vendor events: %d (%s)", 14696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 14706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Continue without vendor events */ 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 14736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, 14746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt no_seq_check, NULL); 14756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, 14766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt process_global_event, global); 14776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 14786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_register_eloop_read(&global->nl_event, 14796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_event_receive, 14806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt global->nl_cb); 14816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 14826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 14836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 14846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidterr: 14856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_destroy_handles(&global->nl_event); 14866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_destroy_handles(&global->nl); 14876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_cb_put(global->nl_cb); 14886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt global->nl_cb = NULL; 14896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14937f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic void nl80211_check_global(struct nl80211_global *global) 14947f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt{ 14957f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct nl_handle *handle; 14967f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt const char *groups[] = { "scan", "mlme", "regulatory", "vendor", NULL }; 14977f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt int ret; 14987f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt unsigned int i; 14997f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 15007f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt /* 15017f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * Try to re-add memberships to handle case of cfg80211 getting reloaded 15027f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * and all registration having been cleared. 15037f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt */ 15047f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt handle = (void *) (((intptr_t) global->nl_event) ^ 15057f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ELOOP_SOCKET_INVALID); 15067f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 15077f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt for (i = 0; groups[i]; i++) { 15087f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = nl_get_multicast_id(global, "nl80211", groups[i]); 15097f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (ret >= 0) 15107f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = nl_socket_add_membership(handle, ret); 15117f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (ret < 0) { 15127f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_INFO, 15137f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "nl80211: Could not re-add multicast membership for %s events: %d (%s)", 15147f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt groups[i], ret, strerror(-ret)); 15157f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 15167f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 15177f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt} 15187f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 15197f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 15206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_rfkill_blocked(void *ctx) 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked"); 15236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 15246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * This may be for any interface; use ifdown event to disable 15256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * interface. 15266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 15276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_rfkill_unblocked(void *ctx) 15316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 15326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = ctx; 15336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked"); 15346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (i802_set_iface_flags(drv->first_bss, 1)) { 15356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP " 15366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "after rfkill unblock"); 15376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* rtnetlink ifup handler will report interface as enabled */ 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_handle_eapol_tx_status(int sock, 15446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void *eloop_ctx, 15456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void *handle) 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = eloop_ctx; 15486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 data[2048]; 15496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct msghdr msg; 15506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct iovec entry; 15516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 control[512]; 15526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct cmsghdr *cmsg; 15536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int res, found_ee = 0, found_wifi = 0, acked = 0; 15546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt union wpa_event_data event; 15556dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 15566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt memset(&msg, 0, sizeof(msg)); 15576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg.msg_iov = &entry; 15586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg.msg_iovlen = 1; 15596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt entry.iov_base = data; 15606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt entry.iov_len = sizeof(data); 15616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg.msg_control = &control; 15626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg.msg_controllen = sizeof(control); 1563c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 15646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = recvmsg(sock, &msg, MSG_ERRQUEUE); 15656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* if error or not fitting 802.3 header, return */ 15666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res < 14) 15676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) 15706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 15716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (cmsg->cmsg_level == SOL_SOCKET && 15726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cmsg->cmsg_type == SCM_WIFI_STATUS) { 15736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int *ack; 15746dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 15756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt found_wifi = 1; 15766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ack = (void *)CMSG_DATA(cmsg); 15776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt acked = *ack; 15786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (cmsg->cmsg_level == SOL_PACKET && 15816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cmsg->cmsg_type == PACKET_TX_TIMESTAMP) { 15826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct sock_extended_err *err = 15836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (struct sock_extended_err *)CMSG_DATA(cmsg); 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS) 15866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt found_ee = 1; 15876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 15886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!found_ee || !found_wifi) 15916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt memset(&event, 0, sizeof(event)); 15946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt event.eapol_tx_status.dst = data; 15956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt event.eapol_tx_status.data = data + 14; 15966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt event.eapol_tx_status.data_len = res - 14; 15976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt event.eapol_tx_status.ack = acked; 15986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event); 15996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_init_bss(struct i802_bss *bss) 16036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 16046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); 16056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!bss->nl_cb) 16066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, 16096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt no_seq_check, NULL); 16106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, 16116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt process_bss_event, bss); 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 16146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_destroy_bss(struct i802_bss *bss) 16186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 16196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_cb_put(bss->nl_cb); 16206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->nl_cb = NULL; 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, 16256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void *global_priv, int hostapd, 16266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *set_addr, 16276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const char *driver_params) 1628700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{ 16296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv; 16306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct rfkill_config *rcfg; 16316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss; 1632700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 16336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (global_priv == NULL) 16346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 16356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv = os_zalloc(sizeof(*drv)); 16366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv == NULL) 16376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 16386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->global = global_priv; 16396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ctx = ctx; 16406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->hostapd = !!hostapd; 16416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->eapol_sock = -1; 1642ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 1643ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt /* 1644ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * There is no driver capability flag for this, so assume it is 1645ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * supported and disable this on first attempt to use if the driver 1646ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt * rejects the command due to missing support. 1647ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt */ 1648ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt drv->set_rekey_offload = 1; 1649ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 16506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int); 16516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->if_indices = drv->default_if_indices; 1652700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 16536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->first_bss = os_zalloc(sizeof(*drv->first_bss)); 16546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->first_bss) { 16556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv); 16566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 1657700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt } 16586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss = drv->first_bss; 16596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->drv = drv; 16606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ctx = ctx; 16616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 16626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname)); 16636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->monitor_ifidx = -1; 16646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->monitor_sock = -1; 16656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->eapol_tx_sock = -1; 16666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; 16676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 16686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_init_bss(bss)) 16696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto failed; 1670700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 16716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rcfg = os_zalloc(sizeof(*rcfg)); 16726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (rcfg == NULL) 16736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto failed; 16746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rcfg->ctx = drv; 16756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname)); 16766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked; 16776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked; 16786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->rfkill = rfkill_init(rcfg); 16796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->rfkill == NULL) { 16806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available"); 16816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(rcfg); 1682700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt } 1683700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 16846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0) 16856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->start_iface_up = 1; 1686700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 16876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params)) 16886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto failed; 1689700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 16906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0); 16916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->eapol_tx_sock < 0) 16926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto failed; 1693700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 16946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->data_tx_status) { 16956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int enabled = 1; 1696700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 16976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS, 16986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt &enabled, sizeof(enabled)) < 0) { 16996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 17006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: wifi status sockopt failed\n"); 17016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->data_tx_status = 0; 17026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->use_monitor) 17036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.flags &= 17046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; 17056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 17066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_register_read_sock(drv->eapol_tx_sock, 17076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_handle_eapol_tx_status, 17086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv, NULL); 17096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 17101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 17111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 17126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->global) { 17137f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nl80211_check_global(drv->global); 17146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_add(&drv->global->interfaces, &drv->list); 17156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->in_interface_list = 1; 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1717fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 17186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return bss; 1719fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 17206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfailed: 17216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_deinit(bss); 17226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 17276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_init - Initialize nl80211 driver interface 17286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @ctx: context to be used when calling wpa_supplicant functions, 17296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * e.g., wpa_supplicant_event() 17306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @ifname: interface name, e.g., wlan0 17316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @global_priv: private driver global data from global_init() 17326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Returns: Pointer to private data, %NULL on failure 17336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 17346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void * wpa_driver_nl80211_init(void *ctx, const char *ifname, 17356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void *global_priv) 17366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 17376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL, 17386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NULL); 17396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_register_frame(struct i802_bss *bss, 17436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_handle *nl_handle, 17446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 type, const u8 *match, size_t match_len) 17456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 17466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 17476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 17486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 17496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char buf[30]; 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt buf[0] = '\0'; 17526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_snprintf_hex(buf, sizeof(buf), match, match_len); 17536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s", 17546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type, fc2str(type), nl_handle, buf); 175534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 17566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REGISTER_ACTION)) || 17576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, type) || 17586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_FRAME_MATCH, match_len, match)) { 17596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 17606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL); 17646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 17656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Register frame command " 17666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "failed (type=%u): ret=%d (%s)", 17676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type, ret, strerror(-ret)); 17686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match", 17696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt match, match_len); 17706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 17716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_alloc_mgmt_handle(struct i802_bss *bss) 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->nl_mgmt) { 17786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting " 17796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "already on! (nl_mgmt=%p)", bss->nl_mgmt); 17806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 17816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->nl_mgmt = nl_create_handle(bss->nl_cb, "mgmt"); 17846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->nl_mgmt == NULL) 17856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 17886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_mgmt_handle_register_eloop(struct i802_bss *bss) 17926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 17936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_register_eloop_read(&bss->nl_mgmt, 17946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_event_receive, 17956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->nl_cb); 17966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 17976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_register_action_frame(struct i802_bss *bss, 18006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *match, size_t match_len) 18016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 18026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); 18036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_register_frame(bss, bss->nl_mgmt, 18046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type, match, match_len); 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 18116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = 0; 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_alloc_mgmt_handle(bss)) 18146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 18156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP " 18166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "handle %p", bss->nl_mgmt); 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_ADHOC) { 18196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4); 18206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 18216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* register for any AUTH message */ 18226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0); 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_INTERWORKING 18266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* QoS Map Configure */ 18276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0) 18286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_INTERWORKING */ 18306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING) 18316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* GAS Initial Request */ 18326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0) 18336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* GAS Initial Response */ 18356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0) 18366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* GAS Comeback Request */ 18386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0) 18396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* GAS Comeback Response */ 18416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0) 18426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Protected GAS Initial Request */ 18446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0) 18456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Protected GAS Initial Response */ 18476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0) 18486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Protected GAS Comeback Request */ 18506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0) 18516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Protected GAS Comeback Response */ 18536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0) 18546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_P2P || CONFIG_INTERWORKING */ 18566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_P2P 18576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* P2P Public Action */ 18586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, 18596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (u8 *) "\x04\x09\x50\x6f\x9a\x09", 18606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6) < 0) 18616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* P2P Action */ 18636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, 18646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (u8 *) "\x7f\x50\x6f\x9a\x09", 18656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 5) < 0) 18666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_P2P */ 18686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_IEEE80211W 18696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* SA Query Response */ 18706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0) 18716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_IEEE80211W */ 18736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_TDLS 18746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) { 18756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* TDLS Discovery Response */ 18766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) < 18776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 0) 18786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_TDLS */ 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* FT Action frames */ 18836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0) 18846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else 18866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT | 18876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* WNM - BSS Transition Management Request */ 18906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0) 18916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* WNM-Sleep Mode Response */ 18936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0) 18946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_HS20 18976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* WNM-Notification */ 18986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0) 18996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_HS20 */ 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* WMM-AC ADDTS Response */ 19036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x11\x01", 2) < 0) 19046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* WMM-AC DELTS */ 19076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x11\x02", 2) < 0) 19086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 19106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Radio Measurement - Neighbor Report Response */ 19116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x05\x05", 2) < 0) 19126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 19146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Radio Measurement - Link Measurement Request */ 19156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((drv->capa.rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION) && 19166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (nl80211_register_action_frame(bss, (u8 *) "\x05\x02", 2) < 0)) 19176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 19196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mgmt_handle_register_eloop(bss); 19206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 19216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_mgmt_subscribe_mesh(struct i802_bss *bss) 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = 0; 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_alloc_mgmt_handle(bss)) 19306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 19336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Subscribe to mgmt frames with mesh handle %p", 19346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->nl_mgmt); 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Auth frames for mesh SAE */ 19376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_frame(bss, bss->nl_mgmt, 19386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (WLAN_FC_TYPE_MGMT << 2) | 19396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (WLAN_FC_STYPE_AUTH << 4), 19406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NULL, 0) < 0) 19416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Mesh peering open */ 19446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x01", 2) < 0) 19456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Mesh peering confirm */ 19476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x02", 2) < 0) 19486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Mesh peering close */ 19506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_action_frame(bss, (u8 *) "\x0f\x03", 2) < 0) 19516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -1; 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mgmt_handle_register_eloop(bss); 19541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 19561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 19571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_register_spurious_class3(struct i802_bss *bss) 19601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 19611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl_msg *msg; 19626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 19631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 19646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UNEXPECTED_FRAME); 19656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL); 19666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 19676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 " 19686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "failed: ret=%d (%s)", 19696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 19706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 19716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_mgmt_subscribe_ap(struct i802_bss *bss) 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static const int stypes[] = { 19786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_AUTH, 19796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_ASSOC_REQ, 19806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_REASSOC_REQ, 19816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_DISASSOC, 19826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_DEAUTH, 19836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_ACTION, 19846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_PROBE_REQ, 19856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/* Beacon doesn't work as mac80211 doesn't currently allow 19866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * it, but it wouldn't really be the right thing anyway as 19876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * it isn't per interface ... maybe just dump the scan 19886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * results periodically for OLBC? 19896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 19906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* WLAN_FC_STYPE_BEACON, */ 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 19926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int i; 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_alloc_mgmt_handle(bss)) 19956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 19966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP " 19976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "handle %p", bss->nl_mgmt); 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < ARRAY_SIZE(stypes); i++) { 20006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_frame(bss, bss->nl_mgmt, 20016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (WLAN_FC_TYPE_MGMT << 2) | 20026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (stypes[i] << 4), 20036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NULL, 0) < 0) { 20046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto out_err; 20056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_spurious_class3(bss)) 20096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto out_err; 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_get_wiphy_data_ap(bss) == NULL) 20126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto out_err; 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mgmt_handle_register_eloop(bss); 20156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtout_err: 20186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_destroy_handles(&bss->nl_mgmt); 20196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss) 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_alloc_mgmt_handle(bss)) 20266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 20276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP " 20286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "handle %p (device SME)", bss->nl_mgmt); 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_register_frame(bss, bss->nl_mgmt, 20316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (WLAN_FC_TYPE_MGMT << 2) | 20326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (WLAN_FC_STYPE_ACTION << 4), 20336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NULL, 0) < 0) 20346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto out_err; 2035c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 20366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mgmt_handle_register_eloop(bss); 20376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtout_err: 20406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_destroy_handles(&bss->nl_mgmt); 20416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason) 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->nl_mgmt == NULL) 2048c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt return; 20496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p " 20506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "(%s)", bss->nl_mgmt, reason); 20516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_destroy_eloop_handle(&bss->nl_mgmt); 2052c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 20536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_put_wiphy_data_ap(bss); 20546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx) 20586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 20596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL); 20606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_del_p2pdev(struct i802_bss *bss) 20646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 20656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 20666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 2067d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 20686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_INTERFACE); 20696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); 20701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s", 20726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, (long long unsigned int) bss->wdev_id, 20736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt strerror(-ret)); 20741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 20751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_p2pdev(struct i802_bss *bss, int start) 20781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 20796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 20806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 20811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(bss, 0, start ? NL80211_CMD_START_P2P_DEVICE : 20836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_STOP_P2P_DEVICE); 20846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); 20851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s", 20876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt start ? "Start" : "Stop", 20886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, (long long unsigned int) bss->wdev_id, 20896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt strerror(-ret)); 20906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 20911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 20921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 20946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int i802_set_iface_flags(struct i802_bss *bss, int up) 2095d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 20966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_iftype nlmode; 2097d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 20986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmode = nl80211_get_ifmode(bss); 20996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nlmode != NL80211_IFTYPE_P2P_DEVICE) { 21006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return linux_set_iface_flags(bss->drv->global->ioctl_sock, 21016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, up); 2102d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 2103d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 21046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* P2P Device has start/stop which is equivalent */ 21056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_set_p2pdev(bss, up); 21065393a0f77c5281735888bd9dcf8d8abeb5961461Dmitry Shmidt} 21075393a0f77c5281735888bd9dcf8d8abeb5961461Dmitry Shmidt 21085393a0f77c5281735888bd9dcf8d8abeb5961461Dmitry Shmidt 21097f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 21107f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic int qca_vendor_test_cmd_handler(struct nl_msg *msg, void *arg) 21117f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt{ 21127f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt /* struct wpa_driver_nl80211_data *drv = arg; */ 21137f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 21147f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 21157f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21167f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21177f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 21187f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "nl80211: QCA vendor test command response received"); 21197f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21207f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 21217f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 21227f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!tb[NL80211_ATTR_VENDOR_DATA]) { 21237f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No vendor data attribute"); 21247f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return NL_SKIP; 21257f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 21267f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21277f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 21287f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "nl80211: Received QCA vendor test command response", 21297f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nla_data(tb[NL80211_ATTR_VENDOR_DATA]), 21307f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nla_len(tb[NL80211_ATTR_VENDOR_DATA])); 21317f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21327f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return NL_SKIP; 21337f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt} 21347f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 21357f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21367f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21377f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic void qca_vendor_test(struct wpa_driver_nl80211_data *drv) 21387f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt{ 21397f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 21407f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct nl_msg *msg; 21417f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct nlattr *params; 21427f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt int ret; 21437f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21447f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 21457f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 21467f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 21477f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_TEST) || 21487f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || 21497f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TEST, 123)) { 21507f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nlmsg_free(msg); 21517f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return; 21527f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 21537f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt nla_nest_end(msg, params); 21547f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21557f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv); 21567f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 21577f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "nl80211: QCA vendor test command returned %d (%s)", 21587f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret, strerror(-ret)); 21597f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 21607f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt} 21617f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21627f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 21636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int 21646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtwpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, 21656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *set_addr, int first, 21666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const char *driver_params) 2167f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{ 21686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = drv->first_bss; 21696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int send_rfkill_event = 0; 21706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_iftype nlmode; 2171f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 21726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ifindex = if_nametoindex(bss->ifname); 21736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifindex = drv->ifindex; 21746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->wdev_id = drv->global->if_add_wdevid; 21756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->wdev_id_set = drv->global->if_add_wdevid_set; 2176f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 21776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex; 21786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set; 21796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->global->if_add_wdevid_set = 0; 2180f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 21816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP) 21826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->static_ap = 1; 2183f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 21846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_capa(drv)) 21856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 2186f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 21876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (driver_params && nl80211_set_param(bss, driver_params) < 0) 21886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 2189f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 21906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s", 21916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, drv->phyname); 2192ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 21936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (set_addr && 21946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) || 21956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, 21966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt set_addr))) 21976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 2198ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 21996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP) 22006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->start_mode_ap = 1; 2201051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 22026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->hostapd || bss->static_ap) 22036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmode = NL80211_IFTYPE_AP; 22046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else if (bss->if_dynamic) 22056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmode = nl80211_get_ifmode(bss); 22066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else 22076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmode = NL80211_IFTYPE_STATION; 2208051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 22096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) { 22106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode"); 22116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 2212051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 2213ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 22146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nlmode == NL80211_IFTYPE_P2P_DEVICE) 22156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_get_macaddr(bss); 22166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 22176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!rfkill_is_blocked(drv->rfkill)) { 22186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = i802_set_iface_flags(bss, 1); 22196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 22206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Could not set " 22216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "interface '%s' UP", bss->ifname); 22226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 22236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 22246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nlmode == NL80211_IFTYPE_P2P_DEVICE) 22256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 22266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 22276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable " 22286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "interface '%s' due to rfkill", bss->ifname); 22296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nlmode == NL80211_IFTYPE_P2P_DEVICE) 22306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 22316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->if_disabled = 1; 22326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt send_rfkill_event = 1; 2233ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt } 2234ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 22356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->hostapd) 22366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 22376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1, IF_OPER_DORMANT); 2238ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 22396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, 22406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->addr)) 22416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 22426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN); 22431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (send_rfkill_event) { 22456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill, 22466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv, drv->ctx); 22476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 22481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22497f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (drv->vendor_cmd_test_avail) 22507f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt qca_vendor_test(drv); 22517f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 22526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 22536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 22566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv) 22576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 22586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 22596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 22606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)", 22616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ifindex); 22626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON); 22636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 22641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 22651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 22676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt/** 22686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface 22696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * @bss: Pointer to private nl80211 data from wpa_driver_nl80211_init() 22706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * 22716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Shut down driver interface and processing of driver events. Free 22726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * private data buffer if one was allocated in wpa_driver_nl80211_init(). 22736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 22746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_deinit(struct i802_bss *bss) 2275cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{ 22766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 2277cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 22786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, "nl80211: deinit ifname=%s disabled_11b_rates=%d", 22796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, drv->disabled_11b_rates); 2280cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 22816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->in_deinit = 1; 22826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->data_tx_status) 22836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_unregister_read_sock(drv->eapol_tx_sock); 22846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->eapol_tx_sock >= 0) 22856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt close(drv->eapol_tx_sock); 2286cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 22876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->nl_preq) 22886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_probe_req_report(bss, 0); 22896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->added_if_into_bridge) { 22906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_br_del_if(drv->global->ioctl_sock, bss->brname, 22916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname) < 0) 22926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to remove " 22936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "interface %s from bridge %s: %s", 22946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, bss->brname, strerror(errno)); 22956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->rtnl_sk) 22966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_handle_destroy(drv->rtnl_sk); 2297cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 22986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->added_bridge) { 22996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_set_iface_flags(drv->global->ioctl_sock, bss->brname, 23006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 0) < 0) 23016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, 23026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Could not set bridge %s down", 23036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->brname); 23046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0) 23056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to remove " 23066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "bridge %s: %s", 23076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->brname, strerror(errno)); 2308cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 2309cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 23106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_remove_monitor_interface(drv); 2311cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 23126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (is_ap_interface(drv->nlmode)) 23136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_del_beacon(drv); 2314cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 23156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->eapol_sock >= 0) { 23166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_unregister_read_sock(drv->eapol_sock); 23176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt close(drv->eapol_sock); 2318cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt } 2319cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt 23206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->if_indices != drv->default_if_indices) 23216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->if_indices); 2322fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 23236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->disabled_11b_rates) 23246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_disable_11b_rates(drv, drv->ifindex, 0); 2325fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 23266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0, 23276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt IF_OPER_UP); 23286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx); 23296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rfkill_deinit(drv->rfkill); 2330fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 23316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); 2332fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 23336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->start_iface_up) 23346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (void) i802_set_iface_flags(bss, 0); 2335fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 23366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->addr_changed) { 23376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 23386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 0) < 0) { 23396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 23406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Could not set interface down to restore permanent MAC address"); 23416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 23426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, 23436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->perm_addr) < 0) { 23446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 23456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Could not restore permanent MAC address"); 23466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 2347fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 2348fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 23496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) { 23506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->hostapd || !drv->start_mode_ap) 23516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_set_mode(bss, 23526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_IFTYPE_STATION); 23536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mgmt_unsubscribe(bss, "deinit"); 23546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 23556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mgmt_unsubscribe(bss, "deinit"); 23566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_del_p2pdev(bss); 2357fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 2358fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 23596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_destroy_bss(drv->first_bss); 23606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 23616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->filter_ssids); 23626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 23636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->auth_ie); 23646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 23656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->in_interface_list) 23666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_del(&drv->list); 23676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 23686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->extended_capa); 23696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->extended_capa_mask); 23706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->first_bss); 23716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv); 2372fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 2373fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2374fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 23756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len) 23767dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt{ 23776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (alg) { 23786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_WEP: 23796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (key_len == 5) 23806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_WEP40; 23816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_WEP104; 23826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_TKIP: 23836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_TKIP; 23846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_CCMP: 23856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_CCMP; 23866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_GCMP: 23876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_GCMP; 23886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_CCMP_256: 23896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_CCMP_256; 23906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_GCMP_256: 23916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_GCMP_256; 23926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_IGTK: 23936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_AES_CMAC; 23946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_BIP_GMAC_128: 23956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_BIP_GMAC_128; 23966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_BIP_GMAC_256: 23976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_BIP_GMAC_256; 23986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_BIP_CMAC_256: 23996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_BIP_CMAC_256; 24006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_SMS4: 24016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_SMS4; 24026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_KRK: 24036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_KRK; 24046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_NONE: 24056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_ALG_PMK: 24066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d", 24076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt alg); 24086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 24096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 24107dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt 24116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Unsupported encryption algorithm %d", 24126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt alg); 24136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 24146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 24157dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt 24167dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt 24176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic u32 wpa_cipher_to_cipher_suite(unsigned int cipher) 24186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 24196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (cipher) { 24206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_CIPHER_CCMP_256: 24216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_CCMP_256; 24226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_CIPHER_GCMP_256: 24236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_GCMP_256; 24246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_CIPHER_CCMP: 24256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_CCMP; 24266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_CIPHER_GCMP: 24276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_GCMP; 24286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_CIPHER_TKIP: 24296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_TKIP; 24306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_CIPHER_WEP104: 24316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_WEP104; 24326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_CIPHER_WEP40: 24336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_WEP40; 24346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_CIPHER_GTK_NOT_USED: 24356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return WLAN_CIPHER_SUITE_NO_GROUP_ADDR; 24367dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt } 24377dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt 24386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 24396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 24407dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt 24417dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt 24426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[], 24436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int max_suites) 24446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 24456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int num_suites = 0; 24466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 24476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP_256) 24486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP_256; 24496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP_256) 24506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP_256; 24516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP) 24526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP; 24536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP) 24546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP; 24556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites < max_suites && ciphers & WPA_CIPHER_TKIP) 24566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP; 24576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP104) 24586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104; 24596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP40) 24606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40; 24616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 24626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return num_suites; 24637dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt} 24647dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt 24657dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt 24666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv, 24676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *key, size_t key_len) 24681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 24696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 24706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 2471a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 24726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) 24736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 247434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 24756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 24766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 24776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 24786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) || 24796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) { 24806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_nlmsg_clear(msg); 24816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 24826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); 24856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 24866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 24876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Key management set key failed: ret=%d (%s)", 24886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 24891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 24906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 24916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 24921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 24931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 24956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss, 24966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum wpa_alg alg, const u8 *addr, 24976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int key_idx, int set_tx, 24986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *seq, size_t seq_len, 24996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *key, size_t key_len) 25001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 25016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 25026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ifindex; 25031d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt struct nl_msg *msg = NULL; 25046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 25056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int tdls = 0; 25061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Ignore for P2P Device */ 25086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) 25096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 25101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ifindex = if_nametoindex(ifname); 25126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d " 25136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "set_tx=%d seq_len=%lu key_len=%lu", 25146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt __func__, ifindex, ifname, alg, addr, key_idx, set_tx, 25156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (unsigned long) seq_len, (unsigned long) key_len); 25166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_TDLS 25176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (key_idx == -1) { 25186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt key_idx = 0; 25196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tdls = 1; 25206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 25216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_TDLS */ 2522a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 25236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (alg == WPA_ALG_PMK && 25246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) { 25256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key", 25266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt __func__); 25276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = issue_key_mgmt_set_key(drv, key, key_len); 25286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 25291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 25301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (alg == WPA_ALG_NONE) { 25326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY); 25336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 25346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 25356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 25361d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt u32 suite; 25371d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 25381d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt suite = wpa_alg_to_cipher_suite(alg, key_len); 25391d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt if (!suite) 25401d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt goto fail; 25416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY); 25426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || 25436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_KEY_DATA, key_len, key) || 25441d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt nla_put_u32(msg, NL80211_ATTR_KEY_CIPHER, suite)) 25456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 25466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len); 25476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 25481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (seq && seq_len) { 25506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq)) 25516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 25526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len); 25536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 25541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (addr && !is_broadcast_ether_addr(addr)) { 25566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); 25576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) 25586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 25591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (alg != WPA_ALG_WEP && key_idx && !set_tx) { 25616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK"); 25626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE, 25636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_KEYTYPE_GROUP)) 25646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 25656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 25666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (addr && is_broadcast_ether_addr(addr)) { 25676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *types; 25681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " broadcast key"); 25701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES); 25726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!types || 25736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST)) 25746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 25756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, types); 25761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 25776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx)) 25786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 25791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL); 25816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE) 25826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = 0; 25836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 25846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)", 25856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 25861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 25886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * If we failed or don't need to set the default TX key (below), 25896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * we're done here. 25906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 25916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret || !set_tx || alg == WPA_ALG_NONE || tdls) 25926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 25936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (is_ap_interface(drv->nlmode) && addr && 25946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !is_broadcast_ether_addr(addr)) 25956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 25961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 25976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY); 25986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || 25996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) || 2600807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt nla_put_flag(msg, (alg == WPA_ALG_IGTK || 2601807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt alg == WPA_ALG_BIP_GMAC_128 || 2602807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt alg == WPA_ALG_BIP_GMAC_256 || 2603807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt alg == WPA_ALG_BIP_CMAC_256) ? 26046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_ATTR_KEY_DEFAULT_MGMT : 26056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_ATTR_KEY_DEFAULT)) 26066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 26076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (addr && is_broadcast_ether_addr(addr)) { 26086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *types; 26091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 26106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES); 26116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!types || 26126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST)) 26136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 26146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, types); 26156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (addr) { 26166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *types; 261734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 26186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES); 26196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!types || 26206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST)) 26216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 26226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, types); 26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 26266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret == -ENOENT) 26276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = 0; 26286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 26296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; " 26306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "err=%d %s)", ret, strerror(-ret)); 26316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 26326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 26336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 26346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_nlmsg_clear(msg); 26356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 26366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl_add_key(struct nl_msg *msg, enum wpa_alg alg, 26416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int key_idx, int defkey, 26426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *seq, size_t seq_len, 26436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *key, size_t key_len) 26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY); 26461d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt u32 suite; 26471d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 26486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!key_attr) 26496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26511d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt suite = wpa_alg_to_cipher_suite(alg, key_len); 26521d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt if (!suite) 26531d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt return -1; 26541d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt 26556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (defkey && alg == WPA_ALG_IGTK) { 26566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_KEY_DEFAULT_MGMT)) 26576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 26586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (defkey) { 26596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_KEY_DEFAULT)) 26606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 266168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 26626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 26636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_KEY_IDX, key_idx) || 26641d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt nla_put_u32(msg, NL80211_KEY_CIPHER, suite) || 26656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (seq && seq_len && 26666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_KEY_SEQ, seq_len, seq)) || 26676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_KEY_DATA, key_len, key)) 26686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 26696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 26706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, key_attr); 26716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 26726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_conn_keys(struct wpa_driver_associate_params *params, 26776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg) 26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int i, privacy = 0; 26806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *nl_keys, *nl_key; 26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < 4; i++) { 26836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!params->wep_key[i]) 26846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt continue; 26856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt privacy = 1; 26866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 26876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 26886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->wps == WPS_MODE_PRIVACY) 26896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt privacy = 1; 26906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->pairwise_suite && 26916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->pairwise_suite != WPA_CIPHER_NONE) 26926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt privacy = 1; 26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!privacy) 26956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_PRIVACY)) 26986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS); 27016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!nl_keys) 27026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < 4; i++) { 27056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!params->wep_key[i]) 27066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt continue; 27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_key = nla_nest_start(msg, i); 27096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!nl_key || 27106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_KEY_DATA, params->wep_key_len[i], 27116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->wep_key[i]) || 27126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_KEY_CIPHER, 27136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->wep_key_len[i] == 5 ? 27146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_CIPHER_SUITE_WEP40 : 27156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_CIPHER_SUITE_WEP104) || 27166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_KEY_IDX, i) || 27176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (i == params->wep_tx_keyidx && 27186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_KEY_DEFAULT))) 27196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 2720cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 27216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, nl_key); 2722cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } 27236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, nl_keys); 27246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 27256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 2726cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt} 2727cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 2728cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 27296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, 27306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr, int cmd, u16 reason_code, 27316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int local_state_change) 2732cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt{ 2733cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int ret; 27342f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt struct nl_msg *msg; 27352f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 27366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, cmd)) || 27376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code) || 27386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) || 27396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (local_state_change && 27406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_ATTR_LOCAL_STATE_CHANGE))) { 27416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 27426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 27436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 27442f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 27456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 27466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 27476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, 27486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: MLME command failed: reason=%u ret=%d (%s)", 27496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt reason_code, ret, strerror(-ret)); 27502f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt } 27516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 27522f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt} 27532f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 27542f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 27556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, 27566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int reason_code) 27572f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt{ 27586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 2759413dde71f7bc166de54229f337c24b61f4d909fdDmitry Shmidt 27606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code); 27616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mark_disconnected(drv); 27626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Disconnect command doesn't need BSSID - it uses cached value */ 27636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT, 27646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt reason_code, 0); 27656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 27666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * For locally generated disconnect, supplicant already generates a 27676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * DEAUTH event, so ignore the event from NL80211. 27686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 27696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ignore_next_local_disconnect = ret == 0; 27702f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 27716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 27722f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt} 27732f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 27742f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 27756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss, 27766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr, int reason_code) 27772f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt{ 27786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 27796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 27802f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 27816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_ADHOC) { 27826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mark_disconnected(drv); 27836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_leave_ibss(drv, 1); 27842f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt } 27856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) 27866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_disconnect(drv, reason_code); 27876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)", 27886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt __func__, MAC2STR(addr), reason_code); 27896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mark_disconnected(drv); 27906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, 27916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt reason_code, 0); 27926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 27936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * For locally generated deauthenticate, supplicant already generates a 27946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * DEAUTH event, so ignore the event from NL80211. 27956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 27966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ignore_next_local_deauth = ret == 0; 27976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 27982f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt} 27992f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 28002f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 28016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv, 28026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_auth_params *params) 28032f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt{ 28042f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt int i; 28052f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 28066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_freq = params->freq; 28076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_alg = params->auth_alg; 28086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_wep_tx_keyidx = params->wep_tx_keyidx; 28096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_local_state_change = params->local_state_change; 28106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_p2p = params->p2p; 2811fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 28126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->bssid) 28136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN); 28146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else 28156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(drv->auth_bssid_, 0, ETH_ALEN); 2816fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 28176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->ssid) { 28186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len); 28196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_ssid_len = params->ssid_len; 28206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else 28216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_ssid_len = 0; 2822fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 2823fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 28246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(drv->auth_ie); 28256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_ie = NULL; 28266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_ie_len = 0; 28276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->ie) { 28286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_ie = os_malloc(params->ie_len); 28296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->auth_ie) { 28306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(drv->auth_ie, params->ie, params->ie_len); 28316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_ie_len = params->ie_len; 28322f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt } 28332f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt } 28342f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 28356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < 4; i++) { 28366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->wep_key[i] && params->wep_key_len[i] && 28376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->wep_key_len[i] <= 16) { 28386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(drv->auth_wep_key[i], params->wep_key[i], 28396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->wep_key_len[i]); 28406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_wep_key_len[i] = params->wep_key_len[i]; 28416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else 28426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->auth_wep_key_len[i] = 0; 28432f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt } 28442f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt} 28452f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 28462f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 28476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_unmask_11b_rates(struct i802_bss *bss) 2848b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt{ 28496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 2850b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 28516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (is_p2p_net_interface(drv->nlmode) || !drv->disabled_11b_rates) 2852b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt return; 2853b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 28546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 28556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Looks like we failed to unmask 11b rates previously. This could 28566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * happen, e.g., if the interface was down at the point in time when a 28576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * P2P group was terminated. 28586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 28596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 28606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Interface %s mode is for non-P2P, but 11b rates were disabled - re-enable them", 28616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname); 28626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_disable_11b_rates(drv, drv->ifindex, 0); 2863b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt} 2864b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 2865b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 28666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_authenticate( 28676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss, struct wpa_driver_auth_params *params) 28682f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt{ 28696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 28706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = -1, i; 28716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 28726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_auth_type type; 28736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_iftype nlmode; 28746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int count = 0; 28756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int is_retry; 28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_unmask_11b_rates(bss); 28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt is_retry = drv->retry_auth; 28806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->retry_auth = 0; 28816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ignore_deauth_event = 0; 28821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 28836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mark_disconnected(drv); 28846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(drv->auth_bssid, 0, ETH_ALEN); 28856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->bssid) 28866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN); 28876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else 28886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN); 28896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* FIX: IBSS mode */ 28906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmode = params->p2p ? 28916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION; 28926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->nlmode != nlmode && 28936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_set_mode(bss, nlmode) < 0) 28946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 28951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 28966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtretry: 28976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)", 28986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ifindex); 28998bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt 29006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_AUTHENTICATE); 29016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 29026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < 4; i++) { 29056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!params->wep_key[i]) 29066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt continue; 29076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_set_key(bss->ifname, bss, WPA_ALG_WEP, 29086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NULL, i, 29096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt i == params->wep_tx_keyidx, NULL, 0, 29106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->wep_key[i], 29116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->wep_key_len[i]); 29126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->wep_tx_keyidx != i) 29136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt continue; 29146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0, 29156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->wep_key[i], params->wep_key_len[i])) 29166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 29171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 29181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 29196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->bssid) { 29206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " * bssid=" MACSTR, 29216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(params->bssid)); 29226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid)) 29236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2924444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 29256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->freq) { 29266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); 29276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq)) 29286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2929fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 29306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->ssid) { 29316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " * SSID", 29326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssid, params->ssid_len); 29336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, 29346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssid)) 29356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 2936fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 29376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len); 29386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->ie && 29396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_IE, params->ie_len, params->ie)) 29406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 29416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->sae_data) { 29426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * SAE data", params->sae_data, 29436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->sae_data_len); 29446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_SAE_DATA, params->sae_data_len, 29456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->sae_data)) 29466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 29476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 29486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_OPEN) 29496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type = NL80211_AUTHTYPE_OPEN_SYSTEM; 29506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_SHARED) 29516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type = NL80211_AUTHTYPE_SHARED_KEY; 29526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_LEAP) 29536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type = NL80211_AUTHTYPE_NETWORK_EAP; 29546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_FT) 29556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type = NL80211_AUTHTYPE_FT; 29566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_SAE) 29576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt type = NL80211_AUTHTYPE_SAE; 29582f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt else 29596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 29606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " * Auth Type %d", type); 29616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type)) 29626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 29636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->local_state_change) { 29646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " * Local state change only"); 29656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_LOCAL_STATE_CHANGE)) 29666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 29672f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt } 29682f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt 29696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 29706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = NULL; 29716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 29726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, 29736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: MLME command failed (auth): ret=%d (%s)", 29746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 29756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt count++; 29766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret == -EALREADY && count == 1 && params->bssid && 29776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !params->local_state_change) { 29786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 29796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * mac80211 does not currently accept new 29806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * authentication if we are already authenticated. As a 29816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * workaround, force deauthentication and try again. 29826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 29836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Retry authentication " 29846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "after forced deauthentication"); 29856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ignore_deauth_event = 1; 29866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_deauthenticate( 29876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss, params->bssid, 29886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID); 29896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 29906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto retry; 29916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 299251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 29936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret == -ENOENT && params->freq && !is_retry) { 29946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 29956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * cfg80211 has likely expired the BSS entry even 29966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * though it was previously available in our internal 29976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * BSS table. To recover quickly, start a single 29986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * channel scan on the specified channel. 29996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 30006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_scan_params scan; 30016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int freqs[2]; 300251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt 30036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(&scan, 0, sizeof(scan)); 30046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan.num_ssids = 1; 30056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->ssid) { 30066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan.ssids[0].ssid = params->ssid; 30076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan.ssids[0].ssid_len = params->ssid_len; 30086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 30096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freqs[0] = params->freq; 30106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freqs[1] = 0; 30116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan.freqs = freqs; 30126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Trigger single " 30136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "channel scan to refresh cfg80211 BSS " 30146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "entry"); 30156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = wpa_driver_nl80211_scan(bss, &scan); 30166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret == 0) { 30176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_copy_auth_params(drv, params); 30186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->scan_for_auth = 1; 30196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 30206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (is_retry) { 30216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 30226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Need to indicate this with an event since the return 30236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * value from the retry is not delivered to core code. 30246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 30256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt union wpa_event_data event; 30266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Authentication retry " 30276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "failed"); 30286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(&event, 0, sizeof(event)); 30296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(event.timeout_event.addr, drv->auth_bssid_, 30306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ETH_ALEN); 30316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT, 30326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt &event); 30336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 30346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 30356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 30366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Authentication request send successfully"); 30376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 3038fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 30396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 30416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_authenticate_retry(struct wpa_driver_nl80211_data *drv) 30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_auth_params params; 30486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = drv->first_bss; 30496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int i; 30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again"); 3052ad266fb3da6083126e7619e525153839b918aa44Dmitry Shmidt 30536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 30546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.freq = drv->auth_freq; 30556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.auth_alg = drv->auth_alg; 30566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.wep_tx_keyidx = drv->auth_wep_tx_keyidx; 30576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.local_state_change = drv->auth_local_state_change; 30586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.p2p = drv->auth_p2p; 3059a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 30606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!is_zero_ether_addr(drv->auth_bssid_)) 30616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.bssid = drv->auth_bssid_; 30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->auth_ssid_len) { 30646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.ssid = drv->auth_ssid; 30656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.ssid_len = drv->auth_ssid_len; 306661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 306761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 30686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.ie = drv->auth_ie; 30696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.ie_len = drv->auth_ie_len; 30701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 30716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < 4; i++) { 30726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->auth_wep_key_len[i]) { 30736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.wep_key[i] = drv->auth_wep_key[i]; 30746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params.wep_key_len[i] = drv->auth_wep_key_len[i]; 30751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->retry_auth = 1; 30796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_authenticate(bss, ¶ms); 30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_send_frame(struct i802_bss *bss, 30846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const void *data, size_t len, 30856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int encrypt, int noack, 30866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int freq, int no_cck, 30876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int offchanok, unsigned int wait_time) 30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 30906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u64 cookie; 30916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int res; 30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (freq == 0 && drv->nlmode == NL80211_IFTYPE_ADHOC) { 30946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq = nl80211_get_assoc_freq(drv); 30956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 30966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: send_frame - Use assoc_freq=%u for IBSS", 30976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq); 30986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 30996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (freq == 0) { 31006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u", 31016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->freq); 31026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq = bss->freq; 31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->use_monitor) { 31066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: send_frame(freq=%u bss->freq=%u) -> send_monitor", 31076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq, bss->freq); 31086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_send_monitor(drv, data, len, encrypt, noack); 31096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd"); 31126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len, 31136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt &cookie, no_cck, noack, offchanok); 31146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res == 0 && !noack) { 31156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const struct ieee80211_mgmt *mgmt; 31166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 fc; 31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt mgmt = (const struct ieee80211_mgmt *) data; 31196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt fc = le_to_host16(mgmt->frame_control); 31206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 31216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { 31226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_MSGDUMP, 31236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Update send_action_cookie from 0x%llx to 0x%llx", 31246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (long long unsigned int) 31256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->send_action_cookie, 31266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (long long unsigned int) cookie); 31276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->send_action_cookie = cookie; 31286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 31296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return res; 31321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 31356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, 31366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t data_len, int noack, 31376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int freq, int no_cck, 31386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int offchanok, 31396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int wait_time) 31401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 31416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 31426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct ieee80211_mgmt *mgmt; 31436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int encrypt = 1; 31446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 fc; 31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt mgmt = (struct ieee80211_mgmt *) data; 31476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt fc = le_to_host16(mgmt->frame_control); 31486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR 31496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x (%s) nlmode=%d", 31506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time, 31516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt fc, fc2str(fc), drv->nlmode); 31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((is_sta_interface(drv->nlmode) || 31546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) && 31556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 31566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) { 31576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 31586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * The use of last_mgmt_freq is a bit of a hack, 31596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * but it works due to the single-threaded nature 31606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * of wpa_supplicant. 31616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 31626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (freq == 0) { 31636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d", 31646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->last_mgmt_freq); 31656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq = drv->last_mgmt_freq; 31666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 31676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_send_frame_cmd(bss, freq, 0, 31686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt data, data_len, NULL, 1, noack, 31696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1); 31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) { 31736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (freq == 0) { 31746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d", 31756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->freq); 31766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq = bss->freq; 31776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 31786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_send_frame_cmd(bss, freq, 31796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (int) freq == bss->freq ? 0 : 31806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wait_time, 31816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt data, data_len, 31826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt &drv->send_action_cookie, 31836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt no_cck, noack, offchanok); 31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 31876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) { 31886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 31896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * Only one of the authentication frame types is encrypted. 31906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * In order for static WEP encryption to work properly (i.e., 31916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * to not encrypt the frame), we need to tell mac80211 about 31926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * the frames that must not be encrypted. 31936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 31946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg); 31956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction); 31966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3) 31976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt encrypt = 0; 3198fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 3199fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 32006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame"); 32016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 32026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt noack, freq, no_cck, offchanok, 32036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wait_time); 32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3207ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic int nl80211_put_basic_rates(struct nl_msg *msg, const int *basic_rates) 3208ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{ 3209ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt u8 rates[NL80211_MAX_SUPP_RATES]; 3210ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt u8 rates_len = 0; 3211ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int i; 3212ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 3213ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!basic_rates) 3214ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 3215ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 3216ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++) 3217ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt rates[rates_len++] = basic_rates[i] / 5; 3218ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 3219ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); 3220ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt} 3221ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 3222ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 32236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble, 32246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int slot, int ht_opmode, int ap_isolate, 3225ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt const int *basic_rates) 32261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 32276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 32286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 32291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_BSS)) || 32316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (cts >= 0 && 32326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_BSS_CTS_PROT, cts)) || 32336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (preamble >= 0 && 32346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble)) || 32356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (slot >= 0 && 32366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot)) || 32376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (ht_opmode >= 0 && 32386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode)) || 32396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (ap_isolate >= 0 && 3240ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate)) || 3241ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nl80211_put_basic_rates(msg, basic_rates)) { 3242ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nlmsg_free(msg); 3243ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return -ENOBUFS; 32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 32456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 32466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_set_acl(void *priv, 32516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct hostapd_acl_params *params) 32521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 32536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 32546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 32556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 32566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *acl; 32576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int i; 32586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 32591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.max_acl_mac_addrs)) 32616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOTSUP; 32621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->num_mac_acl > drv->capa.max_acl_mac_addrs) 32646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOTSUP; 32651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)", 32676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->acl_policy ? "Accept" : "Deny", params->num_mac_acl); 32681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MAC_ACL)) || 32706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ? 32716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_ACL_POLICY_DENY_UNLESS_LISTED : 32726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED) || 32736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS)) == NULL) { 32746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 32756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOMEM; 32766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 32771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt for (i = 0; i < params->num_mac_acl; i++) { 32796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr)) { 32806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 32816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOMEM; 32821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 32831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 32841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, acl); 32861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 32886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 32896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)", 32906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 32916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 32926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 32936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 32941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 32951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 32961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3297ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic int nl80211_put_beacon_int(struct nl_msg *msg, int beacon_int) 3298ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{ 3299ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (beacon_int > 0) { 3300ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * beacon_int=%d", beacon_int); 3301ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL, 3302ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt beacon_int); 3303ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 3304ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 3305ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 3306ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt} 3307ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 3308ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 33096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_set_ap(void *priv, 33106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_ap_params *params) 33111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 33126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 33136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 33146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 33156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 cmd = NL80211_CMD_NEW_BEACON; 33166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 33176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int beacon_set; 33186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int num_suites; 33196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int smps_mode; 33206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 suites[10], suite; 33216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 ver; 33221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 33237f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt beacon_set = params->reenable ? 0 : bss->beacon_set; 33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)", 33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_set); 33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (beacon_set) 33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cmd = NL80211_CMD_SET_BEACON; 33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33300ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head", 33310ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->head, params->head_len); 33320ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: Beacon tail", 33330ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->tail, params->tail_len); 33346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", bss->ifindex); 33350ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int); 33360ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period); 33370ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid", 33380ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->ssid, params->ssid_len); 33396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, cmd)) || 33406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, 33416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->head) || 33426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, 33436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->tail) || 3344ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nl80211_put_beacon_int(msg, params->beacon_int) || 33456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period) || 33466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid)) 33476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 33480ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt if (params->proberesp && params->proberesp_len) { 33490ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)", 33500ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->proberesp, params->proberesp_len); 33516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len, 33526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->proberesp)) 33536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 33540ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt } 33551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (params->hide_ssid) { 33561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NO_SSID_HIDING: 33570ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: hidden SSID not in use"); 33586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID, 33596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_HIDDEN_SSID_NOT_IN_USE)) 33606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 33611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 33621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case HIDDEN_SSID_ZERO_LEN: 33630ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero len"); 33646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID, 33656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_HIDDEN_SSID_ZERO_LEN)) 33666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 33671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 33681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case HIDDEN_SSID_ZERO_CONTENTS: 33690ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero contents"); 33706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_HIDDEN_SSID, 33716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_HIDDEN_SSID_ZERO_CONTENTS)) 33726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 33731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 33741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 33750ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: privacy=%d", params->privacy); 33766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->privacy && 33776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_ATTR_PRIVACY)) 33786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 33790ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: auth_algs=0x%x", params->auth_algs); 33801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) == 33811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) { 33821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Leave out the attribute */ 33836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (params->auth_algs & WPA_AUTH_ALG_SHARED) { 33846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, 33856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_AUTHTYPE_SHARED_KEY)) 33866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 33876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 33886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, 33896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_AUTHTYPE_OPEN_SYSTEM)) 33906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 33916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 33921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 33930ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version); 33941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ver = 0; 33951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->wpa_version & WPA_PROTO_WPA) 33961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ver |= NL80211_WPA_VERSION_1; 33971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->wpa_version & WPA_PROTO_RSN) 33981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ver |= NL80211_WPA_VERSION_2; 33996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ver && 34006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver)) 34016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 34030ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x", 34040ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->key_mgmt_suites); 34051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt num_suites = 0; 34061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X) 34071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt suites[num_suites++] = WLAN_AKM_SUITE_8021X; 34081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK) 34091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt suites[num_suites++] = WLAN_AKM_SUITE_PSK; 34106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites && 34116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), 34126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt suites)) 34136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 34156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA && 34166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40) && 34176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)) 34186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 34200ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x", 34210ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->pairwise_ciphers); 3422fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers, 3423fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt suites, ARRAY_SIZE(suites)); 34246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (num_suites && 34256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, 34266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt num_suites * sizeof(u32), suites)) 34276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 34290ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x", 34300ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->group_cipher); 3431fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt suite = wpa_cipher_to_cipher_suite(params->group_cipher); 34326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (suite && 34336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite)) 34346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 34366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (params->smps_mode) { 34376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_DYNAMIC: 34386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - dynamic"); 34396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt smps_mode = NL80211_SMPS_DYNAMIC; 34406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 34416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_STATIC: 34426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - static"); 34436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt smps_mode = NL80211_SMPS_STATIC; 34446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 34456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 34466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* invalid - fallback to smps off */ 34476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_DISABLED: 34486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - off"); 34496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt smps_mode = NL80211_SMPS_OFF; 34506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 34516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 34526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_SMPS_MODE, smps_mode)) 34536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 34551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->beacon_ies) { 34560ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies", 34570ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->beacon_ies); 34586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_IE, 34596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_len(params->beacon_ies), 34606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_head(params->beacon_ies))) 34616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 34631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->proberesp_ies) { 34640ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "nl80211: proberesp_ies", 34650ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->proberesp_ies); 34666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_IE_PROBE_RESP, 34676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_len(params->proberesp_ies), 34686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_head(params->proberesp_ies))) 34696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 34711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->assocresp_ies) { 34720ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_hexdump_buf(MSG_DEBUG, "nl80211: assocresp_ies", 34730ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->assocresp_ies); 34746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP, 34756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_len(params->assocresp_ies), 34766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_head(params->assocresp_ies))) 34776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 34781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER) { 34810ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: ap_max_inactivity=%d", 34820ccb66edb8d2a0a397320ace3ec2a03fb0d00d5fDmitry Shmidt params->ap_max_inactivity); 34836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT, 34846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ap_max_inactivity)) 34856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 348604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 348704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 34887f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#ifdef CONFIG_P2P 34897f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (params->p2p_go_ctwindow > 0) { 34907f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (drv->p2p_go_ctwindow_supported) { 34917f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: P2P GO ctwindow=%d", 34927f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt params->p2p_go_ctwindow); 34937f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (nla_put_u8(msg, NL80211_ATTR_P2P_CTWINDOW, 34947f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt params->p2p_go_ctwindow)) 34957f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt goto fail; 34967f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } else { 34977f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_INFO, 34987f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "nl80211: Driver does not support CTWindow configuration - ignore this parameter"); 34997f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 35007f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 35017f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#endif /* CONFIG_P2P */ 35027f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 35058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", 35068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret, strerror(-ret)); 35078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 35088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->beacon_set = 1; 35091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_set_bss(bss, params->cts_protect, params->preamble, 35101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->short_slot_time, params->ht_opmode, 35111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->isolate, params->basic_rates); 35127832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (beacon_set && params->freq && 35137832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt params->freq->bandwidth != bss->bandwidth) { 35147832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_DEBUG, 35157832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "nl80211: Update BSS %s bandwidth: %d -> %d", 35167832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt bss->ifname, bss->bandwidth, 35177832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt params->freq->bandwidth); 35187832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret = nl80211_set_channel(bss, params->freq, 1); 35197832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret) { 35207832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_DEBUG, 35217832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "nl80211: Frequency set failed: %d (%s)", 35227832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret, strerror(-ret)); 35237832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } else { 35247832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_DEBUG, 35257832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "nl80211: Frequency set succeeded for ht2040 coex"); 35267832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt bss->bandwidth = params->freq->bandwidth; 35277832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 35287832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } else if (!beacon_set) { 35297832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt /* 35307832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * cfg80211 updates the driver on frequence change in AP 35317832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * mode only at the point when beaconing is started, so 35327832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * set the initial value here. 35337832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt */ 35347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt bss->bandwidth = params->freq->bandwidth; 35357832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 35386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 35391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nlmsg_free(msg); 35408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 35418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 35428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3544e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtstatic int nl80211_put_freq_params(struct nl_msg *msg, 35456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const struct hostapd_freq_params *freq) 35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3547ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * freq=%d", freq->freq); 35486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq)) 35496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 35506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3551ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * vht_enabled=%d", freq->vht_enabled); 3552ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * ht_enabled=%d", freq->ht_enabled); 3553ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 3554a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (freq->vht_enabled) { 35556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_chan_width cw; 35566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3557ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * bandwidth=%d", freq->bandwidth); 3558a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt switch (freq->bandwidth) { 3559a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case 20: 35606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cw = NL80211_CHAN_WIDTH_20; 3561a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 3562a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case 40: 35636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cw = NL80211_CHAN_WIDTH_40; 3564a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 3565a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case 80: 3566a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (freq->center_freq2) 35676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cw = NL80211_CHAN_WIDTH_80P80; 3568a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt else 35696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cw = NL80211_CHAN_WIDTH_80; 3570a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 3571a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case 160: 35726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cw = NL80211_CHAN_WIDTH_160; 3573a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 3574a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt default: 3575e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return -EINVAL; 3576a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 35776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3578ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * channel_width=%d", cw); 3579ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * center_freq1=%d", 3580ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt freq->center_freq1); 3581ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * center_freq2=%d", 3582ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt freq->center_freq2); 35836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cw) || 35846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ1, 35856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq->center_freq1) || 35866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (freq->center_freq2 && 35876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_CENTER_FREQ2, 35886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq->center_freq2))) 35896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 3590a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } else if (freq->ht_enabled) { 35916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_channel_type ct; 35926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3593ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * sec_channel_offset=%d", 3594ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt freq->sec_channel_offset); 3595a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt switch (freq->sec_channel_offset) { 35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case -1: 35976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ct = NL80211_CHAN_HT40MINUS; 35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 36006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ct = NL80211_CHAN_HT40PLUS; 36018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 36028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 36036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ct = NL80211_CHAN_HT20; 36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 36066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 3607ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, " * channel_type=%d", ct); 36086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct)) 36096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 36108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3611e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return 0; 3612e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt} 3613e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 3614e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 36157832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidtstatic int nl80211_set_channel(struct i802_bss *bss, 36167832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt struct hostapd_freq_params *freq, int set_chan) 3617e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{ 3618e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 3619e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt struct nl_msg *msg; 3620e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt int ret; 3621e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 3622e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt wpa_printf(MSG_DEBUG, 3623e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)", 3624e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt freq->freq, freq->ht_enabled, freq->vht_enabled, 3625e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt freq->bandwidth, freq->center_freq1, freq->center_freq2); 3626e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 36276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL : 36286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_SET_WIPHY); 36296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || nl80211_put_freq_params(msg, freq) < 0) { 36306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 36316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 36326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 36351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret == 0) { 3636a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt bss->freq = freq->freq; 36378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 36381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 36398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): " 3640a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt "%d (%s)", freq->freq, ret, strerror(-ret)); 36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 36428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic u32 sta_flags_nl80211(int flags) 36468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 36471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u32 f = 0; 36488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (flags & WPA_STA_AUTHORIZED) 36501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f |= BIT(NL80211_STA_FLAG_AUTHORIZED); 36511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (flags & WPA_STA_WMM) 36521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f |= BIT(NL80211_STA_FLAG_WME); 36531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (flags & WPA_STA_SHORT_PREAMBLE) 36541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE); 36551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (flags & WPA_STA_MFP) 36561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f |= BIT(NL80211_STA_FLAG_MFP); 36571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (flags & WPA_STA_TDLS_PEER) 36581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt f |= BIT(NL80211_STA_FLAG_TDLS_PEER); 36596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (flags & WPA_STA_AUTHENTICATED) 36606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt f |= BIT(NL80211_STA_FLAG_AUTHENTICATED); 36611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 36621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return f; 36631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 36641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 36651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 36666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_MESH 36676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic u32 sta_plink_state_nl80211(enum mesh_plink_state state) 36686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 36696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (state) { 36706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case PLINK_LISTEN: 36716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_PLINK_LISTEN; 36726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case PLINK_OPEN_SENT: 36736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_PLINK_OPN_SNT; 36746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case PLINK_OPEN_RCVD: 36756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_PLINK_OPN_RCVD; 36766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case PLINK_CNF_RCVD: 36776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_PLINK_CNF_RCVD; 36786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case PLINK_ESTAB: 36796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_PLINK_ESTAB; 36806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case PLINK_HOLDING: 36816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_PLINK_HOLDING; 36826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case PLINK_BLOCKED: 36836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_PLINK_BLOCKED; 36846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 36856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Invalid mesh plink state %d", 36866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt state); 36876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 36886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 36896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 36906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_MESH */ 36916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 36926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 36931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_driver_nl80211_sta_add(void *priv, 36941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct hostapd_sta_add_params *params) 36951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 36961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct i802_bss *bss = priv; 36971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 36988da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt struct nl_msg *msg; 36991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct nl80211_sta_flag_update upd; 37001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret = -ENOBUFS; 37011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 37021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((params->flags & WPA_STA_TDLS_PEER) && 37031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) 37041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -EOPNOTSUPP; 37051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3706f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR, 3707f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt params->set ? "Set" : "Add", MAC2STR(params->addr)); 37086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_bss_msg(bss, 0, params->set ? NL80211_CMD_SET_STATION : 37096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_NEW_STATION); 37106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr)) 37116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 37126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 37136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!params->set || (params->flags & WPA_STA_TDLS_PEER)) { 37146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * supported rates", 37156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->supp_rates, params->supp_rates_len); 37166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " * capability=0x%x", 37176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->capability); 37186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_RATES, 37196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->supp_rates_len, params->supp_rates) || 37206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_STA_CAPABILITY, 37216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->capability)) 37226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 37236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 37246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->ht_capabilities) { 37256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * ht_capabilities", 37266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (u8 *) params->ht_capabilities, 37276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sizeof(*params->ht_capabilities)); 37286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_HT_CAPABILITY, 37296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sizeof(*params->ht_capabilities), 37306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ht_capabilities)) 37316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 37326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 37336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 37346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->vht_capabilities) { 37356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * vht_capabilities", 37366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (u8 *) params->vht_capabilities, 37376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sizeof(*params->vht_capabilities)); 37386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_VHT_CAPABILITY, 37396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sizeof(*params->vht_capabilities), 37406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->vht_capabilities)) 37416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 37426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 37436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 37446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->ext_capab) { 37456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * ext_capab", 37466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ext_capab, params->ext_capab_len); 37476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_STA_EXT_CAPABILITY, 37486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ext_capab_len, params->ext_capab)) 37496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 37506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 37516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 37521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!params->set) { 375351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (params->aid) { 375451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_printf(MSG_DEBUG, " * aid=%u", params->aid); 37556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u16(msg, NL80211_ATTR_STA_AID, params->aid)) 37566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 375751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt } else { 375851b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt /* 375951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt * cfg80211 validates that AID is non-zero, so we have 376051b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt * to make this a non-zero value for the TDLS case where 376151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt * a dummy STA entry is used for now. 376251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt */ 376351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)"); 37646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u16(msg, NL80211_ATTR_STA_AID, 1)) 37656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 376651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt } 3767f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, " * listen_interval=%u", 3768f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt params->listen_interval); 37696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, 37706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->listen_interval)) 37716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 37728bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) { 37738bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid); 37746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u16(msg, NL80211_ATTR_PEER_AID, params->aid)) 37756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3776a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 3777a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 3778bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt if (params->vht_opmode_enabled) { 3779bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt wpa_printf(MSG_DEBUG, " * opmode=%u", params->vht_opmode); 37806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_ATTR_OPMODE_NOTIF, 37816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->vht_opmode)) 37826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3783f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt } 3784f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt 3785344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (params->supp_channels) { 3786344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " * supported channels", 3787344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt params->supp_channels, params->supp_channels_len); 37886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_CHANNELS, 37896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->supp_channels_len, params->supp_channels)) 37906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3791344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 3792344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 3793344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (params->supp_oper_classes) { 3794344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " * supported operating classes", 3795344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt params->supp_oper_classes, 3796344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt params->supp_oper_classes_len); 37976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES, 37986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->supp_oper_classes_len, 37996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->supp_oper_classes)) 38006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 3801344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt } 3802344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 38031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&upd, 0, sizeof(upd)); 38046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt upd.set = sta_flags_nl80211(params->flags); 38056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt upd.mask = upd.set | sta_flags_nl80211(params->flags_mask); 3806f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x", 3807f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt upd.set, upd.mask); 38086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) 38096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 38106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 38116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_MESH 38126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->plink_state && 38136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_STA_PLINK_STATE, 38146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt sta_plink_state_nl80211(params->plink_state))) 38156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 38166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_MESH */ 38171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 38181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->flags & WPA_STA_WMM) { 38198da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME); 38208da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt 3821f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt wpa_printf(MSG_DEBUG, " * qosinfo=0x%x", params->qosinfo); 38226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!wme || 38236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES, 38246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->qosinfo & WMM_QOSINFO_STA_AC_MASK) || 38256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_STA_WME_MAX_SP, 38266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) & 38276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WMM_QOSINFO_STA_SP_MASK)) 38286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 38298da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt nla_nest_end(msg, wme); 38301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 38311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 38331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt msg = NULL; 38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 38351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION " 38361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "result: %d (%s)", params->set ? "SET" : "NEW", ret, 38371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt strerror(-ret)); 38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -EEXIST) 38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 38406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 38411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nlmsg_free(msg); 38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 38438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 38448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3846661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidtstatic void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr) 3847661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{ 3848661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#ifdef CONFIG_LIBNL3_ROUTE 3849661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 3850661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct rtnl_neigh *rn; 3851661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct nl_addr *nl_addr; 3852661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt int err; 3853661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 3854661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rn = rtnl_neigh_alloc(); 3855661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (!rn) 3856661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return; 3857661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 3858661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rtnl_neigh_set_family(rn, AF_BRIDGE); 3859661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rtnl_neigh_set_ifindex(rn, bss->ifindex); 3860661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN); 3861661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (!nl_addr) { 3862661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rtnl_neigh_put(rn); 3863661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return; 3864661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 3865661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rtnl_neigh_set_lladdr(rn, nl_addr); 3866661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 3867661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0); 3868661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (err < 0) { 3869661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for " 3870661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt MACSTR " ifindex=%d failed: %s", MAC2STR(addr), 3871661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt bss->ifindex, nl_geterror(err)); 3872661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } else { 3873661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for " 3874661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt MACSTR, MAC2STR(addr)); 3875661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 3876661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 3877661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt nl_addr_put(nl_addr); 3878661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rtnl_neigh_put(rn); 3879661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#endif /* CONFIG_LIBNL3_ROUTE */ 3880661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt} 3881661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 3882661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 38836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr, 38846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int deauth, u16 reason_code) 38858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 38868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 38878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION)) || 38916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || 38926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (deauth == 0 && 38936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_MGMT_SUBTYPE, 38946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_DISASSOC)) || 38956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (deauth == 1 && 38966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_MGMT_SUBTYPE, 38976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_DEAUTH)) || 38986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (reason_code && 38996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_REASON_CODE, reason_code))) { 39006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 39016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 39026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 39038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 3905b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR 3906b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt " --> %d (%s)", 3907b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt bss->ifname, MAC2STR(addr), ret, strerror(-ret)); 3908661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 3909661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (drv->rtnl_sk) 3910661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt rtnl_neigh_delete_fdb_entry(bss, addr); 3911661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 39128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -ENOENT) 39138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtvoid nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx) 39198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 392176cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt struct wpa_driver_nl80211_data *drv2; 39228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx); 39248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* stop listening for EAPOL on this interface */ 392676cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt dl_list_for_each(drv2, &drv->global->interfaces, 392776cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt struct wpa_driver_nl80211_data, list) 392876cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt del_ifidx(drv2, ifidx); 39298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE); 39318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) 39328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 39338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx); 39348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 39358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic const char * nl80211_iftype_str(enum nl80211_iftype mode) 39381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 39391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (mode) { 39401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NL80211_IFTYPE_ADHOC: 39411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return "ADHOC"; 39421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NL80211_IFTYPE_STATION: 39431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return "STATION"; 39441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NL80211_IFTYPE_AP: 39451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return "AP"; 3946f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt case NL80211_IFTYPE_AP_VLAN: 3947f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return "AP_VLAN"; 3948f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt case NL80211_IFTYPE_WDS: 3949f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return "WDS"; 39501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NL80211_IFTYPE_MONITOR: 39511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return "MONITOR"; 3952f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt case NL80211_IFTYPE_MESH_POINT: 3953f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt return "MESH_POINT"; 39541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NL80211_IFTYPE_P2P_CLIENT: 39551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return "P2P_CLIENT"; 39561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case NL80211_IFTYPE_P2P_GO: 39571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return "P2P_GO"; 395834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case NL80211_IFTYPE_P2P_DEVICE: 395934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return "P2P_DEVICE"; 39601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 39611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return "unknown"; 39621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 39631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 39641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 39651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv, 39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, 39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_iftype iftype, 396934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt const u8 *addr, int wds, 397034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt int (*handler)(struct nl_msg *, void *), 397134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt void *arg) 39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 39738da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt struct nl_msg *msg; 39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifidx; 39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -ENOBUFS; 39768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)", 39781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iftype, nl80211_iftype_str(iftype)); 39791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 39806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_NEW_INTERFACE); 39816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || 39826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_string(msg, NL80211_ATTR_IFNAME, ifname) || 39836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_IFTYPE, iftype)) 39846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 39858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iftype == NL80211_IFTYPE_MONITOR) { 39878da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt struct nlattr *flags; 39888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39898da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS); 39906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!flags || 39916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_MNTR_FLAG_COOK_FRAMES)) 39926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 39938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39948da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt nla_nest_end(msg, flags); 39958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wds) { 39966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_ATTR_4ADDR, wds)) 39976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 39988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 39998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4000b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt /* 4001b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt * Tell cfg80211 that the interface belongs to the socket that created 4002b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt * it, and the interface should be deleted when the socket is closed. 4003b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt */ 40046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER)) 40056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 4006b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 400734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, handler, arg); 40081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt msg = NULL; 40098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 40106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt fail: 40111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nlmsg_free(msg); 40128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)", 40138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, ret, strerror(-ret)); 40148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 40158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 40168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 401734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (iftype == NL80211_IFTYPE_P2P_DEVICE) 401834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return 0; 401934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 40208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifidx = if_nametoindex(ifname); 40218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d", 40228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, ifidx); 40238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifidx <= 0) 40258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 40268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 402776cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt /* 402876cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt * Some virtual interfaces need to process EAPOL packets and events on 402976cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt * the parent interface. This is used mainly with hostapd. 403076cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt */ 403176cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt if (drv->hostapd || 403276cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt iftype == NL80211_IFTYPE_AP_VLAN || 403376cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt iftype == NL80211_IFTYPE_WDS || 403476cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt iftype == NL80211_IFTYPE_MONITOR) { 403576cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt /* start listening for EAPOL on this interface */ 403676cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt add_ifidx(drv, ifidx); 403776cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt } 40388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr && iftype != NL80211_IFTYPE_MONITOR && 40401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) { 40418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 40428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 40438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 40448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ifidx; 40468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 40478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint nl80211_create_iface(struct wpa_driver_nl80211_data *drv, 40506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const char *ifname, enum nl80211_iftype iftype, 40516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr, int wds, 40526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int (*handler)(struct nl_msg *, void *), 40536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt void *arg, int use_existing) 40548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 40558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 40568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 405734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler, 405834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt arg); 40598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* if error occurred and interface exists already */ 40618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -ENFILE && if_nametoindex(ifname)) { 4062cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (use_existing) { 4063cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Continue using existing interface %s", 4064cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt ifname); 4065df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (addr && iftype != NL80211_IFTYPE_MONITOR && 4066df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, 4067df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt addr) < 0 && 4068df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt (linux_set_iface_flags(drv->global->ioctl_sock, 4069df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt ifname, 0) < 0 || 4070df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, 4071df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt addr) < 0 || 4072df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt linux_set_iface_flags(drv->global->ioctl_sock, 4073df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt ifname, 1) < 0)) 4074df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return -1; 4075cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return -ENFILE; 4076cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } 40778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname); 40788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to remove the interface that was already there. */ 40808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, if_nametoindex(ifname)); 40818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to create the interface again */ 40838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_create_iface_once(drv, ifname, iftype, addr, 408434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wds, handler, arg); 40858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 40868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret >= 0 && is_p2p_net_interface(iftype)) { 40886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 40896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Interface %s created for P2P - disable 11b rates", 40906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ifname); 40918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_disable_11b_rates(drv, ret, 1); 40928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 40938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 40958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 40968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nl80211_setup_ap(struct i802_bss *bss) 40991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 41001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 41011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4102cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Setup AP(%s) - device_ap_sme=%d use_monitor=%d", 4103cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt bss->ifname, drv->device_ap_sme, drv->use_monitor); 41041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 41061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Disable Probe Request reporting unless we need it in this way for 41071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * devices that include the AP SME, in the other case (unless using 41081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * monitor iface) we'll get it through the nl_mgmt socket instead. 41091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 41101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!drv->device_ap_sme) 41111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_driver_nl80211_probe_req_report(bss, 0); 41121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!drv->device_ap_sme && !drv->use_monitor) 41141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (nl80211_mgmt_subscribe_ap(bss)) 41151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 41161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (drv->device_ap_sme && !drv->use_monitor) 41181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (nl80211_mgmt_subscribe_ap_dev_sme(bss)) 41191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 41201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!drv->device_ap_sme && drv->use_monitor && 41221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_create_monitor_interface(drv) && 41231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt !drv->device_ap_sme) 412404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 412504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 41261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (drv->device_ap_sme && 41271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_driver_nl80211_probe_req_report(bss, 1) < 0) { 41281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to enable " 41291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Probe Request frame reporting in AP mode"); 41301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Try to survive without this */ 41311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 41321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 41341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 41351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nl80211_teardown_ap(struct i802_bss *bss) 41381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 41391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 41401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4141cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Teardown AP(%s) - device_ap_sme=%d use_monitor=%d", 4142cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt bss->ifname, drv->device_ap_sme, drv->use_monitor); 41431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (drv->device_ap_sme) { 41441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_driver_nl80211_probe_req_report(bss, 0); 41451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!drv->use_monitor) 41461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)"); 41471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (drv->use_monitor) 41481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_remove_monitor_interface(drv); 41491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 41501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_mgmt_unsubscribe(bss, "AP teardown"); 41511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->beacon_set = 0; 41531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 41541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nl80211_send_eapol_data(struct i802_bss *bss, 41571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *addr, const u8 *data, 41581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t data_len) 41591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 41601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct sockaddr_ll ll; 41611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 41621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (bss->drv->eapol_tx_sock < 0) { 41641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL"); 41651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 41661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 41671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(&ll, 0, sizeof(ll)); 41691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ll.sll_family = AF_PACKET; 41701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ll.sll_ifindex = bss->ifindex; 41711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ll.sll_protocol = htons(ETH_P_PAE); 41721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ll.sll_halen = ETH_ALEN; 41731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(ll.sll_addr, addr, ETH_ALEN); 41741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0, 41751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (struct sockaddr *) &ll, sizeof(ll)); 41761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret < 0) 41771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s", 41781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt strerror(errno)); 41791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 41811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 41821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 41848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; 41858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_hapd_send_eapol( 41878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *priv, const u8 *addr, const u8 *data, 41888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len, int encrypt, const u8 *own_addr, u32 flags) 41898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 41908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 41918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 41928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_hdr *hdr; 41938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 41948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 41958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 41968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int qos = flags & WPA_STA_WMM; 4197641185ebd73d9607756c87b22f6c520ab1846325Dmitry Shmidt 41981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (drv->device_ap_sme || !drv->use_monitor) 41991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return nl80211_send_eapol_data(bss, addr, data, data_len); 42001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 42018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + 42028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len; 42038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = os_zalloc(len); 42048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr == NULL) { 420568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to allocate EAPOL buffer(len=%lu)", 420668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt (unsigned long) len); 42078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 42088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control = 42118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); 42128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); 42138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypt) 42148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); 42158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (qos) { 42168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control |= 42178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4); 42188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); 42218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); 42228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); 42238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 42248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (qos) { 4226aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt /* Set highest priority in QoS header */ 4227aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt pos[0] = 7; 42288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[1] = 0; 42298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 42308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); 42338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(rfc1042_header); 42348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, ETH_P_PAE); 42358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 42368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(pos, data, data_len); 42378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0, 4239c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 0, 0, 0, 0); 42408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 42418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - " 42428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed: %d (%s)", 42438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, errno, strerror(errno)); 42448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 42468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 42488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 42498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr, 42528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int total_flags, 42538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int flags_or, int flags_and) 42548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 42558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 42568da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt struct nl_msg *msg; 42578da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt struct nlattr *flags; 42588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_sta_flag_update upd; 42598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4260661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set STA flags - ifname=%s addr=" MACSTR 4261661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt " total_flags=0x%x flags_or=0x%x flags_and=0x%x authorized=%d", 4262661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt bss->ifname, MAC2STR(addr), total_flags, flags_or, flags_and, 4263661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt !!(total_flags & WPA_STA_AUTHORIZED)); 4264661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 42656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) || 42666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) 42676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 42688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 42708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This 42718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * can be removed eventually. 42728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 42738da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS); 42746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!flags || 42756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ((total_flags & WPA_STA_AUTHORIZED) && 42766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_STA_FLAG_AUTHORIZED)) || 42776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ((total_flags & WPA_STA_WMM) && 42786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_STA_FLAG_WME)) || 42796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ((total_flags & WPA_STA_SHORT_PREAMBLE) && 42806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_STA_FLAG_SHORT_PREAMBLE)) || 42816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ((total_flags & WPA_STA_MFP) && 42826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_STA_FLAG_MFP)) || 42836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ((total_flags & WPA_STA_TDLS_PEER) && 42846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_STA_FLAG_TDLS_PEER))) 42856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 42861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 42878da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt nla_nest_end(msg, flags); 42888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&upd, 0, sizeof(upd)); 42908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt upd.mask = sta_flags_nl80211(flags_or | ~flags_and); 42918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt upd.set = sta_flags_nl80211(flags_or); 42926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) 42936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 42948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(bss->drv, msg, NULL, NULL); 42966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 42971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nlmsg_free(msg); 42988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 42998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 43008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, 43038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_associate_params *params) 43048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4305a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt enum nl80211_iftype nlmode, old_mode; 43061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 43071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->p2p) { 43088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P " 43098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group (GO)"); 43101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nlmode = NL80211_IFTYPE_P2P_GO; 43111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 43121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nlmode = NL80211_IFTYPE_AP; 43131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4314a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt old_mode = drv->nlmode; 4315cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (wpa_driver_nl80211_set_mode(drv->first_bss, nlmode)) { 4316a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt nl80211_remove_monitor_interface(drv); 4317a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 4318a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 4319a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 4320203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt if (params->freq.freq && 4321203eadb9eda41a1dde4a583edb4684319e3f399eDmitry Shmidt nl80211_set_channel(drv->first_bss, ¶ms->freq, 0)) { 4322a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (old_mode != nlmode) 4323cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_driver_nl80211_set_mode(drv->first_bss, old_mode); 43248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_monitor_interface(drv); 43258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 43268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 43298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 43308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv, 43336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int reset_mode) 43348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 43358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 43366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 43378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS); 43398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 43408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 43418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d " 43428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 43436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 43446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 43456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Leave IBSS request sent successfully"); 43468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (reset_mode && 43496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_set_mode(drv->first_bss, 43505605286c30e1701491bd3af974ae423727750eddDmitry Shmidt NL80211_IFTYPE_STATION)) { 43515605286c30e1701491bd3af974ae423727750eddDmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " 43525605286c30e1701491bd3af974ae423727750eddDmitry Shmidt "station mode"); 43535605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 43545605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 43558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 43568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 43578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43592f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidtstatic int nl80211_ht_vht_overrides(struct nl_msg *msg, 43602f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt struct wpa_driver_associate_params *params) 43612f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt{ 43622f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (params->disable_ht && nla_put_flag(msg, NL80211_ATTR_DISABLE_HT)) 43632f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return -1; 43642f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 43652f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (params->htcaps && params->htcaps_mask) { 43662f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt int sz = sizeof(struct ieee80211_ht_capabilities); 43672f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * htcaps", params->htcaps, sz); 43682f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * htcaps_mask", 43692f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt params->htcaps_mask, sz); 43702f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (nla_put(msg, NL80211_ATTR_HT_CAPABILITY, sz, 43712f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt params->htcaps) || 43722f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt nla_put(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz, 43732f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt params->htcaps_mask)) 43742f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return -1; 43752f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 43762f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 43772f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt#ifdef CONFIG_VHT_OVERRIDES 43782f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (params->disable_vht) { 43792f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_printf(MSG_DEBUG, " * VHT disabled"); 43802f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_DISABLE_VHT)) 43812f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return -1; 43822f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 43832f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 43842f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (params->vhtcaps && params->vhtcaps_mask) { 43852f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt int sz = sizeof(struct ieee80211_vht_capabilities); 43862f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * vhtcaps", params->vhtcaps, sz); 43872f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * vhtcaps_mask", 43882f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt params->vhtcaps_mask, sz); 43892f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (nla_put(msg, NL80211_ATTR_VHT_CAPABILITY, sz, 43902f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt params->vhtcaps) || 43912f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt nla_put(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz, 43922f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt params->vhtcaps_mask)) 43932f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return -1; 43942f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 43952f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt#endif /* CONFIG_VHT_OVERRIDES */ 43962f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 43972f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return 0; 43982f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt} 43992f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 44002f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 44018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv, 44028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_associate_params *params) 44038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 44048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 44058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 44068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count = 0; 44078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); 44098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44109ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, ¶ms->freq)) { 44118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " 44128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IBSS mode"); 44138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 44148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 44158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtretry: 44176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_IBSS)) || 44186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssid == NULL || params->ssid_len > sizeof(drv->ssid)) 44196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 44208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " * SSID", 44228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid, params->ssid_len); 44236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid)) 44246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 44258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->ssid, params->ssid, params->ssid_len); 44268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ssid_len = params->ssid_len; 44278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4428ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (nl80211_put_freq_params(msg, ¶ms->freq) < 0 || 4429ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nl80211_put_beacon_int(msg, params->beacon_int)) 44306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 44318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_set_conn_keys(params, msg); 44338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 44346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 44358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4436c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (params->bssid && params->fixed_bssid) { 4437c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, " * BSSID=" MACSTR, 4438c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt MAC2STR(params->bssid)); 44396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid)) 44406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 4441c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 4442c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 44437f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (params->fixed_freq) { 44447f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, " * fixed_freq"); 44457f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_FREQ_FIXED)) 44467f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt goto fail; 44477f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 44487f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 4449fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || 4450fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_PSK || 4451fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || 4452fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) { 4453c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, " * control port"); 44546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT)) 44556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 4456c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt } 4457c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 44588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wpa_ie) { 44598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 44608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " * Extra IEs for Beacon/Probe Response frames", 44618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wpa_ie, params->wpa_ie_len); 44626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len, 44636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->wpa_ie)) 44646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 44658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 44668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44672f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (nl80211_ht_vht_overrides(msg, params) < 0) 44682f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return -1; 44692f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 44708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 44718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 44728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 44738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)", 44748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret, strerror(-ret)); 44758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 44768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -EALREADY && count == 1) { 44778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after " 44788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "forced leave"); 44796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_leave_ibss(drv, 0); 44808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 44818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto retry; 44828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 44836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 44846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 44856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Join IBSS request sent successfully"); 44868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 44878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 44898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 44908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 44918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 44928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4494fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic int nl80211_connect_common(struct wpa_driver_nl80211_data *drv, 4495fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_driver_associate_params *params, 4496fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct nl_msg *msg) 44978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 44988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->bssid) { 44998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * bssid=" MACSTR, 45008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(params->bssid)); 45016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid)) 45026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 45038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4504fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 450596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if (params->bssid_hint) { 450696be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt wpa_printf(MSG_DEBUG, " * bssid_hint=" MACSTR, 450796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt MAC2STR(params->bssid_hint)); 45086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_MAC_HINT, ETH_ALEN, 45096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->bssid_hint)) 45106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 451196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt } 451296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt 45139ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt if (params->freq.freq) { 45149ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq); 45156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, 45166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->freq.freq)) 45176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 45189ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt drv->assoc_freq = params->freq.freq; 4519b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } else 4520b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt drv->assoc_freq = 0; 4521fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 452296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt if (params->freq_hint) { 452396be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt wpa_printf(MSG_DEBUG, " * freq_hint=%d", params->freq_hint); 45246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ_HINT, 45256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->freq_hint)) 45266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 452796be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt } 452896be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt 452904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (params->bg_scan_period >= 0) { 453004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, " * bg scan period=%d", 453104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params->bg_scan_period); 45326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u16(msg, NL80211_ATTR_BG_SCAN_PERIOD, 45336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->bg_scan_period)) 45346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 453504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 4536fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 45378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ssid) { 45388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " * SSID", 45398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid, params->ssid_len); 45406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, 45416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ssid)) 45426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 45438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ssid_len > sizeof(drv->ssid)) 45446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 45458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->ssid, params->ssid, params->ssid_len); 45468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ssid_len = params->ssid_len; 45478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4548fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 45498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len); 45506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->wpa_ie && 45516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_IE, params->wpa_ie_len, params->wpa_ie)) 45526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 45538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->wpa_proto) { 45551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum nl80211_wpa_versions ver = 0; 45568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->wpa_proto & WPA_PROTO_WPA) 45581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ver |= NL80211_WPA_VERSION_1; 45591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (params->wpa_proto & WPA_PROTO_RSN) 45601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ver |= NL80211_WPA_VERSION_2; 45618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, " * WPA Versions 0x%x", ver); 45636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_WPA_VERSIONS, ver)) 45646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 45658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 45668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4567fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->pairwise_suite != WPA_CIPHER_NONE) { 4568fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt u32 cipher = wpa_cipher_to_cipher_suite(params->pairwise_suite); 4569fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher); 45706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, 45716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt cipher)) 45726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 45738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 45748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4575f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (params->group_suite == WPA_CIPHER_GTK_NOT_USED && 4576f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt !(drv->capa.enc & WPA_DRIVER_CAPA_ENC_GTK_NOT_USED)) { 4577f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* 4578f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * This is likely to work even though many drivers do not 4579f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * advertise support for operations without GTK. 4580f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt */ 4581f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_DEBUG, " * skip group cipher configuration for GTK_NOT_USED due to missing driver support advertisement"); 4582f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else if (params->group_suite != WPA_CIPHER_NONE) { 4583fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt u32 cipher = wpa_cipher_to_cipher_suite(params->group_suite); 4584fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, " * group=0x%x", cipher); 45856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher)) 45866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 45878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 45888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4589fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || 4590fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_PSK || 4591fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_FT_IEEE8021X || 4592fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK || 459315907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_CCKM || 45943c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_OSEN || 45953c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || 45966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 || 4597807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B || 4598807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { 45998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int mgmt = WLAN_AKM_SUITE_PSK; 46008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (params->key_mgmt_suite) { 4602fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_KEY_MGMT_CCKM: 4603d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt mgmt = WLAN_AKM_SUITE_CCKM; 4604d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt break; 4605fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X: 46068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = WLAN_AKM_SUITE_8021X; 46078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4608fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_KEY_MGMT_FT_IEEE8021X: 4609700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt mgmt = WLAN_AKM_SUITE_FT_8021X; 4610700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt break; 4611fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_KEY_MGMT_FT_PSK: 4612700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt mgmt = WLAN_AKM_SUITE_FT_PSK; 4613700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt break; 46143c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SHA256: 46153c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt mgmt = WLAN_AKM_SUITE_8021X_SHA256; 46163c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt break; 46173c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt case WPA_KEY_MGMT_PSK_SHA256: 46183c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt mgmt = WLAN_AKM_SUITE_PSK_SHA256; 46193c57b3f85a2d1d586b8b42014a806df23d309824Dmitry Shmidt break; 462015907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt case WPA_KEY_MGMT_OSEN: 462115907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt mgmt = WLAN_AKM_SUITE_OSEN; 462215907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt break; 46236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SUITE_B: 46246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt mgmt = WLAN_AKM_SUITE_8021X_SUITE_B; 46256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 4626807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: 4627807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt mgmt = WLAN_AKM_SUITE_8021X_SUITE_B_192; 4628807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt break; 4629fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt case WPA_KEY_MGMT_PSK: 46308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 46318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = WLAN_AKM_SUITE_PSK; 46328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 46338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 463415907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt wpa_printf(MSG_DEBUG, " * akm=0x%x", mgmt); 46356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, mgmt)) 46366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 46378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 46388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT)) 46406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 46416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 46426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED && 46436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED)) 46446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 4645fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 46466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->rrm_used) { 46476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 drv_rrm_flags = drv->capa.rrm_flags; 46486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv_rrm_flags & 46496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) || 46506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !(drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET) || 46516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_ATTR_USE_RRM)) 46526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 46536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 4654a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 46552f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (nl80211_ht_vht_overrides(msg, params) < 0) 46566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 4657c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 4658fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->p2p) 4659fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, " * P2P group"); 4660fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4661fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 4662fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 4663fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4664fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4665fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic int wpa_driver_nl80211_try_connect( 4666fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_driver_nl80211_data *drv, 4667fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_driver_associate_params *params) 4668fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 4669fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct nl_msg *msg; 4670fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt enum nl80211_auth_type type; 4671fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int ret; 4672fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt int algs; 4673fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 46746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->req_key_mgmt_offload && params->psk && 46756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (params->key_mgmt_suite == WPA_KEY_MGMT_PSK || 46766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 || 46776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) { 46786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Key management set PSK"); 46796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = issue_key_mgmt_set_key(drv, params->psk, 32); 46806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 46816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 46826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 4683fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4684fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex); 46856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_CONNECT); 46866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 46876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 4688fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4689fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = nl80211_connect_common(drv, params, msg); 4690fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ret) 46916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 4692fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4693fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt algs = 0; 4694fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_OPEN) 4695fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt algs++; 4696fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_SHARED) 4697fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt algs++; 4698fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_LEAP) 4699fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt algs++; 4700fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (algs > 1) { 4701fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic " 4702fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt "selection"); 4703fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt goto skip_auth_type; 4704fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 4705fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4706fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_OPEN) 4707fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt type = NL80211_AUTHTYPE_OPEN_SYSTEM; 4708fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_SHARED) 4709fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt type = NL80211_AUTHTYPE_SHARED_KEY; 4710fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_LEAP) 4711fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt type = NL80211_AUTHTYPE_NETWORK_EAP; 4712fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_FT) 4713fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt type = NL80211_AUTHTYPE_FT; 4714fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt else 47156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 4716fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4717fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, " * Auth Type %d", type); 47186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_AUTH_TYPE, type)) 47196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 4720fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 4721fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtskip_auth_type: 47228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_set_conn_keys(params, msg); 47238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 47246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 47258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 47278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 47288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 47298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " 47308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 47316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 47326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 47336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Connect request send successfully"); 47348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 47378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 47388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 47398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 47418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4743d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int wpa_driver_nl80211_connect( 4744d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_driver_nl80211_data *drv, 4745d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_driver_associate_params *params) 4746d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 4747a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance int ret; 4748a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance 4749a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance /* Store the connection attempted bssid for future use */ 4750a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance if (params->bssid) 4751a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN); 4752a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance else 4753a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN); 4754a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance 4755a7c60b4c03ced564d424e4cae81b85f7112aa59bJithu Jance ret = wpa_driver_nl80211_try_connect(drv, params); 4756d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (ret == -EALREADY) { 4757d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt /* 4758d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * cfg80211 does not currently accept new connections if 4759d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * we are already connected. As a workaround, force 4760d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * disconnection and try again. 4761d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */ 4762d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Explicitly " 4763d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "disconnecting before reassociation " 4764d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "attempt"); 4765d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_driver_nl80211_disconnect( 4766d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt drv, WLAN_REASON_PREV_AUTH_NOT_VALID)) 4767d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 4768d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ret = wpa_driver_nl80211_try_connect(drv, params); 4769d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 4770d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return ret; 4771d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 4772d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 4773d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 47748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_associate( 47758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *priv, struct wpa_driver_associate_params *params) 47768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 47778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 47788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 47796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = -1; 47808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 47818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_unmask_11b_rates(bss); 47836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 47848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->mode == IEEE80211_MODE_AP) 47858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_ap(drv, params); 47868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->mode == IEEE80211_MODE_IBSS) 47888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_ibss(drv, params); 47898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { 47911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt enum nl80211_iftype nlmode = params->p2p ? 47921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION; 47931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 47941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0) 47958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 47968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_connect(drv, params); 47978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47998bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt nl80211_mark_disconnected(drv); 48008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)", 48028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifindex); 48036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_ASSOCIATE); 48046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 48056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 48068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4807fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = nl80211_connect_common(drv, params, msg); 4808fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (ret) 48096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 48108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->prev_bssid) { 48128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR, 48138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(params->prev_bssid)); 48146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN, 48156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->prev_bssid)) 48166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 48178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 48208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 48218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 48221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_dbg(drv->ctx, MSG_DEBUG, 48231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "nl80211: MLME command failed (assoc): ret=%d (%s)", 48241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret, strerror(-ret)); 48258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_dump_scan(drv); 48266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 48276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 48286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Association request send successfully"); 48298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 48328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 48338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 48348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 48358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_set_mode(struct wpa_driver_nl80211_data *drv, 48381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ifindex, enum nl80211_iftype mode) 48398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 48408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 48418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -ENOBUFS; 48428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)", 48441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ifindex, mode, nl80211_iftype_str(mode)); 48451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 48466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(drv->first_bss, 0, NL80211_CMD_SET_INTERFACE); 48476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || nla_put_u32(msg, NL80211_ATTR_IFTYPE, mode)) 48486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 48498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 48511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt msg = NULL; 48528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) 48538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 48546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 48551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nlmsg_free(msg); 48568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:" 48578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " %d (%s)", ifindex, mode, ret, strerror(-ret)); 48588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 48598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 48608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4862d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidtstatic int wpa_driver_nl80211_set_mode_impl( 4863d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt struct i802_bss *bss, 4864d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt enum nl80211_iftype nlmode, 4865d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt struct hostapd_freq_params *desired_freq_params) 48668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 48678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 48688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 48698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 48701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int was_ap = is_ap_interface(drv->nlmode); 48711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int res; 4872d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt int mode_switch_res; 48738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4874d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode); 4875d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (mode_switch_res && nlmode == nl80211_get_ifmode(bss)) 4876d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt mode_switch_res = 0; 487734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 4878d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (mode_switch_res == 0) { 48798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nlmode = nlmode; 48808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 48818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 48828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4884d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (mode_switch_res == -ENODEV) 48851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 48861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 48878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nlmode == drv->nlmode) { 48888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface already in " 48898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "requested mode - ignore error"); 48908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 48918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; /* Already in the requested mode */ 48928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* mac80211 doesn't allow mode changes while the device is up, so 48958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * take the device down, try to set the mode again, and bring the 48968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * device back up. 48978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 48988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting " 48998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface down"); 49008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 10; i++) { 490134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt res = i802_set_iface_flags(bss, 0); 49021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (res == -EACCES || res == -ENODEV) 49031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 4904d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (res != 0) { 49058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set " 49068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface down"); 4907d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt os_sleep(0, 100000); 4908d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt continue; 4909d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } 4910d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 4911d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt /* 4912d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt * Setting the mode will fail for some drivers if the phy is 4913d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt * on a frequency that the mode is disallowed in. 4914d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt */ 4915d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (desired_freq_params) { 49166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = nl80211_set_channel(bss, desired_freq_params, 0); 4917d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (res) { 4918d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_printf(MSG_DEBUG, 4919d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt "nl80211: Failed to set frequency on interface"); 4920d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } 4921d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } 4922d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 4923d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt /* Try to set the mode again while the interface is down */ 4924d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode); 4925d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (mode_switch_res == -EBUSY) { 4926d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_printf(MSG_DEBUG, 4927d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt "nl80211: Delaying mode set while interface going down"); 4928d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt os_sleep(0, 100000); 4929d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt continue; 4930d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } 4931d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt ret = mode_switch_res; 4932d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt break; 49338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 49348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) { 49368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while " 49378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface is down"); 49388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nlmode = nlmode; 49391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->ignore_if_down_event = 1; 49408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 49418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4942d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt /* Bring the interface back up */ 4943d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt res = linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1); 4944d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt if (res != 0) { 4945d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt wpa_printf(MSG_DEBUG, 4946d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt "nl80211: Failed to set interface up after switching mode"); 4947d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt ret = -1; 4948d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt } 4949d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 49508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone: 49511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ret) { 49521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d " 49531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "from %d failed", nlmode, drv->nlmode); 49541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return ret; 49551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 49561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 49576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (is_p2p_net_interface(nlmode)) { 49586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 49596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Interface %s mode change to P2P - disable 11b rates", 49606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname); 496161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt nl80211_disable_11b_rates(drv, drv->ifindex, 1); 49626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (drv->disabled_11b_rates) { 49636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 49646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Interface %s mode changed to non-P2P - re-enable 11b rates", 49656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname); 496661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt nl80211_disable_11b_rates(drv, drv->ifindex, 0); 49676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 496861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 49691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (is_ap_interface(nlmode)) { 49701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_mgmt_unsubscribe(bss, "start AP"); 49718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Setup additional AP mode functionality if needed */ 49721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (nl80211_setup_ap(bss)) 49738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 49741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (was_ap) { 49758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Remove additional AP mode functionality */ 49761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_teardown_ap(bss); 49771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 49781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_mgmt_unsubscribe(bss, "mode change"); 49798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 49808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (is_mesh_interface(nlmode) && 49826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_mgmt_subscribe_mesh(bss)) 49836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 49846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 498504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!bss->in_deinit && !is_ap_interface(nlmode) && 49866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !is_mesh_interface(nlmode) && 49871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_mgmt_subscribe_non_ap(bss) < 0) 49881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action " 49891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "frame processing - ignore for now"); 49908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return 0; 49928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 49938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtint wpa_driver_nl80211_set_mode(struct i802_bss *bss, 49966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_iftype nlmode) 4997d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{ 4998d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt return wpa_driver_nl80211_set_mode_impl(bss, nlmode, NULL); 4999d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt} 5000d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 5001d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 50029ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidtstatic int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, 50039ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt struct hostapd_freq_params *freq) 5004d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt{ 5005d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC, 50069ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt freq); 5007d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt} 5008d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 5009d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt 50108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_get_capa(void *priv, 50118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_capa *capa) 50128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 50138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 50148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 5015d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 50168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->has_capability) 50178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 50188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(capa, &drv->capa, sizeof(*capa)); 5019444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt if (drv->extended_capa && drv->extended_capa_mask) { 5020444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt capa->extended_capa = drv->extended_capa; 5021444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt capa->extended_capa_mask = drv->extended_capa_mask; 5022444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt capa->extended_capa_len = drv->extended_capa_len; 5023444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt } 502434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 50256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 50268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_operstate(void *priv, int state) 50308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 50318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 50328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 50338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5034fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)", 5035fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt bss->ifname, drv->operstate, state, 5036fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt state ? "UP" : "DORMANT"); 50378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->operstate = state; 50381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1, 50398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt state ? IF_OPER_UP : IF_OPER_DORMANT); 50408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_supp_port(void *priv, int authorized) 50448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 50458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 50468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 50478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 50488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_sta_flag_update upd; 50496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 5050fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 5051fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (!drv->associated && is_zero_ether_addr(drv->bssid) && !authorized) { 5052fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Skip set_supp_port(unauthorized) while not associated"); 5053fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 5054fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 50558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50568bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for " 50578bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid)); 50588bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt 50598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&upd, 0, sizeof(upd)); 50608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED); 50618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (authorized) 50628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED); 50636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 50646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) || 50656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid) || 50666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) { 50676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 50686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 50696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 50708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5071fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 5072fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (!ret) 5073fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return 0; 5074fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)", 5075fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt ret, strerror(-ret)); 5076fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return ret; 50778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/* Set kernel driver on given frequency (MHz) */ 508175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int i802_set_freq(void *priv, struct hostapd_freq_params *freq) 50828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 508375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct i802_bss *bss = priv; 50847832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return nl80211_set_channel(bss, freq, 0); 50858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int min_int(int a, int b) 50898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 50908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a < b) 50918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return a; 50928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return b; 50938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int get_key_handler(struct nl_msg *msg, void *arg) 50978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 50988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 50998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 51008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 51028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 51038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 51058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: validate the key index and mac address! 51068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Otherwise, there's a race condition as soon as 51078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the kernel starts sending key notifications. 51088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 51098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_KEY_SEQ]) 51118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]), 51128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6)); 51138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 51148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 51158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, 51188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx, u8 *seq) 51198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 51218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 51228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 51238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_ifindex_msg(drv, if_nametoindex(iface), 0, 51256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_GET_KEY); 51266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || 51276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) || 51286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_KEY_IDX, idx)) { 51296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 51306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 51316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 51328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(seq, 0, 6); 51348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, get_key_handler, seq); 51368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 51378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_rts(void *priv, int rts) 51408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 51428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 51438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 51446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 51458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 val; 51468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rts >= 2347) 51488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = (u32) -1; 51498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 51508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = rts; 51518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) || 51536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val)) { 51546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 51556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 51566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 51578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 51598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) 51608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 51618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: " 51628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d (%s)", rts, ret, strerror(-ret)); 51638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 51648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 51658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_frag(void *priv, int frag) 51688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 51708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 51718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 51726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 51738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 val; 51748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (frag >= 2346) 51768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = (u32) -1; 51778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 51788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = frag; 51798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_WIPHY)) || 51816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val)) { 51826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 51836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 51846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 51858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 51878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) 51888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 51898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold " 51908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d: %d (%s)", frag, ret, strerror(-ret)); 51918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 51928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 51938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_flush(void *priv) 51968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 51988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 51991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int res; 52008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5201b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)", 5202b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt bss->ifname); 52038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 52058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * XXX: FIX! this needs to flush all VLANs too 52068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 52076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION); 52086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = send_and_recv_msgs(bss->drv, msg, NULL, NULL); 52091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (res) { 52101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d " 52111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(%s)", res, strerror(-res)); 52121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 52131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return res; 52148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 52158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int get_sta_handler(struct nl_msg *msg, void *arg) 52188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 52198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 52208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 52218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostap_sta_driver_data *data = arg; 52228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *stats[NL80211_STA_INFO_MAX + 1]; 52238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = { 52248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 }, 52258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 }, 52268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 }, 52278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 }, 52288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 }, 52291e6c57fee4a56b421cc20f6dc0785c9138b21337Jouni Malinen [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 }, 52308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 52318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 52338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 52348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 52368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: validate the interface and mac address! 52378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Otherwise, there's a race condition as soon as 52388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the kernel starts sending station notifications. 52398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 52408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb[NL80211_ATTR_STA_INFO]) { 52428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "sta stats missing!"); 52438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 52448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 52458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nla_parse_nested(stats, NL80211_STA_INFO_MAX, 52468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_STA_INFO], 52478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stats_policy)) { 52488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "failed to parse nested attributes!"); 52498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 52508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 52518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_INACTIVE_TIME]) 52538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->inactive_msec = 52548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]); 52558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_RX_BYTES]) 52568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]); 52578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_TX_BYTES]) 52588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]); 52598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_RX_PACKETS]) 52608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rx_packets = 52618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]); 52628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_TX_PACKETS]) 52638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tx_packets = 52648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]); 52651e6c57fee4a56b421cc20f6dc0785c9138b21337Jouni Malinen if (stats[NL80211_STA_INFO_TX_FAILED]) 52661e6c57fee4a56b421cc20f6dc0785c9138b21337Jouni Malinen data->tx_retry_failed = 52671e6c57fee4a56b421cc20f6dc0785c9138b21337Jouni Malinen nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]); 52688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 52708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 52718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52724b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int i802_read_sta_data(struct i802_bss *bss, 52734b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct hostap_sta_driver_data *data, 52748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr) 52758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 52768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 52778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data, 0, sizeof(*data)); 52798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_GET_STATION)) || 52816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) { 52826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 52836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 52846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 52858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data); 52878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 52888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_tx_queue_params(void *priv, int queue, int aifs, 52918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cw_min, int cw_max, int burst_time) 52928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 52938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 52948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 52958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 52968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *txq, *params; 52978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_WIPHY); 52998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 53008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 53018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); 53038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!txq) 53046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 53058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* We are only sending parameters for a single TXQ at a time */ 53078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params = nla_nest_start(msg, 1); 53088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!params) 53096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 53108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (queue) { 53128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 0: 53136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO)) 53146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 53158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 53168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 53176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI)) 53186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 53198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 53208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: 53216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE)) 53226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 53238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 53248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 3: 53256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK)) 53266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 53278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 53288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 53298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Burst time is configured in units of 0.1 msec and TXOP parameter in 53308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 32 usec, so need to convert the value here. */ 53316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u16(msg, NL80211_TXQ_ATTR_TXOP, 53326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (burst_time * 100 + 16) / 32) || 53336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min) || 53346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max) || 53356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_TXQ_ATTR_AIFS, aifs)) 53366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 53378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, params); 53398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, txq); 53418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) 53438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 53441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt msg = NULL; 53456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 53461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nlmsg_free(msg); 53478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 53488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 53498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53514b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr, 53528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, int vlan_id) 53538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 53548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 53558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 53566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 53578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %s[%d]: set_sta_vlan(" MACSTR 5359cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt ", ifname=%s[%d], vlan_id=%d)", 5360cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt bss->ifname, if_nametoindex(bss->ifname), 5361cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id); 53626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) || 53636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || 53646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_STA_VLAN, if_nametoindex(ifname))) { 53656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 53666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 53676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 53688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 53708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 53718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr=" 53728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)", 53738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr), ifname, vlan_id, ret, 53748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strerror(-ret)); 53758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 53768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 53778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 53788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_get_inact_sec(void *priv, const u8 *addr) 53818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 53828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostap_sta_driver_data data; 53838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 53848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.inactive_msec = (unsigned long) -1; 53868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = i802_read_sta_data(priv, &data, addr); 53872f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (ret == -ENOENT) 53882f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return -ENOENT; 53898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret || data.inactive_msec == (unsigned long) -1) 53908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 53918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data.inactive_msec / 1000; 53928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 53938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_sta_clear_stats(void *priv, const u8 *addr) 53968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 53978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 53988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 53998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 54008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 54018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, 54058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reason) 54068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 54078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 540804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 54098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_mgmt mgmt; 54108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (is_mesh_interface(drv->nlmode)) 54126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 54136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 541404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (drv->device_ap_sme) 54156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_sta_remove(bss, addr, 1, reason); 541604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 54178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(&mgmt, 0, sizeof(mgmt)); 54188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 54198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_FC_STYPE_DEAUTH); 54208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.da, addr, ETH_ALEN); 54218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.sa, own_addr, ETH_ALEN); 54228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.bssid, own_addr, ETH_ALEN); 54238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt.u.deauth.reason_code = host_to_le16(reason); 54248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, 54258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_HDRLEN + 54264b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt sizeof(mgmt.u.deauth), 0, 0, 0, 0, 54274b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 0); 54288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, 54328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reason) 54338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 54348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 543504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 54368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_mgmt mgmt; 54378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (is_mesh_interface(drv->nlmode)) 54396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 54406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 544104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (drv->device_ap_sme) 54426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_sta_remove(bss, addr, 0, reason); 544304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 54448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(&mgmt, 0, sizeof(mgmt)); 54458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 54468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_FC_STYPE_DISASSOC); 54478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.da, addr, ETH_ALEN); 54488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.sa, own_addr, ETH_ALEN); 54498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.bssid, own_addr, ETH_ALEN); 54508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt.u.disassoc.reason_code = host_to_le16(reason); 54518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, 54528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_HDRLEN + 54534b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt sizeof(mgmt.u.disassoc), 0, 0, 0, 0, 54544b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 0); 54558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5458df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidtstatic void dump_ifidx(struct wpa_driver_nl80211_data *drv) 5459df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt{ 5460df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt char buf[200], *pos, *end; 5461df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt int i, res; 5462df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 5463df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt pos = buf; 5464df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt end = pos + sizeof(buf); 5465df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 5466df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt for (i = 0; i < drv->num_if_indices; i++) { 5467df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (!drv->if_indices[i]) 5468df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt continue; 5469df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]); 54706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, res)) 5471df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt break; 5472df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt pos += res; 5473df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 5474df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt *pos = '\0'; 5475df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 5476df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: if_indices[%d]:%s", 5477df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt drv->num_if_indices, buf); 5478df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt} 5479df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 5480df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 548175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 548275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 548375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int i; 548475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int *old; 548575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 548675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d", 548775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen ifidx); 5488df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (have_ifidx(drv, ifidx)) { 5489df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list", 5490df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt ifidx); 5491df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt return; 5492df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt } 549375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen for (i = 0; i < drv->num_if_indices; i++) { 549475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (drv->if_indices[i] == 0) { 549575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices[i] = ifidx; 5496df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt dump_ifidx(drv); 549775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return; 549875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 549975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 550075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 550175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (drv->if_indices != drv->default_if_indices) 550275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen old = drv->if_indices; 550375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen else 550475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen old = NULL; 550575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 550661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1, 550761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt sizeof(int)); 550875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (!drv->if_indices) { 550975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (!old) 551075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices = drv->default_if_indices; 551175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen else 551275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices = old; 551375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_ERROR, "Failed to reallocate memory for " 551475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen "interfaces"); 551575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx); 551675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return; 551775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } else if (!old) 551875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen os_memcpy(drv->if_indices, drv->default_if_indices, 551975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen sizeof(drv->default_if_indices)); 552075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices[drv->num_if_indices] = ifidx; 552175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->num_if_indices++; 5522df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt dump_ifidx(drv); 552375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 552475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 552575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 552675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 552775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 552875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int i; 552975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 553075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen for (i = 0; i < drv->num_if_indices; i++) { 553175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (drv->if_indices[i] == ifidx) { 553275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices[i] = 0; 553375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen break; 553475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 553575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 5536df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt dump_ifidx(drv); 553775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 553875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 553975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 554075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 554175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 554275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int i; 554375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 554475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen for (i = 0; i < drv->num_if_indices; i++) 554575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (drv->if_indices[i] == ifidx) 554675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return 1; 554775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 554875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return 0; 554975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 555075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 555175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 555275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val, 55537832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt const char *bridge_ifname, char *ifname_wds) 555475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 555575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct i802_bss *bss = priv; 555675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct wpa_driver_nl80211_data *drv = bss->drv; 555775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen char name[IFNAMSIZ + 1]; 555875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 555975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid); 5560c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt if (ifname_wds) 5561c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt os_strlcpy(ifname_wds, name, IFNAMSIZ + 1); 5562c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt 556375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR 556475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name); 556575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (val) { 556675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (!if_nametoindex(name)) { 556775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (nl80211_create_iface(drv, name, 556875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen NL80211_IFTYPE_AP_VLAN, 5569cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt bss->addr, 1, NULL, NULL, 0) < 5570cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 0) 557175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return -1; 557275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (bridge_ifname && 55731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt linux_br_add_if(drv->global->ioctl_sock, 55741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bridge_ifname, name) < 0) 557575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return -1; 557675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 557761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (linux_set_iface_flags(drv->global->ioctl_sock, name, 1)) { 557861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA " 557961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "interface %s up", name); 558061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 558175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return i802_set_sta_vlan(priv, addr, name, 0); 558275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } else { 5583aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt if (bridge_ifname) 5584aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt linux_br_del_if(drv->global->ioctl_sock, bridge_ifname, 5585aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt name); 5586aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt 558775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen i802_set_sta_vlan(priv, addr, bss->ifname, 0); 5588a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt nl80211_remove_iface(drv, if_nametoindex(name)); 5589a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt return 0; 559075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 559175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 559275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 559375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 559475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) 559575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 559675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct wpa_driver_nl80211_data *drv = eloop_ctx; 559775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct sockaddr_ll lladdr; 559875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen unsigned char buf[3000]; 559975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int len; 560075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen socklen_t fromlen = sizeof(lladdr); 560175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 560275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen len = recvfrom(sock, buf, sizeof(buf), 0, 560375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen (struct sockaddr *)&lladdr, &fromlen); 560475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (len < 0) { 560568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: EAPOL recv failed: %s", 560668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt strerror(errno)); 560775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return; 560875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 560975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 561075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (have_ifidx(drv, lladdr.sll_ifindex)) 561175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len); 561275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 561375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 561475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 56158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_check_bridge(struct wpa_driver_nl80211_data *drv, 56168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss, 56178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *brname, const char *ifname) 56188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 56196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int br_ifindex; 56208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char in_br[IFNAMSIZ]; 56218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(bss->brname, brname, IFNAMSIZ); 56236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt br_ifindex = if_nametoindex(brname); 56246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (br_ifindex == 0) { 56258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 56268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Bridge was configured, but the bridge device does 56278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not exist. Try to add it now. 56288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 56291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (linux_br_add(drv->global->ioctl_sock, brname) < 0) { 56308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to add the " 56318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bridge interface %s: %s", 56328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brname, strerror(errno)); 56338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 56348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 56358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->added_bridge = 1; 56366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt br_ifindex = if_nametoindex(brname); 56376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt add_ifidx(drv, br_ifindex); 56388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 56396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->br_ifindex = br_ifindex; 56408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_get(in_br, ifname) == 0) { 56428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(in_br, brname) == 0) 56438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; /* already in the bridge */ 56448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from " 56468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bridge %s", ifname, in_br); 56471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) < 56481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 0) { 56498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to " 56508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "remove interface %s from bridge " 56518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s: %s", 56528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, brname, strerror(errno)); 56538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 56548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 56558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 56568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s", 56588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, brname); 56591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) { 56608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s " 56618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "into bridge %s: %s", 56628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, brname, strerror(errno)); 56638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 56648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 56658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->added_if_into_bridge = 1; 56668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 56688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 56698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void *i802_init(struct hostapd_data *hapd, 56728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_init_params *params) 56738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 56748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 56758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss; 56768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 56778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char brname[IFNAMSIZ]; 56788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, br_ifindex; 56798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int br_added = 0; 56808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5681e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt bss = wpa_driver_nl80211_drv_init(hapd, params->ifname, 5682e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt params->global_priv, 1, 56836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->bssid, params->driver_params); 56848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss == NULL) 56858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 56868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv = bss->drv; 56881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 56898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_get(brname, params->ifname) == 0) { 56908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s", 56918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ifname, brname); 56928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt br_ifindex = if_nametoindex(brname); 56936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_strlcpy(bss->brname, brname, IFNAMSIZ); 56948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 56958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brname[0] = '\0'; 56968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt br_ifindex = 0; 56978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 56986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->br_ifindex = br_ifindex; 56998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < params->num_bridge; i++) { 57018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->bridge[i]) { 57028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifindex = if_nametoindex(params->bridge[i]); 57038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifindex) 57048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, ifindex); 57058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifindex == br_ifindex) 57068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt br_added = 1; 57078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* start listening for EAPOL on the default AP interface */ 57118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, drv->ifindex); 57128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->num_bridge && params->bridge[0]) { 57146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (i802_check_bridge(drv, bss, params->bridge[0], 57156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ifname) < 0) 57166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto failed; 57176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_strcmp(params->bridge[0], brname) != 0) 57186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt br_added = 1; 57196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 57206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 57216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!br_added && br_ifindex && 57226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (params->num_bridge == 0 || !params->bridge[0])) 57236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt add_ifidx(drv, br_ifindex); 57248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5725661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#ifdef CONFIG_LIBNL3_ROUTE 5726661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (bss->added_if_into_bridge) { 5727661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt drv->rtnl_sk = nl_socket_alloc(); 5728661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (drv->rtnl_sk == NULL) { 5729661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock"); 5730661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt goto failed; 5731661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 5732661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 5733661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt if (nl_connect(drv->rtnl_sk, NETLINK_ROUTE)) { 5734661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s", 5735661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt strerror(errno)); 5736661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt goto failed; 5737661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 5738661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 5739661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#endif /* CONFIG_LIBNL3_ROUTE */ 5740661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 57418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); 57428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->eapol_sock < 0) { 574368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s", 574468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt strerror(errno)); 57458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 57468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL)) 57498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 575068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol"); 57518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 57528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, 57551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params->own_addr)) 57568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 5757661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt os_memcpy(drv->perm_addr, params->own_addr, ETH_ALEN); 57588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt memcpy(bss->addr, params->own_addr, ETH_ALEN); 57601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 57618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return bss; 57628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 57641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_driver_nl80211_deinit(bss); 57658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 57668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 57678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void i802_deinit(void *priv) 57708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 57714b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct i802_bss *bss = priv; 57724b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt wpa_driver_nl80211_deinit(bss); 57738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 57748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum nl80211_iftype wpa_driver_nl80211_if_type( 57778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_driver_if_type type) 57788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 57798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (type) { 57808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_STATION: 57818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_STATION; 57828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_P2P_CLIENT: 57838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_P2P_GROUP: 57848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_P2P_CLIENT; 57858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_AP_VLAN: 57868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_AP_VLAN; 57878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_AP_BSS: 57888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_AP; 57898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_P2P_GO: 57908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_P2P_GO; 579134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt case WPA_IF_P2P_DEVICE: 579234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NL80211_IFTYPE_P2P_DEVICE; 57936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case WPA_IF_MESH: 57946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL80211_IFTYPE_MESH_POINT; 57958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 57978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 57988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr) 58018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 58028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 58038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(drv, &global->interfaces, 58048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data, list) { 5805cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (os_memcmp(addr, drv->first_bss->addr, ETH_ALEN) == 0) 58068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 58078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 58088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 58098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 58108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_vif_addr(struct wpa_driver_nl80211_data *drv, u8 *new_addr) 58138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 58148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int idx; 58158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->global) 58178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 58188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5819cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt os_memcpy(new_addr, drv->first_bss->addr, ETH_ALEN); 58208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (idx = 0; idx < 64; idx++) { 5821cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt new_addr[0] = drv->first_bss->addr[0] | 0x02; 58228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_addr[0] ^= idx << 2; 58238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!nl80211_addr_in_use(drv->global, new_addr)) 58248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 58258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 58268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (idx == 64) 58278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 58288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Assigned new virtual interface address " 58308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, MAC2STR(new_addr)); 58318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 58338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 58348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 583634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstruct wdev_info { 583734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u64 wdev_id; 583834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt int wdev_id_set; 583934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 macaddr[ETH_ALEN]; 584034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt}; 584134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 584234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int nl80211_wdev_handler(struct nl_msg *msg, void *arg) 584334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 584434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 584534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 584634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wdev_info *wi = arg; 584734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 584834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 584934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 585034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (tb[NL80211_ATTR_WDEV]) { 585134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wi->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]); 585234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wi->wdev_id_set = 1; 585334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 585434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 585534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (tb[NL80211_ATTR_MAC]) 585634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(wi->macaddr, nla_data(tb[NL80211_ATTR_MAC]), 585734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ETH_ALEN); 585834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 585934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NL_SKIP; 586034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 586134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 586234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 58638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, 58648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, const u8 *addr, 58658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *bss_ctx, void **drv_priv, 58668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *force_ifname, u8 *if_addr, 5867cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt const char *bridge, int use_existing) 58688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 586934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt enum nl80211_iftype nlmode; 58708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 58718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 58728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifidx; 5873cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int added = 1; 58748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) 58768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(if_addr, addr, ETH_ALEN); 587734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nlmode = wpa_driver_nl80211_if_type(type); 587834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (nlmode == NL80211_IFTYPE_P2P_DEVICE) { 587934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wdev_info p2pdev_info; 588034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 588134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memset(&p2pdev_info, 0, sizeof(p2pdev_info)); 588234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ifidx = nl80211_create_iface(drv, ifname, nlmode, addr, 588334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 0, nl80211_wdev_handler, 5884cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt &p2pdev_info, use_existing); 588534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (!p2pdev_info.wdev_id_set || ifidx != 0) { 588634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s", 588734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ifname); 588834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return -1; 588934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 589034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 589134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt drv->global->if_add_wdevid = p2pdev_info.wdev_id; 589234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt drv->global->if_add_wdevid_set = p2pdev_info.wdev_id_set; 589334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (!is_zero_ether_addr(p2pdev_info.macaddr)) 589434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(if_addr, p2pdev_info.macaddr, ETH_ALEN); 589534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: New P2P Device interface %s (0x%llx) created", 589634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ifname, 589734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt (long long unsigned int) p2pdev_info.wdev_id); 589834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } else { 589934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt ifidx = nl80211_create_iface(drv, ifname, nlmode, addr, 5900cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 0, NULL, NULL, use_existing); 5901cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (use_existing && ifidx == -ENFILE) { 5902cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt added = 0; 5903cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt ifidx = if_nametoindex(ifname); 5904cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } else if (ifidx < 0) { 590534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return -1; 590634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 59078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 590934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (!addr) { 59101d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt if (nlmode == NL80211_IFTYPE_P2P_DEVICE) 591134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt os_memcpy(if_addr, bss->addr, ETH_ALEN); 591234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt else if (linux_get_ifhwaddr(drv->global->ioctl_sock, 59131d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt ifname, if_addr) < 0) { 5914cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (added) 5915cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 591634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return -1; 591734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 59188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!addr && 59218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP || 59221d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt type == WPA_IF_P2P_GO || type == WPA_IF_MESH || 59231d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt type == WPA_IF_STATION)) { 59241d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt /* Enforce unique address */ 592534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt u8 new_addr[ETH_ALEN]; 59268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 592734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (linux_get_ifhwaddr(drv->global->ioctl_sock, ifname, 59281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt new_addr) < 0) { 5929717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (added) 5930717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt nl80211_remove_iface(drv, ifidx); 59318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 593334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (nl80211_addr_in_use(drv->global, new_addr)) { 59348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Allocate new address " 59351d755d025b206e22b06aeb322e25a79f98ca7777Dmitry Shmidt "for interface %s type %d", ifname, type); 59366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl80211_vif_addr(drv, new_addr) < 0) { 5937717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (added) 5938717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt nl80211_remove_iface(drv, ifidx); 59398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, 59428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_addr) < 0) { 5943717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (added) 5944717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt nl80211_remove_iface(drv, ifidx); 59458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59486e933c1e09094a8972ef1e782c57f8b3c55c91d0Dmitry Shmidt os_memcpy(if_addr, new_addr, ETH_ALEN); 59498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type == WPA_IF_AP_BSS) { 595268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss)); 595368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (new_bss == NULL) { 5954cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (added) 5955cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 595668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return -1; 595768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 595868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 595968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (bridge && 596068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt i802_check_bridge(drv, new_bss, bridge, ifname) < 0) { 596168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to add the new " 596268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt "interface %s to a bridge %s", 596368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt ifname, bridge); 5964cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (added) 5965cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 596668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt os_free(new_bss); 596768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return -1; 596868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 596968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 59701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1)) 59711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt { 5972717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt if (added) 5973717574375e969e8272c6d1a26137286eac158abbDmitry Shmidt nl80211_remove_iface(drv, ifidx); 59748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(new_bss); 59758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ); 59781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(new_bss->addr, if_addr, ETH_ALEN); 59798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_bss->ifindex = ifidx; 59808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_bss->drv = drv; 5981cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt new_bss->next = drv->first_bss->next; 5982cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt new_bss->freq = drv->first_bss->freq; 5983a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt new_bss->ctx = bss_ctx; 5984cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt new_bss->added_if = added; 5985cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt drv->first_bss->next = new_bss; 59868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv_priv) 59878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *drv_priv = new_bss; 59881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_init_bss(new_bss); 5989c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 5990c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* Subscribe management frames for this WPA_IF_AP_BSS */ 5991c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (nl80211_setup_ap(new_bss)) 5992c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return -1; 59938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (drv->global) 59961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->global->if_add_ifindex = ifidx; 59971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 599843cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt /* 599943cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt * Some virtual interfaces need to process EAPOL packets and events on 600043cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt * the parent interface. This is used mainly with hostapd. 600143cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt */ 600243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt if (ifidx > 0 && 600343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt (drv->hostapd || 600443cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt nlmode == NL80211_IFTYPE_AP_VLAN || 600543cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt nlmode == NL80211_IFTYPE_WDS || 600643cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt nlmode == NL80211_IFTYPE_MONITOR)) 6007df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt add_ifidx(drv, ifidx); 6008df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt 60098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 60108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 60118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60134b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int wpa_driver_nl80211_if_remove(struct i802_bss *bss, 60148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_driver_if_type type, 60158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname) 60168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 60178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 60188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex = if_nametoindex(ifname); 60198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6020cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d", 6021cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt __func__, type, ifname, ifindex, bss->added_if); 602201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt if (ifindex > 0 && (bss->added_if || bss->ifindex != ifindex)) 6023051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt nl80211_remove_iface(drv, ifindex); 602476cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt else if (ifindex > 0 && !bss->added_if) { 602576cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt struct wpa_driver_nl80211_data *drv2; 602676cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt dl_list_for_each(drv2, &drv->global->interfaces, 602776cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt struct wpa_driver_nl80211_data, list) 602876cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt del_ifidx(drv2, ifindex); 602976cd2cc44b62e858f1897ce58f4ce7d0174e8839Dmitry Shmidt } 6030aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt 6031aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt if (type != WPA_IF_AP_BSS) 6032aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt return 0; 6033aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt 60348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss->added_if_into_bridge) { 60351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (linux_br_del_if(drv->global->ioctl_sock, bss->brname, 60361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->ifname) < 0) 60378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to remove " 60388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface %s from bridge %s: %s", 60398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->ifname, bss->brname, strerror(errno)); 60408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss->added_bridge) { 60421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0) 60438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to remove " 60448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bridge %s: %s", 60458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->brname, strerror(errno)); 60468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6048cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (bss != drv->first_bss) { 60498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *tbss; 60508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6051cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Not the first BSS - remove it"); 6052cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt for (tbss = drv->first_bss; tbss; tbss = tbss->next) { 60538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tbss->next == bss) { 60548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tbss->next = bss->next; 6055c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt /* Unsubscribe management frames */ 6056c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt nl80211_teardown_ap(bss); 60571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_destroy_bss(bss); 6058df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt if (!bss->added_if) 6059df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt i802_set_iface_flags(bss, 0); 60608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(bss); 60618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss = NULL; 60628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 60638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss) 60668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: %s - could not find " 60678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BSS %p in the list", __func__, bss); 6068cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } else { 6069cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context"); 6070cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt nl80211_teardown_ap(bss); 6071cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (!bss->added_if && !drv->first_bss->next) 6072cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_driver_nl80211_del_beacon(drv); 6073cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt nl80211_destroy_bss(bss); 6074cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (!bss->added_if) 6075cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt i802_set_iface_flags(bss, 0); 6076cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (drv->first_bss->next) { 6077cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt drv->first_bss = drv->first_bss->next; 6078cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt drv->ctx = drv->first_bss->ctx; 6079cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt os_free(bss); 6080cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } else { 6081cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to"); 6082cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } 60838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 60868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 60878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cookie_handler(struct nl_msg *msg, void *arg) 60908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 60918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 60928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 60938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 *cookie = arg; 60948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 60958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 60968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_COOKIE]) 60978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]); 60988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 60998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 61008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nl80211_send_frame_cmd(struct i802_bss *bss, 61038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int freq, unsigned int wait, 61048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t buf_len, 61051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u64 *cookie_out, int no_cck, int no_ack, 61061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int offchanok) 61078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 61081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 61098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 61108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 cookie; 61118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 61128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61138da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d " 611404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "no_ack=%d offchanok=%d", 611504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt freq, wait, no_cck, no_ack, offchanok); 6116c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len); 61178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) || 61196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || 61206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) || 61216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || 61226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->test_use_roc_tx) && 61236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) || 61246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (no_cck && nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE)) || 61256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (no_ack && nla_put_flag(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK)) || 61266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_FRAME, buf_len, buf)) 61276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 61288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie = 0; 61308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); 61318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 61328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 61338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d " 61346e933c1e09094a8972ef1e782c57f8b3c55c91d0Dmitry Shmidt "(%s) (freq=%u wait=%u)", ret, strerror(-ret), 61356e933c1e09094a8972ef1e782c57f8b3c55c91d0Dmitry Shmidt freq, wait); 61366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 61376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; " 61386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "cookie 0x%llx", no_ack ? " (no ACK)" : "", 61396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (long long unsigned int) cookie); 61408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (cookie_out) 61426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt *cookie_out = no_ack ? (u64) -1 : cookie; 61436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 61448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 61468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 61478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 61488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 61498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61514b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int wpa_driver_nl80211_send_action(struct i802_bss *bss, 61524b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt unsigned int freq, 61538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int wait_time, 61548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dst, const u8 *src, 61558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *bssid, 61561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *data, size_t data_len, 61571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int no_cck) 61588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 61598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 61608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 61618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 61628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_hdr *hdr; 61638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, " 6165c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "freq=%u MHz wait=%d ms no_cck=%d)", 6166c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt drv->ifindex, freq, wait_time, no_cck); 61678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(24 + data_len); 61698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 61708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 61718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf + 24, data, data_len); 61728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee80211_hdr *) buf; 61738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control = 61748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); 61758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr->addr1, dst, ETH_ALEN); 61768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr->addr2, src, ETH_ALEN); 61778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr->addr3, bssid, ETH_ALEN); 61788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61795605286c30e1701491bd3af974ae423727750eddDmitry Shmidt if (is_ap_interface(drv->nlmode) && 61805605286c30e1701491bd3af974ae423727750eddDmitry Shmidt (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || 61815605286c30e1701491bd3af974ae423727750eddDmitry Shmidt (int) freq == bss->freq || drv->device_ap_sme || 61825605286c30e1701491bd3af974ae423727750eddDmitry Shmidt !drv->use_monitor)) 61834b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len, 61844b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 0, freq, no_cck, 1, 61854b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt wait_time); 61868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 61871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf, 61888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24 + data_len, 61891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &drv->send_action_cookie, 61901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt no_cck, 0, 1); 61918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 61938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 61948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 61958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_send_action_cancel_wait(void *priv) 61988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 61998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 62008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 62018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 62028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 62038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62042f3b8dec59373945c5feef8a78ced8967a80cc66Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx", 62052f3b8dec59373945c5feef8a78ced8967a80cc66Dmitry Shmidt (long long unsigned int) drv->send_action_cookie); 62066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME_WAIT_CANCEL)) || 62076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie)) { 62086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 62096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 62106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 62118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 62138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 62148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d " 62158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 62168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 62178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq, 62208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int duration) 62218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 62228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 62238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 62248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 62258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 62268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 cookie; 62278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REMAIN_ON_CHANNEL)) || 62296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || 62306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_DURATION, duration)) { 62316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 62328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 62348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie = 0; 62368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); 62378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) { 62388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie " 62398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "0x%llx for freq=%u MHz duration=%u", 62408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long long unsigned int) cookie, freq, duration); 62418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->remain_on_chan_cookie = cookie; 62421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt drv->pending_remain_on_chan = 1; 62438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 62448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel " 62468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(freq=%d duration=%u): %d (%s)", 62478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq, duration, ret, strerror(-ret)); 62488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 62508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_cancel_remain_on_channel(void *priv) 62538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 62548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 62558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 62568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 62578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 62588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->pending_remain_on_chan) { 62608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel " 62618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "to cancel"); 62628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie " 62668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "0x%llx", 62678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long long unsigned int) drv->remain_on_chan_cookie); 62688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL); 62706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || 62716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie)) { 62726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 62738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 62758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 62778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) 62788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 62798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: " 62808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d (%s)", ret, strerror(-ret)); 62818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 62838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62854b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report) 62868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 62878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 62886e933c1e09094a8972ef1e782c57f8b3c55c91d0Dmitry Shmidt 62898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!report) { 62901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (bss->nl_preq && drv->device_ap_sme && 629103658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt is_ap_interface(drv->nlmode) && !bss->in_deinit && 629203658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt !bss->static_ap) { 62931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 62941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Do not disable Probe Request reporting that was 62951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * enabled in nl80211_setup_ap(). 62961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 62971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of " 62981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "Probe Request reporting nl_preq=%p while " 62991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "in AP mode", bss->nl_preq); 63001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (bss->nl_preq) { 63011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request " 63021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "reporting nl_preq=%p", bss->nl_preq); 630368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt nl80211_destroy_eloop_handle(&bss->nl_preq); 63048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 63058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 63068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 63078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (bss->nl_preq) { 63098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting " 63101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "already on! nl_preq=%p", bss->nl_preq); 63118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 63128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 63138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq"); 63151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (bss->nl_preq == NULL) 63168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request " 63181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "reporting nl_preq=%p", bss->nl_preq); 63198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (nl80211_register_frame(bss, bss->nl_preq, 63218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WLAN_FC_TYPE_MGMT << 2) | 63228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WLAN_FC_STYPE_PROBE_REQ << 4), 63231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt NULL, 0) < 0) 63241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto out_err; 6325497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt 632668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt nl80211_register_eloop_read(&bss->nl_preq, 632768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_driver_nl80211_event_receive, 632868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt bss->nl_cb); 63298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 63318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt out_err: 63331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl_destroy_handles(&bss->nl_preq); 63348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 63368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, 63398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, int disabled) 63408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 63418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 63428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *bands, *band; 63438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 63448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 63466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: NL80211_CMD_SET_TX_BITRATE_MASK (ifindex=%d %s)", 63476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ifindex, disabled ? "NL80211_TXRATE_LEGACY=OFDM-only" : 63486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "no NL80211_TXRATE_LEGACY constraint"); 63496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 63506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_ifindex_msg(drv, ifindex, 0, 63516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_CMD_SET_TX_BITRATE_MASK); 63528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 63538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES); 63568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!bands) 63576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 63588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 63608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything 63618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS 63628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rates. All 5 GHz rates are left enabled. 63638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 63648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt band = nla_nest_start(msg, NL80211_BAND_2GHZ); 63656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!band || 63666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (disabled && nla_put(msg, NL80211_TXRATE_LEGACY, 8, 63676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "\x0c\x12\x18\x24\x30\x48\x60\x6c"))) 63686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 63698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, band); 63708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, bands); 63728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 63748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 63758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d " 63768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 637761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 637861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt drv->disabled_11b_rates = disabled; 637961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 63808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 63818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 63838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 63848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 63868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_deinit_ap(void *priv) 63898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 63908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 63918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 63921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!is_ap_interface(drv->nlmode)) 63938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_del_beacon(drv); 63956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->beacon_set = 0; 6396b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 6397b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt /* 6398b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt * If the P2P GO interface was dynamically added, then it is 6399b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt * possible that the interface change to station is not possible. 6400b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt */ 6401b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_P2P_GO && bss->if_dynamic) 6402b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 0; 6403b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 64041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION); 64058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 64068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6408ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidtstatic int wpa_driver_nl80211_stop_ap(void *priv) 6409ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt{ 6410ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt struct i802_bss *bss = priv; 6411ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 6412ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt if (!is_ap_interface(drv->nlmode)) 6413ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt return -1; 6414ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt wpa_driver_nl80211_del_beacon(drv); 6415ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt bss->beacon_set = 0; 6416ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt return 0; 6417ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt} 6418ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 6419ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 642004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic int wpa_driver_nl80211_deinit_p2p_cli(void *priv) 642104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 642204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct i802_bss *bss = priv; 642304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 642404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT) 642504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return -1; 6426b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 6427b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt /* 6428b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt * If the P2P Client interface was dynamically added, then it is 6429b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt * possible that the interface change to station is not possible. 6430b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt */ 6431b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (bss->if_dynamic) 6432b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 0; 6433b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 64346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION); 64358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 64368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void wpa_driver_nl80211_resume(void *priv) 64398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 64408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 64418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (i802_set_iface_flags(bss, 1)) 64436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event"); 64448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 64458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_signal_monitor(void *priv, int threshold, int hysteresis) 64488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 64498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 64508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 64518da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt struct nl_msg *msg; 64528da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt struct nlattr *cqm; 64538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d " 64558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hysteresis=%d", threshold, hysteresis); 64568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_CQM)) || 64586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !(cqm = nla_nest_start(msg, NL80211_ATTR_CQM)) || 64596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold) || 64606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis)) { 64616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 64628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 64636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 64648da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt nla_nest_end(msg, cqm); 64658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 64678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 64688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 647034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int get_channel_width(struct nl_msg *msg, void *arg) 647134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 647234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 647334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 647434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpa_signal_info *sig_change = arg; 647534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 647634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 647734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 647834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 647934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sig_change->center_frq1 = -1; 648034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sig_change->center_frq2 = -1; 648134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sig_change->chanwidth = CHAN_WIDTH_UNKNOWN; 648234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 648334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (tb[NL80211_ATTR_CHANNEL_WIDTH]) { 648434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sig_change->chanwidth = convert2width( 648534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH])); 648634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (tb[NL80211_ATTR_CENTER_FREQ1]) 648734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sig_change->center_frq1 = 648834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]); 648934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (tb[NL80211_ATTR_CENTER_FREQ2]) 649034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt sig_change->center_frq2 = 649134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]); 649234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt } 649334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 649434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return NL_SKIP; 649534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 649634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 649734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 649834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidtstatic int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv, 649934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpa_signal_info *sig) 650034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 650134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct nl_msg *msg; 650234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 65036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE); 650434af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return send_and_recv_msgs(drv, msg, get_channel_width, sig); 650534af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt} 650634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 650734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 65088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_signal_poll(void *priv, struct wpa_signal_info *si) 65098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 65118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 65128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 65138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(si, 0, sizeof(*si)); 65158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = nl80211_get_link_signal(drv, si); 65168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res != 0) 65178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 65188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 651934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt res = nl80211_get_channel_width(drv, si); 652034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt if (res != 0) 652134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt return res; 652234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 65238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return nl80211_get_link_noise(drv, si); 65248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nl80211_send_frame(void *priv, const u8 *data, size_t data_len, 65281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int encrypt) 65291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 65301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct i802_bss *bss = priv; 6531c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0, 6532c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 0, 0, 0, 0); 65338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_set_param(void *priv, const char *param) 65378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param); 65398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (param == NULL) 65408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 65418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 65438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(param, "use_p2p_group_interface=1")) { 65448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 65458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 65468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group " 65488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface"); 65498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; 65508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P; 65518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 65528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 65538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6554fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (os_strstr(param, "use_monitor=1")) { 6555fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct i802_bss *bss = priv; 6556fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 6557fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt drv->use_monitor = 1; 6558fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 6559fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 6560fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (os_strstr(param, "force_connect_cmd=1")) { 6561fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct i802_bss *bss = priv; 6562fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 6563fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME; 6564661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt drv->force_connect_cmd = 1; 6565fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 6566fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 65677d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt if (os_strstr(param, "no_offchannel_tx=1")) { 65687d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt struct i802_bss *bss = priv; 65697d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 65707d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_TX; 65717d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt drv->test_use_roc_tx = 1; 65727d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt } 65737d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt 65748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 65758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * nl80211_global_init(void) 65798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_global *global; 65811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct netlink_config *cfg; 65821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 65838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global = os_zalloc(sizeof(*global)); 65848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global == NULL) 65858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 65861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt global->ioctl_sock = -1; 65878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&global->interfaces); 65881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt global->if_add_ifindex = -1; 65891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 65901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cfg = os_zalloc(sizeof(*cfg)); 65911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (cfg == NULL) 65921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto err; 65931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 65941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cfg->ctx = global; 65951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink; 65961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink; 65971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt global->netlink = netlink_init(cfg); 65981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (global->netlink == NULL) { 65991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(cfg); 66001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto err; 66011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 66021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_driver_nl80211_init_nl_global(global) < 0) 66041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto err; 66051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); 66071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (global->ioctl_sock < 0) { 660868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s", 660968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt strerror(errno)); 66101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto err; 66111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 66121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return global; 66141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidterr: 66161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl80211_global_deinit(global); 66171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 66188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 66198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 66208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 66218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_global_deinit(void *priv) 66228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 66238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_global *global = priv; 66248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global == NULL) 66258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 66268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!dl_list_empty(&global->interfaces)) { 66278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at " 66288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "nl80211_global_deinit", 66298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_len(&global->interfaces)); 66308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 66311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (global->netlink) 66331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt netlink_deinit(global->netlink); 66341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl_destroy_handles(&global->nl); 66361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 663768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (global->nl_event) 663868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt nl80211_destroy_eloop_handle(&global->nl_event); 66391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt nl_cb_put(global->nl_cb); 66411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 66426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (global->ioctl_sock >= 0) 66436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt close(global->ioctl_sock); 66446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(global); 66466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 66476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic const char * nl80211_get_radio_name(void *priv) 66506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 66516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 66526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 66536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return drv->phyname; 66546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 66556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid, 66586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *pmkid) 66596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 66606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 66616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, cmd)) || 66636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (pmkid && nla_put(msg, NL80211_ATTR_PMKID, 16, pmkid)) || 66646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid))) { 66656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 66666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 66676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 66686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(bss->drv, msg, NULL, NULL); 66706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 66716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid) 66746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 66756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 66766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR, MAC2STR(bssid)); 66776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid); 66786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 66796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid) 66826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 66836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 66846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR, 66856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(bssid)); 66866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid); 66876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 66886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_flush_pmkid(void *priv) 66916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 66926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 66936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs"); 66946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL); 66956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 66966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 66986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void clean_survey_results(struct survey_results *survey_results) 66996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 67006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct freq_survey *survey, *tmp; 67016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (dl_list_empty(&survey_results->survey_list)) 67036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 67046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_for_each_safe(survey, tmp, &survey_results->survey_list, 67066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct freq_survey, list) { 67076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_del(&survey->list); 67086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_free(survey); 67096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 67106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 67116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void add_survey(struct nlattr **sinfo, u32 ifidx, 67146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct dl_list *survey_list) 67156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 67166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct freq_survey *survey; 67176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey = os_zalloc(sizeof(struct freq_survey)); 67196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!survey) 67206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 67216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->ifidx = ifidx; 67236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]); 67246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->filled = 0; 67256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sinfo[NL80211_SURVEY_INFO_NOISE]) { 67276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->nf = (int8_t) 67286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]); 67296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->filled |= SURVEY_HAS_NF; 67306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 67316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]) { 67336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->channel_time = 67346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]); 67356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->filled |= SURVEY_HAS_CHAN_TIME; 67366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 67376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]) { 67396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->channel_time_busy = 67406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]); 67416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->filled |= SURVEY_HAS_CHAN_TIME_BUSY; 67426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 67436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]) { 67456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->channel_time_rx = 67466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]); 67476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->filled |= SURVEY_HAS_CHAN_TIME_RX; 67486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 67496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]) { 67516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->channel_time_tx = 67526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]); 67536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->filled |= SURVEY_HAS_CHAN_TIME_TX; 67546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 67556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 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)", 67576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->freq, 67586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->nf, 67596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (unsigned long int) survey->channel_time, 67606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (unsigned long int) survey->channel_time_busy, 67616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (unsigned long int) survey->channel_time_tx, 67626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (unsigned long int) survey->channel_time_rx, 67636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey->filled); 67646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_add_tail(survey_list, &survey->list); 67666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 67676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int check_survey_ok(struct nlattr **sinfo, u32 surveyed_freq, 67706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int freq_filter) 67716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 67726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!freq_filter) 67736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 1; 67746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return freq_filter == surveyed_freq; 67766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 67776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int survey_handler(struct nl_msg *msg, void *arg) 67806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 67816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 67826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 67836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1]; 67846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct survey_results *survey_results; 67856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 surveyed_freq = 0; 67866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 ifidx; 67876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = { 67896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 }, 67906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 }, 67916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt }; 67926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_results = (struct survey_results *) arg; 67946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 67966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 67976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 67986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb[NL80211_ATTR_IFINDEX]) 67996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 68006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); 68026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!tb[NL80211_ATTR_SURVEY_INFO]) 68046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 68056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX, 68076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tb[NL80211_ATTR_SURVEY_INFO], 68086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_policy)) 68096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 68106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) { 68126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Invalid survey data"); 68136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 68146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 68156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt surveyed_freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]); 68176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!check_survey_ok(sinfo, surveyed_freq, 68196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_results->freq_filter)) 68206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 68216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (survey_results->freq_filter && 68236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_results->freq_filter != surveyed_freq) { 68246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_EXCESSIVE, "nl80211: Ignoring survey data for freq %d MHz", 68256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt surveyed_freq); 68266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 68276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 68286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt add_survey(sinfo, ifidx, &survey_results->survey_list); 68306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 68326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 68336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq) 68366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 68376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 68386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 68396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 68406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int err; 68416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt union wpa_event_data data; 68426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct survey_results *survey_results; 68436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(&data, 0, sizeof(data)); 68456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_results = &data.survey_results; 68466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt dl_list_init(&survey_results->survey_list); 68486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); 68506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 68516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 68526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (freq) 68546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt data.survey_results.freq_filter = freq; 68556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt do { 68576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data"); 68586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt err = send_and_recv_msgs(drv, msg, survey_handler, 68596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt survey_results); 68606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } while (err > 0); 68616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (err) 68636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data"); 68646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt else 68656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data); 68661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 68676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt clean_survey_results(survey_results); 68686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return err; 68698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 68708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 68718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6872807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidtstatic void nl80211_set_rekey_info(void *priv, const u8 *kek, size_t kek_len, 6873807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt const u8 *kck, size_t kck_len, 68746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *replay_ctr) 68758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 68768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 68778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 68786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *replay_nested; 68796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 6880ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int ret; 68816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6882ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!drv->set_rekey_offload) 6883ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return; 6884ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 6885ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set rekey offload"); 68866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_REKEY_OFFLOAD)) || 68876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !(replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA)) || 6888807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt nla_put(msg, NL80211_REKEY_DATA_KEK, kek_len, kek) || 6889807291d85bf857320aff6a8ade38c5f622ab9df8Dmitry Shmidt nla_put(msg, NL80211_REKEY_DATA_KCK, kck_len, kck) || 68906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN, 68916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt replay_ctr)) { 68926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_nlmsg_clear(msg); 68936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 68946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 68956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 68966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 68976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, replay_nested); 68986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 6899ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); 6900ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (ret == -EOPNOTSUPP) { 6901ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_printf(MSG_DEBUG, 6902ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt "nl80211: Driver does not support rekey offload"); 6903ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt drv->set_rekey_offload = 0; 6904ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 69058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 69068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 69078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 69086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr, 69096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr, int qos) 691075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 69116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* send data frame to poll STA and check whether 69126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * this frame is ACKed */ 69136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct { 69146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct ieee80211_hdr hdr; 69156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 qos_ctl; 69166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } STRUCT_PACKED nulldata; 69176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t size; 691875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* Send data frame to poll STA and check whether this frame is ACKed */ 692075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memset(&nulldata, 0, sizeof(nulldata)); 69226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 69236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (qos) { 69246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nulldata.hdr.frame_control = 69256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt IEEE80211_FC(WLAN_FC_TYPE_DATA, 69266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_QOS_NULL); 69276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size = sizeof(nulldata); 69286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 69296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nulldata.hdr.frame_control = 69306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt IEEE80211_FC(WLAN_FC_TYPE_DATA, 69316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt WLAN_FC_STYPE_NULLFUNC); 69326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size = sizeof(struct ieee80211_hdr); 69336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 693475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); 69366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN); 69376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); 69386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); 693975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0, 69416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 0, 0) < 0) 69426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to " 69436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "send poll frame"); 694475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 694575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr, 69476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int qos) 694875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 694975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct i802_bss *bss = priv; 69506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 69516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 69527f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt int ret; 695375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->poll_command_supported) { 69556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_send_null_frame(bss, own_addr, addr, qos); 69566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 69576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 695875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_PROBE_CLIENT)) || 69606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) { 69616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 69626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return; 69636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 69646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 69657f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 69667f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (ret < 0) { 69677f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Client probe request for " 69687f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt MACSTR " failed: ret=%d (%s)", 69697f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt MAC2STR(addr), ret, strerror(-ret)); 69707f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 697175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 697275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 697375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_power_save(struct i802_bss *bss, int enabled) 697575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 69766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 69776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 69786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_POWER_SAVE)) || 69796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_PS_STATE, 69806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED)) { 69816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 69826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 69836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 69846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(bss->drv, msg, NULL, NULL); 698575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 698675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 698775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 69886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps, 69896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ctwindow) 6990b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 69916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 6992b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 69936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d " 69946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow); 6995b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 69966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (opp_ps != -1 || ctwindow != -1) { 69976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef ANDROID_P2P 69986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_set_p2p_ps(priv, legacy_ps, opp_ps, ctwindow); 69996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#else /* ANDROID_P2P */ 70006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; /* Not yet supported */ 70016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* ANDROID_P2P */ 7002b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 70036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 70046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (legacy_ps == -1) 70056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 70066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (legacy_ps != 0 && legacy_ps != 1) 70076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; /* Not yet supported */ 70086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 70096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return nl80211_set_power_save(bss, legacy_ps); 7010b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 7011b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7012b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_start_radar_detection(void *priv, 70146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct hostapd_freq_params *freq) 7015b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 70166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 70176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 70186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 70196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 7020b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 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)", 70226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq->freq, freq->ht_enabled, freq->vht_enabled, 70236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt freq->bandwidth, freq->center_freq1, freq->center_freq2); 7024b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) { 70266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar " 70276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "detection"); 70286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 7029b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 7030b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_RADAR_DETECT)) || 70326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_put_freq_params(msg, freq) < 0) { 70336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 70346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 7035b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 7036b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 70386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret == 0) 70396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 70406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: " 70416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "%d (%s)", ret, strerror(-ret)); 70426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 70436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 7044b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_TDLS 7046b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code, 70486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 dialog_token, u16 status_code, 70496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 peer_capab, int initiator, const u8 *buf, 70506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t len) 70516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 70526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 70536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 70546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 7055b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) 70576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EOPNOTSUPP; 7058b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!dst) 70606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 7061b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_TDLS_MGMT)) || 70636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dst) || 70646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_TDLS_ACTION, action_code) || 70656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token) || 70666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status_code)) 70676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 70686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (peer_capab) { 70696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* 70706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * The internal enum tdls_peer_capability definition is 70716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * currently identical with the nl80211 enum 70726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * nl80211_tdls_peer_capability, so no conversion is needed 70736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * here. 70746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt */ 70756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY, 70766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt peer_capab)) 70776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 70786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 70796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((initiator && 70806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_ATTR_TDLS_INITIATOR)) || 70816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_IE, len, buf)) 70826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 7083b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 7085b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 70876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 70886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 7089b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 7090b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7091b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer) 7093b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 70946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 70956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 70966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 70976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum nl80211_tdls_operation nl80211_oper; 7098b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 70996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) 71006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EOPNOTSUPP; 71019767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt 71026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (oper) { 71036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case TDLS_DISCOVERY_REQ: 71046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_oper = NL80211_TDLS_DISCOVERY_REQ; 71056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 71066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case TDLS_SETUP: 71076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_oper = NL80211_TDLS_SETUP; 71086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 71096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case TDLS_TEARDOWN: 71106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_oper = NL80211_TDLS_TEARDOWN; 71116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 71126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case TDLS_ENABLE_LINK: 71136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_oper = NL80211_TDLS_ENABLE_LINK; 71146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 71156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case TDLS_DISABLE_LINK: 71166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_oper = NL80211_TDLS_DISABLE_LINK; 71176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 71186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case TDLS_ENABLE: 71196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 71206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case TDLS_DISABLE: 71216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 71226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 71236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 71246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7125b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_TDLS_OPER)) || 71276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper) || 71286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) { 71296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 71306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 71316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7132b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 71346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 7135b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7136b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int 71386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtnl80211_tdls_enable_channel_switch(void *priv, const u8 *addr, u8 oper_class, 71396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const struct hostapd_freq_params *params) 71406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 71416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 71426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 71436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 71446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = -ENOBUFS; 7145b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) || 71476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH)) 71486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EOPNOTSUPP; 7149b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Enable TDLS channel switch " MACSTR 71516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt " oper_class=%u freq=%u", 71526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(addr), oper_class, params->freq); 71536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_TDLS_CHANNEL_SWITCH); 71546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || 71556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || 71566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_OPER_CLASS, oper_class) || 71576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (ret = nl80211_put_freq_params(msg, params))) { 71586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 71596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not build TDLS chan switch"); 71606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 7161b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 7162b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 7164b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 7165b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7166b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int 71686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtnl80211_tdls_disable_channel_switch(void *priv, const u8 *addr) 7169b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 7170b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt struct i802_bss *bss = priv; 7171b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 7172b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt struct nl_msg *msg; 7173b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) || 71756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH)) 71766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EOPNOTSUPP; 7177b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Disable TDLS channel switch " MACSTR, 71796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(addr)); 71806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH); 71816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || 71826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) { 71836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 71846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 71856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Could not build TDLS cancel chan switch"); 71866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 71876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7188b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 71906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 7191b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG TDLS */ 7193b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7194b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 71956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_set_key(const char *ifname, void *priv, 71966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt enum wpa_alg alg, const u8 *addr, 71976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int key_idx, int set_tx, 71986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *seq, size_t seq_len, 71996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *key, size_t key_len) 72006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx, 72036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt set_tx, seq, seq_len, key, key_len); 72046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 7205b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7206b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 72076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_scan2(void *priv, 72086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_scan_params *params) 72096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_scan(bss, params); 72126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 7213b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7214b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 72156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_deauthenticate(void *priv, const u8 *addr, 72166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int reason_code) 72176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code); 7220b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 7221b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 7222b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 72236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_authenticate(void *priv, 72246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_auth_params *params) 72251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 72261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct i802_bss *bss = priv; 72276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_authenticate(bss, params); 72286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 72291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic void driver_nl80211_deinit(void *priv) 72326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_driver_nl80211_deinit(bss); 72356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 72361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type, 72396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const char *ifname) 72406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_if_remove(bss, type, ifname); 72436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 72441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_send_mlme(void *priv, const u8 *data, 7247a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt size_t data_len, int noack, 7248a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt unsigned int freq) 72496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack, 7252a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt freq, 0, 0, 0); 72536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 72541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 72566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_sta_remove(void *priv, const u8 *addr) 72576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_sta_remove(bss, addr, -1, 0); 72601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 72611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_set_sta_vlan(void *priv, const u8 *addr, 72646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const char *ifname, int vlan_id) 72651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 72666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return i802_set_sta_vlan(bss, addr, ifname, vlan_id); 72686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 72691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_read_sta_data(void *priv, 72726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct hostap_sta_driver_data *data, 72736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr) 72746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return i802_read_sta_data(bss, data, addr); 72776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 72781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_send_action(void *priv, unsigned int freq, 72816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int wait_time, 72826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *dst, const u8 *src, 72836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *bssid, 72846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *data, size_t data_len, 72856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int no_cck) 72866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src, 72896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bssid, data, data_len, no_cck); 72906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 72911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 72936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int driver_nl80211_probe_req_report(void *priv, int report) 72946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 72956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 72966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return wpa_driver_nl80211_probe_req_report(bss, report); 72971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 72981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 72996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 73006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md, 73016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ies, size_t ies_len) 73021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 73036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 73046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 73051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct i802_bss *bss = priv; 73061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 73076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u16 mdid = WPA_GET_LE16(md); 73081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs"); 73106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_UPDATE_FT_IES)) || 73116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_IE, ies_len, ies) || 73126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_MDID, mdid)) { 73136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 73146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 73151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 73161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 73186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 73196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed " 73206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "err=%d (%s)", ret, strerror(-ret)); 73216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 73221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 73241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 73251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtconst u8 * wpa_driver_nl80211_get_macaddr(void *priv) 73281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 73296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 73306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 73311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) 73336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 73341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return bss->addr; 73361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 73371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic const char * scan_state_str(enum scan_states scan_state) 73401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 73416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (scan_state) { 73426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case NO_SCAN: 73436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "NO_SCAN"; 73446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case SCAN_REQUESTED: 73456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "SCAN_REQUESTED"; 73466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case SCAN_STARTED: 73476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "SCAN_STARTED"; 73486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case SCAN_COMPLETED: 73496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "SCAN_COMPLETED"; 73506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case SCAN_ABORTED: 73516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "SCAN_ABORTED"; 73526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case SCHED_SCAN_STARTED: 73536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "SCHED_SCAN_STARTED"; 73546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case SCHED_SCAN_STOPPED: 73556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "SCHED_SCAN_STOPPED"; 73566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case SCHED_SCAN_RESULTS: 73576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "SCHED_SCAN_RESULTS"; 7358292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt } 73591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "??"; 73611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 73621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 73646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen) 7365ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt{ 7366ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt struct i802_bss *bss = priv; 7367ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 73686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int res; 73696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char *pos, *end; 7370ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 73716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos = buf; 73726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt end = buf + buflen; 7373051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 73746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = os_snprintf(pos, end - pos, 73756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "ifindex=%d\n" 73766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "ifname=%s\n" 73776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "brname=%s\n" 73786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "addr=" MACSTR "\n" 73796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "freq=%d\n" 73806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "%s%s%s%s%s", 73816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifindex, 73826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, 73836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->brname, 73846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(bss->addr), 73856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->freq, 73866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->beacon_set ? "beacon_set=1\n" : "", 73876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->added_if_into_bridge ? 73886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "added_if_into_bridge=1\n" : "", 73896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->added_bridge ? "added_bridge=1\n" : "", 73906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->in_deinit ? "in_deinit=1\n" : "", 73916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->if_dynamic ? "if_dynamic=1\n" : ""); 73926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, res)) 73936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return pos - buf; 73946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos += res; 7395ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 73966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->wdev_id_set) { 73976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = os_snprintf(pos, end - pos, "wdev_id=%llu\n", 73986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (unsigned long long) bss->wdev_id); 73996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, res)) 74006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return pos - buf; 74016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos += res; 74026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7403ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 74046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = os_snprintf(pos, end - pos, 74056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "phyname=%s\n" 74066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "perm_addr=" MACSTR "\n" 74076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "drv_ifindex=%d\n" 74086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "operstate=%d\n" 74096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "scan_state=%s\n" 74106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "auth_bssid=" MACSTR "\n" 74116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "auth_attempt_bssid=" MACSTR "\n" 74126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "bssid=" MACSTR "\n" 74136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "prev_bssid=" MACSTR "\n" 74146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "associated=%d\n" 74156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "assoc_freq=%u\n" 74166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "monitor_sock=%d\n" 74176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "monitor_ifidx=%d\n" 74186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "monitor_refcount=%d\n" 74196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "last_mgmt_freq=%u\n" 74206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "eapol_tx_sock=%d\n" 74216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "%s%s%s%s%s%s%s%s%s%s%s%s%s", 74226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->phyname, 74236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(drv->perm_addr), 74246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ifindex, 74256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->operstate, 74266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt scan_state_str(drv->scan_state), 74276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(drv->auth_bssid), 74286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(drv->auth_attempt_bssid), 74296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(drv->bssid), 74306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt MAC2STR(drv->prev_bssid), 74316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->associated, 74326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->assoc_freq, 74336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->monitor_sock, 74346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->monitor_ifidx, 74356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->monitor_refcount, 74366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->last_mgmt_freq, 74376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->eapol_tx_sock, 74386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ignore_if_down_event ? 74396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "ignore_if_down_event=1\n" : "", 74406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->scan_complete_events ? 74416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "scan_complete_events=1\n" : "", 74426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->disabled_11b_rates ? 74436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "disabled_11b_rates=1\n" : "", 74446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->pending_remain_on_chan ? 74456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "pending_remain_on_chan=1\n" : "", 74466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->in_interface_list ? "in_interface_list=1\n" : "", 74476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->device_ap_sme ? "device_ap_sme=1\n" : "", 74486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->poll_command_supported ? 74496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "poll_command_supported=1\n" : "", 74506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->data_tx_status ? "data_tx_status=1\n" : "", 74516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->scan_for_auth ? "scan_for_auth=1\n" : "", 74526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->retry_auth ? "retry_auth=1\n" : "", 74536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->use_monitor ? "use_monitor=1\n" : "", 74546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ignore_next_local_disconnect ? 74556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "ignore_next_local_disconnect=1\n" : "", 74566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->ignore_next_local_deauth ? 74576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "ignore_next_local_deauth=1\n" : ""); 74586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, res)) 74596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return pos - buf; 74606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos += res; 7461ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 74626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (drv->has_capability) { 74636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = os_snprintf(pos, end - pos, 74646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.key_mgmt=0x%x\n" 74656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.enc=0x%x\n" 74666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.auth=0x%x\n" 74676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.flags=0x%llx\n" 74686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.rrm_flags=0x%x\n" 74696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.max_scan_ssids=%d\n" 74706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.max_sched_scan_ssids=%d\n" 74716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.sched_scan_supported=%d\n" 74726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.max_match_sets=%d\n" 74736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.max_remain_on_chan=%u\n" 74746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.max_stations=%u\n" 74756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.probe_resp_offloads=0x%x\n" 74766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.max_acl_mac_addrs=%u\n" 74776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.num_multichan_concurrent=%u\n" 74786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.mac_addr_rand_sched_scan_supported=%d\n" 74796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "capa.mac_addr_rand_scan_supported=%d\n", 74806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.key_mgmt, 74816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.enc, 74826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.auth, 74836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (unsigned long long) drv->capa.flags, 74846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.rrm_flags, 74856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.max_scan_ssids, 74866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.max_sched_scan_ssids, 74876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.sched_scan_supported, 74886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.max_match_sets, 74896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.max_remain_on_chan, 74906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.max_stations, 74916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.probe_resp_offloads, 74926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.max_acl_mac_addrs, 74936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.num_multichan_concurrent, 74946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.mac_addr_rand_sched_scan_supported, 74956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->capa.mac_addr_rand_scan_supported); 74966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(end - pos, res)) 74976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return pos - buf; 74986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt pos += res; 74996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7500ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 75016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return pos - buf; 7502ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt} 7503ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt 75041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int set_beacon_data(struct nl_msg *msg, struct beacon_data *settings) 75061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 75076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((settings->head && 75086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_BEACON_HEAD, 75096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->head_len, settings->head)) || 75106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->tail && 75116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_BEACON_TAIL, 75126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->tail_len, settings->tail)) || 75136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->beacon_ies && 75146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_IE, 75156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->beacon_ies_len, settings->beacon_ies)) || 75166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->proberesp_ies && 75176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_IE_PROBE_RESP, 75186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->proberesp_ies_len, settings->proberesp_ies)) || 75196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->assocresp_ies && 75206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP, 75216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->assocresp_ies_len, settings->assocresp_ies)) || 75226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->probe_resp && 75236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_PROBE_RESP, 75246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->probe_resp_len, settings->probe_resp))) 75256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 75261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 75281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 75291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_switch_channel(void *priv, struct csa_settings *settings) 75321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 75336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 75341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct i802_bss *bss = priv; 75351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 75366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *beacon_csa; 75376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret = -ENOBUFS; 75381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d width=%d cf1=%d cf2=%d)", 75406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->cs_count, settings->block_tx, 75416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->freq_params.freq, settings->freq_params.bandwidth, 75426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->freq_params.center_freq1, 75436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->freq_params.center_freq2); 75441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) { 75466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command"); 75476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EOPNOTSUPP; 75481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 75491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((drv->nlmode != NL80211_IFTYPE_AP) && 75516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (drv->nlmode != NL80211_IFTYPE_P2P_GO)) 75526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EOPNOTSUPP; 75531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* check settings validity */ 75556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!settings->beacon_csa.tail || 75566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ((settings->beacon_csa.tail_len <= 75576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->counter_offset_beacon) || 75586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->beacon_csa.tail[settings->counter_offset_beacon] != 75596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->cs_count))) 75606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 75611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (settings->beacon_csa.probe_resp && 75636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ((settings->beacon_csa.probe_resp_len <= 75646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->counter_offset_presp) || 75656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->beacon_csa.probe_resp[settings->counter_offset_presp] != 75666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->cs_count))) 75676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 75681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_CHANNEL_SWITCH)) || 75706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, 75716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->cs_count) || 75726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (ret = nl80211_put_freq_params(msg, &settings->freq_params)) || 75736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->block_tx && 75746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX))) 75756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto error; 75761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* beacon_after params */ 75786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = set_beacon_data(msg, &settings->beacon_after); 75796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 75806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto error; 75811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* beacon_csa params */ 75836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES); 75846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!beacon_csa) 75856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 75861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = set_beacon_data(msg, &settings->beacon_csa); 75886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 75896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto error; 75901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u16(msg, NL80211_ATTR_CSA_C_OFF_BEACON, 75926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->counter_offset_beacon) || 75936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (settings->beacon_csa.probe_resp && 75946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_CSA_C_OFF_PRESP, 75956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt settings->counter_offset_presp))) 75966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 75971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 75986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, beacon_csa); 75996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 76006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 76016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)", 76026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 76031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 76046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 76056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 76066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 76076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = -ENOBUFS; 76086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidterror: 76096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 76106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not build channel switch request"); 76116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 76121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 76131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr, 76166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 user_priority, u16 admitted_time) 76171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 76186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 76191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 76206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 76211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int ret; 76221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 76246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: add_ts request: tsid=%u admitted_time=%u up=%d", 76256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt tsid, admitted_time, user_priority); 76261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!is_sta_interface(drv->nlmode)) 76286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOTSUP; 76291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ADD_TX_TS); 76316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg || 76326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_TSID, tsid) || 76336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || 76346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_USER_PRIO, user_priority) || 76356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_ATTR_ADMITTED_TIME, admitted_time)) { 76366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 76376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 76381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 76391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 76416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 76426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: add_ts failed err=%d (%s)", 76436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 76446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 76451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 76461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_del_ts(void *priv, u8 tsid, const u8 *addr) 76491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 76506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 76511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 76526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 76536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 76541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: del_ts request: tsid=%u", tsid); 76561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!is_sta_interface(drv->nlmode)) 76586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOTSUP; 76591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_TX_TS)) || 76616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, NL80211_ATTR_TSID, tsid) || 76626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) { 76636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 76646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 76656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 76661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 76676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 76686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 76696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: del_ts failed err=%d (%s)", 76706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 76716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 76724b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 76734b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 76744b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 76756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 76766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int cmd_reply_handler(struct nl_msg *msg, void *arg) 76774b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 76786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 76796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpabuf *buf = arg; 76804b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 76816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!buf) 76826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 76834b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 76846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((size_t) genlmsg_attrlen(gnlh, 0) > wpabuf_tailroom(buf)) { 76856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, "nl80211: insufficient buffer space for reply"); 76866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 76876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 76884b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 76896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_put_data(buf, genlmsg_attrdata(gnlh, 0), 76906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0)); 76914b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 76926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 76934b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 76946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 76954b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 76964b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 76976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int vendor_reply_handler(struct nl_msg *msg, void *arg) 76984b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 76996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 77006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *nl_vendor_reply, *nl; 77016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 77026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpabuf *buf = arg; 77036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int rem; 77044b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!buf) 77066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 77074b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 77096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 77106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_vendor_reply = tb[NL80211_ATTR_VENDOR_DATA]; 77114b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!nl_vendor_reply) 77136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 77144b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((size_t) nla_len(nl_vendor_reply) > wpabuf_tailroom(buf)) { 77166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Vendor command: insufficient buffer space for reply"); 77176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 77186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 77194b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_for_each_nested(nl, nl_vendor_reply, rem) { 77216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpabuf_put_data(buf, nla_data(nl), nla_len(nl)); 77226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 77234b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NL_SKIP; 77254b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 77264b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77274b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, 77296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int subcmd, const u8 *data, 77306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt size_t data_len, struct wpabuf *buf) 77314b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{ 77324b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt struct i802_bss *bss = priv; 77336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 77346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 77356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 77364b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS 77386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (vendor_id == 0xffffffff) { 77396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nlmsg_alloc(); 77406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!msg) 77416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOMEM; 77424b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl80211_cmd(drv, msg, 0, subcmd); 77446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) < 77456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 0) 77466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 77476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf); 77486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 77496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d", 77506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret); 77516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 77526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 77536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */ 77544b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_VENDOR)) || 77566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, vendor_id) || 77576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd) || 77586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (data && 77596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_VENDOR_DATA, data_len, data))) 77606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 77614b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf); 77636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 77646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d", 77656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret); 77666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 77674b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 77696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 77706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 77714b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt} 77724b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77734b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt 77746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_qos_map(void *priv, const u8 *qos_map_set, 77756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u8 qos_map_set_len) 7776700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt{ 7777700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt struct i802_bss *bss = priv; 7778700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 77796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 77806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 7781700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 77826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map", 77836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt qos_map_set, qos_map_set_len); 7784700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 77856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_QOS_MAP)) || 77866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set)) { 77876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 77886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 77896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7790700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 7791700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 77926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 77936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed"); 7794700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 7795700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt return ret; 7796700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt} 7797700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 7798700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt 77996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_wowlan(void *priv, 78006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const struct wowlan_triggers *triggers) 780134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt{ 780234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct i802_bss *bss = priv; 780334af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 78046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 78056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *wowlan_triggers; 78066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 780734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 78086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan"); 780934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 7810a3dc30964aa24aea2b518246f6812663a1103490Dmitry Shmidt if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_SET_WOWLAN)) || 78116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !(wowlan_triggers = nla_nest_start(msg, 78126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_ATTR_WOWLAN_TRIGGERS)) || 78136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (triggers->any && 78146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) || 78156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (triggers->disconnect && 78166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) || 78176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (triggers->magic_pkt && 78186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) || 78196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (triggers->gtk_rekey_failure && 78206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) || 78216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (triggers->eap_identity_req && 78226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) || 78236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (triggers->four_way_handshake && 78246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) || 78256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (triggers->rfkill_release && 78266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE))) { 78276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 78286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 78296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 783034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 78316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, wowlan_triggers); 783234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt 78336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 78346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) 78356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed"); 78365605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 78385605286c30e1701491bd3af974ae423727750eddDmitry Shmidt} 78395605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78405605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_roaming(void *priv, int allowed, const u8 *bssid) 78425605286c30e1701491bd3af974ae423727750eddDmitry Shmidt{ 78435605286c30e1701491bd3af974ae423727750eddDmitry Shmidt struct i802_bss *bss = priv; 78445605286c30e1701491bd3af974ae423727750eddDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 78456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 78466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *params; 78475605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Roaming policy: allowed=%d", allowed); 78495605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->roaming_vendor_cmd_avail) { 78516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 78526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Ignore roaming policy change since driver does not provide command for setting it"); 78536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 78545605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 78555605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 78576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 78586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 78596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_ROAMING) || 78606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || 78616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY, 78626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt allowed ? QCA_ROAMING_ALLOWED_WITHIN_ESS : 78636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt QCA_ROAMING_NOT_ALLOWED) || 78646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (bssid && 78656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put(msg, QCA_WLAN_VENDOR_ATTR_MAC_ADDR, ETH_ALEN, bssid))) { 78666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 78676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 78685605286c30e1701491bd3af974ae423727750eddDmitry Shmidt } 78696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, params); 78705605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 78725605286c30e1701491bd3af974ae423727750eddDmitry Shmidt} 78735605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78745605286c30e1701491bd3af974ae423727750eddDmitry Shmidt 78756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int nl80211_set_mac_addr(void *priv, const u8 *addr) 7876e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{ 78776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 78786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 78796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int new_addr = addr != NULL; 7880e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 78816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!addr) 78826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt addr = drv->perm_addr; 7883e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 78846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0) 78856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 7886e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 78876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr) < 0) 78886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 78896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 78906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: failed to set_mac_addr for %s to " MACSTR, 78916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, MAC2STR(addr)); 78926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 78936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 1) < 0) { 78946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 78956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Could not restore interface UP after failed set_mac_addr"); 78966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 78976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 78986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7899e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 79006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR, 79016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, MAC2STR(addr)); 79026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt drv->addr_changed = new_addr; 79036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_memcpy(bss->addr, addr, ETH_ALEN); 7904e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 79056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0) 79066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt { 79076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 79086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Could not restore interface UP after set_mac_addr"); 79096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 7910e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 7911e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return 0; 79126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 7913e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 79146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 79156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_MESH 79166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 79176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_init_mesh(void *priv) 79186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 79196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_MESH_POINT)) { 79206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, 79216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Failed to set interface into mesh mode"); 79226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 79236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 79246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 7925e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt} 7926e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 7927e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 7928ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidtstatic int nl80211_put_mesh_id(struct nl_msg *msg, const u8 *mesh_id, 7929ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt size_t mesh_id_len) 7930ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt{ 7931ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (mesh_id) { 7932ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " * Mesh ID (SSID)", 7933ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt mesh_id, mesh_id_len); 7934ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return nla_put(msg, NL80211_ATTR_MESH_ID, mesh_id_len, mesh_id); 7935ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt } 7936ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 7937ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return 0; 7938ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt} 7939ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 7940ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt 79417f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic int nl80211_join_mesh(struct i802_bss *bss, 79426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_mesh_join_params *params) 7943e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt{ 7944e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 79456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 79466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *container; 79472f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt int ret = -1; 7948e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 79496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: mesh join (ifindex=%d)", drv->ifindex); 79506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_MESH); 7951ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (!msg || 7952ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nl80211_put_freq_params(msg, ¶ms->freq) || 7953ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nl80211_put_basic_rates(msg, params->basic_rates) || 7954ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) || 7955ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt nl80211_put_beacon_int(msg, params->beacon_int)) 79566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 7957e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 79586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags); 7959e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 79606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP); 79616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!container) 79626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 79636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 79646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->ies) { 79656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_hexdump(MSG_DEBUG, " * IEs", params->ies, params->ie_len); 79666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put(msg, NL80211_MESH_SETUP_IE, params->ie_len, 79676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->ies)) 79686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 79696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 79706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* WPA_DRIVER_MESH_FLAG_OPEN_AUTH is treated as default by nl80211 */ 79716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (params->flags & WPA_DRIVER_MESH_FLAG_SAE_AUTH) { 79726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nla_put_u8(msg, NL80211_MESH_SETUP_AUTH_PROTOCOL, 0x1) || 79736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_AUTH)) 79746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 79756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 79766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((params->flags & WPA_DRIVER_MESH_FLAG_AMPE) && 79776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_AMPE)) 79786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 79796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM) && 79806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, NL80211_MESH_SETUP_USERSPACE_MPM)) 79816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 79826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, container); 7983e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 79846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG); 79856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!container) 79866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 7987e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 79886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(params->conf.flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) && 79896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 0)) 79906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 79916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if ((params->conf.flags & WPA_DRIVER_MESH_FLAG_DRIVER_MPM) && 79926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS, 79936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt params->max_peer_links)) 79946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 79952f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 79962f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt /* 79972f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because 79982f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt * the timer could disconnect stations even in that case. 79992f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt */ 80007f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT, 80017f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt params->conf.peer_link_timeout)) { 80022f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT"); 80032f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt goto fail; 80042f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 80052f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 80066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, container); 8007e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 8008e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 80096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = NULL; 8010e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt if (ret) { 80116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)", 8012e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt ret, strerror(-ret)); 80136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto fail; 8014e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt } 80156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = 0; 8016ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt bss->freq = params->freq.freq; 80176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully"); 8018e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 80196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtfail: 8020e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt nlmsg_free(msg); 8021e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt return ret; 8022e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt} 8023e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 8024e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt 80257f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic int 80267f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtwpa_driver_nl80211_join_mesh(void *priv, 80277f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct wpa_driver_mesh_join_params *params) 80287f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt{ 80297f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct i802_bss *bss = priv; 80307f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt int ret, timeout; 80317f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 80327f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt timeout = params->conf.peer_link_timeout; 80337f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 80347f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt /* Disable kernel inactivity timer */ 80357f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM) 80367f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt params->conf.peer_link_timeout = 0; 80377f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 80387f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = nl80211_join_mesh(bss, params); 80397f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (ret == -EINVAL && params->conf.peer_link_timeout == 0) { 80407f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 80417f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "nl80211: Mesh join retry for peer_link_timeout"); 80427f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt /* 80437f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * Old kernel does not support setting 80447f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * NL80211_MESHCONF_PLINK_TIMEOUT to zero, so set 60 seconds 80457f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * into future from peer_link_timeout. 80467f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt */ 80477f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt params->conf.peer_link_timeout = timeout + 60; 80487f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = nl80211_join_mesh(priv, params); 80497f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 80507f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 80517f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt params->conf.peer_link_timeout = timeout; 80527f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return ret; 80537f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt} 80547f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 80557f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 80566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_nl80211_leave_mesh(void *priv) 8057a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt{ 80586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 80596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 80606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 80616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 8062a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 80636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex); 80646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH); 80656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 80666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 80676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)", 80686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret, strerror(-ret)); 80696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 80706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 80716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: mesh leave request send successfully"); 8072a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt } 8073a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 80746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (wpa_driver_nl80211_set_mode(drv->first_bss, 80756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt NL80211_IFTYPE_STATION)) { 80766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, 80776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Failed to set interface into station mode"); 80786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 80796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 8080a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt} 8081a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 80826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_MESH */ 8083a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 80846c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 80856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_br_add_ip_neigh(void *priv, u8 version, 80866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ipaddr, int prefixlen, 80876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *addr) 8088a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt{ 80896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_LIBNL3_ROUTE 80906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct i802_bss *bss = priv; 80916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 80926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct rtnl_neigh *rn; 80936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_addr *nl_ipaddr = NULL; 80946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_addr *nl_lladdr = NULL; 80956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int family, addrsize; 80966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int res; 8097a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 80986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!ipaddr || prefixlen == 0 || !addr) 80996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 8100a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 81016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->br_ifindex == 0) { 81026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 81036c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: bridge must be set before adding an ip neigh to it"); 81046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 81056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8106a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 81076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->rtnl_sk) { 81086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 81096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: nl_sock for NETLINK_ROUTE is not initialized"); 81106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 81116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8112a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 81136c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (version == 4) { 81146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt family = AF_INET; 81156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt addrsize = 4; 81166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (version == 6) { 81176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt family = AF_INET6; 81186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt addrsize = 16; 81196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 81206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 8121a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt } 8122a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 81236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rn = rtnl_neigh_alloc(); 81246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (rn == NULL) 81256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOMEM; 81266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 81276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* set the destination ip address for neigh */ 81286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize); 81296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl_ipaddr == NULL) { 81306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed"); 81316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = -ENOMEM; 81326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto errout; 81336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 81346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_addr_set_prefixlen(nl_ipaddr, prefixlen); 81356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = rtnl_neigh_set_dst(rn, nl_ipaddr); 81366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res) { 81376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 81386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: neigh set destination addr failed"); 81396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto errout; 8140a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt } 8141a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 81426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* set the corresponding lladdr for neigh */ 81436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_lladdr = nl_addr_build(AF_BRIDGE, (u8 *) addr, ETH_ALEN); 81446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl_lladdr == NULL) { 81456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: neigh set lladdr failed"); 81466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = -ENOMEM; 81476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto errout; 81486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 81496c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rtnl_neigh_set_lladdr(rn, nl_lladdr); 81506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 81516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rtnl_neigh_set_ifindex(rn, bss->br_ifindex); 81526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rtnl_neigh_set_state(rn, NUD_PERMANENT); 81536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 81546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = rtnl_neigh_add(drv->rtnl_sk, rn, NLM_F_CREATE); 81556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res) { 81566c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 81576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Adding bridge ip neigh failed: %s", 81586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt strerror(errno)); 81596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 81606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidterrout: 81616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl_lladdr) 81626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_addr_put(nl_lladdr); 81636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl_ipaddr) 81646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_addr_put(nl_ipaddr); 81656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (rn) 81666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rtnl_neigh_put(rn); 81676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return res; 81686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#else /* CONFIG_LIBNL3_ROUTE */ 81696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 81706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_LIBNL3_ROUTE */ 8171a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt} 8172a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 8173a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 81746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_br_delete_ip_neigh(void *priv, u8 version, 81756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const u8 *ipaddr) 8176a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt{ 81776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_LIBNL3_ROUTE 8178a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt struct i802_bss *bss = priv; 8179a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 81806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct rtnl_neigh *rn; 81816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_addr *nl_ipaddr; 81826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int family, addrsize; 81836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int res; 8184a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 81856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!ipaddr) 81866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 8187a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 81886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (version == 4) { 81896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt family = AF_INET; 81906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt addrsize = 4; 81916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else if (version == 6) { 81926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt family = AF_INET6; 81936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt addrsize = 16; 81946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } else { 81956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 81966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 81976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 81986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (bss->br_ifindex == 0) { 81996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 82006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: bridge must be set to delete an ip neigh"); 82016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 8202a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt } 8203a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 82046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!drv->rtnl_sk) { 82056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 82066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: nl_sock for NETLINK_ROUTE is not initialized"); 82076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 82086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8209a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 82106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rn = rtnl_neigh_alloc(); 82116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (rn == NULL) 82126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOMEM; 8213a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 82146c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt /* set the destination ip address for neigh */ 82156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize); 82166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl_ipaddr == NULL) { 82176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed"); 82186c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = -ENOMEM; 82196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto errout; 82206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 82216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = rtnl_neigh_set_dst(rn, nl_ipaddr); 82226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res) { 82236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 82246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: neigh set destination addr failed"); 82256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt goto errout; 82266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 82276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 82286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rtnl_neigh_set_ifindex(rn, bss->br_ifindex); 82296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 82306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt res = rtnl_neigh_delete(drv->rtnl_sk, rn, 0); 82316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (res) { 82326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 82336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Deleting bridge ip neigh failed: %s", 82346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt strerror(errno)); 82356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 82366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidterrout: 82376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (nl_ipaddr) 82386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nl_addr_put(nl_ipaddr); 82396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (rn) 82406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt rtnl_neigh_put(rn); 82416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return res; 82426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#else /* CONFIG_LIBNL3_ROUTE */ 82436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 82446c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_LIBNL3_ROUTE */ 8245a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt} 8246a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 8247a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 82486c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int linux_write_system_file(const char *path, unsigned int val) 8249fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 82506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char buf[50]; 82516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int fd, len; 8252fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 82536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt len = os_snprintf(buf, sizeof(buf), "%u\n", val); 82546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (os_snprintf_error(sizeof(buf), len)) 82556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 8256fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 82576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt fd = open(path, O_WRONLY); 82586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (fd < 0) 82596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 8260fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 82616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (write(fd, buf, len) < 0) { 82626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_DEBUG, 82636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Failed to write Linux system file: %s with the value of %d", 82646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt path, val); 82656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt close(fd); 82666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 82676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 82686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt close(fd); 8269fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 82706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 82716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8272fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 8273fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 82746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic const char * drv_br_port_attr_str(enum drv_br_port_attr attr) 82756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 82766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (attr) { 82776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case DRV_BR_PORT_ATTR_PROXYARP: 82784dd28dc25895165566a1c8a9cac7bcd755ff8fe3Dmitry Shmidt return "proxyarp_wifi"; 82796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case DRV_BR_PORT_ATTR_HAIRPIN_MODE: 82806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "hairpin_mode"; 82816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 82826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 82836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return NULL; 8284fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 8285fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 8286fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 82876c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_br_port_set_attr(void *priv, enum drv_br_port_attr attr, 82886c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int val) 8289b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt{ 8290b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt struct i802_bss *bss = priv; 82916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char path[128]; 82926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const char *attr_txt; 8293b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 82946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt attr_txt = drv_br_port_attr_str(attr); 82956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (attr_txt == NULL) 82966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 8297b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 82986c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_snprintf(path, sizeof(path), "/sys/class/net/%s/brport/%s", 82996c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt bss->ifname, attr_txt); 8300b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 83016c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_write_system_file(path, val)) 83026c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 8303b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 83046c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 83056c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8306b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 8307b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 83086c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic const char * drv_br_net_param_str(enum drv_br_net_param param) 83096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 83106c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (param) { 83116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case DRV_BR_NET_PARAM_GARP_ACCEPT: 83126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return "arp_accept"; 83138347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt default: 83148347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt return NULL; 83156c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8316b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt} 8317b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 8318b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt 83196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_br_set_net_param(void *priv, enum drv_br_net_param param, 83206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int val) 8321661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{ 8322661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct i802_bss *bss = priv; 83236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt char path[128]; 83246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt const char *param_txt; 83256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ip_version = 4; 8326661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83278347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt if (param == DRV_BR_MULTICAST_SNOOPING) { 83288347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt os_snprintf(path, sizeof(path), 83298347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt "/sys/devices/virtual/net/%s/bridge/multicast_snooping", 83308347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt bss->brname); 83318347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt goto set_val; 83328347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt } 83338347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidt 83346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt param_txt = drv_br_net_param_str(param); 83356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (param_txt == NULL) 83366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 8337661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83386c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (param) { 83396c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case DRV_BR_NET_PARAM_GARP_ACCEPT: 83406c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ip_version = 4; 83416c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 83426c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 83436c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -EINVAL; 8344661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 8345661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt os_snprintf(path, sizeof(path), "/proc/sys/net/ipv%d/conf/%s/%s", 83476c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ip_version, bss->brname, param_txt); 8348661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83498347444e0bfb85e4550817fc99903f38ce8f5bccDmitry Shmidtset_val: 83506c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (linux_write_system_file(path, val)) 83516c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 8352661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83536c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 83546c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt} 8355661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 8356661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83576c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int hw_mode_to_qca_acs(enum hostapd_hw_mode hw_mode) 83586c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt{ 83596c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (hw_mode) { 83606c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HOSTAPD_MODE_IEEE80211B: 83616c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return QCA_ACS_MODE_IEEE80211B; 83626c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HOSTAPD_MODE_IEEE80211G: 83636c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return QCA_ACS_MODE_IEEE80211G; 83646c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HOSTAPD_MODE_IEEE80211A: 83656c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return QCA_ACS_MODE_IEEE80211A; 83666c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HOSTAPD_MODE_IEEE80211AD: 83676c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return QCA_ACS_MODE_IEEE80211AD; 8368b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt case HOSTAPD_MODE_IEEE80211ANY: 8369b1e52102c211357f585e9ff6d54501e90254326eDmitry Shmidt return QCA_ACS_MODE_IEEE80211ANY; 83706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 83716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -1; 83726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 8373661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt} 8374661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 8375661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int wpa_driver_do_acs(void *priv, struct drv_acs_params *params) 8377661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt{ 8378661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct i802_bss *bss = priv; 8379661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 83806c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nl_msg *msg; 83816c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt struct nlattr *data; 83826c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int ret; 83836c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt int mode; 8384661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83856c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt mode = hw_mode_to_qca_acs(params->hw_mode); 83866c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (mode < 0) 8387661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt return -1; 8388661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 83896c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 83906c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 83916c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 83926c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt QCA_NL80211_VENDOR_SUBCMD_DO_ACS) || 83936c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || 83946c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_u8(msg, QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE, mode) || 83956c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (params->ht_enabled && 83966c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED)) || 83976c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt (params->ht40_enabled && 8398dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED)) || 8399dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt (params->vht_enabled && 8400dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED)) || 8401dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH, 8402dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt params->ch_width) || 8403dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt (params->ch_list_len && 8404dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt nla_put(msg, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST, params->ch_list_len, 8405dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt params->ch_list))) { 84066c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nlmsg_free(msg); 84076c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return -ENOBUFS; 8408661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 84096c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt nla_nest_end(msg, data); 8410661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 8411dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt wpa_printf(MSG_DEBUG, 8412dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d CH_LIST_LEN: %u", 8413dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt params->hw_mode, params->ht_enabled, params->ht40_enabled, 8414dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt params->vht_enabled, params->ch_width, params->ch_list_len); 8415dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt 84166c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 84176c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (ret) { 8418661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt wpa_printf(MSG_DEBUG, 84196c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "nl80211: Failed to invoke driver ACS function: %s", 84206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt strerror(errno)); 8421661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt } 84226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return ret; 8423661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt} 8424661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 8425661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt 8426e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshistatic int nl80211_set_band(void *priv, enum set_band band) 8427e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi{ 8428e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi struct i802_bss *bss = priv; 8429e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi struct wpa_driver_nl80211_data *drv = bss->drv; 8430e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi struct nl_msg *msg; 8431e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi struct nlattr *data; 8432e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi int ret; 8433e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi enum qca_set_band qca_band; 8434e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi 8435e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi if (!drv->setband_vendor_cmd_avail) 8436e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi return -1; 8437e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi 8438e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi switch (band) { 8439e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi case WPA_SETBAND_AUTO: 8440e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi qca_band = QCA_SETBAND_AUTO; 8441e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi break; 8442e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi case WPA_SETBAND_5G: 8443e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi qca_band = QCA_SETBAND_5G; 8444e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi break; 8445e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi case WPA_SETBAND_2G: 8446e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi qca_band = QCA_SETBAND_2G; 8447e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi break; 8448e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi default: 8449e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi return -1; 8450e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi } 8451e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi 8452e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || 8453e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || 8454e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, 8455e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi QCA_NL80211_VENDOR_SUBCMD_SETBAND) || 8456e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || 8457e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, qca_band)) { 8458e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi nlmsg_free(msg); 8459e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi return -ENOBUFS; 8460e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi } 8461e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi nla_nest_end(msg, data); 8462e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi 8463e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi ret = send_and_recv_msgs(drv, msg, NULL, NULL); 8464e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi if (ret) { 8465e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi wpa_printf(MSG_DEBUG, 8466e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi "nl80211: Driver setband function failed: %s", 8467e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi strerror(errno)); 8468e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi } 8469e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi return ret; 8470e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi} 8471e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi 8472e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi 84738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct wpa_driver_ops wpa_driver_nl80211_ops = { 84748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .name = "nl80211", 84758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .desc = "Linux nl80211/cfg80211", 84768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_bssid = wpa_driver_nl80211_get_bssid, 84778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_ssid = wpa_driver_nl80211_get_ssid, 84784b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .set_key = driver_nl80211_set_key, 84794b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .scan2 = driver_nl80211_scan2, 84801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .sched_scan = wpa_driver_nl80211_sched_scan, 84811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan, 84828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_scan_results2 = wpa_driver_nl80211_get_scan_results, 84834b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .deauthenticate = driver_nl80211_deauthenticate, 84844b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .authenticate = driver_nl80211_authenticate, 84858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .associate = wpa_driver_nl80211_associate, 84868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .global_init = nl80211_global_init, 84878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .global_deinit = nl80211_global_deinit, 84888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .init2 = wpa_driver_nl80211_init, 84894b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .deinit = driver_nl80211_deinit, 84908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_capa = wpa_driver_nl80211_get_capa, 84918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_operstate = wpa_driver_nl80211_set_operstate, 84928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_supp_port = wpa_driver_nl80211_set_supp_port, 84938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_country = wpa_driver_nl80211_set_country, 8494cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt .get_country = wpa_driver_nl80211_get_country, 84951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .set_ap = wpa_driver_nl80211_set_ap, 84968bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt .set_acl = wpa_driver_nl80211_set_acl, 84978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .if_add = wpa_driver_nl80211_if_add, 84984b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .if_remove = driver_nl80211_if_remove, 84994b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .send_mlme = driver_nl80211_send_mlme, 85006c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .get_hw_feature_data = nl80211_get_hw_feature_data, 85018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_add = wpa_driver_nl80211_sta_add, 85024b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .sta_remove = driver_nl80211_sta_remove, 85038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol, 85048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_set_flags = wpa_driver_nl80211_sta_set_flags, 85058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .hapd_init = i802_init, 85068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .hapd_deinit = i802_deinit, 850775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .set_wds_sta = i802_set_wds_sta, 85088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_seqnum = i802_get_seqnum, 85098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .flush = i802_flush, 85108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_inact_sec = i802_get_inact_sec, 85118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_clear_stats = i802_sta_clear_stats, 85128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_rts = i802_set_rts, 85138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_frag = i802_set_frag, 85148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_tx_queue_params = i802_set_tx_queue_params, 85154b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .set_sta_vlan = driver_nl80211_set_sta_vlan, 85168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_deauth = i802_sta_deauth, 85178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_disassoc = i802_sta_disassoc, 85184b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .read_sta_data = driver_nl80211_read_sta_data, 85198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_freq = i802_set_freq, 85204b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .send_action = driver_nl80211_send_action, 85218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait, 85228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .remain_on_channel = wpa_driver_nl80211_remain_on_channel, 85238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .cancel_remain_on_channel = 85248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_cancel_remain_on_channel, 85254b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt .probe_req_report = driver_nl80211_probe_req_report, 85268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .deinit_ap = wpa_driver_nl80211_deinit_ap, 852704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli, 85288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .resume = wpa_driver_nl80211_resume, 85298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .signal_monitor = nl80211_signal_monitor, 85308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .signal_poll = nl80211_signal_poll, 85318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .send_frame = nl80211_send_frame, 85328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_param = nl80211_set_param, 85338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_radio_name = nl80211_get_radio_name, 853475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .add_pmkid = nl80211_add_pmkid, 853575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .remove_pmkid = nl80211_remove_pmkid, 853675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .flush_pmkid = nl80211_flush_pmkid, 85371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .set_rekey_info = nl80211_set_rekey_info, 85381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .poll_client = nl80211_poll_client, 85391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .set_p2p_powersave = nl80211_set_p2p_powersave, 8540ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt .start_dfs_cac = nl80211_start_radar_detection, 8541ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt .stop_ap = wpa_driver_nl80211_stop_ap, 85421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TDLS 85431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .send_tdls_mgmt = nl80211_send_tdls_mgmt, 85441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .tdls_oper = nl80211_tdls_oper, 85456c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .tdls_enable_channel_switch = nl80211_tdls_enable_channel_switch, 85466c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .tdls_disable_channel_switch = nl80211_tdls_disable_channel_switch, 85471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TDLS */ 8548700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt .update_ft_ies = wpa_driver_nl80211_update_ft_ies, 854934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt .get_mac_addr = wpa_driver_nl80211_get_macaddr, 8550b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt .get_survey = wpa_driver_nl80211_get_survey, 85515605286c30e1701491bd3af974ae423727750eddDmitry Shmidt .status = wpa_driver_nl80211_status, 8552e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt .switch_channel = nl80211_switch_channel, 85531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID_P2P 85546e933c1e09094a8972ef1e782c57f8b3c55c91d0Dmitry Shmidt .set_noa = wpa_driver_set_p2p_noa, 85551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt .get_noa = wpa_driver_get_p2p_noa, 85566e933c1e09094a8972ef1e782c57f8b3c55c91d0Dmitry Shmidt .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie, 8557292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt#endif /* ANDROID_P2P */ 8558738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt#ifdef ANDROID 85594171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt#ifndef ANDROID_LIB_STUB 8560738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt .driver_cmd = wpa_driver_nl80211_driver_cmd, 85614171258d30a612645aa061cede62233b5c58ca2aDmitry Shmidt#endif /* !ANDROID_LIB_STUB */ 8562292b0c3a742226c295f8db76eaef9e90c90e7513Dmitry Shmidt#endif /* ANDROID */ 8563a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt .vendor_cmd = nl80211_vendor_cmd, 8564fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt .set_qos_map = nl80211_set_qos_map, 8565b58836ed5520bf4b769f76ef7dcb802af8c900b8Dmitry Shmidt .set_wowlan = nl80211_set_wowlan, 8566661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt .roaming = nl80211_roaming, 8567661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt .set_mac_addr = nl80211_set_mac_addr, 85686c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#ifdef CONFIG_MESH 85696c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .init_mesh = wpa_driver_nl80211_init_mesh, 85706c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .join_mesh = wpa_driver_nl80211_join_mesh, 85716c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .leave_mesh = wpa_driver_nl80211_leave_mesh, 85726c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt#endif /* CONFIG_MESH */ 85736c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .br_add_ip_neigh = wpa_driver_br_add_ip_neigh, 85746c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .br_delete_ip_neigh = wpa_driver_br_delete_ip_neigh, 85756c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .br_port_set_attr = wpa_driver_br_port_set_attr, 85766c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .br_set_net_param = wpa_driver_br_set_net_param, 85776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .add_tx_ts = nl80211_add_ts, 85786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .del_tx_ts = nl80211_del_ts, 85796c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt .do_acs = wpa_driver_do_acs, 8580e6ccb16448fd0d5cf080fcb534266797855428d6Ravi Joshi .set_band = nl80211_set_band, 85818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 8582