blob: 8ebf7d9cbdcb5c9761da567db57ceafee51d826c [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Driver interaction with Linux nl80211/cfg80211
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003 * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 * Copyright (c) 2003-2004, Instant802 Networks, Inc.
5 * Copyright (c) 2005-2006, Devicescape Software, Inc.
6 * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
7 * Copyright (c) 2009-2010, Atheros Communications
8 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009 * This software may be distributed under the terms of the BSD license.
10 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011 */
12
13#include "includes.h"
14#include <sys/ioctl.h>
15#include <sys/types.h>
16#include <sys/stat.h>
17#include <fcntl.h>
18#include <net/if.h>
19#include <netlink/genl/genl.h>
20#include <netlink/genl/family.h>
21#include <netlink/genl/ctrl.h>
22#include <linux/rtnetlink.h>
23#include <netpacket/packet.h>
24#include <linux/filter.h>
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080025#include <linux/errqueue.h>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "nl80211_copy.h"
27
28#include "common.h"
29#include "eloop.h"
30#include "utils/list.h"
Dmitry Shmidtcf32e602014-01-28 10:57:39 -080031#include "common/qca-vendor.h"
Dmitry Shmidt7832adb2014-04-29 10:53:02 -070032#include "common/qca-vendor-attr.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070033#include "common/ieee802_11_defs.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080034#include "common/ieee802_11_common.h"
35#include "l2_packet/l2_packet.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070036#include "netlink.h"
37#include "linux_ioctl.h"
38#include "radiotap.h"
39#include "radiotap_iter.h"
40#include "rfkill.h"
41#include "driver.h"
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080042
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080043#ifndef SO_WIFI_STATUS
44# if defined(__sparc__)
45# define SO_WIFI_STATUS 0x0025
46# elif defined(__parisc__)
47# define SO_WIFI_STATUS 0x4022
48# else
49# define SO_WIFI_STATUS 41
50# endif
51
52# define SCM_WIFI_STATUS SO_WIFI_STATUS
53#endif
54
55#ifndef SO_EE_ORIGIN_TXSTATUS
56#define SO_EE_ORIGIN_TXSTATUS 4
57#endif
58
59#ifndef PACKET_TX_TIMESTAMP
60#define PACKET_TX_TIMESTAMP 16
61#endif
62
63#ifdef ANDROID
64#include "android_drv.h"
65#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070066#ifdef CONFIG_LIBNL20
67/* libnl 2.0 compatibility code */
68#define nl_handle nl_sock
69#define nl80211_handle_alloc nl_socket_alloc_cb
70#define nl80211_handle_destroy nl_socket_free
71#else
72/*
73 * libnl 1.1 has a bug, it tries to allocate socket numbers densely
74 * but when you free a socket again it will mess up its bitmap and
75 * and use the wrong number the next time it needs a socket ID.
76 * Therefore, we wrap the handle alloc/destroy and add our own pid
77 * accounting.
78 */
79static uint32_t port_bitmap[32] = { 0 };
80
81static struct nl_handle *nl80211_handle_alloc(void *cb)
82{
83 struct nl_handle *handle;
84 uint32_t pid = getpid() & 0x3FFFFF;
85 int i;
86
87 handle = nl_handle_alloc_cb(cb);
88
89 for (i = 0; i < 1024; i++) {
90 if (port_bitmap[i / 32] & (1 << (i % 32)))
91 continue;
92 port_bitmap[i / 32] |= 1 << (i % 32);
93 pid += i << 22;
94 break;
95 }
96
97 nl_socket_set_local_port(handle, pid);
98
99 return handle;
100}
101
102static void nl80211_handle_destroy(struct nl_handle *handle)
103{
104 uint32_t port = nl_socket_get_local_port(handle);
105
106 port >>= 22;
107 port_bitmap[port / 32] &= ~(1 << (port % 32));
108
109 nl_handle_destroy(handle);
110}
111#endif /* CONFIG_LIBNL20 */
112
113
Dmitry Shmidt54605472013-11-08 11:10:19 -0800114#ifdef ANDROID
115/* system/core/libnl_2 does not include nl_socket_set_nonblocking() */
116static int android_nl_socket_set_nonblocking(struct nl_handle *handle)
117{
118 return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
119}
120#undef nl_socket_set_nonblocking
121#define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h)
122#endif /* ANDROID */
123
124
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800125static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
126{
127 struct nl_handle *handle;
128
129 handle = nl80211_handle_alloc(cb);
130 if (handle == NULL) {
131 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
132 "callbacks (%s)", dbg);
133 return NULL;
134 }
135
136 if (genl_connect(handle)) {
137 wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
138 "netlink (%s)", dbg);
139 nl80211_handle_destroy(handle);
140 return NULL;
141 }
142
143 return handle;
144}
145
146
147static void nl_destroy_handles(struct nl_handle **handle)
148{
149 if (*handle == NULL)
150 return;
151 nl80211_handle_destroy(*handle);
152 *handle = NULL;
153}
154
155
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700156#if __WORDSIZE == 64
157#define ELOOP_SOCKET_INVALID (intptr_t) 0x8888888888888889ULL
158#else
159#define ELOOP_SOCKET_INVALID (intptr_t) 0x88888889ULL
160#endif
161
162static void nl80211_register_eloop_read(struct nl_handle **handle,
163 eloop_sock_handler handler,
164 void *eloop_data)
165{
166 nl_socket_set_nonblocking(*handle);
167 eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
168 eloop_data, *handle);
169 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
170}
171
172
173static void nl80211_destroy_eloop_handle(struct nl_handle **handle)
174{
175 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
176 eloop_unregister_read_sock(nl_socket_get_fd(*handle));
177 nl_destroy_handles(handle);
178}
179
180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700181#ifndef IFF_LOWER_UP
182#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
183#endif
184#ifndef IFF_DORMANT
185#define IFF_DORMANT 0x20000 /* driver signals dormant */
186#endif
187
188#ifndef IF_OPER_DORMANT
189#define IF_OPER_DORMANT 5
190#endif
191#ifndef IF_OPER_UP
192#define IF_OPER_UP 6
193#endif
194
195struct nl80211_global {
196 struct dl_list interfaces;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800197 int if_add_ifindex;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700198 u64 if_add_wdevid;
199 int if_add_wdevid_set;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800200 struct netlink_data *netlink;
201 struct nl_cb *nl_cb;
202 struct nl_handle *nl;
203 int nl80211_id;
204 int ioctl_sock; /* socket for ioctl() use */
205
206 struct nl_handle *nl_event;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700207};
208
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800209struct nl80211_wiphy_data {
210 struct dl_list list;
211 struct dl_list bsss;
212 struct dl_list drvs;
213
214 struct nl_handle *nl_beacons;
215 struct nl_cb *nl_cb;
216
217 int wiphy_idx;
218};
219
220static void nl80211_global_deinit(void *priv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800221
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700222struct i802_bss {
223 struct wpa_driver_nl80211_data *drv;
224 struct i802_bss *next;
225 int ifindex;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700226 u64 wdev_id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700227 char ifname[IFNAMSIZ + 1];
228 char brname[IFNAMSIZ];
229 unsigned int beacon_set:1;
230 unsigned int added_if_into_bridge:1;
231 unsigned int added_bridge:1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700232 unsigned int in_deinit:1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700233 unsigned int wdev_id_set:1;
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800234 unsigned int added_if:1;
Dmitry Shmidt03658832014-08-13 11:03:49 -0700235 unsigned int static_ap:1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800236
237 u8 addr[ETH_ALEN];
238
239 int freq;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700240 int bandwidth;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -0700241 int if_dynamic;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800242
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800243 void *ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800244 struct nl_handle *nl_preq, *nl_mgmt;
245 struct nl_cb *nl_cb;
246
247 struct nl80211_wiphy_data *wiphy_data;
248 struct dl_list wiphy_list;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700249};
250
251struct wpa_driver_nl80211_data {
252 struct nl80211_global *global;
253 struct dl_list list;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800254 struct dl_list wiphy_list;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700255 char phyname[32];
256 void *ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257 int ifindex;
258 int if_removed;
259 int if_disabled;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800260 int ignore_if_down_event;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700261 struct rfkill_data *rfkill;
262 struct wpa_driver_capa capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -0700263 u8 *extended_capa, *extended_capa_mask;
264 unsigned int extended_capa_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700265 int has_capability;
266
267 int operstate;
268
269 int scan_complete_events;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700270 enum scan_states {
271 NO_SCAN, SCAN_REQUESTED, SCAN_STARTED, SCAN_COMPLETED,
272 SCAN_ABORTED, SCHED_SCAN_STARTED, SCHED_SCAN_STOPPED,
273 SCHED_SCAN_RESULTS
274 } scan_state;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276 struct nl_cb *nl_cb;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700277
278 u8 auth_bssid[ETH_ALEN];
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700279 u8 auth_attempt_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700280 u8 bssid[ETH_ALEN];
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700281 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700282 int associated;
283 u8 ssid[32];
284 size_t ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800285 enum nl80211_iftype nlmode;
286 enum nl80211_iftype ap_scan_as_station;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700287 unsigned int assoc_freq;
288
289 int monitor_sock;
290 int monitor_ifidx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800291 int monitor_refcount;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700292
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800293 unsigned int disabled_11b_rates:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700294 unsigned int pending_remain_on_chan:1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800295 unsigned int in_interface_list:1;
296 unsigned int device_ap_sme:1;
297 unsigned int poll_command_supported:1;
298 unsigned int data_tx_status:1;
299 unsigned int scan_for_auth:1;
300 unsigned int retry_auth:1;
301 unsigned int use_monitor:1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800302 unsigned int ignore_next_local_disconnect:1;
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -0700303 unsigned int ignore_next_local_deauth:1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700304 unsigned int allow_p2p_device:1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800305 unsigned int hostapd:1;
306 unsigned int start_mode_ap:1;
307 unsigned int start_iface_up:1;
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -0800308 unsigned int test_use_roc_tx:1;
Dmitry Shmidt98660862014-03-11 17:26:21 -0700309 unsigned int ignore_deauth_event:1;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -0700310 unsigned int dfs_vendor_cmd_avail:1;
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -0700311 unsigned int have_low_prio_scan:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700312
313 u64 remain_on_chan_cookie;
314 u64 send_action_cookie;
315
316 unsigned int last_mgmt_freq;
317
318 struct wpa_driver_scan_filter *filter_ssids;
319 size_t num_filter_ssids;
320
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800321 struct i802_bss *first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700322
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800323 int eapol_tx_sock;
324
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700325 int eapol_sock; /* socket for EAPOL frames */
326
327 int default_if_indices[16];
328 int *if_indices;
329 int num_if_indices;
330
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800331 /* From failed authentication command */
332 int auth_freq;
333 u8 auth_bssid_[ETH_ALEN];
334 u8 auth_ssid[32];
335 size_t auth_ssid_len;
336 int auth_alg;
337 u8 *auth_ie;
338 size_t auth_ie_len;
339 u8 auth_wep_key[4][16];
340 size_t auth_wep_key_len[4];
341 int auth_wep_tx_keyidx;
342 int auth_local_state_change;
343 int auth_p2p;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700344};
345
346
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800347static void wpa_driver_nl80211_deinit(struct i802_bss *bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700348static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
349 void *timeout_ctx);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800350static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
351 enum nl80211_iftype nlmode);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700352static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, int freq);
353
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800355wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
356 const u8 *set_addr, int first);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700357static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
358 const u8 *addr, int cmd, u16 reason_code,
359 int local_state_change);
360static void nl80211_remove_monitor_interface(
361 struct wpa_driver_nl80211_data *drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800362static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700363 unsigned int freq, unsigned int wait,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800364 const u8 *buf, size_t buf_len, u64 *cookie,
365 int no_cck, int no_ack, int offchanok);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700366static int nl80211_register_frame(struct i802_bss *bss,
367 struct nl_handle *hl_handle,
368 u16 type, const u8 *match, size_t match_len);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800369static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
370 int report);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800371#ifdef ANDROID
372static int android_pno_start(struct i802_bss *bss,
373 struct wpa_driver_scan_params *params);
374static int android_pno_stop(struct i802_bss *bss);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -0800375extern int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
376 size_t buf_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800377#endif /* ANDROID */
378#ifdef ANDROID_P2P
Dmitry Shmidtb58836e2014-04-29 14:35:56 -0700379#ifdef ANDROID_P2P_STUB
380int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) {
381 return 0;
382}
383int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) {
384 return 0;
385}
386int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) {
387 return -1;
388}
389int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
390 const struct wpabuf *proberesp,
391 const struct wpabuf *assocresp) {
392 return 0;
393}
394#else /* ANDROID_P2P_STUB */
Dmitry Shmidt6e933c12011-09-27 12:29:26 -0700395int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800396int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -0700397int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow);
398int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -0800399 const struct wpabuf *proberesp,
400 const struct wpabuf *assocresp);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -0700401#endif /* ANDROID_P2P_STUB */
Dmitry Shmidt292b0c32013-11-22 12:54:42 -0800402#endif /* ANDROID_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700403
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700404static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
405static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
406static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800407static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700408 enum wpa_driver_if_type type,
409 const char *ifname);
Dmitry Shmidt738a26e2011-07-07 14:22:14 -0700410
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700411static int nl80211_set_channel(struct i802_bss *bss,
412 struct hostapd_freq_params *freq, int set_chan);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700413static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
414 int ifindex, int disabled);
415
416static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800417static int wpa_driver_nl80211_authenticate_retry(
418 struct wpa_driver_nl80211_data *drv);
419
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700420static int i802_set_freq(void *priv, struct hostapd_freq_params *freq);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -0700421static int i802_set_iface_flags(struct i802_bss *bss, int up);
422
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800423
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700424static const char * nl80211_command_to_string(enum nl80211_commands cmd)
425{
426#define C2S(x) case x: return #x;
427 switch (cmd) {
428 C2S(NL80211_CMD_UNSPEC)
429 C2S(NL80211_CMD_GET_WIPHY)
430 C2S(NL80211_CMD_SET_WIPHY)
431 C2S(NL80211_CMD_NEW_WIPHY)
432 C2S(NL80211_CMD_DEL_WIPHY)
433 C2S(NL80211_CMD_GET_INTERFACE)
434 C2S(NL80211_CMD_SET_INTERFACE)
435 C2S(NL80211_CMD_NEW_INTERFACE)
436 C2S(NL80211_CMD_DEL_INTERFACE)
437 C2S(NL80211_CMD_GET_KEY)
438 C2S(NL80211_CMD_SET_KEY)
439 C2S(NL80211_CMD_NEW_KEY)
440 C2S(NL80211_CMD_DEL_KEY)
441 C2S(NL80211_CMD_GET_BEACON)
442 C2S(NL80211_CMD_SET_BEACON)
443 C2S(NL80211_CMD_START_AP)
444 C2S(NL80211_CMD_STOP_AP)
445 C2S(NL80211_CMD_GET_STATION)
446 C2S(NL80211_CMD_SET_STATION)
447 C2S(NL80211_CMD_NEW_STATION)
448 C2S(NL80211_CMD_DEL_STATION)
449 C2S(NL80211_CMD_GET_MPATH)
450 C2S(NL80211_CMD_SET_MPATH)
451 C2S(NL80211_CMD_NEW_MPATH)
452 C2S(NL80211_CMD_DEL_MPATH)
453 C2S(NL80211_CMD_SET_BSS)
454 C2S(NL80211_CMD_SET_REG)
455 C2S(NL80211_CMD_REQ_SET_REG)
456 C2S(NL80211_CMD_GET_MESH_CONFIG)
457 C2S(NL80211_CMD_SET_MESH_CONFIG)
458 C2S(NL80211_CMD_SET_MGMT_EXTRA_IE)
459 C2S(NL80211_CMD_GET_REG)
460 C2S(NL80211_CMD_GET_SCAN)
461 C2S(NL80211_CMD_TRIGGER_SCAN)
462 C2S(NL80211_CMD_NEW_SCAN_RESULTS)
463 C2S(NL80211_CMD_SCAN_ABORTED)
464 C2S(NL80211_CMD_REG_CHANGE)
465 C2S(NL80211_CMD_AUTHENTICATE)
466 C2S(NL80211_CMD_ASSOCIATE)
467 C2S(NL80211_CMD_DEAUTHENTICATE)
468 C2S(NL80211_CMD_DISASSOCIATE)
469 C2S(NL80211_CMD_MICHAEL_MIC_FAILURE)
470 C2S(NL80211_CMD_REG_BEACON_HINT)
471 C2S(NL80211_CMD_JOIN_IBSS)
472 C2S(NL80211_CMD_LEAVE_IBSS)
473 C2S(NL80211_CMD_TESTMODE)
474 C2S(NL80211_CMD_CONNECT)
475 C2S(NL80211_CMD_ROAM)
476 C2S(NL80211_CMD_DISCONNECT)
477 C2S(NL80211_CMD_SET_WIPHY_NETNS)
478 C2S(NL80211_CMD_GET_SURVEY)
479 C2S(NL80211_CMD_NEW_SURVEY_RESULTS)
480 C2S(NL80211_CMD_SET_PMKSA)
481 C2S(NL80211_CMD_DEL_PMKSA)
482 C2S(NL80211_CMD_FLUSH_PMKSA)
483 C2S(NL80211_CMD_REMAIN_ON_CHANNEL)
484 C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL)
485 C2S(NL80211_CMD_SET_TX_BITRATE_MASK)
486 C2S(NL80211_CMD_REGISTER_FRAME)
487 C2S(NL80211_CMD_FRAME)
488 C2S(NL80211_CMD_FRAME_TX_STATUS)
489 C2S(NL80211_CMD_SET_POWER_SAVE)
490 C2S(NL80211_CMD_GET_POWER_SAVE)
491 C2S(NL80211_CMD_SET_CQM)
492 C2S(NL80211_CMD_NOTIFY_CQM)
493 C2S(NL80211_CMD_SET_CHANNEL)
494 C2S(NL80211_CMD_SET_WDS_PEER)
495 C2S(NL80211_CMD_FRAME_WAIT_CANCEL)
496 C2S(NL80211_CMD_JOIN_MESH)
497 C2S(NL80211_CMD_LEAVE_MESH)
498 C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE)
499 C2S(NL80211_CMD_UNPROT_DISASSOCIATE)
500 C2S(NL80211_CMD_NEW_PEER_CANDIDATE)
501 C2S(NL80211_CMD_GET_WOWLAN)
502 C2S(NL80211_CMD_SET_WOWLAN)
503 C2S(NL80211_CMD_START_SCHED_SCAN)
504 C2S(NL80211_CMD_STOP_SCHED_SCAN)
505 C2S(NL80211_CMD_SCHED_SCAN_RESULTS)
506 C2S(NL80211_CMD_SCHED_SCAN_STOPPED)
507 C2S(NL80211_CMD_SET_REKEY_OFFLOAD)
508 C2S(NL80211_CMD_PMKSA_CANDIDATE)
509 C2S(NL80211_CMD_TDLS_OPER)
510 C2S(NL80211_CMD_TDLS_MGMT)
511 C2S(NL80211_CMD_UNEXPECTED_FRAME)
512 C2S(NL80211_CMD_PROBE_CLIENT)
513 C2S(NL80211_CMD_REGISTER_BEACONS)
514 C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME)
515 C2S(NL80211_CMD_SET_NOACK_MAP)
516 C2S(NL80211_CMD_CH_SWITCH_NOTIFY)
517 C2S(NL80211_CMD_START_P2P_DEVICE)
518 C2S(NL80211_CMD_STOP_P2P_DEVICE)
519 C2S(NL80211_CMD_CONN_FAILED)
520 C2S(NL80211_CMD_SET_MCAST_RATE)
521 C2S(NL80211_CMD_SET_MAC_ACL)
522 C2S(NL80211_CMD_RADAR_DETECT)
523 C2S(NL80211_CMD_GET_PROTOCOL_FEATURES)
524 C2S(NL80211_CMD_UPDATE_FT_IES)
525 C2S(NL80211_CMD_FT_EVENT)
526 C2S(NL80211_CMD_CRIT_PROTOCOL_START)
527 C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800528 C2S(NL80211_CMD_GET_COALESCE)
529 C2S(NL80211_CMD_SET_COALESCE)
530 C2S(NL80211_CMD_CHANNEL_SWITCH)
531 C2S(NL80211_CMD_VENDOR)
532 C2S(NL80211_CMD_SET_QOS_MAP)
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700533 default:
534 return "NL80211_CMD_UNKNOWN";
535 }
536#undef C2S
537}
538
539
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800540/* Converts nl80211_chan_width to a common format */
541static enum chan_width convert2width(int width)
542{
543 switch (width) {
544 case NL80211_CHAN_WIDTH_20_NOHT:
545 return CHAN_WIDTH_20_NOHT;
546 case NL80211_CHAN_WIDTH_20:
547 return CHAN_WIDTH_20;
548 case NL80211_CHAN_WIDTH_40:
549 return CHAN_WIDTH_40;
550 case NL80211_CHAN_WIDTH_80:
551 return CHAN_WIDTH_80;
552 case NL80211_CHAN_WIDTH_80P80:
553 return CHAN_WIDTH_80P80;
554 case NL80211_CHAN_WIDTH_160:
555 return CHAN_WIDTH_160;
556 }
557 return CHAN_WIDTH_UNKNOWN;
558}
559
560
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800561static int is_ap_interface(enum nl80211_iftype nlmode)
562{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700563 return nlmode == NL80211_IFTYPE_AP ||
564 nlmode == NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800565}
566
567
568static int is_sta_interface(enum nl80211_iftype nlmode)
569{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700570 return nlmode == NL80211_IFTYPE_STATION ||
571 nlmode == NL80211_IFTYPE_P2P_CLIENT;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800572}
573
574
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700575static int is_p2p_net_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800576{
Dmitry Shmidt7832adb2014-04-29 10:53:02 -0700577 return nlmode == NL80211_IFTYPE_P2P_CLIENT ||
578 nlmode == NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800579}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580
581
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700582static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
583{
584 if (drv->associated)
585 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
586 drv->associated = 0;
587 os_memset(drv->bssid, 0, ETH_ALEN);
588}
589
590
Jouni Malinen87fd2792011-05-16 18:35:42 +0300591struct nl80211_bss_info_arg {
592 struct wpa_driver_nl80211_data *drv;
593 struct wpa_scan_results *res;
594 unsigned int assoc_freq;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -0700595 unsigned int ibss_freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800596 u8 assoc_bssid[ETH_ALEN];
Jouni Malinen87fd2792011-05-16 18:35:42 +0300597};
598
599static int bss_info_handler(struct nl_msg *msg, void *arg);
600
601
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602/* nl80211 code */
603static int ack_handler(struct nl_msg *msg, void *arg)
604{
605 int *err = arg;
606 *err = 0;
607 return NL_STOP;
608}
609
610static int finish_handler(struct nl_msg *msg, void *arg)
611{
612 int *ret = arg;
613 *ret = 0;
614 return NL_SKIP;
615}
616
617static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
618 void *arg)
619{
620 int *ret = arg;
621 *ret = err->error;
622 return NL_SKIP;
623}
624
625
626static int no_seq_check(struct nl_msg *msg, void *arg)
627{
628 return NL_OK;
629}
630
631
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800632static int send_and_recv(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700633 struct nl_handle *nl_handle, struct nl_msg *msg,
634 int (*valid_handler)(struct nl_msg *, void *),
635 void *valid_data)
636{
637 struct nl_cb *cb;
638 int err = -ENOMEM;
639
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800640 cb = nl_cb_clone(global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700641 if (!cb)
642 goto out;
643
644 err = nl_send_auto_complete(nl_handle, msg);
645 if (err < 0)
646 goto out;
647
648 err = 1;
649
650 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
651 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
652 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
653
654 if (valid_handler)
655 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
656 valid_handler, valid_data);
657
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700658 while (err > 0) {
659 int res = nl_recvmsgs(nl_handle, cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -0700660 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700661 wpa_printf(MSG_INFO,
662 "nl80211: %s->nl_recvmsgs failed: %d",
663 __func__, res);
664 }
665 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700666 out:
667 nl_cb_put(cb);
668 nlmsg_free(msg);
669 return err;
670}
671
672
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800673static int send_and_recv_msgs_global(struct nl80211_global *global,
674 struct nl_msg *msg,
675 int (*valid_handler)(struct nl_msg *, void *),
676 void *valid_data)
677{
678 return send_and_recv(global, global->nl, msg, valid_handler,
679 valid_data);
680}
681
Dmitry Shmidt04949592012-07-19 12:16:46 -0700682
Dmitry Shmidt641185e2013-11-06 15:17:13 -0800683static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684 struct nl_msg *msg,
685 int (*valid_handler)(struct nl_msg *, void *),
686 void *valid_data)
687{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800688 return send_and_recv(drv->global, drv->global->nl, msg,
689 valid_handler, valid_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700690}
691
692
693struct family_data {
694 const char *group;
695 int id;
696};
697
698
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700699static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss)
700{
701 if (bss->wdev_id_set)
702 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
703 else
704 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
705 return 0;
706
707nla_put_failure:
708 return -1;
709}
710
711
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700712static int family_handler(struct nl_msg *msg, void *arg)
713{
714 struct family_data *res = arg;
715 struct nlattr *tb[CTRL_ATTR_MAX + 1];
716 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
717 struct nlattr *mcgrp;
718 int i;
719
720 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
721 genlmsg_attrlen(gnlh, 0), NULL);
722 if (!tb[CTRL_ATTR_MCAST_GROUPS])
723 return NL_SKIP;
724
725 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
726 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
727 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
728 nla_len(mcgrp), NULL);
729 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
730 !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
731 os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
732 res->group,
733 nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
734 continue;
735 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
736 break;
737 };
738
739 return NL_SKIP;
740}
741
742
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800743static int nl_get_multicast_id(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744 const char *family, const char *group)
745{
746 struct nl_msg *msg;
747 int ret = -1;
748 struct family_data res = { group, -ENOENT };
749
750 msg = nlmsg_alloc();
751 if (!msg)
752 return -ENOMEM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800753 genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700754 0, 0, CTRL_CMD_GETFAMILY, 0);
755 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
756
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800757 ret = send_and_recv_msgs_global(global, msg, family_handler, &res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700758 msg = NULL;
759 if (ret == 0)
760 ret = res.id;
761
762nla_put_failure:
763 nlmsg_free(msg);
764 return ret;
765}
766
767
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800768static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
769 struct nl_msg *msg, int flags, uint8_t cmd)
770{
771 return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
772 0, flags, cmd, 0);
773}
774
775
776struct wiphy_idx_data {
777 int wiphy_idx;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700778 enum nl80211_iftype nlmode;
779 u8 *macaddr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800780};
781
782
783static int netdev_info_handler(struct nl_msg *msg, void *arg)
784{
785 struct nlattr *tb[NL80211_ATTR_MAX + 1];
786 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
787 struct wiphy_idx_data *info = arg;
788
789 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
790 genlmsg_attrlen(gnlh, 0), NULL);
791
792 if (tb[NL80211_ATTR_WIPHY])
793 info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
794
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700795 if (tb[NL80211_ATTR_IFTYPE])
796 info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
797
798 if (tb[NL80211_ATTR_MAC] && info->macaddr)
799 os_memcpy(info->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
800 ETH_ALEN);
801
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800802 return NL_SKIP;
803}
804
805
806static int nl80211_get_wiphy_index(struct i802_bss *bss)
807{
808 struct nl_msg *msg;
809 struct wiphy_idx_data data = {
810 .wiphy_idx = -1,
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700811 .macaddr = NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800812 };
813
814 msg = nlmsg_alloc();
815 if (!msg)
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700816 return NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800817
818 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
819
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700820 if (nl80211_set_iface_id(msg, bss) < 0)
821 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800822
823 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
824 return data.wiphy_idx;
825 msg = NULL;
826nla_put_failure:
827 nlmsg_free(msg);
828 return -1;
829}
830
831
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700832static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
833{
834 struct nl_msg *msg;
835 struct wiphy_idx_data data = {
836 .nlmode = NL80211_IFTYPE_UNSPECIFIED,
837 .macaddr = NULL,
838 };
839
840 msg = nlmsg_alloc();
841 if (!msg)
842 return -1;
843
844 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
845
846 if (nl80211_set_iface_id(msg, bss) < 0)
847 goto nla_put_failure;
848
849 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
850 return data.nlmode;
851 msg = NULL;
852nla_put_failure:
853 nlmsg_free(msg);
854 return NL80211_IFTYPE_UNSPECIFIED;
855}
856
857
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700858static int nl80211_get_macaddr(struct i802_bss *bss)
859{
860 struct nl_msg *msg;
861 struct wiphy_idx_data data = {
862 .macaddr = bss->addr,
863 };
864
865 msg = nlmsg_alloc();
866 if (!msg)
867 return NL80211_IFTYPE_UNSPECIFIED;
868
869 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
870 if (nl80211_set_iface_id(msg, bss) < 0)
871 goto nla_put_failure;
872
873 return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data);
874
875nla_put_failure:
876 nlmsg_free(msg);
877 return NL80211_IFTYPE_UNSPECIFIED;
878}
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700879
880
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800881static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
882 struct nl80211_wiphy_data *w)
883{
884 struct nl_msg *msg;
885 int ret = -1;
886
887 msg = nlmsg_alloc();
888 if (!msg)
889 return -1;
890
891 nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS);
892
893 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx);
894
895 ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);
896 msg = NULL;
897 if (ret) {
898 wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
899 "failed: ret=%d (%s)",
900 ret, strerror(-ret));
901 goto nla_put_failure;
902 }
903 ret = 0;
904nla_put_failure:
905 nlmsg_free(msg);
906 return ret;
907}
908
909
910static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle)
911{
912 struct nl80211_wiphy_data *w = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700913 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800914
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800915 wpa_printf(MSG_EXCESSIVE, "nl80211: Beacon event message available");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800916
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700917 res = nl_recvmsgs(handle, w->nl_cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -0700918 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700919 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
920 __func__, res);
921 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800922}
923
924
925static int process_beacon_event(struct nl_msg *msg, void *arg)
926{
927 struct nl80211_wiphy_data *w = arg;
928 struct wpa_driver_nl80211_data *drv;
929 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
930 struct nlattr *tb[NL80211_ATTR_MAX + 1];
931 union wpa_event_data event;
932
933 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
934 genlmsg_attrlen(gnlh, 0), NULL);
935
936 if (gnlh->cmd != NL80211_CMD_FRAME) {
937 wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)",
938 gnlh->cmd);
939 return NL_SKIP;
940 }
941
942 if (!tb[NL80211_ATTR_FRAME])
943 return NL_SKIP;
944
945 dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data,
946 wiphy_list) {
947 os_memset(&event, 0, sizeof(event));
948 event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);
949 event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);
950 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
951 }
952
953 return NL_SKIP;
954}
955
956
957static struct nl80211_wiphy_data *
958nl80211_get_wiphy_data_ap(struct i802_bss *bss)
959{
960 static DEFINE_DL_LIST(nl80211_wiphys);
961 struct nl80211_wiphy_data *w;
962 int wiphy_idx, found = 0;
963 struct i802_bss *tmp_bss;
964
965 if (bss->wiphy_data != NULL)
966 return bss->wiphy_data;
967
968 wiphy_idx = nl80211_get_wiphy_index(bss);
969
970 dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) {
971 if (w->wiphy_idx == wiphy_idx)
972 goto add;
973 }
974
975 /* alloc new one */
976 w = os_zalloc(sizeof(*w));
977 if (w == NULL)
978 return NULL;
979 w->wiphy_idx = wiphy_idx;
980 dl_list_init(&w->bsss);
981 dl_list_init(&w->drvs);
982
983 w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
984 if (!w->nl_cb) {
985 os_free(w);
986 return NULL;
987 }
988 nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
989 nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,
990 w);
991
992 w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
993 "wiphy beacons");
994 if (w->nl_beacons == NULL) {
995 os_free(w);
996 return NULL;
997 }
998
999 if (nl80211_register_beacons(bss->drv, w)) {
1000 nl_destroy_handles(&w->nl_beacons);
1001 os_free(w);
1002 return NULL;
1003 }
1004
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001005 nl80211_register_eloop_read(&w->nl_beacons, nl80211_recv_beacons, w);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001006
1007 dl_list_add(&nl80211_wiphys, &w->list);
1008
1009add:
1010 /* drv entry for this bss already there? */
1011 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
1012 if (tmp_bss->drv == bss->drv) {
1013 found = 1;
1014 break;
1015 }
1016 }
1017 /* if not add it */
1018 if (!found)
1019 dl_list_add(&w->drvs, &bss->drv->wiphy_list);
1020
1021 dl_list_add(&w->bsss, &bss->wiphy_list);
1022 bss->wiphy_data = w;
1023 return w;
1024}
1025
1026
1027static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
1028{
1029 struct nl80211_wiphy_data *w = bss->wiphy_data;
1030 struct i802_bss *tmp_bss;
1031 int found = 0;
1032
1033 if (w == NULL)
1034 return;
1035 bss->wiphy_data = NULL;
1036 dl_list_del(&bss->wiphy_list);
1037
1038 /* still any for this drv present? */
1039 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
1040 if (tmp_bss->drv == bss->drv) {
1041 found = 1;
1042 break;
1043 }
1044 }
1045 /* if not remove it */
1046 if (!found)
1047 dl_list_del(&bss->drv->wiphy_list);
1048
1049 if (!dl_list_empty(&w->bsss))
1050 return;
1051
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001052 nl80211_destroy_eloop_handle(&w->nl_beacons);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001053
1054 nl_cb_put(w->nl_cb);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001055 dl_list_del(&w->list);
1056 os_free(w);
1057}
1058
1059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001060static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
1061{
1062 struct i802_bss *bss = priv;
1063 struct wpa_driver_nl80211_data *drv = bss->drv;
1064 if (!drv->associated)
1065 return -1;
1066 os_memcpy(bssid, drv->bssid, ETH_ALEN);
1067 return 0;
1068}
1069
1070
1071static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
1072{
1073 struct i802_bss *bss = priv;
1074 struct wpa_driver_nl80211_data *drv = bss->drv;
1075 if (!drv->associated)
1076 return -1;
1077 os_memcpy(ssid, drv->ssid, drv->ssid_len);
1078 return drv->ssid_len;
1079}
1080
1081
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001082static void wpa_driver_nl80211_event_newlink(
1083 struct wpa_driver_nl80211_data *drv, char *ifname)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001084{
1085 union wpa_event_data event;
1086
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001087 if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
1088 if (if_nametoindex(drv->first_bss->ifname) == 0) {
1089 wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
1090 drv->first_bss->ifname);
1091 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001092 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001093 if (!drv->if_removed)
1094 return;
1095 wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event",
1096 drv->first_bss->ifname);
1097 drv->if_removed = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001098 }
1099
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001100 os_memset(&event, 0, sizeof(event));
1101 os_strlcpy(event.interface_status.ifname, ifname,
1102 sizeof(event.interface_status.ifname));
1103 event.interface_status.ievent = EVENT_INTERFACE_ADDED;
1104 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
1105}
1106
1107
1108static void wpa_driver_nl80211_event_dellink(
1109 struct wpa_driver_nl80211_data *drv, char *ifname)
1110{
1111 union wpa_event_data event;
1112
1113 if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
1114 if (drv->if_removed) {
1115 wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
1116 ifname);
1117 return;
1118 }
1119 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1",
1120 ifname);
1121 drv->if_removed = 1;
1122 } else {
1123 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed",
1124 ifname);
1125 }
1126
1127 os_memset(&event, 0, sizeof(event));
1128 os_strlcpy(event.interface_status.ifname, ifname,
1129 sizeof(event.interface_status.ifname));
1130 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001131 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
1132}
1133
1134
1135static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
1136 u8 *buf, size_t len)
1137{
1138 int attrlen, rta_len;
1139 struct rtattr *attr;
1140
1141 attrlen = len;
1142 attr = (struct rtattr *) buf;
1143
1144 rta_len = RTA_ALIGN(sizeof(struct rtattr));
1145 while (RTA_OK(attr, attrlen)) {
1146 if (attr->rta_type == IFLA_IFNAME) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001147 if (os_strcmp(((char *) attr) + rta_len,
1148 drv->first_bss->ifname) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001149 return 1;
1150 else
1151 break;
1152 }
1153 attr = RTA_NEXT(attr, attrlen);
1154 }
1155
1156 return 0;
1157}
1158
1159
1160static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
1161 int ifindex, u8 *buf, size_t len)
1162{
1163 if (drv->ifindex == ifindex)
1164 return 1;
1165
1166 if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001167 wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
1168 "interface");
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001169 wpa_driver_nl80211_finish_drv_init(drv, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170 return 1;
1171 }
1172
1173 return 0;
1174}
1175
1176
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001177static struct wpa_driver_nl80211_data *
1178nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
1179{
1180 struct wpa_driver_nl80211_data *drv;
1181 dl_list_for_each(drv, &global->interfaces,
1182 struct wpa_driver_nl80211_data, list) {
1183 if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
1184 have_ifidx(drv, idx))
1185 return drv;
1186 }
1187 return NULL;
1188}
1189
1190
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001191static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
1192 struct ifinfomsg *ifi,
1193 u8 *buf, size_t len)
1194{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001195 struct nl80211_global *global = ctx;
1196 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001197 int attrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001198 struct rtattr *attr;
1199 u32 brid = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001200 char namebuf[IFNAMSIZ];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001201 char ifname[IFNAMSIZ + 1];
1202 char extra[100], *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001203
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001204 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
1205 if (!drv) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001206 wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d",
1207 ifi->ifi_index);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001208 return;
1209 }
1210
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001211 extra[0] = '\0';
1212 pos = extra;
1213 end = pos + sizeof(extra);
1214 ifname[0] = '\0';
1215
1216 attrlen = len;
1217 attr = (struct rtattr *) buf;
1218 while (RTA_OK(attr, attrlen)) {
1219 switch (attr->rta_type) {
1220 case IFLA_IFNAME:
1221 if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
1222 break;
1223 os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
1224 ifname[RTA_PAYLOAD(attr)] = '\0';
1225 break;
1226 case IFLA_MASTER:
1227 brid = nla_get_u32((struct nlattr *) attr);
1228 pos += os_snprintf(pos, end - pos, " master=%u", brid);
1229 break;
1230 case IFLA_WIRELESS:
1231 pos += os_snprintf(pos, end - pos, " wext");
1232 break;
1233 case IFLA_OPERSTATE:
1234 pos += os_snprintf(pos, end - pos, " operstate=%u",
1235 nla_get_u32((struct nlattr *) attr));
1236 break;
1237 case IFLA_LINKMODE:
1238 pos += os_snprintf(pos, end - pos, " linkmode=%u",
1239 nla_get_u32((struct nlattr *) attr));
1240 break;
1241 }
1242 attr = RTA_NEXT(attr, attrlen);
1243 }
1244 extra[sizeof(extra) - 1] = '\0';
1245
1246 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_flags=0x%x (%s%s%s%s)",
1247 ifi->ifi_index, ifname, extra, ifi->ifi_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001248 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
1249 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
1250 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
1251 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
1252
1253 if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001254 if (if_indextoname(ifi->ifi_index, namebuf) &&
1255 linux_iface_up(drv->global->ioctl_sock,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001256 drv->first_bss->ifname) > 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001257 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
1258 "event since interface %s is up", namebuf);
1259 return;
1260 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001261 wpa_printf(MSG_DEBUG, "nl80211: Interface down");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001262 if (drv->ignore_if_down_event) {
1263 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
1264 "event generated by mode change");
1265 drv->ignore_if_down_event = 0;
1266 } else {
1267 drv->if_disabled = 1;
1268 wpa_supplicant_event(drv->ctx,
1269 EVENT_INTERFACE_DISABLED, NULL);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08001270
1271 /*
1272 * Try to get drv again, since it may be removed as
1273 * part of the EVENT_INTERFACE_DISABLED handling for
1274 * dynamic interfaces
1275 */
1276 drv = nl80211_find_drv(global, ifi->ifi_index,
1277 buf, len);
1278 if (!drv)
1279 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001280 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001281 }
1282
1283 if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001284 if (if_indextoname(ifi->ifi_index, namebuf) &&
1285 linux_iface_up(drv->global->ioctl_sock,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001286 drv->first_bss->ifname) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001287 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1288 "event since interface %s is down",
1289 namebuf);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001290 } else if (if_nametoindex(drv->first_bss->ifname) == 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001291 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1292 "event since interface %s does not exist",
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001293 drv->first_bss->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001294 } else if (drv->if_removed) {
1295 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1296 "event since interface %s is marked "
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001297 "removed", drv->first_bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001298 } else {
1299 wpa_printf(MSG_DEBUG, "nl80211: Interface up");
1300 drv->if_disabled = 0;
1301 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
1302 NULL);
1303 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001304 }
1305
1306 /*
1307 * Some drivers send the association event before the operup event--in
1308 * this case, lifting operstate in wpa_driver_nl80211_set_operstate()
1309 * fails. This will hit us when wpa_supplicant does not need to do
1310 * IEEE 802.1X authentication
1311 */
1312 if (drv->operstate == 1 &&
1313 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001314 !(ifi->ifi_flags & IFF_RUNNING)) {
1315 wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001316 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001317 -1, IF_OPER_UP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001318 }
1319
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001320 if (ifname[0])
1321 wpa_driver_nl80211_event_newlink(drv, ifname);
1322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001323 if (ifi->ifi_family == AF_BRIDGE && brid) {
1324 /* device has been added to bridge */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001325 if_indextoname(brid, namebuf);
1326 wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
1327 brid, namebuf);
1328 add_ifidx(drv, brid);
1329 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330}
1331
1332
1333static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
1334 struct ifinfomsg *ifi,
1335 u8 *buf, size_t len)
1336{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001337 struct nl80211_global *global = ctx;
1338 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001339 int attrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001340 struct rtattr *attr;
1341 u32 brid = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001342 char ifname[IFNAMSIZ + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001343
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001344 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
1345 if (!drv) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001346 wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d",
1347 ifi->ifi_index);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001348 return;
1349 }
1350
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001351 ifname[0] = '\0';
1352
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353 attrlen = len;
1354 attr = (struct rtattr *) buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001355 while (RTA_OK(attr, attrlen)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001356 switch (attr->rta_type) {
1357 case IFLA_IFNAME:
1358 if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
1359 break;
1360 os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
1361 ifname[RTA_PAYLOAD(attr)] = '\0';
1362 break;
1363 case IFLA_MASTER:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001364 brid = nla_get_u32((struct nlattr *) attr);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001365 break;
1366 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001367 attr = RTA_NEXT(attr, attrlen);
1368 }
1369
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001370 if (ifname[0])
1371 wpa_driver_nl80211_event_dellink(drv, ifname);
1372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001373 if (ifi->ifi_family == AF_BRIDGE && brid) {
1374 /* device has been removed from bridge */
1375 char namebuf[IFNAMSIZ];
1376 if_indextoname(brid, namebuf);
1377 wpa_printf(MSG_DEBUG, "nl80211: Remove ifindex %u for bridge "
1378 "%s", brid, namebuf);
1379 del_ifidx(drv, brid);
1380 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001381}
1382
1383
1384static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
1385 const u8 *frame, size_t len)
1386{
1387 const struct ieee80211_mgmt *mgmt;
1388 union wpa_event_data event;
1389
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001390 wpa_printf(MSG_DEBUG, "nl80211: Authenticate event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001391 mgmt = (const struct ieee80211_mgmt *) frame;
1392 if (len < 24 + sizeof(mgmt->u.auth)) {
1393 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1394 "frame");
1395 return;
1396 }
1397
1398 os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001399 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001400 os_memset(&event, 0, sizeof(event));
1401 os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
1402 event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001403 event.auth.auth_transaction =
1404 le_to_host16(mgmt->u.auth.auth_transaction);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405 event.auth.status_code = le_to_host16(mgmt->u.auth.status_code);
1406 if (len > 24 + sizeof(mgmt->u.auth)) {
1407 event.auth.ies = mgmt->u.auth.variable;
1408 event.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);
1409 }
1410
1411 wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);
1412}
1413
1414
Jouni Malinen87fd2792011-05-16 18:35:42 +03001415static unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
1416{
1417 struct nl_msg *msg;
1418 int ret;
1419 struct nl80211_bss_info_arg arg;
1420
1421 os_memset(&arg, 0, sizeof(arg));
1422 msg = nlmsg_alloc();
1423 if (!msg)
1424 goto nla_put_failure;
1425
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001426 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Jouni Malinen87fd2792011-05-16 18:35:42 +03001427 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
1428
1429 arg.drv = drv;
1430 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
1431 msg = NULL;
1432 if (ret == 0) {
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001433 unsigned int freq = drv->nlmode == NL80211_IFTYPE_ADHOC ?
1434 arg.ibss_freq : arg.assoc_freq;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001435 wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07001436 "associated BSS from scan results: %u MHz", freq);
1437 if (freq)
1438 drv->assoc_freq = freq;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07001439 return drv->assoc_freq;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001440 }
1441 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
1442 "(%s)", ret, strerror(-ret));
1443nla_put_failure:
1444 nlmsg_free(msg);
1445 return drv->assoc_freq;
1446}
1447
1448
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001449static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
1450 const u8 *frame, size_t len)
1451{
1452 const struct ieee80211_mgmt *mgmt;
1453 union wpa_event_data event;
1454 u16 status;
1455
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001456 wpa_printf(MSG_DEBUG, "nl80211: Associate event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001457 mgmt = (const struct ieee80211_mgmt *) frame;
1458 if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
1459 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1460 "frame");
1461 return;
1462 }
1463
1464 status = le_to_host16(mgmt->u.assoc_resp.status_code);
1465 if (status != WLAN_STATUS_SUCCESS) {
1466 os_memset(&event, 0, sizeof(event));
1467 event.assoc_reject.bssid = mgmt->bssid;
1468 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
1469 event.assoc_reject.resp_ies =
1470 (u8 *) mgmt->u.assoc_resp.variable;
1471 event.assoc_reject.resp_ies_len =
1472 len - 24 - sizeof(mgmt->u.assoc_resp);
1473 }
1474 event.assoc_reject.status_code = status;
1475
1476 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
1477 return;
1478 }
1479
1480 drv->associated = 1;
1481 os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001482 os_memcpy(drv->prev_bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001483
1484 os_memset(&event, 0, sizeof(event));
1485 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
1486 event.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;
1487 event.assoc_info.resp_ies_len =
1488 len - 24 - sizeof(mgmt->u.assoc_resp);
1489 }
1490
1491 event.assoc_info.freq = drv->assoc_freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001493 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
1494}
1495
1496
1497static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
1498 enum nl80211_commands cmd, struct nlattr *status,
1499 struct nlattr *addr, struct nlattr *req_ie,
1500 struct nlattr *resp_ie)
1501{
1502 union wpa_event_data event;
1503
1504 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
1505 /*
1506 * Avoid reporting two association events that would confuse
1507 * the core code.
1508 */
1509 wpa_printf(MSG_DEBUG, "nl80211: Ignore connect event (cmd=%d) "
1510 "when using userspace SME", cmd);
1511 return;
1512 }
1513
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001514 if (cmd == NL80211_CMD_CONNECT)
1515 wpa_printf(MSG_DEBUG, "nl80211: Connect event");
1516 else if (cmd == NL80211_CMD_ROAM)
1517 wpa_printf(MSG_DEBUG, "nl80211: Roam event");
1518
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001519 os_memset(&event, 0, sizeof(event));
1520 if (cmd == NL80211_CMD_CONNECT &&
1521 nla_get_u16(status) != WLAN_STATUS_SUCCESS) {
1522 if (addr)
1523 event.assoc_reject.bssid = nla_data(addr);
1524 if (resp_ie) {
1525 event.assoc_reject.resp_ies = nla_data(resp_ie);
1526 event.assoc_reject.resp_ies_len = nla_len(resp_ie);
1527 }
1528 event.assoc_reject.status_code = nla_get_u16(status);
1529 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
1530 return;
1531 }
1532
1533 drv->associated = 1;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001534 if (addr) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001535 os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001536 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
1537 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001538
1539 if (req_ie) {
1540 event.assoc_info.req_ies = nla_data(req_ie);
1541 event.assoc_info.req_ies_len = nla_len(req_ie);
1542 }
1543 if (resp_ie) {
1544 event.assoc_info.resp_ies = nla_data(resp_ie);
1545 event.assoc_info.resp_ies_len = nla_len(resp_ie);
1546 }
1547
Jouni Malinen87fd2792011-05-16 18:35:42 +03001548 event.assoc_info.freq = nl80211_get_assoc_freq(drv);
1549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001550 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
1551}
1552
1553
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001554static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001555 struct nlattr *reason, struct nlattr *addr,
1556 struct nlattr *by_ap)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001557{
1558 union wpa_event_data data;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001559 unsigned int locally_generated = by_ap == NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001560
1561 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
1562 /*
1563 * Avoid reporting two disassociation events that could
1564 * confuse the core code.
1565 */
1566 wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
1567 "event when using userspace SME");
1568 return;
1569 }
1570
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001571 if (drv->ignore_next_local_disconnect) {
1572 drv->ignore_next_local_disconnect = 0;
1573 if (locally_generated) {
1574 wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
1575 "event triggered during reassociation");
1576 return;
1577 }
1578 wpa_printf(MSG_WARNING, "nl80211: Was expecting local "
1579 "disconnect but got another disconnect "
1580 "event first");
1581 }
1582
1583 wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001584 nl80211_mark_disconnected(drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001585 os_memset(&data, 0, sizeof(data));
1586 if (reason)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001587 data.deauth_info.reason_code = nla_get_u16(reason);
1588 data.deauth_info.locally_generated = by_ap == NULL;
1589 wpa_supplicant_event(drv->ctx, EVENT_DEAUTH, &data);
1590}
1591
1592
Dmitry Shmidt97672262014-02-03 13:02:54 -08001593static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
1594{
1595 int freq1 = 0;
1596
1597 switch (convert2width(width)) {
1598 case CHAN_WIDTH_20_NOHT:
1599 case CHAN_WIDTH_20:
1600 return 0;
1601 case CHAN_WIDTH_40:
1602 freq1 = cf1 - 10;
1603 break;
1604 case CHAN_WIDTH_80:
1605 freq1 = cf1 - 30;
1606 break;
1607 case CHAN_WIDTH_160:
1608 freq1 = cf1 - 70;
1609 break;
1610 case CHAN_WIDTH_UNKNOWN:
1611 case CHAN_WIDTH_80P80:
1612 /* FIXME: implement this */
1613 return 0;
1614 }
1615
1616 return (abs(freq - freq1) / 20) % 2 == 0 ? 1 : -1;
1617}
1618
1619
Dmitry Shmidt04949592012-07-19 12:16:46 -07001620static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001621 struct nlattr *ifindex, struct nlattr *freq,
1622 struct nlattr *type, struct nlattr *bw,
1623 struct nlattr *cf1, struct nlattr *cf2)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001624{
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001625 struct i802_bss *bss;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001626 union wpa_event_data data;
1627 int ht_enabled = 1;
1628 int chan_offset = 0;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001629 int ifidx;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001630
1631 wpa_printf(MSG_DEBUG, "nl80211: Channel switch event");
1632
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001633 if (!freq)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001634 return;
1635
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001636 ifidx = nla_get_u32(ifindex);
1637 for (bss = drv->first_bss; bss; bss = bss->next)
1638 if (bss->ifindex == ifidx)
1639 break;
1640
1641 if (bss == NULL) {
1642 wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch, ignoring",
1643 ifidx);
1644 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001645 }
1646
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001647 if (type) {
1648 switch (nla_get_u32(type)) {
1649 case NL80211_CHAN_NO_HT:
1650 ht_enabled = 0;
1651 break;
1652 case NL80211_CHAN_HT20:
1653 break;
1654 case NL80211_CHAN_HT40PLUS:
1655 chan_offset = 1;
1656 break;
1657 case NL80211_CHAN_HT40MINUS:
1658 chan_offset = -1;
1659 break;
1660 }
Dmitry Shmidt97672262014-02-03 13:02:54 -08001661 } else if (bw && cf1) {
1662 /* This can happen for example with VHT80 ch switch */
1663 chan_offset = calculate_chan_offset(nla_get_u32(bw),
1664 nla_get_u32(freq),
1665 nla_get_u32(cf1),
1666 cf2 ? nla_get_u32(cf2) : 0);
1667 } else {
1668 wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information - following channel definition calculations may fail");
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001669 }
1670
1671 os_memset(&data, 0, sizeof(data));
Dmitry Shmidt04949592012-07-19 12:16:46 -07001672 data.ch_switch.freq = nla_get_u32(freq);
1673 data.ch_switch.ht_enabled = ht_enabled;
1674 data.ch_switch.ch_offset = chan_offset;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001675 if (bw)
1676 data.ch_switch.ch_width = convert2width(nla_get_u32(bw));
1677 if (cf1)
1678 data.ch_switch.cf1 = nla_get_u32(cf1);
1679 if (cf2)
1680 data.ch_switch.cf2 = nla_get_u32(cf2);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001681
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001682 bss->freq = data.ch_switch.freq;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001683
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001684 wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001685}
1686
1687
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001688static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
1689 enum nl80211_commands cmd, struct nlattr *addr)
1690{
1691 union wpa_event_data event;
1692 enum wpa_event_type ev;
1693
1694 if (nla_len(addr) != ETH_ALEN)
1695 return;
1696
1697 wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR,
1698 cmd, MAC2STR((u8 *) nla_data(addr)));
1699
1700 if (cmd == NL80211_CMD_AUTHENTICATE)
1701 ev = EVENT_AUTH_TIMED_OUT;
1702 else if (cmd == NL80211_CMD_ASSOCIATE)
1703 ev = EVENT_ASSOC_TIMED_OUT;
1704 else
1705 return;
1706
1707 os_memset(&event, 0, sizeof(event));
1708 os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);
1709 wpa_supplicant_event(drv->ctx, ev, &event);
1710}
1711
1712
Dmitry Shmidt98660862014-03-11 17:26:21 -07001713static void mlme_event_mgmt(struct i802_bss *bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07001714 struct nlattr *freq, struct nlattr *sig,
1715 const u8 *frame, size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716{
Dmitry Shmidt98660862014-03-11 17:26:21 -07001717 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718 const struct ieee80211_mgmt *mgmt;
1719 union wpa_event_data event;
1720 u16 fc, stype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001721 int ssi_signal = 0;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001722 int rx_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001724 wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725 mgmt = (const struct ieee80211_mgmt *) frame;
1726 if (len < 24) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001727 wpa_printf(MSG_DEBUG, "nl80211: Too short management frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001728 return;
1729 }
1730
1731 fc = le_to_host16(mgmt->frame_control);
1732 stype = WLAN_FC_GET_STYPE(fc);
1733
Dmitry Shmidt04949592012-07-19 12:16:46 -07001734 if (sig)
1735 ssi_signal = (s32) nla_get_u32(sig);
1736
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001737 os_memset(&event, 0, sizeof(event));
1738 if (freq) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001739 event.rx_mgmt.freq = nla_get_u32(freq);
1740 rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001741 }
Dmitry Shmidt56052862013-10-04 10:23:25 -07001742 wpa_printf(MSG_DEBUG,
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07001743 "nl80211: RX frame sa=" MACSTR
1744 " freq=%d ssi_signal=%d stype=%u (%s) len=%u",
1745 MAC2STR(mgmt->sa), rx_freq, ssi_signal, stype, fc2str(fc),
1746 (unsigned int) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001747 event.rx_mgmt.frame = frame;
1748 event.rx_mgmt.frame_len = len;
1749 event.rx_mgmt.ssi_signal = ssi_signal;
Dmitry Shmidt98660862014-03-11 17:26:21 -07001750 event.rx_mgmt.drv_priv = bss;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001751 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001752}
1753
1754
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001755static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
1756 struct nlattr *cookie, const u8 *frame,
1757 size_t len, struct nlattr *ack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001758{
1759 union wpa_event_data event;
1760 const struct ieee80211_hdr *hdr;
1761 u16 fc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001762
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001763 wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001764 if (!is_ap_interface(drv->nlmode)) {
1765 u64 cookie_val;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001767 if (!cookie)
1768 return;
1769
1770 cookie_val = nla_get_u64(cookie);
1771 wpa_printf(MSG_DEBUG, "nl80211: Action TX status:"
1772 " cookie=0%llx%s (ack=%d)",
1773 (long long unsigned int) cookie_val,
1774 cookie_val == drv->send_action_cookie ?
1775 " (match)" : " (unknown)", ack != NULL);
1776 if (cookie_val != drv->send_action_cookie)
1777 return;
1778 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001779
1780 hdr = (const struct ieee80211_hdr *) frame;
1781 fc = le_to_host16(hdr->frame_control);
1782
1783 os_memset(&event, 0, sizeof(event));
1784 event.tx_status.type = WLAN_FC_GET_TYPE(fc);
1785 event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
1786 event.tx_status.dst = hdr->addr1;
1787 event.tx_status.data = frame;
1788 event.tx_status.data_len = len;
1789 event.tx_status.ack = ack != NULL;
1790 wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
1791}
1792
1793
1794static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
1795 enum wpa_event_type type,
1796 const u8 *frame, size_t len)
1797{
1798 const struct ieee80211_mgmt *mgmt;
1799 union wpa_event_data event;
1800 const u8 *bssid = NULL;
1801 u16 reason_code = 0;
1802
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001803 if (type == EVENT_DEAUTH)
1804 wpa_printf(MSG_DEBUG, "nl80211: Deauthenticate event");
1805 else
1806 wpa_printf(MSG_DEBUG, "nl80211: Disassociate event");
1807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001808 mgmt = (const struct ieee80211_mgmt *) frame;
1809 if (len >= 24) {
1810 bssid = mgmt->bssid;
1811
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001812 if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
1813 !drv->associated &&
1814 os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
1815 os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
1816 os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
1817 /*
1818 * Avoid issues with some roaming cases where
1819 * disconnection event for the old AP may show up after
1820 * we have started connection with the new AP.
1821 */
1822 wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
1823 MAC2STR(bssid),
1824 MAC2STR(drv->auth_attempt_bssid));
1825 return;
1826 }
1827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001828 if (drv->associated != 0 &&
1829 os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
1830 os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
1831 /*
1832 * We have presumably received this deauth as a
1833 * response to a clear_state_mismatch() outgoing
1834 * deauth. Don't let it take us offline!
1835 */
1836 wpa_printf(MSG_DEBUG, "nl80211: Deauth received "
1837 "from Unknown BSSID " MACSTR " -- ignoring",
1838 MAC2STR(bssid));
1839 return;
1840 }
1841 }
1842
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001843 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844 os_memset(&event, 0, sizeof(event));
1845
1846 /* Note: Same offset for Reason Code in both frame subtypes */
1847 if (len >= 24 + sizeof(mgmt->u.deauth))
1848 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1849
1850 if (type == EVENT_DISASSOC) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001851 event.disassoc_info.locally_generated =
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001852 !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001853 event.disassoc_info.addr = bssid;
1854 event.disassoc_info.reason_code = reason_code;
1855 if (frame + len > mgmt->u.disassoc.variable) {
1856 event.disassoc_info.ie = mgmt->u.disassoc.variable;
1857 event.disassoc_info.ie_len = frame + len -
1858 mgmt->u.disassoc.variable;
1859 }
1860 } else {
Dmitry Shmidt98660862014-03-11 17:26:21 -07001861 if (drv->ignore_deauth_event) {
1862 wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event due to previous forced deauth-during-auth");
1863 drv->ignore_deauth_event = 0;
1864 return;
1865 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001866 event.deauth_info.locally_generated =
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001867 !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07001868 if (drv->ignore_next_local_deauth) {
1869 drv->ignore_next_local_deauth = 0;
1870 if (event.deauth_info.locally_generated) {
1871 wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event triggered due to own deauth request");
1872 return;
1873 }
1874 wpa_printf(MSG_WARNING, "nl80211: Was expecting local deauth but got another disconnect event first");
1875 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876 event.deauth_info.addr = bssid;
1877 event.deauth_info.reason_code = reason_code;
1878 if (frame + len > mgmt->u.deauth.variable) {
1879 event.deauth_info.ie = mgmt->u.deauth.variable;
1880 event.deauth_info.ie_len = frame + len -
1881 mgmt->u.deauth.variable;
1882 }
1883 }
1884
1885 wpa_supplicant_event(drv->ctx, type, &event);
1886}
1887
1888
1889static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv,
1890 enum wpa_event_type type,
1891 const u8 *frame, size_t len)
1892{
1893 const struct ieee80211_mgmt *mgmt;
1894 union wpa_event_data event;
1895 u16 reason_code = 0;
1896
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001897 if (type == EVENT_UNPROT_DEAUTH)
1898 wpa_printf(MSG_DEBUG, "nl80211: Unprot Deauthenticate event");
1899 else
1900 wpa_printf(MSG_DEBUG, "nl80211: Unprot Disassociate event");
1901
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001902 if (len < 24)
1903 return;
1904
1905 mgmt = (const struct ieee80211_mgmt *) frame;
1906
1907 os_memset(&event, 0, sizeof(event));
1908 /* Note: Same offset for Reason Code in both frame subtypes */
1909 if (len >= 24 + sizeof(mgmt->u.deauth))
1910 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1911
1912 if (type == EVENT_UNPROT_DISASSOC) {
1913 event.unprot_disassoc.sa = mgmt->sa;
1914 event.unprot_disassoc.da = mgmt->da;
1915 event.unprot_disassoc.reason_code = reason_code;
1916 } else {
1917 event.unprot_deauth.sa = mgmt->sa;
1918 event.unprot_deauth.da = mgmt->da;
1919 event.unprot_deauth.reason_code = reason_code;
1920 }
1921
1922 wpa_supplicant_event(drv->ctx, type, &event);
1923}
1924
1925
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001926static void mlme_event(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001927 enum nl80211_commands cmd, struct nlattr *frame,
1928 struct nlattr *addr, struct nlattr *timed_out,
1929 struct nlattr *freq, struct nlattr *ack,
Dmitry Shmidt04949592012-07-19 12:16:46 -07001930 struct nlattr *cookie, struct nlattr *sig)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001931{
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001932 struct wpa_driver_nl80211_data *drv = bss->drv;
1933 const u8 *data;
1934 size_t len;
1935
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936 if (timed_out && addr) {
1937 mlme_timeout_event(drv, cmd, addr);
1938 return;
1939 }
1940
1941 if (frame == NULL) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001942 wpa_printf(MSG_DEBUG,
1943 "nl80211: MLME event %d (%s) without frame data",
1944 cmd, nl80211_command_to_string(cmd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945 return;
1946 }
1947
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001948 data = nla_data(frame);
1949 len = nla_len(frame);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001950 if (len < 4 + 2 * ETH_ALEN) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001951 wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s("
1952 MACSTR ") - too short",
1953 cmd, nl80211_command_to_string(cmd), bss->ifname,
1954 MAC2STR(bss->addr));
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001955 return;
1956 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001957 wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s(" MACSTR
1958 ") A1=" MACSTR " A2=" MACSTR, cmd,
1959 nl80211_command_to_string(cmd), bss->ifname,
1960 MAC2STR(bss->addr), MAC2STR(data + 4),
1961 MAC2STR(data + 4 + ETH_ALEN));
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001962 if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) &&
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001963 os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 &&
1964 os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001965 wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
1966 "for foreign address", bss->ifname);
1967 return;
1968 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969 wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame",
1970 nla_data(frame), nla_len(frame));
1971
1972 switch (cmd) {
1973 case NL80211_CMD_AUTHENTICATE:
1974 mlme_event_auth(drv, nla_data(frame), nla_len(frame));
1975 break;
1976 case NL80211_CMD_ASSOCIATE:
1977 mlme_event_assoc(drv, nla_data(frame), nla_len(frame));
1978 break;
1979 case NL80211_CMD_DEAUTHENTICATE:
1980 mlme_event_deauth_disassoc(drv, EVENT_DEAUTH,
1981 nla_data(frame), nla_len(frame));
1982 break;
1983 case NL80211_CMD_DISASSOCIATE:
1984 mlme_event_deauth_disassoc(drv, EVENT_DISASSOC,
1985 nla_data(frame), nla_len(frame));
1986 break;
1987 case NL80211_CMD_FRAME:
Dmitry Shmidt98660862014-03-11 17:26:21 -07001988 mlme_event_mgmt(bss, freq, sig, nla_data(frame),
Dmitry Shmidt04949592012-07-19 12:16:46 -07001989 nla_len(frame));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001990 break;
1991 case NL80211_CMD_FRAME_TX_STATUS:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001992 mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
1993 nla_len(frame), ack);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001994 break;
1995 case NL80211_CMD_UNPROT_DEAUTHENTICATE:
1996 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,
1997 nla_data(frame), nla_len(frame));
1998 break;
1999 case NL80211_CMD_UNPROT_DISASSOCIATE:
2000 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,
2001 nla_data(frame), nla_len(frame));
2002 break;
2003 default:
2004 break;
2005 }
2006}
2007
2008
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002009static void mlme_event_michael_mic_failure(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010 struct nlattr *tb[])
2011{
2012 union wpa_event_data data;
2013
2014 wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure");
2015 os_memset(&data, 0, sizeof(data));
2016 if (tb[NL80211_ATTR_MAC]) {
2017 wpa_hexdump(MSG_DEBUG, "nl80211: Source MAC address",
2018 nla_data(tb[NL80211_ATTR_MAC]),
2019 nla_len(tb[NL80211_ATTR_MAC]));
2020 data.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);
2021 }
2022 if (tb[NL80211_ATTR_KEY_SEQ]) {
2023 wpa_hexdump(MSG_DEBUG, "nl80211: TSC",
2024 nla_data(tb[NL80211_ATTR_KEY_SEQ]),
2025 nla_len(tb[NL80211_ATTR_KEY_SEQ]));
2026 }
2027 if (tb[NL80211_ATTR_KEY_TYPE]) {
2028 enum nl80211_key_type key_type =
2029 nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);
2030 wpa_printf(MSG_DEBUG, "nl80211: Key Type %d", key_type);
2031 if (key_type == NL80211_KEYTYPE_PAIRWISE)
2032 data.michael_mic_failure.unicast = 1;
2033 } else
2034 data.michael_mic_failure.unicast = 1;
2035
2036 if (tb[NL80211_ATTR_KEY_IDX]) {
2037 u8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);
2038 wpa_printf(MSG_DEBUG, "nl80211: Key Id %d", key_id);
2039 }
2040
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002041 wpa_supplicant_event(bss->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042}
2043
2044
2045static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
2046 struct nlattr *tb[])
2047{
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07002048 unsigned int freq;
2049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 if (tb[NL80211_ATTR_MAC] == NULL) {
2051 wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
2052 "event");
2053 return;
2054 }
2055 os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002056
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057 drv->associated = 1;
2058 wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined",
2059 MAC2STR(drv->bssid));
2060
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07002061 freq = nl80211_get_assoc_freq(drv);
2062 if (freq) {
2063 wpa_printf(MSG_DEBUG, "nl80211: IBSS on frequency %u MHz",
2064 freq);
2065 drv->first_bss->freq = freq;
2066 }
2067
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002068 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
2069}
2070
2071
2072static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
2073 int cancel_event, struct nlattr *tb[])
2074{
2075 unsigned int freq, chan_type, duration;
2076 union wpa_event_data data;
2077 u64 cookie;
2078
2079 if (tb[NL80211_ATTR_WIPHY_FREQ])
2080 freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
2081 else
2082 freq = 0;
2083
2084 if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
2085 chan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
2086 else
2087 chan_type = 0;
2088
2089 if (tb[NL80211_ATTR_DURATION])
2090 duration = nla_get_u32(tb[NL80211_ATTR_DURATION]);
2091 else
2092 duration = 0;
2093
2094 if (tb[NL80211_ATTR_COOKIE])
2095 cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
2096 else
2097 cookie = 0;
2098
2099 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel event (cancel=%d "
2100 "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))",
2101 cancel_event, freq, chan_type, duration,
2102 (long long unsigned int) cookie,
2103 cookie == drv->remain_on_chan_cookie ? "match" : "unknown");
2104
2105 if (cookie != drv->remain_on_chan_cookie)
2106 return; /* not for us */
2107
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002108 if (cancel_event)
2109 drv->pending_remain_on_chan = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002110
2111 os_memset(&data, 0, sizeof(data));
2112 data.remain_on_channel.freq = freq;
2113 data.remain_on_channel.duration = duration;
2114 wpa_supplicant_event(drv->ctx, cancel_event ?
2115 EVENT_CANCEL_REMAIN_ON_CHANNEL :
2116 EVENT_REMAIN_ON_CHANNEL, &data);
2117}
2118
2119
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002120static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
2121 struct nlattr *tb[])
2122{
2123 union wpa_event_data data;
2124
2125 os_memset(&data, 0, sizeof(data));
2126
2127 if (tb[NL80211_ATTR_IE]) {
2128 data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
2129 data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
2130 }
2131
2132 if (tb[NL80211_ATTR_IE_RIC]) {
2133 data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
2134 data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
2135 }
2136
2137 if (tb[NL80211_ATTR_MAC])
2138 os_memcpy(data.ft_ies.target_ap,
2139 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2140
2141 wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
2142 MAC2STR(data.ft_ies.target_ap));
2143
2144 wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
2145}
2146
2147
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
2149 struct nlattr *tb[])
2150{
2151 union wpa_event_data event;
2152 struct nlattr *nl;
2153 int rem;
2154 struct scan_info *info;
2155#define MAX_REPORT_FREQS 50
2156 int freqs[MAX_REPORT_FREQS];
2157 int num_freqs = 0;
2158
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002159 if (drv->scan_for_auth) {
2160 drv->scan_for_auth = 0;
2161 wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
2162 "cfg80211 BSS entry");
2163 wpa_driver_nl80211_authenticate_retry(drv);
2164 return;
2165 }
2166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002167 os_memset(&event, 0, sizeof(event));
2168 info = &event.scan_info;
2169 info->aborted = aborted;
2170
2171 if (tb[NL80211_ATTR_SCAN_SSIDS]) {
2172 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {
2173 struct wpa_driver_scan_ssid *s =
2174 &info->ssids[info->num_ssids];
2175 s->ssid = nla_data(nl);
2176 s->ssid_len = nla_len(nl);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002177 wpa_printf(MSG_DEBUG, "nl80211: Scan probed for SSID '%s'",
2178 wpa_ssid_txt(s->ssid, s->ssid_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002179 info->num_ssids++;
2180 if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
2181 break;
2182 }
2183 }
2184 if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002185 char msg[200], *pos, *end;
2186 int res;
2187
2188 pos = msg;
2189 end = pos + sizeof(msg);
2190 *pos = '\0';
2191
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002192 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)
2193 {
2194 freqs[num_freqs] = nla_get_u32(nl);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002195 res = os_snprintf(pos, end - pos, " %d",
2196 freqs[num_freqs]);
2197 if (res > 0 && end - pos > res)
2198 pos += res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002199 num_freqs++;
2200 if (num_freqs == MAX_REPORT_FREQS - 1)
2201 break;
2202 }
2203 info->freqs = freqs;
2204 info->num_freqs = num_freqs;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002205 wpa_printf(MSG_DEBUG, "nl80211: Scan included frequencies:%s",
2206 msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002207 }
2208 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
2209}
2210
2211
2212static int get_link_signal(struct nl_msg *msg, void *arg)
2213{
2214 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2215 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2216 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
2217 static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
2218 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002219 [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220 };
2221 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
2222 static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
2223 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
2224 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
2225 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
2226 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
2227 };
2228 struct wpa_signal_info *sig_change = arg;
2229
2230 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2231 genlmsg_attrlen(gnlh, 0), NULL);
2232 if (!tb[NL80211_ATTR_STA_INFO] ||
2233 nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
2234 tb[NL80211_ATTR_STA_INFO], policy))
2235 return NL_SKIP;
2236 if (!sinfo[NL80211_STA_INFO_SIGNAL])
2237 return NL_SKIP;
2238
2239 sig_change->current_signal =
2240 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
2241
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002242 if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
2243 sig_change->avg_signal =
2244 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
2245 else
2246 sig_change->avg_signal = 0;
2247
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002248 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
2249 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
2250 sinfo[NL80211_STA_INFO_TX_BITRATE],
2251 rate_policy)) {
2252 sig_change->current_txrate = 0;
2253 } else {
2254 if (rinfo[NL80211_RATE_INFO_BITRATE]) {
2255 sig_change->current_txrate =
2256 nla_get_u16(rinfo[
2257 NL80211_RATE_INFO_BITRATE]) * 100;
2258 }
2259 }
2260 }
2261
2262 return NL_SKIP;
2263}
2264
2265
2266static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
2267 struct wpa_signal_info *sig)
2268{
2269 struct nl_msg *msg;
2270
2271 sig->current_signal = -9999;
2272 sig->current_txrate = 0;
2273
2274 msg = nlmsg_alloc();
2275 if (!msg)
2276 return -ENOMEM;
2277
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002278 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002279
2280 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2281 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
2282
2283 return send_and_recv_msgs(drv, msg, get_link_signal, sig);
2284 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002285 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286 return -ENOBUFS;
2287}
2288
2289
2290static int get_link_noise(struct nl_msg *msg, void *arg)
2291{
2292 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2293 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2294 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
2295 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
2296 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
2297 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
2298 };
2299 struct wpa_signal_info *sig_change = arg;
2300
2301 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2302 genlmsg_attrlen(gnlh, 0), NULL);
2303
2304 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
2305 wpa_printf(MSG_DEBUG, "nl80211: survey data missing!");
2306 return NL_SKIP;
2307 }
2308
2309 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
2310 tb[NL80211_ATTR_SURVEY_INFO],
2311 survey_policy)) {
2312 wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested "
2313 "attributes!");
2314 return NL_SKIP;
2315 }
2316
2317 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
2318 return NL_SKIP;
2319
2320 if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
2321 sig_change->frequency)
2322 return NL_SKIP;
2323
2324 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
2325 return NL_SKIP;
2326
2327 sig_change->current_noise =
2328 (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
2329
2330 return NL_SKIP;
2331}
2332
2333
2334static int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
2335 struct wpa_signal_info *sig_change)
2336{
2337 struct nl_msg *msg;
2338
2339 sig_change->current_noise = 9999;
2340 sig_change->frequency = drv->assoc_freq;
2341
2342 msg = nlmsg_alloc();
2343 if (!msg)
2344 return -ENOMEM;
2345
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002346 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347
2348 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2349
2350 return send_and_recv_msgs(drv, msg, get_link_noise, sig_change);
2351 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002352 nlmsg_free(msg);
2353 return -ENOBUFS;
2354}
2355
2356
2357static int get_noise_for_scan_results(struct nl_msg *msg, void *arg)
2358{
2359 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2360 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2361 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
2362 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
2363 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
2364 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
2365 };
2366 struct wpa_scan_results *scan_results = arg;
2367 struct wpa_scan_res *scan_res;
2368 size_t i;
2369
2370 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2371 genlmsg_attrlen(gnlh, 0), NULL);
2372
2373 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
2374 wpa_printf(MSG_DEBUG, "nl80211: Survey data missing");
2375 return NL_SKIP;
2376 }
2377
2378 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
2379 tb[NL80211_ATTR_SURVEY_INFO],
2380 survey_policy)) {
2381 wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested "
2382 "attributes");
2383 return NL_SKIP;
2384 }
2385
2386 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
2387 return NL_SKIP;
2388
2389 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
2390 return NL_SKIP;
2391
2392 for (i = 0; i < scan_results->num; ++i) {
2393 scan_res = scan_results->res[i];
2394 if (!scan_res)
2395 continue;
2396 if ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
2397 scan_res->freq)
2398 continue;
2399 if (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))
2400 continue;
2401 scan_res->noise = (s8)
2402 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
2403 scan_res->flags &= ~WPA_SCAN_NOISE_INVALID;
2404 }
2405
2406 return NL_SKIP;
2407}
2408
2409
2410static int nl80211_get_noise_for_scan_results(
2411 struct wpa_driver_nl80211_data *drv,
2412 struct wpa_scan_results *scan_res)
2413{
2414 struct nl_msg *msg;
2415
2416 msg = nlmsg_alloc();
2417 if (!msg)
2418 return -ENOMEM;
2419
2420 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
2421
2422 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2423
2424 return send_and_recv_msgs(drv, msg, get_noise_for_scan_results,
2425 scan_res);
2426 nla_put_failure:
2427 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428 return -ENOBUFS;
2429}
2430
2431
2432static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
2433 struct nlattr *tb[])
2434{
2435 static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
2436 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
2437 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
2438 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
2439 [NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },
2440 };
2441 struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
2442 enum nl80211_cqm_rssi_threshold_event event;
2443 union wpa_event_data ed;
2444 struct wpa_signal_info sig;
2445 int res;
2446
2447 if (tb[NL80211_ATTR_CQM] == NULL ||
2448 nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],
2449 cqm_policy)) {
2450 wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid CQM event");
2451 return;
2452 }
2453
2454 os_memset(&ed, 0, sizeof(ed));
2455
2456 if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {
2457 if (!tb[NL80211_ATTR_MAC])
2458 return;
2459 os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),
2460 ETH_ALEN);
2461 wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
2462 return;
2463 }
2464
2465 if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)
2466 return;
2467 event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
2468
2469 if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
2470 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
2471 "event: RSSI high");
2472 ed.signal_change.above_threshold = 1;
2473 } else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {
2474 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
2475 "event: RSSI low");
2476 ed.signal_change.above_threshold = 0;
2477 } else
2478 return;
2479
2480 res = nl80211_get_link_signal(drv, &sig);
2481 if (res == 0) {
2482 ed.signal_change.current_signal = sig.current_signal;
2483 ed.signal_change.current_txrate = sig.current_txrate;
2484 wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d",
2485 sig.current_signal, sig.current_txrate);
2486 }
2487
2488 res = nl80211_get_link_noise(drv, &sig);
2489 if (res == 0) {
2490 ed.signal_change.current_noise = sig.current_noise;
2491 wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm",
2492 sig.current_noise);
2493 }
2494
2495 wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);
2496}
2497
2498
2499static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
2500 struct nlattr **tb)
2501{
2502 u8 *addr;
2503 union wpa_event_data data;
2504
2505 if (tb[NL80211_ATTR_MAC] == NULL)
2506 return;
2507 addr = nla_data(tb[NL80211_ATTR_MAC]);
2508 wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr));
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002509
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002510 if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002511 u8 *ies = NULL;
2512 size_t ies_len = 0;
2513 if (tb[NL80211_ATTR_IE]) {
2514 ies = nla_data(tb[NL80211_ATTR_IE]);
2515 ies_len = nla_len(tb[NL80211_ATTR_IE]);
2516 }
2517 wpa_hexdump(MSG_DEBUG, "nl80211: Assoc Req IEs", ies, ies_len);
2518 drv_event_assoc(drv->ctx, addr, ies, ies_len, 0);
2519 return;
2520 }
2521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522 if (drv->nlmode != NL80211_IFTYPE_ADHOC)
2523 return;
2524
2525 os_memset(&data, 0, sizeof(data));
2526 os_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);
2527 wpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data);
2528}
2529
2530
2531static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
2532 struct nlattr **tb)
2533{
2534 u8 *addr;
2535 union wpa_event_data data;
2536
2537 if (tb[NL80211_ATTR_MAC] == NULL)
2538 return;
2539 addr = nla_data(tb[NL80211_ATTR_MAC]);
2540 wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR,
2541 MAC2STR(addr));
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002542
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002543 if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002544 drv_event_disassoc(drv->ctx, addr);
2545 return;
2546 }
2547
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548 if (drv->nlmode != NL80211_IFTYPE_ADHOC)
2549 return;
2550
2551 os_memset(&data, 0, sizeof(data));
2552 os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);
2553 wpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);
2554}
2555
2556
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002557static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data *drv,
2558 struct nlattr **tb)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002560 struct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];
2561 static struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {
2562 [NL80211_REKEY_DATA_KEK] = {
2563 .minlen = NL80211_KEK_LEN,
2564 .maxlen = NL80211_KEK_LEN,
2565 },
2566 [NL80211_REKEY_DATA_KCK] = {
2567 .minlen = NL80211_KCK_LEN,
2568 .maxlen = NL80211_KCK_LEN,
2569 },
2570 [NL80211_REKEY_DATA_REPLAY_CTR] = {
2571 .minlen = NL80211_REPLAY_CTR_LEN,
2572 .maxlen = NL80211_REPLAY_CTR_LEN,
2573 },
2574 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575 union wpa_event_data data;
2576
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002577 if (!tb[NL80211_ATTR_MAC])
2578 return;
2579 if (!tb[NL80211_ATTR_REKEY_DATA])
2580 return;
2581 if (nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,
2582 tb[NL80211_ATTR_REKEY_DATA], rekey_policy))
2583 return;
2584 if (!rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])
2585 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002586
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002587 os_memset(&data, 0, sizeof(data));
2588 data.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);
2589 wpa_printf(MSG_DEBUG, "nl80211: Rekey offload event for BSSID " MACSTR,
2590 MAC2STR(data.driver_gtk_rekey.bssid));
2591 data.driver_gtk_rekey.replay_ctr =
2592 nla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);
2593 wpa_hexdump(MSG_DEBUG, "nl80211: Rekey offload - Replay Counter",
2594 data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);
2595 wpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);
2596}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002597
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002598
2599static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
2600 struct nlattr **tb)
2601{
2602 struct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];
2603 static struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {
2604 [NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },
2605 [NL80211_PMKSA_CANDIDATE_BSSID] = {
2606 .minlen = ETH_ALEN,
2607 .maxlen = ETH_ALEN,
2608 },
2609 [NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },
2610 };
2611 union wpa_event_data data;
2612
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002613 wpa_printf(MSG_DEBUG, "nl80211: PMKSA candidate event");
2614
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002615 if (!tb[NL80211_ATTR_PMKSA_CANDIDATE])
2616 return;
2617 if (nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,
2618 tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy))
2619 return;
2620 if (!cand[NL80211_PMKSA_CANDIDATE_INDEX] ||
2621 !cand[NL80211_PMKSA_CANDIDATE_BSSID])
2622 return;
2623
2624 os_memset(&data, 0, sizeof(data));
2625 os_memcpy(data.pmkid_candidate.bssid,
2626 nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);
2627 data.pmkid_candidate.index =
2628 nla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);
2629 data.pmkid_candidate.preauth =
2630 cand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;
2631 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
2632}
2633
2634
2635static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv,
2636 struct nlattr **tb)
2637{
2638 union wpa_event_data data;
2639
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002640 wpa_printf(MSG_DEBUG, "nl80211: Probe client event");
2641
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002642 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
2643 return;
2644
2645 os_memset(&data, 0, sizeof(data));
2646 os_memcpy(data.client_poll.addr,
2647 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2648
2649 wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
2650}
2651
2652
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002653static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
2654 struct nlattr **tb)
2655{
2656 union wpa_event_data data;
2657
2658 wpa_printf(MSG_DEBUG, "nl80211: TDLS operation event");
2659
2660 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_TDLS_OPERATION])
2661 return;
2662
2663 os_memset(&data, 0, sizeof(data));
2664 os_memcpy(data.tdls.peer, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2665 switch (nla_get_u8(tb[NL80211_ATTR_TDLS_OPERATION])) {
2666 case NL80211_TDLS_SETUP:
2667 wpa_printf(MSG_DEBUG, "nl80211: TDLS setup request for peer "
2668 MACSTR, MAC2STR(data.tdls.peer));
2669 data.tdls.oper = TDLS_REQUEST_SETUP;
2670 break;
2671 case NL80211_TDLS_TEARDOWN:
2672 wpa_printf(MSG_DEBUG, "nl80211: TDLS teardown request for peer "
2673 MACSTR, MAC2STR(data.tdls.peer));
2674 data.tdls.oper = TDLS_REQUEST_TEARDOWN;
2675 break;
2676 default:
2677 wpa_printf(MSG_DEBUG, "nl80211: Unsupported TDLS operatione "
2678 "event");
2679 return;
2680 }
2681 if (tb[NL80211_ATTR_REASON_CODE]) {
2682 data.tdls.reason_code =
2683 nla_get_u16(tb[NL80211_ATTR_REASON_CODE]);
2684 }
2685
2686 wpa_supplicant_event(drv->ctx, EVENT_TDLS, &data);
2687}
2688
2689
Dmitry Shmidt5393a0f2013-08-08 11:23:34 -07002690static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
2691 struct nlattr **tb)
2692{
2693 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
2694}
2695
2696
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002697static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data *drv,
2698 struct nlattr **tb)
2699{
2700 union wpa_event_data data;
2701 u32 reason;
2702
2703 wpa_printf(MSG_DEBUG, "nl80211: Connect failed event");
2704
2705 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_CONN_FAILED_REASON])
2706 return;
2707
2708 os_memset(&data, 0, sizeof(data));
2709 os_memcpy(data.connect_failed_reason.addr,
2710 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2711
2712 reason = nla_get_u32(tb[NL80211_ATTR_CONN_FAILED_REASON]);
2713 switch (reason) {
2714 case NL80211_CONN_FAIL_MAX_CLIENTS:
2715 wpa_printf(MSG_DEBUG, "nl80211: Max client reached");
2716 data.connect_failed_reason.code = MAX_CLIENT_REACHED;
2717 break;
2718 case NL80211_CONN_FAIL_BLOCKED_CLIENT:
2719 wpa_printf(MSG_DEBUG, "nl80211: Blocked client " MACSTR
2720 " tried to connect",
2721 MAC2STR(data.connect_failed_reason.addr));
2722 data.connect_failed_reason.code = BLOCKED_CLIENT;
2723 break;
2724 default:
2725 wpa_printf(MSG_DEBUG, "nl8021l: Unknown connect failed reason "
2726 "%u", reason);
2727 return;
2728 }
2729
2730 wpa_supplicant_event(drv->ctx, EVENT_CONNECT_FAILED_REASON, &data);
2731}
2732
2733
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002734static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
2735 struct nlattr **tb)
2736{
2737 union wpa_event_data data;
2738 enum nl80211_radar_event event_type;
2739
2740 if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
2741 return;
2742
2743 os_memset(&data, 0, sizeof(data));
Dmitry Shmidt051af732013-10-22 13:52:46 -07002744 data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
2745 event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002746
Dmitry Shmidt051af732013-10-22 13:52:46 -07002747 /* Check HT params */
2748 if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
2749 data.dfs_event.ht_enabled = 1;
2750 data.dfs_event.chan_offset = 0;
2751
2752 switch (nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
2753 case NL80211_CHAN_NO_HT:
2754 data.dfs_event.ht_enabled = 0;
2755 break;
2756 case NL80211_CHAN_HT20:
2757 break;
2758 case NL80211_CHAN_HT40PLUS:
2759 data.dfs_event.chan_offset = 1;
2760 break;
2761 case NL80211_CHAN_HT40MINUS:
2762 data.dfs_event.chan_offset = -1;
2763 break;
2764 }
2765 }
2766
2767 /* Get VHT params */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002768 if (tb[NL80211_ATTR_CHANNEL_WIDTH])
2769 data.dfs_event.chan_width =
2770 convert2width(nla_get_u32(
2771 tb[NL80211_ATTR_CHANNEL_WIDTH]));
2772 if (tb[NL80211_ATTR_CENTER_FREQ1])
2773 data.dfs_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002774 if (tb[NL80211_ATTR_CENTER_FREQ2])
2775 data.dfs_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
2776
2777 wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
2778 data.dfs_event.freq, data.dfs_event.ht_enabled,
2779 data.dfs_event.chan_offset, data.dfs_event.chan_width,
2780 data.dfs_event.cf1, data.dfs_event.cf2);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002781
2782 switch (event_type) {
2783 case NL80211_RADAR_DETECTED:
2784 wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
2785 break;
2786 case NL80211_RADAR_CAC_FINISHED:
2787 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
2788 break;
2789 case NL80211_RADAR_CAC_ABORTED:
2790 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
2791 break;
2792 case NL80211_RADAR_NOP_FINISHED:
2793 wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
2794 break;
2795 default:
2796 wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
2797 "received", event_type);
2798 break;
2799 }
2800}
2801
2802
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002803static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
2804 int wds)
2805{
2806 struct wpa_driver_nl80211_data *drv = bss->drv;
2807 union wpa_event_data event;
2808
2809 if (!tb[NL80211_ATTR_MAC])
2810 return;
2811
2812 os_memset(&event, 0, sizeof(event));
2813 event.rx_from_unknown.bssid = bss->addr;
2814 event.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]);
2815 event.rx_from_unknown.wds = wds;
2816
2817 wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
2818}
2819
2820
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002821static void qca_nl80211_avoid_freq(struct wpa_driver_nl80211_data *drv,
2822 const u8 *data, size_t len)
2823{
2824 u32 i, count;
2825 union wpa_event_data event;
2826 struct wpa_freq_range *range = NULL;
2827 const struct qca_avoid_freq_list *freq_range;
2828
2829 freq_range = (const struct qca_avoid_freq_list *) data;
2830 if (len < sizeof(freq_range->count))
2831 return;
2832
2833 count = freq_range->count;
2834 if (len < sizeof(freq_range->count) +
2835 count * sizeof(struct qca_avoid_freq_range)) {
2836 wpa_printf(MSG_DEBUG, "nl80211: Ignored too short avoid frequency list (len=%u)",
2837 (unsigned int) len);
2838 return;
2839 }
2840
2841 if (count > 0) {
2842 range = os_calloc(count, sizeof(struct wpa_freq_range));
2843 if (range == NULL)
2844 return;
2845 }
2846
2847 os_memset(&event, 0, sizeof(event));
2848 for (i = 0; i < count; i++) {
2849 unsigned int idx = event.freq_range.num;
2850 range[idx].min = freq_range->range[i].start_freq;
2851 range[idx].max = freq_range->range[i].end_freq;
2852 wpa_printf(MSG_DEBUG, "nl80211: Avoid frequency range: %u-%u",
2853 range[idx].min, range[idx].max);
2854 if (range[idx].min > range[idx].max) {
2855 wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid frequency range");
2856 continue;
2857 }
2858 event.freq_range.num++;
2859 }
2860 event.freq_range.range = range;
2861
2862 wpa_supplicant_event(drv->ctx, EVENT_AVOID_FREQUENCIES, &event);
2863
2864 os_free(range);
2865}
2866
2867
2868static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
2869 u32 subcmd, u8 *data, size_t len)
2870{
2871 switch (subcmd) {
2872 case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY:
2873 qca_nl80211_avoid_freq(drv, data, len);
2874 break;
2875 default:
2876 wpa_printf(MSG_DEBUG,
2877 "nl80211: Ignore unsupported QCA vendor event %u",
2878 subcmd);
2879 break;
2880 }
2881}
2882
2883
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002884static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
2885 struct nlattr **tb)
2886{
2887 u32 vendor_id, subcmd, wiphy = 0;
2888 int wiphy_idx;
2889 u8 *data = NULL;
2890 size_t len = 0;
2891
2892 if (!tb[NL80211_ATTR_VENDOR_ID] ||
2893 !tb[NL80211_ATTR_VENDOR_SUBCMD])
2894 return;
2895
2896 vendor_id = nla_get_u32(tb[NL80211_ATTR_VENDOR_ID]);
2897 subcmd = nla_get_u32(tb[NL80211_ATTR_VENDOR_SUBCMD]);
2898
2899 if (tb[NL80211_ATTR_WIPHY])
2900 wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
2901
2902 wpa_printf(MSG_DEBUG, "nl80211: Vendor event: wiphy=%u vendor_id=0x%x subcmd=%u",
2903 wiphy, vendor_id, subcmd);
2904
2905 if (tb[NL80211_ATTR_VENDOR_DATA]) {
2906 data = nla_data(tb[NL80211_ATTR_VENDOR_DATA]);
2907 len = nla_len(tb[NL80211_ATTR_VENDOR_DATA]);
2908 wpa_hexdump(MSG_MSGDUMP, "nl80211: Vendor data", data, len);
2909 }
2910
2911 wiphy_idx = nl80211_get_wiphy_index(drv->first_bss);
2912 if (wiphy_idx >= 0 && wiphy_idx != (int) wiphy) {
2913 wpa_printf(MSG_DEBUG, "nl80211: Ignore vendor event for foreign wiphy %u (own: %d)",
2914 wiphy, wiphy_idx);
2915 return;
2916 }
2917
2918 switch (vendor_id) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002919 case OUI_QCA:
2920 nl80211_vendor_event_qca(drv, subcmd, data, len);
2921 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002922 default:
2923 wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
2924 break;
2925 }
2926}
2927
2928
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07002929static void nl80211_reg_change_event(struct wpa_driver_nl80211_data *drv,
2930 struct nlattr *tb[])
2931{
2932 union wpa_event_data data;
2933 enum nl80211_reg_initiator init;
2934
2935 wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
2936
2937 if (tb[NL80211_ATTR_REG_INITIATOR] == NULL)
2938 return;
2939
2940 os_memset(&data, 0, sizeof(data));
2941 init = nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]);
2942 wpa_printf(MSG_DEBUG, " * initiator=%d", init);
2943 switch (init) {
2944 case NL80211_REGDOM_SET_BY_CORE:
2945 data.channel_list_changed.initiator = REGDOM_SET_BY_CORE;
2946 break;
2947 case NL80211_REGDOM_SET_BY_USER:
2948 data.channel_list_changed.initiator = REGDOM_SET_BY_USER;
2949 break;
2950 case NL80211_REGDOM_SET_BY_DRIVER:
2951 data.channel_list_changed.initiator = REGDOM_SET_BY_DRIVER;
2952 break;
2953 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
2954 data.channel_list_changed.initiator = REGDOM_SET_BY_COUNTRY_IE;
2955 break;
2956 }
2957
2958 if (tb[NL80211_ATTR_REG_TYPE]) {
2959 enum nl80211_reg_type type;
2960 type = nla_get_u8(tb[NL80211_ATTR_REG_TYPE]);
2961 wpa_printf(MSG_DEBUG, " * type=%d", type);
2962 switch (type) {
2963 case NL80211_REGDOM_TYPE_COUNTRY:
2964 data.channel_list_changed.type = REGDOM_TYPE_COUNTRY;
2965 break;
2966 case NL80211_REGDOM_TYPE_WORLD:
2967 data.channel_list_changed.type = REGDOM_TYPE_WORLD;
2968 break;
2969 case NL80211_REGDOM_TYPE_CUSTOM_WORLD:
2970 data.channel_list_changed.type =
2971 REGDOM_TYPE_CUSTOM_WORLD;
2972 break;
2973 case NL80211_REGDOM_TYPE_INTERSECTION:
2974 data.channel_list_changed.type =
2975 REGDOM_TYPE_INTERSECTION;
2976 break;
2977 }
2978 }
2979
2980 if (tb[NL80211_ATTR_REG_ALPHA2]) {
2981 os_strlcpy(data.channel_list_changed.alpha2,
2982 nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]),
2983 sizeof(data.channel_list_changed.alpha2));
2984 wpa_printf(MSG_DEBUG, " * alpha2=%s",
2985 data.channel_list_changed.alpha2);
2986 }
2987
2988 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, &data);
2989}
2990
2991
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002992static void do_process_drv_event(struct i802_bss *bss, int cmd,
2993 struct nlattr **tb)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002994{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002995 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002996 union wpa_event_data data;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002997
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002998 wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
2999 cmd, nl80211_command_to_string(cmd), bss->ifname);
3000
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003001 if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
3002 (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
3003 cmd == NL80211_CMD_SCAN_ABORTED)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003004 wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003005 drv->ap_scan_as_station);
3006 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 }
3008
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003009 switch (cmd) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003010 case NL80211_CMD_TRIGGER_SCAN:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003011 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
Dmitry Shmidt56052862013-10-04 10:23:25 -07003012 drv->scan_state = SCAN_STARTED;
Dmitry Shmidt6cb1f652014-03-21 10:54:03 -07003013 if (drv->scan_for_auth) {
3014 /*
3015 * Cannot indicate EVENT_SCAN_STARTED here since we skip
3016 * EVENT_SCAN_RESULTS in scan_for_auth case and the
3017 * upper layer implementation could get confused about
3018 * scanning state.
3019 */
3020 wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
3021 break;
3022 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003023 wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003024 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003025 case NL80211_CMD_START_SCHED_SCAN:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003026 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
Dmitry Shmidt56052862013-10-04 10:23:25 -07003027 drv->scan_state = SCHED_SCAN_STARTED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003028 break;
3029 case NL80211_CMD_SCHED_SCAN_STOPPED:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003030 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
Dmitry Shmidt56052862013-10-04 10:23:25 -07003031 drv->scan_state = SCHED_SCAN_STOPPED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003032 wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
3033 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003034 case NL80211_CMD_NEW_SCAN_RESULTS:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003035 wpa_dbg(drv->ctx, MSG_DEBUG,
3036 "nl80211: New scan results available");
Dmitry Shmidt56052862013-10-04 10:23:25 -07003037 drv->scan_state = SCAN_COMPLETED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003038 drv->scan_complete_events = 1;
3039 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
3040 drv->ctx);
3041 send_scan_event(drv, 0, tb);
3042 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003043 case NL80211_CMD_SCHED_SCAN_RESULTS:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003044 wpa_dbg(drv->ctx, MSG_DEBUG,
3045 "nl80211: New sched scan results available");
Dmitry Shmidt56052862013-10-04 10:23:25 -07003046 drv->scan_state = SCHED_SCAN_RESULTS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003047 send_scan_event(drv, 0, tb);
3048 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003049 case NL80211_CMD_SCAN_ABORTED:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003050 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
Dmitry Shmidt56052862013-10-04 10:23:25 -07003051 drv->scan_state = SCAN_ABORTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052 /*
3053 * Need to indicate that scan results are available in order
3054 * not to make wpa_supplicant stop its scanning.
3055 */
3056 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
3057 drv->ctx);
3058 send_scan_event(drv, 1, tb);
3059 break;
3060 case NL80211_CMD_AUTHENTICATE:
3061 case NL80211_CMD_ASSOCIATE:
3062 case NL80211_CMD_DEAUTHENTICATE:
3063 case NL80211_CMD_DISASSOCIATE:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003064 case NL80211_CMD_FRAME_TX_STATUS:
3065 case NL80211_CMD_UNPROT_DEAUTHENTICATE:
3066 case NL80211_CMD_UNPROT_DISASSOCIATE:
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003067 mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003068 tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
3069 tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
Dmitry Shmidt04949592012-07-19 12:16:46 -07003070 tb[NL80211_ATTR_COOKIE],
3071 tb[NL80211_ATTR_RX_SIGNAL_DBM]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003072 break;
3073 case NL80211_CMD_CONNECT:
3074 case NL80211_CMD_ROAM:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003075 mlme_event_connect(drv, cmd,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003076 tb[NL80211_ATTR_STATUS_CODE],
3077 tb[NL80211_ATTR_MAC],
3078 tb[NL80211_ATTR_REQ_IE],
3079 tb[NL80211_ATTR_RESP_IE]);
3080 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003081 case NL80211_CMD_CH_SWITCH_NOTIFY:
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08003082 mlme_event_ch_switch(drv,
3083 tb[NL80211_ATTR_IFINDEX],
3084 tb[NL80211_ATTR_WIPHY_FREQ],
3085 tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
3086 tb[NL80211_ATTR_CHANNEL_WIDTH],
3087 tb[NL80211_ATTR_CENTER_FREQ1],
3088 tb[NL80211_ATTR_CENTER_FREQ2]);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003089 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003090 case NL80211_CMD_DISCONNECT:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003091 mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003092 tb[NL80211_ATTR_MAC],
3093 tb[NL80211_ATTR_DISCONNECTED_BY_AP]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003094 break;
3095 case NL80211_CMD_MICHAEL_MIC_FAILURE:
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003096 mlme_event_michael_mic_failure(bss, tb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003097 break;
3098 case NL80211_CMD_JOIN_IBSS:
3099 mlme_event_join_ibss(drv, tb);
3100 break;
3101 case NL80211_CMD_REMAIN_ON_CHANNEL:
3102 mlme_event_remain_on_channel(drv, 0, tb);
3103 break;
3104 case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:
3105 mlme_event_remain_on_channel(drv, 1, tb);
3106 break;
3107 case NL80211_CMD_NOTIFY_CQM:
3108 nl80211_cqm_event(drv, tb);
3109 break;
3110 case NL80211_CMD_REG_CHANGE:
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07003111 nl80211_reg_change_event(drv, tb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003112 break;
3113 case NL80211_CMD_REG_BEACON_HINT:
3114 wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint");
Dmitry Shmidt97672262014-02-03 13:02:54 -08003115 os_memset(&data, 0, sizeof(data));
3116 data.channel_list_changed.initiator = REGDOM_BEACON_HINT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003117 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
Dmitry Shmidt97672262014-02-03 13:02:54 -08003118 &data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003119 break;
3120 case NL80211_CMD_NEW_STATION:
3121 nl80211_new_station_event(drv, tb);
3122 break;
3123 case NL80211_CMD_DEL_STATION:
3124 nl80211_del_station_event(drv, tb);
3125 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003126 case NL80211_CMD_SET_REKEY_OFFLOAD:
3127 nl80211_rekey_offload_event(drv, tb);
3128 break;
3129 case NL80211_CMD_PMKSA_CANDIDATE:
3130 nl80211_pmksa_candidate_event(drv, tb);
3131 break;
3132 case NL80211_CMD_PROBE_CLIENT:
3133 nl80211_client_probe_event(drv, tb);
3134 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003135 case NL80211_CMD_TDLS_OPER:
3136 nl80211_tdls_oper_event(drv, tb);
3137 break;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003138 case NL80211_CMD_CONN_FAILED:
3139 nl80211_connect_failed_event(drv, tb);
3140 break;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003141 case NL80211_CMD_FT_EVENT:
3142 mlme_event_ft_event(drv, tb);
3143 break;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003144 case NL80211_CMD_RADAR_DETECT:
3145 nl80211_radar_event(drv, tb);
3146 break;
Dmitry Shmidt5393a0f2013-08-08 11:23:34 -07003147 case NL80211_CMD_STOP_AP:
3148 nl80211_stop_ap(drv, tb);
3149 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003150 case NL80211_CMD_VENDOR:
3151 nl80211_vendor_event(drv, tb);
3152 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003153 default:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003154 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
3155 "(cmd=%d)", cmd);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003156 break;
3157 }
3158}
3159
3160
3161static int process_drv_event(struct nl_msg *msg, void *arg)
3162{
3163 struct wpa_driver_nl80211_data *drv = arg;
3164 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3165 struct nlattr *tb[NL80211_ATTR_MAX + 1];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003166 struct i802_bss *bss;
3167 int ifidx = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003168
3169 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3170 genlmsg_attrlen(gnlh, 0), NULL);
3171
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003172 if (tb[NL80211_ATTR_IFINDEX]) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003173 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
3174
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003175 for (bss = drv->first_bss; bss; bss = bss->next)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003176 if (ifidx == -1 || ifidx == bss->ifindex) {
3177 do_process_drv_event(bss, gnlh->cmd, tb);
3178 return NL_SKIP;
3179 }
3180 wpa_printf(MSG_DEBUG,
3181 "nl80211: Ignored event (cmd=%d) for foreign interface (ifindex %d)",
3182 gnlh->cmd, ifidx);
3183 } else if (tb[NL80211_ATTR_WDEV]) {
3184 u64 wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
3185 wpa_printf(MSG_DEBUG, "nl80211: Process event on P2P device");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003186 for (bss = drv->first_bss; bss; bss = bss->next) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003187 if (bss->wdev_id_set && wdev_id == bss->wdev_id) {
3188 do_process_drv_event(bss, gnlh->cmd, tb);
3189 return NL_SKIP;
3190 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003191 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003192 wpa_printf(MSG_DEBUG,
3193 "nl80211: Ignored event (cmd=%d) for foreign interface (wdev 0x%llx)",
3194 gnlh->cmd, (long long unsigned int) wdev_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003195 }
3196
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003197 return NL_SKIP;
3198}
3199
3200
3201static int process_global_event(struct nl_msg *msg, void *arg)
3202{
3203 struct nl80211_global *global = arg;
3204 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3205 struct nlattr *tb[NL80211_ATTR_MAX + 1];
Dmitry Shmidt04949592012-07-19 12:16:46 -07003206 struct wpa_driver_nl80211_data *drv, *tmp;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003207 int ifidx = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003208 struct i802_bss *bss;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003209 u64 wdev_id = 0;
3210 int wdev_id_set = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003211
3212 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3213 genlmsg_attrlen(gnlh, 0), NULL);
3214
3215 if (tb[NL80211_ATTR_IFINDEX])
3216 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003217 else if (tb[NL80211_ATTR_WDEV]) {
3218 wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
3219 wdev_id_set = 1;
3220 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003221
Dmitry Shmidt04949592012-07-19 12:16:46 -07003222 dl_list_for_each_safe(drv, tmp, &global->interfaces,
3223 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003224 for (bss = drv->first_bss; bss; bss = bss->next) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003225 if ((ifidx == -1 && !wdev_id_set) ||
3226 ifidx == bss->ifindex ||
3227 (wdev_id_set && bss->wdev_id_set &&
3228 wdev_id == bss->wdev_id)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003229 do_process_drv_event(bss, gnlh->cmd, tb);
3230 return NL_SKIP;
3231 }
3232 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003233 }
3234
3235 return NL_SKIP;
3236}
3237
3238
3239static int process_bss_event(struct nl_msg *msg, void *arg)
3240{
3241 struct i802_bss *bss = arg;
3242 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3243 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3244
3245 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3246 genlmsg_attrlen(gnlh, 0), NULL);
3247
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003248 wpa_printf(MSG_DEBUG, "nl80211: BSS Event %d (%s) received for %s",
3249 gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
3250 bss->ifname);
3251
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003252 switch (gnlh->cmd) {
3253 case NL80211_CMD_FRAME:
3254 case NL80211_CMD_FRAME_TX_STATUS:
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003255 mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003256 tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
3257 tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
Dmitry Shmidt04949592012-07-19 12:16:46 -07003258 tb[NL80211_ATTR_COOKIE],
3259 tb[NL80211_ATTR_RX_SIGNAL_DBM]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003260 break;
3261 case NL80211_CMD_UNEXPECTED_FRAME:
3262 nl80211_spurious_frame(bss, tb, 0);
3263 break;
3264 case NL80211_CMD_UNEXPECTED_4ADDR_FRAME:
3265 nl80211_spurious_frame(bss, tb, 1);
3266 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003267 default:
3268 wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
3269 "(cmd=%d)", gnlh->cmd);
3270 break;
3271 }
3272
3273 return NL_SKIP;
3274}
3275
3276
3277static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
3278 void *handle)
3279{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003280 struct nl_cb *cb = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003281 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003282
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003283 wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003284
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003285 res = nl_recvmsgs(handle, cb);
Dmitry Shmidt71757432014-06-02 13:50:35 -07003286 if (res < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003287 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
3288 __func__, res);
3289 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003290}
3291
3292
3293/**
3294 * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
3295 * @priv: driver_nl80211 private data
3296 * @alpha2_arg: country to which to switch to
3297 * Returns: 0 on success, -1 on failure
3298 *
3299 * This asks nl80211 to set the regulatory domain for given
3300 * country ISO / IEC alpha2.
3301 */
3302static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
3303{
3304 struct i802_bss *bss = priv;
3305 struct wpa_driver_nl80211_data *drv = bss->drv;
3306 char alpha2[3];
3307 struct nl_msg *msg;
3308
3309 msg = nlmsg_alloc();
3310 if (!msg)
3311 return -ENOMEM;
3312
3313 alpha2[0] = alpha2_arg[0];
3314 alpha2[1] = alpha2_arg[1];
3315 alpha2[2] = '\0';
3316
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003317 nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003318
3319 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
3320 if (send_and_recv_msgs(drv, msg, NULL, NULL))
3321 return -EINVAL;
3322 return 0;
3323nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003324 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003325 return -EINVAL;
3326}
3327
3328
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003329static int nl80211_get_country(struct nl_msg *msg, void *arg)
3330{
3331 char *alpha2 = arg;
3332 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
3333 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3334
3335 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3336 genlmsg_attrlen(gnlh, 0), NULL);
3337 if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) {
3338 wpa_printf(MSG_DEBUG, "nl80211: No country information available");
3339 return NL_SKIP;
3340 }
3341 os_strlcpy(alpha2, nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]), 3);
3342 return NL_SKIP;
3343}
3344
3345
3346static int wpa_driver_nl80211_get_country(void *priv, char *alpha2)
3347{
3348 struct i802_bss *bss = priv;
3349 struct wpa_driver_nl80211_data *drv = bss->drv;
3350 struct nl_msg *msg;
3351 int ret;
3352
3353 msg = nlmsg_alloc();
3354 if (!msg)
3355 return -ENOMEM;
3356
3357 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
3358 alpha2[0] = '\0';
3359 ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2);
3360 if (!alpha2[0])
3361 ret = -1;
3362
3363 return ret;
3364}
3365
3366
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003367static int protocol_feature_handler(struct nl_msg *msg, void *arg)
3368{
3369 u32 *feat = arg;
3370 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
3371 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3372
3373 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3374 genlmsg_attrlen(gnlh, 0), NULL);
3375
3376 if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES])
3377 *feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]);
3378
3379 return NL_SKIP;
3380}
3381
3382
3383static u32 get_nl80211_protocol_features(struct wpa_driver_nl80211_data *drv)
3384{
3385 u32 feat = 0;
3386 struct nl_msg *msg;
3387
3388 msg = nlmsg_alloc();
3389 if (!msg)
3390 goto nla_put_failure;
3391
3392 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_PROTOCOL_FEATURES);
3393 if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat) == 0)
3394 return feat;
3395
3396 msg = NULL;
3397nla_put_failure:
3398 nlmsg_free(msg);
3399 return 0;
3400}
3401
3402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003403struct wiphy_info_data {
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003404 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003405 struct wpa_driver_capa *capa;
3406
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003407 unsigned int num_multichan_concurrent;
3408
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003409 unsigned int error:1;
3410 unsigned int device_ap_sme:1;
3411 unsigned int poll_command_supported:1;
3412 unsigned int data_tx_status:1;
3413 unsigned int monitor_supported:1;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003414 unsigned int auth_supported:1;
3415 unsigned int connect_supported:1;
3416 unsigned int p2p_go_supported:1;
3417 unsigned int p2p_client_supported:1;
3418 unsigned int p2p_concurrent:1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003419 unsigned int channel_switch_supported:1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003420 unsigned int set_qos_map_supported:1;
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003421 unsigned int have_low_prio_scan:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003422};
3423
3424
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003425static unsigned int probe_resp_offload_support(int supp_protocols)
3426{
3427 unsigned int prot = 0;
3428
3429 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS)
3430 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS;
3431 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)
3432 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2;
3433 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P)
3434 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P;
3435 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U)
3436 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING;
3437
3438 return prot;
3439}
3440
3441
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003442static void wiphy_info_supported_iftypes(struct wiphy_info_data *info,
3443 struct nlattr *tb)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003444{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003445 struct nlattr *nl_mode;
3446 int i;
3447
3448 if (tb == NULL)
3449 return;
3450
3451 nla_for_each_nested(nl_mode, tb, i) {
3452 switch (nla_type(nl_mode)) {
3453 case NL80211_IFTYPE_AP:
3454 info->capa->flags |= WPA_DRIVER_FLAGS_AP;
3455 break;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003456 case NL80211_IFTYPE_ADHOC:
3457 info->capa->flags |= WPA_DRIVER_FLAGS_IBSS;
3458 break;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003459 case NL80211_IFTYPE_P2P_DEVICE:
3460 info->capa->flags |=
3461 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
3462 break;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003463 case NL80211_IFTYPE_P2P_GO:
3464 info->p2p_go_supported = 1;
3465 break;
3466 case NL80211_IFTYPE_P2P_CLIENT:
3467 info->p2p_client_supported = 1;
3468 break;
3469 case NL80211_IFTYPE_MONITOR:
3470 info->monitor_supported = 1;
3471 break;
3472 }
3473 }
3474}
3475
3476
3477static int wiphy_info_iface_comb_process(struct wiphy_info_data *info,
3478 struct nlattr *nl_combi)
3479{
3480 struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
3481 struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
3482 struct nlattr *nl_limit, *nl_mode;
3483 int err, rem_limit, rem_mode;
3484 int combination_has_p2p = 0, combination_has_mgd = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003485 static struct nla_policy
3486 iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
3487 [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
3488 [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
3489 [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
3490 [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003491 [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003492 },
3493 iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
3494 [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
3495 [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
3496 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003497
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003498 err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
3499 nl_combi, iface_combination_policy);
3500 if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
3501 !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
3502 !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
3503 return 0; /* broken combination */
3504
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003505 if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS])
3506 info->capa->flags |= WPA_DRIVER_FLAGS_RADAR;
3507
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003508 nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS],
3509 rem_limit) {
3510 err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
3511 nl_limit, iface_limit_policy);
3512 if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES])
3513 return 0; /* broken combination */
3514
3515 nla_for_each_nested(nl_mode,
3516 tb_limit[NL80211_IFACE_LIMIT_TYPES],
3517 rem_mode) {
3518 int ift = nla_type(nl_mode);
3519 if (ift == NL80211_IFTYPE_P2P_GO ||
3520 ift == NL80211_IFTYPE_P2P_CLIENT)
3521 combination_has_p2p = 1;
3522 if (ift == NL80211_IFTYPE_STATION)
3523 combination_has_mgd = 1;
3524 }
3525 if (combination_has_p2p && combination_has_mgd)
3526 break;
3527 }
3528
3529 if (combination_has_p2p && combination_has_mgd) {
Dmitry Shmidt413dde72014-04-11 10:23:22 -07003530 unsigned int num_channels =
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003531 nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]);
Dmitry Shmidt413dde72014-04-11 10:23:22 -07003532
3533 info->p2p_concurrent = 1;
3534 if (info->num_multichan_concurrent < num_channels)
3535 info->num_multichan_concurrent = num_channels;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003536 }
3537
3538 return 0;
3539}
3540
3541
3542static void wiphy_info_iface_comb(struct wiphy_info_data *info,
3543 struct nlattr *tb)
3544{
3545 struct nlattr *nl_combi;
3546 int rem_combi;
3547
3548 if (tb == NULL)
3549 return;
3550
3551 nla_for_each_nested(nl_combi, tb, rem_combi) {
3552 if (wiphy_info_iface_comb_process(info, nl_combi) > 0)
3553 break;
3554 }
3555}
3556
3557
3558static void wiphy_info_supp_cmds(struct wiphy_info_data *info,
3559 struct nlattr *tb)
3560{
3561 struct nlattr *nl_cmd;
3562 int i;
3563
3564 if (tb == NULL)
3565 return;
3566
3567 nla_for_each_nested(nl_cmd, tb, i) {
3568 switch (nla_get_u32(nl_cmd)) {
3569 case NL80211_CMD_AUTHENTICATE:
3570 info->auth_supported = 1;
3571 break;
3572 case NL80211_CMD_CONNECT:
3573 info->connect_supported = 1;
3574 break;
3575 case NL80211_CMD_START_SCHED_SCAN:
3576 info->capa->sched_scan_supported = 1;
3577 break;
3578 case NL80211_CMD_PROBE_CLIENT:
3579 info->poll_command_supported = 1;
3580 break;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003581 case NL80211_CMD_CHANNEL_SWITCH:
3582 info->channel_switch_supported = 1;
3583 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003584 case NL80211_CMD_SET_QOS_MAP:
3585 info->set_qos_map_supported = 1;
3586 break;
3587 }
3588 }
3589}
3590
3591
3592static void wiphy_info_cipher_suites(struct wiphy_info_data *info,
3593 struct nlattr *tb)
3594{
3595 int i, num;
3596 u32 *ciphers;
3597
3598 if (tb == NULL)
3599 return;
3600
3601 num = nla_len(tb) / sizeof(u32);
3602 ciphers = nla_data(tb);
3603 for (i = 0; i < num; i++) {
3604 u32 c = ciphers[i];
3605
3606 wpa_printf(MSG_DEBUG, "nl80211: Supported cipher %02x-%02x-%02x:%d",
3607 c >> 24, (c >> 16) & 0xff,
3608 (c >> 8) & 0xff, c & 0xff);
3609 switch (c) {
3610 case WLAN_CIPHER_SUITE_CCMP_256:
3611 info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP_256;
3612 break;
3613 case WLAN_CIPHER_SUITE_GCMP_256:
3614 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP_256;
3615 break;
3616 case WLAN_CIPHER_SUITE_CCMP:
3617 info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP;
3618 break;
3619 case WLAN_CIPHER_SUITE_GCMP:
3620 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP;
3621 break;
3622 case WLAN_CIPHER_SUITE_TKIP:
3623 info->capa->enc |= WPA_DRIVER_CAPA_ENC_TKIP;
3624 break;
3625 case WLAN_CIPHER_SUITE_WEP104:
3626 info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP104;
3627 break;
3628 case WLAN_CIPHER_SUITE_WEP40:
3629 info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP40;
3630 break;
3631 case WLAN_CIPHER_SUITE_AES_CMAC:
3632 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP;
3633 break;
3634 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
3635 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_128;
3636 break;
3637 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
3638 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_256;
3639 break;
3640 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
3641 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_CMAC_256;
3642 break;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003643 case WLAN_CIPHER_SUITE_NO_GROUP_ADDR:
3644 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GTK_NOT_USED;
3645 break;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003646 }
3647 }
3648}
3649
3650
3651static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
3652 struct nlattr *tb)
3653{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003654 if (tb)
3655 capa->max_remain_on_chan = nla_get_u32(tb);
3656}
3657
3658
3659static void wiphy_info_tdls(struct wpa_driver_capa *capa, struct nlattr *tdls,
3660 struct nlattr *ext_setup)
3661{
3662 if (tdls == NULL)
3663 return;
3664
3665 wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
3666 capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
3667
3668 if (ext_setup) {
3669 wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
3670 capa->flags |= WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
3671 }
3672}
3673
3674
3675static void wiphy_info_feature_flags(struct wiphy_info_data *info,
3676 struct nlattr *tb)
3677{
3678 u32 flags;
3679 struct wpa_driver_capa *capa = info->capa;
3680
3681 if (tb == NULL)
3682 return;
3683
3684 flags = nla_get_u32(tb);
3685
3686 if (flags & NL80211_FEATURE_SK_TX_STATUS)
3687 info->data_tx_status = 1;
3688
3689 if (flags & NL80211_FEATURE_INACTIVITY_TIMER)
3690 capa->flags |= WPA_DRIVER_FLAGS_INACTIVITY_TIMER;
3691
3692 if (flags & NL80211_FEATURE_SAE)
3693 capa->flags |= WPA_DRIVER_FLAGS_SAE;
3694
3695 if (flags & NL80211_FEATURE_NEED_OBSS_SCAN)
3696 capa->flags |= WPA_DRIVER_FLAGS_OBSS_SCAN;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003697
3698 if (flags & NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE)
3699 capa->flags |= WPA_DRIVER_FLAGS_HT_2040_COEX;
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003700
3701 if (flags & NL80211_FEATURE_LOW_PRIORITY_SCAN)
3702 info->have_low_prio_scan = 1;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003703}
3704
3705
3706static void wiphy_info_probe_resp_offload(struct wpa_driver_capa *capa,
3707 struct nlattr *tb)
3708{
3709 u32 protocols;
3710
3711 if (tb == NULL)
3712 return;
3713
3714 protocols = nla_get_u32(tb);
3715 wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response offload in AP "
3716 "mode");
3717 capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
3718 capa->probe_resp_offloads = probe_resp_offload_support(protocols);
3719}
3720
3721
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003722static void wiphy_info_wowlan_triggers(struct wpa_driver_capa *capa,
3723 struct nlattr *tb)
3724{
3725 struct nlattr *triggers[MAX_NL80211_WOWLAN_TRIG + 1];
3726
3727 if (tb == NULL)
3728 return;
3729
3730 if (nla_parse_nested(triggers, MAX_NL80211_WOWLAN_TRIG,
3731 tb, NULL))
3732 return;
3733
3734 if (triggers[NL80211_WOWLAN_TRIG_ANY])
3735 capa->wowlan_triggers.any = 1;
3736 if (triggers[NL80211_WOWLAN_TRIG_DISCONNECT])
3737 capa->wowlan_triggers.disconnect = 1;
3738 if (triggers[NL80211_WOWLAN_TRIG_MAGIC_PKT])
3739 capa->wowlan_triggers.magic_pkt = 1;
3740 if (triggers[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE])
3741 capa->wowlan_triggers.gtk_rekey_failure = 1;
3742 if (triggers[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST])
3743 capa->wowlan_triggers.eap_identity_req = 1;
3744 if (triggers[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE])
3745 capa->wowlan_triggers.four_way_handshake = 1;
3746 if (triggers[NL80211_WOWLAN_TRIG_RFKILL_RELEASE])
3747 capa->wowlan_triggers.rfkill_release = 1;
3748}
3749
3750
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003751static int wiphy_info_handler(struct nl_msg *msg, void *arg)
3752{
3753 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3754 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3755 struct wiphy_info_data *info = arg;
3756 struct wpa_driver_capa *capa = info->capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003757 struct wpa_driver_nl80211_data *drv = info->drv;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003758
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003759 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3760 genlmsg_attrlen(gnlh, 0), NULL);
3761
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003762 if (tb[NL80211_ATTR_WIPHY_NAME])
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003763 os_strlcpy(drv->phyname,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003764 nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
3765 sizeof(drv->phyname));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003766 if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003767 capa->max_scan_ssids =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003768 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
3769
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003770 if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])
3771 capa->max_sched_scan_ssids =
3772 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
3773
3774 if (tb[NL80211_ATTR_MAX_MATCH_SETS])
3775 capa->max_match_sets =
3776 nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
3777
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003778 if (tb[NL80211_ATTR_MAC_ACL_MAX])
3779 capa->max_acl_mac_addrs =
3780 nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
3781
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003782 wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
3783 wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
3784 wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003785 wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003786
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003787 if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
3788 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
3789 "off-channel TX");
3790 capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
3791 }
3792
3793 if (tb[NL80211_ATTR_ROAM_SUPPORT]) {
3794 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming");
3795 capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
3796 }
3797
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003798 wiphy_info_max_roc(capa,
3799 tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003800
3801 if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
3802 capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003803
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003804 wiphy_info_tdls(capa, tb[NL80211_ATTR_TDLS_SUPPORT],
3805 tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]);
Dmitry Shmidtad266fb2012-08-24 17:03:35 -07003806
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003807 if (tb[NL80211_ATTR_DEVICE_AP_SME])
3808 info->device_ap_sme = 1;
3809
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003810 wiphy_info_feature_flags(info, tb[NL80211_ATTR_FEATURE_FLAGS]);
3811 wiphy_info_probe_resp_offload(capa,
3812 tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003813
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003814 if (tb[NL80211_ATTR_EXT_CAPA] && tb[NL80211_ATTR_EXT_CAPA_MASK] &&
3815 drv->extended_capa == NULL) {
3816 drv->extended_capa =
3817 os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3818 if (drv->extended_capa) {
3819 os_memcpy(drv->extended_capa,
3820 nla_data(tb[NL80211_ATTR_EXT_CAPA]),
3821 nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3822 drv->extended_capa_len =
3823 nla_len(tb[NL80211_ATTR_EXT_CAPA]);
3824 }
3825 drv->extended_capa_mask =
3826 os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3827 if (drv->extended_capa_mask) {
3828 os_memcpy(drv->extended_capa_mask,
3829 nla_data(tb[NL80211_ATTR_EXT_CAPA]),
3830 nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3831 } else {
3832 os_free(drv->extended_capa);
3833 drv->extended_capa = NULL;
3834 drv->extended_capa_len = 0;
3835 }
3836 }
3837
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003838 if (tb[NL80211_ATTR_VENDOR_DATA]) {
3839 struct nlattr *nl;
3840 int rem;
3841
3842 nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
3843 struct nl80211_vendor_cmd_info *vinfo;
Dmitry Shmidt18463232014-01-24 12:29:41 -08003844 if (nla_len(nl) != sizeof(*vinfo)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003845 wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
3846 continue;
3847 }
3848 vinfo = nla_data(nl);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003849 if (vinfo->subcmd ==
3850 QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY)
3851 drv->dfs_vendor_cmd_avail = 1;
3852
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003853 wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
3854 vinfo->vendor_id, vinfo->subcmd);
3855 }
3856 }
3857
3858 if (tb[NL80211_ATTR_VENDOR_EVENTS]) {
3859 struct nlattr *nl;
3860 int rem;
3861
3862 nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_EVENTS], rem) {
3863 struct nl80211_vendor_cmd_info *vinfo;
Dmitry Shmidt18463232014-01-24 12:29:41 -08003864 if (nla_len(nl) != sizeof(*vinfo)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003865 wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
3866 continue;
3867 }
3868 vinfo = nla_data(nl);
3869 wpa_printf(MSG_DEBUG, "nl80211: Supported vendor event: vendor_id=0x%x subcmd=%u",
3870 vinfo->vendor_id, vinfo->subcmd);
3871 }
3872 }
3873
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07003874 wiphy_info_wowlan_triggers(capa,
3875 tb[NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED]);
3876
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -07003877 if (tb[NL80211_ATTR_MAX_AP_ASSOC_STA])
3878 capa->max_stations =
3879 nla_get_u32(tb[NL80211_ATTR_MAX_AP_ASSOC_STA]);
3880
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003881 return NL_SKIP;
3882}
3883
3884
3885static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
3886 struct wiphy_info_data *info)
3887{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003888 u32 feat;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003889 struct nl_msg *msg;
3890
3891 os_memset(info, 0, sizeof(*info));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003892 info->capa = &drv->capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003893 info->drv = drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003894
3895 msg = nlmsg_alloc();
3896 if (!msg)
3897 return -1;
3898
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003899 feat = get_nl80211_protocol_features(drv);
3900 if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
3901 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_WIPHY);
3902 else
3903 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003904
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003905 NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003906 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003907 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003908
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003909 if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info))
3910 return -1;
3911
3912 if (info->auth_supported)
3913 drv->capa.flags |= WPA_DRIVER_FLAGS_SME;
3914 else if (!info->connect_supported) {
3915 wpa_printf(MSG_INFO, "nl80211: Driver does not support "
3916 "authentication/association or connect commands");
3917 info->error = 1;
3918 }
3919
3920 if (info->p2p_go_supported && info->p2p_client_supported)
3921 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
3922 if (info->p2p_concurrent) {
3923 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
3924 "interface (driver advertised support)");
3925 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
3926 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
3927 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003928 if (info->num_multichan_concurrent > 1) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003929 wpa_printf(MSG_DEBUG, "nl80211: Enable multi-channel "
3930 "concurrent (driver advertised support)");
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003931 drv->capa.num_multichan_concurrent =
3932 info->num_multichan_concurrent;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003933 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003934
3935 /* default to 5000 since early versions of mac80211 don't set it */
3936 if (!drv->capa.max_remain_on_chan)
3937 drv->capa.max_remain_on_chan = 5000;
3938
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003939 if (info->channel_switch_supported)
3940 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_CSA;
3941
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003942 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003943nla_put_failure:
3944 nlmsg_free(msg);
3945 return -1;
3946}
3947
3948
3949static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
3950{
3951 struct wiphy_info_data info;
3952 if (wpa_driver_nl80211_get_info(drv, &info))
3953 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003954
3955 if (info.error)
3956 return -1;
3957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958 drv->has_capability = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003959 drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3960 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
3961 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
3962 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003963 drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
3964 WPA_DRIVER_AUTH_SHARED |
3965 WPA_DRIVER_AUTH_LEAP;
3966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003967 drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
3968 drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003969 drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
Dmitry Shmidtad266fb2012-08-24 17:03:35 -07003970
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003971 /*
3972 * As all cfg80211 drivers must support cases where the AP interface is
3973 * removed without the knowledge of wpa_supplicant/hostapd, e.g., in
3974 * case that the user space daemon has crashed, they must be able to
3975 * cleanup all stations and key entries in the AP tear down flow. Thus,
3976 * this flag can/should always be set for cfg80211 drivers.
3977 */
3978 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT;
3979
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003980 if (!info.device_ap_sme) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003981 drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003982
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003983 /*
3984 * No AP SME is currently assumed to also indicate no AP MLME
3985 * in the driver/firmware.
3986 */
3987 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_MLME;
3988 }
3989
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003990 drv->device_ap_sme = info.device_ap_sme;
3991 drv->poll_command_supported = info.poll_command_supported;
3992 drv->data_tx_status = info.data_tx_status;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003993 if (info.set_qos_map_supported)
3994 drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003995 drv->have_low_prio_scan = info.have_low_prio_scan;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003996
3997 /*
Dmitry Shmidtaa532512012-09-24 10:35:31 -07003998 * If poll command and tx status are supported, mac80211 is new enough
3999 * to have everything we need to not need monitor interfaces.
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004000 */
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004001 drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004002
4003 if (drv->device_ap_sme && drv->use_monitor) {
4004 /*
4005 * Non-mac80211 drivers may not support monitor interface.
4006 * Make sure we do not get stuck with incorrect capability here
4007 * by explicitly testing this.
4008 */
4009 if (!info.monitor_supported) {
4010 wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor "
4011 "with device_ap_sme since no monitor mode "
4012 "support detected");
4013 drv->use_monitor = 0;
4014 }
4015 }
4016
4017 /*
4018 * If we aren't going to use monitor interfaces, but the
4019 * driver doesn't support data TX status, we won't get TX
4020 * status for EAPOL frames.
4021 */
4022 if (!drv->use_monitor && !info.data_tx_status)
4023 drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024
4025 return 0;
4026}
4027
4028
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004029#ifdef ANDROID
4030static int android_genl_ctrl_resolve(struct nl_handle *handle,
4031 const char *name)
4032{
4033 /*
4034 * Android ICS has very minimal genl_ctrl_resolve() implementation, so
4035 * need to work around that.
4036 */
4037 struct nl_cache *cache = NULL;
4038 struct genl_family *nl80211 = NULL;
4039 int id = -1;
4040
4041 if (genl_ctrl_alloc_cache(handle, &cache) < 0) {
4042 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
4043 "netlink cache");
4044 goto fail;
4045 }
4046
4047 nl80211 = genl_ctrl_search_by_name(cache, name);
4048 if (nl80211 == NULL)
4049 goto fail;
4050
4051 id = genl_family_get_id(nl80211);
4052
4053fail:
4054 if (nl80211)
4055 genl_family_put(nl80211);
4056 if (cache)
4057 nl_cache_free(cache);
4058
4059 return id;
4060}
4061#define genl_ctrl_resolve android_genl_ctrl_resolve
4062#endif /* ANDROID */
4063
4064
4065static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004066{
4067 int ret;
4068
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004069 global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
4070 if (global->nl_cb == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004071 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
4072 "callbacks");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004073 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004074 }
4075
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004076 global->nl = nl_create_handle(global->nl_cb, "nl");
4077 if (global->nl == NULL)
4078 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004079
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004080 global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
4081 if (global->nl80211_id < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004082 wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
4083 "found");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004084 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004085 }
4086
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004087 global->nl_event = nl_create_handle(global->nl_cb, "event");
4088 if (global->nl_event == NULL)
4089 goto err;
4090
4091 ret = nl_get_multicast_id(global, "nl80211", "scan");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004092 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004093 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004094 if (ret < 0) {
4095 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
4096 "membership for scan events: %d (%s)",
4097 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004098 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004099 }
4100
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004101 ret = nl_get_multicast_id(global, "nl80211", "mlme");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004102 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004103 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004104 if (ret < 0) {
4105 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
4106 "membership for mlme events: %d (%s)",
4107 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004108 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004109 }
4110
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004111 ret = nl_get_multicast_id(global, "nl80211", "regulatory");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004113 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004114 if (ret < 0) {
4115 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
4116 "membership for regulatory events: %d (%s)",
4117 ret, strerror(-ret));
4118 /* Continue without regulatory events */
4119 }
4120
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004121 ret = nl_get_multicast_id(global, "nl80211", "vendor");
4122 if (ret >= 0)
4123 ret = nl_socket_add_membership(global->nl_event, ret);
4124 if (ret < 0) {
4125 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
4126 "membership for vendor events: %d (%s)",
4127 ret, strerror(-ret));
4128 /* Continue without vendor events */
4129 }
4130
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004131 nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
4132 no_seq_check, NULL);
4133 nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
4134 process_global_event, global);
4135
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004136 nl80211_register_eloop_read(&global->nl_event,
4137 wpa_driver_nl80211_event_receive,
4138 global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004139
4140 return 0;
4141
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004142err:
4143 nl_destroy_handles(&global->nl_event);
4144 nl_destroy_handles(&global->nl);
4145 nl_cb_put(global->nl_cb);
4146 global->nl_cb = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004147 return -1;
4148}
4149
4150
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004151static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
4152{
4153 drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
4154 if (!drv->nl_cb) {
4155 wpa_printf(MSG_ERROR, "nl80211: Failed to alloc cb struct");
4156 return -1;
4157 }
4158
4159 nl_cb_set(drv->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
4160 no_seq_check, NULL);
4161 nl_cb_set(drv->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
4162 process_drv_event, drv);
4163
4164 return 0;
4165}
4166
4167
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004168static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
4169{
4170 wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
4171 /*
4172 * This may be for any interface; use ifdown event to disable
4173 * interface.
4174 */
4175}
4176
4177
4178static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
4179{
4180 struct wpa_driver_nl80211_data *drv = ctx;
4181 wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004182 if (i802_set_iface_flags(drv->first_bss, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004183 wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
4184 "after rfkill unblock");
4185 return;
4186 }
4187 /* rtnetlink ifup handler will report interface as enabled */
4188}
4189
4190
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004191static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
4192 void *eloop_ctx,
4193 void *handle)
4194{
4195 struct wpa_driver_nl80211_data *drv = eloop_ctx;
4196 u8 data[2048];
4197 struct msghdr msg;
4198 struct iovec entry;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004199 u8 control[512];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004200 struct cmsghdr *cmsg;
4201 int res, found_ee = 0, found_wifi = 0, acked = 0;
4202 union wpa_event_data event;
4203
4204 memset(&msg, 0, sizeof(msg));
4205 msg.msg_iov = &entry;
4206 msg.msg_iovlen = 1;
4207 entry.iov_base = data;
4208 entry.iov_len = sizeof(data);
4209 msg.msg_control = &control;
4210 msg.msg_controllen = sizeof(control);
4211
4212 res = recvmsg(sock, &msg, MSG_ERRQUEUE);
4213 /* if error or not fitting 802.3 header, return */
4214 if (res < 14)
4215 return;
4216
4217 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
4218 {
4219 if (cmsg->cmsg_level == SOL_SOCKET &&
4220 cmsg->cmsg_type == SCM_WIFI_STATUS) {
4221 int *ack;
4222
4223 found_wifi = 1;
4224 ack = (void *)CMSG_DATA(cmsg);
4225 acked = *ack;
4226 }
4227
4228 if (cmsg->cmsg_level == SOL_PACKET &&
4229 cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
4230 struct sock_extended_err *err =
4231 (struct sock_extended_err *)CMSG_DATA(cmsg);
4232
4233 if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
4234 found_ee = 1;
4235 }
4236 }
4237
4238 if (!found_ee || !found_wifi)
4239 return;
4240
4241 memset(&event, 0, sizeof(event));
4242 event.eapol_tx_status.dst = data;
4243 event.eapol_tx_status.data = data + 14;
4244 event.eapol_tx_status.data_len = res - 14;
4245 event.eapol_tx_status.ack = acked;
4246 wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
4247}
4248
4249
4250static int nl80211_init_bss(struct i802_bss *bss)
4251{
4252 bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
4253 if (!bss->nl_cb)
4254 return -1;
4255
4256 nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
4257 no_seq_check, NULL);
4258 nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
4259 process_bss_event, bss);
4260
4261 return 0;
4262}
4263
4264
4265static void nl80211_destroy_bss(struct i802_bss *bss)
4266{
4267 nl_cb_put(bss->nl_cb);
4268 bss->nl_cb = NULL;
4269}
4270
4271
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004272static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
4273 void *global_priv, int hostapd,
4274 const u8 *set_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004275{
4276 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004277 struct rfkill_config *rcfg;
4278 struct i802_bss *bss;
4279
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004280 if (global_priv == NULL)
4281 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004282 drv = os_zalloc(sizeof(*drv));
4283 if (drv == NULL)
4284 return NULL;
4285 drv->global = global_priv;
4286 drv->ctx = ctx;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004287 drv->hostapd = !!hostapd;
4288 drv->eapol_sock = -1;
4289 drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
4290 drv->if_indices = drv->default_if_indices;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004291
4292 drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
4293 if (!drv->first_bss) {
4294 os_free(drv);
4295 return NULL;
4296 }
4297 bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004298 bss->drv = drv;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004299 bss->ctx = ctx;
4300
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004301 os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
4302 drv->monitor_ifidx = -1;
4303 drv->monitor_sock = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004304 drv->eapol_tx_sock = -1;
4305 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004306
4307 if (wpa_driver_nl80211_init_nl(drv)) {
4308 os_free(drv);
4309 return NULL;
4310 }
4311
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004312 if (nl80211_init_bss(bss))
4313 goto failed;
4314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004315 rcfg = os_zalloc(sizeof(*rcfg));
4316 if (rcfg == NULL)
4317 goto failed;
4318 rcfg->ctx = drv;
4319 os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
4320 rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
4321 rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
4322 drv->rfkill = rfkill_init(rcfg);
4323 if (drv->rfkill == NULL) {
4324 wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
4325 os_free(rcfg);
4326 }
4327
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004328 if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0)
4329 drv->start_iface_up = 1;
4330
4331 if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004332 goto failed;
4333
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004334 drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
4335 if (drv->eapol_tx_sock < 0)
4336 goto failed;
4337
4338 if (drv->data_tx_status) {
4339 int enabled = 1;
4340
4341 if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
4342 &enabled, sizeof(enabled)) < 0) {
4343 wpa_printf(MSG_DEBUG,
4344 "nl80211: wifi status sockopt failed\n");
4345 drv->data_tx_status = 0;
4346 if (!drv->use_monitor)
4347 drv->capa.flags &=
4348 ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
4349 } else {
4350 eloop_register_read_sock(drv->eapol_tx_sock,
4351 wpa_driver_nl80211_handle_eapol_tx_status,
4352 drv, NULL);
4353 }
4354 }
4355
4356 if (drv->global) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004357 dl_list_add(&drv->global->interfaces, &drv->list);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004358 drv->in_interface_list = 1;
4359 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004360
4361 return bss;
4362
4363failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004364 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004365 return NULL;
4366}
4367
4368
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004369/**
4370 * wpa_driver_nl80211_init - Initialize nl80211 driver interface
4371 * @ctx: context to be used when calling wpa_supplicant functions,
4372 * e.g., wpa_supplicant_event()
4373 * @ifname: interface name, e.g., wlan0
4374 * @global_priv: private driver global data from global_init()
4375 * Returns: Pointer to private data, %NULL on failure
4376 */
4377static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
4378 void *global_priv)
4379{
4380 return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL);
4381}
4382
4383
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004384static int nl80211_register_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004385 struct nl_handle *nl_handle,
4386 u16 type, const u8 *match, size_t match_len)
4387{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004388 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004389 struct nl_msg *msg;
4390 int ret = -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004391 char buf[30];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004392
4393 msg = nlmsg_alloc();
4394 if (!msg)
4395 return -1;
4396
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004397 buf[0] = '\0';
4398 wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07004399 wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s",
4400 type, fc2str(type), nl_handle, buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004401
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004402 nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
4403
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004404 if (nl80211_set_iface_id(msg, bss) < 0)
4405 goto nla_put_failure;
4406
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004407 NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
4408 NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);
4409
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004410 ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004411 msg = NULL;
4412 if (ret) {
4413 wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
4414 "failed (type=%u): ret=%d (%s)",
4415 type, ret, strerror(-ret));
4416 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
4417 match, match_len);
4418 goto nla_put_failure;
4419 }
4420 ret = 0;
4421nla_put_failure:
4422 nlmsg_free(msg);
4423 return ret;
4424}
4425
4426
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004427static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
4428{
4429 struct wpa_driver_nl80211_data *drv = bss->drv;
4430
4431 if (bss->nl_mgmt) {
4432 wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting "
4433 "already on! (nl_mgmt=%p)", bss->nl_mgmt);
4434 return -1;
4435 }
4436
4437 bss->nl_mgmt = nl_create_handle(drv->nl_cb, "mgmt");
4438 if (bss->nl_mgmt == NULL)
4439 return -1;
4440
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004441 return 0;
4442}
4443
4444
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004445static void nl80211_mgmt_handle_register_eloop(struct i802_bss *bss)
4446{
4447 nl80211_register_eloop_read(&bss->nl_mgmt,
4448 wpa_driver_nl80211_event_receive,
4449 bss->nl_cb);
4450}
4451
4452
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004453static int nl80211_register_action_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004454 const u8 *match, size_t match_len)
4455{
4456 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004457 return nl80211_register_frame(bss, bss->nl_mgmt,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004458 type, match, match_len);
4459}
4460
4461
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004462static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004463{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004464 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004465 int ret = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004466
4467 if (nl80211_alloc_mgmt_handle(bss))
4468 return -1;
4469 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
4470 "handle %p", bss->nl_mgmt);
4471
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004472 if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
4473 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
4474
4475 /* register for any AUTH message */
4476 nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0);
4477 }
4478
Dmitry Shmidt051af732013-10-22 13:52:46 -07004479#ifdef CONFIG_INTERWORKING
4480 /* QoS Map Configure */
4481 if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004482 ret = -1;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004483#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004484#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004485 /* GAS Initial Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004486 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004487 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004488 /* GAS Initial Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004489 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004490 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004491 /* GAS Comeback Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004492 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004493 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004494 /* GAS Comeback Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004495 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004496 ret = -1;
Dmitry Shmidt18463232014-01-24 12:29:41 -08004497 /* Protected GAS Initial Request */
4498 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0)
4499 ret = -1;
4500 /* Protected GAS Initial Response */
4501 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0)
4502 ret = -1;
4503 /* Protected GAS Comeback Request */
4504 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0)
4505 ret = -1;
4506 /* Protected GAS Comeback Response */
4507 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0)
4508 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004509#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
4510#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004511 /* P2P Public Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004512 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004513 (u8 *) "\x04\x09\x50\x6f\x9a\x09",
4514 6) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004515 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004516 /* P2P Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004517 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004518 (u8 *) "\x7f\x50\x6f\x9a\x09",
4519 5) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004520 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004521#endif /* CONFIG_P2P */
4522#ifdef CONFIG_IEEE80211W
4523 /* SA Query Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004524 if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004525 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004526#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004527#ifdef CONFIG_TDLS
4528 if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
4529 /* TDLS Discovery Response */
4530 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
4531 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004532 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004533 }
4534#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004535
4536 /* FT Action frames */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004537 if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004538 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004539 else
4540 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
4541 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
4542
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004543 /* WNM - BSS Transition Management Request */
4544 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004545 ret = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004546 /* WNM-Sleep Mode Response */
4547 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004548 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004549
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004550#ifdef CONFIG_HS20
4551 /* WNM-Notification */
4552 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0)
4553 return -1;
4554#endif /* CONFIG_HS20 */
4555
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004556 nl80211_mgmt_handle_register_eloop(bss);
4557
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004558 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004559}
4560
4561
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004562static int nl80211_register_spurious_class3(struct i802_bss *bss)
4563{
4564 struct wpa_driver_nl80211_data *drv = bss->drv;
4565 struct nl_msg *msg;
4566 int ret = -1;
4567
4568 msg = nlmsg_alloc();
4569 if (!msg)
4570 return -1;
4571
4572 nl80211_cmd(drv, msg, 0, NL80211_CMD_UNEXPECTED_FRAME);
4573
4574 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
4575
4576 ret = send_and_recv(drv->global, bss->nl_mgmt, msg, NULL, NULL);
4577 msg = NULL;
4578 if (ret) {
4579 wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
4580 "failed: ret=%d (%s)",
4581 ret, strerror(-ret));
4582 goto nla_put_failure;
4583 }
4584 ret = 0;
4585nla_put_failure:
4586 nlmsg_free(msg);
4587 return ret;
4588}
4589
4590
4591static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
4592{
4593 static const int stypes[] = {
4594 WLAN_FC_STYPE_AUTH,
4595 WLAN_FC_STYPE_ASSOC_REQ,
4596 WLAN_FC_STYPE_REASSOC_REQ,
4597 WLAN_FC_STYPE_DISASSOC,
4598 WLAN_FC_STYPE_DEAUTH,
4599 WLAN_FC_STYPE_ACTION,
4600 WLAN_FC_STYPE_PROBE_REQ,
4601/* Beacon doesn't work as mac80211 doesn't currently allow
4602 * it, but it wouldn't really be the right thing anyway as
4603 * it isn't per interface ... maybe just dump the scan
4604 * results periodically for OLBC?
4605 */
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004606 /* WLAN_FC_STYPE_BEACON, */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004607 };
4608 unsigned int i;
4609
4610 if (nl80211_alloc_mgmt_handle(bss))
4611 return -1;
4612 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
4613 "handle %p", bss->nl_mgmt);
4614
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004615 for (i = 0; i < ARRAY_SIZE(stypes); i++) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004616 if (nl80211_register_frame(bss, bss->nl_mgmt,
4617 (WLAN_FC_TYPE_MGMT << 2) |
4618 (stypes[i] << 4),
4619 NULL, 0) < 0) {
4620 goto out_err;
4621 }
4622 }
4623
4624 if (nl80211_register_spurious_class3(bss))
4625 goto out_err;
4626
4627 if (nl80211_get_wiphy_data_ap(bss) == NULL)
4628 goto out_err;
4629
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004630 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004631 return 0;
4632
4633out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004634 nl_destroy_handles(&bss->nl_mgmt);
4635 return -1;
4636}
4637
4638
4639static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)
4640{
4641 if (nl80211_alloc_mgmt_handle(bss))
4642 return -1;
4643 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
4644 "handle %p (device SME)", bss->nl_mgmt);
4645
4646 if (nl80211_register_frame(bss, bss->nl_mgmt,
4647 (WLAN_FC_TYPE_MGMT << 2) |
4648 (WLAN_FC_STYPE_ACTION << 4),
4649 NULL, 0) < 0)
4650 goto out_err;
4651
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004652 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004653 return 0;
4654
4655out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004656 nl_destroy_handles(&bss->nl_mgmt);
4657 return -1;
4658}
4659
4660
4661static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
4662{
4663 if (bss->nl_mgmt == NULL)
4664 return;
4665 wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
4666 "(%s)", bss->nl_mgmt, reason);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004667 nl80211_destroy_eloop_handle(&bss->nl_mgmt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004668
4669 nl80211_put_wiphy_data_ap(bss);
4670}
4671
4672
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004673static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
4674{
4675 wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
4676}
4677
4678
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004679static void nl80211_del_p2pdev(struct i802_bss *bss)
4680{
4681 struct wpa_driver_nl80211_data *drv = bss->drv;
4682 struct nl_msg *msg;
4683 int ret;
4684
4685 msg = nlmsg_alloc();
4686 if (!msg)
4687 return;
4688
4689 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
4690 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
4691
4692 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4693 msg = NULL;
4694
4695 wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
4696 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004697 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004698
4699nla_put_failure:
4700 nlmsg_free(msg);
4701}
4702
4703
4704static int nl80211_set_p2pdev(struct i802_bss *bss, int start)
4705{
4706 struct wpa_driver_nl80211_data *drv = bss->drv;
4707 struct nl_msg *msg;
4708 int ret = -1;
4709
4710 msg = nlmsg_alloc();
4711 if (!msg)
4712 return -1;
4713
4714 if (start)
4715 nl80211_cmd(drv, msg, 0, NL80211_CMD_START_P2P_DEVICE);
4716 else
4717 nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_P2P_DEVICE);
4718
4719 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
4720
4721 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4722 msg = NULL;
4723
4724 wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
4725 start ? "Start" : "Stop",
4726 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004727 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004728
4729nla_put_failure:
4730 nlmsg_free(msg);
4731 return ret;
4732}
4733
4734
4735static int i802_set_iface_flags(struct i802_bss *bss, int up)
4736{
4737 enum nl80211_iftype nlmode;
4738
4739 nlmode = nl80211_get_ifmode(bss);
4740 if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
4741 return linux_set_iface_flags(bss->drv->global->ioctl_sock,
4742 bss->ifname, up);
4743 }
4744
4745 /* P2P Device has start/stop which is equivalent */
4746 return nl80211_set_p2pdev(bss, up);
4747}
4748
4749
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004750static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004751wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
4752 const u8 *set_addr, int first)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004753{
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004754 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004755 int send_rfkill_event = 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004756 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004757
4758 drv->ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004759 bss->ifindex = drv->ifindex;
4760 bss->wdev_id = drv->global->if_add_wdevid;
4761 bss->wdev_id_set = drv->global->if_add_wdevid_set;
4762
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004763 bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;
4764 bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004765 drv->global->if_add_wdevid_set = 0;
4766
Dmitry Shmidt03658832014-08-13 11:03:49 -07004767 if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
4768 bss->static_ap = 1;
4769
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004770 if (wpa_driver_nl80211_capa(drv))
4771 return -1;
4772
4773 wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
4774 bss->ifname, drv->phyname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004775
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004776 if (set_addr &&
4777 (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) ||
4778 linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
4779 set_addr)))
4780 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004781
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004782 if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
4783 drv->start_mode_ap = 1;
4784
Dmitry Shmidt03658832014-08-13 11:03:49 -07004785 if (drv->hostapd || bss->static_ap)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004786 nlmode = NL80211_IFTYPE_AP;
4787 else if (bss->if_dynamic)
4788 nlmode = nl80211_get_ifmode(bss);
4789 else
4790 nlmode = NL80211_IFTYPE_STATION;
4791
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004792 if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004793 wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004794 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004795 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004796
Dmitry Shmidt98660862014-03-11 17:26:21 -07004797 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004798 nl80211_get_macaddr(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004799
Dmitry Shmidt98660862014-03-11 17:26:21 -07004800 if (!rfkill_is_blocked(drv->rfkill)) {
4801 int ret = i802_set_iface_flags(bss, 1);
4802 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004803 wpa_printf(MSG_ERROR, "nl80211: Could not set "
4804 "interface '%s' UP", bss->ifname);
Dmitry Shmidt98660862014-03-11 17:26:21 -07004805 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004806 }
Dmitry Shmidt98660862014-03-11 17:26:21 -07004807 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
4808 return ret;
4809 } else {
4810 wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
4811 "interface '%s' due to rfkill", bss->ifname);
4812 if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
4813 return 0;
4814 drv->if_disabled = 1;
4815 send_rfkill_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004816 }
4817
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004818 if (!drv->hostapd)
4819 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
4820 1, IF_OPER_DORMANT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004821
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004822 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
4823 bss->addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004824 return -1;
4825
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004826 if (send_rfkill_event) {
4827 eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
4828 drv, drv->ctx);
4829 }
4830
4831 return 0;
4832}
4833
4834
4835static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
4836{
4837 struct nl_msg *msg;
4838
4839 msg = nlmsg_alloc();
4840 if (!msg)
4841 return -ENOMEM;
4842
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004843 wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
4844 drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004845 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004846 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4847
4848 return send_and_recv_msgs(drv, msg, NULL, NULL);
4849 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004850 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004851 return -ENOBUFS;
4852}
4853
4854
4855/**
4856 * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004857 * @bss: Pointer to private nl80211 data from wpa_driver_nl80211_init()
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004858 *
4859 * Shut down driver interface and processing of driver events. Free
4860 * private data buffer if one was allocated in wpa_driver_nl80211_init().
4861 */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004862static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004863{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004864 struct wpa_driver_nl80211_data *drv = bss->drv;
4865
Dmitry Shmidt04949592012-07-19 12:16:46 -07004866 bss->in_deinit = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004867 if (drv->data_tx_status)
4868 eloop_unregister_read_sock(drv->eapol_tx_sock);
4869 if (drv->eapol_tx_sock >= 0)
4870 close(drv->eapol_tx_sock);
4871
4872 if (bss->nl_preq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004873 wpa_driver_nl80211_probe_req_report(bss, 0);
4874 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004875 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
4876 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004877 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
4878 "interface %s from bridge %s: %s",
4879 bss->ifname, bss->brname, strerror(errno));
4880 }
4881 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004882 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004883 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
4884 "bridge %s: %s",
4885 bss->brname, strerror(errno));
4886 }
4887
4888 nl80211_remove_monitor_interface(drv);
4889
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004890 if (is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004891 wpa_driver_nl80211_del_beacon(drv);
4892
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004893 if (drv->eapol_sock >= 0) {
4894 eloop_unregister_read_sock(drv->eapol_sock);
4895 close(drv->eapol_sock);
4896 }
4897
4898 if (drv->if_indices != drv->default_if_indices)
4899 os_free(drv->if_indices);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004900
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004901 if (drv->disabled_11b_rates)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004902 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
4903
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004904 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
4905 IF_OPER_UP);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07004906 eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004907 rfkill_deinit(drv->rfkill);
4908
4909 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
4910
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004911 if (!drv->start_iface_up)
4912 (void) i802_set_iface_flags(bss, 0);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004913 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004914 if (!drv->hostapd || !drv->start_mode_ap)
4915 wpa_driver_nl80211_set_mode(bss,
4916 NL80211_IFTYPE_STATION);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004917 nl80211_mgmt_unsubscribe(bss, "deinit");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004918 } else {
4919 nl80211_mgmt_unsubscribe(bss, "deinit");
4920 nl80211_del_p2pdev(bss);
4921 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004922 nl_cb_put(drv->nl_cb);
4923
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004924 nl80211_destroy_bss(drv->first_bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004925
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004926 os_free(drv->filter_ssids);
4927
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004928 os_free(drv->auth_ie);
4929
4930 if (drv->in_interface_list)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004931 dl_list_del(&drv->list);
4932
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004933 os_free(drv->extended_capa);
4934 os_free(drv->extended_capa_mask);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004935 os_free(drv->first_bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004936 os_free(drv);
4937}
4938
4939
4940/**
4941 * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion
4942 * @eloop_ctx: Driver private data
4943 * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init()
4944 *
4945 * This function can be used as registered timeout when starting a scan to
4946 * generate a scan completed event if the driver does not report this.
4947 */
4948static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
4949{
4950 struct wpa_driver_nl80211_data *drv = eloop_ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004951 if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004952 wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004953 drv->ap_scan_as_station);
4954 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004955 }
4956 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
4957 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
4958}
4959
4960
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004961static struct nl_msg *
4962nl80211_scan_common(struct wpa_driver_nl80211_data *drv, u8 cmd,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004963 struct wpa_driver_scan_params *params, u64 *wdev_id)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004964{
4965 struct nl_msg *msg;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004966 size_t i;
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07004967 u32 scan_flags = 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004968
4969 msg = nlmsg_alloc();
4970 if (!msg)
4971 return NULL;
4972
4973 nl80211_cmd(drv, msg, 0, cmd);
4974
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004975 if (!wdev_id)
4976 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4977 else
4978 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, *wdev_id);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004979
4980 if (params->num_ssids) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004981 struct nlattr *ssids;
4982
4983 ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004984 if (ssids == NULL)
4985 goto fail;
4986 for (i = 0; i < params->num_ssids; i++) {
4987 wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
4988 params->ssids[i].ssid,
4989 params->ssids[i].ssid_len);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004990 if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
4991 params->ssids[i].ssid) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004992 goto fail;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004993 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004994 nla_nest_end(msg, ssids);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004995 }
4996
4997 if (params->extra_ies) {
4998 wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
4999 params->extra_ies, params->extra_ies_len);
5000 if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,
5001 params->extra_ies) < 0)
5002 goto fail;
5003 }
5004
5005 if (params->freqs) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005006 struct nlattr *freqs;
5007 freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005008 if (freqs == NULL)
5009 goto fail;
5010 for (i = 0; params->freqs[i]; i++) {
5011 wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
5012 "MHz", params->freqs[i]);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005013 if (nla_put_u32(msg, i + 1, params->freqs[i]) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005014 goto fail;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005015 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005016 nla_nest_end(msg, freqs);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005017 }
5018
5019 os_free(drv->filter_ssids);
5020 drv->filter_ssids = params->filter_ssids;
5021 params->filter_ssids = NULL;
5022 drv->num_filter_ssids = params->num_filter_ssids;
5023
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005024 if (params->only_new_results) {
5025 wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH");
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07005026 scan_flags |= NL80211_SCAN_FLAG_FLUSH;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005027 }
5028
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07005029 if (params->low_priority && drv->have_low_prio_scan) {
5030 wpa_printf(MSG_DEBUG,
5031 "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY");
5032 scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
5033 }
5034
5035 if (scan_flags)
5036 NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags);
5037
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005038 return msg;
5039
5040fail:
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005041nla_put_failure:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005042 nlmsg_free(msg);
5043 return NULL;
5044}
5045
5046
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005047/**
5048 * wpa_driver_nl80211_scan - Request the driver to initiate scan
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005049 * @bss: Pointer to private driver data from wpa_driver_nl80211_init()
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005050 * @params: Scan parameters
5051 * Returns: 0 on success, -1 on failure
5052 */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005053static int wpa_driver_nl80211_scan(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005054 struct wpa_driver_scan_params *params)
5055{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005056 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005057 int ret = -1, timeout;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005058 struct nl_msg *msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005059
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005060 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005061 drv->scan_for_auth = 0;
5062
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005063 msg = nl80211_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params,
5064 bss->wdev_id_set ? &bss->wdev_id : NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005065 if (!msg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005066 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005067
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005068 if (params->p2p_probe) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005069 struct nlattr *rates;
5070
Dmitry Shmidt04949592012-07-19 12:16:46 -07005071 wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
5072
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005073 rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005074 if (rates == NULL)
5075 goto nla_put_failure;
5076
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005077 /*
5078 * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
5079 * by masking out everything else apart from the OFDM rates 6,
5080 * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
5081 * rates are left enabled.
5082 */
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005083 NLA_PUT(msg, NL80211_BAND_2GHZ, 8,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005084 "\x0c\x12\x18\x24\x30\x48\x60\x6c");
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005085 nla_nest_end(msg, rates);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005086
5087 NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
5088 }
5089
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005090 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5091 msg = NULL;
5092 if (ret) {
5093 wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
5094 "(%s)", ret, strerror(-ret));
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005095 if (drv->hostapd && is_ap_interface(drv->nlmode)) {
Dmitry Shmidted003d22014-02-06 10:09:12 -08005096 enum nl80211_iftype old_mode = drv->nlmode;
5097
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005098 /*
5099 * mac80211 does not allow scan requests in AP mode, so
5100 * try to do this in station mode.
5101 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005102 if (wpa_driver_nl80211_set_mode(
5103 bss, NL80211_IFTYPE_STATION))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005104 goto nla_put_failure;
5105
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005106 if (wpa_driver_nl80211_scan(bss, params)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005107 wpa_driver_nl80211_set_mode(bss, drv->nlmode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005108 goto nla_put_failure;
5109 }
5110
5111 /* Restore AP mode when processing scan results */
Dmitry Shmidted003d22014-02-06 10:09:12 -08005112 drv->ap_scan_as_station = old_mode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005113 ret = 0;
5114 } else
5115 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005116 }
5117
Dmitry Shmidt56052862013-10-04 10:23:25 -07005118 drv->scan_state = SCAN_REQUESTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005119 /* Not all drivers generate "scan completed" wireless event, so try to
5120 * read results after a timeout. */
5121 timeout = 10;
5122 if (drv->scan_complete_events) {
5123 /*
5124 * The driver seems to deliver events to notify when scan is
5125 * complete, so use longer timeout to avoid race conditions
5126 * with scanning and following association request.
5127 */
5128 timeout = 30;
5129 }
5130 wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
5131 "seconds", ret, timeout);
5132 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
5133 eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
5134 drv, drv->ctx);
5135
5136nla_put_failure:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005137 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005138 return ret;
5139}
5140
5141
5142/**
5143 * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
5144 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
5145 * @params: Scan parameters
5146 * @interval: Interval between scan cycles in milliseconds
5147 * Returns: 0 on success, -1 on failure or if not supported
5148 */
5149static int wpa_driver_nl80211_sched_scan(void *priv,
5150 struct wpa_driver_scan_params *params,
5151 u32 interval)
5152{
5153 struct i802_bss *bss = priv;
5154 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005155 int ret = -1;
5156 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005157 size_t i;
5158
Dmitry Shmidt700a1372013-03-15 14:14:44 -07005159 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
5160
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005161#ifdef ANDROID
5162 if (!drv->capa.sched_scan_supported)
5163 return android_pno_start(bss, params);
5164#endif /* ANDROID */
5165
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005166 msg = nl80211_scan_common(drv, NL80211_CMD_START_SCHED_SCAN, params,
5167 bss->wdev_id_set ? &bss->wdev_id : NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005168 if (!msg)
5169 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005170
5171 NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);
5172
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005173 if ((drv->num_filter_ssids &&
5174 (int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
5175 params->filter_rssi) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005176 struct nlattr *match_sets;
5177 match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005178 if (match_sets == NULL)
5179 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005180
5181 for (i = 0; i < drv->num_filter_ssids; i++) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005182 struct nlattr *match_set_ssid;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005183 wpa_hexdump_ascii(MSG_MSGDUMP,
5184 "nl80211: Sched scan filter SSID",
5185 drv->filter_ssids[i].ssid,
5186 drv->filter_ssids[i].ssid_len);
5187
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005188 match_set_ssid = nla_nest_start(msg, i + 1);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005189 if (match_set_ssid == NULL)
5190 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005191 NLA_PUT(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005192 drv->filter_ssids[i].ssid_len,
5193 drv->filter_ssids[i].ssid);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005194 if (params->filter_rssi)
5195 NLA_PUT_U32(msg,
5196 NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
5197 params->filter_rssi);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005198
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005199 nla_nest_end(msg, match_set_ssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005200 }
5201
Dmitry Shmidt97672262014-02-03 13:02:54 -08005202 /*
5203 * Due to backward compatibility code, newer kernels treat this
5204 * matchset (with only an RSSI filter) as the default for all
5205 * other matchsets, unless it's the only one, in which case the
5206 * matchset will actually allow all SSIDs above the RSSI.
5207 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005208 if (params->filter_rssi) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005209 struct nlattr *match_set_rssi;
5210 match_set_rssi = nla_nest_start(msg, 0);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005211 if (match_set_rssi == NULL)
5212 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005213 NLA_PUT_U32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005214 params->filter_rssi);
5215 wpa_printf(MSG_MSGDUMP,
5216 "nl80211: Sched scan RSSI filter %d dBm",
5217 params->filter_rssi);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005218 nla_nest_end(msg, match_set_rssi);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005219 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005220
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005221 nla_nest_end(msg, match_sets);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005222 }
5223
5224 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5225
5226 /* TODO: if we get an error here, we should fall back to normal scan */
5227
5228 msg = NULL;
5229 if (ret) {
5230 wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: "
5231 "ret=%d (%s)", ret, strerror(-ret));
5232 goto nla_put_failure;
5233 }
5234
5235 wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) - "
5236 "scan interval %d msec", ret, interval);
5237
5238nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005239 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005240 return ret;
5241}
5242
5243
5244/**
5245 * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan
5246 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
5247 * Returns: 0 on success, -1 on failure or if not supported
5248 */
5249static int wpa_driver_nl80211_stop_sched_scan(void *priv)
5250{
5251 struct i802_bss *bss = priv;
5252 struct wpa_driver_nl80211_data *drv = bss->drv;
5253 int ret = 0;
5254 struct nl_msg *msg;
5255
5256#ifdef ANDROID
5257 if (!drv->capa.sched_scan_supported)
5258 return android_pno_stop(bss);
5259#endif /* ANDROID */
5260
5261 msg = nlmsg_alloc();
5262 if (!msg)
5263 return -1;
5264
5265 nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_SCHED_SCAN);
5266
5267 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5268
5269 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5270 msg = NULL;
5271 if (ret) {
5272 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop failed: "
5273 "ret=%d (%s)", ret, strerror(-ret));
5274 goto nla_put_failure;
5275 }
5276
5277 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop sent (ret=%d)", ret);
5278
5279nla_put_failure:
5280 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005281 return ret;
5282}
5283
5284
5285static const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
5286{
5287 const u8 *end, *pos;
5288
5289 if (ies == NULL)
5290 return NULL;
5291
5292 pos = ies;
5293 end = ies + ies_len;
5294
5295 while (pos + 1 < end) {
5296 if (pos + 2 + pos[1] > end)
5297 break;
5298 if (pos[0] == ie)
5299 return pos;
5300 pos += 2 + pos[1];
5301 }
5302
5303 return NULL;
5304}
5305
5306
5307static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
5308 const u8 *ie, size_t ie_len)
5309{
5310 const u8 *ssid;
5311 size_t i;
5312
5313 if (drv->filter_ssids == NULL)
5314 return 0;
5315
5316 ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID);
5317 if (ssid == NULL)
5318 return 1;
5319
5320 for (i = 0; i < drv->num_filter_ssids; i++) {
5321 if (ssid[1] == drv->filter_ssids[i].ssid_len &&
5322 os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==
5323 0)
5324 return 0;
5325 }
5326
5327 return 1;
5328}
5329
5330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005331static int bss_info_handler(struct nl_msg *msg, void *arg)
5332{
5333 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5334 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5335 struct nlattr *bss[NL80211_BSS_MAX + 1];
5336 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
5337 [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
5338 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
5339 [NL80211_BSS_TSF] = { .type = NLA_U64 },
5340 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
5341 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
5342 [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
5343 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
5344 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
5345 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
5346 [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
5347 [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
5348 };
5349 struct nl80211_bss_info_arg *_arg = arg;
5350 struct wpa_scan_results *res = _arg->res;
5351 struct wpa_scan_res **tmp;
5352 struct wpa_scan_res *r;
5353 const u8 *ie, *beacon_ie;
5354 size_t ie_len, beacon_ie_len;
5355 u8 *pos;
Jouni Malinen87fd2792011-05-16 18:35:42 +03005356 size_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005357
5358 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5359 genlmsg_attrlen(gnlh, 0), NULL);
5360 if (!tb[NL80211_ATTR_BSS])
5361 return NL_SKIP;
5362 if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
5363 bss_policy))
5364 return NL_SKIP;
Jouni Malinen87fd2792011-05-16 18:35:42 +03005365 if (bss[NL80211_BSS_STATUS]) {
5366 enum nl80211_bss_status status;
5367 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
5368 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
5369 bss[NL80211_BSS_FREQUENCY]) {
5370 _arg->assoc_freq =
5371 nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
5372 wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
5373 _arg->assoc_freq);
5374 }
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07005375 if (status == NL80211_BSS_STATUS_IBSS_JOINED &&
5376 bss[NL80211_BSS_FREQUENCY]) {
5377 _arg->ibss_freq =
5378 nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
5379 wpa_printf(MSG_DEBUG, "nl80211: IBSS-joined on %u MHz",
5380 _arg->ibss_freq);
5381 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005382 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
5383 bss[NL80211_BSS_BSSID]) {
5384 os_memcpy(_arg->assoc_bssid,
5385 nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
5386 wpa_printf(MSG_DEBUG, "nl80211: Associated with "
5387 MACSTR, MAC2STR(_arg->assoc_bssid));
5388 }
Jouni Malinen87fd2792011-05-16 18:35:42 +03005389 }
5390 if (!res)
5391 return NL_SKIP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005392 if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
5393 ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
5394 ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
5395 } else {
5396 ie = NULL;
5397 ie_len = 0;
5398 }
5399 if (bss[NL80211_BSS_BEACON_IES]) {
5400 beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);
5401 beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);
5402 } else {
5403 beacon_ie = NULL;
5404 beacon_ie_len = 0;
5405 }
5406
5407 if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie,
5408 ie ? ie_len : beacon_ie_len))
5409 return NL_SKIP;
5410
5411 r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);
5412 if (r == NULL)
5413 return NL_SKIP;
5414 if (bss[NL80211_BSS_BSSID])
5415 os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),
5416 ETH_ALEN);
5417 if (bss[NL80211_BSS_FREQUENCY])
5418 r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
5419 if (bss[NL80211_BSS_BEACON_INTERVAL])
5420 r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);
5421 if (bss[NL80211_BSS_CAPABILITY])
5422 r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
5423 r->flags |= WPA_SCAN_NOISE_INVALID;
5424 if (bss[NL80211_BSS_SIGNAL_MBM]) {
5425 r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
5426 r->level /= 100; /* mBm to dBm */
5427 r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;
5428 } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
5429 r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005430 r->flags |= WPA_SCAN_QUAL_INVALID;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005431 } else
5432 r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;
5433 if (bss[NL80211_BSS_TSF])
5434 r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);
5435 if (bss[NL80211_BSS_SEEN_MS_AGO])
5436 r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
5437 r->ie_len = ie_len;
5438 pos = (u8 *) (r + 1);
5439 if (ie) {
5440 os_memcpy(pos, ie, ie_len);
5441 pos += ie_len;
5442 }
5443 r->beacon_ie_len = beacon_ie_len;
5444 if (beacon_ie)
5445 os_memcpy(pos, beacon_ie, beacon_ie_len);
5446
5447 if (bss[NL80211_BSS_STATUS]) {
5448 enum nl80211_bss_status status;
5449 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
5450 switch (status) {
5451 case NL80211_BSS_STATUS_AUTHENTICATED:
5452 r->flags |= WPA_SCAN_AUTHENTICATED;
5453 break;
5454 case NL80211_BSS_STATUS_ASSOCIATED:
5455 r->flags |= WPA_SCAN_ASSOCIATED;
5456 break;
5457 default:
5458 break;
5459 }
5460 }
5461
Jouni Malinen87fd2792011-05-16 18:35:42 +03005462 /*
5463 * cfg80211 maintains separate BSS table entries for APs if the same
5464 * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does
5465 * not use frequency as a separate key in the BSS table, so filter out
5466 * duplicated entries. Prefer associated BSS entry in such a case in
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005467 * order to get the correct frequency into the BSS table. Similarly,
5468 * prefer newer entries over older.
Jouni Malinen87fd2792011-05-16 18:35:42 +03005469 */
5470 for (i = 0; i < res->num; i++) {
5471 const u8 *s1, *s2;
5472 if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)
5473 continue;
5474
5475 s1 = nl80211_get_ie((u8 *) (res->res[i] + 1),
5476 res->res[i]->ie_len, WLAN_EID_SSID);
5477 s2 = nl80211_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
5478 if (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||
5479 os_memcmp(s1, s2, 2 + s1[1]) != 0)
5480 continue;
5481
5482 /* Same BSSID,SSID was already included in scan results */
5483 wpa_printf(MSG_DEBUG, "nl80211: Remove duplicated scan result "
5484 "for " MACSTR, MAC2STR(r->bssid));
5485
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005486 if (((r->flags & WPA_SCAN_ASSOCIATED) &&
5487 !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) ||
5488 r->age < res->res[i]->age) {
Jouni Malinen87fd2792011-05-16 18:35:42 +03005489 os_free(res->res[i]);
5490 res->res[i] = r;
5491 } else
5492 os_free(r);
5493 return NL_SKIP;
5494 }
5495
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005496 tmp = os_realloc_array(res->res, res->num + 1,
5497 sizeof(struct wpa_scan_res *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005498 if (tmp == NULL) {
5499 os_free(r);
5500 return NL_SKIP;
5501 }
5502 tmp[res->num++] = r;
5503 res->res = tmp;
5504
5505 return NL_SKIP;
5506}
5507
5508
5509static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
5510 const u8 *addr)
5511{
5512 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
5513 wpa_printf(MSG_DEBUG, "nl80211: Clear possible state "
5514 "mismatch (" MACSTR ")", MAC2STR(addr));
5515 wpa_driver_nl80211_mlme(drv, addr,
5516 NL80211_CMD_DEAUTHENTICATE,
5517 WLAN_REASON_PREV_AUTH_NOT_VALID, 1);
5518 }
5519}
5520
5521
5522static void wpa_driver_nl80211_check_bss_status(
5523 struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res)
5524{
5525 size_t i;
5526
5527 for (i = 0; i < res->num; i++) {
5528 struct wpa_scan_res *r = res->res[i];
5529 if (r->flags & WPA_SCAN_AUTHENTICATED) {
5530 wpa_printf(MSG_DEBUG, "nl80211: Scan results "
5531 "indicates BSS status with " MACSTR
5532 " as authenticated",
5533 MAC2STR(r->bssid));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005534 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005535 os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&
5536 os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=
5537 0) {
5538 wpa_printf(MSG_DEBUG, "nl80211: Unknown BSSID"
5539 " in local state (auth=" MACSTR
5540 " assoc=" MACSTR ")",
5541 MAC2STR(drv->auth_bssid),
5542 MAC2STR(drv->bssid));
5543 clear_state_mismatch(drv, r->bssid);
5544 }
5545 }
5546
5547 if (r->flags & WPA_SCAN_ASSOCIATED) {
5548 wpa_printf(MSG_DEBUG, "nl80211: Scan results "
5549 "indicate BSS status with " MACSTR
5550 " as associated",
5551 MAC2STR(r->bssid));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005552 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005553 !drv->associated) {
5554 wpa_printf(MSG_DEBUG, "nl80211: Local state "
5555 "(not associated) does not match "
5556 "with BSS state");
5557 clear_state_mismatch(drv, r->bssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005558 } else if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005559 os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
5560 0) {
5561 wpa_printf(MSG_DEBUG, "nl80211: Local state "
5562 "(associated with " MACSTR ") does "
5563 "not match with BSS state",
5564 MAC2STR(drv->bssid));
5565 clear_state_mismatch(drv, r->bssid);
5566 clear_state_mismatch(drv, drv->bssid);
5567 }
5568 }
5569 }
5570}
5571
5572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005573static struct wpa_scan_results *
5574nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
5575{
5576 struct nl_msg *msg;
5577 struct wpa_scan_results *res;
5578 int ret;
5579 struct nl80211_bss_info_arg arg;
5580
5581 res = os_zalloc(sizeof(*res));
5582 if (res == NULL)
5583 return NULL;
5584 msg = nlmsg_alloc();
5585 if (!msg)
5586 goto nla_put_failure;
5587
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005588 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005589 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005590 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005591
5592 arg.drv = drv;
5593 arg.res = res;
5594 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
5595 msg = NULL;
5596 if (ret == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005597 wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu "
5598 "BSSes)", (unsigned long) res->num);
5599 nl80211_get_noise_for_scan_results(drv, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005600 return res;
5601 }
5602 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
5603 "(%s)", ret, strerror(-ret));
5604nla_put_failure:
5605 nlmsg_free(msg);
5606 wpa_scan_results_free(res);
5607 return NULL;
5608}
5609
5610
5611/**
5612 * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
5613 * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
5614 * Returns: Scan results on success, -1 on failure
5615 */
5616static struct wpa_scan_results *
5617wpa_driver_nl80211_get_scan_results(void *priv)
5618{
5619 struct i802_bss *bss = priv;
5620 struct wpa_driver_nl80211_data *drv = bss->drv;
5621 struct wpa_scan_results *res;
5622
5623 res = nl80211_get_scan_results(drv);
5624 if (res)
5625 wpa_driver_nl80211_check_bss_status(drv, res);
5626 return res;
5627}
5628
5629
5630static void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv)
5631{
5632 struct wpa_scan_results *res;
5633 size_t i;
5634
5635 res = nl80211_get_scan_results(drv);
5636 if (res == NULL) {
5637 wpa_printf(MSG_DEBUG, "nl80211: Failed to get scan results");
5638 return;
5639 }
5640
5641 wpa_printf(MSG_DEBUG, "nl80211: Scan result dump");
5642 for (i = 0; i < res->num; i++) {
5643 struct wpa_scan_res *r = res->res[i];
5644 wpa_printf(MSG_DEBUG, "nl80211: %d/%d " MACSTR "%s%s",
5645 (int) i, (int) res->num, MAC2STR(r->bssid),
5646 r->flags & WPA_SCAN_AUTHENTICATED ? " [auth]" : "",
5647 r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : "");
5648 }
5649
5650 wpa_scan_results_free(res);
5651}
5652
5653
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005654static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len)
5655{
5656 switch (alg) {
5657 case WPA_ALG_WEP:
5658 if (key_len == 5)
5659 return WLAN_CIPHER_SUITE_WEP40;
5660 return WLAN_CIPHER_SUITE_WEP104;
5661 case WPA_ALG_TKIP:
5662 return WLAN_CIPHER_SUITE_TKIP;
5663 case WPA_ALG_CCMP:
5664 return WLAN_CIPHER_SUITE_CCMP;
5665 case WPA_ALG_GCMP:
5666 return WLAN_CIPHER_SUITE_GCMP;
5667 case WPA_ALG_CCMP_256:
5668 return WLAN_CIPHER_SUITE_CCMP_256;
5669 case WPA_ALG_GCMP_256:
5670 return WLAN_CIPHER_SUITE_GCMP_256;
5671 case WPA_ALG_IGTK:
5672 return WLAN_CIPHER_SUITE_AES_CMAC;
5673 case WPA_ALG_BIP_GMAC_128:
5674 return WLAN_CIPHER_SUITE_BIP_GMAC_128;
5675 case WPA_ALG_BIP_GMAC_256:
5676 return WLAN_CIPHER_SUITE_BIP_GMAC_256;
5677 case WPA_ALG_BIP_CMAC_256:
5678 return WLAN_CIPHER_SUITE_BIP_CMAC_256;
5679 case WPA_ALG_SMS4:
5680 return WLAN_CIPHER_SUITE_SMS4;
5681 case WPA_ALG_KRK:
5682 return WLAN_CIPHER_SUITE_KRK;
5683 case WPA_ALG_NONE:
5684 case WPA_ALG_PMK:
5685 wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d",
5686 alg);
5687 return 0;
5688 }
5689
5690 wpa_printf(MSG_ERROR, "nl80211: Unsupported encryption algorithm %d",
5691 alg);
5692 return 0;
5693}
5694
5695
5696static u32 wpa_cipher_to_cipher_suite(unsigned int cipher)
5697{
5698 switch (cipher) {
5699 case WPA_CIPHER_CCMP_256:
5700 return WLAN_CIPHER_SUITE_CCMP_256;
5701 case WPA_CIPHER_GCMP_256:
5702 return WLAN_CIPHER_SUITE_GCMP_256;
5703 case WPA_CIPHER_CCMP:
5704 return WLAN_CIPHER_SUITE_CCMP;
5705 case WPA_CIPHER_GCMP:
5706 return WLAN_CIPHER_SUITE_GCMP;
5707 case WPA_CIPHER_TKIP:
5708 return WLAN_CIPHER_SUITE_TKIP;
5709 case WPA_CIPHER_WEP104:
5710 return WLAN_CIPHER_SUITE_WEP104;
5711 case WPA_CIPHER_WEP40:
5712 return WLAN_CIPHER_SUITE_WEP40;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005713 case WPA_CIPHER_GTK_NOT_USED:
5714 return WLAN_CIPHER_SUITE_NO_GROUP_ADDR;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005715 }
5716
5717 return 0;
5718}
5719
5720
5721static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[],
5722 int max_suites)
5723{
5724 int num_suites = 0;
5725
5726 if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP_256)
5727 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP_256;
5728 if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP_256)
5729 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP_256;
5730 if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP)
5731 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
5732 if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP)
5733 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;
5734 if (num_suites < max_suites && ciphers & WPA_CIPHER_TKIP)
5735 suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
5736 if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP104)
5737 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
5738 if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP40)
5739 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
5740
5741 return num_suites;
5742}
5743
5744
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005745static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005746 enum wpa_alg alg, const u8 *addr,
5747 int key_idx, int set_tx,
5748 const u8 *seq, size_t seq_len,
5749 const u8 *key, size_t key_len)
5750{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005751 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005752 int ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005753 struct nl_msg *msg;
5754 int ret;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005755 int tdls = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005756
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005757 /* Ignore for P2P Device */
5758 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
5759 return 0;
5760
5761 ifindex = if_nametoindex(ifname);
5762 wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005763 "set_tx=%d seq_len=%lu key_len=%lu",
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005764 __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005765 (unsigned long) seq_len, (unsigned long) key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005766#ifdef CONFIG_TDLS
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005767 if (key_idx == -1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005768 key_idx = 0;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005769 tdls = 1;
5770 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005771#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005772
5773 msg = nlmsg_alloc();
5774 if (!msg)
5775 return -ENOMEM;
5776
5777 if (alg == WPA_ALG_NONE) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005778 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005779 } else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005780 nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005781 NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);
Dmitry Shmidt98660862014-03-11 17:26:21 -07005782 wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005783 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5784 wpa_alg_to_cipher_suite(alg, key_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005785 }
5786
Dmitry Shmidt98660862014-03-11 17:26:21 -07005787 if (seq && seq_len) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005788 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq);
Dmitry Shmidt98660862014-03-11 17:26:21 -07005789 wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
5790 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005791
5792 if (addr && !is_broadcast_ether_addr(addr)) {
5793 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
5794 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
5795
5796 if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
5797 wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK");
5798 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE,
5799 NL80211_KEYTYPE_GROUP);
5800 }
5801 } else if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005802 struct nlattr *types;
5803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005804 wpa_printf(MSG_DEBUG, " broadcast key");
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005805
5806 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005807 if (!types)
5808 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005809 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
5810 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005811 }
5812 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
5813 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
5814
5815 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5816 if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
5817 ret = 0;
5818 if (ret)
5819 wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)",
5820 ret, strerror(-ret));
5821
5822 /*
5823 * If we failed or don't need to set the default TX key (below),
5824 * we're done here.
5825 */
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005826 if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005827 return ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005828 if (is_ap_interface(drv->nlmode) && addr &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005829 !is_broadcast_ether_addr(addr))
5830 return ret;
5831
5832 msg = nlmsg_alloc();
5833 if (!msg)
5834 return -ENOMEM;
5835
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005836 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005837 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
5838 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
5839 if (alg == WPA_ALG_IGTK)
5840 NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT);
5841 else
5842 NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
5843 if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005844 struct nlattr *types;
5845
5846 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005847 if (!types)
5848 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005849 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
5850 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005851 } else if (addr) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005852 struct nlattr *types;
5853
5854 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005855 if (!types)
5856 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005857 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST);
5858 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005859 }
5860
5861 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5862 if (ret == -ENOENT)
5863 ret = 0;
5864 if (ret)
5865 wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
5866 "err=%d %s)", ret, strerror(-ret));
5867 return ret;
5868
5869nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005870 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005871 return -ENOBUFS;
5872}
5873
5874
5875static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,
5876 int key_idx, int defkey,
5877 const u8 *seq, size_t seq_len,
5878 const u8 *key, size_t key_len)
5879{
5880 struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);
5881 if (!key_attr)
5882 return -1;
5883
5884 if (defkey && alg == WPA_ALG_IGTK)
5885 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT);
5886 else if (defkey)
5887 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
5888
5889 NLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);
5890
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005891 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5892 wpa_alg_to_cipher_suite(alg, key_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005893
5894 if (seq && seq_len)
5895 NLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);
5896
5897 NLA_PUT(msg, NL80211_KEY_DATA, key_len, key);
5898
5899 nla_nest_end(msg, key_attr);
5900
5901 return 0;
5902 nla_put_failure:
5903 return -1;
5904}
5905
5906
5907static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
5908 struct nl_msg *msg)
5909{
5910 int i, privacy = 0;
5911 struct nlattr *nl_keys, *nl_key;
5912
5913 for (i = 0; i < 4; i++) {
5914 if (!params->wep_key[i])
5915 continue;
5916 privacy = 1;
5917 break;
5918 }
5919 if (params->wps == WPS_MODE_PRIVACY)
5920 privacy = 1;
5921 if (params->pairwise_suite &&
5922 params->pairwise_suite != WPA_CIPHER_NONE)
5923 privacy = 1;
5924
5925 if (!privacy)
5926 return 0;
5927
5928 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
5929
5930 nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
5931 if (!nl_keys)
5932 goto nla_put_failure;
5933
5934 for (i = 0; i < 4; i++) {
5935 if (!params->wep_key[i])
5936 continue;
5937
5938 nl_key = nla_nest_start(msg, i);
5939 if (!nl_key)
5940 goto nla_put_failure;
5941
5942 NLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],
5943 params->wep_key[i]);
5944 if (params->wep_key_len[i] == 5)
5945 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5946 WLAN_CIPHER_SUITE_WEP40);
5947 else
5948 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5949 WLAN_CIPHER_SUITE_WEP104);
5950
5951 NLA_PUT_U8(msg, NL80211_KEY_IDX, i);
5952
5953 if (i == params->wep_tx_keyidx)
5954 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
5955
5956 nla_nest_end(msg, nl_key);
5957 }
5958 nla_nest_end(msg, nl_keys);
5959
5960 return 0;
5961
5962nla_put_failure:
5963 return -ENOBUFS;
5964}
5965
5966
5967static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
5968 const u8 *addr, int cmd, u16 reason_code,
5969 int local_state_change)
5970{
5971 int ret = -1;
5972 struct nl_msg *msg;
5973
5974 msg = nlmsg_alloc();
5975 if (!msg)
5976 return -1;
5977
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005978 nl80211_cmd(drv, msg, 0, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005979
5980 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5981 NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005982 if (addr)
5983 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005984 if (local_state_change)
5985 NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);
5986
5987 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5988 msg = NULL;
5989 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005990 wpa_dbg(drv->ctx, MSG_DEBUG,
5991 "nl80211: MLME command failed: reason=%u ret=%d (%s)",
5992 reason_code, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005993 goto nla_put_failure;
5994 }
5995 ret = 0;
5996
5997nla_put_failure:
5998 nlmsg_free(msg);
5999 return ret;
6000}
6001
6002
6003static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006004 int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006005{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006006 int ret;
6007
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006008 wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006009 nl80211_mark_disconnected(drv);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006010 /* Disconnect command doesn't need BSSID - it uses cached value */
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006011 ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
6012 reason_code, 0);
6013 /*
6014 * For locally generated disconnect, supplicant already generates a
6015 * DEAUTH event, so ignore the event from NL80211.
6016 */
6017 drv->ignore_next_local_disconnect = ret == 0;
6018
6019 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006020}
6021
6022
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006023static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
6024 const u8 *addr, int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006025{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006026 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07006027 int ret;
Dmitry Shmidt413dde72014-04-11 10:23:22 -07006028
6029 if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
6030 nl80211_mark_disconnected(drv);
6031 return nl80211_leave_ibss(drv);
6032 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006033 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006034 return wpa_driver_nl80211_disconnect(drv, reason_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006035 wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
6036 __func__, MAC2STR(addr), reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006037 nl80211_mark_disconnected(drv);
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07006038 ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
6039 reason_code, 0);
6040 /*
6041 * For locally generated deauthenticate, supplicant already generates a
6042 * DEAUTH event, so ignore the event from NL80211.
6043 */
6044 drv->ignore_next_local_deauth = ret == 0;
6045 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006046}
6047
6048
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006049static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
6050 struct wpa_driver_auth_params *params)
6051{
6052 int i;
6053
6054 drv->auth_freq = params->freq;
6055 drv->auth_alg = params->auth_alg;
6056 drv->auth_wep_tx_keyidx = params->wep_tx_keyidx;
6057 drv->auth_local_state_change = params->local_state_change;
6058 drv->auth_p2p = params->p2p;
6059
6060 if (params->bssid)
6061 os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);
6062 else
6063 os_memset(drv->auth_bssid_, 0, ETH_ALEN);
6064
6065 if (params->ssid) {
6066 os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);
6067 drv->auth_ssid_len = params->ssid_len;
6068 } else
6069 drv->auth_ssid_len = 0;
6070
6071
6072 os_free(drv->auth_ie);
6073 drv->auth_ie = NULL;
6074 drv->auth_ie_len = 0;
6075 if (params->ie) {
6076 drv->auth_ie = os_malloc(params->ie_len);
6077 if (drv->auth_ie) {
6078 os_memcpy(drv->auth_ie, params->ie, params->ie_len);
6079 drv->auth_ie_len = params->ie_len;
6080 }
6081 }
6082
6083 for (i = 0; i < 4; i++) {
6084 if (params->wep_key[i] && params->wep_key_len[i] &&
6085 params->wep_key_len[i] <= 16) {
6086 os_memcpy(drv->auth_wep_key[i], params->wep_key[i],
6087 params->wep_key_len[i]);
6088 drv->auth_wep_key_len[i] = params->wep_key_len[i];
6089 } else
6090 drv->auth_wep_key_len[i] = 0;
6091 }
6092}
6093
6094
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006095static int wpa_driver_nl80211_authenticate(
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006096 struct i802_bss *bss, struct wpa_driver_auth_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006097{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006098 struct wpa_driver_nl80211_data *drv = bss->drv;
6099 int ret = -1, i;
6100 struct nl_msg *msg;
6101 enum nl80211_auth_type type;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006102 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006103 int count = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006104 int is_retry;
6105
6106 is_retry = drv->retry_auth;
6107 drv->retry_auth = 0;
Dmitry Shmidt98660862014-03-11 17:26:21 -07006108 drv->ignore_deauth_event = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006109
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006110 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006111 os_memset(drv->auth_bssid, 0, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006112 if (params->bssid)
6113 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
6114 else
6115 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006116 /* FIX: IBSS mode */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006117 nlmode = params->p2p ?
6118 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
6119 if (drv->nlmode != nlmode &&
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006120 wpa_driver_nl80211_set_mode(bss, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006121 return -1;
6122
6123retry:
6124 msg = nlmsg_alloc();
6125 if (!msg)
6126 return -1;
6127
6128 wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
6129 drv->ifindex);
6130
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006131 nl80211_cmd(drv, msg, 0, NL80211_CMD_AUTHENTICATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006132
6133 for (i = 0; i < 4; i++) {
6134 if (!params->wep_key[i])
6135 continue;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006136 wpa_driver_nl80211_set_key(bss->ifname, bss, WPA_ALG_WEP,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006137 NULL, i,
6138 i == params->wep_tx_keyidx, NULL, 0,
6139 params->wep_key[i],
6140 params->wep_key_len[i]);
6141 if (params->wep_tx_keyidx != i)
6142 continue;
6143 if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
6144 params->wep_key[i], params->wep_key_len[i])) {
6145 nlmsg_free(msg);
6146 return -1;
6147 }
6148 }
6149
6150 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6151 if (params->bssid) {
6152 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
6153 MAC2STR(params->bssid));
6154 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
6155 }
6156 if (params->freq) {
6157 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
6158 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
6159 }
6160 if (params->ssid) {
6161 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
6162 params->ssid, params->ssid_len);
6163 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
6164 params->ssid);
6165 }
6166 wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len);
6167 if (params->ie)
6168 NLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006169 if (params->sae_data) {
6170 wpa_hexdump(MSG_DEBUG, " * SAE data", params->sae_data,
6171 params->sae_data_len);
6172 NLA_PUT(msg, NL80211_ATTR_SAE_DATA, params->sae_data_len,
6173 params->sae_data);
6174 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006175 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
6176 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
6177 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
6178 type = NL80211_AUTHTYPE_SHARED_KEY;
6179 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
6180 type = NL80211_AUTHTYPE_NETWORK_EAP;
6181 else if (params->auth_alg & WPA_AUTH_ALG_FT)
6182 type = NL80211_AUTHTYPE_FT;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006183 else if (params->auth_alg & WPA_AUTH_ALG_SAE)
6184 type = NL80211_AUTHTYPE_SAE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006185 else
6186 goto nla_put_failure;
6187 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
6188 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
6189 if (params->local_state_change) {
6190 wpa_printf(MSG_DEBUG, " * Local state change only");
6191 NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);
6192 }
6193
6194 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6195 msg = NULL;
6196 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006197 wpa_dbg(drv->ctx, MSG_DEBUG,
6198 "nl80211: MLME command failed (auth): ret=%d (%s)",
6199 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006200 count++;
6201 if (ret == -EALREADY && count == 1 && params->bssid &&
6202 !params->local_state_change) {
6203 /*
6204 * mac80211 does not currently accept new
6205 * authentication if we are already authenticated. As a
6206 * workaround, force deauthentication and try again.
6207 */
6208 wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
6209 "after forced deauthentication");
Dmitry Shmidt98660862014-03-11 17:26:21 -07006210 drv->ignore_deauth_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006211 wpa_driver_nl80211_deauthenticate(
6212 bss, params->bssid,
6213 WLAN_REASON_PREV_AUTH_NOT_VALID);
6214 nlmsg_free(msg);
6215 goto retry;
6216 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006217
6218 if (ret == -ENOENT && params->freq && !is_retry) {
6219 /*
6220 * cfg80211 has likely expired the BSS entry even
6221 * though it was previously available in our internal
6222 * BSS table. To recover quickly, start a single
6223 * channel scan on the specified channel.
6224 */
6225 struct wpa_driver_scan_params scan;
6226 int freqs[2];
6227
6228 os_memset(&scan, 0, sizeof(scan));
6229 scan.num_ssids = 1;
6230 if (params->ssid) {
6231 scan.ssids[0].ssid = params->ssid;
6232 scan.ssids[0].ssid_len = params->ssid_len;
6233 }
6234 freqs[0] = params->freq;
6235 freqs[1] = 0;
6236 scan.freqs = freqs;
6237 wpa_printf(MSG_DEBUG, "nl80211: Trigger single "
6238 "channel scan to refresh cfg80211 BSS "
6239 "entry");
6240 ret = wpa_driver_nl80211_scan(bss, &scan);
6241 if (ret == 0) {
6242 nl80211_copy_auth_params(drv, params);
6243 drv->scan_for_auth = 1;
6244 }
6245 } else if (is_retry) {
6246 /*
6247 * Need to indicate this with an event since the return
6248 * value from the retry is not delivered to core code.
6249 */
6250 union wpa_event_data event;
6251 wpa_printf(MSG_DEBUG, "nl80211: Authentication retry "
6252 "failed");
6253 os_memset(&event, 0, sizeof(event));
6254 os_memcpy(event.timeout_event.addr, drv->auth_bssid_,
6255 ETH_ALEN);
6256 wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,
6257 &event);
6258 }
6259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006260 goto nla_put_failure;
6261 }
6262 ret = 0;
6263 wpa_printf(MSG_DEBUG, "nl80211: Authentication request send "
6264 "successfully");
6265
6266nla_put_failure:
6267 nlmsg_free(msg);
6268 return ret;
6269}
6270
6271
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006272static int wpa_driver_nl80211_authenticate_retry(
6273 struct wpa_driver_nl80211_data *drv)
6274{
6275 struct wpa_driver_auth_params params;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006276 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006277 int i;
6278
6279 wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
6280
6281 os_memset(&params, 0, sizeof(params));
6282 params.freq = drv->auth_freq;
6283 params.auth_alg = drv->auth_alg;
6284 params.wep_tx_keyidx = drv->auth_wep_tx_keyidx;
6285 params.local_state_change = drv->auth_local_state_change;
6286 params.p2p = drv->auth_p2p;
6287
6288 if (!is_zero_ether_addr(drv->auth_bssid_))
6289 params.bssid = drv->auth_bssid_;
6290
6291 if (drv->auth_ssid_len) {
6292 params.ssid = drv->auth_ssid;
6293 params.ssid_len = drv->auth_ssid_len;
6294 }
6295
6296 params.ie = drv->auth_ie;
6297 params.ie_len = drv->auth_ie_len;
6298
6299 for (i = 0; i < 4; i++) {
6300 if (drv->auth_wep_key_len[i]) {
6301 params.wep_key[i] = drv->auth_wep_key[i];
6302 params.wep_key_len[i] = drv->auth_wep_key_len[i];
6303 }
6304 }
6305
6306 drv->retry_auth = 1;
6307 return wpa_driver_nl80211_authenticate(bss, &params);
6308}
6309
6310
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006311struct phy_info_arg {
6312 u16 *num_modes;
6313 struct hostapd_hw_modes *modes;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006314 int last_mode, last_chan_idx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006315};
6316
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006317static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
6318 struct nlattr *ampdu_factor,
6319 struct nlattr *ampdu_density,
6320 struct nlattr *mcs_set)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006321{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006322 if (capa)
6323 mode->ht_capab = nla_get_u16(capa);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006324
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006325 if (ampdu_factor)
6326 mode->a_mpdu_params |= nla_get_u8(ampdu_factor) & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006327
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006328 if (ampdu_density)
6329 mode->a_mpdu_params |= nla_get_u8(ampdu_density) << 2;
6330
6331 if (mcs_set && nla_len(mcs_set) >= 16) {
6332 u8 *mcs;
6333 mcs = nla_data(mcs_set);
6334 os_memcpy(mode->mcs_set, mcs, 16);
6335 }
6336}
6337
6338
6339static void phy_info_vht_capa(struct hostapd_hw_modes *mode,
6340 struct nlattr *capa,
6341 struct nlattr *mcs_set)
6342{
6343 if (capa)
6344 mode->vht_capab = nla_get_u32(capa);
6345
6346 if (mcs_set && nla_len(mcs_set) >= 8) {
6347 u8 *mcs;
6348 mcs = nla_data(mcs_set);
6349 os_memcpy(mode->vht_mcs_set, mcs, 8);
6350 }
6351}
6352
6353
6354static void phy_info_freq(struct hostapd_hw_modes *mode,
6355 struct hostapd_channel_data *chan,
6356 struct nlattr *tb_freq[])
6357{
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006358 u8 channel;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006359 chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
6360 chan->flag = 0;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006361 chan->dfs_cac_ms = 0;
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006362 if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
6363 chan->chan = channel;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006364
6365 if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
6366 chan->flag |= HOSTAPD_CHAN_DISABLED;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006367 if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR])
6368 chan->flag |= HOSTAPD_CHAN_PASSIVE_SCAN | HOSTAPD_CHAN_NO_IBSS;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006369 if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
6370 chan->flag |= HOSTAPD_CHAN_RADAR;
6371
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006372 if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) {
6373 enum nl80211_dfs_state state =
6374 nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]);
6375
6376 switch (state) {
6377 case NL80211_DFS_USABLE:
6378 chan->flag |= HOSTAPD_CHAN_DFS_USABLE;
6379 break;
6380 case NL80211_DFS_AVAILABLE:
6381 chan->flag |= HOSTAPD_CHAN_DFS_AVAILABLE;
6382 break;
6383 case NL80211_DFS_UNAVAILABLE:
6384 chan->flag |= HOSTAPD_CHAN_DFS_UNAVAILABLE;
6385 break;
6386 }
6387 }
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07006388
6389 if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]) {
6390 chan->dfs_cac_ms = nla_get_u32(
6391 tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]);
6392 }
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006393}
6394
6395
6396static int phy_info_freqs(struct phy_info_arg *phy_info,
6397 struct hostapd_hw_modes *mode, struct nlattr *tb)
6398{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006399 static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
6400 [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
6401 [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006402 [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006403 [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
6404 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006405 [NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006406 };
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006407 int new_channels = 0;
6408 struct hostapd_channel_data *channel;
6409 struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006410 struct nlattr *nl_freq;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006411 int rem_freq, idx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006412
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006413 if (tb == NULL)
6414 return NL_OK;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006415
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006416 nla_for_each_nested(nl_freq, tb, rem_freq) {
6417 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
6418 nla_data(nl_freq), nla_len(nl_freq), freq_policy);
6419 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
6420 continue;
6421 new_channels++;
6422 }
6423
6424 channel = os_realloc_array(mode->channels,
6425 mode->num_channels + new_channels,
6426 sizeof(struct hostapd_channel_data));
6427 if (!channel)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006428 return NL_SKIP;
6429
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006430 mode->channels = channel;
6431 mode->num_channels += new_channels;
6432
6433 idx = phy_info->last_chan_idx;
6434
6435 nla_for_each_nested(nl_freq, tb, rem_freq) {
6436 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
6437 nla_data(nl_freq), nla_len(nl_freq), freq_policy);
6438 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
6439 continue;
6440 phy_info_freq(mode, &mode->channels[idx], tb_freq);
6441 idx++;
6442 }
6443 phy_info->last_chan_idx = idx;
6444
6445 return NL_OK;
6446}
6447
6448
6449static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
6450{
6451 static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {
6452 [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },
6453 [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] =
6454 { .type = NLA_FLAG },
6455 };
6456 struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
6457 struct nlattr *nl_rate;
6458 int rem_rate, idx;
6459
6460 if (tb == NULL)
6461 return NL_OK;
6462
6463 nla_for_each_nested(nl_rate, tb, rem_rate) {
6464 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
6465 nla_data(nl_rate), nla_len(nl_rate),
6466 rate_policy);
6467 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
6468 continue;
6469 mode->num_rates++;
6470 }
6471
6472 mode->rates = os_calloc(mode->num_rates, sizeof(int));
6473 if (!mode->rates)
6474 return NL_SKIP;
6475
6476 idx = 0;
6477
6478 nla_for_each_nested(nl_rate, tb, rem_rate) {
6479 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
6480 nla_data(nl_rate), nla_len(nl_rate),
6481 rate_policy);
6482 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
6483 continue;
6484 mode->rates[idx] = nla_get_u32(
6485 tb_rate[NL80211_BITRATE_ATTR_RATE]);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006486 idx++;
6487 }
6488
6489 return NL_OK;
6490}
6491
6492
6493static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
6494{
6495 struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
6496 struct hostapd_hw_modes *mode;
6497 int ret;
6498
6499 if (phy_info->last_mode != nl_band->nla_type) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006500 mode = os_realloc_array(phy_info->modes,
6501 *phy_info->num_modes + 1,
6502 sizeof(*mode));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006503 if (!mode)
6504 return NL_SKIP;
6505 phy_info->modes = mode;
6506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006507 mode = &phy_info->modes[*(phy_info->num_modes)];
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006508 os_memset(mode, 0, sizeof(*mode));
6509 mode->mode = NUM_HOSTAPD_MODES;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006510 mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN |
6511 HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN;
6512
6513 /*
6514 * Unsupported VHT MCS stream is defined as value 3, so the VHT
6515 * MCS RX/TX map must be initialized with 0xffff to mark all 8
6516 * possible streams as unsupported. This will be overridden if
6517 * driver advertises VHT support.
6518 */
6519 mode->vht_mcs_set[0] = 0xff;
6520 mode->vht_mcs_set[1] = 0xff;
6521 mode->vht_mcs_set[4] = 0xff;
6522 mode->vht_mcs_set[5] = 0xff;
6523
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006524 *(phy_info->num_modes) += 1;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006525 phy_info->last_mode = nl_band->nla_type;
6526 phy_info->last_chan_idx = 0;
6527 } else
6528 mode = &phy_info->modes[*(phy_info->num_modes) - 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006529
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006530 nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
6531 nla_len(nl_band), NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006532
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006533 phy_info_ht_capa(mode, tb_band[NL80211_BAND_ATTR_HT_CAPA],
6534 tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR],
6535 tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY],
6536 tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);
6537 phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
6538 tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
6539 ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]);
6540 if (ret != NL_OK)
6541 return ret;
6542 ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
6543 if (ret != NL_OK)
6544 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006545
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006546 return NL_OK;
6547}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006549
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006550static int phy_info_handler(struct nl_msg *msg, void *arg)
6551{
6552 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
6553 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6554 struct phy_info_arg *phy_info = arg;
6555 struct nlattr *nl_band;
6556 int rem_band;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006557
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006558 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6559 genlmsg_attrlen(gnlh, 0), NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006560
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006561 if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
6562 return NL_SKIP;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006563
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006564 nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band)
6565 {
6566 int res = phy_info_band(phy_info, nl_band);
6567 if (res != NL_OK)
6568 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006569 }
6570
6571 return NL_SKIP;
6572}
6573
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006574
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006575static struct hostapd_hw_modes *
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006576wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
6577 u16 *num_modes)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006578{
6579 u16 m;
6580 struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
6581 int i, mode11g_idx = -1;
6582
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006583 /* heuristic to set up modes */
6584 for (m = 0; m < *num_modes; m++) {
6585 if (!modes[m].num_channels)
6586 continue;
6587 if (modes[m].channels[0].freq < 4000) {
6588 modes[m].mode = HOSTAPD_MODE_IEEE80211B;
6589 for (i = 0; i < modes[m].num_rates; i++) {
6590 if (modes[m].rates[i] > 200) {
6591 modes[m].mode = HOSTAPD_MODE_IEEE80211G;
6592 break;
6593 }
6594 }
6595 } else if (modes[m].channels[0].freq > 50000)
6596 modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
6597 else
6598 modes[m].mode = HOSTAPD_MODE_IEEE80211A;
6599 }
6600
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006601 /* If only 802.11g mode is included, use it to construct matching
6602 * 802.11b mode data. */
6603
6604 for (m = 0; m < *num_modes; m++) {
6605 if (modes[m].mode == HOSTAPD_MODE_IEEE80211B)
6606 return modes; /* 802.11b already included */
6607 if (modes[m].mode == HOSTAPD_MODE_IEEE80211G)
6608 mode11g_idx = m;
6609 }
6610
6611 if (mode11g_idx < 0)
6612 return modes; /* 2.4 GHz band not supported at all */
6613
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006614 nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006615 if (nmodes == NULL)
6616 return modes; /* Could not add 802.11b mode */
6617
6618 mode = &nmodes[*num_modes];
6619 os_memset(mode, 0, sizeof(*mode));
6620 (*num_modes)++;
6621 modes = nmodes;
6622
6623 mode->mode = HOSTAPD_MODE_IEEE80211B;
6624
6625 mode11g = &modes[mode11g_idx];
6626 mode->num_channels = mode11g->num_channels;
6627 mode->channels = os_malloc(mode11g->num_channels *
6628 sizeof(struct hostapd_channel_data));
6629 if (mode->channels == NULL) {
6630 (*num_modes)--;
6631 return modes; /* Could not add 802.11b mode */
6632 }
6633 os_memcpy(mode->channels, mode11g->channels,
6634 mode11g->num_channels * sizeof(struct hostapd_channel_data));
6635
6636 mode->num_rates = 0;
6637 mode->rates = os_malloc(4 * sizeof(int));
6638 if (mode->rates == NULL) {
6639 os_free(mode->channels);
6640 (*num_modes)--;
6641 return modes; /* Could not add 802.11b mode */
6642 }
6643
6644 for (i = 0; i < mode11g->num_rates; i++) {
6645 if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&
6646 mode11g->rates[i] != 55 && mode11g->rates[i] != 110)
6647 continue;
6648 mode->rates[mode->num_rates] = mode11g->rates[i];
6649 mode->num_rates++;
6650 if (mode->num_rates == 4)
6651 break;
6652 }
6653
6654 if (mode->num_rates == 0) {
6655 os_free(mode->channels);
6656 os_free(mode->rates);
6657 (*num_modes)--;
6658 return modes; /* No 802.11b rates */
6659 }
6660
6661 wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g "
6662 "information");
6663
6664 return modes;
6665}
6666
6667
6668static void nl80211_set_ht40_mode(struct hostapd_hw_modes *mode, int start,
6669 int end)
6670{
6671 int c;
6672
6673 for (c = 0; c < mode->num_channels; c++) {
6674 struct hostapd_channel_data *chan = &mode->channels[c];
6675 if (chan->freq - 10 >= start && chan->freq + 10 <= end)
6676 chan->flag |= HOSTAPD_CHAN_HT40;
6677 }
6678}
6679
6680
6681static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,
6682 int end)
6683{
6684 int c;
6685
6686 for (c = 0; c < mode->num_channels; c++) {
6687 struct hostapd_channel_data *chan = &mode->channels[c];
6688 if (!(chan->flag & HOSTAPD_CHAN_HT40))
6689 continue;
6690 if (chan->freq - 30 >= start && chan->freq - 10 <= end)
6691 chan->flag |= HOSTAPD_CHAN_HT40MINUS;
6692 if (chan->freq + 10 >= start && chan->freq + 30 <= end)
6693 chan->flag |= HOSTAPD_CHAN_HT40PLUS;
6694 }
6695}
6696
6697
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006698static void nl80211_reg_rule_max_eirp(u32 start, u32 end, u32 max_eirp,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006699 struct phy_info_arg *results)
6700{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006701 u16 m;
6702
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006703 for (m = 0; m < *results->num_modes; m++) {
6704 int c;
6705 struct hostapd_hw_modes *mode = &results->modes[m];
6706
6707 for (c = 0; c < mode->num_channels; c++) {
6708 struct hostapd_channel_data *chan = &mode->channels[c];
6709 if ((u32) chan->freq - 10 >= start &&
6710 (u32) chan->freq + 10 <= end)
6711 chan->max_tx_power = max_eirp;
6712 }
6713 }
6714}
6715
6716
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006717static void nl80211_reg_rule_ht40(u32 start, u32 end,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006718 struct phy_info_arg *results)
6719{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006720 u16 m;
6721
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006722 for (m = 0; m < *results->num_modes; m++) {
6723 if (!(results->modes[m].ht_capab &
6724 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6725 continue;
6726 nl80211_set_ht40_mode(&results->modes[m], start, end);
6727 }
6728}
6729
6730
6731static void nl80211_reg_rule_sec(struct nlattr *tb[],
6732 struct phy_info_arg *results)
6733{
6734 u32 start, end, max_bw;
6735 u16 m;
6736
6737 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6738 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
6739 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
6740 return;
6741
6742 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6743 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6744 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
6745
6746 if (max_bw < 20)
6747 return;
6748
6749 for (m = 0; m < *results->num_modes; m++) {
6750 if (!(results->modes[m].ht_capab &
6751 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6752 continue;
6753 nl80211_set_ht40_mode_sec(&results->modes[m], start, end);
6754 }
6755}
6756
6757
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006758static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
6759 int end)
6760{
6761 int c;
6762
6763 for (c = 0; c < mode->num_channels; c++) {
6764 struct hostapd_channel_data *chan = &mode->channels[c];
6765 if (chan->freq - 10 >= start && chan->freq + 70 <= end)
6766 chan->flag |= HOSTAPD_CHAN_VHT_10_70;
6767
6768 if (chan->freq - 30 >= start && chan->freq + 50 <= end)
6769 chan->flag |= HOSTAPD_CHAN_VHT_30_50;
6770
6771 if (chan->freq - 50 >= start && chan->freq + 30 <= end)
6772 chan->flag |= HOSTAPD_CHAN_VHT_50_30;
6773
6774 if (chan->freq - 70 >= start && chan->freq + 10 <= end)
6775 chan->flag |= HOSTAPD_CHAN_VHT_70_10;
6776 }
6777}
6778
6779
6780static void nl80211_reg_rule_vht(struct nlattr *tb[],
6781 struct phy_info_arg *results)
6782{
6783 u32 start, end, max_bw;
6784 u16 m;
6785
6786 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6787 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
6788 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
6789 return;
6790
6791 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6792 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6793 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
6794
6795 if (max_bw < 80)
6796 return;
6797
6798 for (m = 0; m < *results->num_modes; m++) {
6799 if (!(results->modes[m].ht_capab &
6800 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6801 continue;
6802 /* TODO: use a real VHT support indication */
6803 if (!results->modes[m].vht_capab)
6804 continue;
6805
6806 nl80211_set_vht_mode(&results->modes[m], start, end);
6807 }
6808}
6809
6810
Dmitry Shmidt97672262014-02-03 13:02:54 -08006811static const char * dfs_domain_name(enum nl80211_dfs_regions region)
6812{
6813 switch (region) {
6814 case NL80211_DFS_UNSET:
6815 return "DFS-UNSET";
6816 case NL80211_DFS_FCC:
6817 return "DFS-FCC";
6818 case NL80211_DFS_ETSI:
6819 return "DFS-ETSI";
6820 case NL80211_DFS_JP:
6821 return "DFS-JP";
6822 default:
6823 return "DFS-invalid";
6824 }
6825}
6826
6827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006828static int nl80211_get_reg(struct nl_msg *msg, void *arg)
6829{
6830 struct phy_info_arg *results = arg;
6831 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
6832 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6833 struct nlattr *nl_rule;
6834 struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
6835 int rem_rule;
6836 static struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
6837 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
6838 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
6839 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
6840 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
6841 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
6842 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
6843 };
6844
6845 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6846 genlmsg_attrlen(gnlh, 0), NULL);
6847 if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
6848 !tb_msg[NL80211_ATTR_REG_RULES]) {
6849 wpa_printf(MSG_DEBUG, "nl80211: No regulatory information "
6850 "available");
6851 return NL_SKIP;
6852 }
6853
Dmitry Shmidt97672262014-02-03 13:02:54 -08006854 if (tb_msg[NL80211_ATTR_DFS_REGION]) {
6855 enum nl80211_dfs_regions dfs_domain;
6856 dfs_domain = nla_get_u8(tb_msg[NL80211_ATTR_DFS_REGION]);
6857 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s (%s)",
6858 (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]),
6859 dfs_domain_name(dfs_domain));
6860 } else {
6861 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s",
6862 (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));
6863 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006864
6865 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6866 {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006867 u32 start, end, max_eirp = 0, max_bw = 0, flags = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006868 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6869 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006870 if (tb_rule[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6871 tb_rule[NL80211_ATTR_FREQ_RANGE_END] == NULL)
6872 continue;
6873 start = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6874 end = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6875 if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
6876 max_eirp = nla_get_u32(tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP]) / 100;
6877 if (tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW])
6878 max_bw = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006879 if (tb_rule[NL80211_ATTR_REG_RULE_FLAGS])
6880 flags = nla_get_u32(tb_rule[NL80211_ATTR_REG_RULE_FLAGS]);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006881
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006882 wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s",
6883 start, end, max_bw, max_eirp,
6884 flags & NL80211_RRF_NO_OFDM ? " (no OFDM)" : "",
6885 flags & NL80211_RRF_NO_CCK ? " (no CCK)" : "",
6886 flags & NL80211_RRF_NO_INDOOR ? " (no indoor)" : "",
6887 flags & NL80211_RRF_NO_OUTDOOR ? " (no outdoor)" :
6888 "",
6889 flags & NL80211_RRF_DFS ? " (DFS)" : "",
6890 flags & NL80211_RRF_PTP_ONLY ? " (PTP only)" : "",
6891 flags & NL80211_RRF_PTMP_ONLY ? " (PTMP only)" : "",
6892 flags & NL80211_RRF_NO_IR ? " (no IR)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006893 if (max_bw >= 40)
6894 nl80211_reg_rule_ht40(start, end, results);
6895 if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
6896 nl80211_reg_rule_max_eirp(start, end, max_eirp,
6897 results);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006898 }
6899
6900 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6901 {
6902 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6903 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
6904 nl80211_reg_rule_sec(tb_rule, results);
6905 }
6906
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006907 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6908 {
6909 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6910 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
6911 nl80211_reg_rule_vht(tb_rule, results);
6912 }
6913
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006914 return NL_SKIP;
6915}
6916
6917
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006918static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv,
6919 struct phy_info_arg *results)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006920{
6921 struct nl_msg *msg;
6922
6923 msg = nlmsg_alloc();
6924 if (!msg)
6925 return -ENOMEM;
6926
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006927 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006928 return send_and_recv_msgs(drv, msg, nl80211_get_reg, results);
6929}
6930
6931
6932static struct hostapd_hw_modes *
6933wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
6934{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006935 u32 feat;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006936 struct i802_bss *bss = priv;
6937 struct wpa_driver_nl80211_data *drv = bss->drv;
6938 struct nl_msg *msg;
6939 struct phy_info_arg result = {
6940 .num_modes = num_modes,
6941 .modes = NULL,
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006942 .last_mode = -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006943 };
6944
6945 *num_modes = 0;
6946 *flags = 0;
6947
6948 msg = nlmsg_alloc();
6949 if (!msg)
6950 return NULL;
6951
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006952 feat = get_nl80211_protocol_features(drv);
6953 if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
6954 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_WIPHY);
6955 else
6956 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006957
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006958 NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006959 if (nl80211_set_iface_id(msg, bss) < 0)
6960 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006961
6962 if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006963 nl80211_set_regulatory_flags(drv, &result);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006964 return wpa_driver_nl80211_postprocess_modes(result.modes,
6965 num_modes);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006966 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006967 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006968 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006969 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006970 return NULL;
6971}
6972
6973
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006974static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv,
6975 const void *data, size_t len,
6976 int encrypt, int noack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006977{
6978 __u8 rtap_hdr[] = {
6979 0x00, 0x00, /* radiotap version */
6980 0x0e, 0x00, /* radiotap length */
6981 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
6982 IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
6983 0x00, /* padding */
6984 0x00, 0x00, /* RX and TX flags to indicate that */
6985 0x00, 0x00, /* this is the injected frame directly */
6986 };
6987 struct iovec iov[2] = {
6988 {
6989 .iov_base = &rtap_hdr,
6990 .iov_len = sizeof(rtap_hdr),
6991 },
6992 {
6993 .iov_base = (void *) data,
6994 .iov_len = len,
6995 }
6996 };
6997 struct msghdr msg = {
6998 .msg_name = NULL,
6999 .msg_namelen = 0,
7000 .msg_iov = iov,
7001 .msg_iovlen = 2,
7002 .msg_control = NULL,
7003 .msg_controllen = 0,
7004 .msg_flags = 0,
7005 };
7006 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007007 u16 txflags = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007008
7009 if (encrypt)
7010 rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
7011
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07007012 if (drv->monitor_sock < 0) {
7013 wpa_printf(MSG_DEBUG, "nl80211: No monitor socket available "
7014 "for %s", __func__);
7015 return -1;
7016 }
7017
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007018 if (noack)
7019 txflags |= IEEE80211_RADIOTAP_F_TX_NOACK;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007020 WPA_PUT_LE16(&rtap_hdr[12], txflags);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007021
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007022 res = sendmsg(drv->monitor_sock, &msg, 0);
7023 if (res < 0) {
7024 wpa_printf(MSG_INFO, "nl80211: sendmsg: %s", strerror(errno));
7025 return -1;
7026 }
7027 return 0;
7028}
7029
7030
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007031static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
7032 const void *data, size_t len,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007033 int encrypt, int noack,
7034 unsigned int freq, int no_cck,
7035 int offchanok, unsigned int wait_time)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007036{
7037 struct wpa_driver_nl80211_data *drv = bss->drv;
7038 u64 cookie;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007039 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007040
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07007041 if (freq == 0 && drv->nlmode == NL80211_IFTYPE_ADHOC) {
7042 freq = nl80211_get_assoc_freq(drv);
7043 wpa_printf(MSG_DEBUG,
7044 "nl80211: send_frame - Use assoc_freq=%u for IBSS",
7045 freq);
7046 }
Dmitry Shmidt56052862013-10-04 10:23:25 -07007047 if (freq == 0) {
7048 wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u",
7049 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007050 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07007051 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007052
Dmitry Shmidt56052862013-10-04 10:23:25 -07007053 if (drv->use_monitor) {
7054 wpa_printf(MSG_DEBUG, "nl80211: send_frame(freq=%u bss->freq=%u) -> send_mntr",
7055 freq, bss->freq);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007056 return wpa_driver_nl80211_send_mntr(drv, data, len,
7057 encrypt, noack);
Dmitry Shmidt56052862013-10-04 10:23:25 -07007058 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007059
Dmitry Shmidt56052862013-10-04 10:23:25 -07007060 wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
Dmitry Shmidt051af732013-10-22 13:52:46 -07007061 res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
7062 &cookie, no_cck, noack, offchanok);
7063 if (res == 0 && !noack) {
7064 const struct ieee80211_mgmt *mgmt;
7065 u16 fc;
7066
7067 mgmt = (const struct ieee80211_mgmt *) data;
7068 fc = le_to_host16(mgmt->frame_control);
7069 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
7070 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
7071 wpa_printf(MSG_MSGDUMP,
7072 "nl80211: Update send_action_cookie from 0x%llx to 0x%llx",
7073 (long long unsigned int)
7074 drv->send_action_cookie,
7075 (long long unsigned int) cookie);
7076 drv->send_action_cookie = cookie;
7077 }
7078 }
7079
7080 return res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007081}
7082
7083
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007084static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
7085 size_t data_len, int noack,
7086 unsigned int freq, int no_cck,
7087 int offchanok,
7088 unsigned int wait_time)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007089{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007090 struct wpa_driver_nl80211_data *drv = bss->drv;
7091 struct ieee80211_mgmt *mgmt;
7092 int encrypt = 1;
7093 u16 fc;
7094
7095 mgmt = (struct ieee80211_mgmt *) data;
7096 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07007097 wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR
7098 " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x (%s) nlmode=%d",
7099 MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time,
7100 fc, fc2str(fc), drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007101
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007102 if ((is_sta_interface(drv->nlmode) ||
7103 drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007104 WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
7105 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
7106 /*
7107 * The use of last_mgmt_freq is a bit of a hack,
7108 * but it works due to the single-threaded nature
7109 * of wpa_supplicant.
7110 */
Dmitry Shmidt56052862013-10-04 10:23:25 -07007111 if (freq == 0) {
7112 wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d",
7113 drv->last_mgmt_freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007114 freq = drv->last_mgmt_freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07007115 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007116 return nl80211_send_frame_cmd(bss, freq, 0,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007117 data, data_len, NULL, 1, noack,
7118 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007119 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007120
7121 if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
Dmitry Shmidt56052862013-10-04 10:23:25 -07007122 if (freq == 0) {
7123 wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d",
7124 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007125 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07007126 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07007127 return nl80211_send_frame_cmd(bss, freq,
7128 (int) freq == bss->freq ? 0 :
7129 wait_time,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007130 data, data_len,
7131 &drv->send_action_cookie,
7132 no_cck, noack, offchanok);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07007133 }
Dmitry Shmidtb638fe72012-03-20 12:51:25 -07007134
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007135 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
7136 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {
7137 /*
7138 * Only one of the authentication frame types is encrypted.
7139 * In order for static WEP encryption to work properly (i.e.,
7140 * to not encrypt the frame), we need to tell mac80211 about
7141 * the frames that must not be encrypted.
7142 */
7143 u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
7144 u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);
7145 if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)
7146 encrypt = 0;
7147 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007148
Dmitry Shmidt56052862013-10-04 10:23:25 -07007149 wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007150 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007151 noack, freq, no_cck, offchanok,
7152 wait_time);
7153}
7154
7155
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007156static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
7157 int slot, int ht_opmode, int ap_isolate,
7158 int *basic_rates)
7159{
7160 struct wpa_driver_nl80211_data *drv = bss->drv;
7161 struct nl_msg *msg;
7162
7163 msg = nlmsg_alloc();
7164 if (!msg)
7165 return -ENOMEM;
7166
7167 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);
7168
7169 if (cts >= 0)
7170 NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);
7171 if (preamble >= 0)
7172 NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);
7173 if (slot >= 0)
7174 NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
7175 if (ht_opmode >= 0)
7176 NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);
7177 if (ap_isolate >= 0)
7178 NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate);
7179
7180 if (basic_rates) {
7181 u8 rates[NL80211_MAX_SUPP_RATES];
7182 u8 rates_len = 0;
7183 int i;
7184
7185 for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0;
7186 i++)
7187 rates[rates_len++] = basic_rates[i] / 5;
7188
7189 NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
7190 }
7191
7192 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
7193
7194 return send_and_recv_msgs(drv, msg, NULL, NULL);
7195 nla_put_failure:
7196 nlmsg_free(msg);
7197 return -ENOBUFS;
7198}
7199
7200
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07007201static int wpa_driver_nl80211_set_acl(void *priv,
7202 struct hostapd_acl_params *params)
7203{
7204 struct i802_bss *bss = priv;
7205 struct wpa_driver_nl80211_data *drv = bss->drv;
7206 struct nl_msg *msg;
7207 struct nlattr *acl;
7208 unsigned int i;
7209 int ret = 0;
7210
7211 if (!(drv->capa.max_acl_mac_addrs))
7212 return -ENOTSUP;
7213
7214 if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
7215 return -ENOTSUP;
7216
7217 msg = nlmsg_alloc();
7218 if (!msg)
7219 return -ENOMEM;
7220
7221 wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
7222 params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
7223
7224 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_MAC_ACL);
7225
7226 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7227
7228 NLA_PUT_U32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
7229 NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
7230 NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED);
7231
7232 acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
7233 if (acl == NULL)
7234 goto nla_put_failure;
7235
7236 for (i = 0; i < params->num_mac_acl; i++)
7237 NLA_PUT(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr);
7238
7239 nla_nest_end(msg, acl);
7240
7241 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7242 msg = NULL;
7243 if (ret) {
7244 wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
7245 ret, strerror(-ret));
7246 }
7247
7248nla_put_failure:
7249 nlmsg_free(msg);
7250
7251 return ret;
7252}
7253
7254
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007255static int wpa_driver_nl80211_set_ap(void *priv,
7256 struct wpa_driver_ap_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007257{
7258 struct i802_bss *bss = priv;
7259 struct wpa_driver_nl80211_data *drv = bss->drv;
7260 struct nl_msg *msg;
7261 u8 cmd = NL80211_CMD_NEW_BEACON;
7262 int ret;
7263 int beacon_set;
7264 int ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007265 int num_suites;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007266 u32 suites[10], suite;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007267 u32 ver;
7268
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07007269 beacon_set = bss->beacon_set;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007270
7271 msg = nlmsg_alloc();
7272 if (!msg)
7273 return -ENOMEM;
7274
7275 wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
7276 beacon_set);
7277 if (beacon_set)
7278 cmd = NL80211_CMD_SET_BEACON;
7279
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007280 nl80211_cmd(drv, msg, 0, cmd);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007281 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
7282 params->head, params->head_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007283 NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007284 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon tail",
7285 params->tail, params->tail_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007286 NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007287 wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007288 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007289 wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007290 NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007291 wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007292 NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007293 wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid",
7294 params->ssid, params->ssid_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007295 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
7296 params->ssid);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007297 if (params->proberesp && params->proberesp_len) {
7298 wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)",
7299 params->proberesp, params->proberesp_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007300 NLA_PUT(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
7301 params->proberesp);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007302 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007303 switch (params->hide_ssid) {
7304 case NO_SSID_HIDING:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007305 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID not in use");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007306 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
7307 NL80211_HIDDEN_SSID_NOT_IN_USE);
7308 break;
7309 case HIDDEN_SSID_ZERO_LEN:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007310 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero len");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007311 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
7312 NL80211_HIDDEN_SSID_ZERO_LEN);
7313 break;
7314 case HIDDEN_SSID_ZERO_CONTENTS:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007315 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero contents");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007316 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
7317 NL80211_HIDDEN_SSID_ZERO_CONTENTS);
7318 break;
7319 }
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007320 wpa_printf(MSG_DEBUG, "nl80211: privacy=%d", params->privacy);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007321 if (params->privacy)
7322 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007323 wpa_printf(MSG_DEBUG, "nl80211: auth_algs=0x%x", params->auth_algs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007324 if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
7325 (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
7326 /* Leave out the attribute */
7327 } else if (params->auth_algs & WPA_AUTH_ALG_SHARED)
7328 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
7329 NL80211_AUTHTYPE_SHARED_KEY);
7330 else
7331 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
7332 NL80211_AUTHTYPE_OPEN_SYSTEM);
7333
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007334 wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007335 ver = 0;
7336 if (params->wpa_version & WPA_PROTO_WPA)
7337 ver |= NL80211_WPA_VERSION_1;
7338 if (params->wpa_version & WPA_PROTO_RSN)
7339 ver |= NL80211_WPA_VERSION_2;
7340 if (ver)
7341 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
7342
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007343 wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x",
7344 params->key_mgmt_suites);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007345 num_suites = 0;
7346 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
7347 suites[num_suites++] = WLAN_AKM_SUITE_8021X;
7348 if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
7349 suites[num_suites++] = WLAN_AKM_SUITE_PSK;
7350 if (num_suites) {
7351 NLA_PUT(msg, NL80211_ATTR_AKM_SUITES,
7352 num_suites * sizeof(u32), suites);
7353 }
7354
7355 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X &&
7356 params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40))
7357 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
7358
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007359 wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
7360 params->pairwise_ciphers);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007361 num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers,
7362 suites, ARRAY_SIZE(suites));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007363 if (num_suites) {
7364 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
7365 num_suites * sizeof(u32), suites);
7366 }
7367
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007368 wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x",
7369 params->group_cipher);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007370 suite = wpa_cipher_to_cipher_suite(params->group_cipher);
7371 if (suite)
7372 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007373
7374 if (params->beacon_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007375 wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
7376 params->beacon_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007377 NLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
7378 wpabuf_head(params->beacon_ies));
7379 }
7380 if (params->proberesp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007381 wpa_hexdump_buf(MSG_DEBUG, "nl80211: proberesp_ies",
7382 params->proberesp_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007383 NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
7384 wpabuf_len(params->proberesp_ies),
7385 wpabuf_head(params->proberesp_ies));
7386 }
7387 if (params->assocresp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007388 wpa_hexdump_buf(MSG_DEBUG, "nl80211: assocresp_ies",
7389 params->assocresp_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007390 NLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,
7391 wpabuf_len(params->assocresp_ies),
7392 wpabuf_head(params->assocresp_ies));
7393 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007394
Dmitry Shmidt04949592012-07-19 12:16:46 -07007395 if (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007396 wpa_printf(MSG_DEBUG, "nl80211: ap_max_inactivity=%d",
7397 params->ap_max_inactivity);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007398 NLA_PUT_U16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT,
7399 params->ap_max_inactivity);
7400 }
7401
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007402 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7403 if (ret) {
7404 wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
7405 ret, strerror(-ret));
7406 } else {
7407 bss->beacon_set = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007408 nl80211_set_bss(bss, params->cts_protect, params->preamble,
7409 params->short_slot_time, params->ht_opmode,
7410 params->isolate, params->basic_rates);
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07007411 if (beacon_set && params->freq &&
7412 params->freq->bandwidth != bss->bandwidth) {
7413 wpa_printf(MSG_DEBUG,
7414 "nl80211: Update BSS %s bandwidth: %d -> %d",
7415 bss->ifname, bss->bandwidth,
7416 params->freq->bandwidth);
7417 ret = nl80211_set_channel(bss, params->freq, 1);
7418 if (ret) {
7419 wpa_printf(MSG_DEBUG,
7420 "nl80211: Frequency set failed: %d (%s)",
7421 ret, strerror(-ret));
7422 } else {
7423 wpa_printf(MSG_DEBUG,
7424 "nl80211: Frequency set succeeded for ht2040 coex");
7425 bss->bandwidth = params->freq->bandwidth;
7426 }
7427 } else if (!beacon_set) {
7428 /*
7429 * cfg80211 updates the driver on frequence change in AP
7430 * mode only at the point when beaconing is started, so
7431 * set the initial value here.
7432 */
7433 bss->bandwidth = params->freq->bandwidth;
7434 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007435 }
7436 return ret;
7437 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007438 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007439 return -ENOBUFS;
7440}
7441
7442
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007443static int nl80211_put_freq_params(struct nl_msg *msg,
7444 struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007445{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007446 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq);
7447 if (freq->vht_enabled) {
7448 switch (freq->bandwidth) {
7449 case 20:
7450 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7451 NL80211_CHAN_WIDTH_20);
7452 break;
7453 case 40:
7454 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7455 NL80211_CHAN_WIDTH_40);
7456 break;
7457 case 80:
7458 if (freq->center_freq2)
7459 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7460 NL80211_CHAN_WIDTH_80P80);
7461 else
7462 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7463 NL80211_CHAN_WIDTH_80);
7464 break;
7465 case 160:
7466 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7467 NL80211_CHAN_WIDTH_160);
7468 break;
7469 default:
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007470 return -EINVAL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007471 }
7472 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1);
7473 if (freq->center_freq2)
7474 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2,
7475 freq->center_freq2);
7476 } else if (freq->ht_enabled) {
7477 switch (freq->sec_channel_offset) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007478 case -1:
7479 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
7480 NL80211_CHAN_HT40MINUS);
7481 break;
7482 case 1:
7483 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
7484 NL80211_CHAN_HT40PLUS);
7485 break;
7486 default:
7487 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
7488 NL80211_CHAN_HT20);
7489 break;
7490 }
7491 }
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007492 return 0;
7493
7494nla_put_failure:
7495 return -ENOBUFS;
7496}
7497
7498
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07007499static int nl80211_set_channel(struct i802_bss *bss,
7500 struct hostapd_freq_params *freq, int set_chan)
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007501{
7502 struct wpa_driver_nl80211_data *drv = bss->drv;
7503 struct nl_msg *msg;
7504 int ret;
7505
7506 wpa_printf(MSG_DEBUG,
7507 "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
7508 freq->freq, freq->ht_enabled, freq->vht_enabled,
7509 freq->bandwidth, freq->center_freq1, freq->center_freq2);
7510 msg = nlmsg_alloc();
7511 if (!msg)
7512 return -1;
7513
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07007514 nl80211_cmd(drv, msg, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
7515 NL80211_CMD_SET_WIPHY);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007516
7517 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7518 if (nl80211_put_freq_params(msg, freq) < 0)
7519 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007520
7521 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007522 msg = NULL;
7523 if (ret == 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007524 bss->freq = freq->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007525 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007526 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007527 wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007528 "%d (%s)", freq->freq, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007529nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007530 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007531 return -1;
7532}
7533
7534
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007535static u32 sta_flags_nl80211(int flags)
7536{
7537 u32 f = 0;
7538
7539 if (flags & WPA_STA_AUTHORIZED)
7540 f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
7541 if (flags & WPA_STA_WMM)
7542 f |= BIT(NL80211_STA_FLAG_WME);
7543 if (flags & WPA_STA_SHORT_PREAMBLE)
7544 f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
7545 if (flags & WPA_STA_MFP)
7546 f |= BIT(NL80211_STA_FLAG_MFP);
7547 if (flags & WPA_STA_TDLS_PEER)
7548 f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
7549
7550 return f;
7551}
7552
7553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007554static int wpa_driver_nl80211_sta_add(void *priv,
7555 struct hostapd_sta_add_params *params)
7556{
7557 struct i802_bss *bss = priv;
7558 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007559 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007560 struct nl80211_sta_flag_update upd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007561 int ret = -ENOBUFS;
7562
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007563 if ((params->flags & WPA_STA_TDLS_PEER) &&
7564 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
7565 return -EOPNOTSUPP;
7566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007567 msg = nlmsg_alloc();
7568 if (!msg)
7569 return -ENOMEM;
7570
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007571 wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR,
7572 params->set ? "Set" : "Add", MAC2STR(params->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007573 nl80211_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION :
7574 NL80211_CMD_NEW_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007575
7576 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
7577 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007578 NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,
7579 params->supp_rates);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007580 wpa_hexdump(MSG_DEBUG, " * supported rates", params->supp_rates,
7581 params->supp_rates_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007582 if (!params->set) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07007583 if (params->aid) {
7584 wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
7585 NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
7586 } else {
7587 /*
7588 * cfg80211 validates that AID is non-zero, so we have
7589 * to make this a non-zero value for the TDLS case where
7590 * a dummy STA entry is used for now.
7591 */
7592 wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)");
7593 NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, 1);
7594 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007595 wpa_printf(MSG_DEBUG, " * listen_interval=%u",
7596 params->listen_interval);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007597 NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
7598 params->listen_interval);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07007599 } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
7600 wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
7601 NLA_PUT_U16(msg, NL80211_ATTR_PEER_AID, params->aid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007602 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007603 if (params->ht_capabilities) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007604 wpa_hexdump(MSG_DEBUG, " * ht_capabilities",
7605 (u8 *) params->ht_capabilities,
7606 sizeof(*params->ht_capabilities));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007607 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,
7608 sizeof(*params->ht_capabilities),
7609 params->ht_capabilities);
7610 }
7611
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007612 if (params->vht_capabilities) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007613 wpa_hexdump(MSG_DEBUG, " * vht_capabilities",
7614 (u8 *) params->vht_capabilities,
7615 sizeof(*params->vht_capabilities));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007616 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY,
7617 sizeof(*params->vht_capabilities),
7618 params->vht_capabilities);
7619 }
7620
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007621 if (params->vht_opmode_enabled) {
7622 wpa_printf(MSG_DEBUG, " * opmode=%u", params->vht_opmode);
7623 NLA_PUT_U8(msg, NL80211_ATTR_OPMODE_NOTIF,
7624 params->vht_opmode);
7625 }
7626
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007627 wpa_printf(MSG_DEBUG, " * capability=0x%x", params->capability);
7628 NLA_PUT_U16(msg, NL80211_ATTR_STA_CAPABILITY, params->capability);
7629
7630 if (params->ext_capab) {
7631 wpa_hexdump(MSG_DEBUG, " * ext_capab",
7632 params->ext_capab, params->ext_capab_len);
7633 NLA_PUT(msg, NL80211_ATTR_STA_EXT_CAPABILITY,
7634 params->ext_capab_len, params->ext_capab);
7635 }
7636
Dmitry Shmidt344abd32014-01-14 13:17:00 -08007637 if (params->supp_channels) {
7638 wpa_hexdump(MSG_DEBUG, " * supported channels",
7639 params->supp_channels, params->supp_channels_len);
7640 NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_CHANNELS,
7641 params->supp_channels_len, params->supp_channels);
7642 }
7643
7644 if (params->supp_oper_classes) {
7645 wpa_hexdump(MSG_DEBUG, " * supported operating classes",
7646 params->supp_oper_classes,
7647 params->supp_oper_classes_len);
7648 NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
7649 params->supp_oper_classes_len,
7650 params->supp_oper_classes);
7651 }
7652
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007653 os_memset(&upd, 0, sizeof(upd));
7654 upd.mask = sta_flags_nl80211(params->flags);
7655 upd.set = upd.mask;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007656 wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x",
7657 upd.set, upd.mask);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007658 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
7659
7660 if (params->flags & WPA_STA_WMM) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007661 struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME);
7662
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007663 if (!wme)
7664 goto nla_put_failure;
7665
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007666 wpa_printf(MSG_DEBUG, " * qosinfo=0x%x", params->qosinfo);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007667 NLA_PUT_U8(msg, NL80211_STA_WME_UAPSD_QUEUES,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007668 params->qosinfo & WMM_QOSINFO_STA_AC_MASK);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007669 NLA_PUT_U8(msg, NL80211_STA_WME_MAX_SP,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007670 (params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007671 WMM_QOSINFO_STA_SP_MASK);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007672 nla_nest_end(msg, wme);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007673 }
7674
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007675 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007676 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007677 if (ret)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007678 wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
7679 "result: %d (%s)", params->set ? "SET" : "NEW", ret,
7680 strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007681 if (ret == -EEXIST)
7682 ret = 0;
7683 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007684 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007685 return ret;
7686}
7687
7688
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007689static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007690{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007691 struct wpa_driver_nl80211_data *drv = bss->drv;
7692 struct nl_msg *msg;
7693 int ret;
7694
7695 msg = nlmsg_alloc();
7696 if (!msg)
7697 return -ENOMEM;
7698
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007699 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007700
7701 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
7702 if_nametoindex(bss->ifname));
7703 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
7704
7705 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007706 wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
7707 " --> %d (%s)",
7708 bss->ifname, MAC2STR(addr), ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007709 if (ret == -ENOENT)
7710 return 0;
7711 return ret;
7712 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007713 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007714 return -ENOBUFS;
7715}
7716
7717
7718static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
7719 int ifidx)
7720{
7721 struct nl_msg *msg;
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07007722 struct wpa_driver_nl80211_data *drv2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007723
7724 wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx);
7725
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007726 /* stop listening for EAPOL on this interface */
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07007727 dl_list_for_each(drv2, &drv->global->interfaces,
7728 struct wpa_driver_nl80211_data, list)
7729 del_ifidx(drv2, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007730
7731 msg = nlmsg_alloc();
7732 if (!msg)
7733 goto nla_put_failure;
7734
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007735 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007736 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
7737
7738 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
7739 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007740 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007741 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007742 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007743 wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
7744}
7745
7746
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007747static const char * nl80211_iftype_str(enum nl80211_iftype mode)
7748{
7749 switch (mode) {
7750 case NL80211_IFTYPE_ADHOC:
7751 return "ADHOC";
7752 case NL80211_IFTYPE_STATION:
7753 return "STATION";
7754 case NL80211_IFTYPE_AP:
7755 return "AP";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07007756 case NL80211_IFTYPE_AP_VLAN:
7757 return "AP_VLAN";
7758 case NL80211_IFTYPE_WDS:
7759 return "WDS";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007760 case NL80211_IFTYPE_MONITOR:
7761 return "MONITOR";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07007762 case NL80211_IFTYPE_MESH_POINT:
7763 return "MESH_POINT";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007764 case NL80211_IFTYPE_P2P_CLIENT:
7765 return "P2P_CLIENT";
7766 case NL80211_IFTYPE_P2P_GO:
7767 return "P2P_GO";
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007768 case NL80211_IFTYPE_P2P_DEVICE:
7769 return "P2P_DEVICE";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007770 default:
7771 return "unknown";
7772 }
7773}
7774
7775
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007776static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
7777 const char *ifname,
7778 enum nl80211_iftype iftype,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007779 const u8 *addr, int wds,
7780 int (*handler)(struct nl_msg *, void *),
7781 void *arg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007782{
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007783 struct nl_msg *msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007784 int ifidx;
7785 int ret = -ENOBUFS;
7786
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007787 wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)",
7788 iftype, nl80211_iftype_str(iftype));
7789
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007790 msg = nlmsg_alloc();
7791 if (!msg)
7792 return -1;
7793
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007794 nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007795 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007796 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007797 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);
7798 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
7799
7800 if (iftype == NL80211_IFTYPE_MONITOR) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007801 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007802
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007803 flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007804 if (!flags)
7805 goto nla_put_failure;
7806
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007807 NLA_PUT_FLAG(msg, NL80211_MNTR_FLAG_COOK_FRAMES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007808
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007809 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007810 } else if (wds) {
7811 NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
7812 }
7813
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07007814 /*
7815 * Tell cfg80211 that the interface belongs to the socket that created
7816 * it, and the interface should be deleted when the socket is closed.
7817 */
7818 NLA_PUT_FLAG(msg, NL80211_ATTR_IFACE_SOCKET_OWNER);
7819
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007820 ret = send_and_recv_msgs(drv, msg, handler, arg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007821 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007822 if (ret) {
7823 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007824 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007825 wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)",
7826 ifname, ret, strerror(-ret));
7827 return ret;
7828 }
7829
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007830 if (iftype == NL80211_IFTYPE_P2P_DEVICE)
7831 return 0;
7832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007833 ifidx = if_nametoindex(ifname);
7834 wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d",
7835 ifname, ifidx);
7836
7837 if (ifidx <= 0)
7838 return -1;
7839
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07007840 /*
7841 * Some virtual interfaces need to process EAPOL packets and events on
7842 * the parent interface. This is used mainly with hostapd.
7843 */
7844 if (drv->hostapd ||
7845 iftype == NL80211_IFTYPE_AP_VLAN ||
7846 iftype == NL80211_IFTYPE_WDS ||
7847 iftype == NL80211_IFTYPE_MONITOR) {
7848 /* start listening for EAPOL on this interface */
7849 add_ifidx(drv, ifidx);
7850 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007851
7852 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007853 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007854 nl80211_remove_iface(drv, ifidx);
7855 return -1;
7856 }
7857
7858 return ifidx;
7859}
7860
7861
7862static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
7863 const char *ifname, enum nl80211_iftype iftype,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007864 const u8 *addr, int wds,
7865 int (*handler)(struct nl_msg *, void *),
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007866 void *arg, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007867{
7868 int ret;
7869
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007870 ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler,
7871 arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007872
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007873 /* if error occurred and interface exists already */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007874 if (ret == -ENFILE && if_nametoindex(ifname)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007875 if (use_existing) {
7876 wpa_printf(MSG_DEBUG, "nl80211: Continue using existing interface %s",
7877 ifname);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07007878 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
7879 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
7880 addr) < 0 &&
7881 (linux_set_iface_flags(drv->global->ioctl_sock,
7882 ifname, 0) < 0 ||
7883 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
7884 addr) < 0 ||
7885 linux_set_iface_flags(drv->global->ioctl_sock,
7886 ifname, 1) < 0))
7887 return -1;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007888 return -ENFILE;
7889 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007890 wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname);
7891
7892 /* Try to remove the interface that was already there. */
7893 nl80211_remove_iface(drv, if_nametoindex(ifname));
7894
7895 /* Try to create the interface again */
7896 ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007897 wds, handler, arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007898 }
7899
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007900 if (ret >= 0 && is_p2p_net_interface(iftype))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007901 nl80211_disable_11b_rates(drv, ret, 1);
7902
7903 return ret;
7904}
7905
7906
7907static void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)
7908{
7909 struct ieee80211_hdr *hdr;
7910 u16 fc;
7911 union wpa_event_data event;
7912
7913 hdr = (struct ieee80211_hdr *) buf;
7914 fc = le_to_host16(hdr->frame_control);
7915
7916 os_memset(&event, 0, sizeof(event));
7917 event.tx_status.type = WLAN_FC_GET_TYPE(fc);
7918 event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
7919 event.tx_status.dst = hdr->addr1;
7920 event.tx_status.data = buf;
7921 event.tx_status.data_len = len;
7922 event.tx_status.ack = ok;
7923 wpa_supplicant_event(ctx, EVENT_TX_STATUS, &event);
7924}
7925
7926
7927static void from_unknown_sta(struct wpa_driver_nl80211_data *drv,
7928 u8 *buf, size_t len)
7929{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007930 struct ieee80211_hdr *hdr = (void *)buf;
7931 u16 fc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007932 union wpa_event_data event;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007933
7934 if (len < sizeof(*hdr))
7935 return;
7936
7937 fc = le_to_host16(hdr->frame_control);
7938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007939 os_memset(&event, 0, sizeof(event));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007940 event.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);
7941 event.rx_from_unknown.addr = hdr->addr2;
7942 event.rx_from_unknown.wds = (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) ==
7943 (WLAN_FC_FROMDS | WLAN_FC_TODS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007944 wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
7945}
7946
7947
7948static void handle_frame(struct wpa_driver_nl80211_data *drv,
7949 u8 *buf, size_t len, int datarate, int ssi_signal)
7950{
7951 struct ieee80211_hdr *hdr;
7952 u16 fc;
7953 union wpa_event_data event;
7954
7955 hdr = (struct ieee80211_hdr *) buf;
7956 fc = le_to_host16(hdr->frame_control);
7957
7958 switch (WLAN_FC_GET_TYPE(fc)) {
7959 case WLAN_FC_TYPE_MGMT:
7960 os_memset(&event, 0, sizeof(event));
7961 event.rx_mgmt.frame = buf;
7962 event.rx_mgmt.frame_len = len;
7963 event.rx_mgmt.datarate = datarate;
7964 event.rx_mgmt.ssi_signal = ssi_signal;
7965 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
7966 break;
7967 case WLAN_FC_TYPE_CTRL:
7968 /* can only get here with PS-Poll frames */
7969 wpa_printf(MSG_DEBUG, "CTRL");
7970 from_unknown_sta(drv, buf, len);
7971 break;
7972 case WLAN_FC_TYPE_DATA:
7973 from_unknown_sta(drv, buf, len);
7974 break;
7975 }
7976}
7977
7978
7979static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
7980{
7981 struct wpa_driver_nl80211_data *drv = eloop_ctx;
7982 int len;
7983 unsigned char buf[3000];
7984 struct ieee80211_radiotap_iterator iter;
7985 int ret;
7986 int datarate = 0, ssi_signal = 0;
7987 int injected = 0, failed = 0, rxflags = 0;
7988
7989 len = recv(sock, buf, sizeof(buf), 0);
7990 if (len < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007991 wpa_printf(MSG_ERROR, "nl80211: Monitor socket recv failed: %s",
7992 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007993 return;
7994 }
7995
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07007996 if (ieee80211_radiotap_iterator_init(&iter, (void *) buf, len, NULL)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007997 wpa_printf(MSG_INFO, "nl80211: received invalid radiotap frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007998 return;
7999 }
8000
8001 while (1) {
8002 ret = ieee80211_radiotap_iterator_next(&iter);
8003 if (ret == -ENOENT)
8004 break;
8005 if (ret) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008006 wpa_printf(MSG_INFO, "nl80211: received invalid radiotap frame (%d)",
8007 ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008008 return;
8009 }
8010 switch (iter.this_arg_index) {
8011 case IEEE80211_RADIOTAP_FLAGS:
8012 if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
8013 len -= 4;
8014 break;
8015 case IEEE80211_RADIOTAP_RX_FLAGS:
8016 rxflags = 1;
8017 break;
8018 case IEEE80211_RADIOTAP_TX_FLAGS:
8019 injected = 1;
8020 failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
8021 IEEE80211_RADIOTAP_F_TX_FAIL;
8022 break;
8023 case IEEE80211_RADIOTAP_DATA_RETRIES:
8024 break;
8025 case IEEE80211_RADIOTAP_CHANNEL:
8026 /* TODO: convert from freq/flags to channel number */
8027 break;
8028 case IEEE80211_RADIOTAP_RATE:
8029 datarate = *iter.this_arg * 5;
8030 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008031 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
8032 ssi_signal = (s8) *iter.this_arg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008033 break;
8034 }
8035 }
8036
8037 if (rxflags && injected)
8038 return;
8039
8040 if (!injected)
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07008041 handle_frame(drv, buf + iter._max_length,
8042 len - iter._max_length, datarate, ssi_signal);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008043 else
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -07008044 handle_tx_callback(drv->ctx, buf + iter._max_length,
8045 len - iter._max_length, !failed);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008046}
8047
8048
8049/*
8050 * we post-process the filter code later and rewrite
8051 * this to the offset to the last instruction
8052 */
8053#define PASS 0xFF
8054#define FAIL 0xFE
8055
8056static struct sock_filter msock_filter_insns[] = {
8057 /*
8058 * do a little-endian load of the radiotap length field
8059 */
8060 /* load lower byte into A */
8061 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 2),
8062 /* put it into X (== index register) */
8063 BPF_STMT(BPF_MISC| BPF_TAX, 0),
8064 /* load upper byte into A */
8065 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 3),
8066 /* left-shift it by 8 */
8067 BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8),
8068 /* or with X */
8069 BPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0),
8070 /* put result into X */
8071 BPF_STMT(BPF_MISC| BPF_TAX, 0),
8072
8073 /*
8074 * Allow management frames through, this also gives us those
8075 * management frames that we sent ourselves with status
8076 */
8077 /* load the lower byte of the IEEE 802.11 frame control field */
8078 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
8079 /* mask off frame type and version */
8080 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF),
8081 /* accept frame if it's both 0, fall through otherwise */
8082 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0),
8083
8084 /*
8085 * TODO: add a bit to radiotap RX flags that indicates
8086 * that the sending station is not associated, then
8087 * add a filter here that filters on our DA and that flag
8088 * to allow us to deauth frames to that bad station.
8089 *
8090 * For now allow all To DS data frames through.
8091 */
8092 /* load the IEEE 802.11 frame control field */
8093 BPF_STMT(BPF_LD | BPF_H | BPF_IND, 0),
8094 /* mask off frame type, version and DS status */
8095 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03),
8096 /* accept frame if version 0, type 2 and To DS, fall through otherwise
8097 */
8098 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0),
8099
8100#if 0
8101 /*
8102 * drop non-data frames
8103 */
8104 /* load the lower byte of the frame control field */
8105 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
8106 /* mask off QoS bit */
8107 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c),
8108 /* drop non-data frames */
8109 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL),
8110#endif
8111 /* load the upper byte of the frame control field */
8112 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1),
8113 /* mask off toDS/fromDS */
8114 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03),
8115 /* accept WDS frames */
8116 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0),
8117
8118 /*
8119 * add header length to index
8120 */
8121 /* load the lower byte of the frame control field */
8122 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
8123 /* mask off QoS bit */
8124 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x80),
8125 /* right shift it by 6 to give 0 or 2 */
8126 BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 6),
8127 /* add data frame header length */
8128 BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 24),
8129 /* add index, was start of 802.11 header */
8130 BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0),
8131 /* move to index, now start of LL header */
8132 BPF_STMT(BPF_MISC | BPF_TAX, 0),
8133
8134 /*
8135 * Accept empty data frames, we use those for
8136 * polling activity.
8137 */
8138 BPF_STMT(BPF_LD | BPF_W | BPF_LEN, 0),
8139 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0),
8140
8141 /*
8142 * Accept EAPOL frames
8143 */
8144 BPF_STMT(BPF_LD | BPF_W | BPF_IND, 0),
8145 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL),
8146 BPF_STMT(BPF_LD | BPF_W | BPF_IND, 4),
8147 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL),
8148
8149 /* keep these last two statements or change the code below */
8150 /* return 0 == "DROP" */
8151 BPF_STMT(BPF_RET | BPF_K, 0),
8152 /* return ~0 == "keep all" */
8153 BPF_STMT(BPF_RET | BPF_K, ~0),
8154};
8155
8156static struct sock_fprog msock_filter = {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008157 .len = ARRAY_SIZE(msock_filter_insns),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008158 .filter = msock_filter_insns,
8159};
8160
8161
8162static int add_monitor_filter(int s)
8163{
8164 int idx;
8165
8166 /* rewrite all PASS/FAIL jump offsets */
8167 for (idx = 0; idx < msock_filter.len; idx++) {
8168 struct sock_filter *insn = &msock_filter_insns[idx];
8169
8170 if (BPF_CLASS(insn->code) == BPF_JMP) {
8171 if (insn->code == (BPF_JMP|BPF_JA)) {
8172 if (insn->k == PASS)
8173 insn->k = msock_filter.len - idx - 2;
8174 else if (insn->k == FAIL)
8175 insn->k = msock_filter.len - idx - 3;
8176 }
8177
8178 if (insn->jt == PASS)
8179 insn->jt = msock_filter.len - idx - 2;
8180 else if (insn->jt == FAIL)
8181 insn->jt = msock_filter.len - idx - 3;
8182
8183 if (insn->jf == PASS)
8184 insn->jf = msock_filter.len - idx - 2;
8185 else if (insn->jf == FAIL)
8186 insn->jf = msock_filter.len - idx - 3;
8187 }
8188 }
8189
8190 if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER,
8191 &msock_filter, sizeof(msock_filter))) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008192 wpa_printf(MSG_ERROR, "nl80211: setsockopt(SO_ATTACH_FILTER) failed: %s",
8193 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008194 return -1;
8195 }
8196
8197 return 0;
8198}
8199
8200
8201static void nl80211_remove_monitor_interface(
8202 struct wpa_driver_nl80211_data *drv)
8203{
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008204 if (drv->monitor_refcount > 0)
8205 drv->monitor_refcount--;
8206 wpa_printf(MSG_DEBUG, "nl80211: Remove monitor interface: refcount=%d",
8207 drv->monitor_refcount);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008208 if (drv->monitor_refcount > 0)
8209 return;
8210
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008211 if (drv->monitor_ifidx >= 0) {
8212 nl80211_remove_iface(drv, drv->monitor_ifidx);
8213 drv->monitor_ifidx = -1;
8214 }
8215 if (drv->monitor_sock >= 0) {
8216 eloop_unregister_read_sock(drv->monitor_sock);
8217 close(drv->monitor_sock);
8218 drv->monitor_sock = -1;
8219 }
8220}
8221
8222
8223static int
8224nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
8225{
8226 char buf[IFNAMSIZ];
8227 struct sockaddr_ll ll;
8228 int optval;
8229 socklen_t optlen;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008230
8231 if (drv->monitor_ifidx >= 0) {
8232 drv->monitor_refcount++;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008233 wpa_printf(MSG_DEBUG, "nl80211: Re-use existing monitor interface: refcount=%d",
8234 drv->monitor_refcount);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008235 return 0;
8236 }
8237
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008238 if (os_strncmp(drv->first_bss->ifname, "p2p-", 4) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008239 /*
8240 * P2P interface name is of the format p2p-%s-%d. For monitor
8241 * interface name corresponding to P2P GO, replace "p2p-" with
8242 * "mon-" to retain the same interface name length and to
8243 * indicate that it is a monitor interface.
8244 */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008245 snprintf(buf, IFNAMSIZ, "mon-%s", drv->first_bss->ifname + 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008246 } else {
8247 /* Non-P2P interface with AP functionality. */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008248 snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008249 }
8250
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008251 buf[IFNAMSIZ - 1] = '\0';
8252
8253 drv->monitor_ifidx =
8254 nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008255 0, NULL, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008256
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07008257 if (drv->monitor_ifidx == -EOPNOTSUPP) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008258 /*
8259 * This is backward compatibility for a few versions of
8260 * the kernel only that didn't advertise the right
8261 * attributes for the only driver that then supported
8262 * AP mode w/o monitor -- ath6kl.
8263 */
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07008264 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support "
8265 "monitor interface type - try to run without it");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008266 drv->device_ap_sme = 1;
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07008267 }
8268
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008269 if (drv->monitor_ifidx < 0)
8270 return -1;
8271
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008272 if (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008273 goto error;
8274
8275 memset(&ll, 0, sizeof(ll));
8276 ll.sll_family = AF_PACKET;
8277 ll.sll_ifindex = drv->monitor_ifidx;
8278 drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
8279 if (drv->monitor_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008280 wpa_printf(MSG_ERROR, "nl80211: socket[PF_PACKET,SOCK_RAW] failed: %s",
8281 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008282 goto error;
8283 }
8284
8285 if (add_monitor_filter(drv->monitor_sock)) {
8286 wpa_printf(MSG_INFO, "Failed to set socket filter for monitor "
8287 "interface; do filtering in user space");
8288 /* This works, but will cost in performance. */
8289 }
8290
8291 if (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008292 wpa_printf(MSG_ERROR, "nl80211: monitor socket bind failed: %s",
8293 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008294 goto error;
8295 }
8296
8297 optlen = sizeof(optval);
8298 optval = 20;
8299 if (setsockopt
8300 (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008301 wpa_printf(MSG_ERROR, "nl80211: Failed to set socket priority: %s",
8302 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008303 goto error;
8304 }
8305
8306 if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,
8307 drv, NULL)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008308 wpa_printf(MSG_INFO, "nl80211: Could not register monitor read socket");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008309 goto error;
8310 }
8311
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008312 drv->monitor_refcount++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008313 return 0;
8314 error:
8315 nl80211_remove_monitor_interface(drv);
8316 return -1;
8317}
8318
8319
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008320static int nl80211_setup_ap(struct i802_bss *bss)
8321{
8322 struct wpa_driver_nl80211_data *drv = bss->drv;
8323
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008324 wpa_printf(MSG_DEBUG, "nl80211: Setup AP(%s) - device_ap_sme=%d use_monitor=%d",
8325 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008326
8327 /*
8328 * Disable Probe Request reporting unless we need it in this way for
8329 * devices that include the AP SME, in the other case (unless using
8330 * monitor iface) we'll get it through the nl_mgmt socket instead.
8331 */
8332 if (!drv->device_ap_sme)
8333 wpa_driver_nl80211_probe_req_report(bss, 0);
8334
8335 if (!drv->device_ap_sme && !drv->use_monitor)
8336 if (nl80211_mgmt_subscribe_ap(bss))
8337 return -1;
8338
8339 if (drv->device_ap_sme && !drv->use_monitor)
8340 if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
8341 return -1;
8342
8343 if (!drv->device_ap_sme && drv->use_monitor &&
8344 nl80211_create_monitor_interface(drv) &&
8345 !drv->device_ap_sme)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008346 return -1;
8347
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008348 if (drv->device_ap_sme &&
8349 wpa_driver_nl80211_probe_req_report(bss, 1) < 0) {
8350 wpa_printf(MSG_DEBUG, "nl80211: Failed to enable "
8351 "Probe Request frame reporting in AP mode");
8352 /* Try to survive without this */
8353 }
8354
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008355 return 0;
8356}
8357
8358
8359static void nl80211_teardown_ap(struct i802_bss *bss)
8360{
8361 struct wpa_driver_nl80211_data *drv = bss->drv;
8362
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008363 wpa_printf(MSG_DEBUG, "nl80211: Teardown AP(%s) - device_ap_sme=%d use_monitor=%d",
8364 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008365 if (drv->device_ap_sme) {
8366 wpa_driver_nl80211_probe_req_report(bss, 0);
8367 if (!drv->use_monitor)
8368 nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)");
8369 } else if (drv->use_monitor)
8370 nl80211_remove_monitor_interface(drv);
8371 else
8372 nl80211_mgmt_unsubscribe(bss, "AP teardown");
8373
8374 bss->beacon_set = 0;
8375}
8376
8377
8378static int nl80211_send_eapol_data(struct i802_bss *bss,
8379 const u8 *addr, const u8 *data,
8380 size_t data_len)
8381{
8382 struct sockaddr_ll ll;
8383 int ret;
8384
8385 if (bss->drv->eapol_tx_sock < 0) {
8386 wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL");
8387 return -1;
8388 }
8389
8390 os_memset(&ll, 0, sizeof(ll));
8391 ll.sll_family = AF_PACKET;
8392 ll.sll_ifindex = bss->ifindex;
8393 ll.sll_protocol = htons(ETH_P_PAE);
8394 ll.sll_halen = ETH_ALEN;
8395 os_memcpy(ll.sll_addr, addr, ETH_ALEN);
8396 ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,
8397 (struct sockaddr *) &ll, sizeof(ll));
8398 if (ret < 0)
8399 wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s",
8400 strerror(errno));
8401
8402 return ret;
8403}
8404
8405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008406static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
8407
8408static int wpa_driver_nl80211_hapd_send_eapol(
8409 void *priv, const u8 *addr, const u8 *data,
8410 size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
8411{
8412 struct i802_bss *bss = priv;
8413 struct wpa_driver_nl80211_data *drv = bss->drv;
8414 struct ieee80211_hdr *hdr;
8415 size_t len;
8416 u8 *pos;
8417 int res;
8418 int qos = flags & WPA_STA_WMM;
Dmitry Shmidt641185e2013-11-06 15:17:13 -08008419
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008420 if (drv->device_ap_sme || !drv->use_monitor)
8421 return nl80211_send_eapol_data(bss, addr, data, data_len);
8422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008423 len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
8424 data_len;
8425 hdr = os_zalloc(len);
8426 if (hdr == NULL) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008427 wpa_printf(MSG_INFO, "nl80211: Failed to allocate EAPOL buffer(len=%lu)",
8428 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008429 return -1;
8430 }
8431
8432 hdr->frame_control =
8433 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
8434 hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
8435 if (encrypt)
8436 hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
8437 if (qos) {
8438 hdr->frame_control |=
8439 host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
8440 }
8441
8442 memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
8443 memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
8444 memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
8445 pos = (u8 *) (hdr + 1);
8446
8447 if (qos) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07008448 /* Set highest priority in QoS header */
8449 pos[0] = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008450 pos[1] = 0;
8451 pos += 2;
8452 }
8453
8454 memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
8455 pos += sizeof(rfc1042_header);
8456 WPA_PUT_BE16(pos, ETH_P_PAE);
8457 pos += 2;
8458 memcpy(pos, data, data_len);
8459
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008460 res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
8461 0, 0, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008462 if (res < 0) {
8463 wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
8464 "failed: %d (%s)",
8465 (unsigned long) len, errno, strerror(errno));
8466 }
8467 os_free(hdr);
8468
8469 return res;
8470}
8471
8472
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008473static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
8474 int total_flags,
8475 int flags_or, int flags_and)
8476{
8477 struct i802_bss *bss = priv;
8478 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008479 struct nl_msg *msg;
8480 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008481 struct nl80211_sta_flag_update upd;
8482
8483 msg = nlmsg_alloc();
8484 if (!msg)
8485 return -ENOMEM;
8486
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008487 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008488
8489 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
8490 if_nametoindex(bss->ifname));
8491 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
8492
8493 /*
8494 * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
8495 * can be removed eventually.
8496 */
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008497 flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS);
8498 if (!flags)
8499 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008500 if (total_flags & WPA_STA_AUTHORIZED)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008501 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_AUTHORIZED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008502
8503 if (total_flags & WPA_STA_WMM)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008504 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_WME);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008505
8506 if (total_flags & WPA_STA_SHORT_PREAMBLE)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008507 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_SHORT_PREAMBLE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008508
8509 if (total_flags & WPA_STA_MFP)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008510 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_MFP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008511
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008512 if (total_flags & WPA_STA_TDLS_PEER)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008513 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_TDLS_PEER);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008514
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008515 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008516
8517 os_memset(&upd, 0, sizeof(upd));
8518 upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
8519 upd.set = sta_flags_nl80211(flags_or);
8520 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
8521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008522 return send_and_recv_msgs(drv, msg, NULL, NULL);
8523 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008524 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008525 return -ENOBUFS;
8526}
8527
8528
8529static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
8530 struct wpa_driver_associate_params *params)
8531{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008532 enum nl80211_iftype nlmode, old_mode;
8533 struct hostapd_freq_params freq = {
8534 .freq = params->freq,
8535 };
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008536
8537 if (params->p2p) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008538 wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
8539 "group (GO)");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008540 nlmode = NL80211_IFTYPE_P2P_GO;
8541 } else
8542 nlmode = NL80211_IFTYPE_AP;
8543
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008544 old_mode = drv->nlmode;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008545 if (wpa_driver_nl80211_set_mode(drv->first_bss, nlmode)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008546 nl80211_remove_monitor_interface(drv);
8547 return -1;
8548 }
8549
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07008550 if (nl80211_set_channel(drv->first_bss, &freq, 0)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008551 if (old_mode != nlmode)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008552 wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008553 nl80211_remove_monitor_interface(drv);
8554 return -1;
8555 }
8556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008557 return 0;
8558}
8559
8560
8561static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv)
8562{
8563 struct nl_msg *msg;
8564 int ret = -1;
8565
8566 msg = nlmsg_alloc();
8567 if (!msg)
8568 return -1;
8569
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008570 nl80211_cmd(drv, msg, 0, NL80211_CMD_LEAVE_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008571 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8572 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8573 msg = NULL;
8574 if (ret) {
8575 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
8576 "(%s)", ret, strerror(-ret));
8577 goto nla_put_failure;
8578 }
8579
8580 ret = 0;
8581 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS request sent successfully");
8582
8583nla_put_failure:
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008584 if (wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt56052862013-10-04 10:23:25 -07008585 NL80211_IFTYPE_STATION)) {
8586 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
8587 "station mode");
8588 }
8589
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008590 nlmsg_free(msg);
8591 return ret;
8592}
8593
8594
8595static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
8596 struct wpa_driver_associate_params *params)
8597{
8598 struct nl_msg *msg;
8599 int ret = -1;
8600 int count = 0;
8601
8602 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
8603
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07008604 if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, params->freq)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008605 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
8606 "IBSS mode");
8607 return -1;
8608 }
8609
8610retry:
8611 msg = nlmsg_alloc();
8612 if (!msg)
8613 return -1;
8614
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008615 nl80211_cmd(drv, msg, 0, NL80211_CMD_JOIN_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008616 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8617
8618 if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
8619 goto nla_put_failure;
8620
8621 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
8622 params->ssid, params->ssid_len);
8623 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
8624 params->ssid);
8625 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
8626 drv->ssid_len = params->ssid_len;
8627
8628 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
8629 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
8630
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08008631 if (params->beacon_int > 0) {
8632 wpa_printf(MSG_DEBUG, " * beacon_int=%d", params->beacon_int);
8633 NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL,
8634 params->beacon_int);
8635 }
8636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008637 ret = nl80211_set_conn_keys(params, msg);
8638 if (ret)
8639 goto nla_put_failure;
8640
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008641 if (params->bssid && params->fixed_bssid) {
8642 wpa_printf(MSG_DEBUG, " * BSSID=" MACSTR,
8643 MAC2STR(params->bssid));
8644 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
8645 }
8646
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008647 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
8648 params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
8649 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
8650 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008651 wpa_printf(MSG_DEBUG, " * control port");
8652 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
8653 }
8654
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008655 if (params->wpa_ie) {
8656 wpa_hexdump(MSG_DEBUG,
8657 " * Extra IEs for Beacon/Probe Response frames",
8658 params->wpa_ie, params->wpa_ie_len);
8659 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
8660 params->wpa_ie);
8661 }
8662
8663 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8664 msg = NULL;
8665 if (ret) {
8666 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
8667 ret, strerror(-ret));
8668 count++;
8669 if (ret == -EALREADY && count == 1) {
8670 wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after "
8671 "forced leave");
8672 nl80211_leave_ibss(drv);
8673 nlmsg_free(msg);
8674 goto retry;
8675 }
8676
8677 goto nla_put_failure;
8678 }
8679 ret = 0;
8680 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS request sent successfully");
8681
8682nla_put_failure:
8683 nlmsg_free(msg);
8684 return ret;
8685}
8686
8687
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008688static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
8689 struct wpa_driver_associate_params *params,
8690 struct nl_msg *msg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008691{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008692 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008693
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008694 if (params->bssid) {
8695 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
8696 MAC2STR(params->bssid));
8697 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
8698 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008699
Dmitry Shmidt96be6222014-02-13 10:16:51 -08008700 if (params->bssid_hint) {
8701 wpa_printf(MSG_DEBUG, " * bssid_hint=" MACSTR,
8702 MAC2STR(params->bssid_hint));
8703 NLA_PUT(msg, NL80211_ATTR_MAC_HINT, ETH_ALEN,
8704 params->bssid_hint);
8705 }
8706
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008707 if (params->freq) {
8708 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
8709 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07008710 drv->assoc_freq = params->freq;
8711 } else
8712 drv->assoc_freq = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008713
Dmitry Shmidt96be6222014-02-13 10:16:51 -08008714 if (params->freq_hint) {
8715 wpa_printf(MSG_DEBUG, " * freq_hint=%d", params->freq_hint);
8716 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ_HINT,
8717 params->freq_hint);
8718 }
8719
Dmitry Shmidt04949592012-07-19 12:16:46 -07008720 if (params->bg_scan_period >= 0) {
8721 wpa_printf(MSG_DEBUG, " * bg scan period=%d",
8722 params->bg_scan_period);
8723 NLA_PUT_U16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
8724 params->bg_scan_period);
8725 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008726
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008727 if (params->ssid) {
8728 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
8729 params->ssid, params->ssid_len);
8730 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
8731 params->ssid);
8732 if (params->ssid_len > sizeof(drv->ssid))
8733 goto nla_put_failure;
8734 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
8735 drv->ssid_len = params->ssid_len;
8736 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008737
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008738 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
8739 if (params->wpa_ie)
8740 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
8741 params->wpa_ie);
8742
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008743 if (params->wpa_proto) {
8744 enum nl80211_wpa_versions ver = 0;
8745
8746 if (params->wpa_proto & WPA_PROTO_WPA)
8747 ver |= NL80211_WPA_VERSION_1;
8748 if (params->wpa_proto & WPA_PROTO_RSN)
8749 ver |= NL80211_WPA_VERSION_2;
8750
8751 wpa_printf(MSG_DEBUG, " * WPA Versions 0x%x", ver);
8752 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
8753 }
8754
8755 if (params->pairwise_suite != WPA_CIPHER_NONE) {
8756 u32 cipher = wpa_cipher_to_cipher_suite(params->pairwise_suite);
8757 wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher);
8758 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
8759 }
8760
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008761 if (params->group_suite == WPA_CIPHER_GTK_NOT_USED &&
8762 !(drv->capa.enc & WPA_DRIVER_CAPA_ENC_GTK_NOT_USED)) {
8763 /*
8764 * This is likely to work even though many drivers do not
8765 * advertise support for operations without GTK.
8766 */
8767 wpa_printf(MSG_DEBUG, " * skip group cipher configuration for GTK_NOT_USED due to missing driver support advertisement");
8768 } else if (params->group_suite != WPA_CIPHER_NONE) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008769 u32 cipher = wpa_cipher_to_cipher_suite(params->group_suite);
8770 wpa_printf(MSG_DEBUG, " * group=0x%x", cipher);
8771 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
8772 }
8773
8774 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
8775 params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
8776 params->key_mgmt_suite == WPA_KEY_MGMT_FT_IEEE8021X ||
8777 params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
Dmitry Shmidt15907092014-03-25 10:42:57 -07008778 params->key_mgmt_suite == WPA_KEY_MGMT_CCKM ||
Dmitry Shmidt3c57b3f2014-05-22 15:13:07 -07008779 params->key_mgmt_suite == WPA_KEY_MGMT_OSEN ||
8780 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
8781 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008782 int mgmt = WLAN_AKM_SUITE_PSK;
8783
8784 switch (params->key_mgmt_suite) {
8785 case WPA_KEY_MGMT_CCKM:
8786 mgmt = WLAN_AKM_SUITE_CCKM;
8787 break;
8788 case WPA_KEY_MGMT_IEEE8021X:
8789 mgmt = WLAN_AKM_SUITE_8021X;
8790 break;
8791 case WPA_KEY_MGMT_FT_IEEE8021X:
8792 mgmt = WLAN_AKM_SUITE_FT_8021X;
8793 break;
8794 case WPA_KEY_MGMT_FT_PSK:
8795 mgmt = WLAN_AKM_SUITE_FT_PSK;
8796 break;
Dmitry Shmidt3c57b3f2014-05-22 15:13:07 -07008797 case WPA_KEY_MGMT_IEEE8021X_SHA256:
8798 mgmt = WLAN_AKM_SUITE_8021X_SHA256;
8799 break;
8800 case WPA_KEY_MGMT_PSK_SHA256:
8801 mgmt = WLAN_AKM_SUITE_PSK_SHA256;
8802 break;
Dmitry Shmidt15907092014-03-25 10:42:57 -07008803 case WPA_KEY_MGMT_OSEN:
8804 mgmt = WLAN_AKM_SUITE_OSEN;
8805 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008806 case WPA_KEY_MGMT_PSK:
8807 default:
8808 mgmt = WLAN_AKM_SUITE_PSK;
8809 break;
8810 }
Dmitry Shmidt15907092014-03-25 10:42:57 -07008811 wpa_printf(MSG_DEBUG, " * akm=0x%x", mgmt);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008812 NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);
8813 }
8814
8815 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
8816
8817 if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)
8818 NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);
8819
8820 if (params->disable_ht)
8821 NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);
8822
8823 if (params->htcaps && params->htcaps_mask) {
8824 int sz = sizeof(struct ieee80211_ht_capabilities);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07008825 wpa_hexdump(MSG_DEBUG, " * htcaps", params->htcaps, sz);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008826 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07008827 wpa_hexdump(MSG_DEBUG, " * htcaps_mask",
8828 params->htcaps_mask, sz);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008829 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
8830 params->htcaps_mask);
8831 }
8832
8833#ifdef CONFIG_VHT_OVERRIDES
8834 if (params->disable_vht) {
8835 wpa_printf(MSG_DEBUG, " * VHT disabled");
8836 NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
8837 }
8838
8839 if (params->vhtcaps && params->vhtcaps_mask) {
8840 int sz = sizeof(struct ieee80211_vht_capabilities);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07008841 wpa_hexdump(MSG_DEBUG, " * vhtcaps", params->vhtcaps, sz);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008842 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
Dmitry Shmidt61593f02014-04-21 16:27:35 -07008843 wpa_hexdump(MSG_DEBUG, " * vhtcaps_mask",
8844 params->vhtcaps_mask, sz);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008845 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
8846 params->vhtcaps_mask);
8847 }
8848#endif /* CONFIG_VHT_OVERRIDES */
8849
8850 if (params->p2p)
8851 wpa_printf(MSG_DEBUG, " * P2P group");
8852
8853 return 0;
8854nla_put_failure:
8855 return -1;
8856}
8857
8858
8859static int wpa_driver_nl80211_try_connect(
8860 struct wpa_driver_nl80211_data *drv,
8861 struct wpa_driver_associate_params *params)
8862{
8863 struct nl_msg *msg;
8864 enum nl80211_auth_type type;
8865 int ret;
8866 int algs;
8867
8868 msg = nlmsg_alloc();
8869 if (!msg)
8870 return -1;
8871
8872 wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
8873 nl80211_cmd(drv, msg, 0, NL80211_CMD_CONNECT);
8874
8875 ret = nl80211_connect_common(drv, params, msg);
8876 if (ret)
8877 goto nla_put_failure;
8878
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008879 algs = 0;
8880 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
8881 algs++;
8882 if (params->auth_alg & WPA_AUTH_ALG_SHARED)
8883 algs++;
8884 if (params->auth_alg & WPA_AUTH_ALG_LEAP)
8885 algs++;
8886 if (algs > 1) {
8887 wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic "
8888 "selection");
8889 goto skip_auth_type;
8890 }
8891
8892 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
8893 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
8894 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
8895 type = NL80211_AUTHTYPE_SHARED_KEY;
8896 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
8897 type = NL80211_AUTHTYPE_NETWORK_EAP;
8898 else if (params->auth_alg & WPA_AUTH_ALG_FT)
8899 type = NL80211_AUTHTYPE_FT;
8900 else
8901 goto nla_put_failure;
8902
8903 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
8904 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
8905
8906skip_auth_type:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008907 ret = nl80211_set_conn_keys(params, msg);
8908 if (ret)
8909 goto nla_put_failure;
8910
8911 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8912 msg = NULL;
8913 if (ret) {
8914 wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
8915 "(%s)", ret, strerror(-ret));
8916 goto nla_put_failure;
8917 }
8918 ret = 0;
8919 wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully");
8920
8921nla_put_failure:
8922 nlmsg_free(msg);
8923 return ret;
8924
8925}
8926
8927
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008928static int wpa_driver_nl80211_connect(
8929 struct wpa_driver_nl80211_data *drv,
8930 struct wpa_driver_associate_params *params)
8931{
8932 int ret = wpa_driver_nl80211_try_connect(drv, params);
8933 if (ret == -EALREADY) {
8934 /*
8935 * cfg80211 does not currently accept new connections if
8936 * we are already connected. As a workaround, force
8937 * disconnection and try again.
8938 */
8939 wpa_printf(MSG_DEBUG, "nl80211: Explicitly "
8940 "disconnecting before reassociation "
8941 "attempt");
8942 if (wpa_driver_nl80211_disconnect(
8943 drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
8944 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008945 ret = wpa_driver_nl80211_try_connect(drv, params);
8946 }
8947 return ret;
8948}
8949
8950
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008951static int wpa_driver_nl80211_associate(
8952 void *priv, struct wpa_driver_associate_params *params)
8953{
8954 struct i802_bss *bss = priv;
8955 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008956 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008957 struct nl_msg *msg;
8958
8959 if (params->mode == IEEE80211_MODE_AP)
8960 return wpa_driver_nl80211_ap(drv, params);
8961
8962 if (params->mode == IEEE80211_MODE_IBSS)
8963 return wpa_driver_nl80211_ibss(drv, params);
8964
8965 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008966 enum nl80211_iftype nlmode = params->p2p ?
8967 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
8968
8969 if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008970 return -1;
8971 return wpa_driver_nl80211_connect(drv, params);
8972 }
8973
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008974 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008975
8976 msg = nlmsg_alloc();
8977 if (!msg)
8978 return -1;
8979
8980 wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)",
8981 drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008982 nl80211_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008983
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008984 ret = nl80211_connect_common(drv, params, msg);
8985 if (ret)
8986 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008987
8988 if (params->prev_bssid) {
8989 wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
8990 MAC2STR(params->prev_bssid));
8991 NLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
8992 params->prev_bssid);
8993 }
8994
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008995 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8996 msg = NULL;
8997 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008998 wpa_dbg(drv->ctx, MSG_DEBUG,
8999 "nl80211: MLME command failed (assoc): ret=%d (%s)",
9000 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009001 nl80211_dump_scan(drv);
9002 goto nla_put_failure;
9003 }
9004 ret = 0;
9005 wpa_printf(MSG_DEBUG, "nl80211: Association request send "
9006 "successfully");
9007
9008nla_put_failure:
9009 nlmsg_free(msg);
9010 return ret;
9011}
9012
9013
9014static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009015 int ifindex, enum nl80211_iftype mode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009016{
9017 struct nl_msg *msg;
9018 int ret = -ENOBUFS;
9019
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009020 wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)",
9021 ifindex, mode, nl80211_iftype_str(mode));
9022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009023 msg = nlmsg_alloc();
9024 if (!msg)
9025 return -ENOMEM;
9026
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009027 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009028 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009029 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009030 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);
9031
9032 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009033 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009034 if (!ret)
9035 return 0;
9036nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009037 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009038 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
9039 " %d (%s)", ifindex, mode, ret, strerror(-ret));
9040 return ret;
9041}
9042
9043
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009044static int wpa_driver_nl80211_set_mode_impl(
9045 struct i802_bss *bss,
9046 enum nl80211_iftype nlmode,
9047 struct hostapd_freq_params *desired_freq_params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009048{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009049 struct wpa_driver_nl80211_data *drv = bss->drv;
9050 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009051 int i;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009052 int was_ap = is_ap_interface(drv->nlmode);
9053 int res;
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009054 int mode_switch_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009055
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009056 mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
9057 if (mode_switch_res && nlmode == nl80211_get_ifmode(bss))
9058 mode_switch_res = 0;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009059
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009060 if (mode_switch_res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009061 drv->nlmode = nlmode;
9062 ret = 0;
9063 goto done;
9064 }
9065
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009066 if (mode_switch_res == -ENODEV)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009067 return -1;
9068
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009069 if (nlmode == drv->nlmode) {
9070 wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
9071 "requested mode - ignore error");
9072 ret = 0;
9073 goto done; /* Already in the requested mode */
9074 }
9075
9076 /* mac80211 doesn't allow mode changes while the device is up, so
9077 * take the device down, try to set the mode again, and bring the
9078 * device back up.
9079 */
9080 wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
9081 "interface down");
9082 for (i = 0; i < 10; i++) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009083 res = i802_set_iface_flags(bss, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009084 if (res == -EACCES || res == -ENODEV)
9085 break;
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009086 if (res != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009087 wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
9088 "interface down");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009089 os_sleep(0, 100000);
9090 continue;
9091 }
9092
9093 /*
9094 * Setting the mode will fail for some drivers if the phy is
9095 * on a frequency that the mode is disallowed in.
9096 */
9097 if (desired_freq_params) {
9098 res = i802_set_freq(bss, desired_freq_params);
9099 if (res) {
9100 wpa_printf(MSG_DEBUG,
9101 "nl80211: Failed to set frequency on interface");
9102 }
9103 }
9104
9105 /* Try to set the mode again while the interface is down */
9106 mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
9107 if (mode_switch_res == -EBUSY) {
9108 wpa_printf(MSG_DEBUG,
9109 "nl80211: Delaying mode set while interface going down");
9110 os_sleep(0, 100000);
9111 continue;
9112 }
9113 ret = mode_switch_res;
9114 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009115 }
9116
9117 if (!ret) {
9118 wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
9119 "interface is down");
9120 drv->nlmode = nlmode;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009121 drv->ignore_if_down_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009122 }
9123
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009124 /* Bring the interface back up */
9125 res = linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
9126 if (res != 0) {
9127 wpa_printf(MSG_DEBUG,
9128 "nl80211: Failed to set interface up after switching mode");
9129 ret = -1;
9130 }
9131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009132done:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009133 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009134 wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
9135 "from %d failed", nlmode, drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009136 return ret;
9137 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009138
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009139 if (is_p2p_net_interface(nlmode))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009140 nl80211_disable_11b_rates(drv, drv->ifindex, 1);
9141 else if (drv->disabled_11b_rates)
9142 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
9143
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009144 if (is_ap_interface(nlmode)) {
9145 nl80211_mgmt_unsubscribe(bss, "start AP");
9146 /* Setup additional AP mode functionality if needed */
9147 if (nl80211_setup_ap(bss))
9148 return -1;
9149 } else if (was_ap) {
9150 /* Remove additional AP mode functionality */
9151 nl80211_teardown_ap(bss);
9152 } else {
9153 nl80211_mgmt_unsubscribe(bss, "mode change");
9154 }
9155
Dmitry Shmidt04949592012-07-19 12:16:46 -07009156 if (!bss->in_deinit && !is_ap_interface(nlmode) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009157 nl80211_mgmt_subscribe_non_ap(bss) < 0)
9158 wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
9159 "frame processing - ignore for now");
9160
9161 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009162}
9163
9164
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07009165static int dfs_info_handler(struct nl_msg *msg, void *arg)
9166{
9167 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9168 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9169 int *dfs_capability_ptr = arg;
9170
9171 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9172 genlmsg_attrlen(gnlh, 0), NULL);
9173
9174 if (tb[NL80211_ATTR_VENDOR_DATA]) {
9175 struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
9176 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9177
9178 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
9179 nla_data(nl_vend), nla_len(nl_vend), NULL);
9180
9181 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]) {
9182 u32 val;
9183 val = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_DFS]);
9184 wpa_printf(MSG_DEBUG, "nl80211: DFS offload capability: %u",
9185 val);
9186 *dfs_capability_ptr = val;
9187 }
9188 }
9189
9190 return NL_SKIP;
9191}
9192
9193
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07009194static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
9195 enum nl80211_iftype nlmode)
9196{
9197 return wpa_driver_nl80211_set_mode_impl(bss, nlmode, NULL);
9198}
9199
9200
9201static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, int freq)
9202{
9203 struct hostapd_freq_params freq_params;
9204 os_memset(&freq_params, 0, sizeof(freq_params));
9205 freq_params.freq = freq;
9206 return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC,
9207 &freq_params);
9208}
9209
9210
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009211static int wpa_driver_nl80211_get_capa(void *priv,
9212 struct wpa_driver_capa *capa)
9213{
9214 struct i802_bss *bss = priv;
9215 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07009216 struct nl_msg *msg;
9217 int dfs_capability = 0;
9218 int ret = 0;
9219
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009220 if (!drv->has_capability)
9221 return -1;
9222 os_memcpy(capa, &drv->capa, sizeof(*capa));
Dmitry Shmidt444d5672013-04-01 13:08:44 -07009223 if (drv->extended_capa && drv->extended_capa_mask) {
9224 capa->extended_capa = drv->extended_capa;
9225 capa->extended_capa_mask = drv->extended_capa_mask;
9226 capa->extended_capa_len = drv->extended_capa_len;
9227 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009228
9229 if ((capa->flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
9230 !drv->allow_p2p_device) {
9231 wpa_printf(MSG_DEBUG, "nl80211: Do not indicate P2P_DEVICE support (p2p_device=1 driver param not specified)");
9232 capa->flags &= ~WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
9233 }
9234
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07009235 if (drv->dfs_vendor_cmd_avail == 1) {
9236 msg = nlmsg_alloc();
9237 if (!msg)
9238 return -ENOMEM;
9239
9240 nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR);
9241
9242 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
9243 NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA);
9244 NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD,
9245 QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY);
9246
9247 ret = send_and_recv_msgs(drv, msg, dfs_info_handler,
9248 &dfs_capability);
9249 if (!ret) {
9250 if (dfs_capability)
9251 capa->flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD;
9252 }
9253 }
9254
9255 return ret;
9256
9257 nla_put_failure:
9258 nlmsg_free(msg);
9259 return -ENOBUFS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009260}
9261
9262
9263static int wpa_driver_nl80211_set_operstate(void *priv, int state)
9264{
9265 struct i802_bss *bss = priv;
9266 struct wpa_driver_nl80211_data *drv = bss->drv;
9267
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009268 wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)",
9269 bss->ifname, drv->operstate, state,
9270 state ? "UP" : "DORMANT");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009271 drv->operstate = state;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009272 return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009273 state ? IF_OPER_UP : IF_OPER_DORMANT);
9274}
9275
9276
9277static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
9278{
9279 struct i802_bss *bss = priv;
9280 struct wpa_driver_nl80211_data *drv = bss->drv;
9281 struct nl_msg *msg;
9282 struct nl80211_sta_flag_update upd;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009283 int ret = -ENOBUFS;
9284
9285 if (!drv->associated && is_zero_ether_addr(drv->bssid) && !authorized) {
9286 wpa_printf(MSG_DEBUG, "nl80211: Skip set_supp_port(unauthorized) while not associated");
9287 return 0;
9288 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009289
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07009290 wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
9291 MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
9292
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009293 msg = nlmsg_alloc();
9294 if (!msg)
9295 return -ENOMEM;
9296
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009297 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009298
9299 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
9300 if_nametoindex(bss->ifname));
9301 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
9302
9303 os_memset(&upd, 0, sizeof(upd));
9304 upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);
9305 if (authorized)
9306 upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);
9307 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
9308
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009309 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9310 msg = NULL;
9311 if (!ret)
9312 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009313 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009314 nlmsg_free(msg);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08009315 wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)",
9316 ret, strerror(-ret));
9317 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009318}
9319
9320
Jouni Malinen75ecf522011-06-27 15:19:46 -07009321/* Set kernel driver on given frequency (MHz) */
9322static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009323{
Jouni Malinen75ecf522011-06-27 15:19:46 -07009324 struct i802_bss *bss = priv;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07009325 return nl80211_set_channel(bss, freq, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009326}
9327
9328
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009329static inline int min_int(int a, int b)
9330{
9331 if (a < b)
9332 return a;
9333 return b;
9334}
9335
9336
9337static int get_key_handler(struct nl_msg *msg, void *arg)
9338{
9339 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9340 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9341
9342 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9343 genlmsg_attrlen(gnlh, 0), NULL);
9344
9345 /*
9346 * TODO: validate the key index and mac address!
9347 * Otherwise, there's a race condition as soon as
9348 * the kernel starts sending key notifications.
9349 */
9350
9351 if (tb[NL80211_ATTR_KEY_SEQ])
9352 memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
9353 min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
9354 return NL_SKIP;
9355}
9356
9357
9358static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
9359 int idx, u8 *seq)
9360{
9361 struct i802_bss *bss = priv;
9362 struct wpa_driver_nl80211_data *drv = bss->drv;
9363 struct nl_msg *msg;
9364
9365 msg = nlmsg_alloc();
9366 if (!msg)
9367 return -ENOMEM;
9368
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009369 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009370
9371 if (addr)
9372 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
9373 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
9374 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
9375
9376 memset(seq, 0, 6);
9377
9378 return send_and_recv_msgs(drv, msg, get_key_handler, seq);
9379 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009380 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009381 return -ENOBUFS;
9382}
9383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009384
9385static int i802_set_rts(void *priv, int rts)
9386{
9387 struct i802_bss *bss = priv;
9388 struct wpa_driver_nl80211_data *drv = bss->drv;
9389 struct nl_msg *msg;
9390 int ret = -ENOBUFS;
9391 u32 val;
9392
9393 msg = nlmsg_alloc();
9394 if (!msg)
9395 return -ENOMEM;
9396
9397 if (rts >= 2347)
9398 val = (u32) -1;
9399 else
9400 val = rts;
9401
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009402 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009403 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
9404 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val);
9405
9406 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009407 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009408 if (!ret)
9409 return 0;
9410nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009411 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009412 wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
9413 "%d (%s)", rts, ret, strerror(-ret));
9414 return ret;
9415}
9416
9417
9418static int i802_set_frag(void *priv, int frag)
9419{
9420 struct i802_bss *bss = priv;
9421 struct wpa_driver_nl80211_data *drv = bss->drv;
9422 struct nl_msg *msg;
9423 int ret = -ENOBUFS;
9424 u32 val;
9425
9426 msg = nlmsg_alloc();
9427 if (!msg)
9428 return -ENOMEM;
9429
9430 if (frag >= 2346)
9431 val = (u32) -1;
9432 else
9433 val = frag;
9434
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009435 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009436 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
9437 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val);
9438
9439 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009440 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009441 if (!ret)
9442 return 0;
9443nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009444 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009445 wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
9446 "%d: %d (%s)", frag, ret, strerror(-ret));
9447 return ret;
9448}
9449
9450
9451static int i802_flush(void *priv)
9452{
9453 struct i802_bss *bss = priv;
9454 struct wpa_driver_nl80211_data *drv = bss->drv;
9455 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009456 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009457
9458 msg = nlmsg_alloc();
9459 if (!msg)
9460 return -1;
9461
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07009462 wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
9463 bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009464 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009465
9466 /*
9467 * XXX: FIX! this needs to flush all VLANs too
9468 */
9469 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
9470 if_nametoindex(bss->ifname));
9471
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009472 res = send_and_recv_msgs(drv, msg, NULL, NULL);
9473 if (res) {
9474 wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
9475 "(%s)", res, strerror(-res));
9476 }
9477 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009478 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009479 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009480 return -ENOBUFS;
9481}
9482
9483
9484static int get_sta_handler(struct nl_msg *msg, void *arg)
9485{
9486 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9487 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9488 struct hostap_sta_driver_data *data = arg;
9489 struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
9490 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9491 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
9492 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
9493 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
9494 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
9495 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03009496 [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009497 };
9498
9499 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9500 genlmsg_attrlen(gnlh, 0), NULL);
9501
9502 /*
9503 * TODO: validate the interface and mac address!
9504 * Otherwise, there's a race condition as soon as
9505 * the kernel starts sending station notifications.
9506 */
9507
9508 if (!tb[NL80211_ATTR_STA_INFO]) {
9509 wpa_printf(MSG_DEBUG, "sta stats missing!");
9510 return NL_SKIP;
9511 }
9512 if (nla_parse_nested(stats, NL80211_STA_INFO_MAX,
9513 tb[NL80211_ATTR_STA_INFO],
9514 stats_policy)) {
9515 wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
9516 return NL_SKIP;
9517 }
9518
9519 if (stats[NL80211_STA_INFO_INACTIVE_TIME])
9520 data->inactive_msec =
9521 nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);
9522 if (stats[NL80211_STA_INFO_RX_BYTES])
9523 data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
9524 if (stats[NL80211_STA_INFO_TX_BYTES])
9525 data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
9526 if (stats[NL80211_STA_INFO_RX_PACKETS])
9527 data->rx_packets =
9528 nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
9529 if (stats[NL80211_STA_INFO_TX_PACKETS])
9530 data->tx_packets =
9531 nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03009532 if (stats[NL80211_STA_INFO_TX_FAILED])
9533 data->tx_retry_failed =
9534 nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009535
9536 return NL_SKIP;
9537}
9538
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009539static int i802_read_sta_data(struct i802_bss *bss,
9540 struct hostap_sta_driver_data *data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009541 const u8 *addr)
9542{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009543 struct wpa_driver_nl80211_data *drv = bss->drv;
9544 struct nl_msg *msg;
9545
9546 os_memset(data, 0, sizeof(*data));
9547 msg = nlmsg_alloc();
9548 if (!msg)
9549 return -ENOMEM;
9550
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009551 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009552
9553 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
9554 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
9555
9556 return send_and_recv_msgs(drv, msg, get_sta_handler, data);
9557 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009558 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009559 return -ENOBUFS;
9560}
9561
9562
9563static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
9564 int cw_min, int cw_max, int burst_time)
9565{
9566 struct i802_bss *bss = priv;
9567 struct wpa_driver_nl80211_data *drv = bss->drv;
9568 struct nl_msg *msg;
9569 struct nlattr *txq, *params;
9570
9571 msg = nlmsg_alloc();
9572 if (!msg)
9573 return -1;
9574
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009575 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009576
9577 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
9578
9579 txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);
9580 if (!txq)
9581 goto nla_put_failure;
9582
9583 /* We are only sending parameters for a single TXQ at a time */
9584 params = nla_nest_start(msg, 1);
9585 if (!params)
9586 goto nla_put_failure;
9587
9588 switch (queue) {
9589 case 0:
9590 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO);
9591 break;
9592 case 1:
9593 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI);
9594 break;
9595 case 2:
9596 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE);
9597 break;
9598 case 3:
9599 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK);
9600 break;
9601 }
9602 /* Burst time is configured in units of 0.1 msec and TXOP parameter in
9603 * 32 usec, so need to convert the value here. */
9604 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32);
9605 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min);
9606 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max);
9607 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs);
9608
9609 nla_nest_end(msg, params);
9610
9611 nla_nest_end(msg, txq);
9612
9613 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
9614 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009615 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009616 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009617 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009618 return -1;
9619}
9620
9621
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009622static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009623 const char *ifname, int vlan_id)
9624{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009625 struct wpa_driver_nl80211_data *drv = bss->drv;
9626 struct nl_msg *msg;
9627 int ret = -ENOBUFS;
9628
9629 msg = nlmsg_alloc();
9630 if (!msg)
9631 return -ENOMEM;
9632
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009633 wpa_printf(MSG_DEBUG, "nl80211: %s[%d]: set_sta_vlan(" MACSTR
9634 ", ifname=%s[%d], vlan_id=%d)",
9635 bss->ifname, if_nametoindex(bss->ifname),
9636 MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009637 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009638
9639 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
9640 if_nametoindex(bss->ifname));
9641 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
9642 NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN,
9643 if_nametoindex(ifname));
9644
9645 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009646 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009647 if (ret < 0) {
9648 wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
9649 MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
9650 MAC2STR(addr), ifname, vlan_id, ret,
9651 strerror(-ret));
9652 }
9653 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009654 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009655 return ret;
9656}
9657
9658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009659static int i802_get_inact_sec(void *priv, const u8 *addr)
9660{
9661 struct hostap_sta_driver_data data;
9662 int ret;
9663
9664 data.inactive_msec = (unsigned long) -1;
9665 ret = i802_read_sta_data(priv, &data, addr);
9666 if (ret || data.inactive_msec == (unsigned long) -1)
9667 return -1;
9668 return data.inactive_msec / 1000;
9669}
9670
9671
9672static int i802_sta_clear_stats(void *priv, const u8 *addr)
9673{
9674#if 0
9675 /* TODO */
9676#endif
9677 return 0;
9678}
9679
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009680
9681static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
9682 int reason)
9683{
9684 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07009685 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009686 struct ieee80211_mgmt mgmt;
9687
Dmitry Shmidt04949592012-07-19 12:16:46 -07009688 if (drv->device_ap_sme)
9689 return wpa_driver_nl80211_sta_remove(bss, addr);
9690
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009691 memset(&mgmt, 0, sizeof(mgmt));
9692 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
9693 WLAN_FC_STYPE_DEAUTH);
9694 memcpy(mgmt.da, addr, ETH_ALEN);
9695 memcpy(mgmt.sa, own_addr, ETH_ALEN);
9696 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
9697 mgmt.u.deauth.reason_code = host_to_le16(reason);
9698 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
9699 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009700 sizeof(mgmt.u.deauth), 0, 0, 0, 0,
9701 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009702}
9703
9704
9705static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
9706 int reason)
9707{
9708 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07009709 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009710 struct ieee80211_mgmt mgmt;
9711
Dmitry Shmidt04949592012-07-19 12:16:46 -07009712 if (drv->device_ap_sme)
9713 return wpa_driver_nl80211_sta_remove(bss, addr);
9714
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009715 memset(&mgmt, 0, sizeof(mgmt));
9716 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
9717 WLAN_FC_STYPE_DISASSOC);
9718 memcpy(mgmt.da, addr, ETH_ALEN);
9719 memcpy(mgmt.sa, own_addr, ETH_ALEN);
9720 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
9721 mgmt.u.disassoc.reason_code = host_to_le16(reason);
9722 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
9723 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009724 sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
9725 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009726}
9727
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009728
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07009729static void dump_ifidx(struct wpa_driver_nl80211_data *drv)
9730{
9731 char buf[200], *pos, *end;
9732 int i, res;
9733
9734 pos = buf;
9735 end = pos + sizeof(buf);
9736
9737 for (i = 0; i < drv->num_if_indices; i++) {
9738 if (!drv->if_indices[i])
9739 continue;
9740 res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]);
9741 if (res < 0 || res >= end - pos)
9742 break;
9743 pos += res;
9744 }
9745 *pos = '\0';
9746
9747 wpa_printf(MSG_DEBUG, "nl80211: if_indices[%d]:%s",
9748 drv->num_if_indices, buf);
9749}
9750
9751
Jouni Malinen75ecf522011-06-27 15:19:46 -07009752static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9753{
9754 int i;
9755 int *old;
9756
9757 wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
9758 ifidx);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07009759 if (have_ifidx(drv, ifidx)) {
9760 wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
9761 ifidx);
9762 return;
9763 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07009764 for (i = 0; i < drv->num_if_indices; i++) {
9765 if (drv->if_indices[i] == 0) {
9766 drv->if_indices[i] = ifidx;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07009767 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07009768 return;
9769 }
9770 }
9771
9772 if (drv->if_indices != drv->default_if_indices)
9773 old = drv->if_indices;
9774 else
9775 old = NULL;
9776
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009777 drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
9778 sizeof(int));
Jouni Malinen75ecf522011-06-27 15:19:46 -07009779 if (!drv->if_indices) {
9780 if (!old)
9781 drv->if_indices = drv->default_if_indices;
9782 else
9783 drv->if_indices = old;
9784 wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
9785 "interfaces");
9786 wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
9787 return;
9788 } else if (!old)
9789 os_memcpy(drv->if_indices, drv->default_if_indices,
9790 sizeof(drv->default_if_indices));
9791 drv->if_indices[drv->num_if_indices] = ifidx;
9792 drv->num_if_indices++;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07009793 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07009794}
9795
9796
9797static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9798{
9799 int i;
9800
9801 for (i = 0; i < drv->num_if_indices; i++) {
9802 if (drv->if_indices[i] == ifidx) {
9803 drv->if_indices[i] = 0;
9804 break;
9805 }
9806 }
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07009807 dump_ifidx(drv);
Jouni Malinen75ecf522011-06-27 15:19:46 -07009808}
9809
9810
9811static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9812{
9813 int i;
9814
9815 for (i = 0; i < drv->num_if_indices; i++)
9816 if (drv->if_indices[i] == ifidx)
9817 return 1;
9818
9819 return 0;
9820}
9821
9822
9823static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07009824 const char *bridge_ifname, char *ifname_wds)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009825{
9826 struct i802_bss *bss = priv;
9827 struct wpa_driver_nl80211_data *drv = bss->drv;
9828 char name[IFNAMSIZ + 1];
9829
9830 os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009831 if (ifname_wds)
9832 os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
9833
Jouni Malinen75ecf522011-06-27 15:19:46 -07009834 wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
9835 " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
9836 if (val) {
9837 if (!if_nametoindex(name)) {
9838 if (nl80211_create_iface(drv, name,
9839 NL80211_IFTYPE_AP_VLAN,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009840 bss->addr, 1, NULL, NULL, 0) <
9841 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009842 return -1;
9843 if (bridge_ifname &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009844 linux_br_add_if(drv->global->ioctl_sock,
9845 bridge_ifname, name) < 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009846 return -1;
9847 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009848 if (linux_set_iface_flags(drv->global->ioctl_sock, name, 1)) {
9849 wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA "
9850 "interface %s up", name);
9851 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07009852 return i802_set_sta_vlan(priv, addr, name, 0);
9853 } else {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07009854 if (bridge_ifname)
9855 linux_br_del_if(drv->global->ioctl_sock, bridge_ifname,
9856 name);
9857
Jouni Malinen75ecf522011-06-27 15:19:46 -07009858 i802_set_sta_vlan(priv, addr, bss->ifname, 0);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08009859 nl80211_remove_iface(drv, if_nametoindex(name));
9860 return 0;
Jouni Malinen75ecf522011-06-27 15:19:46 -07009861 }
9862}
9863
9864
9865static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
9866{
9867 struct wpa_driver_nl80211_data *drv = eloop_ctx;
9868 struct sockaddr_ll lladdr;
9869 unsigned char buf[3000];
9870 int len;
9871 socklen_t fromlen = sizeof(lladdr);
9872
9873 len = recvfrom(sock, buf, sizeof(buf), 0,
9874 (struct sockaddr *)&lladdr, &fromlen);
9875 if (len < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009876 wpa_printf(MSG_ERROR, "nl80211: EAPOL recv failed: %s",
9877 strerror(errno));
Jouni Malinen75ecf522011-06-27 15:19:46 -07009878 return;
9879 }
9880
9881 if (have_ifidx(drv, lladdr.sll_ifindex))
9882 drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
9883}
9884
9885
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009886static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
9887 struct i802_bss *bss,
9888 const char *brname, const char *ifname)
9889{
9890 int ifindex;
9891 char in_br[IFNAMSIZ];
9892
9893 os_strlcpy(bss->brname, brname, IFNAMSIZ);
9894 ifindex = if_nametoindex(brname);
9895 if (ifindex == 0) {
9896 /*
9897 * Bridge was configured, but the bridge device does
9898 * not exist. Try to add it now.
9899 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009900 if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009901 wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
9902 "bridge interface %s: %s",
9903 brname, strerror(errno));
9904 return -1;
9905 }
9906 bss->added_bridge = 1;
9907 add_ifidx(drv, if_nametoindex(brname));
9908 }
9909
9910 if (linux_br_get(in_br, ifname) == 0) {
9911 if (os_strcmp(in_br, brname) == 0)
9912 return 0; /* already in the bridge */
9913
9914 wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
9915 "bridge %s", ifname, in_br);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009916 if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
9917 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009918 wpa_printf(MSG_ERROR, "nl80211: Failed to "
9919 "remove interface %s from bridge "
9920 "%s: %s",
9921 ifname, brname, strerror(errno));
9922 return -1;
9923 }
9924 }
9925
9926 wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
9927 ifname, brname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009928 if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009929 wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
9930 "into bridge %s: %s",
9931 ifname, brname, strerror(errno));
9932 return -1;
9933 }
9934 bss->added_if_into_bridge = 1;
9935
9936 return 0;
9937}
9938
9939
9940static void *i802_init(struct hostapd_data *hapd,
9941 struct wpa_init_params *params)
9942{
9943 struct wpa_driver_nl80211_data *drv;
9944 struct i802_bss *bss;
9945 size_t i;
9946 char brname[IFNAMSIZ];
9947 int ifindex, br_ifindex;
9948 int br_added = 0;
9949
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08009950 bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
9951 params->global_priv, 1,
9952 params->bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009953 if (bss == NULL)
9954 return NULL;
9955
9956 drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009958 if (linux_br_get(brname, params->ifname) == 0) {
9959 wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
9960 params->ifname, brname);
9961 br_ifindex = if_nametoindex(brname);
9962 } else {
9963 brname[0] = '\0';
9964 br_ifindex = 0;
9965 }
9966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009967 for (i = 0; i < params->num_bridge; i++) {
9968 if (params->bridge[i]) {
9969 ifindex = if_nametoindex(params->bridge[i]);
9970 if (ifindex)
9971 add_ifidx(drv, ifindex);
9972 if (ifindex == br_ifindex)
9973 br_added = 1;
9974 }
9975 }
9976 if (!br_added && br_ifindex &&
9977 (params->num_bridge == 0 || !params->bridge[0]))
9978 add_ifidx(drv, br_ifindex);
9979
9980 /* start listening for EAPOL on the default AP interface */
9981 add_ifidx(drv, drv->ifindex);
9982
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009983 if (params->num_bridge && params->bridge[0] &&
9984 i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)
9985 goto failed;
9986
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009987 drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
9988 if (drv->eapol_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009989 wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s",
9990 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009991 goto failed;
9992 }
9993
9994 if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
9995 {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009996 wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009997 goto failed;
9998 }
9999
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010000 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
10001 params->own_addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010002 goto failed;
10003
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010004 memcpy(bss->addr, params->own_addr, ETH_ALEN);
10005
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010006 return bss;
10007
10008failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010009 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010010 return NULL;
10011}
10012
10013
10014static void i802_deinit(void *priv)
10015{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010016 struct i802_bss *bss = priv;
10017 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010018}
10019
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010020
10021static enum nl80211_iftype wpa_driver_nl80211_if_type(
10022 enum wpa_driver_if_type type)
10023{
10024 switch (type) {
10025 case WPA_IF_STATION:
10026 return NL80211_IFTYPE_STATION;
10027 case WPA_IF_P2P_CLIENT:
10028 case WPA_IF_P2P_GROUP:
10029 return NL80211_IFTYPE_P2P_CLIENT;
10030 case WPA_IF_AP_VLAN:
10031 return NL80211_IFTYPE_AP_VLAN;
10032 case WPA_IF_AP_BSS:
10033 return NL80211_IFTYPE_AP;
10034 case WPA_IF_P2P_GO:
10035 return NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010036 case WPA_IF_P2P_DEVICE:
10037 return NL80211_IFTYPE_P2P_DEVICE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010038 }
10039 return -1;
10040}
10041
10042
10043#ifdef CONFIG_P2P
10044
10045static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr)
10046{
10047 struct wpa_driver_nl80211_data *drv;
10048 dl_list_for_each(drv, &global->interfaces,
10049 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010050 if (os_memcmp(addr, drv->first_bss->addr, ETH_ALEN) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010051 return 1;
10052 }
10053 return 0;
10054}
10055
10056
10057static int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv,
10058 u8 *new_addr)
10059{
10060 unsigned int idx;
10061
10062 if (!drv->global)
10063 return -1;
10064
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010065 os_memcpy(new_addr, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010066 for (idx = 0; idx < 64; idx++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010067 new_addr[0] = drv->first_bss->addr[0] | 0x02;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010068 new_addr[0] ^= idx << 2;
10069 if (!nl80211_addr_in_use(drv->global, new_addr))
10070 break;
10071 }
10072 if (idx == 64)
10073 return -1;
10074
10075 wpa_printf(MSG_DEBUG, "nl80211: Assigned new P2P Interface Address "
10076 MACSTR, MAC2STR(new_addr));
10077
10078 return 0;
10079}
10080
10081#endif /* CONFIG_P2P */
10082
10083
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010084struct wdev_info {
10085 u64 wdev_id;
10086 int wdev_id_set;
10087 u8 macaddr[ETH_ALEN];
10088};
10089
10090static int nl80211_wdev_handler(struct nl_msg *msg, void *arg)
10091{
10092 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10093 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10094 struct wdev_info *wi = arg;
10095
10096 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10097 genlmsg_attrlen(gnlh, 0), NULL);
10098 if (tb[NL80211_ATTR_WDEV]) {
10099 wi->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
10100 wi->wdev_id_set = 1;
10101 }
10102
10103 if (tb[NL80211_ATTR_MAC])
10104 os_memcpy(wi->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
10105 ETH_ALEN);
10106
10107 return NL_SKIP;
10108}
10109
10110
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010111static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
10112 const char *ifname, const u8 *addr,
10113 void *bss_ctx, void **drv_priv,
10114 char *force_ifname, u8 *if_addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010115 const char *bridge, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010116{
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010117 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010118 struct i802_bss *bss = priv;
10119 struct wpa_driver_nl80211_data *drv = bss->drv;
10120 int ifidx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010121 int added = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010122
10123 if (addr)
10124 os_memcpy(if_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010125 nlmode = wpa_driver_nl80211_if_type(type);
10126 if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
10127 struct wdev_info p2pdev_info;
10128
10129 os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
10130 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
10131 0, nl80211_wdev_handler,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010132 &p2pdev_info, use_existing);
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010133 if (!p2pdev_info.wdev_id_set || ifidx != 0) {
10134 wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s",
10135 ifname);
10136 return -1;
10137 }
10138
10139 drv->global->if_add_wdevid = p2pdev_info.wdev_id;
10140 drv->global->if_add_wdevid_set = p2pdev_info.wdev_id_set;
10141 if (!is_zero_ether_addr(p2pdev_info.macaddr))
10142 os_memcpy(if_addr, p2pdev_info.macaddr, ETH_ALEN);
10143 wpa_printf(MSG_DEBUG, "nl80211: New P2P Device interface %s (0x%llx) created",
10144 ifname,
10145 (long long unsigned int) p2pdev_info.wdev_id);
10146 } else {
10147 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010148 0, NULL, NULL, use_existing);
10149 if (use_existing && ifidx == -ENFILE) {
10150 added = 0;
10151 ifidx = if_nametoindex(ifname);
10152 } else if (ifidx < 0) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010153 return -1;
10154 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010155 }
10156
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010157 if (!addr) {
10158 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
10159 os_memcpy(if_addr, bss->addr, ETH_ALEN);
10160 else if (linux_get_ifhwaddr(drv->global->ioctl_sock,
10161 bss->ifname, if_addr) < 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010162 if (added)
10163 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010164 return -1;
10165 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010166 }
10167
10168#ifdef CONFIG_P2P
10169 if (!addr &&
10170 (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||
10171 type == WPA_IF_P2P_GO)) {
10172 /* Enforce unique P2P Interface Address */
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010173 u8 new_addr[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010174
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010175 if (linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010176 new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -070010177 if (added)
10178 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010179 return -1;
10180 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010181 if (nl80211_addr_in_use(drv->global, new_addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010182 wpa_printf(MSG_DEBUG, "nl80211: Allocate new address "
10183 "for P2P group interface");
10184 if (nl80211_p2p_interface_addr(drv, new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -070010185 if (added)
10186 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010187 return -1;
10188 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010189 if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010190 new_addr) < 0) {
Dmitry Shmidt71757432014-06-02 13:50:35 -070010191 if (added)
10192 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010193 return -1;
10194 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010195 }
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070010196 os_memcpy(if_addr, new_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010197 }
10198#endif /* CONFIG_P2P */
10199
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010200 if (type == WPA_IF_AP_BSS) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010201 struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
10202 if (new_bss == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010203 if (added)
10204 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010205 return -1;
10206 }
10207
10208 if (bridge &&
10209 i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
10210 wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
10211 "interface %s to a bridge %s",
10212 ifname, bridge);
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010213 if (added)
10214 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010215 os_free(new_bss);
10216 return -1;
10217 }
10218
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010219 if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
10220 {
Dmitry Shmidt71757432014-06-02 13:50:35 -070010221 if (added)
10222 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010223 os_free(new_bss);
10224 return -1;
10225 }
10226 os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010227 os_memcpy(new_bss->addr, if_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010228 new_bss->ifindex = ifidx;
10229 new_bss->drv = drv;
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010230 new_bss->next = drv->first_bss->next;
10231 new_bss->freq = drv->first_bss->freq;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080010232 new_bss->ctx = bss_ctx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010233 new_bss->added_if = added;
10234 drv->first_bss->next = new_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010235 if (drv_priv)
10236 *drv_priv = new_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010237 nl80211_init_bss(new_bss);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010238
10239 /* Subscribe management frames for this WPA_IF_AP_BSS */
10240 if (nl80211_setup_ap(new_bss))
10241 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010242 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010243
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010244 if (drv->global)
10245 drv->global->if_add_ifindex = ifidx;
10246
Dmitry Shmidt43cb5782014-06-16 16:23:22 -070010247 /*
10248 * Some virtual interfaces need to process EAPOL packets and events on
10249 * the parent interface. This is used mainly with hostapd.
10250 */
10251 if (ifidx > 0 &&
10252 (drv->hostapd ||
10253 nlmode == NL80211_IFTYPE_AP_VLAN ||
10254 nlmode == NL80211_IFTYPE_WDS ||
10255 nlmode == NL80211_IFTYPE_MONITOR))
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -070010256 add_ifidx(drv, ifidx);
10257
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010258 return 0;
10259}
10260
10261
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010262static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010263 enum wpa_driver_if_type type,
10264 const char *ifname)
10265{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010266 struct wpa_driver_nl80211_data *drv = bss->drv;
10267 int ifindex = if_nametoindex(ifname);
10268
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010269 wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d",
10270 __func__, type, ifname, ifindex, bss->added_if);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -080010271 if (ifindex > 0 && (bss->added_if || bss->ifindex != ifindex))
Dmitry Shmidt051af732013-10-22 13:52:46 -070010272 nl80211_remove_iface(drv, ifindex);
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -070010273 else if (ifindex > 0 && !bss->added_if) {
10274 struct wpa_driver_nl80211_data *drv2;
10275 dl_list_for_each(drv2, &drv->global->interfaces,
10276 struct wpa_driver_nl80211_data, list)
10277 del_ifidx(drv2, ifindex);
10278 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -070010279
Dmitry Shmidtaa532512012-09-24 10:35:31 -070010280 if (type != WPA_IF_AP_BSS)
10281 return 0;
10282
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010283 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010284 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
10285 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010286 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
10287 "interface %s from bridge %s: %s",
10288 bss->ifname, bss->brname, strerror(errno));
10289 }
10290 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010291 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010292 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
10293 "bridge %s: %s",
10294 bss->brname, strerror(errno));
10295 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010296
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010297 if (bss != drv->first_bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010298 struct i802_bss *tbss;
10299
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010300 wpa_printf(MSG_DEBUG, "nl80211: Not the first BSS - remove it");
10301 for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010302 if (tbss->next == bss) {
10303 tbss->next = bss->next;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010304 /* Unsubscribe management frames */
10305 nl80211_teardown_ap(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010306 nl80211_destroy_bss(bss);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -070010307 if (!bss->added_if)
10308 i802_set_iface_flags(bss, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010309 os_free(bss);
10310 bss = NULL;
10311 break;
10312 }
10313 }
10314 if (bss)
10315 wpa_printf(MSG_INFO, "nl80211: %s - could not find "
10316 "BSS %p in the list", __func__, bss);
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010317 } else {
10318 wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
10319 nl80211_teardown_ap(bss);
10320 if (!bss->added_if && !drv->first_bss->next)
10321 wpa_driver_nl80211_del_beacon(drv);
10322 nl80211_destroy_bss(bss);
10323 if (!bss->added_if)
10324 i802_set_iface_flags(bss, 0);
10325 if (drv->first_bss->next) {
10326 drv->first_bss = drv->first_bss->next;
10327 drv->ctx = drv->first_bss->ctx;
10328 os_free(bss);
10329 } else {
10330 wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
10331 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010332 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010333
10334 return 0;
10335}
10336
10337
10338static int cookie_handler(struct nl_msg *msg, void *arg)
10339{
10340 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10341 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10342 u64 *cookie = arg;
10343 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10344 genlmsg_attrlen(gnlh, 0), NULL);
10345 if (tb[NL80211_ATTR_COOKIE])
10346 *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
10347 return NL_SKIP;
10348}
10349
10350
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010351static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010352 unsigned int freq, unsigned int wait,
10353 const u8 *buf, size_t buf_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010354 u64 *cookie_out, int no_cck, int no_ack,
10355 int offchanok)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010356{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010357 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010358 struct nl_msg *msg;
10359 u64 cookie;
10360 int ret = -1;
10361
10362 msg = nlmsg_alloc();
10363 if (!msg)
10364 return -1;
10365
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010366 wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
Dmitry Shmidt04949592012-07-19 12:16:46 -070010367 "no_ack=%d offchanok=%d",
10368 freq, wait, no_cck, no_ack, offchanok);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -070010369 wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010370 nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010371
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010372 if (nl80211_set_iface_id(msg, bss) < 0)
10373 goto nla_put_failure;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -070010374 if (freq)
10375 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070010376 if (wait)
10377 NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -080010378 if (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
10379 drv->test_use_roc_tx))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010380 NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
10381 if (no_cck)
10382 NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
10383 if (no_ack)
10384 NLA_PUT_FLAG(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK);
10385
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010386 NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);
10387
10388 cookie = 0;
10389 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
10390 msg = NULL;
10391 if (ret) {
10392 wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070010393 "(%s) (freq=%u wait=%u)", ret, strerror(-ret),
10394 freq, wait);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010395 goto nla_put_failure;
10396 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010397 wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010398 "cookie 0x%llx", no_ack ? " (no ACK)" : "",
10399 (long long unsigned int) cookie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010400
10401 if (cookie_out)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010402 *cookie_out = no_ack ? (u64) -1 : cookie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010403
10404nla_put_failure:
10405 nlmsg_free(msg);
10406 return ret;
10407}
10408
10409
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010410static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
10411 unsigned int freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010412 unsigned int wait_time,
10413 const u8 *dst, const u8 *src,
10414 const u8 *bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010415 const u8 *data, size_t data_len,
10416 int no_cck)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010417{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010418 struct wpa_driver_nl80211_data *drv = bss->drv;
10419 int ret = -1;
10420 u8 *buf;
10421 struct ieee80211_hdr *hdr;
10422
10423 wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010424 "freq=%u MHz wait=%d ms no_cck=%d)",
10425 drv->ifindex, freq, wait_time, no_cck);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010426
10427 buf = os_zalloc(24 + data_len);
10428 if (buf == NULL)
10429 return ret;
10430 os_memcpy(buf + 24, data, data_len);
10431 hdr = (struct ieee80211_hdr *) buf;
10432 hdr->frame_control =
10433 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);
10434 os_memcpy(hdr->addr1, dst, ETH_ALEN);
10435 os_memcpy(hdr->addr2, src, ETH_ALEN);
10436 os_memcpy(hdr->addr3, bssid, ETH_ALEN);
10437
Dmitry Shmidt56052862013-10-04 10:23:25 -070010438 if (is_ap_interface(drv->nlmode) &&
10439 (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
10440 (int) freq == bss->freq || drv->device_ap_sme ||
10441 !drv->use_monitor))
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010442 ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
10443 0, freq, no_cck, 1,
10444 wait_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010445 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010446 ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010447 24 + data_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010448 &drv->send_action_cookie,
10449 no_cck, 0, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010450
10451 os_free(buf);
10452 return ret;
10453}
10454
10455
10456static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
10457{
10458 struct i802_bss *bss = priv;
10459 struct wpa_driver_nl80211_data *drv = bss->drv;
10460 struct nl_msg *msg;
10461 int ret;
10462
10463 msg = nlmsg_alloc();
10464 if (!msg)
10465 return;
10466
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -080010467 wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx",
10468 (long long unsigned int) drv->send_action_cookie);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010469 nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010470
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010471 if (nl80211_set_iface_id(msg, bss) < 0)
10472 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010473 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);
10474
10475 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
10476 msg = NULL;
10477 if (ret)
10478 wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
10479 "(%s)", ret, strerror(-ret));
10480
10481 nla_put_failure:
10482 nlmsg_free(msg);
10483}
10484
10485
10486static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
10487 unsigned int duration)
10488{
10489 struct i802_bss *bss = priv;
10490 struct wpa_driver_nl80211_data *drv = bss->drv;
10491 struct nl_msg *msg;
10492 int ret;
10493 u64 cookie;
10494
10495 msg = nlmsg_alloc();
10496 if (!msg)
10497 return -1;
10498
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010499 nl80211_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010500
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010501 if (nl80211_set_iface_id(msg, bss) < 0)
10502 goto nla_put_failure;
10503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010504 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
10505 NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);
10506
10507 cookie = 0;
10508 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010509 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010510 if (ret == 0) {
10511 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
10512 "0x%llx for freq=%u MHz duration=%u",
10513 (long long unsigned int) cookie, freq, duration);
10514 drv->remain_on_chan_cookie = cookie;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010515 drv->pending_remain_on_chan = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010516 return 0;
10517 }
10518 wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel "
10519 "(freq=%d duration=%u): %d (%s)",
10520 freq, duration, ret, strerror(-ret));
10521nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010522 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010523 return -1;
10524}
10525
10526
10527static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
10528{
10529 struct i802_bss *bss = priv;
10530 struct wpa_driver_nl80211_data *drv = bss->drv;
10531 struct nl_msg *msg;
10532 int ret;
10533
10534 if (!drv->pending_remain_on_chan) {
10535 wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel "
10536 "to cancel");
10537 return -1;
10538 }
10539
10540 wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie "
10541 "0x%llx",
10542 (long long unsigned int) drv->remain_on_chan_cookie);
10543
10544 msg = nlmsg_alloc();
10545 if (!msg)
10546 return -1;
10547
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010548 nl80211_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010549
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010550 if (nl80211_set_iface_id(msg, bss) < 0)
10551 goto nla_put_failure;
10552
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010553 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);
10554
10555 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010556 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010557 if (ret == 0)
10558 return 0;
10559 wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
10560 "%d (%s)", ret, strerror(-ret));
10561nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010562 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010563 return -1;
10564}
10565
10566
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010567static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010568{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010569 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070010570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010571 if (!report) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010572 if (bss->nl_preq && drv->device_ap_sme &&
Dmitry Shmidt03658832014-08-13 11:03:49 -070010573 is_ap_interface(drv->nlmode) && !bss->in_deinit &&
10574 !bss->static_ap) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010575 /*
10576 * Do not disable Probe Request reporting that was
10577 * enabled in nl80211_setup_ap().
10578 */
10579 wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of "
10580 "Probe Request reporting nl_preq=%p while "
10581 "in AP mode", bss->nl_preq);
10582 } else if (bss->nl_preq) {
10583 wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
10584 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010585 nl80211_destroy_eloop_handle(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010586 }
10587 return 0;
10588 }
10589
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010590 if (bss->nl_preq) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010591 wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010592 "already on! nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010593 return 0;
10594 }
10595
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010596 bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq");
10597 if (bss->nl_preq == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010598 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010599 wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request "
10600 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010601
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010602 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010603 (WLAN_FC_TYPE_MGMT << 2) |
10604 (WLAN_FC_STYPE_PROBE_REQ << 4),
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010605 NULL, 0) < 0)
10606 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -070010607
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010608 nl80211_register_eloop_read(&bss->nl_preq,
10609 wpa_driver_nl80211_event_receive,
10610 bss->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010611
10612 return 0;
10613
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010614 out_err:
10615 nl_destroy_handles(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010616 return -1;
10617}
10618
10619
10620static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
10621 int ifindex, int disabled)
10622{
10623 struct nl_msg *msg;
10624 struct nlattr *bands, *band;
10625 int ret;
10626
10627 msg = nlmsg_alloc();
10628 if (!msg)
10629 return -1;
10630
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010631 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_TX_BITRATE_MASK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010632 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
10633
10634 bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
10635 if (!bands)
10636 goto nla_put_failure;
10637
10638 /*
10639 * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything
10640 * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS
10641 * rates. All 5 GHz rates are left enabled.
10642 */
10643 band = nla_nest_start(msg, NL80211_BAND_2GHZ);
10644 if (!band)
10645 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010646 if (disabled) {
10647 NLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,
10648 "\x0c\x12\x18\x24\x30\x48\x60\x6c");
10649 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010650 nla_nest_end(msg, band);
10651
10652 nla_nest_end(msg, bands);
10653
10654 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
10655 msg = NULL;
10656 if (ret) {
10657 wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
10658 "(%s)", ret, strerror(-ret));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010659 } else
10660 drv->disabled_11b_rates = disabled;
10661
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010662 return ret;
10663
10664nla_put_failure:
10665 nlmsg_free(msg);
10666 return -1;
10667}
10668
10669
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010670static int wpa_driver_nl80211_deinit_ap(void *priv)
10671{
10672 struct i802_bss *bss = priv;
10673 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010674 if (!is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010675 return -1;
10676 wpa_driver_nl80211_del_beacon(drv);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070010677
10678 /*
10679 * If the P2P GO interface was dynamically added, then it is
10680 * possible that the interface change to station is not possible.
10681 */
10682 if (drv->nlmode == NL80211_IFTYPE_P2P_GO && bss->if_dynamic)
10683 return 0;
10684
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010685 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010686}
10687
10688
Dmitry Shmidtea69e842013-05-13 14:52:28 -070010689static int wpa_driver_nl80211_stop_ap(void *priv)
10690{
10691 struct i802_bss *bss = priv;
10692 struct wpa_driver_nl80211_data *drv = bss->drv;
10693 if (!is_ap_interface(drv->nlmode))
10694 return -1;
10695 wpa_driver_nl80211_del_beacon(drv);
10696 bss->beacon_set = 0;
10697 return 0;
10698}
10699
10700
Dmitry Shmidt04949592012-07-19 12:16:46 -070010701static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
10702{
10703 struct i802_bss *bss = priv;
10704 struct wpa_driver_nl80211_data *drv = bss->drv;
10705 if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)
10706 return -1;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070010707
10708 /*
10709 * If the P2P Client interface was dynamically added, then it is
10710 * possible that the interface change to station is not possible.
10711 */
10712 if (bss->if_dynamic)
10713 return 0;
10714
Dmitry Shmidt04949592012-07-19 12:16:46 -070010715 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
10716}
10717
10718
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010719static void wpa_driver_nl80211_resume(void *priv)
10720{
10721 struct i802_bss *bss = priv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010722
10723 if (i802_set_iface_flags(bss, 1))
10724 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010725}
10726
10727
10728static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
10729 const u8 *ies, size_t ies_len)
10730{
10731 struct i802_bss *bss = priv;
10732 struct wpa_driver_nl80211_data *drv = bss->drv;
10733 int ret;
10734 u8 *data, *pos;
10735 size_t data_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010736 const u8 *own_addr = bss->addr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010737
10738 if (action != 1) {
10739 wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action "
10740 "action %d", action);
10741 return -1;
10742 }
10743
10744 /*
10745 * Action frame payload:
10746 * Category[1] = 6 (Fast BSS Transition)
10747 * Action[1] = 1 (Fast BSS Transition Request)
10748 * STA Address
10749 * Target AP Address
10750 * FT IEs
10751 */
10752
10753 data_len = 2 + 2 * ETH_ALEN + ies_len;
10754 data = os_malloc(data_len);
10755 if (data == NULL)
10756 return -1;
10757 pos = data;
10758 *pos++ = 0x06; /* FT Action category */
10759 *pos++ = action;
10760 os_memcpy(pos, own_addr, ETH_ALEN);
10761 pos += ETH_ALEN;
10762 os_memcpy(pos, target_ap, ETH_ALEN);
10763 pos += ETH_ALEN;
10764 os_memcpy(pos, ies, ies_len);
10765
10766 ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0,
10767 drv->bssid, own_addr, drv->bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010768 data, data_len, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010769 os_free(data);
10770
10771 return ret;
10772}
10773
10774
10775static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
10776{
10777 struct i802_bss *bss = priv;
10778 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010779 struct nl_msg *msg;
10780 struct nlattr *cqm;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010781 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010782
10783 wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
10784 "hysteresis=%d", threshold, hysteresis);
10785
10786 msg = nlmsg_alloc();
10787 if (!msg)
10788 return -1;
10789
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010790 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_CQM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010791
10792 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10793
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010794 cqm = nla_nest_start(msg, NL80211_ATTR_CQM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010795 if (cqm == NULL)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010796 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010797
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010798 NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
10799 NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);
10800 nla_nest_end(msg, cqm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010801
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010802 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010803 msg = NULL;
10804
10805nla_put_failure:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010806 nlmsg_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010807 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010808}
10809
10810
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010811static int get_channel_width(struct nl_msg *msg, void *arg)
10812{
10813 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10814 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10815 struct wpa_signal_info *sig_change = arg;
10816
10817 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10818 genlmsg_attrlen(gnlh, 0), NULL);
10819
10820 sig_change->center_frq1 = -1;
10821 sig_change->center_frq2 = -1;
10822 sig_change->chanwidth = CHAN_WIDTH_UNKNOWN;
10823
10824 if (tb[NL80211_ATTR_CHANNEL_WIDTH]) {
10825 sig_change->chanwidth = convert2width(
10826 nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
10827 if (tb[NL80211_ATTR_CENTER_FREQ1])
10828 sig_change->center_frq1 =
10829 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
10830 if (tb[NL80211_ATTR_CENTER_FREQ2])
10831 sig_change->center_frq2 =
10832 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
10833 }
10834
10835 return NL_SKIP;
10836}
10837
10838
10839static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
10840 struct wpa_signal_info *sig)
10841{
10842 struct nl_msg *msg;
10843
10844 msg = nlmsg_alloc();
10845 if (!msg)
10846 return -ENOMEM;
10847
10848 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_INTERFACE);
10849 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
10850
10851 return send_and_recv_msgs(drv, msg, get_channel_width, sig);
10852
10853nla_put_failure:
10854 nlmsg_free(msg);
10855 return -ENOBUFS;
10856}
10857
10858
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010859static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
10860{
10861 struct i802_bss *bss = priv;
10862 struct wpa_driver_nl80211_data *drv = bss->drv;
10863 int res;
10864
10865 os_memset(si, 0, sizeof(*si));
10866 res = nl80211_get_link_signal(drv, si);
10867 if (res != 0)
10868 return res;
10869
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010870 res = nl80211_get_channel_width(drv, si);
10871 if (res != 0)
10872 return res;
10873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010874 return nl80211_get_link_noise(drv, si);
10875}
10876
10877
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010878static int wpa_driver_nl80211_shared_freq(void *priv)
10879{
10880 struct i802_bss *bss = priv;
10881 struct wpa_driver_nl80211_data *drv = bss->drv;
10882 struct wpa_driver_nl80211_data *driver;
10883 int freq = 0;
10884
10885 /*
10886 * If the same PHY is in connected state with some other interface,
10887 * then retrieve the assoc freq.
10888 */
10889 wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s",
10890 drv->phyname);
10891
10892 dl_list_for_each(driver, &drv->global->interfaces,
10893 struct wpa_driver_nl80211_data, list) {
10894 if (drv == driver ||
10895 os_strcmp(drv->phyname, driver->phyname) != 0 ||
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010896 !driver->associated)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010897 continue;
10898
10899 wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
10900 MACSTR,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010901 driver->phyname, driver->first_bss->ifname,
10902 MAC2STR(driver->first_bss->addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -070010903 if (is_ap_interface(driver->nlmode))
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010904 freq = driver->first_bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010905 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010906 freq = nl80211_get_assoc_freq(driver);
10907 wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
10908 drv->phyname, freq);
10909 }
10910
10911 if (!freq)
10912 wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
10913 "PHY (%s) in associated state", drv->phyname);
10914
10915 return freq;
10916}
10917
10918
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010919static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
10920 int encrypt)
10921{
10922 struct i802_bss *bss = priv;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010923 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
10924 0, 0, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010925}
10926
10927
10928static int nl80211_set_param(void *priv, const char *param)
10929{
10930 wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
10931 if (param == NULL)
10932 return 0;
10933
10934#ifdef CONFIG_P2P
10935 if (os_strstr(param, "use_p2p_group_interface=1")) {
10936 struct i802_bss *bss = priv;
10937 struct wpa_driver_nl80211_data *drv = bss->drv;
10938
10939 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
10940 "interface");
10941 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
10942 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
10943 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010944
10945 if (os_strstr(param, "p2p_device=1")) {
10946 struct i802_bss *bss = priv;
10947 struct wpa_driver_nl80211_data *drv = bss->drv;
10948 drv->allow_p2p_device = 1;
10949 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010950#endif /* CONFIG_P2P */
10951
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080010952 if (os_strstr(param, "use_monitor=1")) {
10953 struct i802_bss *bss = priv;
10954 struct wpa_driver_nl80211_data *drv = bss->drv;
10955 drv->use_monitor = 1;
10956 }
10957
10958 if (os_strstr(param, "force_connect_cmd=1")) {
10959 struct i802_bss *bss = priv;
10960 struct wpa_driver_nl80211_data *drv = bss->drv;
10961 drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
10962 }
10963
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -080010964 if (os_strstr(param, "no_offchannel_tx=1")) {
10965 struct i802_bss *bss = priv;
10966 struct wpa_driver_nl80211_data *drv = bss->drv;
10967 drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
10968 drv->test_use_roc_tx = 1;
10969 }
10970
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010971 return 0;
10972}
10973
10974
10975static void * nl80211_global_init(void)
10976{
10977 struct nl80211_global *global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010978 struct netlink_config *cfg;
10979
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010980 global = os_zalloc(sizeof(*global));
10981 if (global == NULL)
10982 return NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010983 global->ioctl_sock = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010984 dl_list_init(&global->interfaces);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010985 global->if_add_ifindex = -1;
10986
10987 cfg = os_zalloc(sizeof(*cfg));
10988 if (cfg == NULL)
10989 goto err;
10990
10991 cfg->ctx = global;
10992 cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
10993 cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
10994 global->netlink = netlink_init(cfg);
10995 if (global->netlink == NULL) {
10996 os_free(cfg);
10997 goto err;
10998 }
10999
11000 if (wpa_driver_nl80211_init_nl_global(global) < 0)
11001 goto err;
11002
11003 global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
11004 if (global->ioctl_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070011005 wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",
11006 strerror(errno));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011007 goto err;
11008 }
11009
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011010 return global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011011
11012err:
11013 nl80211_global_deinit(global);
11014 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011015}
11016
11017
11018static void nl80211_global_deinit(void *priv)
11019{
11020 struct nl80211_global *global = priv;
11021 if (global == NULL)
11022 return;
11023 if (!dl_list_empty(&global->interfaces)) {
11024 wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at "
11025 "nl80211_global_deinit",
11026 dl_list_len(&global->interfaces));
11027 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011028
11029 if (global->netlink)
11030 netlink_deinit(global->netlink);
11031
11032 nl_destroy_handles(&global->nl);
11033
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070011034 if (global->nl_event)
11035 nl80211_destroy_eloop_handle(&global->nl_event);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011036
11037 nl_cb_put(global->nl_cb);
11038
11039 if (global->ioctl_sock >= 0)
11040 close(global->ioctl_sock);
11041
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011042 os_free(global);
11043}
11044
11045
11046static const char * nl80211_get_radio_name(void *priv)
11047{
11048 struct i802_bss *bss = priv;
11049 struct wpa_driver_nl80211_data *drv = bss->drv;
11050 return drv->phyname;
11051}
11052
11053
Jouni Malinen75ecf522011-06-27 15:19:46 -070011054static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,
11055 const u8 *pmkid)
11056{
11057 struct nl_msg *msg;
11058
11059 msg = nlmsg_alloc();
11060 if (!msg)
11061 return -ENOMEM;
11062
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011063 nl80211_cmd(bss->drv, msg, 0, cmd);
Jouni Malinen75ecf522011-06-27 15:19:46 -070011064
11065 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
11066 if (pmkid)
11067 NLA_PUT(msg, NL80211_ATTR_PMKID, 16, pmkid);
11068 if (bssid)
11069 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
11070
11071 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
11072 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011073 nlmsg_free(msg);
Jouni Malinen75ecf522011-06-27 15:19:46 -070011074 return -ENOBUFS;
11075}
11076
11077
11078static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
11079{
11080 struct i802_bss *bss = priv;
11081 wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR, MAC2STR(bssid));
11082 return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);
11083}
11084
11085
11086static int nl80211_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
11087{
11088 struct i802_bss *bss = priv;
11089 wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR,
11090 MAC2STR(bssid));
11091 return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);
11092}
11093
11094
11095static int nl80211_flush_pmkid(void *priv)
11096{
11097 struct i802_bss *bss = priv;
11098 wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs");
11099 return nl80211_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);
11100}
11101
11102
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070011103static void clean_survey_results(struct survey_results *survey_results)
11104{
11105 struct freq_survey *survey, *tmp;
11106
11107 if (dl_list_empty(&survey_results->survey_list))
11108 return;
11109
11110 dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
11111 struct freq_survey, list) {
11112 dl_list_del(&survey->list);
11113 os_free(survey);
11114 }
11115}
11116
11117
11118static void add_survey(struct nlattr **sinfo, u32 ifidx,
11119 struct dl_list *survey_list)
11120{
11121 struct freq_survey *survey;
11122
11123 survey = os_zalloc(sizeof(struct freq_survey));
11124 if (!survey)
11125 return;
11126
11127 survey->ifidx = ifidx;
11128 survey->freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
11129 survey->filled = 0;
11130
11131 if (sinfo[NL80211_SURVEY_INFO_NOISE]) {
11132 survey->nf = (int8_t)
11133 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
11134 survey->filled |= SURVEY_HAS_NF;
11135 }
11136
11137 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]) {
11138 survey->channel_time =
11139 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]);
11140 survey->filled |= SURVEY_HAS_CHAN_TIME;
11141 }
11142
11143 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]) {
11144 survey->channel_time_busy =
11145 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]);
11146 survey->filled |= SURVEY_HAS_CHAN_TIME_BUSY;
11147 }
11148
11149 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]) {
11150 survey->channel_time_rx =
11151 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]);
11152 survey->filled |= SURVEY_HAS_CHAN_TIME_RX;
11153 }
11154
11155 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]) {
11156 survey->channel_time_tx =
11157 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]);
11158 survey->filled |= SURVEY_HAS_CHAN_TIME_TX;
11159 }
11160
11161 wpa_printf(MSG_DEBUG, "nl80211: Freq survey dump event (freq=%d MHz noise=%d channel_time=%ld busy_time=%ld tx_time=%ld rx_time=%ld filled=%04x)",
11162 survey->freq,
11163 survey->nf,
11164 (unsigned long int) survey->channel_time,
11165 (unsigned long int) survey->channel_time_busy,
11166 (unsigned long int) survey->channel_time_tx,
11167 (unsigned long int) survey->channel_time_rx,
11168 survey->filled);
11169
11170 dl_list_add_tail(survey_list, &survey->list);
11171}
11172
11173
11174static int check_survey_ok(struct nlattr **sinfo, u32 surveyed_freq,
11175 unsigned int freq_filter)
11176{
11177 if (!freq_filter)
11178 return 1;
11179
11180 return freq_filter == surveyed_freq;
11181}
11182
11183
11184static int survey_handler(struct nl_msg *msg, void *arg)
11185{
11186 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11187 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11188 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
11189 struct survey_results *survey_results;
11190 u32 surveyed_freq = 0;
11191 u32 ifidx;
11192
11193 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
11194 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
11195 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
11196 };
11197
11198 survey_results = (struct survey_results *) arg;
11199
11200 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
11201 genlmsg_attrlen(gnlh, 0), NULL);
11202
Dmitry Shmidt97672262014-02-03 13:02:54 -080011203 if (!tb[NL80211_ATTR_IFINDEX])
11204 return NL_SKIP;
11205
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070011206 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
11207
11208 if (!tb[NL80211_ATTR_SURVEY_INFO])
11209 return NL_SKIP;
11210
11211 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
11212 tb[NL80211_ATTR_SURVEY_INFO],
11213 survey_policy))
11214 return NL_SKIP;
11215
11216 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) {
11217 wpa_printf(MSG_ERROR, "nl80211: Invalid survey data");
11218 return NL_SKIP;
11219 }
11220
11221 surveyed_freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
11222
11223 if (!check_survey_ok(sinfo, surveyed_freq,
11224 survey_results->freq_filter))
11225 return NL_SKIP;
11226
11227 if (survey_results->freq_filter &&
11228 survey_results->freq_filter != surveyed_freq) {
11229 wpa_printf(MSG_EXCESSIVE, "nl80211: Ignoring survey data for freq %d MHz",
11230 surveyed_freq);
11231 return NL_SKIP;
11232 }
11233
11234 add_survey(sinfo, ifidx, &survey_results->survey_list);
11235
11236 return NL_SKIP;
11237}
11238
11239
11240static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
11241{
11242 struct i802_bss *bss = priv;
11243 struct wpa_driver_nl80211_data *drv = bss->drv;
11244 struct nl_msg *msg;
11245 int err = -ENOBUFS;
11246 union wpa_event_data data;
11247 struct survey_results *survey_results;
11248
11249 os_memset(&data, 0, sizeof(data));
11250 survey_results = &data.survey_results;
11251
11252 dl_list_init(&survey_results->survey_list);
11253
11254 msg = nlmsg_alloc();
11255 if (!msg)
11256 goto nla_put_failure;
11257
11258 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
11259
11260 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11261
11262 if (freq)
11263 data.survey_results.freq_filter = freq;
11264
11265 do {
11266 wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data");
11267 err = send_and_recv_msgs(drv, msg, survey_handler,
11268 survey_results);
11269 } while (err > 0);
11270
11271 if (err) {
11272 wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
11273 goto out_clean;
11274 }
11275
11276 wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data);
11277
11278out_clean:
11279 clean_survey_results(survey_results);
11280nla_put_failure:
11281 return err;
11282}
11283
11284
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011285static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
11286 const u8 *replay_ctr)
11287{
11288 struct i802_bss *bss = priv;
11289 struct wpa_driver_nl80211_data *drv = bss->drv;
11290 struct nlattr *replay_nested;
11291 struct nl_msg *msg;
11292
11293 msg = nlmsg_alloc();
11294 if (!msg)
11295 return;
11296
11297 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
11298
11299 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
11300
11301 replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
11302 if (!replay_nested)
11303 goto nla_put_failure;
11304
11305 NLA_PUT(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek);
11306 NLA_PUT(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck);
11307 NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
11308 replay_ctr);
11309
11310 nla_nest_end(msg, replay_nested);
11311
11312 send_and_recv_msgs(drv, msg, NULL, NULL);
11313 return;
11314 nla_put_failure:
11315 nlmsg_free(msg);
11316}
11317
11318
11319static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
11320 const u8 *addr, int qos)
11321{
11322 /* send data frame to poll STA and check whether
11323 * this frame is ACKed */
11324 struct {
11325 struct ieee80211_hdr hdr;
11326 u16 qos_ctl;
11327 } STRUCT_PACKED nulldata;
11328 size_t size;
11329
11330 /* Send data frame to poll STA and check whether this frame is ACKed */
11331
11332 os_memset(&nulldata, 0, sizeof(nulldata));
11333
11334 if (qos) {
11335 nulldata.hdr.frame_control =
11336 IEEE80211_FC(WLAN_FC_TYPE_DATA,
11337 WLAN_FC_STYPE_QOS_NULL);
11338 size = sizeof(nulldata);
11339 } else {
11340 nulldata.hdr.frame_control =
11341 IEEE80211_FC(WLAN_FC_TYPE_DATA,
11342 WLAN_FC_STYPE_NULLFUNC);
11343 size = sizeof(struct ieee80211_hdr);
11344 }
11345
11346 nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
11347 os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
11348 os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
11349 os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
11350
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011351 if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
11352 0, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011353 wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
11354 "send poll frame");
11355}
11356
11357static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
11358 int qos)
11359{
11360 struct i802_bss *bss = priv;
11361 struct wpa_driver_nl80211_data *drv = bss->drv;
11362 struct nl_msg *msg;
11363
11364 if (!drv->poll_command_supported) {
11365 nl80211_send_null_frame(bss, own_addr, addr, qos);
11366 return;
11367 }
11368
11369 msg = nlmsg_alloc();
11370 if (!msg)
11371 return;
11372
11373 nl80211_cmd(drv, msg, 0, NL80211_CMD_PROBE_CLIENT);
11374
11375 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
11376 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
11377
11378 send_and_recv_msgs(drv, msg, NULL, NULL);
11379 return;
11380 nla_put_failure:
11381 nlmsg_free(msg);
11382}
11383
11384
11385static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
11386{
11387 struct nl_msg *msg;
11388
11389 msg = nlmsg_alloc();
11390 if (!msg)
11391 return -ENOMEM;
11392
11393 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_SET_POWER_SAVE);
11394 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
11395 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE,
11396 enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);
11397 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
11398nla_put_failure:
11399 nlmsg_free(msg);
11400 return -ENOBUFS;
11401}
11402
11403
11404static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,
11405 int ctwindow)
11406{
11407 struct i802_bss *bss = priv;
11408
11409 wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d "
11410 "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow);
11411
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080011412 if (opp_ps != -1 || ctwindow != -1) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080011413#ifdef ANDROID_P2P
11414 wpa_driver_set_p2p_ps(priv, legacy_ps, opp_ps, ctwindow);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080011415#else /* ANDROID_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011416 return -1; /* Not yet supported */
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080011417#endif /* ANDROID_P2P */
11418 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011419
11420 if (legacy_ps == -1)
11421 return 0;
11422 if (legacy_ps != 0 && legacy_ps != 1)
11423 return -1; /* Not yet supported */
11424
11425 return nl80211_set_power_save(bss, legacy_ps);
11426}
11427
11428
Dmitry Shmidt051af732013-10-22 13:52:46 -070011429static int nl80211_start_radar_detection(void *priv,
11430 struct hostapd_freq_params *freq)
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011431{
11432 struct i802_bss *bss = priv;
11433 struct wpa_driver_nl80211_data *drv = bss->drv;
11434 struct nl_msg *msg;
11435 int ret;
11436
Dmitry Shmidt051af732013-10-22 13:52:46 -070011437 wpa_printf(MSG_DEBUG, "nl80211: Start radar detection (CAC) %d MHz (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
11438 freq->freq, freq->ht_enabled, freq->vht_enabled,
11439 freq->bandwidth, freq->center_freq1, freq->center_freq2);
11440
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011441 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
11442 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar "
11443 "detection");
11444 return -1;
11445 }
11446
11447 msg = nlmsg_alloc();
11448 if (!msg)
11449 return -1;
11450
11451 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_RADAR_DETECT);
11452 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
Dmitry Shmidt051af732013-10-22 13:52:46 -070011453 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq);
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011454
Dmitry Shmidt051af732013-10-22 13:52:46 -070011455 if (freq->vht_enabled) {
11456 switch (freq->bandwidth) {
11457 case 20:
11458 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11459 NL80211_CHAN_WIDTH_20);
11460 break;
11461 case 40:
11462 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11463 NL80211_CHAN_WIDTH_40);
11464 break;
11465 case 80:
11466 if (freq->center_freq2)
11467 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11468 NL80211_CHAN_WIDTH_80P80);
11469 else
11470 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11471 NL80211_CHAN_WIDTH_80);
11472 break;
11473 case 160:
11474 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11475 NL80211_CHAN_WIDTH_160);
11476 break;
11477 default:
11478 return -1;
11479 }
11480 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1);
11481 if (freq->center_freq2)
11482 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2,
11483 freq->center_freq2);
11484 } else if (freq->ht_enabled) {
11485 switch (freq->sec_channel_offset) {
11486 case -1:
11487 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
11488 NL80211_CHAN_HT40MINUS);
11489 break;
11490 case 1:
11491 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
11492 NL80211_CHAN_HT40PLUS);
11493 break;
11494 default:
11495 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
11496 NL80211_CHAN_HT20);
11497 break;
11498 }
11499 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011500
11501 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
11502 if (ret == 0)
11503 return 0;
11504 wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
11505 "%d (%s)", ret, strerror(-ret));
11506nla_put_failure:
11507 return -1;
11508}
11509
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011510#ifdef CONFIG_TDLS
11511
11512static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
11513 u8 dialog_token, u16 status_code,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -070011514 u32 peer_capab, const u8 *buf, size_t len)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011515{
11516 struct i802_bss *bss = priv;
11517 struct wpa_driver_nl80211_data *drv = bss->drv;
11518 struct nl_msg *msg;
11519
11520 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
11521 return -EOPNOTSUPP;
11522
11523 if (!dst)
11524 return -EINVAL;
11525
11526 msg = nlmsg_alloc();
11527 if (!msg)
11528 return -ENOMEM;
11529
11530 nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_MGMT);
11531 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11532 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
11533 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code);
11534 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token);
11535 NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code);
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -070011536 if (peer_capab) {
11537 /*
11538 * The internal enum tdls_peer_capability definition is
11539 * currently identical with the nl80211 enum
11540 * nl80211_tdls_peer_capability, so no conversion is needed
11541 * here.
11542 */
11543 NLA_PUT_U32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY, peer_capab);
11544 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011545 NLA_PUT(msg, NL80211_ATTR_IE, len, buf);
11546
11547 return send_and_recv_msgs(drv, msg, NULL, NULL);
11548
11549nla_put_failure:
11550 nlmsg_free(msg);
11551 return -ENOBUFS;
11552}
11553
11554
11555static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
11556{
11557 struct i802_bss *bss = priv;
11558 struct wpa_driver_nl80211_data *drv = bss->drv;
11559 struct nl_msg *msg;
11560 enum nl80211_tdls_operation nl80211_oper;
11561
11562 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
11563 return -EOPNOTSUPP;
11564
11565 switch (oper) {
11566 case TDLS_DISCOVERY_REQ:
11567 nl80211_oper = NL80211_TDLS_DISCOVERY_REQ;
11568 break;
11569 case TDLS_SETUP:
11570 nl80211_oper = NL80211_TDLS_SETUP;
11571 break;
11572 case TDLS_TEARDOWN:
11573 nl80211_oper = NL80211_TDLS_TEARDOWN;
11574 break;
11575 case TDLS_ENABLE_LINK:
11576 nl80211_oper = NL80211_TDLS_ENABLE_LINK;
11577 break;
11578 case TDLS_DISABLE_LINK:
11579 nl80211_oper = NL80211_TDLS_DISABLE_LINK;
11580 break;
11581 case TDLS_ENABLE:
11582 return 0;
11583 case TDLS_DISABLE:
11584 return 0;
11585 default:
11586 return -EINVAL;
11587 }
11588
11589 msg = nlmsg_alloc();
11590 if (!msg)
11591 return -ENOMEM;
11592
11593 nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_OPER);
11594 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper);
11595 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11596 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer);
11597
11598 return send_and_recv_msgs(drv, msg, NULL, NULL);
11599
11600nla_put_failure:
11601 nlmsg_free(msg);
11602 return -ENOBUFS;
11603}
11604
11605#endif /* CONFIG TDLS */
11606
11607
11608#ifdef ANDROID
11609
11610typedef struct android_wifi_priv_cmd {
11611 char *buf;
11612 int used_len;
11613 int total_len;
11614} android_wifi_priv_cmd;
11615
11616static int drv_errors = 0;
11617
11618static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
11619{
11620 drv_errors++;
11621 if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
11622 drv_errors = 0;
11623 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
11624 }
11625}
11626
11627
11628static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
11629{
11630 struct wpa_driver_nl80211_data *drv = bss->drv;
11631 struct ifreq ifr;
11632 android_wifi_priv_cmd priv_cmd;
11633 char buf[MAX_DRV_CMD_SIZE];
11634 int ret;
11635
11636 os_memset(&ifr, 0, sizeof(ifr));
11637 os_memset(&priv_cmd, 0, sizeof(priv_cmd));
11638 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
11639
11640 os_memset(buf, 0, sizeof(buf));
11641 os_strlcpy(buf, cmd, sizeof(buf));
11642
11643 priv_cmd.buf = buf;
11644 priv_cmd.used_len = sizeof(buf);
11645 priv_cmd.total_len = sizeof(buf);
11646 ifr.ifr_data = &priv_cmd;
11647
11648 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
11649 if (ret < 0) {
11650 wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
11651 __func__);
11652 wpa_driver_send_hang_msg(drv);
11653 return ret;
11654 }
11655
11656 drv_errors = 0;
11657 return 0;
11658}
11659
11660
11661static int android_pno_start(struct i802_bss *bss,
11662 struct wpa_driver_scan_params *params)
11663{
11664 struct wpa_driver_nl80211_data *drv = bss->drv;
11665 struct ifreq ifr;
11666 android_wifi_priv_cmd priv_cmd;
11667 int ret = 0, i = 0, bp;
11668 char buf[WEXT_PNO_MAX_COMMAND_SIZE];
11669
11670 bp = WEXT_PNOSETUP_HEADER_SIZE;
11671 os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
11672 buf[bp++] = WEXT_PNO_TLV_PREFIX;
11673 buf[bp++] = WEXT_PNO_TLV_VERSION;
11674 buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
11675 buf[bp++] = WEXT_PNO_TLV_RESERVED;
11676
11677 while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
11678 /* Check that there is enough space needed for 1 more SSID, the
11679 * other sections and null termination */
11680 if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
11681 WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
11682 break;
11683 wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
11684 params->ssids[i].ssid,
11685 params->ssids[i].ssid_len);
11686 buf[bp++] = WEXT_PNO_SSID_SECTION;
11687 buf[bp++] = params->ssids[i].ssid_len;
11688 os_memcpy(&buf[bp], params->ssids[i].ssid,
11689 params->ssids[i].ssid_len);
11690 bp += params->ssids[i].ssid_len;
11691 i++;
11692 }
11693
11694 buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
11695 os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
11696 WEXT_PNO_SCAN_INTERVAL);
11697 bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
11698
11699 buf[bp++] = WEXT_PNO_REPEAT_SECTION;
11700 os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
11701 WEXT_PNO_REPEAT);
11702 bp += WEXT_PNO_REPEAT_LENGTH;
11703
11704 buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
11705 os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
11706 WEXT_PNO_MAX_REPEAT);
11707 bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
11708
11709 memset(&ifr, 0, sizeof(ifr));
11710 memset(&priv_cmd, 0, sizeof(priv_cmd));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070011711 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011712
11713 priv_cmd.buf = buf;
11714 priv_cmd.used_len = bp;
11715 priv_cmd.total_len = bp;
11716 ifr.ifr_data = &priv_cmd;
11717
11718 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
11719
11720 if (ret < 0) {
11721 wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
11722 ret);
11723 wpa_driver_send_hang_msg(drv);
11724 return ret;
11725 }
11726
11727 drv_errors = 0;
11728
11729 return android_priv_cmd(bss, "PNOFORCE 1");
11730}
11731
11732
11733static int android_pno_stop(struct i802_bss *bss)
11734{
11735 return android_priv_cmd(bss, "PNOFORCE 0");
11736}
11737
11738#endif /* ANDROID */
11739
11740
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011741static int driver_nl80211_set_key(const char *ifname, void *priv,
11742 enum wpa_alg alg, const u8 *addr,
11743 int key_idx, int set_tx,
11744 const u8 *seq, size_t seq_len,
11745 const u8 *key, size_t key_len)
11746{
11747 struct i802_bss *bss = priv;
11748 return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx,
11749 set_tx, seq, seq_len, key, key_len);
11750}
11751
11752
11753static int driver_nl80211_scan2(void *priv,
11754 struct wpa_driver_scan_params *params)
11755{
11756 struct i802_bss *bss = priv;
11757 return wpa_driver_nl80211_scan(bss, params);
11758}
11759
11760
11761static int driver_nl80211_deauthenticate(void *priv, const u8 *addr,
11762 int reason_code)
11763{
11764 struct i802_bss *bss = priv;
11765 return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code);
11766}
11767
11768
11769static int driver_nl80211_authenticate(void *priv,
11770 struct wpa_driver_auth_params *params)
11771{
11772 struct i802_bss *bss = priv;
11773 return wpa_driver_nl80211_authenticate(bss, params);
11774}
11775
11776
11777static void driver_nl80211_deinit(void *priv)
11778{
11779 struct i802_bss *bss = priv;
11780 wpa_driver_nl80211_deinit(bss);
11781}
11782
11783
11784static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
11785 const char *ifname)
11786{
11787 struct i802_bss *bss = priv;
11788 return wpa_driver_nl80211_if_remove(bss, type, ifname);
11789}
11790
11791
11792static int driver_nl80211_send_mlme(void *priv, const u8 *data,
11793 size_t data_len, int noack)
11794{
11795 struct i802_bss *bss = priv;
11796 return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
11797 0, 0, 0, 0);
11798}
11799
11800
11801static int driver_nl80211_sta_remove(void *priv, const u8 *addr)
11802{
11803 struct i802_bss *bss = priv;
11804 return wpa_driver_nl80211_sta_remove(bss, addr);
11805}
11806
11807
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011808static int driver_nl80211_set_sta_vlan(void *priv, const u8 *addr,
11809 const char *ifname, int vlan_id)
11810{
11811 struct i802_bss *bss = priv;
11812 return i802_set_sta_vlan(bss, addr, ifname, vlan_id);
11813}
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011814
11815
11816static int driver_nl80211_read_sta_data(void *priv,
11817 struct hostap_sta_driver_data *data,
11818 const u8 *addr)
11819{
11820 struct i802_bss *bss = priv;
11821 return i802_read_sta_data(bss, data, addr);
11822}
11823
11824
11825static int driver_nl80211_send_action(void *priv, unsigned int freq,
11826 unsigned int wait_time,
11827 const u8 *dst, const u8 *src,
11828 const u8 *bssid,
11829 const u8 *data, size_t data_len,
11830 int no_cck)
11831{
11832 struct i802_bss *bss = priv;
11833 return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src,
11834 bssid, data, data_len, no_cck);
11835}
11836
11837
11838static int driver_nl80211_probe_req_report(void *priv, int report)
11839{
11840 struct i802_bss *bss = priv;
11841 return wpa_driver_nl80211_probe_req_report(bss, report);
11842}
11843
11844
Dmitry Shmidt700a1372013-03-15 14:14:44 -070011845static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
11846 const u8 *ies, size_t ies_len)
11847{
11848 int ret;
11849 struct nl_msg *msg;
11850 struct i802_bss *bss = priv;
11851 struct wpa_driver_nl80211_data *drv = bss->drv;
11852 u16 mdid = WPA_GET_LE16(md);
11853
11854 msg = nlmsg_alloc();
11855 if (!msg)
11856 return -ENOMEM;
11857
11858 wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
11859 nl80211_cmd(drv, msg, 0, NL80211_CMD_UPDATE_FT_IES);
11860 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11861 NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies);
11862 NLA_PUT_U16(msg, NL80211_ATTR_MDID, mdid);
11863
11864 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
11865 if (ret) {
11866 wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
11867 "err=%d (%s)", ret, strerror(-ret));
11868 }
11869
11870 return ret;
11871
11872nla_put_failure:
11873 nlmsg_free(msg);
11874 return -ENOBUFS;
11875}
11876
11877
Dmitry Shmidt34af3062013-07-11 10:46:32 -070011878const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
11879{
11880 struct i802_bss *bss = priv;
11881 struct wpa_driver_nl80211_data *drv = bss->drv;
11882
11883 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE)
11884 return NULL;
11885
11886 return bss->addr;
11887}
11888
11889
Dmitry Shmidt56052862013-10-04 10:23:25 -070011890static const char * scan_state_str(enum scan_states scan_state)
11891{
11892 switch (scan_state) {
11893 case NO_SCAN:
11894 return "NO_SCAN";
11895 case SCAN_REQUESTED:
11896 return "SCAN_REQUESTED";
11897 case SCAN_STARTED:
11898 return "SCAN_STARTED";
11899 case SCAN_COMPLETED:
11900 return "SCAN_COMPLETED";
11901 case SCAN_ABORTED:
11902 return "SCAN_ABORTED";
11903 case SCHED_SCAN_STARTED:
11904 return "SCHED_SCAN_STARTED";
11905 case SCHED_SCAN_STOPPED:
11906 return "SCHED_SCAN_STOPPED";
11907 case SCHED_SCAN_RESULTS:
11908 return "SCHED_SCAN_RESULTS";
11909 }
11910
11911 return "??";
11912}
11913
11914
11915static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
11916{
11917 struct i802_bss *bss = priv;
11918 struct wpa_driver_nl80211_data *drv = bss->drv;
11919 int res;
11920 char *pos, *end;
11921
11922 pos = buf;
11923 end = buf + buflen;
11924
11925 res = os_snprintf(pos, end - pos,
11926 "ifindex=%d\n"
11927 "ifname=%s\n"
11928 "brname=%s\n"
11929 "addr=" MACSTR "\n"
11930 "freq=%d\n"
11931 "%s%s%s%s%s",
11932 bss->ifindex,
11933 bss->ifname,
11934 bss->brname,
11935 MAC2STR(bss->addr),
11936 bss->freq,
11937 bss->beacon_set ? "beacon_set=1\n" : "",
11938 bss->added_if_into_bridge ?
11939 "added_if_into_bridge=1\n" : "",
11940 bss->added_bridge ? "added_bridge=1\n" : "",
11941 bss->in_deinit ? "in_deinit=1\n" : "",
11942 bss->if_dynamic ? "if_dynamic=1\n" : "");
11943 if (res < 0 || res >= end - pos)
11944 return pos - buf;
11945 pos += res;
11946
11947 if (bss->wdev_id_set) {
11948 res = os_snprintf(pos, end - pos, "wdev_id=%llu\n",
11949 (unsigned long long) bss->wdev_id);
11950 if (res < 0 || res >= end - pos)
11951 return pos - buf;
11952 pos += res;
11953 }
11954
11955 res = os_snprintf(pos, end - pos,
11956 "phyname=%s\n"
11957 "drv_ifindex=%d\n"
11958 "operstate=%d\n"
11959 "scan_state=%s\n"
11960 "auth_bssid=" MACSTR "\n"
11961 "auth_attempt_bssid=" MACSTR "\n"
11962 "bssid=" MACSTR "\n"
11963 "prev_bssid=" MACSTR "\n"
11964 "associated=%d\n"
11965 "assoc_freq=%u\n"
11966 "monitor_sock=%d\n"
11967 "monitor_ifidx=%d\n"
11968 "monitor_refcount=%d\n"
11969 "last_mgmt_freq=%u\n"
11970 "eapol_tx_sock=%d\n"
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -070011971 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
Dmitry Shmidt56052862013-10-04 10:23:25 -070011972 drv->phyname,
11973 drv->ifindex,
11974 drv->operstate,
11975 scan_state_str(drv->scan_state),
11976 MAC2STR(drv->auth_bssid),
11977 MAC2STR(drv->auth_attempt_bssid),
11978 MAC2STR(drv->bssid),
11979 MAC2STR(drv->prev_bssid),
11980 drv->associated,
11981 drv->assoc_freq,
11982 drv->monitor_sock,
11983 drv->monitor_ifidx,
11984 drv->monitor_refcount,
11985 drv->last_mgmt_freq,
11986 drv->eapol_tx_sock,
11987 drv->ignore_if_down_event ?
11988 "ignore_if_down_event=1\n" : "",
11989 drv->scan_complete_events ?
11990 "scan_complete_events=1\n" : "",
11991 drv->disabled_11b_rates ?
11992 "disabled_11b_rates=1\n" : "",
11993 drv->pending_remain_on_chan ?
11994 "pending_remain_on_chan=1\n" : "",
11995 drv->in_interface_list ? "in_interface_list=1\n" : "",
11996 drv->device_ap_sme ? "device_ap_sme=1\n" : "",
11997 drv->poll_command_supported ?
11998 "poll_command_supported=1\n" : "",
11999 drv->data_tx_status ? "data_tx_status=1\n" : "",
12000 drv->scan_for_auth ? "scan_for_auth=1\n" : "",
12001 drv->retry_auth ? "retry_auth=1\n" : "",
12002 drv->use_monitor ? "use_monitor=1\n" : "",
12003 drv->ignore_next_local_disconnect ?
12004 "ignore_next_local_disconnect=1\n" : "",
Dmitry Shmidt7dba0e52014-04-14 10:49:15 -070012005 drv->ignore_next_local_deauth ?
12006 "ignore_next_local_deauth=1\n" : "",
Dmitry Shmidt56052862013-10-04 10:23:25 -070012007 drv->allow_p2p_device ? "allow_p2p_device=1\n" : "");
12008 if (res < 0 || res >= end - pos)
12009 return pos - buf;
12010 pos += res;
12011
12012 if (drv->has_capability) {
12013 res = os_snprintf(pos, end - pos,
12014 "capa.key_mgmt=0x%x\n"
12015 "capa.enc=0x%x\n"
12016 "capa.auth=0x%x\n"
12017 "capa.flags=0x%x\n"
12018 "capa.max_scan_ssids=%d\n"
12019 "capa.max_sched_scan_ssids=%d\n"
12020 "capa.sched_scan_supported=%d\n"
12021 "capa.max_match_sets=%d\n"
12022 "capa.max_remain_on_chan=%u\n"
12023 "capa.max_stations=%u\n"
12024 "capa.probe_resp_offloads=0x%x\n"
12025 "capa.max_acl_mac_addrs=%u\n"
12026 "capa.num_multichan_concurrent=%u\n",
12027 drv->capa.key_mgmt,
12028 drv->capa.enc,
12029 drv->capa.auth,
12030 drv->capa.flags,
12031 drv->capa.max_scan_ssids,
12032 drv->capa.max_sched_scan_ssids,
12033 drv->capa.sched_scan_supported,
12034 drv->capa.max_match_sets,
12035 drv->capa.max_remain_on_chan,
12036 drv->capa.max_stations,
12037 drv->capa.probe_resp_offloads,
12038 drv->capa.max_acl_mac_addrs,
12039 drv->capa.num_multichan_concurrent);
12040 if (res < 0 || res >= end - pos)
12041 return pos - buf;
12042 pos += res;
12043 }
12044
12045 return pos - buf;
12046}
12047
12048
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080012049static int set_beacon_data(struct nl_msg *msg, struct beacon_data *settings)
12050{
12051 if (settings->head)
12052 NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD,
12053 settings->head_len, settings->head);
12054
12055 if (settings->tail)
12056 NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL,
12057 settings->tail_len, settings->tail);
12058
12059 if (settings->beacon_ies)
12060 NLA_PUT(msg, NL80211_ATTR_IE,
12061 settings->beacon_ies_len, settings->beacon_ies);
12062
12063 if (settings->proberesp_ies)
12064 NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
12065 settings->proberesp_ies_len, settings->proberesp_ies);
12066
12067 if (settings->assocresp_ies)
12068 NLA_PUT(msg,
12069 NL80211_ATTR_IE_ASSOC_RESP,
12070 settings->assocresp_ies_len, settings->assocresp_ies);
12071
12072 if (settings->probe_resp)
12073 NLA_PUT(msg, NL80211_ATTR_PROBE_RESP,
12074 settings->probe_resp_len, settings->probe_resp);
12075
12076 return 0;
12077
12078nla_put_failure:
12079 return -ENOBUFS;
12080}
12081
12082
12083static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
12084{
12085 struct nl_msg *msg;
12086 struct i802_bss *bss = priv;
12087 struct wpa_driver_nl80211_data *drv = bss->drv;
12088 struct nlattr *beacon_csa;
12089 int ret = -ENOBUFS;
12090
Dmitry Shmidt04f534e2013-12-09 15:50:16 -080012091 wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d width=%d cf1=%d cf2=%d)",
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080012092 settings->cs_count, settings->block_tx,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -080012093 settings->freq_params.freq, settings->freq_params.bandwidth,
12094 settings->freq_params.center_freq1,
12095 settings->freq_params.center_freq2);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080012096
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012097 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080012098 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command");
12099 return -EOPNOTSUPP;
12100 }
12101
12102 if ((drv->nlmode != NL80211_IFTYPE_AP) &&
12103 (drv->nlmode != NL80211_IFTYPE_P2P_GO))
12104 return -EOPNOTSUPP;
12105
12106 /* check settings validity */
12107 if (!settings->beacon_csa.tail ||
12108 ((settings->beacon_csa.tail_len <=
12109 settings->counter_offset_beacon) ||
12110 (settings->beacon_csa.tail[settings->counter_offset_beacon] !=
12111 settings->cs_count)))
12112 return -EINVAL;
12113
12114 if (settings->beacon_csa.probe_resp &&
12115 ((settings->beacon_csa.probe_resp_len <=
12116 settings->counter_offset_presp) ||
12117 (settings->beacon_csa.probe_resp[settings->counter_offset_presp] !=
12118 settings->cs_count)))
12119 return -EINVAL;
12120
12121 msg = nlmsg_alloc();
12122 if (!msg)
12123 return -ENOMEM;
12124
12125 nl80211_cmd(drv, msg, 0, NL80211_CMD_CHANNEL_SWITCH);
Dmitry Shmidtd30ac602014-06-30 09:54:22 -070012126 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080012127 NLA_PUT_U32(msg, NL80211_ATTR_CH_SWITCH_COUNT, settings->cs_count);
12128 ret = nl80211_put_freq_params(msg, &settings->freq_params);
12129 if (ret)
12130 goto error;
12131
12132 if (settings->block_tx)
12133 NLA_PUT_FLAG(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX);
12134
12135 /* beacon_after params */
12136 ret = set_beacon_data(msg, &settings->beacon_after);
12137 if (ret)
12138 goto error;
12139
12140 /* beacon_csa params */
12141 beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
12142 if (!beacon_csa)
12143 goto nla_put_failure;
12144
12145 ret = set_beacon_data(msg, &settings->beacon_csa);
12146 if (ret)
12147 goto error;
12148
12149 NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_BEACON,
12150 settings->counter_offset_beacon);
12151
12152 if (settings->beacon_csa.probe_resp)
12153 NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_PRESP,
12154 settings->counter_offset_presp);
12155
12156 nla_nest_end(msg, beacon_csa);
12157 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
12158 if (ret) {
12159 wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)",
12160 ret, strerror(-ret));
12161 }
12162 return ret;
12163
12164nla_put_failure:
12165 ret = -ENOBUFS;
12166error:
12167 nlmsg_free(msg);
12168 wpa_printf(MSG_DEBUG, "nl80211: Could not build channel switch request");
12169 return ret;
12170}
12171
12172
Dmitry Shmidta38abf92014-03-06 13:38:44 -080012173#ifdef CONFIG_TESTING_OPTIONS
12174static int cmd_reply_handler(struct nl_msg *msg, void *arg)
12175{
12176 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12177 struct wpabuf *buf = arg;
12178
12179 if (!buf)
12180 return NL_SKIP;
12181
12182 if ((size_t) genlmsg_attrlen(gnlh, 0) > wpabuf_tailroom(buf)) {
12183 wpa_printf(MSG_INFO, "nl80211: insufficient buffer space for reply");
12184 return NL_SKIP;
12185 }
12186
12187 wpabuf_put_data(buf, genlmsg_attrdata(gnlh, 0),
12188 genlmsg_attrlen(gnlh, 0));
12189
12190 return NL_SKIP;
12191}
12192#endif /* CONFIG_TESTING_OPTIONS */
12193
12194
12195static int vendor_reply_handler(struct nl_msg *msg, void *arg)
12196{
12197 struct nlattr *tb[NL80211_ATTR_MAX + 1];
12198 struct nlattr *nl_vendor_reply, *nl;
12199 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
12200 struct wpabuf *buf = arg;
12201 int rem;
12202
12203 if (!buf)
12204 return NL_SKIP;
12205
12206 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
12207 genlmsg_attrlen(gnlh, 0), NULL);
12208 nl_vendor_reply = tb[NL80211_ATTR_VENDOR_DATA];
12209
12210 if (!nl_vendor_reply)
12211 return NL_SKIP;
12212
12213 if ((size_t) nla_len(nl_vendor_reply) > wpabuf_tailroom(buf)) {
12214 wpa_printf(MSG_INFO, "nl80211: Vendor command: insufficient buffer space for reply");
12215 return NL_SKIP;
12216 }
12217
12218 nla_for_each_nested(nl, nl_vendor_reply, rem) {
12219 wpabuf_put_data(buf, nla_data(nl), nla_len(nl));
12220 }
12221
12222 return NL_SKIP;
12223}
12224
12225
12226static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
12227 unsigned int subcmd, const u8 *data,
12228 size_t data_len, struct wpabuf *buf)
12229{
12230 struct i802_bss *bss = priv;
12231 struct wpa_driver_nl80211_data *drv = bss->drv;
12232 struct nl_msg *msg;
12233 int ret;
12234
12235 msg = nlmsg_alloc();
12236 if (!msg)
12237 return -ENOMEM;
12238
12239#ifdef CONFIG_TESTING_OPTIONS
12240 if (vendor_id == 0xffffffff) {
12241 nl80211_cmd(drv, msg, 0, subcmd);
12242 if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) <
12243 0)
12244 goto nla_put_failure;
12245 ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf);
12246 if (ret)
12247 wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
12248 ret);
12249 return ret;
12250 }
12251#endif /* CONFIG_TESTING_OPTIONS */
12252
12253 nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR);
12254 if (nl80211_set_iface_id(msg, bss) < 0)
12255 goto nla_put_failure;
12256 NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, vendor_id);
12257 NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd);
12258 if (data)
12259 NLA_PUT(msg, NL80211_ATTR_VENDOR_DATA, data_len, data);
12260
12261 ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf);
12262 if (ret)
12263 wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d",
12264 ret);
12265 return ret;
12266
12267nla_put_failure:
12268 nlmsg_free(msg);
12269 return -ENOBUFS;
12270}
12271
12272
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012273static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set,
12274 u8 qos_map_set_len)
12275{
12276 struct i802_bss *bss = priv;
12277 struct wpa_driver_nl80211_data *drv = bss->drv;
12278 struct nl_msg *msg;
12279 int ret;
12280
12281 msg = nlmsg_alloc();
12282 if (!msg)
12283 return -ENOMEM;
12284
12285 wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map",
12286 qos_map_set, qos_map_set_len);
12287
12288 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_QOS_MAP);
12289 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
12290 NLA_PUT(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set);
12291
12292 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
12293 if (ret)
12294 wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed");
12295
12296 return ret;
12297
12298nla_put_failure:
12299 nlmsg_free(msg);
12300 return -ENOBUFS;
12301}
12302
12303
Dmitry Shmidtb58836e2014-04-29 14:35:56 -070012304static int nl80211_set_wowlan(void *priv,
12305 const struct wowlan_triggers *triggers)
12306{
12307 struct i802_bss *bss = priv;
12308 struct wpa_driver_nl80211_data *drv = bss->drv;
12309 struct nl_msg *msg;
12310 struct nlattr *wowlan_triggers;
12311 int ret;
12312
12313 msg = nlmsg_alloc();
12314 if (!msg)
12315 return -ENOMEM;
12316
12317 wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan");
12318
12319 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WOWLAN);
12320 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
12321
12322 wowlan_triggers = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
12323 if (!wowlan_triggers)
12324 goto nla_put_failure;
12325
12326 if (triggers->any)
12327 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY);
12328 if (triggers->disconnect)
12329 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT);
12330 if (triggers->magic_pkt)
12331 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
12332 if (triggers->gtk_rekey_failure)
12333 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
12334 if (triggers->eap_identity_req)
12335 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
12336 if (triggers->four_way_handshake)
12337 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
12338 if (triggers->rfkill_release)
12339 NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
12340
12341 nla_nest_end(msg, wowlan_triggers);
12342
12343 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
12344 if (ret)
12345 wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed");
12346
12347 return ret;
12348
12349nla_put_failure:
12350 nlmsg_free(msg);
12351 return -ENOBUFS;
12352}
12353
12354
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012355const struct wpa_driver_ops wpa_driver_nl80211_ops = {
12356 .name = "nl80211",
12357 .desc = "Linux nl80211/cfg80211",
12358 .get_bssid = wpa_driver_nl80211_get_bssid,
12359 .get_ssid = wpa_driver_nl80211_get_ssid,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012360 .set_key = driver_nl80211_set_key,
12361 .scan2 = driver_nl80211_scan2,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012362 .sched_scan = wpa_driver_nl80211_sched_scan,
12363 .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012364 .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012365 .deauthenticate = driver_nl80211_deauthenticate,
12366 .authenticate = driver_nl80211_authenticate,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012367 .associate = wpa_driver_nl80211_associate,
12368 .global_init = nl80211_global_init,
12369 .global_deinit = nl80211_global_deinit,
12370 .init2 = wpa_driver_nl80211_init,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012371 .deinit = driver_nl80211_deinit,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012372 .get_capa = wpa_driver_nl80211_get_capa,
12373 .set_operstate = wpa_driver_nl80211_set_operstate,
12374 .set_supp_port = wpa_driver_nl80211_set_supp_port,
12375 .set_country = wpa_driver_nl80211_set_country,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080012376 .get_country = wpa_driver_nl80211_get_country,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012377 .set_ap = wpa_driver_nl80211_set_ap,
Dmitry Shmidt8bae4132013-06-06 11:25:10 -070012378 .set_acl = wpa_driver_nl80211_set_acl,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012379 .if_add = wpa_driver_nl80211_if_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012380 .if_remove = driver_nl80211_if_remove,
12381 .send_mlme = driver_nl80211_send_mlme,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012382 .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data,
12383 .sta_add = wpa_driver_nl80211_sta_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012384 .sta_remove = driver_nl80211_sta_remove,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012385 .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
12386 .sta_set_flags = wpa_driver_nl80211_sta_set_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012387 .hapd_init = i802_init,
12388 .hapd_deinit = i802_deinit,
Jouni Malinen75ecf522011-06-27 15:19:46 -070012389 .set_wds_sta = i802_set_wds_sta,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012390 .get_seqnum = i802_get_seqnum,
12391 .flush = i802_flush,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012392 .get_inact_sec = i802_get_inact_sec,
12393 .sta_clear_stats = i802_sta_clear_stats,
12394 .set_rts = i802_set_rts,
12395 .set_frag = i802_set_frag,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012396 .set_tx_queue_params = i802_set_tx_queue_params,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012397 .set_sta_vlan = driver_nl80211_set_sta_vlan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012398 .sta_deauth = i802_sta_deauth,
12399 .sta_disassoc = i802_sta_disassoc,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012400 .read_sta_data = driver_nl80211_read_sta_data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012401 .set_freq = i802_set_freq,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012402 .send_action = driver_nl80211_send_action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012403 .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
12404 .remain_on_channel = wpa_driver_nl80211_remain_on_channel,
12405 .cancel_remain_on_channel =
12406 wpa_driver_nl80211_cancel_remain_on_channel,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080012407 .probe_req_report = driver_nl80211_probe_req_report,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012408 .deinit_ap = wpa_driver_nl80211_deinit_ap,
Dmitry Shmidt04949592012-07-19 12:16:46 -070012409 .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012410 .resume = wpa_driver_nl80211_resume,
12411 .send_ft_action = nl80211_send_ft_action,
12412 .signal_monitor = nl80211_signal_monitor,
12413 .signal_poll = nl80211_signal_poll,
12414 .send_frame = nl80211_send_frame,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012415 .shared_freq = wpa_driver_nl80211_shared_freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012416 .set_param = nl80211_set_param,
12417 .get_radio_name = nl80211_get_radio_name,
Jouni Malinen75ecf522011-06-27 15:19:46 -070012418 .add_pmkid = nl80211_add_pmkid,
12419 .remove_pmkid = nl80211_remove_pmkid,
12420 .flush_pmkid = nl80211_flush_pmkid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012421 .set_rekey_info = nl80211_set_rekey_info,
12422 .poll_client = nl80211_poll_client,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012423 .set_p2p_powersave = nl80211_set_p2p_powersave,
Dmitry Shmidtea69e842013-05-13 14:52:28 -070012424 .start_dfs_cac = nl80211_start_radar_detection,
12425 .stop_ap = wpa_driver_nl80211_stop_ap,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012426#ifdef CONFIG_TDLS
12427 .send_tdls_mgmt = nl80211_send_tdls_mgmt,
12428 .tdls_oper = nl80211_tdls_oper,
12429#endif /* CONFIG_TDLS */
Dmitry Shmidt700a1372013-03-15 14:14:44 -070012430 .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
Dmitry Shmidt34af3062013-07-11 10:46:32 -070012431 .get_mac_addr = wpa_driver_nl80211_get_macaddr,
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070012432 .get_survey = wpa_driver_nl80211_get_survey,
Dmitry Shmidt56052862013-10-04 10:23:25 -070012433 .status = wpa_driver_nl80211_status,
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080012434 .switch_channel = nl80211_switch_channel,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012435#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070012436 .set_noa = wpa_driver_set_p2p_noa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080012437 .get_noa = wpa_driver_get_p2p_noa,
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070012438 .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080012439#endif /* ANDROID_P2P */
Dmitry Shmidt738a26e2011-07-07 14:22:14 -070012440#ifdef ANDROID
12441 .driver_cmd = wpa_driver_nl80211_driver_cmd,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080012442#endif /* ANDROID */
Dmitry Shmidta38abf92014-03-06 13:38:44 -080012443 .vendor_cmd = nl80211_vendor_cmd,
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080012444 .set_qos_map = nl80211_set_qos_map,
Dmitry Shmidtb58836e2014-04-29 14:35:56 -070012445 .set_wowlan = nl80211_set_wowlan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070012446};