driver_nl80211.c revision 738a26e9e2087b0d43eba3534535632b27b49947
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Driver interaction with Linux nl80211/cfg80211 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2002-2010, 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 * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/ioctl.h> 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/types.h> 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/stat.h> 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <fcntl.h> 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <net/if.h> 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netlink/genl/genl.h> 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netlink/genl/family.h> 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netlink/genl/ctrl.h> 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <linux/rtnetlink.h> 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netpacket/packet.h> 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <linux/filter.h> 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "nl80211_copy.h" 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/list.h" 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "netlink.h" 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "linux_ioctl.h" 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radiotap.h" 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radiotap_iter.h" 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rfkill.h" 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver.h" 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_LIBNL20 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* libnl 2.0 compatibility code */ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define nl_handle nl_sock 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define nl80211_handle_alloc nl_socket_alloc_cb 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define nl80211_handle_destroy nl_socket_free 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * libnl 1.1 has a bug, it tries to allocate socket numbers densely 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * but when you free a socket again it will mess up its bitmap and 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and use the wrong number the next time it needs a socket ID. 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Therefore, we wrap the handle alloc/destroy and add our own pid 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * accounting. 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic uint32_t port_bitmap[32] = { 0 }; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct nl_handle *nl80211_handle_alloc(void *cb) 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_handle *handle; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uint32_t pid = getpid() & 0x3FFFFF; 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handle = nl_handle_alloc_cb(cb); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 1024; i++) { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (port_bitmap[i / 32] & (1 << (i % 32))) 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt port_bitmap[i / 32] |= 1 << (i % 32); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pid += i << 22; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_socket_set_local_port(handle, pid); 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return handle; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_handle_destroy(struct nl_handle *handle) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uint32_t port = nl_socket_get_local_port(handle); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt port >>= 22; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt port_bitmap[port / 32] &= ~(1 << (port % 32)); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_handle_destroy(handle); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_LIBNL20 */ 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef IFF_LOWER_UP 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef IFF_DORMANT 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IFF_DORMANT 0x20000 /* driver signals dormant */ 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef IF_OPER_DORMANT 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IF_OPER_DORMANT 5 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef IF_OPER_UP 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IF_OPER_UP 6 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct nl80211_global { 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct dl_list interfaces; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct i802_bss { 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *next; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char ifname[IFNAMSIZ + 1]; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char brname[IFNAMSIZ]; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int beacon_set:1; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int added_if_into_bridge:1; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int added_bridge:1; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_driver_nl80211_data { 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_global *global; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct dl_list list; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr[ETH_ALEN]; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char phyname[32]; 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct netlink_data *netlink; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ioctl_sock; /* socket for ioctl() use */ 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex; 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int if_removed; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int if_disabled; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rfkill_data *rfkill; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_capa capa; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int has_capability; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int operstate; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int scan_complete_events; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_handle *nl_handle; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_handle *nl_handle_event; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_handle *nl_handle_preq; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_cache *nl_cache; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_cache *nl_cache_event; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_cache *nl_cache_preq; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_cb *nl_cb; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genl_family *nl80211; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 auth_bssid[ETH_ALEN]; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN]; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int associated; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ssid[32]; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ssid_len; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int nlmode; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ap_scan_as_station; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int assoc_freq; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int monitor_sock; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int monitor_ifidx; 160c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt int no_monitor_iface_capab; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int disable_11b_rates; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int pending_remain_on_chan:1; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 remain_on_chan_cookie; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 send_action_cookie; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int last_mgmt_freq; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_filter *filter_ssids; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_filter_ssids; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss first_bss; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int eapol_sock; /* socket for EAPOL frames */ 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int default_if_indices[16]; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *if_indices; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int num_if_indices; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int last_freq; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int last_freq_ht; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *timeout_ctx); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_mode(void *priv, int mode); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int cmd, u16 reason_code, 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int local_state_change); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_remove_monitor_interface( 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int freq, unsigned int wait, 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t buf_len, u64 *cookie); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_probe_req_report(void *priv, int report); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_if_remove(void *priv, 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_driver_if_type type, 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* HOSTAPD */ 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 217738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt#ifdef ANDROID 218738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidtextern int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, 219738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt size_t buf_len); 220738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt#endif 221738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_freq(void *priv, struct hostapd_freq_params *freq); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, int disabled); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinenstruct nl80211_bss_info_arg { 23087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen struct wpa_driver_nl80211_data *drv; 23187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen struct wpa_scan_results *res; 23287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen unsigned int assoc_freq; 23387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen}; 23487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 23587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinenstatic int bss_info_handler(struct nl_msg *msg, void *arg); 23687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 23787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* nl80211 code */ 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ack_handler(struct nl_msg *msg, void *arg) 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *err = arg; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *err = 0; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_STOP; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int finish_handler(struct nl_msg *msg, void *arg) 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *ret = arg; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ret = 0; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *arg) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *ret = arg; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *ret = err->error; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int no_seq_check(struct nl_msg *msg, void *arg) 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_OK; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int send_and_recv(struct wpa_driver_nl80211_data *drv, 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_handle *nl_handle, struct nl_msg *msg, 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*valid_handler)(struct nl_msg *, void *), 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *valid_data) 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_cb *cb; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err = -ENOMEM; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb = nl_cb_clone(drv->nl_cb); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!cb) 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = nl_send_auto_complete(nl_handle, msg); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err < 0) 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out; 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = 1; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (valid_handler) 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt valid_handler, valid_data); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (err > 0) 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_recvmsgs(nl_handle, cb); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out: 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_put(cb); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return err; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 303738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidtint send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg, 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int (*valid_handler)(struct nl_msg *, void *), 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *valid_data) 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv(drv, drv->nl_handle, msg, valid_handler, 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt valid_data); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct family_data { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *group; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int id; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int family_handler(struct nl_msg *msg, void *arg) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct family_data *res = arg; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[CTRL_ATTR_MAX + 1]; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *mcgrp; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb[CTRL_ATTR_MCAST_GROUPS]) 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp), 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(mcgrp), NULL); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !tb2[CTRL_ATTR_MCAST_GRP_ID] || 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]), 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->group, 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0) 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv, 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *family, const char *group) 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct family_data res = { group, -ENOENT }; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"), 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, 0, CTRL_CMD_GETFAMILY, 0); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family); 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, family_handler, &res); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = res.id; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid) 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->associated) 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(bssid, drv->bssid, ETH_ALEN); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid) 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->associated) 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ssid, drv->ssid, drv->ssid_len); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return drv->ssid_len; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv, 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf, size_t len, int del) 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > sizeof(event.interface_status.ifname)) 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(event.interface_status.ifname) - 1; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(event.interface_status.ifname, buf, len); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED : 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EVENT_INTERFACE_ADDED; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s", 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt del ? "DEL" : "NEW", 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.interface_status.ifname, 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt del ? "removed" : "added"); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) { 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (del) 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_removed = 1; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_removed = 0; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv, 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attrlen, rta_len; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attrlen = len; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = (struct rtattr *) buf; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rta_len = RTA_ALIGN(sizeof(struct rtattr)); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->rta_type == IFLA_IFNAME) { 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(((char *) attr) + rta_len, drv->first_bss.ifname) 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv, 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, u8 *buf, size_t len) 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ifindex == ifindex) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) { 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed " 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface"); 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_finish_drv_init(drv); 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_event_rtm_newlink(void *ctx, 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ifinfomsg *ifi, 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = ctx; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attrlen, rta_len; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 brid = 0; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_driver_nl80211_own_ifindex(drv, ifi->ifi_index, buf, len) && 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !have_ifidx(drv, ifi->ifi_index)) { 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore event for foreign " 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ifindex %d", ifi->ifi_index); 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x " 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s%s%s%s)", 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->operstate, ifi->ifi_flags, 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_UP) ? "[UP]" : "", 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "", 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "", 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : ""); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) { 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface down"); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_disabled = 1; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) { 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface up"); 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_disabled = 0; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Some drivers send the association event before the operup event--in 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this case, lifting operstate in wpa_driver_nl80211_set_operstate() 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * fails. This will hit us when wpa_supplicant does not need to do 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * IEEE 802.1X authentication 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->operstate == 1 && 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP && 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(ifi->ifi_flags & IFF_RUNNING)) 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_send_oper_ifla(drv->netlink, drv->ifindex, 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt -1, IF_OPER_UP); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attrlen = len; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = (struct rtattr *) buf; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rta_len = RTA_ALIGN(sizeof(struct rtattr)); 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->rta_type == IFLA_IFNAME) { 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_event_link( 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((char *) attr) + rta_len, 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->rta_len - rta_len, 0); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (attr->rta_type == IFLA_MASTER) 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brid = nla_get_u32((struct nlattr *) attr); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifi->ifi_family == AF_BRIDGE && brid) { 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* device has been added to bridge */ 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char namebuf[IFNAMSIZ]; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if_indextoname(brid, namebuf); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s", 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brid, namebuf); 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, brid); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_event_rtm_dellink(void *ctx, 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ifinfomsg *ifi, 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = ctx; 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int attrlen, rta_len; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rtattr *attr; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 brid = 0; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attrlen = len; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = (struct rtattr *) buf; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rta_len = RTA_ALIGN(sizeof(struct rtattr)); 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (RTA_OK(attr, attrlen)) { 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (attr->rta_type == IFLA_IFNAME) { 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_event_link( 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ((char *) attr) + rta_len, 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr->rta_len - rta_len, 1); 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (attr->rta_type == IFLA_MASTER) 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brid = nla_get_u32((struct nlattr *) attr); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt attr = RTA_NEXT(attr, attrlen); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifi->ifi_family == AF_BRIDGE && brid) { 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* device has been removed from bridge */ 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char namebuf[IFNAMSIZ]; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if_indextoname(brid, namebuf); 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Remove ifindex %u for bridge " 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s", brid, namebuf); 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt del_ifidx(drv, brid); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_auth(struct wpa_driver_nl80211_data *drv, 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *frame, size_t len) 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ieee80211_mgmt *mgmt; 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = (const struct ieee80211_mgmt *) frame; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 24 + sizeof(mgmt->u.auth)) { 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Too short association event " 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame"); 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN); 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.auth.status_code = le_to_host16(mgmt->u.auth.status_code); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > 24 + sizeof(mgmt->u.auth)) { 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.auth.ies = mgmt->u.auth.variable; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.auth.ies_len = len - 24 - sizeof(mgmt->u.auth); 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinenstatic unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv) 60887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen{ 60987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen struct nl_msg *msg; 61087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen int ret; 61187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen struct nl80211_bss_info_arg arg; 61287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 61387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen os_memset(&arg, 0, sizeof(arg)); 61487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen msg = nlmsg_alloc(); 61587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if (!msg) 61687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen goto nla_put_failure; 61787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 61887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, NLM_F_DUMP, 61987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen NL80211_CMD_GET_SCAN, 0); 62087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 62187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 62287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen arg.drv = drv; 62387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); 62487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen msg = NULL; 62587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if (ret == 0) { 62687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the " 62787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen "associated BSS from scan results: %u MHz", 62887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen arg.assoc_freq); 62987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen return arg.assoc_freq ? arg.assoc_freq : drv->assoc_freq; 63087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen } 63187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " 63287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen "(%s)", ret, strerror(-ret)); 63387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinennla_put_failure: 63487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen nlmsg_free(msg); 63587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen return drv->assoc_freq; 63687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen} 63787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 63887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *frame, size_t len) 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ieee80211_mgmt *mgmt; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status; 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = (const struct ieee80211_mgmt *) frame; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 24 + sizeof(mgmt->u.assoc_resp)) { 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Too short association event " 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame"); 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = le_to_host16(mgmt->u.assoc_resp.status_code); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status != WLAN_STATUS_SUCCESS) { 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_reject.bssid = mgmt->bssid; 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > 24 + sizeof(mgmt->u.assoc_resp)) { 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_reject.resp_ies = 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) mgmt->u.assoc_resp.variable; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_reject.resp_ies_len = 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len - 24 - sizeof(mgmt->u.assoc_resp); 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_reject.status_code = status; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event); 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 1; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > 24 + sizeof(mgmt->u.assoc_resp)) { 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_info.resp_ies_len = 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len - 24 - sizeof(mgmt->u.assoc_resp); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_info.freq = drv->assoc_freq; 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_connect(struct wpa_driver_nl80211_data *drv, 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_commands cmd, struct nlattr *status, 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *addr, struct nlattr *req_ie, 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *resp_ie) 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Avoid reporting two association events that would confuse 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the core code. 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore connect event (cmd=%d) " 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when using userspace SME", cmd); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cmd == NL80211_CMD_CONNECT && 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u16(status) != WLAN_STATUS_SUCCESS) { 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_reject.bssid = nla_data(addr); 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp_ie) { 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_reject.resp_ies = nla_data(resp_ie); 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_reject.resp_ies_len = nla_len(resp_ie); 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_reject.status_code = nla_get_u16(status); 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event); 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 1; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN); 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req_ie) { 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_info.req_ies = nla_data(req_ie); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_info.req_ies_len = nla_len(req_ie); 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp_ie) { 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_info.resp_ies = nla_data(resp_ie); 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.assoc_info.resp_ies_len = nla_len(resp_ie); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 72987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen event.assoc_info.freq = nl80211_get_assoc_freq(drv); 73087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event); 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_timeout_event(struct wpa_driver_nl80211_data *drv, 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_commands cmd, struct nlattr *addr) 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_event_type ev; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nla_len(addr) != ETH_ALEN) 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR, 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cmd, MAC2STR((u8 *) nla_data(addr))); 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cmd == NL80211_CMD_AUTHENTICATE) 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev = EVENT_AUTH_TIMED_OUT; 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (cmd == NL80211_CMD_ASSOCIATE) 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ev = EVENT_ASSOC_TIMED_OUT; 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN); 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, ev, &event); 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv, 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *freq, const u8 *frame, size_t len) 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ieee80211_mgmt *mgmt; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 fc, stype; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = (const struct ieee80211_mgmt *) frame; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 24) { 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Too short action frame"); 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fc = le_to_host16(mgmt->frame_control); 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stype = WLAN_FC_GET_STYPE(fc); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (freq) { 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_action.freq = nla_get_u32(freq); 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->last_mgmt_freq = event.rx_action.freq; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stype == WLAN_FC_STYPE_ACTION) { 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_action.da = mgmt->da; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_action.sa = mgmt->sa; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_action.bssid = mgmt->bssid; 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_action.category = mgmt->u.action.category; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_action.data = &mgmt->u.action.category + 1; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_action.len = frame + len - event.rx_action.data; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event); 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_mgmt.frame = frame; 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_mgmt.frame_len = len; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_action_tx_status(struct wpa_driver_nl80211_data *drv, 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *cookie, const u8 *frame, 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, struct nlattr *ack) 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ieee80211_hdr *hdr; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 fc; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 cookie_val; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!cookie) 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie_val = nla_get_u64(cookie); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Action TX status: cookie=0%llx%s " 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(ack=%d)", 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long long unsigned int) cookie_val, 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie_val == drv->send_action_cookie ? 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (match)" : " (unknown)", ack != NULL); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cookie_val != drv->send_action_cookie) 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (const struct ieee80211_hdr *) frame; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fc = le_to_host16(hdr->frame_control); 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.type = WLAN_FC_GET_TYPE(fc); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.stype = WLAN_FC_GET_STYPE(fc); 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.dst = hdr->addr1; 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.data = frame; 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.data_len = len; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.ack = ack != NULL; 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event); 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv, 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_event_type type, 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *frame, size_t len) 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ieee80211_mgmt *mgmt; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *bssid = NULL; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 reason_code = 0; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = (const struct ieee80211_mgmt *) frame; 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= 24) { 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bssid = mgmt->bssid; 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->associated != 0 && 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 && 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) { 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * We have presumably received this deauth as a 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * response to a clear_state_mismatch() outgoing 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * deauth. Don't let it take us offline! 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Deauth received " 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from Unknown BSSID " MACSTR " -- ignoring", 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(bssid)); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 0; 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: Same offset for Reason Code in both frame subtypes */ 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= 24 + sizeof(mgmt->u.deauth)) 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code = le_to_host16(mgmt->u.deauth.reason_code); 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type == EVENT_DISASSOC) { 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.disassoc_info.addr = bssid; 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.disassoc_info.reason_code = reason_code; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (frame + len > mgmt->u.disassoc.variable) { 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.disassoc_info.ie = mgmt->u.disassoc.variable; 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.disassoc_info.ie_len = frame + len - 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt->u.disassoc.variable; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.deauth_info.addr = bssid; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.deauth_info.reason_code = reason_code; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (frame + len > mgmt->u.deauth.variable) { 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.deauth_info.ie = mgmt->u.deauth.variable; 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.deauth_info.ie_len = frame + len - 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt->u.deauth.variable; 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, type, &event); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv, 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_event_type type, 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *frame, size_t len) 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct ieee80211_mgmt *mgmt; 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 reason_code = 0; 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 24) 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = (const struct ieee80211_mgmt *) frame; 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: Same offset for Reason Code in both frame subtypes */ 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len >= 24 + sizeof(mgmt->u.deauth)) 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code = le_to_host16(mgmt->u.deauth.reason_code); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type == EVENT_UNPROT_DISASSOC) { 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.unprot_disassoc.sa = mgmt->sa; 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.unprot_disassoc.da = mgmt->da; 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.unprot_disassoc.reason_code = reason_code; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.unprot_deauth.sa = mgmt->sa; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.unprot_deauth.da = mgmt->da; 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.unprot_deauth.reason_code = reason_code; 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, type, &event); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event(struct wpa_driver_nl80211_data *drv, 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_commands cmd, struct nlattr *frame, 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *addr, struct nlattr *timed_out, 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *freq, struct nlattr *ack, 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *cookie) 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (timed_out && addr) { 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_timeout_event(drv, cmd, addr); 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (frame == NULL) { 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME event %d without frame " 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data", cmd); 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME event %d", cmd); 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame", 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(frame), nla_len(frame)); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (cmd) { 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_AUTHENTICATE: 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_auth(drv, nla_data(frame), nla_len(frame)); 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_ASSOCIATE: 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_assoc(drv, nla_data(frame), nla_len(frame)); 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_DEAUTHENTICATE: 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_deauth_disassoc(drv, EVENT_DEAUTH, 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(frame), nla_len(frame)); 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_DISASSOCIATE: 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_deauth_disassoc(drv, EVENT_DISASSOC, 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(frame), nla_len(frame)); 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_FRAME: 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_mgmt(drv, freq, nla_data(frame), nla_len(frame)); 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_FRAME_TX_STATUS: 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_action_tx_status(drv, cookie, nla_data(frame), 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(frame), ack); 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_UNPROT_DEAUTHENTICATE: 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH, 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(frame), nla_len(frame)); 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_UNPROT_DISASSOCIATE: 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC, 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(frame), nla_len(frame)); 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_michael_mic_failure(struct wpa_driver_nl80211_data *drv, 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[]) 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure"); 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_MAC]) { 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: Source MAC address", 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(tb[NL80211_ATTR_MAC]), 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(tb[NL80211_ATTR_MAC])); 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]); 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_KEY_SEQ]) { 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: TSC", 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(tb[NL80211_ATTR_KEY_SEQ]), 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(tb[NL80211_ATTR_KEY_SEQ])); 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_KEY_TYPE]) { 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_key_type key_type = 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]); 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Key Type %d", key_type); 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_type == NL80211_KEYTYPE_PAIRWISE) 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.michael_mic_failure.unicast = 1; 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.michael_mic_failure.unicast = 1; 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_KEY_IDX]) { 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]); 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Key Id %d", key_id); 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, &data); 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv, 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[]) 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_MAC] == NULL) { 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined " 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "event"); 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN); 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 1; 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined", 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(drv->bssid)); 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv, 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cancel_event, struct nlattr *tb[]) 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int freq, chan_type, duration; 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 cookie; 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_WIPHY_FREQ]) 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]); 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq = 0; 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chan_type = 0; 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_DURATION]) 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt duration = nla_get_u32(tb[NL80211_ATTR_DURATION]); 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt duration = 0; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_COOKIE]) 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie = 0; 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel event (cancel=%d " 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))", 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cancel_event, freq, chan_type, duration, 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long long unsigned int) cookie, 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie == drv->remain_on_chan_cookie ? "match" : "unknown"); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cookie != drv->remain_on_chan_cookie) 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* not for us */ 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->pending_remain_on_chan = !cancel_event; 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.remain_on_channel.freq = freq; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.remain_on_channel.duration = duration; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, cancel_event ? 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EVENT_CANCEL_REMAIN_ON_CHANNEL : 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EVENT_REMAIN_ON_CHANNEL, &data); 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted, 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[]) 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *nl; 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rem; 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct scan_info *info; 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MAX_REPORT_FREQS 50 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int freqs[MAX_REPORT_FREQS]; 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int num_freqs = 0; 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info = &event.scan_info; 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->aborted = aborted; 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_SCAN_SSIDS]) { 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) { 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_ssid *s = 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &info->ssids[info->num_ssids]; 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s->ssid = nla_data(nl); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt s->ssid_len = nla_len(nl); 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->num_ssids++; 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (info->num_ssids == WPAS_MAX_SCAN_SSIDS) 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) { 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem) 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freqs[num_freqs] = nla_get_u32(nl); 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_freqs++; 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (num_freqs == MAX_REPORT_FREQS - 1) 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->freqs = freqs; 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->num_freqs = num_freqs; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event); 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int get_link_signal(struct nl_msg *msg, void *arg) 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1]; 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = { 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 }, 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1]; 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = { 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 }, 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 }, 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG }, 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_signal_info *sig_change = arg; 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb[NL80211_ATTR_STA_INFO] || 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse_nested(sinfo, NL80211_STA_INFO_MAX, 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_STA_INFO], policy)) 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sinfo[NL80211_STA_INFO_SIGNAL]) 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig_change->current_signal = 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]); 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sinfo[NL80211_STA_INFO_TX_BITRATE]) { 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sinfo[NL80211_STA_INFO_TX_BITRATE], 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate_policy)) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig_change->current_txrate = 0; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rinfo[NL80211_RATE_INFO_BITRATE]) { 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig_change->current_txrate = 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u16(rinfo[ 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_RATE_INFO_BITRATE]) * 100; 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv, 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_signal_info *sig) 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig->current_signal = -9999; 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig->current_txrate = 0; 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_GET_STATION, 0); 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid); 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, get_link_signal, sig); 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int get_link_noise(struct nl_msg *msg, void *arg) 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1]; 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = { 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 }, 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 }, 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_signal_info *sig_change = arg; 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb[NL80211_ATTR_SURVEY_INFO]) { 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: survey data missing!"); 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX, 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_SURVEY_INFO], 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt survey_policy)) { 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested " 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "attributes!"); 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) != 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig_change->frequency) 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sinfo[NL80211_SURVEY_INFO_NOISE]) 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig_change->current_noise = 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]); 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv, 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_signal_info *sig_change) 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig_change->current_noise = 9999; 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig_change->frequency = drv->assoc_freq; 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLM_F_DUMP, NL80211_CMD_GET_SURVEY, 0); 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, get_link_noise, sig_change); 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[]) 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 }, 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 }, 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_cqm_rssi_threshold_event event; 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data ed; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_signal_info sig; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_CQM] == NULL || 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM], 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cqm_policy)) { 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid CQM event"); 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ed, 0, sizeof(ed)); 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) { 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb[NL80211_ATTR_MAC]) 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]), 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_ALEN); 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed); 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL) 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]); 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) { 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor " 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "event: RSSI high"); 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ed.signal_change.above_threshold = 1; 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) { 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor " 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "event: RSSI low"); 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ed.signal_change.above_threshold = 0; 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = nl80211_get_link_signal(drv, &sig); 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 0) { 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ed.signal_change.current_signal = sig.current_signal; 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ed.signal_change.current_txrate = sig.current_txrate; 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d", 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig.current_signal, sig.current_txrate); 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = nl80211_get_link_noise(drv, &sig); 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 0) { 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ed.signal_change.current_noise = sig.current_noise; 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm", 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sig.current_noise); 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed); 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv, 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr **tb) 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *addr; 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_MAC] == NULL) 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = nla_data(tb[NL80211_ATTR_MAC]); 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr)); 1334c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 1335c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_AP && 1336c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt drv->no_monitor_iface_capab) { 1337c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt u8 *ies = NULL; 1338c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt size_t ies_len = 0; 1339c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (tb[NL80211_ATTR_IE]) { 1340c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt ies = nla_data(tb[NL80211_ATTR_IE]); 1341c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt ies_len = nla_len(tb[NL80211_ATTR_IE]); 1342c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt } 1343c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: Assoc Req IEs", ies, ies_len); 1344c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt drv_event_assoc(drv->ctx, addr, ies, ies_len, 0); 1345c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt return; 1346c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt } 1347c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode != NL80211_IFTYPE_ADHOC) 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN); 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data); 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv, 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr **tb) 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *addr; 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_MAC] == NULL) 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr = nla_data(tb[NL80211_ATTR_MAC]); 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR, 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr)); 1368c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 1369c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_AP && 1370c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt drv->no_monitor_iface_capab) { 1371c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt drv_event_disassoc(drv->ctx, addr); 1372c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt return; 1373c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt } 1374c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode != NL80211_IFTYPE_ADHOC) 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN); 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data); 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int process_event(struct nl_msg *msg, void *arg) 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = arg; 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data data; 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_IFINDEX]) { 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) { 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)" 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " for foreign interface (ifindex %d)", 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnlh->cmd, ifindex); 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ap_scan_as_station && 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS || 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) { 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_set_mode(&drv->first_bss, 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_MODE_AP); 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ap_scan_as_station = 0; 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (gnlh->cmd) { 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_TRIGGER_SCAN: 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan trigger"); 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_NEW_SCAN_RESULTS: 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: New scan results available"); 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->scan_complete_events = 1; 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ctx); 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_scan_event(drv, 0, tb); 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_SCAN_ABORTED: 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan aborted"); 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Need to indicate that scan results are available in order 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not to make wpa_supplicant stop its scanning. 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ctx); 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_scan_event(drv, 1, tb); 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_AUTHENTICATE: 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_ASSOCIATE: 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_DEAUTHENTICATE: 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_DISASSOCIATE: 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_FRAME: 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_FRAME_TX_STATUS: 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_UNPROT_DEAUTHENTICATE: 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_UNPROT_DISASSOCIATE: 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME], 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT], 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK], 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_COOKIE]); 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_CONNECT: 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_ROAM: 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_connect(drv, gnlh->cmd, 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_STATUS_CODE], 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_MAC], 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_REQ_IE], 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_RESP_IE]); 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_DISCONNECT: 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Avoid reporting two disassociation events that could 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * confuse the core code. 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect " 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "event when using userspace SME"); 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 0; 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&data, 0, sizeof(data)); 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_REASON_CODE]) 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.disassoc_info.reason_code = 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u16(tb[NL80211_ATTR_REASON_CODE]); 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data); 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_MICHAEL_MIC_FAILURE: 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_michael_mic_failure(drv, tb); 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_JOIN_IBSS: 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_join_ibss(drv, tb); 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_REMAIN_ON_CHANNEL: 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_remain_on_channel(drv, 0, tb); 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlme_event_remain_on_channel(drv, 1, tb); 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_NOTIFY_CQM: 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_cqm_event(drv, tb); 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_REG_CHANGE: 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change"); 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_REG_BEACON_HINT: 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint"); 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_NEW_STATION: 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_new_station_event(drv, tb); 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_CMD_DEL_STATION: 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_del_station_event(drv, tb); 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event " 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(cmd=%d)", gnlh->cmd); 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx, 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *handle) 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_cb *cb; 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = eloop_ctx; 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Event message available"); 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb = nl_cb_clone(drv->nl_cb); 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!cb) 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv); 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_recvmsgs(handle, cb); 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_put(cb); 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: driver_nl80211 private data 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @alpha2_arg: country to which to switch to 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This asks nl80211 to set the regulatory domain for given 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * country ISO / IEC alpha2. 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg) 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char alpha2[3]; 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alpha2[0] = alpha2_arg[0]; 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alpha2[1] = alpha2_arg[1]; 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alpha2[2] = '\0'; 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_REQ_SET_REG, 0); 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2); 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_and_recv_msgs(drv, msg, NULL, NULL)) 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -EINVAL; 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -EINVAL; 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wiphy_info_data { 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int max_scan_ssids; 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ap_supported; 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int p2p_supported; 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auth_supported; 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int connect_supported; 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int offchan_tx_supported; 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int max_remain_on_chan; 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wiphy_info_handler(struct nl_msg *msg, void *arg) 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wiphy_info_data *info = arg; 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int p2p_go_supported = 0, p2p_client_supported = 0; 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]) 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->max_scan_ssids = 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]); 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) { 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *nl_mode; 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_mode, 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) { 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (nla_type(nl_mode)) { 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_IFTYPE_AP: 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->ap_supported = 1; 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_IFTYPE_P2P_GO: 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_go_supported = 1; 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_IFTYPE_P2P_CLIENT: 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt p2p_client_supported = 1; 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->p2p_supported = p2p_go_supported && p2p_client_supported; 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) { 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *nl_cmd; 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_cmd, 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 cmd = nla_get_u32(nl_cmd); 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cmd == NL80211_CMD_AUTHENTICATE) 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->auth_supported = 1; 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (cmd == NL80211_CMD_CONNECT) 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->connect_supported = 1; 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->offchan_tx_supported = 1; 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]) 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->max_remain_on_chan = 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]); 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv, 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wiphy_info_data *info) 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(info, 0, sizeof(*info)); 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* default to 5000 since early versions of mac80211 don't set it */ 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt info->max_remain_on_chan = 5000; 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_GET_WIPHY, 0); 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->first_bss.ifindex); 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info) == 0) 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wiphy_info_data info; 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_get_info(drv, &info)) 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->has_capability = 1; 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */ 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 | 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_ENC_WEP104 | 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_ENC_TKIP | 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_ENC_CCMP; 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.auth = WPA_DRIVER_AUTH_OPEN | 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_AUTH_SHARED | 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_AUTH_LEAP; 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.max_scan_ssids = info.max_scan_ssids; 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (info.ap_supported) 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_AP; 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (info.auth_supported) 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_SME; 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (!info.connect_supported) { 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Driver does not support " 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication/association or connect commands"); 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (info.offchan_tx_supported) { 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Using driver-based " 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "off-channel TX"); 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX; 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES; 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE; 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (info.p2p_supported) 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE; 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.max_remain_on_chan = info.max_remain_on_chan; 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv) 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initialize generic netlink and nl80211 */ 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_cb == NULL) { 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "callbacks"); 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err1; 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_handle = nl80211_handle_alloc(drv->nl_cb); 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_handle == NULL) { 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "callbacks"); 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err2; 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_handle_event = nl80211_handle_alloc(drv->nl_cb); 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_handle_event == NULL) { 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink " 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "callbacks (event)"); 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err2b; 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (genl_connect(drv->nl_handle)) { 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink"); 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err3; 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (genl_connect(drv->nl_handle_event)) { 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic " 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink (event)"); 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err3; 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_LIBNL20 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (genl_ctrl_alloc_cache(drv->nl_handle, &drv->nl_cache) < 0) { 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink cache"); 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err3; 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (genl_ctrl_alloc_cache(drv->nl_handle_event, &drv->nl_cache_event) < 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink cache (event)"); 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err3b; 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_LIBNL20 */ 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle); 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_cache == NULL) { 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink cache"); 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err3; 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_cache_event = genl_ctrl_alloc_cache(drv->nl_handle_event); 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_cache_event == NULL) { 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink cache (event)"); 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err3b; 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_LIBNL20 */ 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211"); 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl80211 == NULL) { 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not " 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found"); 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err4; 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl_get_multicast_id(drv, "nl80211", "scan"); 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret >= 0) 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl_socket_add_membership(drv->nl_handle_event, ret); 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "membership for scan events: %d (%s)", 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret, strerror(-ret)); 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err4; 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl_get_multicast_id(drv, "nl80211", "mlme"); 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret >= 0) 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl_socket_add_membership(drv->nl_handle_event, ret); 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Could not add multicast " 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "membership for mlme events: %d (%s)", 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret, strerror(-ret)); 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto err4; 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl_get_multicast_id(drv, "nl80211", "regulatory"); 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret >= 0) 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl_socket_add_membership(drv->nl_handle_event, ret); 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast " 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "membership for regulatory events: %d (%s)", 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret, strerror(-ret)); 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Continue without regulatory events */ 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event), 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_event_receive, drv, 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_handle_event); 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr4: 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cache_free(drv->nl_cache_event); 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr3b: 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cache_free(drv->nl_cache); 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr3: 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_handle_destroy(drv->nl_handle_event); 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr2b: 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_handle_destroy(drv->nl_handle); 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr2: 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_put(drv->nl_cb); 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterr1: 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_rfkill_blocked(void *ctx) 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked"); 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This may be for any interface; use ifdown event to disable 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * interface. 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_rfkill_unblocked(void *ctx) 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = ctx; 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked"); 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, drv->first_bss.ifname, 1)) { 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP " 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "after rfkill unblock"); 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* rtnetlink ifup handler will report interface as enabled */ 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv) 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find phy (radio) to which this interface belongs */ 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[90], *pos; 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int f, rv; 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->phyname[0] = '\0'; 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name", 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->first_bss.ifname); 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f = open(buf, O_RDONLY); 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (f < 0) { 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not open file %s: %s", 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, strerror(errno)); 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rv = read(f, drv->phyname, sizeof(drv->phyname) - 1); 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(f); 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rv < 0) { 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Could not read file %s: %s", 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, strerror(errno)); 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->phyname[rv] = '\0'; 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(drv->phyname, '\n'); 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s", 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->first_bss.ifname, drv->phyname); 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_nl80211_init - Initialize nl80211 driver interface 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: context to be used when calling wpa_supplicant functions, 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * e.g., wpa_supplicant_event() 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ifname: interface name, e.g., wlan0 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @global_priv: private driver global data from global_init() 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to private data, %NULL on failure 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * wpa_driver_nl80211_init(void *ctx, const char *ifname, 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *global_priv) 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct netlink_config *cfg; 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rfkill_config *rcfg; 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss; 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv = os_zalloc(sizeof(*drv)); 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv == NULL) 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->global = global_priv; 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ctx = ctx; 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss = &drv->first_bss; 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->drv = drv; 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname)); 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->monitor_ifidx = -1; 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->monitor_sock = -1; 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ioctl_sock = -1; 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_init_nl(drv)) { 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv); 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_get_phy_name(drv); 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ioctl_sock < 0) { 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket(PF_INET,SOCK_DGRAM)"); 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg = os_zalloc(sizeof(*cfg)); 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cfg == NULL) 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg->ctx = drv; 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink; 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink; 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->netlink = netlink_init(cfg); 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->netlink == NULL) { 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cfg); 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rcfg = os_zalloc(sizeof(*rcfg)); 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rcfg == NULL) 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rcfg->ctx = drv; 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname)); 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked; 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked; 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->rfkill = rfkill_init(rcfg); 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->rfkill == NULL) { 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available"); 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rcfg); 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_finish_drv_init(drv)) 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->global) 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_add(&drv->global->interfaces, &drv->list); 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return bss; 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rfkill_deinit(drv->rfkill); 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_deinit(drv->netlink); 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ioctl_sock >= 0) 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(drv->ioctl_sock); 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genl_family_put(drv->nl80211); 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cache_free(drv->nl_cache); 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_handle_destroy(drv->nl_handle); 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_put(drv->nl_cb); 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event)); 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv); 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_register_frame(struct wpa_driver_nl80211_data *drv, 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_handle *nl_handle, 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 type, const u8 *match, size_t match_len) 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_REGISTER_ACTION, 0); 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type); 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match); 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv(drv, nl_handle, msg, NULL, NULL); 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Register frame command " 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed (type=%u): ret=%d (%s)", 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type, ret, strerror(-ret)); 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match", 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt match, match_len); 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_register_action_frame(struct wpa_driver_nl80211_data *drv, 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *match, size_t match_len) 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return nl80211_register_frame(drv, drv->nl_handle_event, 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type, match, match_len); 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_register_action_frames(struct wpa_driver_nl80211_data *drv) 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GAS Initial Request */ 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0a", 2) < 0) 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GAS Initial Response */ 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0b", 2) < 0) 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GAS Comeback Request */ 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0c", 2) < 0) 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* GAS Comeback Response */ 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0d", 2) < 0) 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* P2P Public Action */ 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frame(drv, 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) "\x04\x09\x50\x6f\x9a\x09", 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6) < 0) 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* P2P Action */ 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frame(drv, 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) "\x7f\x50\x6f\x9a\x09", 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5) < 0) 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SA Query Response */ 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frame(drv, (u8 *) "\x08\x01", 2) < 0) 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FT Action frames */ 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frame(drv, (u8 *) "\x06", 1) < 0) 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT | 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx) 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL); 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv) 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = &drv->first_bss; 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int send_rfkill_event = 0; 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifindex = if_nametoindex(bss->ifname); 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->first_bss.ifindex = drv->ifindex; 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef HOSTAPD 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0) { 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to " 20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "use managed mode"); 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) { 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rfkill_is_blocked(drv->rfkill)) { 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable " 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface '%s' due to rfkill", 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->ifname); 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_disabled = 1; 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_rfkill_event = 1; 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Could not set " 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface '%s' UP", bss->ifname); 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_send_oper_ifla(drv->netlink, drv->ifindex, 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1, IF_OPER_DORMANT); 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_capa(drv)) 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, drv->addr)) 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_action_frames(drv) < 0) { 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action " 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "frame processing - ignore for now"); 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Older kernel versions did not support this, so ignore the 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * error for now. Some functionality may not be available 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * because of this. 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_rfkill_event) { 21278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill, 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, drv->ctx); 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv) 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_DEL_BEACON, 0); 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init() 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Shut down driver interface and processing of driver events. Free 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * private data buffer if one was allocated in wpa_driver_nl80211_init(). 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_deinit(void *priv) 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_handle_preq) 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_probe_req_report(bss, 0); 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss->added_if_into_bridge) { 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname) 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to remove " 21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface %s from bridge %s: %s", 21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->ifname, bss->brname, strerror(errno)); 21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss->added_bridge) { 21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_del(drv->ioctl_sock, bss->brname) < 0) 21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to remove " 21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bridge %s: %s", 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->brname, strerror(errno)); 21798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_monitor_interface(drv); 21828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_AP) 21848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_del_beacon(drv); 21858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 21878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->last_freq_ht) { 21888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Clear HT flags from the driver */ 21898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_freq_params freq; 21908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&freq, 0, sizeof(freq)); 21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq.freq = drv->last_freq; 21928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i802_set_freq(priv, &freq); 21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->eapol_sock >= 0) { 21968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(drv->eapol_sock); 21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(drv->eapol_sock); 21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->if_indices != drv->default_if_indices) 22018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->if_indices); 22028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->disable_11b_rates) 22058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_disable_11b_rates(drv, drv->ifindex, 0); 22068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP); 22088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_deinit(drv->netlink); 22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rfkill_deinit(drv->rfkill); 22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); 22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (void) linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0); 22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA); 22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ioctl_sock >= 0) 22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(drv->ioctl_sock); 22188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event)); 22208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genl_family_put(drv->nl80211); 22218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cache_free(drv->nl_cache); 22228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cache_free(drv->nl_cache_event); 22238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_handle_destroy(drv->nl_handle); 22248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_handle_destroy(drv->nl_handle_event); 22258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_put(drv->nl_cb); 22268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->filter_ssids); 22288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->global) 22308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_del(&drv->list); 22318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv); 22338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion 22388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eloop_ctx: Driver private data 22398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init() 22408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 22418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used as registered timeout when starting a scan to 22428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generate a scan completed event if the driver does not report this. 22438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) 22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = eloop_ctx; 22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ap_scan_as_station) { 22488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_set_mode(&drv->first_bss, 22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_MODE_AP); 22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ap_scan_as_station = 0; 22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); 22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); 22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_nl80211_scan - Request the driver to initiate scan 22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private driver data from wpa_driver_nl80211_init() 22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @params: Scan parameters 22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_scan(void *priv, 22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_params *params) 22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 22678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0, timeout; 22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg, *ssids, *freqs; 22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 22718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 22738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssids = nlmsg_alloc(); 22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freqs = nlmsg_alloc(); 22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg || !ssids || !freqs) { 22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(ssids); 22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(freqs); 22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv->filter_ssids); 22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->filter_ssids = params->filter_ssids; 22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->filter_ssids = NULL; 22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->num_filter_ssids = params->num_filter_ssids; 22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_TRIGGER_SCAN, 0); 22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 22928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < params->num_ssids; i++) { 22938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID", 22948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssids[i].ssid, 22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssids[i].ssid_len); 22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(ssids, i + 1, params->ssids[i].ssid_len, 22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssids[i].ssid); 22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->num_ssids) 23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); 23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->extra_ies) { 23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan extra IEs", 23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->extra_ies, params->extra_ies_len); 23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len, 23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->extra_ies); 23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->freqs) { 23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; params->freqs[i]; i++) { 23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u " 23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MHz", params->freqs[i]); 23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(freqs, i + 1, params->freqs[i]); 23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs); 23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " 23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_AP) { 23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mac80211 does not allow scan requests in AP mode, so 23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * try to do this in station mode. 23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_set_mode(bss, 23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_MODE_INFRA)) 23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_scan(drv, params)) { 23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_set_mode(bss, 23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_MODE_AP); 23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Restore AP mode when processing scan results */ 23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ap_scan_as_station = 1; 23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* HOSTAPD */ 23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Not all drivers generate "scan completed" wireless event, so try to 23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * read results after a timeout. */ 23518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout = 10; 23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->scan_complete_events) { 23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The driver seems to deliver events to notify when scan is 23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * complete, so use longer timeout to avoid race conditions 23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * with scanning and following association request. 23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout = 30; 23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d " 23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "seconds", ret, timeout); 23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx); 23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout, 23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, drv->ctx); 23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(ssids); 23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(freqs); 23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie) 23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end, *pos; 23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ies == NULL) 23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = ies; 23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = ies + ies_len; 23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < end) { 23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + pos[1] > end) 23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos[0] == ie) 23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + pos[1]; 23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 23918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv, 23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie, size_t ie_len) 23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ssid; 24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->filter_ssids == NULL) 24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID); 24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL) 24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < drv->num_filter_ssids; i++) { 24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid[1] == drv->filter_ssids[i].ssid_len && 24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) == 24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int bss_info_handler(struct nl_msg *msg, void *arg) 24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 24248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *bss[NL80211_BSS_MAX + 1]; 24258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { 24268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC }, 24278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, 24288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_TSF] = { .type = NLA_U64 }, 24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, 24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, 24318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC }, 24328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, 24338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, 24348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_STATUS] = { .type = NLA_U32 }, 24358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 }, 24368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC }, 24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_bss_info_arg *_arg = arg; 24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *res = _arg->res; 24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res **tmp; 24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *r; 24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie, *beacon_ie; 24438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ie_len, beacon_ie_len; 24448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 244587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen size_t i; 24468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 24488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 24498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb[NL80211_ATTR_BSS]) 24508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 24518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], 24528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss_policy)) 24538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 245487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if (bss[NL80211_BSS_STATUS]) { 245587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen enum nl80211_bss_status status; 245687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen status = nla_get_u32(bss[NL80211_BSS_STATUS]); 245787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if (status == NL80211_BSS_STATUS_ASSOCIATED && 245887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen bss[NL80211_BSS_FREQUENCY]) { 245987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen _arg->assoc_freq = 246087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen nla_get_u32(bss[NL80211_BSS_FREQUENCY]); 246187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz", 246287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen _arg->assoc_freq); 246387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen } 246487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen } 246587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if (!res) 246687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen return NL_SKIP; 24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { 24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]); 24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]); 24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie = NULL; 24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie_len = 0; 24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_BEACON_IES]) { 24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]); 24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]); 24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_ie = NULL; 24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_ie_len = 0; 24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie, 24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie ? ie_len : beacon_ie_len)) 24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len); 24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (r == NULL) 24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_BSSID]) 24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]), 24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_ALEN); 24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_FREQUENCY]) 24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); 24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_BEACON_INTERVAL]) 24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]); 24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_CAPABILITY]) 24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]); 24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags |= WPA_SCAN_NOISE_INVALID; 24998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_SIGNAL_MBM]) { 25008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); 25018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->level /= 100; /* mBm to dBm */ 25028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID; 25038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) { 25048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); 25058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags |= WPA_SCAN_LEVEL_INVALID; 25068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 25078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID; 25088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_TSF]) 25098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]); 25108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_SEEN_MS_AGO]) 25118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]); 25128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->ie_len = ie_len; 25138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (r + 1); 25148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie) { 25158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ie_len; 25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->beacon_ie_len = beacon_ie_len; 25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (beacon_ie) 25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, beacon_ie, beacon_ie_len); 25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss[NL80211_BSS_STATUS]) { 25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_bss_status status; 25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = nla_get_u32(bss[NL80211_BSS_STATUS]); 25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (status) { 25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_BSS_STATUS_AUTHENTICATED: 25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags |= WPA_SCAN_AUTHENTICATED; 25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case NL80211_BSS_STATUS_ASSOCIATED: 25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags |= WPA_SCAN_ASSOCIATED; 25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 253787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen /* 253887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen * cfg80211 maintains separate BSS table entries for APs if the same 253987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does 254087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen * not use frequency as a separate key in the BSS table, so filter out 254187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen * duplicated entries. Prefer associated BSS entry in such a case in 254287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen * order to get the correct frequency into the BSS table. 254387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen */ 254487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen for (i = 0; i < res->num; i++) { 254587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen const u8 *s1, *s2; 254687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0) 254787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen continue; 254887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 254987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen s1 = nl80211_get_ie((u8 *) (res->res[i] + 1), 255087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen res->res[i]->ie_len, WLAN_EID_SSID); 255187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen s2 = nl80211_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID); 255287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if (s1 == NULL || s2 == NULL || s1[1] != s2[1] || 255387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen os_memcmp(s1, s2, 2 + s1[1]) != 0) 255487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen continue; 255587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 255687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen /* Same BSSID,SSID was already included in scan results */ 255787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Remove duplicated scan result " 255887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen "for " MACSTR, MAC2STR(r->bssid)); 255987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 256087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen if ((r->flags & WPA_SCAN_ASSOCIATED) && 256187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) { 256287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen os_free(res->res[i]); 256387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen res->res[i] = r; 256487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen } else 256587fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen os_free(r); 256687fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen return NL_SKIP; 256787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen } 256887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen 25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = os_realloc(res->res, 25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (res->num + 1) * sizeof(struct wpa_scan_res *)); 25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tmp == NULL) { 25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(r); 25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp[res->num++] = r; 25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res->res = tmp; 25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void clear_state_mismatch(struct wpa_driver_nl80211_data *drv, 25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr) 25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) { 25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Clear possible state " 25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "mismatch (" MACSTR ")", MAC2STR(addr)); 25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_mlme(drv, addr, 25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_DEAUTHENTICATE, 25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID, 1); 25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_check_bss_status( 25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res) 25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 25998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < res->num; i++) { 26018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *r = res->res[i]; 26028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (r->flags & WPA_SCAN_AUTHENTICATED) { 26038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan results " 26048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicates BSS status with " MACSTR 26058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " as authenticated", 26068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(r->bssid)); 26078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_STATION && 26088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 && 26098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) != 26108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 26118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Unknown BSSID" 26128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " in local state (auth=" MACSTR 26138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " assoc=" MACSTR ")", 26148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(drv->auth_bssid), 26158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(drv->bssid)); 26168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clear_state_mismatch(drv, r->bssid); 26178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (r->flags & WPA_SCAN_ASSOCIATED) { 26218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan results " 26228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicate BSS status with " MACSTR 26238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " as associated", 26248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(r->bssid)); 26258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_STATION && 26268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !drv->associated) { 26278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Local state " 26288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(not associated) does not match " 26298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with BSS state"); 26308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clear_state_mismatch(drv, r->bssid); 26318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (drv->nlmode == NL80211_IFTYPE_STATION && 26328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(drv->bssid, r->bssid, ETH_ALEN) != 26338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 26348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Local state " 26358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(associated with " MACSTR ") does " 26368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with BSS state", 26378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(drv->bssid)); 26388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clear_state_mismatch(drv, r->bssid); 26398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt clear_state_mismatch(drv, drv->bssid); 26408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_scan_results_free(struct wpa_scan_results *res) 26478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 26498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == NULL) 26518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 26528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < res->num; i++) 26548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res->res[i]); 26558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res->res); 26568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(res); 26578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_scan_results * 26618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnl80211_get_scan_results(struct wpa_driver_nl80211_data *drv) 26628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 26638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 26648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *res; 26658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 26668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_bss_info_arg arg; 26678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = os_zalloc(sizeof(*res)); 26698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == NULL) 26708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 26718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 26728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 26738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 26748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, NLM_F_DUMP, 26768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_GET_SCAN, 0); 26778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 26788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt arg.drv = drv; 26808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt arg.res = res; 26818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); 26828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 26838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) { 26848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Received scan results (%lu BSSes)", 26858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) res->num); 26868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 26878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 26888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d " 26898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 26908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 26918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 26928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_results_free(res); 26938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 26948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 26958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 26978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 26988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results 26998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private wext data from wpa_driver_nl80211_init() 27008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Scan results on success, -1 on failure 27018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 27028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_scan_results * 27038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_nl80211_get_scan_results(void *priv) 27048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 27068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 27078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *res; 27088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = nl80211_get_scan_results(drv); 27108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 27118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_check_bss_status(drv, res); 27128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 27138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv) 27178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *res; 27198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 27208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = nl80211_get_scan_results(drv); 27228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == NULL) { 27238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to get scan results"); 27248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 27258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Scan result dump"); 27288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < res->num; i++) { 27298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_res *r = res->res[i]; 27308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %d/%d " MACSTR "%s%s", 27318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) i, (int) res->num, MAC2STR(r->bssid), 27328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags & WPA_SCAN_AUTHENTICATED ? " [auth]" : "", 27338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : ""); 27348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_results_free(res); 27378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 27388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_key(const char *ifname, void *priv, 27418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg, const u8 *addr, 27428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_idx, int set_tx, 27438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *seq, size_t seq_len, 27448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key, size_t key_len) 27458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 27468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 27478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 27488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex = if_nametoindex(ifname); 27498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 27508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 27518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ifindex=%d alg=%d addr=%p key_idx=%d " 27538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "set_tx=%d seq_len=%lu key_len=%lu", 27548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, ifindex, alg, addr, key_idx, set_tx, 27558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) seq_len, (unsigned long) key_len); 27568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 27588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 27598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 27608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (alg == WPA_ALG_NONE) { 27628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 27638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_DEL_KEY, 0); 27648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 27658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 27668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_NEW_KEY, 0); 27678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key); 27688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 27698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_WEP: 27708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len == 5) 27718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 27728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_WEP40); 27738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 27748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 27758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_WEP104); 27768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_TKIP: 27788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 27798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_TKIP); 27808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_CCMP: 27828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 27838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_CCMP); 27848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_IGTK: 27868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 27878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_AES_CMAC); 27888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 27898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 27908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: Unsupported encryption " 27918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "algorithm %d", __func__, alg); 27928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 27938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 27948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 27968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 27978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (seq && seq_len) 27988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq); 27998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr && !is_broadcast_ether_addr(addr)) { 28018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); 28028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); 28038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (alg != WPA_ALG_WEP && key_idx && !set_tx) { 28058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK"); 28068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE, 28078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_KEYTYPE_GROUP); 28088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 28098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (addr && is_broadcast_ether_addr(addr)) { 28108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *types; 28118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err; 28128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " broadcast key"); 28138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt types = nlmsg_alloc(); 28148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!types) 28158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 28168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST); 28178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES, 28188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt types); 28198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(types); 28208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) 28218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 28228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 28238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); 28248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); 28258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 28278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE) 28288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 28298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 28308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)", 28318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret, strerror(-ret)); 28328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 28348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * If we failed or don't need to set the default TX key (below), 28358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * we're done here. 28368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 28378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret || !set_tx || alg == WPA_ALG_NONE) 28388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 28398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_AP && addr && 28408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !is_broadcast_ether_addr(addr)) 28418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 28428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 28448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 28458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 28468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 28488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_KEY, 0); 28498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); 28508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); 28518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (alg == WPA_ALG_IGTK) 28528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT); 28538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 28548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT); 28558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr && is_broadcast_ether_addr(addr)) { 28568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *types; 28578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err; 28588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt types = nlmsg_alloc(); 28598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!types) 28608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 28618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST); 28628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES, 28638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt types); 28648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(types); 28658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) 28668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 28678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (addr) { 28688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *types; 28698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err; 28708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt types = nlmsg_alloc(); 28718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!types) 28728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 28738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_UNICAST); 28748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES, 28758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt types); 28768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(types); 28778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) 28788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 28798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 28808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 28828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -ENOENT) 28838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 28848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 28858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; " 28868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "err=%d %s)", ret, strerror(-ret)); 28878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 28888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 28908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 28918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 28928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 28948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl_add_key(struct nl_msg *msg, enum wpa_alg alg, 28958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_idx, int defkey, 28968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *seq, size_t seq_len, 28978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *key, size_t key_len) 28988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 28998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY); 29008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!key_attr) 29018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 29028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (defkey && alg == WPA_ALG_IGTK) 29048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT); 29058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (defkey) 29068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT); 29078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx); 29098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (alg) { 29118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_WEP: 29128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key_len == 5) 29138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 29148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_WEP40); 29158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 29168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 29178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_WEP104); 29188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 29198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_TKIP: 29208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_TKIP); 29218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 29228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_CCMP: 29238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP); 29248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 29258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_ALG_IGTK: 29268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 29278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_AES_CMAC); 29288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 29298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 29308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "%s: Unsupported encryption " 29318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "algorithm %d", __func__, alg); 29328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 29338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 29348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (seq && seq_len) 29368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq); 29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_KEY_DATA, key_len, key); 29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, key_attr); 29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 29448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 29458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 29468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_set_conn_keys(struct wpa_driver_associate_params *params, 29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg) 29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, privacy = 0; 29528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *nl_keys, *nl_key; 29538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 4; i++) { 29558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!params->wep_key[i]) 29568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 29578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt privacy = 1; 29588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 29598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 29608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wps == WPS_MODE_PRIVACY) 29618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt privacy = 1; 29628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->pairwise_suite && 29638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->pairwise_suite != WPA_CIPHER_NONE) 29648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt privacy = 1; 29658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!privacy) 29678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 29688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY); 29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS); 29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!nl_keys) 29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 4; i++) { 29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!params->wep_key[i]) 29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_key = nla_nest_start(msg, i); 29808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!nl_key) 29818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i], 29848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wep_key[i]); 29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wep_key_len[i] == 5) 29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_WEP40); 29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 29908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_CIPHER_SUITE_WEP104); 29918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_KEY_IDX, i); 29938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i == params->wep_tx_keyidx) 29958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT); 29968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 29978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, nl_key); 29988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 29998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, nl_keys); 30008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 30028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 30048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 30058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, 30098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int cmd, u16 reason_code, 30108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int local_state_change) 30118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 30138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 30148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 30178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 30188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, cmd, 0); 30208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 30228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code); 30238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); 30248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (local_state_change) 30258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE); 30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 30288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 30298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " 30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv, 30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int reason_code) 30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)", 30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, MAC2STR(addr), reason_code); 30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 0; 30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISCONNECT, 30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code, 0); 30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_deauthenticate(void *priv, const u8 *addr, 30548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reason_code) 30558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) 30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_disconnect(drv, addr, reason_code); 30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)", 30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, MAC2STR(addr), reason_code); 30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 0; 30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_ADHOC) 30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return nl80211_leave_ibss(drv); 30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, 30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code, 0); 30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr, 30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reason_code) 30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) 30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_disconnect(drv, addr, reason_code); 30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s", __func__); 30788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 0; 30798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISASSOCIATE, 30808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code, 0); 30818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 30828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_authenticate( 30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *priv, struct wpa_driver_auth_params *params) 30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1, i; 30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_auth_type type; 30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count = 0; 30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 0; 30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(drv->auth_bssid, 0, ETH_ALEN); 30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* FIX: IBSS mode */ 30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode != NL80211_IFTYPE_STATION && 30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA) < 0) 30998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtretry: 31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 31048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)", 31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifindex); 31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 31108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_AUTHENTICATE, 0); 31118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 4; i++) { 31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!params->wep_key[i]) 31148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 31158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_set_key(bss->ifname, priv, WPA_ALG_WEP, 31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, i, 31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i == params->wep_tx_keyidx, NULL, 0, 31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wep_key[i], 31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wep_key_len[i]); 31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wep_tx_keyidx != i) 31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0, 31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wep_key[i], params->wep_key_len[i])) { 31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 31268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->bssid) { 31318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * bssid=" MACSTR, 31328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(params->bssid)); 31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid); 31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->freq) { 31368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); 31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); 31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ssid) { 31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " * SSID", 31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid, params->ssid_len); 31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, 31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid); 31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len); 31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ie) 31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie); 31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_OPEN) 31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = NL80211_AUTHTYPE_OPEN_SYSTEM; 31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_SHARED) 31518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = NL80211_AUTHTYPE_SHARED_KEY; 31528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_LEAP) 31538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = NL80211_AUTHTYPE_NETWORK_EAP; 31548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_FT) 31558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = NL80211_AUTHTYPE_FT; 31568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 31578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 31588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * Auth Type %d", type); 31598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type); 31608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->local_state_change) { 31618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * Local state change only"); 31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE); 31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 31668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 31678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " 31698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 31708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 31718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -EALREADY && count == 1 && params->bssid && 31728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !params->local_state_change) { 31738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 31748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mac80211 does not currently accept new 31758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * authentication if we are already authenticated. As a 31768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * workaround, force deauthentication and try again. 31778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 31788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Retry authentication " 31798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "after forced deauthentication"); 31808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_deauthenticate( 31818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss, params->bssid, 31828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_PREV_AUTH_NOT_VALID); 31838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 31848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto retry; 31858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 31878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 31888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 31898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Authentication request send " 31908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "successfully"); 31918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 31938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 31948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 31958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 31968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 31988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct phy_info_arg { 31998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 *num_modes; 32008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *modes; 32018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 32028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int phy_info_handler(struct nl_msg *msg, void *arg) 32048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 32058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; 32068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 32078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct phy_info_arg *phy_info = arg; 32088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; 32108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; 32128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { 32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 }, 32148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG }, 32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG }, 32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG }, 32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG }, 32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 }, 32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1]; 32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = { 32238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 }, 32248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG }, 32258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 32268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *nl_band; 32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *nl_freq; 32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *nl_rate; 32308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rem_band, rem_freq, rem_rate; 32318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *mode; 32328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx, mode_is_set; 32338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 32358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 32368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb_msg[NL80211_ATTR_WIPHY_BANDS]) 32388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 32398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) { 32418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode = os_realloc(phy_info->modes, (*phy_info->num_modes + 1) * sizeof(*mode)); 32428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!mode) 32438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 32448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt phy_info->modes = mode; 32458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode_is_set = 0; 32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode = &phy_info->modes[*(phy_info->num_modes)]; 32498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(mode, 0, sizeof(*mode)); 32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *(phy_info->num_modes) += 1; 32518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band), 32538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(nl_band), NULL); 32548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) { 32568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->ht_capab = nla_get_u16( 32578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb_band[NL80211_BAND_ATTR_HT_CAPA]); 32588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 32598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) { 32618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->a_mpdu_params |= nla_get_u8( 32628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) & 32638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x03; 32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 32658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) { 32678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->a_mpdu_params |= nla_get_u8( 32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) << 32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2; 32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] && 32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET])) { 32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *mcs; 32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mcs = nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]); 32768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mode->mcs_set, mcs, 16); 32778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { 32808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), 32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(nl_freq), freq_policy); 32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) 32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->num_channels++; 32858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 32868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels = os_zalloc(mode->num_channels * sizeof(struct hostapd_channel_data)); 32888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!mode->channels) 32898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx = 0; 32928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { 32948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), 32958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(nl_freq), freq_policy); 32968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) 32978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 32988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 32998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); 33008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].flag = 0; 33018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!mode_is_set) { 33038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* crude heuristic */ 33048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->channels[idx].freq < 4000) 33058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->mode = HOSTAPD_MODE_IEEE80211B; 33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->mode = HOSTAPD_MODE_IEEE80211A; 33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode_is_set = 1; 33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* crude heuristic */ 33128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->channels[idx].freq < 4000) 33138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->channels[idx].freq == 2484) 33148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].chan = 14; 33158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 33168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].chan = (mode->channels[idx].freq - 2407) / 5; 33178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 33188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].chan = mode->channels[idx].freq/5 - 1000; 33198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) 33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].flag |= 33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_CHAN_DISABLED; 33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) 33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].flag |= 33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_CHAN_PASSIVE_SCAN; 33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS]) 33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].flag |= 33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_CHAN_NO_IBSS; 33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) 33308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].flag |= 33318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_CHAN_RADAR; 33328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] && 33348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) 33358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels[idx].max_tx_power = 33368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100; 33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx++; 33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { 33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate), 33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(nl_rate), rate_policy); 33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) 33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->num_rates++; 33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->rates = os_zalloc(mode->num_rates * sizeof(int)); 33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!mode->rates) 33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx = 0; 33548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { 33568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate), 33578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_len(nl_rate), rate_policy); 33588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb_rate[NL80211_BITRATE_ATTR_RATE]) 33598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 33608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->rates[idx] = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]); 33618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* crude heuristic */ 33638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->mode == HOSTAPD_MODE_IEEE80211B && 33648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->rates[idx] > 200) 33658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->mode = HOSTAPD_MODE_IEEE80211G; 33668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx++; 33688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 33698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 33708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 33728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 33738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_hw_modes * 33758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_nl80211_add_11b(struct hostapd_hw_modes *modes, u16 *num_modes) 33768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 33778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 m; 33788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode; 33798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, mode11g_idx = -1; 33808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* If only 802.11g mode is included, use it to construct matching 33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 802.11b mode data. */ 33838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (m = 0; m < *num_modes; m++) { 33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (modes[m].mode == HOSTAPD_MODE_IEEE80211B) 33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return modes; /* 802.11b already included */ 33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (modes[m].mode == HOSTAPD_MODE_IEEE80211G) 33888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode11g_idx = m; 33898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode11g_idx < 0) 33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return modes; /* 2.4 GHz band not supported at all */ 33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nmodes = os_realloc(modes, (*num_modes + 1) * sizeof(*nmodes)); 33958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nmodes == NULL) 33968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return modes; /* Could not add 802.11b mode */ 33978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode = &nmodes[*num_modes]; 33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(mode, 0, sizeof(*mode)); 34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*num_modes)++; 34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt modes = nmodes; 34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->mode = HOSTAPD_MODE_IEEE80211B; 34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode11g = &modes[mode11g_idx]; 34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->num_channels = mode11g->num_channels; 34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->channels = os_malloc(mode11g->num_channels * 34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct hostapd_channel_data)); 34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->channels == NULL) { 34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*num_modes)--; 34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return modes; /* Could not add 802.11b mode */ 34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mode->channels, mode11g->channels, 34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode11g->num_channels * sizeof(struct hostapd_channel_data)); 34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->num_rates = 0; 34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->rates = os_malloc(4 * sizeof(int)); 34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->rates == NULL) { 34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(mode->channels); 34208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*num_modes)--; 34218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return modes; /* Could not add 802.11b mode */ 34228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 34238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < mode11g->num_rates; i++) { 34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 && 34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode11g->rates[i] != 55 && mode11g->rates[i] != 110) 34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->rates[mode->num_rates] = mode11g->rates[i]; 34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->num_rates++; 34308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->num_rates == 4) 34318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 34328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 34338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->num_rates == 0) { 34358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(mode->channels); 34368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(mode->rates); 34378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (*num_modes)--; 34388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return modes; /* No 802.11b rates */ 34398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 34408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g " 34428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "information"); 34438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return modes; 34458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 34468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_set_ht40_mode(struct hostapd_hw_modes *mode, int start, 34498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int end) 34508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 34518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int c; 34528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (c = 0; c < mode->num_channels; c++) { 34548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_channel_data *chan = &mode->channels[c]; 34558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chan->freq - 10 >= start && chan->freq + 10 <= end) 34568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chan->flag |= HOSTAPD_CHAN_HT40; 34578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 34588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 34598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start, 34628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int end) 34638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 34648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int c; 34658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (c = 0; c < mode->num_channels; c++) { 34678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_channel_data *chan = &mode->channels[c]; 34688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(chan->flag & HOSTAPD_CHAN_HT40)) 34698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 34708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chan->freq - 30 >= start && chan->freq - 10 <= end) 34718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chan->flag |= HOSTAPD_CHAN_HT40MINUS; 34728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chan->freq + 10 >= start && chan->freq + 30 <= end) 34738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chan->flag |= HOSTAPD_CHAN_HT40PLUS; 34748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 34758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 34768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_reg_rule_ht40(struct nlattr *tb[], 34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct phy_info_arg *results) 34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 start, end, max_bw; 34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 m; 34838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL || 34858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_FREQ_RANGE_END] == NULL || 34868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL) 34878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 34888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000; 34908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000; 34918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000; 34928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz", 34948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start, end, max_bw); 34958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (max_bw < 40) 34968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 34978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 34988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (m = 0; m < *results->num_modes; m++) { 34998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(results->modes[m].ht_capab & 35008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) 35018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 35028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_set_ht40_mode(&results->modes[m], start, end); 35038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 35058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_reg_rule_sec(struct nlattr *tb[], 35088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct phy_info_arg *results) 35098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 35108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 start, end, max_bw; 35118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 m; 35128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL || 35148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_FREQ_RANGE_END] == NULL || 35158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL) 35168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 35178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000; 35198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000; 35208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000; 35218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (max_bw < 20) 35238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 35248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (m = 0; m < *results->num_modes; m++) { 35268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(results->modes[m].ht_capab & 35278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) 35288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 35298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_set_ht40_mode_sec(&results->modes[m], start, end); 35308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 35328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_get_reg(struct nl_msg *msg, void *arg) 35358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 35368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct phy_info_arg *results = arg; 35378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; 35388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 35398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *nl_rule; 35408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1]; 35418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int rem_rule; 35428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = { 35438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 }, 35448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 }, 35458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 }, 35468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, 35478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, 35488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, 35498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 35508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 35528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 35538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb_msg[NL80211_ATTR_REG_ALPHA2] || 35548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !tb_msg[NL80211_ATTR_REG_RULES]) { 35558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No regulatory information " 35568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "available"); 35578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 35588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s", 35618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2])); 35628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) 35648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 35658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX, 35668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(nl_rule), nla_len(nl_rule), reg_policy); 35678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_reg_rule_ht40(tb_rule, results); 35688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) 35718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 35728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX, 35738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_data(nl_rule), nla_len(nl_rule), reg_policy); 35748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_reg_rule_sec(tb_rule, results); 35758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 35768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 35788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 35798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_set_ht40_flags(struct wpa_driver_nl80211_data *drv, 35828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct phy_info_arg *results) 35838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 35848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 35858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 35878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 35888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 35898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 35918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_GET_REG, 0); 35928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, nl80211_get_reg, results); 35938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 35948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct hostapd_hw_modes * 35978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) 35988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 35998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 36008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 36018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 36028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct phy_info_arg result = { 36038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .num_modes = num_modes, 36048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .modes = NULL, 36058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 36068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *num_modes = 0; 36088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *flags = 0; 36098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 36118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 36128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 36138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 36158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_GET_WIPHY, 0); 36168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 36188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) { 36208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_set_ht40_flags(drv, &result); 36218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_add_11b(result.modes, num_modes); 36228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 36238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 36248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 36258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 36268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_send_frame(struct wpa_driver_nl80211_data *drv, 36298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const void *data, size_t len, 36308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encrypt) 36318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 36328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __u8 rtap_hdr[] = { 36338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, /* radiotap version */ 36348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x0e, 0x00, /* radiotap length */ 36358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */ 36368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */ 36378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, /* padding */ 36388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, /* RX and TX flags to indicate that */ 36398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0x00, 0x00, /* this is the injected frame directly */ 36408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 36418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iovec iov[2] = { 36428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 36438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .iov_base = &rtap_hdr, 36448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .iov_len = sizeof(rtap_hdr), 36458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }, 36468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 36478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .iov_base = (void *) data, 36488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .iov_len = len, 36498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 36508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 36518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct msghdr msg = { 36528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .msg_name = NULL, 36538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .msg_namelen = 0, 36548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .msg_iov = iov, 36558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .msg_iovlen = 2, 36568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .msg_control = NULL, 36578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .msg_controllen = 0, 36588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .msg_flags = 0, 36598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 36608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 36618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypt) 36638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP; 36648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3665c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (drv->monitor_sock < 0) { 3666c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No monitor socket available " 3667c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt "for %s", __func__); 3668c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt return -1; 3669c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt } 3670c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 36718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = sendmsg(drv->monitor_sock, &msg, 0); 36728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 36738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: sendmsg: %s", strerror(errno)); 36748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 36758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 36768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 36778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 36788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data, 36818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len) 36828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 36838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 36848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 36858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_mgmt *mgmt; 36868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encrypt = 1; 36878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 fc; 36888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = (struct ieee80211_mgmt *) data; 36908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fc = le_to_host16(mgmt->frame_control); 36918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 36928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_STATION && 36938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 36948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) { 36958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 36968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The use of last_mgmt_freq is a bit of a hack, 36978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * but it works due to the single-threaded nature 36988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * of wpa_supplicant. 36998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 37008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return nl80211_send_frame_cmd(drv, drv->last_mgmt_freq, 0, 37018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, data_len, NULL); 37028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 37038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && 37058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) { 37068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 37078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Only one of the authentication frame types is encrypted. 37088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * In order for static WEP encryption to work properly (i.e., 37098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to not encrypt the frame), we need to tell mac80211 about 37108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the frames that must not be encrypted. 37118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 37128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg); 37138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction); 37148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3) 37158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt encrypt = 0; 37168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 37178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt); 37198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 37208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_beacon(void *priv, 37238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *head, size_t head_len, 37248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *tail, size_t tail_len, 37258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int dtim_period, int beacon_int) 37268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 37278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 37288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 37298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 37308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 cmd = NL80211_CMD_NEW_BEACON; 37318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 37328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int beacon_set; 37338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex = if_nametoindex(bss->ifname); 37348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_set = bss->beacon_set; 37368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 37388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 37398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 37408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)", 37428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt beacon_set); 37438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (beacon_set) 37448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cmd = NL80211_CMD_SET_BEACON; 37458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 37478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, cmd, 0); 37488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, head_len, head); 37498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, tail_len, tail); 37508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); 37518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, beacon_int); 37528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period); 37538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 37558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 37568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", 37578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret, strerror(-ret)); 37588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 37598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->beacon_set = 1; 37608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 37618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 37628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 37638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 37648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 37658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_freq(struct wpa_driver_nl80211_data *drv, 37688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int freq, int ht_enabled, 37698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sec_channel_offset) 37708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 37718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 37728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 37738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 37758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 37768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 37778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 37798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_SET_WIPHY, 0); 37808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 37818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 37828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); 37838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ht_enabled) { 37848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (sec_channel_offset) { 37858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case -1: 37868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, 37878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CHAN_HT40MINUS); 37888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 37898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 37908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, 37918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CHAN_HT40PLUS); 37928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 37938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 37948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, 37958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CHAN_HT20); 37968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 37978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 37988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 37998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 38018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) 38028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 38038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): " 38048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d (%s)", freq, ret, strerror(-ret)); 38058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 38068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 38078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 38088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_sta_add(void *priv, 38118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_sta_add_params *params) 38128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 38138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 38148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 38158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 38168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -ENOBUFS; 38178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 38198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 38208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 38218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 38238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_NEW_STATION, 0); 38248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); 38268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr); 38278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid); 38288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len, 38298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->supp_rates); 38308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, 38318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->listen_interval); 38328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ht_capabilities) { 38338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, 38348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*params->ht_capabilities), 38358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ht_capabilities); 38368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 38378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 38398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 38408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_NEW_STATION " 38418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "result: %d (%s)", ret, strerror(-ret)); 38428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -EEXIST) 38438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 38448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 38458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 38468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 38478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr) 38508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 38518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 38528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 38538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 38548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 38558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 38578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 38588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 38598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 38618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_DEL_STATION, 0); 38628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, 38648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if_nametoindex(bss->ifname)); 38658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); 38668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 38688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -ENOENT) 38698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 38708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 38718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 38728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 38738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 38748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, 38778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifidx) 38788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 38798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 38808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx); 38828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 38848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* stop listening for EAPOL on this interface */ 38858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt del_ifidx(drv, ifidx); 38868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 38878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 38898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 38908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 38918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 38938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_DEL_INTERFACE, 0); 38948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx); 38958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 38968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) 38978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 38988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 38998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx); 39008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 39018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv, 39048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, 39058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_iftype iftype, 39068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int wds) 39078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 39088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg, *flags = NULL; 39098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifidx; 39108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -ENOBUFS; 39118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 39138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 39148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 39158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 39178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_NEW_INTERFACE, 0); 39188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 39198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname); 39208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype); 39218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iftype == NL80211_IFTYPE_MONITOR) { 39238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int err; 39248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = nlmsg_alloc(); 39268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!flags) 39278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 39288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES); 39308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags); 39328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(flags); 39348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (err) 39368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 39378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (wds) { 39388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds); 39398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 39408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 39428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 39438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 39448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)", 39458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, ret, strerror(-ret)); 39468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 39478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 39488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifidx = if_nametoindex(ifname); 39508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d", 39518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, ifidx); 39528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifidx <= 0) 39548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 39558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 39578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* start listening for EAPOL on this interface */ 39588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, ifidx); 39598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 39608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr && iftype != NL80211_IFTYPE_MONITOR && 39628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt linux_set_ifhwaddr(drv->ioctl_sock, ifname, addr)) { 39638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 39648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 39658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 39668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ifidx; 39688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 39698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, 39728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, enum nl80211_iftype iftype, 39738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr, int wds) 39748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 39758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 39768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds); 39788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* if error occured and interface exists already */ 39808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -ENFILE && if_nametoindex(ifname)) { 39818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname); 39828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to remove the interface that was already there. */ 39848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, if_nametoindex(ifname)); 39858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to create the interface again */ 39878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_create_iface_once(drv, ifname, iftype, addr, 39888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wds); 39898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 39908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret >= 0 && drv->disable_11b_rates) 39928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_disable_11b_rates(drv, ret, 1); 39938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 39958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 39968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 39988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok) 39998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 40008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_hdr *hdr; 40018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 fc; 40028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 40038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee80211_hdr *) buf; 40058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fc = le_to_host16(hdr->frame_control); 40068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 40088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.type = WLAN_FC_GET_TYPE(fc); 40098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.stype = WLAN_FC_GET_STYPE(fc); 40108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.dst = hdr->addr1; 40118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.data = buf; 40128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.data_len = len; 40138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.tx_status.ack = ok; 40148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(ctx, EVENT_TX_STATUS, &event); 40158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 40168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void from_unknown_sta(struct wpa_driver_nl80211_data *drv, 40198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len) 40208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 40218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 40228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 40238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_from_unknown.frame = buf; 40248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_from_unknown.len = len; 40258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event); 40268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 40278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_frame(struct wpa_driver_nl80211_data *drv, 40308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, size_t len, int datarate, int ssi_signal) 40318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 40328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_hdr *hdr; 40338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 fc; 40348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data event; 40358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee80211_hdr *) buf; 40378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fc = le_to_host16(hdr->frame_control); 40388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (WLAN_FC_GET_TYPE(fc)) { 40408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_FC_TYPE_MGMT: 40418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&event, 0, sizeof(event)); 40428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_mgmt.frame = buf; 40438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_mgmt.frame_len = len; 40448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_mgmt.datarate = datarate; 40458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt event.rx_mgmt.ssi_signal = ssi_signal; 40468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); 40478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 40488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_FC_TYPE_CTRL: 40498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* can only get here with PS-Poll frames */ 40508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "CTRL"); 40518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from_unknown_sta(drv, buf, len); 40528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 40538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_FC_TYPE_DATA: 40548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt from_unknown_sta(drv, buf, len); 40558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 40568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 40578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 40588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx) 40618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 40628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = eloop_ctx; 40638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len; 40648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char buf[3000]; 40658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_radiotap_iterator iter; 40668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 40678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int datarate = 0, ssi_signal = 0; 40688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int injected = 0, failed = 0, rxflags = 0; 40698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = recv(sock, buf, sizeof(buf), 0); 40718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 0) { 40728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("recv"); 40738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 40748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 40758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) { 40778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("received invalid radiotap frame\n"); 40788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 40798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 40808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 40818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (1) { 40828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = ieee80211_radiotap_iterator_next(&iter); 40838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -ENOENT) 40848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 40858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 40868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("received invalid radiotap frame (%d)\n", ret); 40878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 40888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 40898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (iter.this_arg_index) { 40908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE80211_RADIOTAP_FLAGS: 40918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) 40928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len -= 4; 40938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 40948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE80211_RADIOTAP_RX_FLAGS: 40958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rxflags = 1; 40968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 40978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE80211_RADIOTAP_TX_FLAGS: 40988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt injected = 1; 40998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt failed = le_to_host16((*(uint16_t *) iter.this_arg)) & 41008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_RADIOTAP_F_TX_FAIL; 41018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 41028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE80211_RADIOTAP_DATA_RETRIES: 41038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 41048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE80211_RADIOTAP_CHANNEL: 41058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: convert from freq/flags to channel number */ 41068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 41078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE80211_RADIOTAP_RATE: 41088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt datarate = *iter.this_arg * 5; 41098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 41108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IEEE80211_RADIOTAP_DB_ANTSIGNAL: 41118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssi_signal = *iter.this_arg; 41128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 41138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 41148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 41158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rxflags && injected) 41178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 41188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!injected) 41208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handle_frame(drv, buf + iter.max_length, 41218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len - iter.max_length, datarate, ssi_signal); 41228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 41238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt handle_tx_callback(drv->ctx, buf + iter.max_length, 41248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len - iter.max_length, !failed); 41258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 41268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 41298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * we post-process the filter code later and rewrite 41308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this to the offset to the last instruction 41318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 41328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define PASS 0xFF 41338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define FAIL 0xFE 41348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct sock_filter msock_filter_insns[] = { 41368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 41378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * do a little-endian load of the radiotap length field 41388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 41398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* load lower byte into A */ 41408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 2), 41418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* put it into X (== index register) */ 41428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_MISC| BPF_TAX, 0), 41438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* load upper byte into A */ 41448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 3), 41458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* left-shift it by 8 */ 41468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8), 41478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* or with X */ 41488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0), 41498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* put result into X */ 41508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_MISC| BPF_TAX, 0), 41518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 41538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Allow management frames through, this also gives us those 41548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * management frames that we sent ourselves with status 41558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 41568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* load the lower byte of the IEEE 802.11 frame control field */ 41578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), 41588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* mask off frame type and version */ 41598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF), 41608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* accept frame if it's both 0, fall through otherwise */ 41618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0), 41628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 41648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: add a bit to radiotap RX flags that indicates 41658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * that the sending station is not associated, then 41668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * add a filter here that filters on our DA and that flag 41678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to allow us to deauth frames to that bad station. 41688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 41698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * For now allow all To DS data frames through. 41708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 41718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* load the IEEE 802.11 frame control field */ 41728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_H | BPF_IND, 0), 41738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* mask off frame type, version and DS status */ 41748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03), 41758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* accept frame if version 0, type 2 and To DS, fall through otherwise 41768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 41778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0), 41788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 41808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 41818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * drop non-data frames 41828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 41838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* load the lower byte of the frame control field */ 41848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), 41858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* mask off QoS bit */ 41868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c), 41878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* drop non-data frames */ 41888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL), 41898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 41908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* load the upper byte of the frame control field */ 41918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1), 41928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* mask off toDS/fromDS */ 41938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03), 41948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* accept WDS frames */ 41958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0), 41968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 41978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 41988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * add header length to index 41998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 42008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* load the lower byte of the frame control field */ 42018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), 42028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* mask off QoS bit */ 42038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x80), 42048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* right shift it by 6 to give 0 or 2 */ 42058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 6), 42068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* add data frame header length */ 42078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 24), 42088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* add index, was start of 802.11 header */ 42098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0), 42108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* move to index, now start of LL header */ 42118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_MISC | BPF_TAX, 0), 42128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 42148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Accept empty data frames, we use those for 42158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * polling activity. 42168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 42178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_W | BPF_LEN, 0), 42188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0), 42198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 42218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Accept EAPOL frames 42228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 42238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_W | BPF_IND, 0), 42248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL), 42258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_LD | BPF_W | BPF_IND, 4), 42268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL), 42278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* keep these last two statements or change the code below */ 42298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* return 0 == "DROP" */ 42308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_RET | BPF_K, 0), 42318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* return ~0 == "keep all" */ 42328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt BPF_STMT(BPF_RET | BPF_K, ~0), 42338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 42348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct sock_fprog msock_filter = { 42368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .len = sizeof(msock_filter_insns)/sizeof(msock_filter_insns[0]), 42378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .filter = msock_filter_insns, 42388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 42398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int add_monitor_filter(int s) 42428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 42438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx; 42448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* rewrite all PASS/FAIL jump offsets */ 42468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (idx = 0; idx < msock_filter.len; idx++) { 42478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sock_filter *insn = &msock_filter_insns[idx]; 42488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (BPF_CLASS(insn->code) == BPF_JMP) { 42508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (insn->code == (BPF_JMP|BPF_JA)) { 42518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (insn->k == PASS) 42528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt insn->k = msock_filter.len - idx - 2; 42538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (insn->k == FAIL) 42548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt insn->k = msock_filter.len - idx - 3; 42558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (insn->jt == PASS) 42588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt insn->jt = msock_filter.len - idx - 2; 42598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (insn->jt == FAIL) 42608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt insn->jt = msock_filter.len - idx - 3; 42618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (insn->jf == PASS) 42638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt insn->jf = msock_filter.len - idx - 2; 42648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (insn->jf == FAIL) 42658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt insn->jf = msock_filter.len - idx - 3; 42668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, 42708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &msock_filter, sizeof(msock_filter))) { 42718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("SO_ATTACH_FILTER"); 42728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 42738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 42768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 42778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_remove_monitor_interface( 42808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv) 42818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 42828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->monitor_ifidx >= 0) { 42838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, drv->monitor_ifidx); 42848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->monitor_ifidx = -1; 42858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->monitor_sock >= 0) { 42878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(drv->monitor_sock); 42888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(drv->monitor_sock); 42898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->monitor_sock = -1; 42908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 42918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 42928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 42948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int 42958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) 42968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 42978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[IFNAMSIZ]; 42988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_ll ll; 42998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int optval; 43008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t optlen; 43018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss.ifname); 43038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[IFNAMSIZ - 1] = '\0'; 43048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->monitor_ifidx = 43068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL, 43078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 43088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4309c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (drv->monitor_ifidx == -EOPNOTSUPP) { 4310c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Driver does not support " 4311c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt "monitor interface type - try to run without it"); 4312c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt drv->no_monitor_iface_capab = 1; 4313c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt } 4314c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 43158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->monitor_ifidx < 0) 43168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 43178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, buf, 1)) 43198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 43208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(&ll, 0, sizeof(ll)); 43228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_family = AF_PACKET; 43238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ll.sll_ifindex = drv->monitor_ifidx; 43248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 43258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->monitor_sock < 0) { 43268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket[PF_PACKET,SOCK_RAW]"); 43278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 43288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (add_monitor_filter(drv->monitor_sock)) { 43318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Failed to set socket filter for monitor " 43328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface; do filtering in user space"); 43338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* This works, but will cost in performance. */ 43348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) { 43378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("monitor socket bind"); 43388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 43398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt optlen = sizeof(optval); 43428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt optval = 20; 43438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (setsockopt 43448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) { 43458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("Failed to set socket priority"); 43468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 43478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read, 43508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv, NULL)) { 43518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not register monitor read socket\n"); 43528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 43538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 43568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt error: 43578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_monitor_interface(drv); 43588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 43598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 43608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; 43638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_hapd_send_eapol( 43658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *priv, const u8 *addr, const u8 *data, 43668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len, int encrypt, const u8 *own_addr, u32 flags) 43678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 43688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 43698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 43708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_hdr *hdr; 43718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 43728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 43738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 43748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int qos = flags & WPA_STA_WMM; 43758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + 43778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len; 43788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = os_zalloc(len); 43798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr == NULL) { 43808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("malloc() failed for i802_send_data(len=%lu)\n", 43818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 43828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 43838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control = 43868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); 43878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); 43888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypt) 43898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); 43908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (qos) { 43918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control |= 43928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4); 43938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 43948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); 43968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); 43978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); 43988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 43998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (qos) { 44018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* add an empty QoS header if needed */ 44028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[0] = 0; 44038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos[1] = 0; 44048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 44058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 44068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); 44088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(rfc1042_header); 44098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, ETH_P_PAE); 44108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 44118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(pos, data, data_len); 44128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_driver_nl80211_send_frame(drv, (u8 *) hdr, len, encrypt); 44148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 44158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - " 44168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed: %d (%s)", 44178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, errno, strerror(errno)); 44188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 44198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hdr); 44208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 44228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 44238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u32 sta_flags_nl80211(int flags) 44268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 44278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 f = 0; 44288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WPA_STA_AUTHORIZED) 44308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f |= BIT(NL80211_STA_FLAG_AUTHORIZED); 44318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WPA_STA_WMM) 44328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f |= BIT(NL80211_STA_FLAG_WME); 44338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WPA_STA_SHORT_PREAMBLE) 44348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE); 44358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & WPA_STA_MFP) 44368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt f |= BIT(NL80211_STA_FLAG_MFP); 44378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return f; 44398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 44408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr, 44438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int total_flags, 44448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int flags_or, int flags_and) 44458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 44468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 44478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 44488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg, *flags = NULL; 44498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_sta_flag_update upd; 44508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 44528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 44538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 44548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = nlmsg_alloc(); 44568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!flags) { 44578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 44588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 44598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 44608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 44628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_STATION, 0); 44638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, 44658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if_nametoindex(bss->ifname)); 44668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); 44678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 44698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This 44708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * can be removed eventually. 44718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 44728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (total_flags & WPA_STA_AUTHORIZED) 44738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED); 44748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (total_flags & WPA_STA_WMM) 44768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME); 44778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (total_flags & WPA_STA_SHORT_PREAMBLE) 44798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE); 44808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (total_flags & WPA_STA_MFP) 44828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP); 44838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags)) 44858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 44868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&upd, 0, sizeof(upd)); 44888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt upd.mask = sta_flags_nl80211(flags_or | ~flags_and); 44898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt upd.set = sta_flags_nl80211(flags_or); 44908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd); 44918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(flags); 44938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 44948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 44958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 44968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(flags); 44978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 44988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 44998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, 45028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_associate_params *params) 45038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 45048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->p2p) 45058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P " 45068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "group (GO)"); 45078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode) || 45088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) { 45098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_monitor_interface(drv); 45108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 45118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 45128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: setup monitor interface (and add code somewhere to remove this 45148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * when AP mode is stopped; associate with mode != 2 or drv_deinit) */ 45158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 45178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 45188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv) 45218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 45228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 45238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 45248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 45268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 45278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 45288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 45308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_LEAVE_IBSS, 0); 45318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 45328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 45338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 45348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 45358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d " 45368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 45378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 45388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 45398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 45418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS request sent successfully"); 45428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 45448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 45458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 45468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 45478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv, 45508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_associate_params *params) 45518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 45528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 45538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 45548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count = 0; 45558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); 45578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) { 45598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to set interface into " 45608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IBSS mode"); 45618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 45628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 45638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtretry: 45658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 45668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 45678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 45688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 45708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_JOIN_IBSS, 0); 45718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 45728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid)) 45748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 45758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " * SSID", 45778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid, params->ssid_len); 45788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, 45798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid); 45808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->ssid, params->ssid, params->ssid_len); 45818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ssid_len = params->ssid_len; 45828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); 45848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); 45858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_set_conn_keys(params, msg); 45878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 45888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 45898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wpa_ie) { 45918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 45928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " * Extra IEs for Beacon/Probe Response frames", 45938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wpa_ie, params->wpa_ie_len); 45948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len, 45958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wpa_ie); 45968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 45978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 45998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 46008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 46018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)", 46028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret, strerror(-ret)); 46038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 46048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == -EALREADY && count == 1) { 46058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after " 46068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "forced leave"); 46078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_leave_ibss(drv); 46088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 46098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto retry; 46108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 46118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 46138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 46148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 46158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Join IBSS request sent successfully"); 46168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 46188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 46198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 46208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 46218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_connect( 46248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv, 46258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_associate_params *params) 46268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 46278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 46288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_auth_type type; 46298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = 0; 46308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int algs; 46318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 46338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 46348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 46358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex); 46378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 46388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_CONNECT, 0); 46398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 46418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->bssid) { 46428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * bssid=" MACSTR, 46438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(params->bssid)); 46448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid); 46458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 46468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->freq) { 46478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); 46488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); 46498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 46508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ssid) { 46518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " * SSID", 46528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid, params->ssid_len); 46538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, 46548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid); 46558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ssid_len > sizeof(drv->ssid)) 46568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 46578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->ssid, params->ssid, params->ssid_len); 46588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ssid_len = params->ssid_len; 46598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 46608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len); 46618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wpa_ie) 46628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len, 46638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wpa_ie); 46648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs = 0; 46668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_OPEN) 46678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs++; 46688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_SHARED) 46698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs++; 46708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_LEAP) 46718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt algs++; 46728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (algs > 1) { 46738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic " 46748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "selection"); 46758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_auth_type; 46768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 46778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->auth_alg & WPA_AUTH_ALG_OPEN) 46798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = NL80211_AUTHTYPE_OPEN_SYSTEM; 46808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_SHARED) 46818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = NL80211_AUTHTYPE_SHARED_KEY; 46828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_LEAP) 46838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = NL80211_AUTHTYPE_NETWORK_EAP; 46848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else if (params->auth_alg & WPA_AUTH_ALG_FT) 46858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = NL80211_AUTHTYPE_FT; 46868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 46878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 46888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * Auth Type %d", type); 46908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type); 46918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_auth_type: 46938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wpa_ie && params->wpa_ie_len) { 46948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum nl80211_wpa_versions ver; 46958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 46968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wpa_ie[0] == WLAN_EID_RSN) 46978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = NL80211_WPA_VERSION_2; 46988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 46998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ver = NL80211_WPA_VERSION_1; 47008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * WPA Version %d", ver); 47028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver); 47038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->pairwise_suite != CIPHER_NONE) { 47068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 47078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (params->pairwise_suite) { 47098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP40: 47108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_WEP40; 47118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP104: 47138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_WEP104; 47148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_CCMP: 47168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_CCMP; 47178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_TKIP: 47198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 47208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_TKIP; 47218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher); 47248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->group_suite != CIPHER_NONE) { 47278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 47288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (params->group_suite) { 47308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP40: 47318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_WEP40; 47328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP104: 47348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_WEP104; 47358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_CCMP: 47378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_CCMP; 47388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_TKIP: 47408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 47418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_TKIP; 47428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher); 47458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->key_mgmt_suite == KEY_MGMT_802_1X || 47488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->key_mgmt_suite == KEY_MGMT_PSK) { 47498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int mgmt = WLAN_AKM_SUITE_PSK; 47508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (params->key_mgmt_suite) { 47528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case KEY_MGMT_802_1X: 47538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = WLAN_AKM_SUITE_8021X; 47548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case KEY_MGMT_PSK: 47568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 47578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt = WLAN_AKM_SUITE_PSK; 47588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 47598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt); 47618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_set_conn_keys(params, msg); 47648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 47658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 47668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 47688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 47698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 47708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " 47718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 47728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 47738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 47748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 47758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully"); 47768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 47788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 47798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 47808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 47828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_associate( 47858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *priv, struct wpa_driver_associate_params *params) 47868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 47878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 47888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 47898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 47908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 47918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->mode == IEEE80211_MODE_AP) 47938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_ap(drv, params); 47948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->mode == IEEE80211_MODE_IBSS) 47968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_ibss(drv, params); 47978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 47988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { 47998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_set_mode(priv, params->mode) < 0) 48008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 48018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_connect(drv, params); 48028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->associated = 0; 48058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 48078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 48088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 48098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)", 48118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ifindex); 48128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 48138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_ASSOCIATE, 0); 48148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 48168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->bssid) { 48178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * bssid=" MACSTR, 48188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(params->bssid)); 48198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid); 48208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->freq) { 48228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * freq=%d", params->freq); 48238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq); 48248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_freq = params->freq; 48258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 48268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->assoc_freq = 0; 48278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ssid) { 48288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, " * SSID", 48298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid, params->ssid_len); 48308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len, 48318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ssid); 48328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->ssid_len > sizeof(drv->ssid)) 48338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 48348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(drv->ssid, params->ssid, params->ssid_len); 48358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->ssid_len = params->ssid_len; 48368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len); 48388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->wpa_ie) 48398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len, 48408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->wpa_ie); 48418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->pairwise_suite != CIPHER_NONE) { 48438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 48448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (params->pairwise_suite) { 48468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP40: 48478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_WEP40; 48488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 48498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP104: 48508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_WEP104; 48518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 48528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_CCMP: 48538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_CCMP; 48548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 48558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_TKIP: 48568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 48578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_TKIP; 48588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 48598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher); 48618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher); 48628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->group_suite != CIPHER_NONE) { 48658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 48668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (params->group_suite) { 48688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP40: 48698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_WEP40; 48708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 48718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_WEP104: 48728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_WEP104; 48738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 48748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_CCMP: 48758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_CCMP; 48768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 48778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case CIPHER_TKIP: 48788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 48798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WLAN_CIPHER_SUITE_TKIP; 48808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 48818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * group=0x%x", cipher); 48838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher); 48848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 48878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED) 48888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED); 48898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 48908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT); 48928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 48938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->prev_bssid) { 48948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR, 48958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(params->prev_bssid)); 48968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN, 48978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->prev_bssid); 48988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 48998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->p2p) 49018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, " * P2P group"); 49028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 49048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 49058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 49068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d " 49078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 49088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_dump_scan(drv); 49098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 49108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 49118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 49128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Association request send " 49138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "successfully"); 49148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 49168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 49178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 49188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 49198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_set_mode(struct wpa_driver_nl80211_data *drv, 49228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, int mode) 49238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 49248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 49258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -ENOBUFS; 49268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 49288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 49298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 49308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 49328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_INTERFACE, 0); 49338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); 49348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode); 49358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 49378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) 49388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 49398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 49408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:" 49418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " %d (%s)", ifindex, mode, ret, strerror(-ret)); 49428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 49438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 49448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_mode(void *priv, int mode) 49478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 49488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 49498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 49508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 49518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int nlmode; 49528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 49538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (mode) { 49558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 0: 49568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmode = NL80211_IFTYPE_STATION; 49578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 49588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 49598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmode = NL80211_IFTYPE_ADHOC; 49608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 49618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: 49628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmode = NL80211_IFTYPE_AP; 49638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 49648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 49658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 49668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 49678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_set_mode(drv, drv->ifindex, nlmode) == 0) { 49698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nlmode = nlmode; 49708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 49718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 49728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 49738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nlmode == drv->nlmode) { 49758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface already in " 49768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "requested mode - ignore error"); 49778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = 0; 49788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; /* Already in the requested mode */ 49798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 49808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 49818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* mac80211 doesn't allow mode changes while the device is up, so 49828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * take the device down, try to set the mode again, and bring the 49838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * device back up. 49848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 49858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting " 49868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface down"); 49878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < 10; i++) { 49888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0) == 49898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) { 49908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Try to set the mode again while the interface is 49918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * down */ 49928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_set_mode(drv, drv->ifindex, nlmode); 49938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 49948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1)) 49958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = -1; 49968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) 49978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 49988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 49998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set " 50008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface down"); 50018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_sleep(0, 100000); 50028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 50038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) { 50058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while " 50068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface is down"); 50078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nlmode = nlmode; 50088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 50098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone: 50118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret && nlmode == NL80211_IFTYPE_AP) { 50128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Setup additional AP mode functionality if needed */ 5013c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (!drv->no_monitor_iface_capab && drv->monitor_ifidx < 0 && 5014c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt nl80211_create_monitor_interface(drv) && 5015c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt !drv->no_monitor_iface_capab) 50168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 50178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (!ret && nlmode != NL80211_IFTYPE_AP) { 50188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Remove additional AP mode functionality */ 50198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_monitor_interface(drv); 50208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->beacon_set = 0; 50218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 50228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 50248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d " 50258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from %d failed", nlmode, drv->nlmode); 50268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 50288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_get_capa(void *priv, 50328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_capa *capa) 50338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 50348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 50358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 50368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->has_capability) 50378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 50388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(capa, &drv->capa, sizeof(*capa)); 50398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 50408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_operstate(void *priv, int state) 50448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 50458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 50468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 50478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)", 50498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, drv->operstate, state, state ? "UP" : "DORMANT"); 50508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->operstate = state; 50518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1, 50528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt state ? IF_OPER_UP : IF_OPER_DORMANT); 50538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_set_supp_port(void *priv, int authorized) 50578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 50588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 50598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 50608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 50618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_sta_flag_update upd; 50628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 50648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 50658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 50668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 50688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_STATION, 0); 50698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, 50718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if_nametoindex(bss->ifname)); 50728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid); 50738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&upd, 0, sizeof(upd)); 50758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED); 50768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (authorized) 50778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED); 50788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd); 50798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 50818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 50828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 50838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/* Set kernel driver on given frequency (MHz) */ 508775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int i802_set_freq(void *priv, struct hostapd_freq_params *freq) 50888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 508975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct i802_bss *bss = priv; 509075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct wpa_driver_nl80211_data *drv = bss->drv; 509175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return wpa_driver_nl80211_set_freq(drv, freq->freq, freq->ht_enabled, 509275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen freq->sec_channel_offset); 50938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 50948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 509675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen#if defined(HOSTAPD) || defined(CONFIG_AP) 50978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 50988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic inline int min_int(int a, int b) 50998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a < b) 51018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return a; 51028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return b; 51038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 51048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int get_key_handler(struct nl_msg *msg, void *arg) 51078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 51098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 51108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 51128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 51138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 51158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: validate the key index and mac address! 51168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Otherwise, there's a race condition as soon as 51178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the kernel starts sending key notifications. 51188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 51198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_KEY_SEQ]) 51218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]), 51228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6)); 51238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 51248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 51258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, 51288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int idx, u8 *seq) 51298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 51318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 51328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 51338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 51358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 51368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 51378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 51398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_GET_KEY, 0); 51408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) 51428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); 51438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx); 51448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface)); 51458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(seq, 0, 6); 51478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, get_key_handler, seq); 51498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 51508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 51518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 51528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates, 51558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int mode) 51568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 51588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 51598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 51608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rates[NL80211_MAX_SUPP_RATES]; 51618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rates_len = 0; 51628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 51638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 51658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 51668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 51678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 51698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_SET_BSS, 0); 51708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++) 51728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rates[rates_len++] = basic_rates[i] / 5; 51738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates); 51758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); 51778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 51798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 51808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 51818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 51828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_rts(void *priv, int rts) 51858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 51868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 51878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 51888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 51898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -ENOBUFS; 51908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 val; 51918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 51938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 51948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 51958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 51968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rts >= 2347) 51978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = (u32) -1; 51988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 51998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = rts; 52008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 52028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_WIPHY, 0); 52038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 52048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val); 52058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 52078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) 52088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 52098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 52108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: " 52118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d (%s)", rts, ret, strerror(-ret)); 52128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 52138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 52148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_frag(void *priv, int frag) 52178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 52188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 52198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 52208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 52218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -ENOBUFS; 52228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 val; 52238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 52258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 52268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 52278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (frag >= 2346) 52298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = (u32) -1; 52308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 52318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val = frag; 52328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 52348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_WIPHY, 0); 52358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 52368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val); 52378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 52398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ret) 52408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 52418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 52428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold " 52438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d: %d (%s)", frag, ret, strerror(-ret)); 52448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 52458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 52468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_flush(void *priv) 52498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 52508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 52518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 52528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 52538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 52558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 52568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 52578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 52598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_DEL_STATION, 0); 52608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 52628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * XXX: FIX! this needs to flush all VLANs too 52638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 52648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, 52658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if_nametoindex(bss->ifname)); 52668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 52688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 52698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 52708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 52718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int get_sta_handler(struct nl_msg *msg, void *arg) 52748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 52758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 52768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 52778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostap_sta_driver_data *data = arg; 52788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *stats[NL80211_STA_INFO_MAX + 1]; 52798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = { 52808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 }, 52818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 }, 52828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 }, 52838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 }, 52848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 }, 52858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt }; 52868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 52888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 52898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 52918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: validate the interface and mac address! 52928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Otherwise, there's a race condition as soon as 52938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the kernel starts sending station notifications. 52948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 52958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 52968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tb[NL80211_ATTR_STA_INFO]) { 52978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "sta stats missing!"); 52988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 52998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 53008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nla_parse_nested(stats, NL80211_STA_INFO_MAX, 53018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tb[NL80211_ATTR_STA_INFO], 53028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt stats_policy)) { 53038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "failed to parse nested attributes!"); 53048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 53058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 53068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_INACTIVE_TIME]) 53088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->inactive_msec = 53098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]); 53108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_RX_BYTES]) 53118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]); 53128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_TX_BYTES]) 53138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]); 53148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_RX_PACKETS]) 53158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rx_packets = 53168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]); 53178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (stats[NL80211_STA_INFO_TX_PACKETS]) 53188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tx_packets = 53198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]); 53208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 53228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 53238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data, 53258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *addr) 53268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 53278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 53288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 53298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 53308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(data, 0, sizeof(*data)); 53328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 53338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 53348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 53358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 53378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_GET_STATION, 0); 53388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); 53408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); 53418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, get_sta_handler, data); 53438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 53448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 53458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 53468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_tx_queue_params(void *priv, int queue, int aifs, 53498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cw_min, int cw_max, int burst_time) 53508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 53518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 53528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 53538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 53548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *txq, *params; 53558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 53578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 53588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 53598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 53618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_WIPHY, 0); 53628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); 53648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS); 53668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!txq) 53678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 53688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* We are only sending parameters for a single TXQ at a time */ 53708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params = nla_nest_start(msg, 1); 53718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!params) 53728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 53738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (queue) { 53758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 0: 53768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO); 53778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 53788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 53798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI); 53808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 53818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: 53828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE); 53838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 53848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 3: 53858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK); 53868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 53878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 53888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Burst time is configured in units of 0.1 msec and TXOP parameter in 53898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 32 usec, so need to convert the value here. */ 53908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32); 53918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min); 53928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max); 53938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs); 53948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, params); 53968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, txq); 53988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 53998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) 54008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 54018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 54028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 54038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_bss(void *priv, int cts, int preamble, int slot, 54078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ht_opmode) 54088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 54098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 54108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 54118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 54128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 54148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 54158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 54168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 54188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_SET_BSS, 0); 54198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cts >= 0) 54218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts); 54228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (preamble >= 0) 54238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble); 54248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (slot >= 0) 54258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot); 54268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ht_opmode >= 0) 54278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode); 54288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); 54298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 54318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 54328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 54338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_cts_protect(void *priv, int value) 54378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 54388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return i802_set_bss(priv, value, -1, -1, -1); 54398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_preamble(void *priv, int value) 54438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 54448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return i802_set_bss(priv, -1, value, -1, -1); 54458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_short_slot_time(void *priv, int value) 54498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 54508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return i802_set_bss(priv, -1, -1, value, -1); 54518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_sta_vlan(void *priv, const u8 *addr, 54558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, int vlan_id) 54568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 54578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 54588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 54598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 54608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -ENOBUFS; 54618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 54638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 54648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 54658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 54678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_STATION, 0); 54688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, 54708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if_nametoindex(bss->ifname)); 54718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr); 54728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN, 54738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if_nametoindex(ifname)); 54748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 54768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0) { 54778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr=" 54788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)", 54798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr), ifname, vlan_id, ret, 54808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt strerror(-ret)); 54818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 54828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 54838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 54848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_set_ht_params(void *priv, const u8 *ht_capab, 54888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ht_capab_len, const u8 *ht_oper, 54898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ht_oper_len) 54908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 54918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ht_oper_len >= 6) { 54928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ht opmode uses 16bit in octet 5 & 6 */ 54938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ht_opmode = le_to_host16(((u16 *) ht_oper)[2]); 54948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return i802_set_bss(priv, -1, -1, -1, ht_opmode); 54958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 54968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 54978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 54988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 54998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_get_inact_sec(void *priv, const u8 *addr) 55018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 55028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostap_sta_driver_data data; 55038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 55048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data.inactive_msec = (unsigned long) -1; 55068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = i802_read_sta_data(priv, &data, addr); 55078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret || data.inactive_msec == (unsigned long) -1) 55088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 55098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data.inactive_msec / 1000; 55108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 55118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_sta_clear_stats(void *priv, const u8 *addr) 55148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 55158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 55168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO */ 55178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 55188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 55198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 55208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, 55238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reason) 55248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 55258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 55268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_mgmt mgmt; 55278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(&mgmt, 0, sizeof(mgmt)); 55298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 55308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_FC_STYPE_DEAUTH); 55318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.da, addr, ETH_ALEN); 55328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.sa, own_addr, ETH_ALEN); 55338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.bssid, own_addr, ETH_ALEN); 55348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt.u.deauth.reason_code = host_to_le16(reason); 55358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, 55368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_HDRLEN + 55378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(mgmt.u.deauth)); 55388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 55398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, 55428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int reason) 55438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 55448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 55458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_mgmt mgmt; 55468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memset(&mgmt, 0, sizeof(mgmt)); 55488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, 55498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_FC_STYPE_DISASSOC); 55508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.da, addr, ETH_ALEN); 55518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.sa, own_addr, ETH_ALEN); 55528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt memcpy(mgmt.bssid, own_addr, ETH_ALEN); 55538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mgmt.u.disassoc.reason_code = host_to_le16(reason); 55548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt, 55558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_HDRLEN + 55568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(mgmt.u.disassoc)); 55578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 55588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD || CONFIG_AP */ 55608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 55618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 55628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 556375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 556475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 556575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int i; 556675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int *old; 556775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 556875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d", 556975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen ifidx); 557075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen for (i = 0; i < drv->num_if_indices; i++) { 557175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (drv->if_indices[i] == 0) { 557275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices[i] = ifidx; 557375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return; 557475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 557575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 557675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 557775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (drv->if_indices != drv->default_if_indices) 557875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen old = drv->if_indices; 557975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen else 558075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen old = NULL; 558175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 558275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices = os_realloc(old, 558375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen sizeof(int) * (drv->num_if_indices + 1)); 558475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (!drv->if_indices) { 558575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (!old) 558675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices = drv->default_if_indices; 558775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen else 558875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices = old; 558975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_ERROR, "Failed to reallocate memory for " 559075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen "interfaces"); 559175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx); 559275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return; 559375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } else if (!old) 559475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen os_memcpy(drv->if_indices, drv->default_if_indices, 559575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen sizeof(drv->default_if_indices)); 559675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices[drv->num_if_indices] = ifidx; 559775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->num_if_indices++; 559875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 559975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 560075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 560175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 560275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 560375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int i; 560475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 560575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen for (i = 0; i < drv->num_if_indices; i++) { 560675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (drv->if_indices[i] == ifidx) { 560775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv->if_indices[i] = 0; 560875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen break; 560975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 561075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 561175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 561275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 561375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 561475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx) 561575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 561675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int i; 561775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 561875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen for (i = 0; i < drv->num_if_indices; i++) 561975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (drv->if_indices[i] == ifidx) 562075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return 1; 562175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 562275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return 0; 562375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 562475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 562575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 562675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val, 562775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen const char *bridge_ifname) 562875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 562975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct i802_bss *bss = priv; 563075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct wpa_driver_nl80211_data *drv = bss->drv; 563175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen char name[IFNAMSIZ + 1]; 563275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 563375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid); 563475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR 563575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name); 563675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (val) { 563775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (!if_nametoindex(name)) { 563875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (nl80211_create_iface(drv, name, 563975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen NL80211_IFTYPE_AP_VLAN, 564075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen NULL, 1) < 0) 564175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return -1; 564275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (bridge_ifname && 564375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen linux_br_add_if(drv->ioctl_sock, bridge_ifname, 564475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen name) < 0) 564575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return -1; 564675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 564775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen linux_set_iface_flags(drv->ioctl_sock, name, 1); 564875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return i802_set_sta_vlan(priv, addr, name, 0); 564975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } else { 565075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen i802_set_sta_vlan(priv, addr, bss->ifname, 0); 565175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN, 565275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen name); 565375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 565475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 565575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 565675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 565775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) 565875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 565975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct wpa_driver_nl80211_data *drv = eloop_ctx; 566075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct sockaddr_ll lladdr; 566175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen unsigned char buf[3000]; 566275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen int len; 566375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen socklen_t fromlen = sizeof(lladdr); 566475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 566575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen len = recvfrom(sock, buf, sizeof(buf), 0, 566675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen (struct sockaddr *)&lladdr, &fromlen); 566775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (len < 0) { 566875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen perror("recv"); 566975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return; 567075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen } 567175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 567275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (have_ifidx(drv, lladdr.sll_ifindex)) 567375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len); 567475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 567575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 567675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 56778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int i802_check_bridge(struct wpa_driver_nl80211_data *drv, 56788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss, 56798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *brname, const char *ifname) 56808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 56818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex; 56828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char in_br[IFNAMSIZ]; 56838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 56848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(bss->brname, brname, IFNAMSIZ); 56858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifindex = if_nametoindex(brname); 56868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifindex == 0) { 56878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 56888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Bridge was configured, but the bridge device does 56898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not exist. Try to add it now. 56908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 56918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_add(drv->ioctl_sock, brname) < 0) { 56928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to add the " 56938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bridge interface %s: %s", 56948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brname, strerror(errno)); 56958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 56968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 56978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->added_bridge = 1; 56988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, if_nametoindex(brname)); 56998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_get(in_br, ifname) == 0) { 57028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strcmp(in_br, brname) == 0) 57038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; /* already in the bridge */ 57048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from " 57068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bridge %s", ifname, in_br); 57078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_del_if(drv->ioctl_sock, in_br, ifname) < 0) { 57088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to " 57098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "remove interface %s from bridge " 57108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%s: %s", 57118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, brname, strerror(errno)); 57128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 57138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s", 57178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, brname); 57188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_add_if(drv->ioctl_sock, brname, ifname) < 0) { 57198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s " 57208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "into bridge %s: %s", 57218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifname, brname, strerror(errno)); 57228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 57238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->added_if_into_bridge = 1; 57258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 57278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 57288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void *i802_init(struct hostapd_data *hapd, 57318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_init_params *params) 57328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 57338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 57348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss; 57358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 57368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char brname[IFNAMSIZ]; 57378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, br_ifindex; 57388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int br_added = 0; 57398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss = wpa_driver_nl80211_init(hapd, params->ifname, NULL); 57418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss == NULL) 57428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 57438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv = bss->drv; 57458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nlmode = NL80211_IFTYPE_AP; 57468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_get(brname, params->ifname) == 0) { 57478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s", 57488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->ifname, brname); 57498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt br_ifindex = if_nametoindex(brname); 57508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 57518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt brname[0] = '\0'; 57528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt br_ifindex = 0; 57538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int); 57568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->if_indices = drv->default_if_indices; 57578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < params->num_bridge; i++) { 57588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->bridge[i]) { 57598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifindex = if_nametoindex(params->bridge[i]); 57608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifindex) 57618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, ifindex); 57628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifindex == br_ifindex) 57638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt br_added = 1; 57648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!br_added && br_ifindex && 57678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (params->num_bridge == 0 || !params->bridge[0])) 57688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, br_ifindex); 57698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* start listening for EAPOL on the default AP interface */ 57718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add_ifidx(drv, drv->ifindex); 57728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0)) 57748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 57758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->bssid) { 57778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_ifhwaddr(drv->ioctl_sock, bss->ifname, 57788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params->bssid)) 57798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 57808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_AP)) { 57838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s " 57848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "into AP mode", bss->ifname); 57858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 57868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 57878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params->num_bridge && params->bridge[0] && 57898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0) 57908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 57918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) 57938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 57948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 57958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); 57968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->eapol_sock < 0) { 57978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)"); 57988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 57998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 58008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL)) 58028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 58038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt printf("Could not register read socket for eapol\n"); 58048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 58058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 58068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, params->own_addr)) 58088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 58098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return bss; 58118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 58138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_monitor_interface(drv); 58148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rfkill_deinit(drv->rfkill); 58158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt netlink_deinit(drv->netlink); 58168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->ioctl_sock >= 0) 58178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(drv->ioctl_sock); 58188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genl_family_put(drv->nl80211); 58208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cache_free(drv->nl_cache); 58218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_handle_destroy(drv->nl_handle); 58228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cb_put(drv->nl_cb); 58238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event)); 58248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(drv); 58268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 58278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 58288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void i802_deinit(void *priv) 58318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 58328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_deinit(priv); 58338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 58348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 58368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic enum nl80211_iftype wpa_driver_nl80211_if_type( 58398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_driver_if_type type) 58408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 58418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (type) { 58428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_STATION: 58438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_STATION; 58448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_P2P_CLIENT: 58458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_P2P_GROUP: 58468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_P2P_CLIENT; 58478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_AP_VLAN: 58488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_AP_VLAN; 58498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_AP_BSS: 58508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_AP; 58518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_IF_P2P_GO: 58528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL80211_IFTYPE_P2P_GO; 58538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 58548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 58558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 58568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 58598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr) 58618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 58628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv; 58638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_for_each(drv, &global->interfaces, 58648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data, list) { 58658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(addr, drv->addr, ETH_ALEN) == 0) 58668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 58678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 58688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 58698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 58708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv, 58738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *new_addr) 58748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 58758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int idx; 58768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->global) 58788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 58798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(new_addr, drv->addr, ETH_ALEN); 58818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (idx = 0; idx < 64; idx++) { 58828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_addr[0] = drv->addr[0] | 0x02; 58838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_addr[0] ^= idx << 2; 58848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!nl80211_addr_in_use(drv->global, new_addr)) 58858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 58868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 58878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (idx == 64) 58888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 58898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Assigned new P2P Interface Address " 58918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, MAC2STR(new_addr)); 58928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 58948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 58958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 58978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 58998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type, 59008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname, const u8 *addr, 59018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *bss_ctx, void **drv_priv, 59028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *force_ifname, u8 *if_addr, 59038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *bridge) 59048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 59058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 59068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 59078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifidx; 59088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 59098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *new_bss = NULL; 59108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type == WPA_IF_AP_BSS) { 59128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_bss = os_zalloc(sizeof(*new_bss)); 59138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (new_bss == NULL) 59148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 59178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (addr) 59198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(if_addr, addr, ETH_ALEN); 59208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifidx = nl80211_create_iface(drv, ifname, 59218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_if_type(type), addr, 59228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0); 59238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifidx < 0) { 59248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 59258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(new_bss); 59268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 59278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!addr && 59318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, if_addr) < 0) { 59328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 59338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 59378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!addr && 59388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP || 59398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type == WPA_IF_P2P_GO)) { 59408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Enforce unique P2P Interface Address */ 59418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 new_addr[ETH_ALEN], own_addr[ETH_ALEN]; 59428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr) 59448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0 || 59458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt linux_get_ifhwaddr(drv->ioctl_sock, ifname, new_addr) < 0) 59468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 59478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 59488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(own_addr, new_addr, ETH_ALEN) == 0) { 59518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Allocate new address " 59528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for P2P group interface"); 59538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_p2p_interface_addr(drv, new_addr) < 0) { 59548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 59558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_ifhwaddr(drv->ioctl_sock, ifname, 59588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_addr) < 0) { 59598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 59608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(if_addr, new_addr, ETH_ALEN); 59638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 59668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 59688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bridge && 59698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i802_check_bridge(drv, new_bss, bridge, ifname) < 0) { 59708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to add the new " 59718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface %s to a bridge %s", ifname, bridge); 59728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 59738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(new_bss); 59748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type == WPA_IF_AP_BSS) { 59788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) { 59798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifidx); 59808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(new_bss); 59818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 59828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ); 59848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_bss->ifindex = ifidx; 59858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_bss->drv = drv; 59868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_bss->next = drv->first_bss.next; 59878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->first_bss.next = new_bss; 59888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv_priv) 59898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *drv_priv = new_bss; 59908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 59918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 59928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 59948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 59958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 59978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_if_remove(void *priv, 59988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_driver_if_type type, 59998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *ifname) 60008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 60018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 60028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 60038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex = if_nametoindex(ifname); 60048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d", 60068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt __func__, type, ifname, ifindex); 60078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ifindex <= 0) 60088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 60098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 60118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss->added_if_into_bridge) { 60128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname) 60138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 60148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to remove " 60158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface %s from bridge %s: %s", 60168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->ifname, bss->brname, strerror(errno)); 60178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss->added_bridge) { 60198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_br_del(drv->ioctl_sock, bss->brname) < 0) 60208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: Failed to remove " 60218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "bridge %s: %s", 60228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss->brname, strerror(errno)); 60238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 60258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_remove_iface(drv, ifindex); 60278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 60298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type != WPA_IF_AP_BSS) 60308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 60318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss != &drv->first_bss) { 60338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *tbss; 60348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (tbss = &drv->first_bss; tbss; tbss = tbss->next) { 60368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tbss->next == bss) { 60378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tbss->next = bss->next; 60388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(bss); 60398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bss = NULL; 60408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 60418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss) 60448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "nl80211: %s - could not find " 60458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BSS %p in the list", __func__, bss); 60468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD */ 60488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 60508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 60518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int cookie_handler(struct nl_msg *msg, void *arg) 60548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 60558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *tb[NL80211_ATTR_MAX + 1]; 60568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 60578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 *cookie = arg; 60588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 60598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_attrlen(gnlh, 0), NULL); 60608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tb[NL80211_ATTR_COOKIE]) 60618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]); 60628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NL_SKIP; 60638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 60648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, 60678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int freq, unsigned int wait, 60688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t buf_len, 60698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 *cookie_out) 60708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 60718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 60728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 cookie; 60738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 60748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 60768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 60778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 60788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 60808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_FRAME, 0); 60818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 60838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); 60848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait); 60858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); 60868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf); 60878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie = 0; 60898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); 60908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 60918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 60928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d " 60938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 60948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 60958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 60968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted; " 60978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "cookie 0x%llx", (long long unsigned int) cookie); 60988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cookie_out) 61008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *cookie_out = cookie; 61018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 61038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 61048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 61058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 61068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_send_action(void *priv, unsigned int freq, 61098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int wait_time, 61108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *dst, const u8 *src, 61118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *bssid, 61128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t data_len) 61138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 61148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 61158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 61168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret = -1; 61178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; 61188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee80211_hdr *hdr; 61198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, " 61218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "wait=%d ms)", drv->ifindex, wait_time); 61228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(24 + data_len); 61248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf == NULL) 61258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 61268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf + 24, data, data_len); 61278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct ieee80211_hdr *) buf; 61288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->frame_control = 61298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); 61308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr->addr1, dst, ETH_ALEN); 61318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr->addr2, src, ETH_ALEN); 61328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(hdr->addr3, bssid, ETH_ALEN); 61338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode == NL80211_IFTYPE_AP) 61358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len); 61368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 61378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf, 61388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 24 + data_len, 61398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &drv->send_action_cookie); 61408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 61428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 61438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 61448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_send_action_cancel_wait(void *priv) 61478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 61488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 61498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 61508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 61518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 61528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 61548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 61558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 61568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 61588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_FRAME_WAIT_CANCEL, 0); 61598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 61618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie); 61628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 61648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 61658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 61668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d " 61678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 61688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 61708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 61718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 61728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq, 61758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int duration) 61768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 61778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 61788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 61798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 61808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 61818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u64 cookie; 61828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 61848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 61858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 61868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 61888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_REMAIN_ON_CHANNEL, 0); 61898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 61918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); 61928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration); 61938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cookie = 0; 61958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); 61968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) { 61978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie " 61988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "0x%llx for freq=%u MHz duration=%u", 61998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long long unsigned int) cookie, freq, duration); 62008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->remain_on_chan_cookie = cookie; 62018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 62028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel " 62048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(freq=%d duration=%u): %d (%s)", 62058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt freq, duration, ret, strerror(-ret)); 62068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 62078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 62098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_cancel_remain_on_channel(void *priv) 62128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 62138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 62148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 62158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 62168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 62178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!drv->pending_remain_on_chan) { 62198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel " 62208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "to cancel"); 62218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie " 62258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "0x%llx", 62268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (long long unsigned int) drv->remain_on_chan_cookie); 62278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 62298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 62308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 62338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, 0); 62348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); 62368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie); 62378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 62398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret == 0) 62408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 62418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: " 62428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d (%s)", ret, strerror(-ret)); 62438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 62448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 62468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_probe_req_report(void *priv, int report) 62498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 62508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 62518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 62528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode != NL80211_IFTYPE_STATION) { 62548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only " 62558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "allowed in station mode (iftype=%d)", 62568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nlmode); 62578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!report) { 62618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_handle_preq) { 62628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock( 62638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_socket_get_fd(drv->nl_handle_preq)); 62648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cache_free(drv->nl_cache_preq); 62658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_handle_destroy(drv->nl_handle_preq); 62668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_handle_preq = NULL; 62678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 62698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_handle_preq) { 62728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting " 62738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "already on!"); 62748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 62758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_handle_preq = nl80211_handle_alloc(drv->nl_cb); 62788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_handle_preq == NULL) { 62798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate " 62808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink callbacks (preq)"); 62818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out_err1; 62828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (genl_connect(drv->nl_handle_preq)) { 62858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to connect to " 62868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "generic netlink (preq)"); 62878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out_err2; 62888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 62898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 62918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_LIBNL20 62928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (genl_ctrl_alloc_cache(drv->nl_handle_preq, 62938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &drv->nl_cache_preq) < 0) { 62948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " 62958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink cache (preq)"); 62968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out_err2; 62978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 62988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_LIBNL20 */ 62998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_cache_preq = genl_ctrl_alloc_cache(drv->nl_handle_preq); 63008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nl_cache_preq == NULL) { 63018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic " 63028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "netlink cache (preq)"); 63038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out_err2; 63048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 63058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_LIBNL20 */ 63068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nl80211_register_frame(drv, drv->nl_handle_preq, 63088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WLAN_FC_TYPE_MGMT << 2) | 63098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WLAN_FC_STYPE_PROBE_REQ << 4), 63108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0) < 0) { 63118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto out_err3; 63128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 63138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_preq), 63158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_event_receive, drv, 63168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_handle_preq); 63178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 63198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_err3: 63218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl_cache_free(drv->nl_cache_preq); 63228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_err2: 63238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nl80211_handle_destroy(drv->nl_handle_preq); 63248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->nl_handle_preq = NULL; 63258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_err1: 63268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 63288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, 63318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex, int disabled) 63328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 63338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 63348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nlattr *bands, *band; 63358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 63368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 63388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 63398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 63428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_SET_TX_BITRATE_MASK, 0); 63438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); 63448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES); 63468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!bands) 63478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 63488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 63508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything 63518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS 63528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rates. All 5 GHz rates are left enabled. 63538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 63548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt band = nla_nest_start(msg, NL80211_BAND_2GHZ); 63558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!band) 63568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto nla_put_failure; 63578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT(msg, NL80211_TXRATE_LEGACY, 8, 63588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "\x0c\x12\x18\x24\x30\x48\x60\x6c"); 63598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, band); 63608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_nest_end(msg, bands); 63628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = send_and_recv_msgs(drv, msg, NULL, NULL); 63648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 63658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) { 63668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d " 63678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s)", ret, strerror(-ret)); 63688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 63698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 63718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 63738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 63748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 63768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_disable_11b_rates(void *priv, int disabled) 63798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 63808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 63818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 63828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->disable_11b_rates = disabled; 63838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return nl80211_disable_11b_rates(drv, drv->ifindex, disabled); 63848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 63858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_deinit_ap(void *priv) 63888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 63898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 63908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 63918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (drv->nlmode != NL80211_IFTYPE_AP) 63928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 63938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_del_beacon(drv); 63948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA); 63958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 63968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 63988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_resume(void *priv) 63998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 64008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 64018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 64028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) { 64038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on " 64048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "resume event"); 64058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 64068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 64078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap, 64108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ies, size_t ies_len) 64118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 64128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 64138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 64148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 64158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *data, *pos; 64168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len; 64178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 own_addr[ETH_ALEN]; 64188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr) < 0) 64208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 64218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action != 1) { 64238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action " 64248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "action %d", action); 64258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 64268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 64278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 64298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Action frame payload: 64308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Category[1] = 6 (Fast BSS Transition) 64318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Action[1] = 1 (Fast BSS Transition Request) 64328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * STA Address 64338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Target AP Address 64348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FT IEs 64358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 64368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len = 2 + 2 * ETH_ALEN + ies_len; 64388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_malloc(data_len); 64398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 64408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 64418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = data; 64428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0x06; /* FT Action category */ 64438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = action; 64448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, own_addr, ETH_ALEN); 64458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 64468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, target_ap, ETH_ALEN); 64478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 64488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ies, ies_len); 64498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0, 64518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->bssid, own_addr, drv->bssid, 64528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data, data_len); 64538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 64548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 64568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 64578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_signal_monitor(void *priv, int threshold, int hysteresis) 64608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 64618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 64628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 64638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg, *cqm = NULL; 64648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d " 64668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hysteresis=%d", threshold, hysteresis); 64678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 64698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 64708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 64718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 64738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, NL80211_CMD_SET_CQM, 0); 64748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex); 64768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cqm = nlmsg_alloc(); 64788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cqm == NULL) 64798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 64808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, threshold); 64828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hysteresis); 64838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_nested(msg, NL80211_ATTR_CQM, cqm); 64848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) 64868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 64878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = NULL; 64888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtnla_put_failure: 64908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cqm) 64918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(cqm); 64928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nlmsg_free(msg); 64938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 64948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 64958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 64978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_signal_poll(void *priv, struct wpa_signal_info *si) 64988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 64998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 65008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 65018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 65028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(si, 0, sizeof(*si)); 65048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = nl80211_get_link_signal(drv, si); 65058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res != 0) 65068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 65078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return nl80211_get_link_noise(drv, si); 65098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_send_frame(void *priv, const u8 *data, size_t data_len, 65138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int encrypt) 65148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 65168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 65178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt); 65188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_set_intra_bss(void *priv, int enabled) 65228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 65248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 65258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl_msg *msg; 65268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = nlmsg_alloc(); 65288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!msg) 65298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOMEM; 65308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, 65328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NL80211_CMD_SET_BSS, 0); 65338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); 65358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, !enabled); 65368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return send_and_recv_msgs(drv, msg, NULL, NULL); 65388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nla_put_failure: 65398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -ENOBUFS; 65408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int nl80211_set_param(void *priv, const char *param) 65448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param); 65468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (param == NULL) 65478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 65488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 65508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strstr(param, "use_p2p_group_interface=1")) { 65518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 65528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 65538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group " 65558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "interface"); 65568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; 65578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P; 65588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 65598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 65608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 65628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * nl80211_global_init(void) 65668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_global *global; 65688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt global = os_zalloc(sizeof(*global)); 65698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global == NULL) 65708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 65718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_init(&global->interfaces); 65728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return global; 65738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_global_deinit(void *priv) 65778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct nl80211_global *global = priv; 65798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (global == NULL) 65808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 65818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!dl_list_empty(&global->interfaces)) { 65828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at " 65838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "nl80211_global_deinit", 65848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dl_list_len(&global->interfaces)); 65858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 65868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(global); 65878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const char * nl80211_get_radio_name(void *priv) 65918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 65928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct i802_bss *bss = priv; 65938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_nl80211_data *drv = bss->drv; 65948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return drv->phyname; 65958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 65968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 65978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 659875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid, 659975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen const u8 *pmkid) 660075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 660175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct nl_msg *msg; 660275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 660375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen msg = nlmsg_alloc(); 660475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (!msg) 660575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return -ENOMEM; 660675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 660775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen genlmsg_put(msg, 0, 0, genl_family_get_id(bss->drv->nl80211), 0, 0, 660875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen cmd, 0); 660975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 661075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname)); 661175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (pmkid) 661275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen NLA_PUT(msg, NL80211_ATTR_PMKID, 16, pmkid); 661375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen if (bssid) 661475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid); 661575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 661675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return send_and_recv_msgs(bss->drv, msg, NULL, NULL); 661775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen nla_put_failure: 661875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return -ENOBUFS; 661975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 662075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 662175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 662275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid) 662375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 662475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct i802_bss *bss = priv; 662575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR, MAC2STR(bssid)); 662675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid); 662775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 662875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 662975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 663075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int nl80211_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid) 663175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 663275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct i802_bss *bss = priv; 663375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR, 663475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen MAC2STR(bssid)); 663575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid); 663675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 663775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 663875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 663975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int nl80211_flush_pmkid(void *priv) 664075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{ 664175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen struct i802_bss *bss = priv; 664275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs"); 664375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen return nl80211_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL); 664475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen} 664575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 664675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen 66478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst struct wpa_driver_ops wpa_driver_nl80211_ops = { 66488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .name = "nl80211", 66498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .desc = "Linux nl80211/cfg80211", 66508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_bssid = wpa_driver_nl80211_get_bssid, 66518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_ssid = wpa_driver_nl80211_get_ssid, 66528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_key = wpa_driver_nl80211_set_key, 66538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .scan2 = wpa_driver_nl80211_scan, 66548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_scan_results2 = wpa_driver_nl80211_get_scan_results, 66558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .deauthenticate = wpa_driver_nl80211_deauthenticate, 66568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .disassociate = wpa_driver_nl80211_disassociate, 66578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .authenticate = wpa_driver_nl80211_authenticate, 66588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .associate = wpa_driver_nl80211_associate, 66598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .global_init = nl80211_global_init, 66608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .global_deinit = nl80211_global_deinit, 66618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .init2 = wpa_driver_nl80211_init, 66628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .deinit = wpa_driver_nl80211_deinit, 66638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_capa = wpa_driver_nl80211_get_capa, 66648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_operstate = wpa_driver_nl80211_set_operstate, 66658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_supp_port = wpa_driver_nl80211_set_supp_port, 66668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_country = wpa_driver_nl80211_set_country, 66678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_beacon = wpa_driver_nl80211_set_beacon, 66688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .if_add = wpa_driver_nl80211_if_add, 66698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .if_remove = wpa_driver_nl80211_if_remove, 66708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .send_mlme = wpa_driver_nl80211_send_mlme, 66718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data, 66728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_add = wpa_driver_nl80211_sta_add, 66738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_remove = wpa_driver_nl80211_sta_remove, 66748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol, 66758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_set_flags = wpa_driver_nl80211_sta_set_flags, 66768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef HOSTAPD 66778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .hapd_init = i802_init, 66788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .hapd_deinit = i802_deinit, 667975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .set_wds_sta = i802_set_wds_sta, 668075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen#endif /* HOSTAPD */ 668175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen#if defined(HOSTAPD) || defined(CONFIG_AP) 66828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_seqnum = i802_get_seqnum, 66838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .flush = i802_flush, 66848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .read_sta_data = i802_read_sta_data, 66858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_inact_sec = i802_get_inact_sec, 66868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_clear_stats = i802_sta_clear_stats, 66878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_rts = i802_set_rts, 66888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_frag = i802_set_frag, 66898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_cts_protect = i802_set_cts_protect, 66908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_preamble = i802_set_preamble, 66918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_short_slot_time = i802_set_short_slot_time, 66928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_tx_queue_params = i802_set_tx_queue_params, 66938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_sta_vlan = i802_set_sta_vlan, 66948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_ht_params = i802_set_ht_params, 669575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .set_rate_sets = i802_set_rate_sets, 66968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_deauth = i802_sta_deauth, 66978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .sta_disassoc = i802_sta_disassoc, 66988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* HOSTAPD || CONFIG_AP */ 66998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_freq = i802_set_freq, 67008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .send_action = wpa_driver_nl80211_send_action, 67018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait, 67028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .remain_on_channel = wpa_driver_nl80211_remain_on_channel, 67038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .cancel_remain_on_channel = 67048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_driver_nl80211_cancel_remain_on_channel, 67058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .probe_req_report = wpa_driver_nl80211_probe_req_report, 67068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .disable_11b_rates = wpa_driver_nl80211_disable_11b_rates, 67078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .deinit_ap = wpa_driver_nl80211_deinit_ap, 67088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .resume = wpa_driver_nl80211_resume, 67098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .send_ft_action = nl80211_send_ft_action, 67108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .signal_monitor = nl80211_signal_monitor, 67118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .signal_poll = nl80211_signal_poll, 67128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .send_frame = nl80211_send_frame, 67138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_intra_bss = nl80211_set_intra_bss, 67148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .set_param = nl80211_set_param, 67158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt .get_radio_name = nl80211_get_radio_name, 671675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .add_pmkid = nl80211_add_pmkid, 671775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .remove_pmkid = nl80211_remove_pmkid, 671875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen .flush_pmkid = nl80211_flush_pmkid, 6719738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt#ifdef ANDROID 6720738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt .driver_cmd = wpa_driver_nl80211_driver_cmd, 6721738a26e9e2087b0d43eba3534535632b27b49947Dmitry Shmidt#endif 67228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 6723