blob: 87c9661de640195ecfa5477c7ded029347444885 [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 Shmidt8d520ff2011-05-09 14:06:53 -070032#include "common/ieee802_11_defs.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080033#include "common/ieee802_11_common.h"
34#include "l2_packet/l2_packet.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070035#include "netlink.h"
36#include "linux_ioctl.h"
37#include "radiotap.h"
38#include "radiotap_iter.h"
39#include "rfkill.h"
40#include "driver.h"
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080041
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080042#ifndef SO_WIFI_STATUS
43# if defined(__sparc__)
44# define SO_WIFI_STATUS 0x0025
45# elif defined(__parisc__)
46# define SO_WIFI_STATUS 0x4022
47# else
48# define SO_WIFI_STATUS 41
49# endif
50
51# define SCM_WIFI_STATUS SO_WIFI_STATUS
52#endif
53
54#ifndef SO_EE_ORIGIN_TXSTATUS
55#define SO_EE_ORIGIN_TXSTATUS 4
56#endif
57
58#ifndef PACKET_TX_TIMESTAMP
59#define PACKET_TX_TIMESTAMP 16
60#endif
61
62#ifdef ANDROID
63#include "android_drv.h"
64#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070065#ifdef CONFIG_LIBNL20
66/* libnl 2.0 compatibility code */
67#define nl_handle nl_sock
68#define nl80211_handle_alloc nl_socket_alloc_cb
69#define nl80211_handle_destroy nl_socket_free
70#else
71/*
72 * libnl 1.1 has a bug, it tries to allocate socket numbers densely
73 * but when you free a socket again it will mess up its bitmap and
74 * and use the wrong number the next time it needs a socket ID.
75 * Therefore, we wrap the handle alloc/destroy and add our own pid
76 * accounting.
77 */
78static uint32_t port_bitmap[32] = { 0 };
79
80static struct nl_handle *nl80211_handle_alloc(void *cb)
81{
82 struct nl_handle *handle;
83 uint32_t pid = getpid() & 0x3FFFFF;
84 int i;
85
86 handle = nl_handle_alloc_cb(cb);
87
88 for (i = 0; i < 1024; i++) {
89 if (port_bitmap[i / 32] & (1 << (i % 32)))
90 continue;
91 port_bitmap[i / 32] |= 1 << (i % 32);
92 pid += i << 22;
93 break;
94 }
95
96 nl_socket_set_local_port(handle, pid);
97
98 return handle;
99}
100
101static void nl80211_handle_destroy(struct nl_handle *handle)
102{
103 uint32_t port = nl_socket_get_local_port(handle);
104
105 port >>= 22;
106 port_bitmap[port / 32] &= ~(1 << (port % 32));
107
108 nl_handle_destroy(handle);
109}
110#endif /* CONFIG_LIBNL20 */
111
112
Dmitry Shmidt54605472013-11-08 11:10:19 -0800113#ifdef ANDROID
114/* system/core/libnl_2 does not include nl_socket_set_nonblocking() */
115static int android_nl_socket_set_nonblocking(struct nl_handle *handle)
116{
117 return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
118}
119#undef nl_socket_set_nonblocking
120#define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h)
121#endif /* ANDROID */
122
123
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800124static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
125{
126 struct nl_handle *handle;
127
128 handle = nl80211_handle_alloc(cb);
129 if (handle == NULL) {
130 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
131 "callbacks (%s)", dbg);
132 return NULL;
133 }
134
135 if (genl_connect(handle)) {
136 wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
137 "netlink (%s)", dbg);
138 nl80211_handle_destroy(handle);
139 return NULL;
140 }
141
142 return handle;
143}
144
145
146static void nl_destroy_handles(struct nl_handle **handle)
147{
148 if (*handle == NULL)
149 return;
150 nl80211_handle_destroy(*handle);
151 *handle = NULL;
152}
153
154
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700155#if __WORDSIZE == 64
156#define ELOOP_SOCKET_INVALID (intptr_t) 0x8888888888888889ULL
157#else
158#define ELOOP_SOCKET_INVALID (intptr_t) 0x88888889ULL
159#endif
160
161static void nl80211_register_eloop_read(struct nl_handle **handle,
162 eloop_sock_handler handler,
163 void *eloop_data)
164{
165 nl_socket_set_nonblocking(*handle);
166 eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
167 eloop_data, *handle);
168 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
169}
170
171
172static void nl80211_destroy_eloop_handle(struct nl_handle **handle)
173{
174 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
175 eloop_unregister_read_sock(nl_socket_get_fd(*handle));
176 nl_destroy_handles(handle);
177}
178
179
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700180#ifndef IFF_LOWER_UP
181#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
182#endif
183#ifndef IFF_DORMANT
184#define IFF_DORMANT 0x20000 /* driver signals dormant */
185#endif
186
187#ifndef IF_OPER_DORMANT
188#define IF_OPER_DORMANT 5
189#endif
190#ifndef IF_OPER_UP
191#define IF_OPER_UP 6
192#endif
193
194struct nl80211_global {
195 struct dl_list interfaces;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800196 int if_add_ifindex;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700197 u64 if_add_wdevid;
198 int if_add_wdevid_set;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800199 struct netlink_data *netlink;
200 struct nl_cb *nl_cb;
201 struct nl_handle *nl;
202 int nl80211_id;
203 int ioctl_sock; /* socket for ioctl() use */
204
205 struct nl_handle *nl_event;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206};
207
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800208struct nl80211_wiphy_data {
209 struct dl_list list;
210 struct dl_list bsss;
211 struct dl_list drvs;
212
213 struct nl_handle *nl_beacons;
214 struct nl_cb *nl_cb;
215
216 int wiphy_idx;
217};
218
219static void nl80211_global_deinit(void *priv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800220
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700221struct i802_bss {
222 struct wpa_driver_nl80211_data *drv;
223 struct i802_bss *next;
224 int ifindex;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700225 u64 wdev_id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700226 char ifname[IFNAMSIZ + 1];
227 char brname[IFNAMSIZ];
228 unsigned int beacon_set:1;
229 unsigned int added_if_into_bridge:1;
230 unsigned int added_bridge:1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700231 unsigned int in_deinit:1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700232 unsigned int wdev_id_set:1;
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800233 unsigned int added_if:1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800234
235 u8 addr[ETH_ALEN];
236
237 int freq;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -0700238 int if_dynamic;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800239
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800240 void *ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800241 struct nl_handle *nl_preq, *nl_mgmt;
242 struct nl_cb *nl_cb;
243
244 struct nl80211_wiphy_data *wiphy_data;
245 struct dl_list wiphy_list;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700246};
247
248struct wpa_driver_nl80211_data {
249 struct nl80211_global *global;
250 struct dl_list list;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800251 struct dl_list wiphy_list;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700252 char phyname[32];
253 void *ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254 int ifindex;
255 int if_removed;
256 int if_disabled;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800257 int ignore_if_down_event;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700258 struct rfkill_data *rfkill;
259 struct wpa_driver_capa capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -0700260 u8 *extended_capa, *extended_capa_mask;
261 unsigned int extended_capa_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700262 int has_capability;
263
264 int operstate;
265
266 int scan_complete_events;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700267 enum scan_states {
268 NO_SCAN, SCAN_REQUESTED, SCAN_STARTED, SCAN_COMPLETED,
269 SCAN_ABORTED, SCHED_SCAN_STARTED, SCHED_SCAN_STOPPED,
270 SCHED_SCAN_RESULTS
271 } scan_state;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700272
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700273 struct nl_cb *nl_cb;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700274
275 u8 auth_bssid[ETH_ALEN];
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700276 u8 auth_attempt_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700277 u8 bssid[ETH_ALEN];
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700278 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700279 int associated;
280 u8 ssid[32];
281 size_t ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800282 enum nl80211_iftype nlmode;
283 enum nl80211_iftype ap_scan_as_station;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284 unsigned int assoc_freq;
285
286 int monitor_sock;
287 int monitor_ifidx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800288 int monitor_refcount;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700289
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800290 unsigned int disabled_11b_rates:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700291 unsigned int pending_remain_on_chan:1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800292 unsigned int in_interface_list:1;
293 unsigned int device_ap_sme:1;
294 unsigned int poll_command_supported:1;
295 unsigned int data_tx_status:1;
296 unsigned int scan_for_auth:1;
297 unsigned int retry_auth:1;
298 unsigned int use_monitor:1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800299 unsigned int ignore_next_local_disconnect:1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700300 unsigned int allow_p2p_device:1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800301 unsigned int hostapd:1;
302 unsigned int start_mode_ap:1;
303 unsigned int start_iface_up:1;
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -0800304 unsigned int test_use_roc_tx:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700305
306 u64 remain_on_chan_cookie;
307 u64 send_action_cookie;
308
309 unsigned int last_mgmt_freq;
310
311 struct wpa_driver_scan_filter *filter_ssids;
312 size_t num_filter_ssids;
313
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800314 struct i802_bss *first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700315
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800316 int eapol_tx_sock;
317
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700318 int eapol_sock; /* socket for EAPOL frames */
319
320 int default_if_indices[16];
321 int *if_indices;
322 int num_if_indices;
323
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800324 /* From failed authentication command */
325 int auth_freq;
326 u8 auth_bssid_[ETH_ALEN];
327 u8 auth_ssid[32];
328 size_t auth_ssid_len;
329 int auth_alg;
330 u8 *auth_ie;
331 size_t auth_ie_len;
332 u8 auth_wep_key[4][16];
333 size_t auth_wep_key_len[4];
334 int auth_wep_tx_keyidx;
335 int auth_local_state_change;
336 int auth_p2p;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700337};
338
339
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800340static void wpa_driver_nl80211_deinit(struct i802_bss *bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700341static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
342 void *timeout_ctx);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800343static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
344 enum nl80211_iftype nlmode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700345static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800346wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
347 const u8 *set_addr, int first);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700348static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
349 const u8 *addr, int cmd, u16 reason_code,
350 int local_state_change);
351static void nl80211_remove_monitor_interface(
352 struct wpa_driver_nl80211_data *drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800353static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354 unsigned int freq, unsigned int wait,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800355 const u8 *buf, size_t buf_len, u64 *cookie,
356 int no_cck, int no_ack, int offchanok);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700357static int nl80211_register_frame(struct i802_bss *bss,
358 struct nl_handle *hl_handle,
359 u16 type, const u8 *match, size_t match_len);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800360static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
361 int report);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800362#ifdef ANDROID
363static int android_pno_start(struct i802_bss *bss,
364 struct wpa_driver_scan_params *params);
365static int android_pno_stop(struct i802_bss *bss);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -0800366extern int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
367 size_t buf_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800368#endif /* ANDROID */
369#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -0700370int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800371int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -0700372int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow);
373int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -0800374 const struct wpabuf *proberesp,
375 const struct wpabuf *assocresp);
376#endif /* ANDROID_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700378static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
379static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
380static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800381static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700382 enum wpa_driver_if_type type,
383 const char *ifname);
Dmitry Shmidt738a26e2011-07-07 14:22:14 -0700384
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800385static int wpa_driver_nl80211_set_freq(struct i802_bss *bss,
386 struct hostapd_freq_params *freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700387static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
388 int ifindex, int disabled);
389
390static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800391static int wpa_driver_nl80211_authenticate_retry(
392 struct wpa_driver_nl80211_data *drv);
393
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -0700394static int i802_set_iface_flags(struct i802_bss *bss, int up);
395
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800396
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700397static const char * nl80211_command_to_string(enum nl80211_commands cmd)
398{
399#define C2S(x) case x: return #x;
400 switch (cmd) {
401 C2S(NL80211_CMD_UNSPEC)
402 C2S(NL80211_CMD_GET_WIPHY)
403 C2S(NL80211_CMD_SET_WIPHY)
404 C2S(NL80211_CMD_NEW_WIPHY)
405 C2S(NL80211_CMD_DEL_WIPHY)
406 C2S(NL80211_CMD_GET_INTERFACE)
407 C2S(NL80211_CMD_SET_INTERFACE)
408 C2S(NL80211_CMD_NEW_INTERFACE)
409 C2S(NL80211_CMD_DEL_INTERFACE)
410 C2S(NL80211_CMD_GET_KEY)
411 C2S(NL80211_CMD_SET_KEY)
412 C2S(NL80211_CMD_NEW_KEY)
413 C2S(NL80211_CMD_DEL_KEY)
414 C2S(NL80211_CMD_GET_BEACON)
415 C2S(NL80211_CMD_SET_BEACON)
416 C2S(NL80211_CMD_START_AP)
417 C2S(NL80211_CMD_STOP_AP)
418 C2S(NL80211_CMD_GET_STATION)
419 C2S(NL80211_CMD_SET_STATION)
420 C2S(NL80211_CMD_NEW_STATION)
421 C2S(NL80211_CMD_DEL_STATION)
422 C2S(NL80211_CMD_GET_MPATH)
423 C2S(NL80211_CMD_SET_MPATH)
424 C2S(NL80211_CMD_NEW_MPATH)
425 C2S(NL80211_CMD_DEL_MPATH)
426 C2S(NL80211_CMD_SET_BSS)
427 C2S(NL80211_CMD_SET_REG)
428 C2S(NL80211_CMD_REQ_SET_REG)
429 C2S(NL80211_CMD_GET_MESH_CONFIG)
430 C2S(NL80211_CMD_SET_MESH_CONFIG)
431 C2S(NL80211_CMD_SET_MGMT_EXTRA_IE)
432 C2S(NL80211_CMD_GET_REG)
433 C2S(NL80211_CMD_GET_SCAN)
434 C2S(NL80211_CMD_TRIGGER_SCAN)
435 C2S(NL80211_CMD_NEW_SCAN_RESULTS)
436 C2S(NL80211_CMD_SCAN_ABORTED)
437 C2S(NL80211_CMD_REG_CHANGE)
438 C2S(NL80211_CMD_AUTHENTICATE)
439 C2S(NL80211_CMD_ASSOCIATE)
440 C2S(NL80211_CMD_DEAUTHENTICATE)
441 C2S(NL80211_CMD_DISASSOCIATE)
442 C2S(NL80211_CMD_MICHAEL_MIC_FAILURE)
443 C2S(NL80211_CMD_REG_BEACON_HINT)
444 C2S(NL80211_CMD_JOIN_IBSS)
445 C2S(NL80211_CMD_LEAVE_IBSS)
446 C2S(NL80211_CMD_TESTMODE)
447 C2S(NL80211_CMD_CONNECT)
448 C2S(NL80211_CMD_ROAM)
449 C2S(NL80211_CMD_DISCONNECT)
450 C2S(NL80211_CMD_SET_WIPHY_NETNS)
451 C2S(NL80211_CMD_GET_SURVEY)
452 C2S(NL80211_CMD_NEW_SURVEY_RESULTS)
453 C2S(NL80211_CMD_SET_PMKSA)
454 C2S(NL80211_CMD_DEL_PMKSA)
455 C2S(NL80211_CMD_FLUSH_PMKSA)
456 C2S(NL80211_CMD_REMAIN_ON_CHANNEL)
457 C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL)
458 C2S(NL80211_CMD_SET_TX_BITRATE_MASK)
459 C2S(NL80211_CMD_REGISTER_FRAME)
460 C2S(NL80211_CMD_FRAME)
461 C2S(NL80211_CMD_FRAME_TX_STATUS)
462 C2S(NL80211_CMD_SET_POWER_SAVE)
463 C2S(NL80211_CMD_GET_POWER_SAVE)
464 C2S(NL80211_CMD_SET_CQM)
465 C2S(NL80211_CMD_NOTIFY_CQM)
466 C2S(NL80211_CMD_SET_CHANNEL)
467 C2S(NL80211_CMD_SET_WDS_PEER)
468 C2S(NL80211_CMD_FRAME_WAIT_CANCEL)
469 C2S(NL80211_CMD_JOIN_MESH)
470 C2S(NL80211_CMD_LEAVE_MESH)
471 C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE)
472 C2S(NL80211_CMD_UNPROT_DISASSOCIATE)
473 C2S(NL80211_CMD_NEW_PEER_CANDIDATE)
474 C2S(NL80211_CMD_GET_WOWLAN)
475 C2S(NL80211_CMD_SET_WOWLAN)
476 C2S(NL80211_CMD_START_SCHED_SCAN)
477 C2S(NL80211_CMD_STOP_SCHED_SCAN)
478 C2S(NL80211_CMD_SCHED_SCAN_RESULTS)
479 C2S(NL80211_CMD_SCHED_SCAN_STOPPED)
480 C2S(NL80211_CMD_SET_REKEY_OFFLOAD)
481 C2S(NL80211_CMD_PMKSA_CANDIDATE)
482 C2S(NL80211_CMD_TDLS_OPER)
483 C2S(NL80211_CMD_TDLS_MGMT)
484 C2S(NL80211_CMD_UNEXPECTED_FRAME)
485 C2S(NL80211_CMD_PROBE_CLIENT)
486 C2S(NL80211_CMD_REGISTER_BEACONS)
487 C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME)
488 C2S(NL80211_CMD_SET_NOACK_MAP)
489 C2S(NL80211_CMD_CH_SWITCH_NOTIFY)
490 C2S(NL80211_CMD_START_P2P_DEVICE)
491 C2S(NL80211_CMD_STOP_P2P_DEVICE)
492 C2S(NL80211_CMD_CONN_FAILED)
493 C2S(NL80211_CMD_SET_MCAST_RATE)
494 C2S(NL80211_CMD_SET_MAC_ACL)
495 C2S(NL80211_CMD_RADAR_DETECT)
496 C2S(NL80211_CMD_GET_PROTOCOL_FEATURES)
497 C2S(NL80211_CMD_UPDATE_FT_IES)
498 C2S(NL80211_CMD_FT_EVENT)
499 C2S(NL80211_CMD_CRIT_PROTOCOL_START)
500 C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800501 C2S(NL80211_CMD_GET_COALESCE)
502 C2S(NL80211_CMD_SET_COALESCE)
503 C2S(NL80211_CMD_CHANNEL_SWITCH)
504 C2S(NL80211_CMD_VENDOR)
505 C2S(NL80211_CMD_SET_QOS_MAP)
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700506 default:
507 return "NL80211_CMD_UNKNOWN";
508 }
509#undef C2S
510}
511
512
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800513/* Converts nl80211_chan_width to a common format */
514static enum chan_width convert2width(int width)
515{
516 switch (width) {
517 case NL80211_CHAN_WIDTH_20_NOHT:
518 return CHAN_WIDTH_20_NOHT;
519 case NL80211_CHAN_WIDTH_20:
520 return CHAN_WIDTH_20;
521 case NL80211_CHAN_WIDTH_40:
522 return CHAN_WIDTH_40;
523 case NL80211_CHAN_WIDTH_80:
524 return CHAN_WIDTH_80;
525 case NL80211_CHAN_WIDTH_80P80:
526 return CHAN_WIDTH_80P80;
527 case NL80211_CHAN_WIDTH_160:
528 return CHAN_WIDTH_160;
529 }
530 return CHAN_WIDTH_UNKNOWN;
531}
532
533
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800534static int is_ap_interface(enum nl80211_iftype nlmode)
535{
536 return (nlmode == NL80211_IFTYPE_AP ||
537 nlmode == NL80211_IFTYPE_P2P_GO);
538}
539
540
541static int is_sta_interface(enum nl80211_iftype nlmode)
542{
543 return (nlmode == NL80211_IFTYPE_STATION ||
544 nlmode == NL80211_IFTYPE_P2P_CLIENT);
545}
546
547
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700548static int is_p2p_net_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800549{
550 return (nlmode == NL80211_IFTYPE_P2P_CLIENT ||
551 nlmode == NL80211_IFTYPE_P2P_GO);
552}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700553
554
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700555static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
556{
557 if (drv->associated)
558 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
559 drv->associated = 0;
560 os_memset(drv->bssid, 0, ETH_ALEN);
561}
562
563
Jouni Malinen87fd2792011-05-16 18:35:42 +0300564struct nl80211_bss_info_arg {
565 struct wpa_driver_nl80211_data *drv;
566 struct wpa_scan_results *res;
567 unsigned int assoc_freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800568 u8 assoc_bssid[ETH_ALEN];
Jouni Malinen87fd2792011-05-16 18:35:42 +0300569};
570
571static int bss_info_handler(struct nl_msg *msg, void *arg);
572
573
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700574/* nl80211 code */
575static int ack_handler(struct nl_msg *msg, void *arg)
576{
577 int *err = arg;
578 *err = 0;
579 return NL_STOP;
580}
581
582static int finish_handler(struct nl_msg *msg, void *arg)
583{
584 int *ret = arg;
585 *ret = 0;
586 return NL_SKIP;
587}
588
589static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
590 void *arg)
591{
592 int *ret = arg;
593 *ret = err->error;
594 return NL_SKIP;
595}
596
597
598static int no_seq_check(struct nl_msg *msg, void *arg)
599{
600 return NL_OK;
601}
602
603
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800604static int send_and_recv(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700605 struct nl_handle *nl_handle, struct nl_msg *msg,
606 int (*valid_handler)(struct nl_msg *, void *),
607 void *valid_data)
608{
609 struct nl_cb *cb;
610 int err = -ENOMEM;
611
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800612 cb = nl_cb_clone(global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700613 if (!cb)
614 goto out;
615
616 err = nl_send_auto_complete(nl_handle, msg);
617 if (err < 0)
618 goto out;
619
620 err = 1;
621
622 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
623 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
624 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
625
626 if (valid_handler)
627 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
628 valid_handler, valid_data);
629
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700630 while (err > 0) {
631 int res = nl_recvmsgs(nl_handle, cb);
632 if (res) {
633 wpa_printf(MSG_INFO,
634 "nl80211: %s->nl_recvmsgs failed: %d",
635 __func__, res);
636 }
637 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700638 out:
639 nl_cb_put(cb);
640 nlmsg_free(msg);
641 return err;
642}
643
644
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800645static int send_and_recv_msgs_global(struct nl80211_global *global,
646 struct nl_msg *msg,
647 int (*valid_handler)(struct nl_msg *, void *),
648 void *valid_data)
649{
650 return send_and_recv(global, global->nl, msg, valid_handler,
651 valid_data);
652}
653
Dmitry Shmidt04949592012-07-19 12:16:46 -0700654
Dmitry Shmidt641185e2013-11-06 15:17:13 -0800655static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700656 struct nl_msg *msg,
657 int (*valid_handler)(struct nl_msg *, void *),
658 void *valid_data)
659{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800660 return send_and_recv(drv->global, drv->global->nl, msg,
661 valid_handler, valid_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700662}
663
664
665struct family_data {
666 const char *group;
667 int id;
668};
669
670
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700671static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss)
672{
673 if (bss->wdev_id_set)
674 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
675 else
676 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
677 return 0;
678
679nla_put_failure:
680 return -1;
681}
682
683
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684static int family_handler(struct nl_msg *msg, void *arg)
685{
686 struct family_data *res = arg;
687 struct nlattr *tb[CTRL_ATTR_MAX + 1];
688 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
689 struct nlattr *mcgrp;
690 int i;
691
692 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
693 genlmsg_attrlen(gnlh, 0), NULL);
694 if (!tb[CTRL_ATTR_MCAST_GROUPS])
695 return NL_SKIP;
696
697 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
698 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
699 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
700 nla_len(mcgrp), NULL);
701 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
702 !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
703 os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
704 res->group,
705 nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
706 continue;
707 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
708 break;
709 };
710
711 return NL_SKIP;
712}
713
714
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800715static int nl_get_multicast_id(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716 const char *family, const char *group)
717{
718 struct nl_msg *msg;
719 int ret = -1;
720 struct family_data res = { group, -ENOENT };
721
722 msg = nlmsg_alloc();
723 if (!msg)
724 return -ENOMEM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800725 genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700726 0, 0, CTRL_CMD_GETFAMILY, 0);
727 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
728
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800729 ret = send_and_recv_msgs_global(global, msg, family_handler, &res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730 msg = NULL;
731 if (ret == 0)
732 ret = res.id;
733
734nla_put_failure:
735 nlmsg_free(msg);
736 return ret;
737}
738
739
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800740static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
741 struct nl_msg *msg, int flags, uint8_t cmd)
742{
743 return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
744 0, flags, cmd, 0);
745}
746
747
748struct wiphy_idx_data {
749 int wiphy_idx;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700750 enum nl80211_iftype nlmode;
751 u8 *macaddr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800752};
753
754
755static int netdev_info_handler(struct nl_msg *msg, void *arg)
756{
757 struct nlattr *tb[NL80211_ATTR_MAX + 1];
758 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
759 struct wiphy_idx_data *info = arg;
760
761 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
762 genlmsg_attrlen(gnlh, 0), NULL);
763
764 if (tb[NL80211_ATTR_WIPHY])
765 info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
766
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700767 if (tb[NL80211_ATTR_IFTYPE])
768 info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
769
770 if (tb[NL80211_ATTR_MAC] && info->macaddr)
771 os_memcpy(info->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
772 ETH_ALEN);
773
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800774 return NL_SKIP;
775}
776
777
778static int nl80211_get_wiphy_index(struct i802_bss *bss)
779{
780 struct nl_msg *msg;
781 struct wiphy_idx_data data = {
782 .wiphy_idx = -1,
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700783 .macaddr = NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800784 };
785
786 msg = nlmsg_alloc();
787 if (!msg)
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700788 return NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800789
790 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
791
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700792 if (nl80211_set_iface_id(msg, bss) < 0)
793 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800794
795 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
796 return data.wiphy_idx;
797 msg = NULL;
798nla_put_failure:
799 nlmsg_free(msg);
800 return -1;
801}
802
803
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700804static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
805{
806 struct nl_msg *msg;
807 struct wiphy_idx_data data = {
808 .nlmode = NL80211_IFTYPE_UNSPECIFIED,
809 .macaddr = NULL,
810 };
811
812 msg = nlmsg_alloc();
813 if (!msg)
814 return -1;
815
816 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
817
818 if (nl80211_set_iface_id(msg, bss) < 0)
819 goto nla_put_failure;
820
821 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
822 return data.nlmode;
823 msg = NULL;
824nla_put_failure:
825 nlmsg_free(msg);
826 return NL80211_IFTYPE_UNSPECIFIED;
827}
828
829
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700830static int nl80211_get_macaddr(struct i802_bss *bss)
831{
832 struct nl_msg *msg;
833 struct wiphy_idx_data data = {
834 .macaddr = bss->addr,
835 };
836
837 msg = nlmsg_alloc();
838 if (!msg)
839 return NL80211_IFTYPE_UNSPECIFIED;
840
841 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
842 if (nl80211_set_iface_id(msg, bss) < 0)
843 goto nla_put_failure;
844
845 return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data);
846
847nla_put_failure:
848 nlmsg_free(msg);
849 return NL80211_IFTYPE_UNSPECIFIED;
850}
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700851
852
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800853static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
854 struct nl80211_wiphy_data *w)
855{
856 struct nl_msg *msg;
857 int ret = -1;
858
859 msg = nlmsg_alloc();
860 if (!msg)
861 return -1;
862
863 nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS);
864
865 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx);
866
867 ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);
868 msg = NULL;
869 if (ret) {
870 wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
871 "failed: ret=%d (%s)",
872 ret, strerror(-ret));
873 goto nla_put_failure;
874 }
875 ret = 0;
876nla_put_failure:
877 nlmsg_free(msg);
878 return ret;
879}
880
881
882static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle)
883{
884 struct nl80211_wiphy_data *w = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700885 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800886
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800887 wpa_printf(MSG_EXCESSIVE, "nl80211: Beacon event message available");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800888
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700889 res = nl_recvmsgs(handle, w->nl_cb);
890 if (res) {
891 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
892 __func__, res);
893 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800894}
895
896
897static int process_beacon_event(struct nl_msg *msg, void *arg)
898{
899 struct nl80211_wiphy_data *w = arg;
900 struct wpa_driver_nl80211_data *drv;
901 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
902 struct nlattr *tb[NL80211_ATTR_MAX + 1];
903 union wpa_event_data event;
904
905 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
906 genlmsg_attrlen(gnlh, 0), NULL);
907
908 if (gnlh->cmd != NL80211_CMD_FRAME) {
909 wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)",
910 gnlh->cmd);
911 return NL_SKIP;
912 }
913
914 if (!tb[NL80211_ATTR_FRAME])
915 return NL_SKIP;
916
917 dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data,
918 wiphy_list) {
919 os_memset(&event, 0, sizeof(event));
920 event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);
921 event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);
922 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
923 }
924
925 return NL_SKIP;
926}
927
928
929static struct nl80211_wiphy_data *
930nl80211_get_wiphy_data_ap(struct i802_bss *bss)
931{
932 static DEFINE_DL_LIST(nl80211_wiphys);
933 struct nl80211_wiphy_data *w;
934 int wiphy_idx, found = 0;
935 struct i802_bss *tmp_bss;
936
937 if (bss->wiphy_data != NULL)
938 return bss->wiphy_data;
939
940 wiphy_idx = nl80211_get_wiphy_index(bss);
941
942 dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) {
943 if (w->wiphy_idx == wiphy_idx)
944 goto add;
945 }
946
947 /* alloc new one */
948 w = os_zalloc(sizeof(*w));
949 if (w == NULL)
950 return NULL;
951 w->wiphy_idx = wiphy_idx;
952 dl_list_init(&w->bsss);
953 dl_list_init(&w->drvs);
954
955 w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
956 if (!w->nl_cb) {
957 os_free(w);
958 return NULL;
959 }
960 nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
961 nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,
962 w);
963
964 w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
965 "wiphy beacons");
966 if (w->nl_beacons == NULL) {
967 os_free(w);
968 return NULL;
969 }
970
971 if (nl80211_register_beacons(bss->drv, w)) {
972 nl_destroy_handles(&w->nl_beacons);
973 os_free(w);
974 return NULL;
975 }
976
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700977 nl80211_register_eloop_read(&w->nl_beacons, nl80211_recv_beacons, w);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800978
979 dl_list_add(&nl80211_wiphys, &w->list);
980
981add:
982 /* drv entry for this bss already there? */
983 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
984 if (tmp_bss->drv == bss->drv) {
985 found = 1;
986 break;
987 }
988 }
989 /* if not add it */
990 if (!found)
991 dl_list_add(&w->drvs, &bss->drv->wiphy_list);
992
993 dl_list_add(&w->bsss, &bss->wiphy_list);
994 bss->wiphy_data = w;
995 return w;
996}
997
998
999static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
1000{
1001 struct nl80211_wiphy_data *w = bss->wiphy_data;
1002 struct i802_bss *tmp_bss;
1003 int found = 0;
1004
1005 if (w == NULL)
1006 return;
1007 bss->wiphy_data = NULL;
1008 dl_list_del(&bss->wiphy_list);
1009
1010 /* still any for this drv present? */
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 remove it */
1018 if (!found)
1019 dl_list_del(&bss->drv->wiphy_list);
1020
1021 if (!dl_list_empty(&w->bsss))
1022 return;
1023
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001024 nl80211_destroy_eloop_handle(&w->nl_beacons);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001025
1026 nl_cb_put(w->nl_cb);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001027 dl_list_del(&w->list);
1028 os_free(w);
1029}
1030
1031
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
1033{
1034 struct i802_bss *bss = priv;
1035 struct wpa_driver_nl80211_data *drv = bss->drv;
1036 if (!drv->associated)
1037 return -1;
1038 os_memcpy(bssid, drv->bssid, ETH_ALEN);
1039 return 0;
1040}
1041
1042
1043static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
1044{
1045 struct i802_bss *bss = priv;
1046 struct wpa_driver_nl80211_data *drv = bss->drv;
1047 if (!drv->associated)
1048 return -1;
1049 os_memcpy(ssid, drv->ssid, drv->ssid_len);
1050 return drv->ssid_len;
1051}
1052
1053
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001054static void wpa_driver_nl80211_event_newlink(
1055 struct wpa_driver_nl80211_data *drv, char *ifname)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001056{
1057 union wpa_event_data event;
1058
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001059 if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
1060 if (if_nametoindex(drv->first_bss->ifname) == 0) {
1061 wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
1062 drv->first_bss->ifname);
1063 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001064 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001065 if (!drv->if_removed)
1066 return;
1067 wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event",
1068 drv->first_bss->ifname);
1069 drv->if_removed = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070 }
1071
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001072 os_memset(&event, 0, sizeof(event));
1073 os_strlcpy(event.interface_status.ifname, ifname,
1074 sizeof(event.interface_status.ifname));
1075 event.interface_status.ievent = EVENT_INTERFACE_ADDED;
1076 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
1077}
1078
1079
1080static void wpa_driver_nl80211_event_dellink(
1081 struct wpa_driver_nl80211_data *drv, char *ifname)
1082{
1083 union wpa_event_data event;
1084
1085 if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
1086 if (drv->if_removed) {
1087 wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
1088 ifname);
1089 return;
1090 }
1091 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1",
1092 ifname);
1093 drv->if_removed = 1;
1094 } else {
1095 wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed",
1096 ifname);
1097 }
1098
1099 os_memset(&event, 0, sizeof(event));
1100 os_strlcpy(event.interface_status.ifname, ifname,
1101 sizeof(event.interface_status.ifname));
1102 event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001103 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
1104}
1105
1106
1107static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
1108 u8 *buf, size_t len)
1109{
1110 int attrlen, rta_len;
1111 struct rtattr *attr;
1112
1113 attrlen = len;
1114 attr = (struct rtattr *) buf;
1115
1116 rta_len = RTA_ALIGN(sizeof(struct rtattr));
1117 while (RTA_OK(attr, attrlen)) {
1118 if (attr->rta_type == IFLA_IFNAME) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001119 if (os_strcmp(((char *) attr) + rta_len,
1120 drv->first_bss->ifname) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121 return 1;
1122 else
1123 break;
1124 }
1125 attr = RTA_NEXT(attr, attrlen);
1126 }
1127
1128 return 0;
1129}
1130
1131
1132static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
1133 int ifindex, u8 *buf, size_t len)
1134{
1135 if (drv->ifindex == ifindex)
1136 return 1;
1137
1138 if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001139 wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
1140 "interface");
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001141 wpa_driver_nl80211_finish_drv_init(drv, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142 return 1;
1143 }
1144
1145 return 0;
1146}
1147
1148
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001149static struct wpa_driver_nl80211_data *
1150nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
1151{
1152 struct wpa_driver_nl80211_data *drv;
1153 dl_list_for_each(drv, &global->interfaces,
1154 struct wpa_driver_nl80211_data, list) {
1155 if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
1156 have_ifidx(drv, idx))
1157 return drv;
1158 }
1159 return NULL;
1160}
1161
1162
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001163static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
1164 struct ifinfomsg *ifi,
1165 u8 *buf, size_t len)
1166{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001167 struct nl80211_global *global = ctx;
1168 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001169 int attrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170 struct rtattr *attr;
1171 u32 brid = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001172 char namebuf[IFNAMSIZ];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001173 char ifname[IFNAMSIZ + 1];
1174 char extra[100], *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001175
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001176 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
1177 if (!drv) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001178 wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d",
1179 ifi->ifi_index);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001180 return;
1181 }
1182
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001183 extra[0] = '\0';
1184 pos = extra;
1185 end = pos + sizeof(extra);
1186 ifname[0] = '\0';
1187
1188 attrlen = len;
1189 attr = (struct rtattr *) buf;
1190 while (RTA_OK(attr, attrlen)) {
1191 switch (attr->rta_type) {
1192 case IFLA_IFNAME:
1193 if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
1194 break;
1195 os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
1196 ifname[RTA_PAYLOAD(attr)] = '\0';
1197 break;
1198 case IFLA_MASTER:
1199 brid = nla_get_u32((struct nlattr *) attr);
1200 pos += os_snprintf(pos, end - pos, " master=%u", brid);
1201 break;
1202 case IFLA_WIRELESS:
1203 pos += os_snprintf(pos, end - pos, " wext");
1204 break;
1205 case IFLA_OPERSTATE:
1206 pos += os_snprintf(pos, end - pos, " operstate=%u",
1207 nla_get_u32((struct nlattr *) attr));
1208 break;
1209 case IFLA_LINKMODE:
1210 pos += os_snprintf(pos, end - pos, " linkmode=%u",
1211 nla_get_u32((struct nlattr *) attr));
1212 break;
1213 }
1214 attr = RTA_NEXT(attr, attrlen);
1215 }
1216 extra[sizeof(extra) - 1] = '\0';
1217
1218 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_flags=0x%x (%s%s%s%s)",
1219 ifi->ifi_index, ifname, extra, ifi->ifi_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001220 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
1221 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
1222 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
1223 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
1224
1225 if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001226 if (if_indextoname(ifi->ifi_index, namebuf) &&
1227 linux_iface_up(drv->global->ioctl_sock,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001228 drv->first_bss->ifname) > 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001229 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
1230 "event since interface %s is up", namebuf);
1231 return;
1232 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001233 wpa_printf(MSG_DEBUG, "nl80211: Interface down");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001234 if (drv->ignore_if_down_event) {
1235 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
1236 "event generated by mode change");
1237 drv->ignore_if_down_event = 0;
1238 } else {
1239 drv->if_disabled = 1;
1240 wpa_supplicant_event(drv->ctx,
1241 EVENT_INTERFACE_DISABLED, NULL);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08001242
1243 /*
1244 * Try to get drv again, since it may be removed as
1245 * part of the EVENT_INTERFACE_DISABLED handling for
1246 * dynamic interfaces
1247 */
1248 drv = nl80211_find_drv(global, ifi->ifi_index,
1249 buf, len);
1250 if (!drv)
1251 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001252 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001253 }
1254
1255 if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001256 if (if_indextoname(ifi->ifi_index, namebuf) &&
1257 linux_iface_up(drv->global->ioctl_sock,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001258 drv->first_bss->ifname) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001259 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1260 "event since interface %s is down",
1261 namebuf);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001262 } else if (if_nametoindex(drv->first_bss->ifname) == 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001263 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1264 "event since interface %s does not exist",
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001265 drv->first_bss->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001266 } else if (drv->if_removed) {
1267 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1268 "event since interface %s is marked "
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001269 "removed", drv->first_bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001270 } else {
1271 wpa_printf(MSG_DEBUG, "nl80211: Interface up");
1272 drv->if_disabled = 0;
1273 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
1274 NULL);
1275 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001276 }
1277
1278 /*
1279 * Some drivers send the association event before the operup event--in
1280 * this case, lifting operstate in wpa_driver_nl80211_set_operstate()
1281 * fails. This will hit us when wpa_supplicant does not need to do
1282 * IEEE 802.1X authentication
1283 */
1284 if (drv->operstate == 1 &&
1285 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001286 !(ifi->ifi_flags & IFF_RUNNING)) {
1287 wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001288 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001289 -1, IF_OPER_UP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001290 }
1291
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001292 if (ifname[0])
1293 wpa_driver_nl80211_event_newlink(drv, ifname);
1294
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001295 if (ifi->ifi_family == AF_BRIDGE && brid) {
1296 /* device has been added to bridge */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001297 if_indextoname(brid, namebuf);
1298 wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
1299 brid, namebuf);
1300 add_ifidx(drv, brid);
1301 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001302}
1303
1304
1305static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
1306 struct ifinfomsg *ifi,
1307 u8 *buf, size_t len)
1308{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001309 struct nl80211_global *global = ctx;
1310 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001311 int attrlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312 struct rtattr *attr;
1313 u32 brid = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001314 char ifname[IFNAMSIZ + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001316 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
1317 if (!drv) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001318 wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d",
1319 ifi->ifi_index);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001320 return;
1321 }
1322
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001323 ifname[0] = '\0';
1324
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001325 attrlen = len;
1326 attr = (struct rtattr *) buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001327 while (RTA_OK(attr, attrlen)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001328 switch (attr->rta_type) {
1329 case IFLA_IFNAME:
1330 if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
1331 break;
1332 os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
1333 ifname[RTA_PAYLOAD(attr)] = '\0';
1334 break;
1335 case IFLA_MASTER:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001336 brid = nla_get_u32((struct nlattr *) attr);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001337 break;
1338 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001339 attr = RTA_NEXT(attr, attrlen);
1340 }
1341
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001342 if (ifname[0])
1343 wpa_driver_nl80211_event_dellink(drv, ifname);
1344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345 if (ifi->ifi_family == AF_BRIDGE && brid) {
1346 /* device has been removed from bridge */
1347 char namebuf[IFNAMSIZ];
1348 if_indextoname(brid, namebuf);
1349 wpa_printf(MSG_DEBUG, "nl80211: Remove ifindex %u for bridge "
1350 "%s", brid, namebuf);
1351 del_ifidx(drv, brid);
1352 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353}
1354
1355
1356static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
1357 const u8 *frame, size_t len)
1358{
1359 const struct ieee80211_mgmt *mgmt;
1360 union wpa_event_data event;
1361
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001362 wpa_printf(MSG_DEBUG, "nl80211: Authenticate event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363 mgmt = (const struct ieee80211_mgmt *) frame;
1364 if (len < 24 + sizeof(mgmt->u.auth)) {
1365 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1366 "frame");
1367 return;
1368 }
1369
1370 os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001371 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001372 os_memset(&event, 0, sizeof(event));
1373 os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
1374 event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001375 event.auth.auth_transaction =
1376 le_to_host16(mgmt->u.auth.auth_transaction);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001377 event.auth.status_code = le_to_host16(mgmt->u.auth.status_code);
1378 if (len > 24 + sizeof(mgmt->u.auth)) {
1379 event.auth.ies = mgmt->u.auth.variable;
1380 event.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);
1381 }
1382
1383 wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);
1384}
1385
1386
Jouni Malinen87fd2792011-05-16 18:35:42 +03001387static unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
1388{
1389 struct nl_msg *msg;
1390 int ret;
1391 struct nl80211_bss_info_arg arg;
1392
1393 os_memset(&arg, 0, sizeof(arg));
1394 msg = nlmsg_alloc();
1395 if (!msg)
1396 goto nla_put_failure;
1397
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001398 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Jouni Malinen87fd2792011-05-16 18:35:42 +03001399 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
1400
1401 arg.drv = drv;
1402 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
1403 msg = NULL;
1404 if (ret == 0) {
1405 wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
1406 "associated BSS from scan results: %u MHz",
1407 arg.assoc_freq);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07001408 if (arg.assoc_freq)
1409 drv->assoc_freq = arg.assoc_freq;
1410 return drv->assoc_freq;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001411 }
1412 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
1413 "(%s)", ret, strerror(-ret));
1414nla_put_failure:
1415 nlmsg_free(msg);
1416 return drv->assoc_freq;
1417}
1418
1419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
1421 const u8 *frame, size_t len)
1422{
1423 const struct ieee80211_mgmt *mgmt;
1424 union wpa_event_data event;
1425 u16 status;
1426
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001427 wpa_printf(MSG_DEBUG, "nl80211: Associate event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001428 mgmt = (const struct ieee80211_mgmt *) frame;
1429 if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
1430 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1431 "frame");
1432 return;
1433 }
1434
1435 status = le_to_host16(mgmt->u.assoc_resp.status_code);
1436 if (status != WLAN_STATUS_SUCCESS) {
1437 os_memset(&event, 0, sizeof(event));
1438 event.assoc_reject.bssid = mgmt->bssid;
1439 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
1440 event.assoc_reject.resp_ies =
1441 (u8 *) mgmt->u.assoc_resp.variable;
1442 event.assoc_reject.resp_ies_len =
1443 len - 24 - sizeof(mgmt->u.assoc_resp);
1444 }
1445 event.assoc_reject.status_code = status;
1446
1447 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
1448 return;
1449 }
1450
1451 drv->associated = 1;
1452 os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001453 os_memcpy(drv->prev_bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001454
1455 os_memset(&event, 0, sizeof(event));
1456 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
1457 event.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;
1458 event.assoc_info.resp_ies_len =
1459 len - 24 - sizeof(mgmt->u.assoc_resp);
1460 }
1461
1462 event.assoc_info.freq = drv->assoc_freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001463
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001464 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
1465}
1466
1467
1468static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
1469 enum nl80211_commands cmd, struct nlattr *status,
1470 struct nlattr *addr, struct nlattr *req_ie,
1471 struct nlattr *resp_ie)
1472{
1473 union wpa_event_data event;
1474
1475 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
1476 /*
1477 * Avoid reporting two association events that would confuse
1478 * the core code.
1479 */
1480 wpa_printf(MSG_DEBUG, "nl80211: Ignore connect event (cmd=%d) "
1481 "when using userspace SME", cmd);
1482 return;
1483 }
1484
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001485 if (cmd == NL80211_CMD_CONNECT)
1486 wpa_printf(MSG_DEBUG, "nl80211: Connect event");
1487 else if (cmd == NL80211_CMD_ROAM)
1488 wpa_printf(MSG_DEBUG, "nl80211: Roam event");
1489
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001490 os_memset(&event, 0, sizeof(event));
1491 if (cmd == NL80211_CMD_CONNECT &&
1492 nla_get_u16(status) != WLAN_STATUS_SUCCESS) {
1493 if (addr)
1494 event.assoc_reject.bssid = nla_data(addr);
1495 if (resp_ie) {
1496 event.assoc_reject.resp_ies = nla_data(resp_ie);
1497 event.assoc_reject.resp_ies_len = nla_len(resp_ie);
1498 }
1499 event.assoc_reject.status_code = nla_get_u16(status);
1500 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
1501 return;
1502 }
1503
1504 drv->associated = 1;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001505 if (addr) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001506 os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001507 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
1508 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001509
1510 if (req_ie) {
1511 event.assoc_info.req_ies = nla_data(req_ie);
1512 event.assoc_info.req_ies_len = nla_len(req_ie);
1513 }
1514 if (resp_ie) {
1515 event.assoc_info.resp_ies = nla_data(resp_ie);
1516 event.assoc_info.resp_ies_len = nla_len(resp_ie);
1517 }
1518
Jouni Malinen87fd2792011-05-16 18:35:42 +03001519 event.assoc_info.freq = nl80211_get_assoc_freq(drv);
1520
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001521 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
1522}
1523
1524
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001525static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001526 struct nlattr *reason, struct nlattr *addr,
1527 struct nlattr *by_ap)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001528{
1529 union wpa_event_data data;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001530 unsigned int locally_generated = by_ap == NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001531
1532 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
1533 /*
1534 * Avoid reporting two disassociation events that could
1535 * confuse the core code.
1536 */
1537 wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
1538 "event when using userspace SME");
1539 return;
1540 }
1541
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001542 if (drv->ignore_next_local_disconnect) {
1543 drv->ignore_next_local_disconnect = 0;
1544 if (locally_generated) {
1545 wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
1546 "event triggered during reassociation");
1547 return;
1548 }
1549 wpa_printf(MSG_WARNING, "nl80211: Was expecting local "
1550 "disconnect but got another disconnect "
1551 "event first");
1552 }
1553
1554 wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001555 nl80211_mark_disconnected(drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001556 os_memset(&data, 0, sizeof(data));
1557 if (reason)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001558 data.deauth_info.reason_code = nla_get_u16(reason);
1559 data.deauth_info.locally_generated = by_ap == NULL;
1560 wpa_supplicant_event(drv->ctx, EVENT_DEAUTH, &data);
1561}
1562
1563
Dmitry Shmidt97672262014-02-03 13:02:54 -08001564static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
1565{
1566 int freq1 = 0;
1567
1568 switch (convert2width(width)) {
1569 case CHAN_WIDTH_20_NOHT:
1570 case CHAN_WIDTH_20:
1571 return 0;
1572 case CHAN_WIDTH_40:
1573 freq1 = cf1 - 10;
1574 break;
1575 case CHAN_WIDTH_80:
1576 freq1 = cf1 - 30;
1577 break;
1578 case CHAN_WIDTH_160:
1579 freq1 = cf1 - 70;
1580 break;
1581 case CHAN_WIDTH_UNKNOWN:
1582 case CHAN_WIDTH_80P80:
1583 /* FIXME: implement this */
1584 return 0;
1585 }
1586
1587 return (abs(freq - freq1) / 20) % 2 == 0 ? 1 : -1;
1588}
1589
1590
Dmitry Shmidt04949592012-07-19 12:16:46 -07001591static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001592 struct nlattr *ifindex, struct nlattr *freq,
1593 struct nlattr *type, struct nlattr *bw,
1594 struct nlattr *cf1, struct nlattr *cf2)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001595{
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001596 struct i802_bss *bss;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001597 union wpa_event_data data;
1598 int ht_enabled = 1;
1599 int chan_offset = 0;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001600 int ifidx;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001601
1602 wpa_printf(MSG_DEBUG, "nl80211: Channel switch event");
1603
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001604 if (!freq)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001605 return;
1606
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001607 ifidx = nla_get_u32(ifindex);
1608 for (bss = drv->first_bss; bss; bss = bss->next)
1609 if (bss->ifindex == ifidx)
1610 break;
1611
1612 if (bss == NULL) {
1613 wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch, ignoring",
1614 ifidx);
1615 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001616 }
1617
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001618 if (type) {
1619 switch (nla_get_u32(type)) {
1620 case NL80211_CHAN_NO_HT:
1621 ht_enabled = 0;
1622 break;
1623 case NL80211_CHAN_HT20:
1624 break;
1625 case NL80211_CHAN_HT40PLUS:
1626 chan_offset = 1;
1627 break;
1628 case NL80211_CHAN_HT40MINUS:
1629 chan_offset = -1;
1630 break;
1631 }
Dmitry Shmidt97672262014-02-03 13:02:54 -08001632 } else if (bw && cf1) {
1633 /* This can happen for example with VHT80 ch switch */
1634 chan_offset = calculate_chan_offset(nla_get_u32(bw),
1635 nla_get_u32(freq),
1636 nla_get_u32(cf1),
1637 cf2 ? nla_get_u32(cf2) : 0);
1638 } else {
1639 wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information - following channel definition calculations may fail");
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001640 }
1641
1642 os_memset(&data, 0, sizeof(data));
Dmitry Shmidt04949592012-07-19 12:16:46 -07001643 data.ch_switch.freq = nla_get_u32(freq);
1644 data.ch_switch.ht_enabled = ht_enabled;
1645 data.ch_switch.ch_offset = chan_offset;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001646 if (bw)
1647 data.ch_switch.ch_width = convert2width(nla_get_u32(bw));
1648 if (cf1)
1649 data.ch_switch.cf1 = nla_get_u32(cf1);
1650 if (cf2)
1651 data.ch_switch.cf2 = nla_get_u32(cf2);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001652
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001653 bss->freq = data.ch_switch.freq;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001654
Dmitry Shmidt04949592012-07-19 12:16:46 -07001655 wpa_supplicant_event(drv->ctx, EVENT_CH_SWITCH, &data);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001656}
1657
1658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001659static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
1660 enum nl80211_commands cmd, struct nlattr *addr)
1661{
1662 union wpa_event_data event;
1663 enum wpa_event_type ev;
1664
1665 if (nla_len(addr) != ETH_ALEN)
1666 return;
1667
1668 wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR,
1669 cmd, MAC2STR((u8 *) nla_data(addr)));
1670
1671 if (cmd == NL80211_CMD_AUTHENTICATE)
1672 ev = EVENT_AUTH_TIMED_OUT;
1673 else if (cmd == NL80211_CMD_ASSOCIATE)
1674 ev = EVENT_ASSOC_TIMED_OUT;
1675 else
1676 return;
1677
1678 os_memset(&event, 0, sizeof(event));
1679 os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);
1680 wpa_supplicant_event(drv->ctx, ev, &event);
1681}
1682
1683
1684static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt04949592012-07-19 12:16:46 -07001685 struct nlattr *freq, struct nlattr *sig,
1686 const u8 *frame, size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001687{
1688 const struct ieee80211_mgmt *mgmt;
1689 union wpa_event_data event;
1690 u16 fc, stype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001691 int ssi_signal = 0;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001692 int rx_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001693
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001694 wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001695 mgmt = (const struct ieee80211_mgmt *) frame;
1696 if (len < 24) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001697 wpa_printf(MSG_DEBUG, "nl80211: Too short management frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001698 return;
1699 }
1700
1701 fc = le_to_host16(mgmt->frame_control);
1702 stype = WLAN_FC_GET_STYPE(fc);
1703
Dmitry Shmidt04949592012-07-19 12:16:46 -07001704 if (sig)
1705 ssi_signal = (s32) nla_get_u32(sig);
1706
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001707 os_memset(&event, 0, sizeof(event));
1708 if (freq) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001709 event.rx_mgmt.freq = nla_get_u32(freq);
1710 rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001711 }
Dmitry Shmidt56052862013-10-04 10:23:25 -07001712 wpa_printf(MSG_DEBUG,
1713 "nl80211: RX frame freq=%d ssi_signal=%d stype=%u len=%u",
1714 rx_freq, ssi_signal, stype, (unsigned int) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001715 event.rx_mgmt.frame = frame;
1716 event.rx_mgmt.frame_len = len;
1717 event.rx_mgmt.ssi_signal = ssi_signal;
1718 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001719}
1720
1721
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001722static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
1723 struct nlattr *cookie, const u8 *frame,
1724 size_t len, struct nlattr *ack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725{
1726 union wpa_event_data event;
1727 const struct ieee80211_hdr *hdr;
1728 u16 fc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001729
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001730 wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001731 if (!is_ap_interface(drv->nlmode)) {
1732 u64 cookie_val;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001733
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001734 if (!cookie)
1735 return;
1736
1737 cookie_val = nla_get_u64(cookie);
1738 wpa_printf(MSG_DEBUG, "nl80211: Action TX status:"
1739 " cookie=0%llx%s (ack=%d)",
1740 (long long unsigned int) cookie_val,
1741 cookie_val == drv->send_action_cookie ?
1742 " (match)" : " (unknown)", ack != NULL);
1743 if (cookie_val != drv->send_action_cookie)
1744 return;
1745 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746
1747 hdr = (const struct ieee80211_hdr *) frame;
1748 fc = le_to_host16(hdr->frame_control);
1749
1750 os_memset(&event, 0, sizeof(event));
1751 event.tx_status.type = WLAN_FC_GET_TYPE(fc);
1752 event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
1753 event.tx_status.dst = hdr->addr1;
1754 event.tx_status.data = frame;
1755 event.tx_status.data_len = len;
1756 event.tx_status.ack = ack != NULL;
1757 wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
1758}
1759
1760
1761static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
1762 enum wpa_event_type type,
1763 const u8 *frame, size_t len)
1764{
1765 const struct ieee80211_mgmt *mgmt;
1766 union wpa_event_data event;
1767 const u8 *bssid = NULL;
1768 u16 reason_code = 0;
1769
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001770 if (type == EVENT_DEAUTH)
1771 wpa_printf(MSG_DEBUG, "nl80211: Deauthenticate event");
1772 else
1773 wpa_printf(MSG_DEBUG, "nl80211: Disassociate event");
1774
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001775 mgmt = (const struct ieee80211_mgmt *) frame;
1776 if (len >= 24) {
1777 bssid = mgmt->bssid;
1778
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001779 if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
1780 !drv->associated &&
1781 os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
1782 os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
1783 os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
1784 /*
1785 * Avoid issues with some roaming cases where
1786 * disconnection event for the old AP may show up after
1787 * we have started connection with the new AP.
1788 */
1789 wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
1790 MAC2STR(bssid),
1791 MAC2STR(drv->auth_attempt_bssid));
1792 return;
1793 }
1794
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001795 if (drv->associated != 0 &&
1796 os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
1797 os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
1798 /*
1799 * We have presumably received this deauth as a
1800 * response to a clear_state_mismatch() outgoing
1801 * deauth. Don't let it take us offline!
1802 */
1803 wpa_printf(MSG_DEBUG, "nl80211: Deauth received "
1804 "from Unknown BSSID " MACSTR " -- ignoring",
1805 MAC2STR(bssid));
1806 return;
1807 }
1808 }
1809
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001810 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811 os_memset(&event, 0, sizeof(event));
1812
1813 /* Note: Same offset for Reason Code in both frame subtypes */
1814 if (len >= 24 + sizeof(mgmt->u.deauth))
1815 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1816
1817 if (type == EVENT_DISASSOC) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001818 event.disassoc_info.locally_generated =
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001819 !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001820 event.disassoc_info.addr = bssid;
1821 event.disassoc_info.reason_code = reason_code;
1822 if (frame + len > mgmt->u.disassoc.variable) {
1823 event.disassoc_info.ie = mgmt->u.disassoc.variable;
1824 event.disassoc_info.ie_len = frame + len -
1825 mgmt->u.disassoc.variable;
1826 }
1827 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001828 event.deauth_info.locally_generated =
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001829 !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830 event.deauth_info.addr = bssid;
1831 event.deauth_info.reason_code = reason_code;
1832 if (frame + len > mgmt->u.deauth.variable) {
1833 event.deauth_info.ie = mgmt->u.deauth.variable;
1834 event.deauth_info.ie_len = frame + len -
1835 mgmt->u.deauth.variable;
1836 }
1837 }
1838
1839 wpa_supplicant_event(drv->ctx, type, &event);
1840}
1841
1842
1843static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv,
1844 enum wpa_event_type type,
1845 const u8 *frame, size_t len)
1846{
1847 const struct ieee80211_mgmt *mgmt;
1848 union wpa_event_data event;
1849 u16 reason_code = 0;
1850
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001851 if (type == EVENT_UNPROT_DEAUTH)
1852 wpa_printf(MSG_DEBUG, "nl80211: Unprot Deauthenticate event");
1853 else
1854 wpa_printf(MSG_DEBUG, "nl80211: Unprot Disassociate event");
1855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856 if (len < 24)
1857 return;
1858
1859 mgmt = (const struct ieee80211_mgmt *) frame;
1860
1861 os_memset(&event, 0, sizeof(event));
1862 /* Note: Same offset for Reason Code in both frame subtypes */
1863 if (len >= 24 + sizeof(mgmt->u.deauth))
1864 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1865
1866 if (type == EVENT_UNPROT_DISASSOC) {
1867 event.unprot_disassoc.sa = mgmt->sa;
1868 event.unprot_disassoc.da = mgmt->da;
1869 event.unprot_disassoc.reason_code = reason_code;
1870 } else {
1871 event.unprot_deauth.sa = mgmt->sa;
1872 event.unprot_deauth.da = mgmt->da;
1873 event.unprot_deauth.reason_code = reason_code;
1874 }
1875
1876 wpa_supplicant_event(drv->ctx, type, &event);
1877}
1878
1879
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001880static void mlme_event(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881 enum nl80211_commands cmd, struct nlattr *frame,
1882 struct nlattr *addr, struct nlattr *timed_out,
1883 struct nlattr *freq, struct nlattr *ack,
Dmitry Shmidt04949592012-07-19 12:16:46 -07001884 struct nlattr *cookie, struct nlattr *sig)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885{
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001886 struct wpa_driver_nl80211_data *drv = bss->drv;
1887 const u8 *data;
1888 size_t len;
1889
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001890 if (timed_out && addr) {
1891 mlme_timeout_event(drv, cmd, addr);
1892 return;
1893 }
1894
1895 if (frame == NULL) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001896 wpa_printf(MSG_DEBUG,
1897 "nl80211: MLME event %d (%s) without frame data",
1898 cmd, nl80211_command_to_string(cmd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001899 return;
1900 }
1901
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001902 data = nla_data(frame);
1903 len = nla_len(frame);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001904 if (len < 4 + 2 * ETH_ALEN) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001905 wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s("
1906 MACSTR ") - too short",
1907 cmd, nl80211_command_to_string(cmd), bss->ifname,
1908 MAC2STR(bss->addr));
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001909 return;
1910 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001911 wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s(" MACSTR
1912 ") A1=" MACSTR " A2=" MACSTR, cmd,
1913 nl80211_command_to_string(cmd), bss->ifname,
1914 MAC2STR(bss->addr), MAC2STR(data + 4),
1915 MAC2STR(data + 4 + ETH_ALEN));
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001916 if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) &&
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001917 os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 &&
1918 os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001919 wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
1920 "for foreign address", bss->ifname);
1921 return;
1922 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923 wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame",
1924 nla_data(frame), nla_len(frame));
1925
1926 switch (cmd) {
1927 case NL80211_CMD_AUTHENTICATE:
1928 mlme_event_auth(drv, nla_data(frame), nla_len(frame));
1929 break;
1930 case NL80211_CMD_ASSOCIATE:
1931 mlme_event_assoc(drv, nla_data(frame), nla_len(frame));
1932 break;
1933 case NL80211_CMD_DEAUTHENTICATE:
1934 mlme_event_deauth_disassoc(drv, EVENT_DEAUTH,
1935 nla_data(frame), nla_len(frame));
1936 break;
1937 case NL80211_CMD_DISASSOCIATE:
1938 mlme_event_deauth_disassoc(drv, EVENT_DISASSOC,
1939 nla_data(frame), nla_len(frame));
1940 break;
1941 case NL80211_CMD_FRAME:
Dmitry Shmidt04949592012-07-19 12:16:46 -07001942 mlme_event_mgmt(drv, freq, sig, nla_data(frame),
1943 nla_len(frame));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001944 break;
1945 case NL80211_CMD_FRAME_TX_STATUS:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001946 mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
1947 nla_len(frame), ack);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001948 break;
1949 case NL80211_CMD_UNPROT_DEAUTHENTICATE:
1950 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,
1951 nla_data(frame), nla_len(frame));
1952 break;
1953 case NL80211_CMD_UNPROT_DISASSOCIATE:
1954 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,
1955 nla_data(frame), nla_len(frame));
1956 break;
1957 default:
1958 break;
1959 }
1960}
1961
1962
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001963static void mlme_event_michael_mic_failure(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001964 struct nlattr *tb[])
1965{
1966 union wpa_event_data data;
1967
1968 wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure");
1969 os_memset(&data, 0, sizeof(data));
1970 if (tb[NL80211_ATTR_MAC]) {
1971 wpa_hexdump(MSG_DEBUG, "nl80211: Source MAC address",
1972 nla_data(tb[NL80211_ATTR_MAC]),
1973 nla_len(tb[NL80211_ATTR_MAC]));
1974 data.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);
1975 }
1976 if (tb[NL80211_ATTR_KEY_SEQ]) {
1977 wpa_hexdump(MSG_DEBUG, "nl80211: TSC",
1978 nla_data(tb[NL80211_ATTR_KEY_SEQ]),
1979 nla_len(tb[NL80211_ATTR_KEY_SEQ]));
1980 }
1981 if (tb[NL80211_ATTR_KEY_TYPE]) {
1982 enum nl80211_key_type key_type =
1983 nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);
1984 wpa_printf(MSG_DEBUG, "nl80211: Key Type %d", key_type);
1985 if (key_type == NL80211_KEYTYPE_PAIRWISE)
1986 data.michael_mic_failure.unicast = 1;
1987 } else
1988 data.michael_mic_failure.unicast = 1;
1989
1990 if (tb[NL80211_ATTR_KEY_IDX]) {
1991 u8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);
1992 wpa_printf(MSG_DEBUG, "nl80211: Key Id %d", key_id);
1993 }
1994
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001995 wpa_supplicant_event(bss->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001996}
1997
1998
1999static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
2000 struct nlattr *tb[])
2001{
2002 if (tb[NL80211_ATTR_MAC] == NULL) {
2003 wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
2004 "event");
2005 return;
2006 }
2007 os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 drv->associated = 1;
2010 wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined",
2011 MAC2STR(drv->bssid));
2012
2013 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
2014}
2015
2016
2017static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
2018 int cancel_event, struct nlattr *tb[])
2019{
2020 unsigned int freq, chan_type, duration;
2021 union wpa_event_data data;
2022 u64 cookie;
2023
2024 if (tb[NL80211_ATTR_WIPHY_FREQ])
2025 freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
2026 else
2027 freq = 0;
2028
2029 if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
2030 chan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
2031 else
2032 chan_type = 0;
2033
2034 if (tb[NL80211_ATTR_DURATION])
2035 duration = nla_get_u32(tb[NL80211_ATTR_DURATION]);
2036 else
2037 duration = 0;
2038
2039 if (tb[NL80211_ATTR_COOKIE])
2040 cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
2041 else
2042 cookie = 0;
2043
2044 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel event (cancel=%d "
2045 "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))",
2046 cancel_event, freq, chan_type, duration,
2047 (long long unsigned int) cookie,
2048 cookie == drv->remain_on_chan_cookie ? "match" : "unknown");
2049
2050 if (cookie != drv->remain_on_chan_cookie)
2051 return; /* not for us */
2052
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002053 if (cancel_event)
2054 drv->pending_remain_on_chan = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002055
2056 os_memset(&data, 0, sizeof(data));
2057 data.remain_on_channel.freq = freq;
2058 data.remain_on_channel.duration = duration;
2059 wpa_supplicant_event(drv->ctx, cancel_event ?
2060 EVENT_CANCEL_REMAIN_ON_CHANNEL :
2061 EVENT_REMAIN_ON_CHANNEL, &data);
2062}
2063
2064
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002065static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
2066 struct nlattr *tb[])
2067{
2068 union wpa_event_data data;
2069
2070 os_memset(&data, 0, sizeof(data));
2071
2072 if (tb[NL80211_ATTR_IE]) {
2073 data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
2074 data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
2075 }
2076
2077 if (tb[NL80211_ATTR_IE_RIC]) {
2078 data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
2079 data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
2080 }
2081
2082 if (tb[NL80211_ATTR_MAC])
2083 os_memcpy(data.ft_ies.target_ap,
2084 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2085
2086 wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
2087 MAC2STR(data.ft_ies.target_ap));
2088
2089 wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
2090}
2091
2092
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
2094 struct nlattr *tb[])
2095{
2096 union wpa_event_data event;
2097 struct nlattr *nl;
2098 int rem;
2099 struct scan_info *info;
2100#define MAX_REPORT_FREQS 50
2101 int freqs[MAX_REPORT_FREQS];
2102 int num_freqs = 0;
2103
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002104 if (drv->scan_for_auth) {
2105 drv->scan_for_auth = 0;
2106 wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
2107 "cfg80211 BSS entry");
2108 wpa_driver_nl80211_authenticate_retry(drv);
2109 return;
2110 }
2111
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002112 os_memset(&event, 0, sizeof(event));
2113 info = &event.scan_info;
2114 info->aborted = aborted;
2115
2116 if (tb[NL80211_ATTR_SCAN_SSIDS]) {
2117 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {
2118 struct wpa_driver_scan_ssid *s =
2119 &info->ssids[info->num_ssids];
2120 s->ssid = nla_data(nl);
2121 s->ssid_len = nla_len(nl);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002122 wpa_printf(MSG_DEBUG, "nl80211: Scan probed for SSID '%s'",
2123 wpa_ssid_txt(s->ssid, s->ssid_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002124 info->num_ssids++;
2125 if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
2126 break;
2127 }
2128 }
2129 if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002130 char msg[200], *pos, *end;
2131 int res;
2132
2133 pos = msg;
2134 end = pos + sizeof(msg);
2135 *pos = '\0';
2136
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)
2138 {
2139 freqs[num_freqs] = nla_get_u32(nl);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002140 res = os_snprintf(pos, end - pos, " %d",
2141 freqs[num_freqs]);
2142 if (res > 0 && end - pos > res)
2143 pos += res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002144 num_freqs++;
2145 if (num_freqs == MAX_REPORT_FREQS - 1)
2146 break;
2147 }
2148 info->freqs = freqs;
2149 info->num_freqs = num_freqs;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002150 wpa_printf(MSG_DEBUG, "nl80211: Scan included frequencies:%s",
2151 msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152 }
2153 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
2154}
2155
2156
2157static int get_link_signal(struct nl_msg *msg, void *arg)
2158{
2159 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2160 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2161 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
2162 static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
2163 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002164 [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002165 };
2166 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
2167 static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
2168 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
2169 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
2170 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
2171 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
2172 };
2173 struct wpa_signal_info *sig_change = arg;
2174
2175 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2176 genlmsg_attrlen(gnlh, 0), NULL);
2177 if (!tb[NL80211_ATTR_STA_INFO] ||
2178 nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
2179 tb[NL80211_ATTR_STA_INFO], policy))
2180 return NL_SKIP;
2181 if (!sinfo[NL80211_STA_INFO_SIGNAL])
2182 return NL_SKIP;
2183
2184 sig_change->current_signal =
2185 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
2186
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002187 if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
2188 sig_change->avg_signal =
2189 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
2190 else
2191 sig_change->avg_signal = 0;
2192
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002193 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
2194 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
2195 sinfo[NL80211_STA_INFO_TX_BITRATE],
2196 rate_policy)) {
2197 sig_change->current_txrate = 0;
2198 } else {
2199 if (rinfo[NL80211_RATE_INFO_BITRATE]) {
2200 sig_change->current_txrate =
2201 nla_get_u16(rinfo[
2202 NL80211_RATE_INFO_BITRATE]) * 100;
2203 }
2204 }
2205 }
2206
2207 return NL_SKIP;
2208}
2209
2210
2211static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
2212 struct wpa_signal_info *sig)
2213{
2214 struct nl_msg *msg;
2215
2216 sig->current_signal = -9999;
2217 sig->current_txrate = 0;
2218
2219 msg = nlmsg_alloc();
2220 if (!msg)
2221 return -ENOMEM;
2222
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002223 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002224
2225 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2226 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
2227
2228 return send_and_recv_msgs(drv, msg, get_link_signal, sig);
2229 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002230 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231 return -ENOBUFS;
2232}
2233
2234
2235static int get_link_noise(struct nl_msg *msg, void *arg)
2236{
2237 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2238 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2239 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
2240 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
2241 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
2242 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
2243 };
2244 struct wpa_signal_info *sig_change = arg;
2245
2246 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2247 genlmsg_attrlen(gnlh, 0), NULL);
2248
2249 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
2250 wpa_printf(MSG_DEBUG, "nl80211: survey data missing!");
2251 return NL_SKIP;
2252 }
2253
2254 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
2255 tb[NL80211_ATTR_SURVEY_INFO],
2256 survey_policy)) {
2257 wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested "
2258 "attributes!");
2259 return NL_SKIP;
2260 }
2261
2262 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
2263 return NL_SKIP;
2264
2265 if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
2266 sig_change->frequency)
2267 return NL_SKIP;
2268
2269 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
2270 return NL_SKIP;
2271
2272 sig_change->current_noise =
2273 (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
2274
2275 return NL_SKIP;
2276}
2277
2278
2279static int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
2280 struct wpa_signal_info *sig_change)
2281{
2282 struct nl_msg *msg;
2283
2284 sig_change->current_noise = 9999;
2285 sig_change->frequency = drv->assoc_freq;
2286
2287 msg = nlmsg_alloc();
2288 if (!msg)
2289 return -ENOMEM;
2290
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002291 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002292
2293 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2294
2295 return send_and_recv_msgs(drv, msg, get_link_noise, sig_change);
2296 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002297 nlmsg_free(msg);
2298 return -ENOBUFS;
2299}
2300
2301
2302static int get_noise_for_scan_results(struct nl_msg *msg, void *arg)
2303{
2304 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2305 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2306 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
2307 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
2308 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
2309 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
2310 };
2311 struct wpa_scan_results *scan_results = arg;
2312 struct wpa_scan_res *scan_res;
2313 size_t i;
2314
2315 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2316 genlmsg_attrlen(gnlh, 0), NULL);
2317
2318 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
2319 wpa_printf(MSG_DEBUG, "nl80211: Survey data missing");
2320 return NL_SKIP;
2321 }
2322
2323 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
2324 tb[NL80211_ATTR_SURVEY_INFO],
2325 survey_policy)) {
2326 wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested "
2327 "attributes");
2328 return NL_SKIP;
2329 }
2330
2331 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
2332 return NL_SKIP;
2333
2334 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
2335 return NL_SKIP;
2336
2337 for (i = 0; i < scan_results->num; ++i) {
2338 scan_res = scan_results->res[i];
2339 if (!scan_res)
2340 continue;
2341 if ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
2342 scan_res->freq)
2343 continue;
2344 if (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))
2345 continue;
2346 scan_res->noise = (s8)
2347 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
2348 scan_res->flags &= ~WPA_SCAN_NOISE_INVALID;
2349 }
2350
2351 return NL_SKIP;
2352}
2353
2354
2355static int nl80211_get_noise_for_scan_results(
2356 struct wpa_driver_nl80211_data *drv,
2357 struct wpa_scan_results *scan_res)
2358{
2359 struct nl_msg *msg;
2360
2361 msg = nlmsg_alloc();
2362 if (!msg)
2363 return -ENOMEM;
2364
2365 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
2366
2367 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2368
2369 return send_and_recv_msgs(drv, msg, get_noise_for_scan_results,
2370 scan_res);
2371 nla_put_failure:
2372 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373 return -ENOBUFS;
2374}
2375
2376
2377static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
2378 struct nlattr *tb[])
2379{
2380 static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
2381 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
2382 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
2383 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
2384 [NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },
2385 };
2386 struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
2387 enum nl80211_cqm_rssi_threshold_event event;
2388 union wpa_event_data ed;
2389 struct wpa_signal_info sig;
2390 int res;
2391
2392 if (tb[NL80211_ATTR_CQM] == NULL ||
2393 nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],
2394 cqm_policy)) {
2395 wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid CQM event");
2396 return;
2397 }
2398
2399 os_memset(&ed, 0, sizeof(ed));
2400
2401 if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {
2402 if (!tb[NL80211_ATTR_MAC])
2403 return;
2404 os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),
2405 ETH_ALEN);
2406 wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
2407 return;
2408 }
2409
2410 if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)
2411 return;
2412 event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
2413
2414 if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
2415 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
2416 "event: RSSI high");
2417 ed.signal_change.above_threshold = 1;
2418 } else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {
2419 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
2420 "event: RSSI low");
2421 ed.signal_change.above_threshold = 0;
2422 } else
2423 return;
2424
2425 res = nl80211_get_link_signal(drv, &sig);
2426 if (res == 0) {
2427 ed.signal_change.current_signal = sig.current_signal;
2428 ed.signal_change.current_txrate = sig.current_txrate;
2429 wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d",
2430 sig.current_signal, sig.current_txrate);
2431 }
2432
2433 res = nl80211_get_link_noise(drv, &sig);
2434 if (res == 0) {
2435 ed.signal_change.current_noise = sig.current_noise;
2436 wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm",
2437 sig.current_noise);
2438 }
2439
2440 wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);
2441}
2442
2443
2444static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
2445 struct nlattr **tb)
2446{
2447 u8 *addr;
2448 union wpa_event_data data;
2449
2450 if (tb[NL80211_ATTR_MAC] == NULL)
2451 return;
2452 addr = nla_data(tb[NL80211_ATTR_MAC]);
2453 wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr));
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002454
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002455 if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002456 u8 *ies = NULL;
2457 size_t ies_len = 0;
2458 if (tb[NL80211_ATTR_IE]) {
2459 ies = nla_data(tb[NL80211_ATTR_IE]);
2460 ies_len = nla_len(tb[NL80211_ATTR_IE]);
2461 }
2462 wpa_hexdump(MSG_DEBUG, "nl80211: Assoc Req IEs", ies, ies_len);
2463 drv_event_assoc(drv->ctx, addr, ies, ies_len, 0);
2464 return;
2465 }
2466
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002467 if (drv->nlmode != NL80211_IFTYPE_ADHOC)
2468 return;
2469
2470 os_memset(&data, 0, sizeof(data));
2471 os_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);
2472 wpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data);
2473}
2474
2475
2476static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
2477 struct nlattr **tb)
2478{
2479 u8 *addr;
2480 union wpa_event_data data;
2481
2482 if (tb[NL80211_ATTR_MAC] == NULL)
2483 return;
2484 addr = nla_data(tb[NL80211_ATTR_MAC]);
2485 wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR,
2486 MAC2STR(addr));
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002487
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002488 if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002489 drv_event_disassoc(drv->ctx, addr);
2490 return;
2491 }
2492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 if (drv->nlmode != NL80211_IFTYPE_ADHOC)
2494 return;
2495
2496 os_memset(&data, 0, sizeof(data));
2497 os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);
2498 wpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);
2499}
2500
2501
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002502static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data *drv,
2503 struct nlattr **tb)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002505 struct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];
2506 static struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {
2507 [NL80211_REKEY_DATA_KEK] = {
2508 .minlen = NL80211_KEK_LEN,
2509 .maxlen = NL80211_KEK_LEN,
2510 },
2511 [NL80211_REKEY_DATA_KCK] = {
2512 .minlen = NL80211_KCK_LEN,
2513 .maxlen = NL80211_KCK_LEN,
2514 },
2515 [NL80211_REKEY_DATA_REPLAY_CTR] = {
2516 .minlen = NL80211_REPLAY_CTR_LEN,
2517 .maxlen = NL80211_REPLAY_CTR_LEN,
2518 },
2519 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 union wpa_event_data data;
2521
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002522 if (!tb[NL80211_ATTR_MAC])
2523 return;
2524 if (!tb[NL80211_ATTR_REKEY_DATA])
2525 return;
2526 if (nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,
2527 tb[NL80211_ATTR_REKEY_DATA], rekey_policy))
2528 return;
2529 if (!rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])
2530 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002532 os_memset(&data, 0, sizeof(data));
2533 data.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);
2534 wpa_printf(MSG_DEBUG, "nl80211: Rekey offload event for BSSID " MACSTR,
2535 MAC2STR(data.driver_gtk_rekey.bssid));
2536 data.driver_gtk_rekey.replay_ctr =
2537 nla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);
2538 wpa_hexdump(MSG_DEBUG, "nl80211: Rekey offload - Replay Counter",
2539 data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);
2540 wpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);
2541}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002543
2544static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
2545 struct nlattr **tb)
2546{
2547 struct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];
2548 static struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {
2549 [NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },
2550 [NL80211_PMKSA_CANDIDATE_BSSID] = {
2551 .minlen = ETH_ALEN,
2552 .maxlen = ETH_ALEN,
2553 },
2554 [NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },
2555 };
2556 union wpa_event_data data;
2557
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002558 wpa_printf(MSG_DEBUG, "nl80211: PMKSA candidate event");
2559
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002560 if (!tb[NL80211_ATTR_PMKSA_CANDIDATE])
2561 return;
2562 if (nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,
2563 tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy))
2564 return;
2565 if (!cand[NL80211_PMKSA_CANDIDATE_INDEX] ||
2566 !cand[NL80211_PMKSA_CANDIDATE_BSSID])
2567 return;
2568
2569 os_memset(&data, 0, sizeof(data));
2570 os_memcpy(data.pmkid_candidate.bssid,
2571 nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);
2572 data.pmkid_candidate.index =
2573 nla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);
2574 data.pmkid_candidate.preauth =
2575 cand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;
2576 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
2577}
2578
2579
2580static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv,
2581 struct nlattr **tb)
2582{
2583 union wpa_event_data data;
2584
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002585 wpa_printf(MSG_DEBUG, "nl80211: Probe client event");
2586
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002587 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
2588 return;
2589
2590 os_memset(&data, 0, sizeof(data));
2591 os_memcpy(data.client_poll.addr,
2592 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2593
2594 wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
2595}
2596
2597
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002598static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
2599 struct nlattr **tb)
2600{
2601 union wpa_event_data data;
2602
2603 wpa_printf(MSG_DEBUG, "nl80211: TDLS operation event");
2604
2605 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_TDLS_OPERATION])
2606 return;
2607
2608 os_memset(&data, 0, sizeof(data));
2609 os_memcpy(data.tdls.peer, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2610 switch (nla_get_u8(tb[NL80211_ATTR_TDLS_OPERATION])) {
2611 case NL80211_TDLS_SETUP:
2612 wpa_printf(MSG_DEBUG, "nl80211: TDLS setup request for peer "
2613 MACSTR, MAC2STR(data.tdls.peer));
2614 data.tdls.oper = TDLS_REQUEST_SETUP;
2615 break;
2616 case NL80211_TDLS_TEARDOWN:
2617 wpa_printf(MSG_DEBUG, "nl80211: TDLS teardown request for peer "
2618 MACSTR, MAC2STR(data.tdls.peer));
2619 data.tdls.oper = TDLS_REQUEST_TEARDOWN;
2620 break;
2621 default:
2622 wpa_printf(MSG_DEBUG, "nl80211: Unsupported TDLS operatione "
2623 "event");
2624 return;
2625 }
2626 if (tb[NL80211_ATTR_REASON_CODE]) {
2627 data.tdls.reason_code =
2628 nla_get_u16(tb[NL80211_ATTR_REASON_CODE]);
2629 }
2630
2631 wpa_supplicant_event(drv->ctx, EVENT_TDLS, &data);
2632}
2633
2634
Dmitry Shmidt5393a0f2013-08-08 11:23:34 -07002635static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
2636 struct nlattr **tb)
2637{
2638 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
2639}
2640
2641
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002642static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data *drv,
2643 struct nlattr **tb)
2644{
2645 union wpa_event_data data;
2646 u32 reason;
2647
2648 wpa_printf(MSG_DEBUG, "nl80211: Connect failed event");
2649
2650 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_CONN_FAILED_REASON])
2651 return;
2652
2653 os_memset(&data, 0, sizeof(data));
2654 os_memcpy(data.connect_failed_reason.addr,
2655 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2656
2657 reason = nla_get_u32(tb[NL80211_ATTR_CONN_FAILED_REASON]);
2658 switch (reason) {
2659 case NL80211_CONN_FAIL_MAX_CLIENTS:
2660 wpa_printf(MSG_DEBUG, "nl80211: Max client reached");
2661 data.connect_failed_reason.code = MAX_CLIENT_REACHED;
2662 break;
2663 case NL80211_CONN_FAIL_BLOCKED_CLIENT:
2664 wpa_printf(MSG_DEBUG, "nl80211: Blocked client " MACSTR
2665 " tried to connect",
2666 MAC2STR(data.connect_failed_reason.addr));
2667 data.connect_failed_reason.code = BLOCKED_CLIENT;
2668 break;
2669 default:
2670 wpa_printf(MSG_DEBUG, "nl8021l: Unknown connect failed reason "
2671 "%u", reason);
2672 return;
2673 }
2674
2675 wpa_supplicant_event(drv->ctx, EVENT_CONNECT_FAILED_REASON, &data);
2676}
2677
2678
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002679static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
2680 struct nlattr **tb)
2681{
2682 union wpa_event_data data;
2683 enum nl80211_radar_event event_type;
2684
2685 if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
2686 return;
2687
2688 os_memset(&data, 0, sizeof(data));
Dmitry Shmidt051af732013-10-22 13:52:46 -07002689 data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
2690 event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002691
Dmitry Shmidt051af732013-10-22 13:52:46 -07002692 /* Check HT params */
2693 if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
2694 data.dfs_event.ht_enabled = 1;
2695 data.dfs_event.chan_offset = 0;
2696
2697 switch (nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
2698 case NL80211_CHAN_NO_HT:
2699 data.dfs_event.ht_enabled = 0;
2700 break;
2701 case NL80211_CHAN_HT20:
2702 break;
2703 case NL80211_CHAN_HT40PLUS:
2704 data.dfs_event.chan_offset = 1;
2705 break;
2706 case NL80211_CHAN_HT40MINUS:
2707 data.dfs_event.chan_offset = -1;
2708 break;
2709 }
2710 }
2711
2712 /* Get VHT params */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002713 if (tb[NL80211_ATTR_CHANNEL_WIDTH])
2714 data.dfs_event.chan_width =
2715 convert2width(nla_get_u32(
2716 tb[NL80211_ATTR_CHANNEL_WIDTH]));
2717 if (tb[NL80211_ATTR_CENTER_FREQ1])
2718 data.dfs_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002719 if (tb[NL80211_ATTR_CENTER_FREQ2])
2720 data.dfs_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
2721
2722 wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
2723 data.dfs_event.freq, data.dfs_event.ht_enabled,
2724 data.dfs_event.chan_offset, data.dfs_event.chan_width,
2725 data.dfs_event.cf1, data.dfs_event.cf2);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002726
2727 switch (event_type) {
2728 case NL80211_RADAR_DETECTED:
2729 wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
2730 break;
2731 case NL80211_RADAR_CAC_FINISHED:
2732 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
2733 break;
2734 case NL80211_RADAR_CAC_ABORTED:
2735 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
2736 break;
2737 case NL80211_RADAR_NOP_FINISHED:
2738 wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
2739 break;
2740 default:
2741 wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
2742 "received", event_type);
2743 break;
2744 }
2745}
2746
2747
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002748static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
2749 int wds)
2750{
2751 struct wpa_driver_nl80211_data *drv = bss->drv;
2752 union wpa_event_data event;
2753
2754 if (!tb[NL80211_ATTR_MAC])
2755 return;
2756
2757 os_memset(&event, 0, sizeof(event));
2758 event.rx_from_unknown.bssid = bss->addr;
2759 event.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]);
2760 event.rx_from_unknown.wds = wds;
2761
2762 wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
2763}
2764
2765
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002766static void qca_nl80211_avoid_freq(struct wpa_driver_nl80211_data *drv,
2767 const u8 *data, size_t len)
2768{
2769 u32 i, count;
2770 union wpa_event_data event;
2771 struct wpa_freq_range *range = NULL;
2772 const struct qca_avoid_freq_list *freq_range;
2773
2774 freq_range = (const struct qca_avoid_freq_list *) data;
2775 if (len < sizeof(freq_range->count))
2776 return;
2777
2778 count = freq_range->count;
2779 if (len < sizeof(freq_range->count) +
2780 count * sizeof(struct qca_avoid_freq_range)) {
2781 wpa_printf(MSG_DEBUG, "nl80211: Ignored too short avoid frequency list (len=%u)",
2782 (unsigned int) len);
2783 return;
2784 }
2785
2786 if (count > 0) {
2787 range = os_calloc(count, sizeof(struct wpa_freq_range));
2788 if (range == NULL)
2789 return;
2790 }
2791
2792 os_memset(&event, 0, sizeof(event));
2793 for (i = 0; i < count; i++) {
2794 unsigned int idx = event.freq_range.num;
2795 range[idx].min = freq_range->range[i].start_freq;
2796 range[idx].max = freq_range->range[i].end_freq;
2797 wpa_printf(MSG_DEBUG, "nl80211: Avoid frequency range: %u-%u",
2798 range[idx].min, range[idx].max);
2799 if (range[idx].min > range[idx].max) {
2800 wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid frequency range");
2801 continue;
2802 }
2803 event.freq_range.num++;
2804 }
2805 event.freq_range.range = range;
2806
2807 wpa_supplicant_event(drv->ctx, EVENT_AVOID_FREQUENCIES, &event);
2808
2809 os_free(range);
2810}
2811
2812
2813static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
2814 u32 subcmd, u8 *data, size_t len)
2815{
2816 switch (subcmd) {
2817 case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY:
2818 qca_nl80211_avoid_freq(drv, data, len);
2819 break;
2820 default:
2821 wpa_printf(MSG_DEBUG,
2822 "nl80211: Ignore unsupported QCA vendor event %u",
2823 subcmd);
2824 break;
2825 }
2826}
2827
2828
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002829static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
2830 struct nlattr **tb)
2831{
2832 u32 vendor_id, subcmd, wiphy = 0;
2833 int wiphy_idx;
2834 u8 *data = NULL;
2835 size_t len = 0;
2836
2837 if (!tb[NL80211_ATTR_VENDOR_ID] ||
2838 !tb[NL80211_ATTR_VENDOR_SUBCMD])
2839 return;
2840
2841 vendor_id = nla_get_u32(tb[NL80211_ATTR_VENDOR_ID]);
2842 subcmd = nla_get_u32(tb[NL80211_ATTR_VENDOR_SUBCMD]);
2843
2844 if (tb[NL80211_ATTR_WIPHY])
2845 wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
2846
2847 wpa_printf(MSG_DEBUG, "nl80211: Vendor event: wiphy=%u vendor_id=0x%x subcmd=%u",
2848 wiphy, vendor_id, subcmd);
2849
2850 if (tb[NL80211_ATTR_VENDOR_DATA]) {
2851 data = nla_data(tb[NL80211_ATTR_VENDOR_DATA]);
2852 len = nla_len(tb[NL80211_ATTR_VENDOR_DATA]);
2853 wpa_hexdump(MSG_MSGDUMP, "nl80211: Vendor data", data, len);
2854 }
2855
2856 wiphy_idx = nl80211_get_wiphy_index(drv->first_bss);
2857 if (wiphy_idx >= 0 && wiphy_idx != (int) wiphy) {
2858 wpa_printf(MSG_DEBUG, "nl80211: Ignore vendor event for foreign wiphy %u (own: %d)",
2859 wiphy, wiphy_idx);
2860 return;
2861 }
2862
2863 switch (vendor_id) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002864 case OUI_QCA:
2865 nl80211_vendor_event_qca(drv, subcmd, data, len);
2866 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002867 default:
2868 wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
2869 break;
2870 }
2871}
2872
2873
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002874static void do_process_drv_event(struct i802_bss *bss, int cmd,
2875 struct nlattr **tb)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002876{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002877 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002878 union wpa_event_data data;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002879
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002880 wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
2881 cmd, nl80211_command_to_string(cmd), bss->ifname);
2882
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002883 if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
2884 (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
2885 cmd == NL80211_CMD_SCAN_ABORTED)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002886 wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002887 drv->ap_scan_as_station);
2888 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002889 }
2890
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002891 switch (cmd) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002892 case NL80211_CMD_TRIGGER_SCAN:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002893 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002894 drv->scan_state = SCAN_STARTED;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002895 wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002896 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002897 case NL80211_CMD_START_SCHED_SCAN:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002898 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002899 drv->scan_state = SCHED_SCAN_STARTED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002900 break;
2901 case NL80211_CMD_SCHED_SCAN_STOPPED:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002902 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002903 drv->scan_state = SCHED_SCAN_STOPPED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002904 wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
2905 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002906 case NL80211_CMD_NEW_SCAN_RESULTS:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002907 wpa_dbg(drv->ctx, MSG_DEBUG,
2908 "nl80211: New scan results available");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002909 drv->scan_state = SCAN_COMPLETED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002910 drv->scan_complete_events = 1;
2911 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
2912 drv->ctx);
2913 send_scan_event(drv, 0, tb);
2914 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002915 case NL80211_CMD_SCHED_SCAN_RESULTS:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002916 wpa_dbg(drv->ctx, MSG_DEBUG,
2917 "nl80211: New sched scan results available");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002918 drv->scan_state = SCHED_SCAN_RESULTS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002919 send_scan_event(drv, 0, tb);
2920 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921 case NL80211_CMD_SCAN_ABORTED:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002922 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002923 drv->scan_state = SCAN_ABORTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 /*
2925 * Need to indicate that scan results are available in order
2926 * not to make wpa_supplicant stop its scanning.
2927 */
2928 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
2929 drv->ctx);
2930 send_scan_event(drv, 1, tb);
2931 break;
2932 case NL80211_CMD_AUTHENTICATE:
2933 case NL80211_CMD_ASSOCIATE:
2934 case NL80211_CMD_DEAUTHENTICATE:
2935 case NL80211_CMD_DISASSOCIATE:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002936 case NL80211_CMD_FRAME_TX_STATUS:
2937 case NL80211_CMD_UNPROT_DEAUTHENTICATE:
2938 case NL80211_CMD_UNPROT_DISASSOCIATE:
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002939 mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002940 tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
2941 tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
Dmitry Shmidt04949592012-07-19 12:16:46 -07002942 tb[NL80211_ATTR_COOKIE],
2943 tb[NL80211_ATTR_RX_SIGNAL_DBM]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002944 break;
2945 case NL80211_CMD_CONNECT:
2946 case NL80211_CMD_ROAM:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002947 mlme_event_connect(drv, cmd,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002948 tb[NL80211_ATTR_STATUS_CODE],
2949 tb[NL80211_ATTR_MAC],
2950 tb[NL80211_ATTR_REQ_IE],
2951 tb[NL80211_ATTR_RESP_IE]);
2952 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002953 case NL80211_CMD_CH_SWITCH_NOTIFY:
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002954 mlme_event_ch_switch(drv,
2955 tb[NL80211_ATTR_IFINDEX],
2956 tb[NL80211_ATTR_WIPHY_FREQ],
2957 tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
2958 tb[NL80211_ATTR_CHANNEL_WIDTH],
2959 tb[NL80211_ATTR_CENTER_FREQ1],
2960 tb[NL80211_ATTR_CENTER_FREQ2]);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002961 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002962 case NL80211_CMD_DISCONNECT:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002963 mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002964 tb[NL80211_ATTR_MAC],
2965 tb[NL80211_ATTR_DISCONNECTED_BY_AP]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002966 break;
2967 case NL80211_CMD_MICHAEL_MIC_FAILURE:
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002968 mlme_event_michael_mic_failure(bss, tb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002969 break;
2970 case NL80211_CMD_JOIN_IBSS:
2971 mlme_event_join_ibss(drv, tb);
2972 break;
2973 case NL80211_CMD_REMAIN_ON_CHANNEL:
2974 mlme_event_remain_on_channel(drv, 0, tb);
2975 break;
2976 case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:
2977 mlme_event_remain_on_channel(drv, 1, tb);
2978 break;
2979 case NL80211_CMD_NOTIFY_CQM:
2980 nl80211_cqm_event(drv, tb);
2981 break;
2982 case NL80211_CMD_REG_CHANGE:
2983 wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002984 if (tb[NL80211_ATTR_REG_INITIATOR] == NULL)
2985 break;
2986 os_memset(&data, 0, sizeof(data));
2987 switch (nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])) {
2988 case NL80211_REGDOM_SET_BY_CORE:
2989 data.channel_list_changed.initiator =
2990 REGDOM_SET_BY_CORE;
2991 break;
2992 case NL80211_REGDOM_SET_BY_USER:
2993 data.channel_list_changed.initiator =
2994 REGDOM_SET_BY_USER;
2995 break;
2996 case NL80211_REGDOM_SET_BY_DRIVER:
2997 data.channel_list_changed.initiator =
2998 REGDOM_SET_BY_DRIVER;
2999 break;
3000 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
3001 data.channel_list_changed.initiator =
3002 REGDOM_SET_BY_COUNTRY_IE;
3003 break;
3004 default:
3005 wpa_printf(MSG_DEBUG, "nl80211: Unknown reg change initiator %d received",
3006 nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]));
3007 break;
3008 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003009 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003010 &data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003011 break;
3012 case NL80211_CMD_REG_BEACON_HINT:
3013 wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint");
Dmitry Shmidt97672262014-02-03 13:02:54 -08003014 os_memset(&data, 0, sizeof(data));
3015 data.channel_list_changed.initiator = REGDOM_BEACON_HINT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003016 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
Dmitry Shmidt97672262014-02-03 13:02:54 -08003017 &data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003018 break;
3019 case NL80211_CMD_NEW_STATION:
3020 nl80211_new_station_event(drv, tb);
3021 break;
3022 case NL80211_CMD_DEL_STATION:
3023 nl80211_del_station_event(drv, tb);
3024 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003025 case NL80211_CMD_SET_REKEY_OFFLOAD:
3026 nl80211_rekey_offload_event(drv, tb);
3027 break;
3028 case NL80211_CMD_PMKSA_CANDIDATE:
3029 nl80211_pmksa_candidate_event(drv, tb);
3030 break;
3031 case NL80211_CMD_PROBE_CLIENT:
3032 nl80211_client_probe_event(drv, tb);
3033 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003034 case NL80211_CMD_TDLS_OPER:
3035 nl80211_tdls_oper_event(drv, tb);
3036 break;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003037 case NL80211_CMD_CONN_FAILED:
3038 nl80211_connect_failed_event(drv, tb);
3039 break;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003040 case NL80211_CMD_FT_EVENT:
3041 mlme_event_ft_event(drv, tb);
3042 break;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003043 case NL80211_CMD_RADAR_DETECT:
3044 nl80211_radar_event(drv, tb);
3045 break;
Dmitry Shmidt5393a0f2013-08-08 11:23:34 -07003046 case NL80211_CMD_STOP_AP:
3047 nl80211_stop_ap(drv, tb);
3048 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003049 case NL80211_CMD_VENDOR:
3050 nl80211_vendor_event(drv, tb);
3051 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003052 default:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003053 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
3054 "(cmd=%d)", cmd);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003055 break;
3056 }
3057}
3058
3059
3060static int process_drv_event(struct nl_msg *msg, void *arg)
3061{
3062 struct wpa_driver_nl80211_data *drv = arg;
3063 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3064 struct nlattr *tb[NL80211_ATTR_MAX + 1];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003065 struct i802_bss *bss;
3066 int ifidx = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003067
3068 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3069 genlmsg_attrlen(gnlh, 0), NULL);
3070
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003071 if (tb[NL80211_ATTR_IFINDEX]) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003072 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
3073
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003074 for (bss = drv->first_bss; bss; bss = bss->next)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003075 if (ifidx == -1 || ifidx == bss->ifindex) {
3076 do_process_drv_event(bss, gnlh->cmd, tb);
3077 return NL_SKIP;
3078 }
3079 wpa_printf(MSG_DEBUG,
3080 "nl80211: Ignored event (cmd=%d) for foreign interface (ifindex %d)",
3081 gnlh->cmd, ifidx);
3082 } else if (tb[NL80211_ATTR_WDEV]) {
3083 u64 wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
3084 wpa_printf(MSG_DEBUG, "nl80211: Process event on P2P device");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003085 for (bss = drv->first_bss; bss; bss = bss->next) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003086 if (bss->wdev_id_set && wdev_id == bss->wdev_id) {
3087 do_process_drv_event(bss, gnlh->cmd, tb);
3088 return NL_SKIP;
3089 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003090 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003091 wpa_printf(MSG_DEBUG,
3092 "nl80211: Ignored event (cmd=%d) for foreign interface (wdev 0x%llx)",
3093 gnlh->cmd, (long long unsigned int) wdev_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003094 }
3095
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003096 return NL_SKIP;
3097}
3098
3099
3100static int process_global_event(struct nl_msg *msg, void *arg)
3101{
3102 struct nl80211_global *global = arg;
3103 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3104 struct nlattr *tb[NL80211_ATTR_MAX + 1];
Dmitry Shmidt04949592012-07-19 12:16:46 -07003105 struct wpa_driver_nl80211_data *drv, *tmp;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003106 int ifidx = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003107 struct i802_bss *bss;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003108 u64 wdev_id = 0;
3109 int wdev_id_set = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003110
3111 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3112 genlmsg_attrlen(gnlh, 0), NULL);
3113
3114 if (tb[NL80211_ATTR_IFINDEX])
3115 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003116 else if (tb[NL80211_ATTR_WDEV]) {
3117 wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
3118 wdev_id_set = 1;
3119 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003120
Dmitry Shmidt04949592012-07-19 12:16:46 -07003121 dl_list_for_each_safe(drv, tmp, &global->interfaces,
3122 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003123 for (bss = drv->first_bss; bss; bss = bss->next) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003124 if ((ifidx == -1 && !wdev_id_set) ||
3125 ifidx == bss->ifindex ||
3126 (wdev_id_set && bss->wdev_id_set &&
3127 wdev_id == bss->wdev_id)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003128 do_process_drv_event(bss, gnlh->cmd, tb);
3129 return NL_SKIP;
3130 }
3131 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003132 }
3133
3134 return NL_SKIP;
3135}
3136
3137
3138static int process_bss_event(struct nl_msg *msg, void *arg)
3139{
3140 struct i802_bss *bss = arg;
3141 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3142 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3143
3144 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3145 genlmsg_attrlen(gnlh, 0), NULL);
3146
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003147 wpa_printf(MSG_DEBUG, "nl80211: BSS Event %d (%s) received for %s",
3148 gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
3149 bss->ifname);
3150
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003151 switch (gnlh->cmd) {
3152 case NL80211_CMD_FRAME:
3153 case NL80211_CMD_FRAME_TX_STATUS:
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003154 mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003155 tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
3156 tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
Dmitry Shmidt04949592012-07-19 12:16:46 -07003157 tb[NL80211_ATTR_COOKIE],
3158 tb[NL80211_ATTR_RX_SIGNAL_DBM]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003159 break;
3160 case NL80211_CMD_UNEXPECTED_FRAME:
3161 nl80211_spurious_frame(bss, tb, 0);
3162 break;
3163 case NL80211_CMD_UNEXPECTED_4ADDR_FRAME:
3164 nl80211_spurious_frame(bss, tb, 1);
3165 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003166 default:
3167 wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
3168 "(cmd=%d)", gnlh->cmd);
3169 break;
3170 }
3171
3172 return NL_SKIP;
3173}
3174
3175
3176static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
3177 void *handle)
3178{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003179 struct nl_cb *cb = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003180 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003181
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003182 wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003183
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003184 res = nl_recvmsgs(handle, cb);
3185 if (res) {
3186 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
3187 __func__, res);
3188 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003189}
3190
3191
3192/**
3193 * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
3194 * @priv: driver_nl80211 private data
3195 * @alpha2_arg: country to which to switch to
3196 * Returns: 0 on success, -1 on failure
3197 *
3198 * This asks nl80211 to set the regulatory domain for given
3199 * country ISO / IEC alpha2.
3200 */
3201static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
3202{
3203 struct i802_bss *bss = priv;
3204 struct wpa_driver_nl80211_data *drv = bss->drv;
3205 char alpha2[3];
3206 struct nl_msg *msg;
3207
3208 msg = nlmsg_alloc();
3209 if (!msg)
3210 return -ENOMEM;
3211
3212 alpha2[0] = alpha2_arg[0];
3213 alpha2[1] = alpha2_arg[1];
3214 alpha2[2] = '\0';
3215
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003216 nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003217
3218 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
3219 if (send_and_recv_msgs(drv, msg, NULL, NULL))
3220 return -EINVAL;
3221 return 0;
3222nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003223 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003224 return -EINVAL;
3225}
3226
3227
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003228static int nl80211_get_country(struct nl_msg *msg, void *arg)
3229{
3230 char *alpha2 = arg;
3231 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
3232 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3233
3234 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3235 genlmsg_attrlen(gnlh, 0), NULL);
3236 if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) {
3237 wpa_printf(MSG_DEBUG, "nl80211: No country information available");
3238 return NL_SKIP;
3239 }
3240 os_strlcpy(alpha2, nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]), 3);
3241 return NL_SKIP;
3242}
3243
3244
3245static int wpa_driver_nl80211_get_country(void *priv, char *alpha2)
3246{
3247 struct i802_bss *bss = priv;
3248 struct wpa_driver_nl80211_data *drv = bss->drv;
3249 struct nl_msg *msg;
3250 int ret;
3251
3252 msg = nlmsg_alloc();
3253 if (!msg)
3254 return -ENOMEM;
3255
3256 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
3257 alpha2[0] = '\0';
3258 ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2);
3259 if (!alpha2[0])
3260 ret = -1;
3261
3262 return ret;
3263}
3264
3265
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003266static int protocol_feature_handler(struct nl_msg *msg, void *arg)
3267{
3268 u32 *feat = arg;
3269 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
3270 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3271
3272 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3273 genlmsg_attrlen(gnlh, 0), NULL);
3274
3275 if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES])
3276 *feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]);
3277
3278 return NL_SKIP;
3279}
3280
3281
3282static u32 get_nl80211_protocol_features(struct wpa_driver_nl80211_data *drv)
3283{
3284 u32 feat = 0;
3285 struct nl_msg *msg;
3286
3287 msg = nlmsg_alloc();
3288 if (!msg)
3289 goto nla_put_failure;
3290
3291 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_PROTOCOL_FEATURES);
3292 if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat) == 0)
3293 return feat;
3294
3295 msg = NULL;
3296nla_put_failure:
3297 nlmsg_free(msg);
3298 return 0;
3299}
3300
3301
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003302struct wiphy_info_data {
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003303 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003304 struct wpa_driver_capa *capa;
3305
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003306 unsigned int num_multichan_concurrent;
3307
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003308 unsigned int error:1;
3309 unsigned int device_ap_sme:1;
3310 unsigned int poll_command_supported:1;
3311 unsigned int data_tx_status:1;
3312 unsigned int monitor_supported:1;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003313 unsigned int auth_supported:1;
3314 unsigned int connect_supported:1;
3315 unsigned int p2p_go_supported:1;
3316 unsigned int p2p_client_supported:1;
3317 unsigned int p2p_concurrent:1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003318 unsigned int channel_switch_supported:1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003319 unsigned int set_qos_map_supported:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003320};
3321
3322
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003323static unsigned int probe_resp_offload_support(int supp_protocols)
3324{
3325 unsigned int prot = 0;
3326
3327 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS)
3328 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS;
3329 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)
3330 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2;
3331 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P)
3332 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P;
3333 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U)
3334 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING;
3335
3336 return prot;
3337}
3338
3339
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003340static void wiphy_info_supported_iftypes(struct wiphy_info_data *info,
3341 struct nlattr *tb)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003343 struct nlattr *nl_mode;
3344 int i;
3345
3346 if (tb == NULL)
3347 return;
3348
3349 nla_for_each_nested(nl_mode, tb, i) {
3350 switch (nla_type(nl_mode)) {
3351 case NL80211_IFTYPE_AP:
3352 info->capa->flags |= WPA_DRIVER_FLAGS_AP;
3353 break;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003354 case NL80211_IFTYPE_ADHOC:
3355 info->capa->flags |= WPA_DRIVER_FLAGS_IBSS;
3356 break;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003357 case NL80211_IFTYPE_P2P_DEVICE:
3358 info->capa->flags |=
3359 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
3360 break;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003361 case NL80211_IFTYPE_P2P_GO:
3362 info->p2p_go_supported = 1;
3363 break;
3364 case NL80211_IFTYPE_P2P_CLIENT:
3365 info->p2p_client_supported = 1;
3366 break;
3367 case NL80211_IFTYPE_MONITOR:
3368 info->monitor_supported = 1;
3369 break;
3370 }
3371 }
3372}
3373
3374
3375static int wiphy_info_iface_comb_process(struct wiphy_info_data *info,
3376 struct nlattr *nl_combi)
3377{
3378 struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
3379 struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
3380 struct nlattr *nl_limit, *nl_mode;
3381 int err, rem_limit, rem_mode;
3382 int combination_has_p2p = 0, combination_has_mgd = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003383 static struct nla_policy
3384 iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
3385 [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
3386 [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
3387 [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
3388 [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003389 [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003390 },
3391 iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
3392 [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
3393 [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
3394 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003395
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003396 err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
3397 nl_combi, iface_combination_policy);
3398 if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
3399 !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
3400 !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
3401 return 0; /* broken combination */
3402
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003403 if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS])
3404 info->capa->flags |= WPA_DRIVER_FLAGS_RADAR;
3405
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003406 nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS],
3407 rem_limit) {
3408 err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
3409 nl_limit, iface_limit_policy);
3410 if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES])
3411 return 0; /* broken combination */
3412
3413 nla_for_each_nested(nl_mode,
3414 tb_limit[NL80211_IFACE_LIMIT_TYPES],
3415 rem_mode) {
3416 int ift = nla_type(nl_mode);
3417 if (ift == NL80211_IFTYPE_P2P_GO ||
3418 ift == NL80211_IFTYPE_P2P_CLIENT)
3419 combination_has_p2p = 1;
3420 if (ift == NL80211_IFTYPE_STATION)
3421 combination_has_mgd = 1;
3422 }
3423 if (combination_has_p2p && combination_has_mgd)
3424 break;
3425 }
3426
3427 if (combination_has_p2p && combination_has_mgd) {
3428 info->p2p_concurrent = 1;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003429 info->num_multichan_concurrent =
3430 nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003431 return 1;
3432 }
3433
3434 return 0;
3435}
3436
3437
3438static void wiphy_info_iface_comb(struct wiphy_info_data *info,
3439 struct nlattr *tb)
3440{
3441 struct nlattr *nl_combi;
3442 int rem_combi;
3443
3444 if (tb == NULL)
3445 return;
3446
3447 nla_for_each_nested(nl_combi, tb, rem_combi) {
3448 if (wiphy_info_iface_comb_process(info, nl_combi) > 0)
3449 break;
3450 }
3451}
3452
3453
3454static void wiphy_info_supp_cmds(struct wiphy_info_data *info,
3455 struct nlattr *tb)
3456{
3457 struct nlattr *nl_cmd;
3458 int i;
3459
3460 if (tb == NULL)
3461 return;
3462
3463 nla_for_each_nested(nl_cmd, tb, i) {
3464 switch (nla_get_u32(nl_cmd)) {
3465 case NL80211_CMD_AUTHENTICATE:
3466 info->auth_supported = 1;
3467 break;
3468 case NL80211_CMD_CONNECT:
3469 info->connect_supported = 1;
3470 break;
3471 case NL80211_CMD_START_SCHED_SCAN:
3472 info->capa->sched_scan_supported = 1;
3473 break;
3474 case NL80211_CMD_PROBE_CLIENT:
3475 info->poll_command_supported = 1;
3476 break;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003477 case NL80211_CMD_CHANNEL_SWITCH:
3478 info->channel_switch_supported = 1;
3479 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003480 case NL80211_CMD_SET_QOS_MAP:
3481 info->set_qos_map_supported = 1;
3482 break;
3483 }
3484 }
3485}
3486
3487
3488static void wiphy_info_cipher_suites(struct wiphy_info_data *info,
3489 struct nlattr *tb)
3490{
3491 int i, num;
3492 u32 *ciphers;
3493
3494 if (tb == NULL)
3495 return;
3496
3497 num = nla_len(tb) / sizeof(u32);
3498 ciphers = nla_data(tb);
3499 for (i = 0; i < num; i++) {
3500 u32 c = ciphers[i];
3501
3502 wpa_printf(MSG_DEBUG, "nl80211: Supported cipher %02x-%02x-%02x:%d",
3503 c >> 24, (c >> 16) & 0xff,
3504 (c >> 8) & 0xff, c & 0xff);
3505 switch (c) {
3506 case WLAN_CIPHER_SUITE_CCMP_256:
3507 info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP_256;
3508 break;
3509 case WLAN_CIPHER_SUITE_GCMP_256:
3510 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP_256;
3511 break;
3512 case WLAN_CIPHER_SUITE_CCMP:
3513 info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP;
3514 break;
3515 case WLAN_CIPHER_SUITE_GCMP:
3516 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP;
3517 break;
3518 case WLAN_CIPHER_SUITE_TKIP:
3519 info->capa->enc |= WPA_DRIVER_CAPA_ENC_TKIP;
3520 break;
3521 case WLAN_CIPHER_SUITE_WEP104:
3522 info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP104;
3523 break;
3524 case WLAN_CIPHER_SUITE_WEP40:
3525 info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP40;
3526 break;
3527 case WLAN_CIPHER_SUITE_AES_CMAC:
3528 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP;
3529 break;
3530 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
3531 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_128;
3532 break;
3533 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
3534 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_256;
3535 break;
3536 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
3537 info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_CMAC_256;
3538 break;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003539 case WLAN_CIPHER_SUITE_NO_GROUP_ADDR:
3540 info->capa->enc |= WPA_DRIVER_CAPA_ENC_GTK_NOT_USED;
3541 break;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003542 }
3543 }
3544}
3545
3546
3547static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
3548 struct nlattr *tb)
3549{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003550 if (tb)
3551 capa->max_remain_on_chan = nla_get_u32(tb);
3552}
3553
3554
3555static void wiphy_info_tdls(struct wpa_driver_capa *capa, struct nlattr *tdls,
3556 struct nlattr *ext_setup)
3557{
3558 if (tdls == NULL)
3559 return;
3560
3561 wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
3562 capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
3563
3564 if (ext_setup) {
3565 wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
3566 capa->flags |= WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
3567 }
3568}
3569
3570
3571static void wiphy_info_feature_flags(struct wiphy_info_data *info,
3572 struct nlattr *tb)
3573{
3574 u32 flags;
3575 struct wpa_driver_capa *capa = info->capa;
3576
3577 if (tb == NULL)
3578 return;
3579
3580 flags = nla_get_u32(tb);
3581
3582 if (flags & NL80211_FEATURE_SK_TX_STATUS)
3583 info->data_tx_status = 1;
3584
3585 if (flags & NL80211_FEATURE_INACTIVITY_TIMER)
3586 capa->flags |= WPA_DRIVER_FLAGS_INACTIVITY_TIMER;
3587
3588 if (flags & NL80211_FEATURE_SAE)
3589 capa->flags |= WPA_DRIVER_FLAGS_SAE;
3590
3591 if (flags & NL80211_FEATURE_NEED_OBSS_SCAN)
3592 capa->flags |= WPA_DRIVER_FLAGS_OBSS_SCAN;
3593}
3594
3595
3596static void wiphy_info_probe_resp_offload(struct wpa_driver_capa *capa,
3597 struct nlattr *tb)
3598{
3599 u32 protocols;
3600
3601 if (tb == NULL)
3602 return;
3603
3604 protocols = nla_get_u32(tb);
3605 wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response offload in AP "
3606 "mode");
3607 capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
3608 capa->probe_resp_offloads = probe_resp_offload_support(protocols);
3609}
3610
3611
3612static int wiphy_info_handler(struct nl_msg *msg, void *arg)
3613{
3614 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3615 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3616 struct wiphy_info_data *info = arg;
3617 struct wpa_driver_capa *capa = info->capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003618 struct wpa_driver_nl80211_data *drv = info->drv;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003619
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003620 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3621 genlmsg_attrlen(gnlh, 0), NULL);
3622
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003623 if (tb[NL80211_ATTR_WIPHY_NAME])
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003624 os_strlcpy(drv->phyname,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003625 nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
3626 sizeof(drv->phyname));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003627 if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003628 capa->max_scan_ssids =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
3630
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003631 if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])
3632 capa->max_sched_scan_ssids =
3633 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
3634
3635 if (tb[NL80211_ATTR_MAX_MATCH_SETS])
3636 capa->max_match_sets =
3637 nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
3638
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003639 if (tb[NL80211_ATTR_MAC_ACL_MAX])
3640 capa->max_acl_mac_addrs =
3641 nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
3642
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003643 wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
3644 wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
3645 wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003646 wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003647
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003648 if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
3649 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
3650 "off-channel TX");
3651 capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
3652 }
3653
3654 if (tb[NL80211_ATTR_ROAM_SUPPORT]) {
3655 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming");
3656 capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
3657 }
3658
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003659 wiphy_info_max_roc(capa,
3660 tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003661
3662 if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
3663 capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003664
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003665 wiphy_info_tdls(capa, tb[NL80211_ATTR_TDLS_SUPPORT],
3666 tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]);
Dmitry Shmidtad266fb2012-08-24 17:03:35 -07003667
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003668 if (tb[NL80211_ATTR_DEVICE_AP_SME])
3669 info->device_ap_sme = 1;
3670
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003671 wiphy_info_feature_flags(info, tb[NL80211_ATTR_FEATURE_FLAGS]);
3672 wiphy_info_probe_resp_offload(capa,
3673 tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003674
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003675 if (tb[NL80211_ATTR_EXT_CAPA] && tb[NL80211_ATTR_EXT_CAPA_MASK] &&
3676 drv->extended_capa == NULL) {
3677 drv->extended_capa =
3678 os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3679 if (drv->extended_capa) {
3680 os_memcpy(drv->extended_capa,
3681 nla_data(tb[NL80211_ATTR_EXT_CAPA]),
3682 nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3683 drv->extended_capa_len =
3684 nla_len(tb[NL80211_ATTR_EXT_CAPA]);
3685 }
3686 drv->extended_capa_mask =
3687 os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3688 if (drv->extended_capa_mask) {
3689 os_memcpy(drv->extended_capa_mask,
3690 nla_data(tb[NL80211_ATTR_EXT_CAPA]),
3691 nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3692 } else {
3693 os_free(drv->extended_capa);
3694 drv->extended_capa = NULL;
3695 drv->extended_capa_len = 0;
3696 }
3697 }
3698
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003699 if (tb[NL80211_ATTR_VENDOR_DATA]) {
3700 struct nlattr *nl;
3701 int rem;
3702
3703 nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
3704 struct nl80211_vendor_cmd_info *vinfo;
Dmitry Shmidt18463232014-01-24 12:29:41 -08003705 if (nla_len(nl) != sizeof(*vinfo)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003706 wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
3707 continue;
3708 }
3709 vinfo = nla_data(nl);
3710 wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
3711 vinfo->vendor_id, vinfo->subcmd);
3712 }
3713 }
3714
3715 if (tb[NL80211_ATTR_VENDOR_EVENTS]) {
3716 struct nlattr *nl;
3717 int rem;
3718
3719 nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_EVENTS], rem) {
3720 struct nl80211_vendor_cmd_info *vinfo;
Dmitry Shmidt18463232014-01-24 12:29:41 -08003721 if (nla_len(nl) != sizeof(*vinfo)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003722 wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
3723 continue;
3724 }
3725 vinfo = nla_data(nl);
3726 wpa_printf(MSG_DEBUG, "nl80211: Supported vendor event: vendor_id=0x%x subcmd=%u",
3727 vinfo->vendor_id, vinfo->subcmd);
3728 }
3729 }
3730
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731 return NL_SKIP;
3732}
3733
3734
3735static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
3736 struct wiphy_info_data *info)
3737{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003738 u32 feat;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003739 struct nl_msg *msg;
3740
3741 os_memset(info, 0, sizeof(*info));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003742 info->capa = &drv->capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003743 info->drv = drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003744
3745 msg = nlmsg_alloc();
3746 if (!msg)
3747 return -1;
3748
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003749 feat = get_nl80211_protocol_features(drv);
3750 if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
3751 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_WIPHY);
3752 else
3753 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003754
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003755 NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003756 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003757 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003758
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003759 if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info))
3760 return -1;
3761
3762 if (info->auth_supported)
3763 drv->capa.flags |= WPA_DRIVER_FLAGS_SME;
3764 else if (!info->connect_supported) {
3765 wpa_printf(MSG_INFO, "nl80211: Driver does not support "
3766 "authentication/association or connect commands");
3767 info->error = 1;
3768 }
3769
3770 if (info->p2p_go_supported && info->p2p_client_supported)
3771 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
3772 if (info->p2p_concurrent) {
3773 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
3774 "interface (driver advertised support)");
3775 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
3776 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
3777 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003778 if (info->num_multichan_concurrent > 1) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003779 wpa_printf(MSG_DEBUG, "nl80211: Enable multi-channel "
3780 "concurrent (driver advertised support)");
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003781 drv->capa.num_multichan_concurrent =
3782 info->num_multichan_concurrent;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003783 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003784
3785 /* default to 5000 since early versions of mac80211 don't set it */
3786 if (!drv->capa.max_remain_on_chan)
3787 drv->capa.max_remain_on_chan = 5000;
3788
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003789 if (info->channel_switch_supported)
3790 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_CSA;
3791
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003792 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003793nla_put_failure:
3794 nlmsg_free(msg);
3795 return -1;
3796}
3797
3798
3799static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
3800{
3801 struct wiphy_info_data info;
3802 if (wpa_driver_nl80211_get_info(drv, &info))
3803 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003804
3805 if (info.error)
3806 return -1;
3807
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003808 drv->has_capability = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003809 drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3810 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
3811 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
3812 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003813 drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
3814 WPA_DRIVER_AUTH_SHARED |
3815 WPA_DRIVER_AUTH_LEAP;
3816
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003817 drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
3818 drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003819 drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
Dmitry Shmidtad266fb2012-08-24 17:03:35 -07003820
Dmitry Shmidta38abf92014-03-06 13:38:44 -08003821 /*
3822 * As all cfg80211 drivers must support cases where the AP interface is
3823 * removed without the knowledge of wpa_supplicant/hostapd, e.g., in
3824 * case that the user space daemon has crashed, they must be able to
3825 * cleanup all stations and key entries in the AP tear down flow. Thus,
3826 * this flag can/should always be set for cfg80211 drivers.
3827 */
3828 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT;
3829
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003830 if (!info.device_ap_sme) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003831 drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003832
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003833 /*
3834 * No AP SME is currently assumed to also indicate no AP MLME
3835 * in the driver/firmware.
3836 */
3837 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_MLME;
3838 }
3839
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003840 drv->device_ap_sme = info.device_ap_sme;
3841 drv->poll_command_supported = info.poll_command_supported;
3842 drv->data_tx_status = info.data_tx_status;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003843 if (info.set_qos_map_supported)
3844 drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003845
3846 /*
Dmitry Shmidtaa532512012-09-24 10:35:31 -07003847 * If poll command and tx status are supported, mac80211 is new enough
3848 * to have everything we need to not need monitor interfaces.
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003849 */
Dmitry Shmidtaa532512012-09-24 10:35:31 -07003850 drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003851
3852 if (drv->device_ap_sme && drv->use_monitor) {
3853 /*
3854 * Non-mac80211 drivers may not support monitor interface.
3855 * Make sure we do not get stuck with incorrect capability here
3856 * by explicitly testing this.
3857 */
3858 if (!info.monitor_supported) {
3859 wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor "
3860 "with device_ap_sme since no monitor mode "
3861 "support detected");
3862 drv->use_monitor = 0;
3863 }
3864 }
3865
3866 /*
3867 * If we aren't going to use monitor interfaces, but the
3868 * driver doesn't support data TX status, we won't get TX
3869 * status for EAPOL frames.
3870 */
3871 if (!drv->use_monitor && !info.data_tx_status)
3872 drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003873
3874 return 0;
3875}
3876
3877
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003878#ifdef ANDROID
3879static int android_genl_ctrl_resolve(struct nl_handle *handle,
3880 const char *name)
3881{
3882 /*
3883 * Android ICS has very minimal genl_ctrl_resolve() implementation, so
3884 * need to work around that.
3885 */
3886 struct nl_cache *cache = NULL;
3887 struct genl_family *nl80211 = NULL;
3888 int id = -1;
3889
3890 if (genl_ctrl_alloc_cache(handle, &cache) < 0) {
3891 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
3892 "netlink cache");
3893 goto fail;
3894 }
3895
3896 nl80211 = genl_ctrl_search_by_name(cache, name);
3897 if (nl80211 == NULL)
3898 goto fail;
3899
3900 id = genl_family_get_id(nl80211);
3901
3902fail:
3903 if (nl80211)
3904 genl_family_put(nl80211);
3905 if (cache)
3906 nl_cache_free(cache);
3907
3908 return id;
3909}
3910#define genl_ctrl_resolve android_genl_ctrl_resolve
3911#endif /* ANDROID */
3912
3913
3914static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003915{
3916 int ret;
3917
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003918 global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
3919 if (global->nl_cb == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003920 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
3921 "callbacks");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003922 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 }
3924
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003925 global->nl = nl_create_handle(global->nl_cb, "nl");
3926 if (global->nl == NULL)
3927 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003928
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003929 global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
3930 if (global->nl80211_id < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003931 wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
3932 "found");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003933 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003934 }
3935
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003936 global->nl_event = nl_create_handle(global->nl_cb, "event");
3937 if (global->nl_event == NULL)
3938 goto err;
3939
3940 ret = nl_get_multicast_id(global, "nl80211", "scan");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003941 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003942 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003943 if (ret < 0) {
3944 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
3945 "membership for scan events: %d (%s)",
3946 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003947 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003948 }
3949
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003950 ret = nl_get_multicast_id(global, "nl80211", "mlme");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003951 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003952 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003953 if (ret < 0) {
3954 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
3955 "membership for mlme events: %d (%s)",
3956 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003957 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958 }
3959
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003960 ret = nl_get_multicast_id(global, "nl80211", "regulatory");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003961 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003962 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003963 if (ret < 0) {
3964 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
3965 "membership for regulatory events: %d (%s)",
3966 ret, strerror(-ret));
3967 /* Continue without regulatory events */
3968 }
3969
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003970 ret = nl_get_multicast_id(global, "nl80211", "vendor");
3971 if (ret >= 0)
3972 ret = nl_socket_add_membership(global->nl_event, ret);
3973 if (ret < 0) {
3974 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
3975 "membership for vendor events: %d (%s)",
3976 ret, strerror(-ret));
3977 /* Continue without vendor events */
3978 }
3979
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003980 nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
3981 no_seq_check, NULL);
3982 nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
3983 process_global_event, global);
3984
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003985 nl80211_register_eloop_read(&global->nl_event,
3986 wpa_driver_nl80211_event_receive,
3987 global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003988
3989 return 0;
3990
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003991err:
3992 nl_destroy_handles(&global->nl_event);
3993 nl_destroy_handles(&global->nl);
3994 nl_cb_put(global->nl_cb);
3995 global->nl_cb = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003996 return -1;
3997}
3998
3999
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004000static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
4001{
4002 drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
4003 if (!drv->nl_cb) {
4004 wpa_printf(MSG_ERROR, "nl80211: Failed to alloc cb struct");
4005 return -1;
4006 }
4007
4008 nl_cb_set(drv->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
4009 no_seq_check, NULL);
4010 nl_cb_set(drv->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
4011 process_drv_event, drv);
4012
4013 return 0;
4014}
4015
4016
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004017static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
4018{
4019 wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
4020 /*
4021 * This may be for any interface; use ifdown event to disable
4022 * interface.
4023 */
4024}
4025
4026
4027static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
4028{
4029 struct wpa_driver_nl80211_data *drv = ctx;
4030 wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004031 if (i802_set_iface_flags(drv->first_bss, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004032 wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
4033 "after rfkill unblock");
4034 return;
4035 }
4036 /* rtnetlink ifup handler will report interface as enabled */
4037}
4038
4039
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004040static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
4041 void *eloop_ctx,
4042 void *handle)
4043{
4044 struct wpa_driver_nl80211_data *drv = eloop_ctx;
4045 u8 data[2048];
4046 struct msghdr msg;
4047 struct iovec entry;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004048 u8 control[512];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004049 struct cmsghdr *cmsg;
4050 int res, found_ee = 0, found_wifi = 0, acked = 0;
4051 union wpa_event_data event;
4052
4053 memset(&msg, 0, sizeof(msg));
4054 msg.msg_iov = &entry;
4055 msg.msg_iovlen = 1;
4056 entry.iov_base = data;
4057 entry.iov_len = sizeof(data);
4058 msg.msg_control = &control;
4059 msg.msg_controllen = sizeof(control);
4060
4061 res = recvmsg(sock, &msg, MSG_ERRQUEUE);
4062 /* if error or not fitting 802.3 header, return */
4063 if (res < 14)
4064 return;
4065
4066 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
4067 {
4068 if (cmsg->cmsg_level == SOL_SOCKET &&
4069 cmsg->cmsg_type == SCM_WIFI_STATUS) {
4070 int *ack;
4071
4072 found_wifi = 1;
4073 ack = (void *)CMSG_DATA(cmsg);
4074 acked = *ack;
4075 }
4076
4077 if (cmsg->cmsg_level == SOL_PACKET &&
4078 cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
4079 struct sock_extended_err *err =
4080 (struct sock_extended_err *)CMSG_DATA(cmsg);
4081
4082 if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
4083 found_ee = 1;
4084 }
4085 }
4086
4087 if (!found_ee || !found_wifi)
4088 return;
4089
4090 memset(&event, 0, sizeof(event));
4091 event.eapol_tx_status.dst = data;
4092 event.eapol_tx_status.data = data + 14;
4093 event.eapol_tx_status.data_len = res - 14;
4094 event.eapol_tx_status.ack = acked;
4095 wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
4096}
4097
4098
4099static int nl80211_init_bss(struct i802_bss *bss)
4100{
4101 bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
4102 if (!bss->nl_cb)
4103 return -1;
4104
4105 nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
4106 no_seq_check, NULL);
4107 nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
4108 process_bss_event, bss);
4109
4110 return 0;
4111}
4112
4113
4114static void nl80211_destroy_bss(struct i802_bss *bss)
4115{
4116 nl_cb_put(bss->nl_cb);
4117 bss->nl_cb = NULL;
4118}
4119
4120
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004121static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
4122 void *global_priv, int hostapd,
4123 const u8 *set_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004124{
4125 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126 struct rfkill_config *rcfg;
4127 struct i802_bss *bss;
4128
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004129 if (global_priv == NULL)
4130 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004131 drv = os_zalloc(sizeof(*drv));
4132 if (drv == NULL)
4133 return NULL;
4134 drv->global = global_priv;
4135 drv->ctx = ctx;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004136 drv->hostapd = !!hostapd;
4137 drv->eapol_sock = -1;
4138 drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
4139 drv->if_indices = drv->default_if_indices;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004140
4141 drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
4142 if (!drv->first_bss) {
4143 os_free(drv);
4144 return NULL;
4145 }
4146 bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004147 bss->drv = drv;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004148 bss->ctx = ctx;
4149
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004150 os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
4151 drv->monitor_ifidx = -1;
4152 drv->monitor_sock = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004153 drv->eapol_tx_sock = -1;
4154 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004155
4156 if (wpa_driver_nl80211_init_nl(drv)) {
4157 os_free(drv);
4158 return NULL;
4159 }
4160
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004161 if (nl80211_init_bss(bss))
4162 goto failed;
4163
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004164 rcfg = os_zalloc(sizeof(*rcfg));
4165 if (rcfg == NULL)
4166 goto failed;
4167 rcfg->ctx = drv;
4168 os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
4169 rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
4170 rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
4171 drv->rfkill = rfkill_init(rcfg);
4172 if (drv->rfkill == NULL) {
4173 wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
4174 os_free(rcfg);
4175 }
4176
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004177 if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0)
4178 drv->start_iface_up = 1;
4179
4180 if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004181 goto failed;
4182
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004183 drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
4184 if (drv->eapol_tx_sock < 0)
4185 goto failed;
4186
4187 if (drv->data_tx_status) {
4188 int enabled = 1;
4189
4190 if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
4191 &enabled, sizeof(enabled)) < 0) {
4192 wpa_printf(MSG_DEBUG,
4193 "nl80211: wifi status sockopt failed\n");
4194 drv->data_tx_status = 0;
4195 if (!drv->use_monitor)
4196 drv->capa.flags &=
4197 ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
4198 } else {
4199 eloop_register_read_sock(drv->eapol_tx_sock,
4200 wpa_driver_nl80211_handle_eapol_tx_status,
4201 drv, NULL);
4202 }
4203 }
4204
4205 if (drv->global) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004206 dl_list_add(&drv->global->interfaces, &drv->list);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004207 drv->in_interface_list = 1;
4208 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004209
4210 return bss;
4211
4212failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004213 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004214 return NULL;
4215}
4216
4217
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004218/**
4219 * wpa_driver_nl80211_init - Initialize nl80211 driver interface
4220 * @ctx: context to be used when calling wpa_supplicant functions,
4221 * e.g., wpa_supplicant_event()
4222 * @ifname: interface name, e.g., wlan0
4223 * @global_priv: private driver global data from global_init()
4224 * Returns: Pointer to private data, %NULL on failure
4225 */
4226static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
4227 void *global_priv)
4228{
4229 return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL);
4230}
4231
4232
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004233static int nl80211_register_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004234 struct nl_handle *nl_handle,
4235 u16 type, const u8 *match, size_t match_len)
4236{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004237 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004238 struct nl_msg *msg;
4239 int ret = -1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004240 char buf[30];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004241
4242 msg = nlmsg_alloc();
4243 if (!msg)
4244 return -1;
4245
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004246 buf[0] = '\0';
4247 wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
4248 wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x nl_handle=%p match=%s",
4249 type, nl_handle, buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004250
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004251 nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
4252
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004253 if (nl80211_set_iface_id(msg, bss) < 0)
4254 goto nla_put_failure;
4255
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004256 NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
4257 NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);
4258
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004259 ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004260 msg = NULL;
4261 if (ret) {
4262 wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
4263 "failed (type=%u): ret=%d (%s)",
4264 type, ret, strerror(-ret));
4265 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
4266 match, match_len);
4267 goto nla_put_failure;
4268 }
4269 ret = 0;
4270nla_put_failure:
4271 nlmsg_free(msg);
4272 return ret;
4273}
4274
4275
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004276static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
4277{
4278 struct wpa_driver_nl80211_data *drv = bss->drv;
4279
4280 if (bss->nl_mgmt) {
4281 wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting "
4282 "already on! (nl_mgmt=%p)", bss->nl_mgmt);
4283 return -1;
4284 }
4285
4286 bss->nl_mgmt = nl_create_handle(drv->nl_cb, "mgmt");
4287 if (bss->nl_mgmt == NULL)
4288 return -1;
4289
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004290 return 0;
4291}
4292
4293
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004294static void nl80211_mgmt_handle_register_eloop(struct i802_bss *bss)
4295{
4296 nl80211_register_eloop_read(&bss->nl_mgmt,
4297 wpa_driver_nl80211_event_receive,
4298 bss->nl_cb);
4299}
4300
4301
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004302static int nl80211_register_action_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004303 const u8 *match, size_t match_len)
4304{
4305 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004306 return nl80211_register_frame(bss, bss->nl_mgmt,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004307 type, match, match_len);
4308}
4309
4310
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004311static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004312{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004313 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004314 int ret = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004315
4316 if (nl80211_alloc_mgmt_handle(bss))
4317 return -1;
4318 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
4319 "handle %p", bss->nl_mgmt);
4320
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004321 if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
4322 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
4323
4324 /* register for any AUTH message */
4325 nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0);
4326 }
4327
Dmitry Shmidt051af732013-10-22 13:52:46 -07004328#ifdef CONFIG_INTERWORKING
4329 /* QoS Map Configure */
4330 if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004331 ret = -1;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004332#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004333#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004334 /* GAS Initial Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004335 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004336 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004337 /* GAS Initial Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004338 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004339 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004340 /* GAS Comeback Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004341 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004342 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004343 /* GAS Comeback Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004344 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004345 ret = -1;
Dmitry Shmidt18463232014-01-24 12:29:41 -08004346 /* Protected GAS Initial Request */
4347 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0a", 2) < 0)
4348 ret = -1;
4349 /* Protected GAS Initial Response */
4350 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0b", 2) < 0)
4351 ret = -1;
4352 /* Protected GAS Comeback Request */
4353 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0c", 2) < 0)
4354 ret = -1;
4355 /* Protected GAS Comeback Response */
4356 if (nl80211_register_action_frame(bss, (u8 *) "\x09\x0d", 2) < 0)
4357 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004358#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
4359#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004360 /* P2P Public Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004361 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004362 (u8 *) "\x04\x09\x50\x6f\x9a\x09",
4363 6) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004364 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004365 /* P2P Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004366 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004367 (u8 *) "\x7f\x50\x6f\x9a\x09",
4368 5) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004369 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004370#endif /* CONFIG_P2P */
4371#ifdef CONFIG_IEEE80211W
4372 /* SA Query Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004373 if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004374 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004375#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004376#ifdef CONFIG_TDLS
4377 if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
4378 /* TDLS Discovery Response */
4379 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
4380 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004381 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004382 }
4383#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004384
4385 /* FT Action frames */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004386 if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004387 ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004388 else
4389 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
4390 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
4391
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004392 /* WNM - BSS Transition Management Request */
4393 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004394 ret = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004395 /* WNM-Sleep Mode Response */
4396 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004397 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004398
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004399#ifdef CONFIG_HS20
4400 /* WNM-Notification */
4401 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x1a", 2) < 0)
4402 return -1;
4403#endif /* CONFIG_HS20 */
4404
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004405 nl80211_mgmt_handle_register_eloop(bss);
4406
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004407 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004408}
4409
4410
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004411static int nl80211_register_spurious_class3(struct i802_bss *bss)
4412{
4413 struct wpa_driver_nl80211_data *drv = bss->drv;
4414 struct nl_msg *msg;
4415 int ret = -1;
4416
4417 msg = nlmsg_alloc();
4418 if (!msg)
4419 return -1;
4420
4421 nl80211_cmd(drv, msg, 0, NL80211_CMD_UNEXPECTED_FRAME);
4422
4423 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
4424
4425 ret = send_and_recv(drv->global, bss->nl_mgmt, msg, NULL, NULL);
4426 msg = NULL;
4427 if (ret) {
4428 wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
4429 "failed: ret=%d (%s)",
4430 ret, strerror(-ret));
4431 goto nla_put_failure;
4432 }
4433 ret = 0;
4434nla_put_failure:
4435 nlmsg_free(msg);
4436 return ret;
4437}
4438
4439
4440static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
4441{
4442 static const int stypes[] = {
4443 WLAN_FC_STYPE_AUTH,
4444 WLAN_FC_STYPE_ASSOC_REQ,
4445 WLAN_FC_STYPE_REASSOC_REQ,
4446 WLAN_FC_STYPE_DISASSOC,
4447 WLAN_FC_STYPE_DEAUTH,
4448 WLAN_FC_STYPE_ACTION,
4449 WLAN_FC_STYPE_PROBE_REQ,
4450/* Beacon doesn't work as mac80211 doesn't currently allow
4451 * it, but it wouldn't really be the right thing anyway as
4452 * it isn't per interface ... maybe just dump the scan
4453 * results periodically for OLBC?
4454 */
4455// WLAN_FC_STYPE_BEACON,
4456 };
4457 unsigned int i;
4458
4459 if (nl80211_alloc_mgmt_handle(bss))
4460 return -1;
4461 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
4462 "handle %p", bss->nl_mgmt);
4463
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004464 for (i = 0; i < ARRAY_SIZE(stypes); i++) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004465 if (nl80211_register_frame(bss, bss->nl_mgmt,
4466 (WLAN_FC_TYPE_MGMT << 2) |
4467 (stypes[i] << 4),
4468 NULL, 0) < 0) {
4469 goto out_err;
4470 }
4471 }
4472
4473 if (nl80211_register_spurious_class3(bss))
4474 goto out_err;
4475
4476 if (nl80211_get_wiphy_data_ap(bss) == NULL)
4477 goto out_err;
4478
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004479 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004480 return 0;
4481
4482out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004483 nl_destroy_handles(&bss->nl_mgmt);
4484 return -1;
4485}
4486
4487
4488static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)
4489{
4490 if (nl80211_alloc_mgmt_handle(bss))
4491 return -1;
4492 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
4493 "handle %p (device SME)", bss->nl_mgmt);
4494
4495 if (nl80211_register_frame(bss, bss->nl_mgmt,
4496 (WLAN_FC_TYPE_MGMT << 2) |
4497 (WLAN_FC_STYPE_ACTION << 4),
4498 NULL, 0) < 0)
4499 goto out_err;
4500
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004501 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004502 return 0;
4503
4504out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004505 nl_destroy_handles(&bss->nl_mgmt);
4506 return -1;
4507}
4508
4509
4510static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
4511{
4512 if (bss->nl_mgmt == NULL)
4513 return;
4514 wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
4515 "(%s)", bss->nl_mgmt, reason);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004516 nl80211_destroy_eloop_handle(&bss->nl_mgmt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004517
4518 nl80211_put_wiphy_data_ap(bss);
4519}
4520
4521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004522static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
4523{
4524 wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
4525}
4526
4527
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004528static void nl80211_del_p2pdev(struct i802_bss *bss)
4529{
4530 struct wpa_driver_nl80211_data *drv = bss->drv;
4531 struct nl_msg *msg;
4532 int ret;
4533
4534 msg = nlmsg_alloc();
4535 if (!msg)
4536 return;
4537
4538 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
4539 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
4540
4541 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4542 msg = NULL;
4543
4544 wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
4545 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004546 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004547
4548nla_put_failure:
4549 nlmsg_free(msg);
4550}
4551
4552
4553static int nl80211_set_p2pdev(struct i802_bss *bss, int start)
4554{
4555 struct wpa_driver_nl80211_data *drv = bss->drv;
4556 struct nl_msg *msg;
4557 int ret = -1;
4558
4559 msg = nlmsg_alloc();
4560 if (!msg)
4561 return -1;
4562
4563 if (start)
4564 nl80211_cmd(drv, msg, 0, NL80211_CMD_START_P2P_DEVICE);
4565 else
4566 nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_P2P_DEVICE);
4567
4568 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
4569
4570 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4571 msg = NULL;
4572
4573 wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
4574 start ? "Start" : "Stop",
4575 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004576 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004577
4578nla_put_failure:
4579 nlmsg_free(msg);
4580 return ret;
4581}
4582
4583
4584static int i802_set_iface_flags(struct i802_bss *bss, int up)
4585{
4586 enum nl80211_iftype nlmode;
4587
4588 nlmode = nl80211_get_ifmode(bss);
4589 if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
4590 return linux_set_iface_flags(bss->drv->global->ioctl_sock,
4591 bss->ifname, up);
4592 }
4593
4594 /* P2P Device has start/stop which is equivalent */
4595 return nl80211_set_p2pdev(bss, up);
4596}
4597
4598
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004599static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004600wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
4601 const u8 *set_addr, int first)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004602{
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004603 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004604 int send_rfkill_event = 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004605 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004606
4607 drv->ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004608 bss->ifindex = drv->ifindex;
4609 bss->wdev_id = drv->global->if_add_wdevid;
4610 bss->wdev_id_set = drv->global->if_add_wdevid_set;
4611
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004612 bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;
4613 bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004614 drv->global->if_add_wdevid_set = 0;
4615
4616 if (wpa_driver_nl80211_capa(drv))
4617 return -1;
4618
4619 wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
4620 bss->ifname, drv->phyname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004621
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004622 if (set_addr &&
4623 (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) ||
4624 linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
4625 set_addr)))
4626 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004627
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004628 if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
4629 drv->start_mode_ap = 1;
4630
4631 if (drv->hostapd)
4632 nlmode = NL80211_IFTYPE_AP;
4633 else if (bss->if_dynamic)
4634 nlmode = nl80211_get_ifmode(bss);
4635 else
4636 nlmode = NL80211_IFTYPE_STATION;
4637
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004638 if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004639 wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004640 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004641 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004642
4643 if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
4644 int ret = nl80211_set_p2pdev(bss, 1);
4645 if (ret < 0)
4646 wpa_printf(MSG_ERROR, "nl80211: Could not start P2P device");
4647 nl80211_get_macaddr(bss);
4648 return ret;
4649 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004650
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004651 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004652 if (rfkill_is_blocked(drv->rfkill)) {
4653 wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
4654 "interface '%s' due to rfkill",
4655 bss->ifname);
4656 drv->if_disabled = 1;
4657 send_rfkill_event = 1;
4658 } else {
4659 wpa_printf(MSG_ERROR, "nl80211: Could not set "
4660 "interface '%s' UP", bss->ifname);
4661 return -1;
4662 }
4663 }
4664
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004665 if (!drv->hostapd)
4666 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
4667 1, IF_OPER_DORMANT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004668
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004669 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
4670 bss->addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004671 return -1;
4672
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004673 if (send_rfkill_event) {
4674 eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
4675 drv, drv->ctx);
4676 }
4677
4678 return 0;
4679}
4680
4681
4682static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
4683{
4684 struct nl_msg *msg;
4685
4686 msg = nlmsg_alloc();
4687 if (!msg)
4688 return -ENOMEM;
4689
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004690 wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
4691 drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004692 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004693 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4694
4695 return send_and_recv_msgs(drv, msg, NULL, NULL);
4696 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004697 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004698 return -ENOBUFS;
4699}
4700
4701
4702/**
4703 * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004704 * @bss: Pointer to private nl80211 data from wpa_driver_nl80211_init()
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004705 *
4706 * Shut down driver interface and processing of driver events. Free
4707 * private data buffer if one was allocated in wpa_driver_nl80211_init().
4708 */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004709static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004710{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711 struct wpa_driver_nl80211_data *drv = bss->drv;
4712
Dmitry Shmidt04949592012-07-19 12:16:46 -07004713 bss->in_deinit = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004714 if (drv->data_tx_status)
4715 eloop_unregister_read_sock(drv->eapol_tx_sock);
4716 if (drv->eapol_tx_sock >= 0)
4717 close(drv->eapol_tx_sock);
4718
4719 if (bss->nl_preq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004720 wpa_driver_nl80211_probe_req_report(bss, 0);
4721 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004722 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
4723 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004724 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
4725 "interface %s from bridge %s: %s",
4726 bss->ifname, bss->brname, strerror(errno));
4727 }
4728 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004729 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004730 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
4731 "bridge %s: %s",
4732 bss->brname, strerror(errno));
4733 }
4734
4735 nl80211_remove_monitor_interface(drv);
4736
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004737 if (is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004738 wpa_driver_nl80211_del_beacon(drv);
4739
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004740 if (drv->eapol_sock >= 0) {
4741 eloop_unregister_read_sock(drv->eapol_sock);
4742 close(drv->eapol_sock);
4743 }
4744
4745 if (drv->if_indices != drv->default_if_indices)
4746 os_free(drv->if_indices);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004747
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004748 if (drv->disabled_11b_rates)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004749 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
4750
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004751 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
4752 IF_OPER_UP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004753 rfkill_deinit(drv->rfkill);
4754
4755 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
4756
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004757 if (!drv->start_iface_up)
4758 (void) i802_set_iface_flags(bss, 0);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004759 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004760 if (!drv->hostapd || !drv->start_mode_ap)
4761 wpa_driver_nl80211_set_mode(bss,
4762 NL80211_IFTYPE_STATION);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004763 nl80211_mgmt_unsubscribe(bss, "deinit");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004764 } else {
4765 nl80211_mgmt_unsubscribe(bss, "deinit");
4766 nl80211_del_p2pdev(bss);
4767 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004768 nl_cb_put(drv->nl_cb);
4769
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004770 nl80211_destroy_bss(drv->first_bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004771
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004772 os_free(drv->filter_ssids);
4773
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004774 os_free(drv->auth_ie);
4775
4776 if (drv->in_interface_list)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004777 dl_list_del(&drv->list);
4778
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004779 os_free(drv->extended_capa);
4780 os_free(drv->extended_capa_mask);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004781 os_free(drv->first_bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004782 os_free(drv);
4783}
4784
4785
4786/**
4787 * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion
4788 * @eloop_ctx: Driver private data
4789 * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init()
4790 *
4791 * This function can be used as registered timeout when starting a scan to
4792 * generate a scan completed event if the driver does not report this.
4793 */
4794static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
4795{
4796 struct wpa_driver_nl80211_data *drv = eloop_ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004797 if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004798 wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004799 drv->ap_scan_as_station);
4800 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004801 }
4802 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
4803 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
4804}
4805
4806
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004807static struct nl_msg *
4808nl80211_scan_common(struct wpa_driver_nl80211_data *drv, u8 cmd,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004809 struct wpa_driver_scan_params *params, u64 *wdev_id)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004810{
4811 struct nl_msg *msg;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004812 size_t i;
4813
4814 msg = nlmsg_alloc();
4815 if (!msg)
4816 return NULL;
4817
4818 nl80211_cmd(drv, msg, 0, cmd);
4819
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004820 if (!wdev_id)
4821 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4822 else
4823 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, *wdev_id);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004824
4825 if (params->num_ssids) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004826 struct nlattr *ssids;
4827
4828 ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004829 if (ssids == NULL)
4830 goto fail;
4831 for (i = 0; i < params->num_ssids; i++) {
4832 wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
4833 params->ssids[i].ssid,
4834 params->ssids[i].ssid_len);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004835 if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
4836 params->ssids[i].ssid) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004837 goto fail;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004838 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004839 nla_nest_end(msg, ssids);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004840 }
4841
4842 if (params->extra_ies) {
4843 wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
4844 params->extra_ies, params->extra_ies_len);
4845 if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,
4846 params->extra_ies) < 0)
4847 goto fail;
4848 }
4849
4850 if (params->freqs) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004851 struct nlattr *freqs;
4852 freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004853 if (freqs == NULL)
4854 goto fail;
4855 for (i = 0; params->freqs[i]; i++) {
4856 wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
4857 "MHz", params->freqs[i]);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004858 if (nla_put_u32(msg, i + 1, params->freqs[i]) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004859 goto fail;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004860 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004861 nla_nest_end(msg, freqs);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004862 }
4863
4864 os_free(drv->filter_ssids);
4865 drv->filter_ssids = params->filter_ssids;
4866 params->filter_ssids = NULL;
4867 drv->num_filter_ssids = params->num_filter_ssids;
4868
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004869 if (params->only_new_results) {
4870 wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH");
4871 NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS,
4872 NL80211_SCAN_FLAG_FLUSH);
4873 }
4874
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004875 return msg;
4876
4877fail:
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004878nla_put_failure:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004879 nlmsg_free(msg);
4880 return NULL;
4881}
4882
4883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004884/**
4885 * wpa_driver_nl80211_scan - Request the driver to initiate scan
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004886 * @bss: Pointer to private driver data from wpa_driver_nl80211_init()
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004887 * @params: Scan parameters
4888 * Returns: 0 on success, -1 on failure
4889 */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004890static int wpa_driver_nl80211_scan(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004891 struct wpa_driver_scan_params *params)
4892{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004893 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004894 int ret = -1, timeout;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004895 struct nl_msg *msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004896
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004897 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004898 drv->scan_for_auth = 0;
4899
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004900 msg = nl80211_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params,
4901 bss->wdev_id_set ? &bss->wdev_id : NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004902 if (!msg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004903 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004904
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004905 if (params->p2p_probe) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004906 struct nlattr *rates;
4907
Dmitry Shmidt04949592012-07-19 12:16:46 -07004908 wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
4909
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004910 rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004911 if (rates == NULL)
4912 goto nla_put_failure;
4913
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004914 /*
4915 * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
4916 * by masking out everything else apart from the OFDM rates 6,
4917 * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
4918 * rates are left enabled.
4919 */
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004920 NLA_PUT(msg, NL80211_BAND_2GHZ, 8,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004921 "\x0c\x12\x18\x24\x30\x48\x60\x6c");
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004922 nla_nest_end(msg, rates);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004923
4924 NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
4925 }
4926
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004927 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4928 msg = NULL;
4929 if (ret) {
4930 wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
4931 "(%s)", ret, strerror(-ret));
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004932 if (drv->hostapd && is_ap_interface(drv->nlmode)) {
Dmitry Shmidted003d22014-02-06 10:09:12 -08004933 enum nl80211_iftype old_mode = drv->nlmode;
4934
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004935 /*
4936 * mac80211 does not allow scan requests in AP mode, so
4937 * try to do this in station mode.
4938 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004939 if (wpa_driver_nl80211_set_mode(
4940 bss, NL80211_IFTYPE_STATION))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004941 goto nla_put_failure;
4942
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004943 if (wpa_driver_nl80211_scan(bss, params)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004944 wpa_driver_nl80211_set_mode(bss, drv->nlmode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004945 goto nla_put_failure;
4946 }
4947
4948 /* Restore AP mode when processing scan results */
Dmitry Shmidted003d22014-02-06 10:09:12 -08004949 drv->ap_scan_as_station = old_mode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004950 ret = 0;
4951 } else
4952 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004953 }
4954
Dmitry Shmidt56052862013-10-04 10:23:25 -07004955 drv->scan_state = SCAN_REQUESTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004956 /* Not all drivers generate "scan completed" wireless event, so try to
4957 * read results after a timeout. */
4958 timeout = 10;
4959 if (drv->scan_complete_events) {
4960 /*
4961 * The driver seems to deliver events to notify when scan is
4962 * complete, so use longer timeout to avoid race conditions
4963 * with scanning and following association request.
4964 */
4965 timeout = 30;
4966 }
4967 wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
4968 "seconds", ret, timeout);
4969 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
4970 eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
4971 drv, drv->ctx);
4972
4973nla_put_failure:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004974 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004975 return ret;
4976}
4977
4978
4979/**
4980 * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
4981 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
4982 * @params: Scan parameters
4983 * @interval: Interval between scan cycles in milliseconds
4984 * Returns: 0 on success, -1 on failure or if not supported
4985 */
4986static int wpa_driver_nl80211_sched_scan(void *priv,
4987 struct wpa_driver_scan_params *params,
4988 u32 interval)
4989{
4990 struct i802_bss *bss = priv;
4991 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004992 int ret = -1;
4993 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004994 size_t i;
4995
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004996 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
4997
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004998#ifdef ANDROID
4999 if (!drv->capa.sched_scan_supported)
5000 return android_pno_start(bss, params);
5001#endif /* ANDROID */
5002
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005003 msg = nl80211_scan_common(drv, NL80211_CMD_START_SCHED_SCAN, params,
5004 bss->wdev_id_set ? &bss->wdev_id : NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005005 if (!msg)
5006 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005007
5008 NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);
5009
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005010 if ((drv->num_filter_ssids &&
5011 (int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
5012 params->filter_rssi) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005013 struct nlattr *match_sets;
5014 match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005015 if (match_sets == NULL)
5016 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005017
5018 for (i = 0; i < drv->num_filter_ssids; i++) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005019 struct nlattr *match_set_ssid;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005020 wpa_hexdump_ascii(MSG_MSGDUMP,
5021 "nl80211: Sched scan filter SSID",
5022 drv->filter_ssids[i].ssid,
5023 drv->filter_ssids[i].ssid_len);
5024
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005025 match_set_ssid = nla_nest_start(msg, i + 1);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005026 if (match_set_ssid == NULL)
5027 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005028 NLA_PUT(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005029 drv->filter_ssids[i].ssid_len,
5030 drv->filter_ssids[i].ssid);
Dmitry Shmidt97672262014-02-03 13:02:54 -08005031 if (params->filter_rssi)
5032 NLA_PUT_U32(msg,
5033 NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
5034 params->filter_rssi);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005035
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005036 nla_nest_end(msg, match_set_ssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005037 }
5038
Dmitry Shmidt97672262014-02-03 13:02:54 -08005039 /*
5040 * Due to backward compatibility code, newer kernels treat this
5041 * matchset (with only an RSSI filter) as the default for all
5042 * other matchsets, unless it's the only one, in which case the
5043 * matchset will actually allow all SSIDs above the RSSI.
5044 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005045 if (params->filter_rssi) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005046 struct nlattr *match_set_rssi;
5047 match_set_rssi = nla_nest_start(msg, 0);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005048 if (match_set_rssi == NULL)
5049 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005050 NLA_PUT_U32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005051 params->filter_rssi);
5052 wpa_printf(MSG_MSGDUMP,
5053 "nl80211: Sched scan RSSI filter %d dBm",
5054 params->filter_rssi);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005055 nla_nest_end(msg, match_set_rssi);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005056 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005057
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005058 nla_nest_end(msg, match_sets);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005059 }
5060
5061 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5062
5063 /* TODO: if we get an error here, we should fall back to normal scan */
5064
5065 msg = NULL;
5066 if (ret) {
5067 wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: "
5068 "ret=%d (%s)", ret, strerror(-ret));
5069 goto nla_put_failure;
5070 }
5071
5072 wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) - "
5073 "scan interval %d msec", ret, interval);
5074
5075nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005076 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005077 return ret;
5078}
5079
5080
5081/**
5082 * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan
5083 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
5084 * Returns: 0 on success, -1 on failure or if not supported
5085 */
5086static int wpa_driver_nl80211_stop_sched_scan(void *priv)
5087{
5088 struct i802_bss *bss = priv;
5089 struct wpa_driver_nl80211_data *drv = bss->drv;
5090 int ret = 0;
5091 struct nl_msg *msg;
5092
5093#ifdef ANDROID
5094 if (!drv->capa.sched_scan_supported)
5095 return android_pno_stop(bss);
5096#endif /* ANDROID */
5097
5098 msg = nlmsg_alloc();
5099 if (!msg)
5100 return -1;
5101
5102 nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_SCHED_SCAN);
5103
5104 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5105
5106 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5107 msg = NULL;
5108 if (ret) {
5109 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop failed: "
5110 "ret=%d (%s)", ret, strerror(-ret));
5111 goto nla_put_failure;
5112 }
5113
5114 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop sent (ret=%d)", ret);
5115
5116nla_put_failure:
5117 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005118 return ret;
5119}
5120
5121
5122static const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
5123{
5124 const u8 *end, *pos;
5125
5126 if (ies == NULL)
5127 return NULL;
5128
5129 pos = ies;
5130 end = ies + ies_len;
5131
5132 while (pos + 1 < end) {
5133 if (pos + 2 + pos[1] > end)
5134 break;
5135 if (pos[0] == ie)
5136 return pos;
5137 pos += 2 + pos[1];
5138 }
5139
5140 return NULL;
5141}
5142
5143
5144static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
5145 const u8 *ie, size_t ie_len)
5146{
5147 const u8 *ssid;
5148 size_t i;
5149
5150 if (drv->filter_ssids == NULL)
5151 return 0;
5152
5153 ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID);
5154 if (ssid == NULL)
5155 return 1;
5156
5157 for (i = 0; i < drv->num_filter_ssids; i++) {
5158 if (ssid[1] == drv->filter_ssids[i].ssid_len &&
5159 os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==
5160 0)
5161 return 0;
5162 }
5163
5164 return 1;
5165}
5166
5167
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005168static int bss_info_handler(struct nl_msg *msg, void *arg)
5169{
5170 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5171 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5172 struct nlattr *bss[NL80211_BSS_MAX + 1];
5173 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
5174 [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
5175 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
5176 [NL80211_BSS_TSF] = { .type = NLA_U64 },
5177 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
5178 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
5179 [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
5180 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
5181 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
5182 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
5183 [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
5184 [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
5185 };
5186 struct nl80211_bss_info_arg *_arg = arg;
5187 struct wpa_scan_results *res = _arg->res;
5188 struct wpa_scan_res **tmp;
5189 struct wpa_scan_res *r;
5190 const u8 *ie, *beacon_ie;
5191 size_t ie_len, beacon_ie_len;
5192 u8 *pos;
Jouni Malinen87fd2792011-05-16 18:35:42 +03005193 size_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005194
5195 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5196 genlmsg_attrlen(gnlh, 0), NULL);
5197 if (!tb[NL80211_ATTR_BSS])
5198 return NL_SKIP;
5199 if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
5200 bss_policy))
5201 return NL_SKIP;
Jouni Malinen87fd2792011-05-16 18:35:42 +03005202 if (bss[NL80211_BSS_STATUS]) {
5203 enum nl80211_bss_status status;
5204 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
5205 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
5206 bss[NL80211_BSS_FREQUENCY]) {
5207 _arg->assoc_freq =
5208 nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
5209 wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
5210 _arg->assoc_freq);
5211 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005212 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
5213 bss[NL80211_BSS_BSSID]) {
5214 os_memcpy(_arg->assoc_bssid,
5215 nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
5216 wpa_printf(MSG_DEBUG, "nl80211: Associated with "
5217 MACSTR, MAC2STR(_arg->assoc_bssid));
5218 }
Jouni Malinen87fd2792011-05-16 18:35:42 +03005219 }
5220 if (!res)
5221 return NL_SKIP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005222 if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
5223 ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
5224 ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
5225 } else {
5226 ie = NULL;
5227 ie_len = 0;
5228 }
5229 if (bss[NL80211_BSS_BEACON_IES]) {
5230 beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);
5231 beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);
5232 } else {
5233 beacon_ie = NULL;
5234 beacon_ie_len = 0;
5235 }
5236
5237 if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie,
5238 ie ? ie_len : beacon_ie_len))
5239 return NL_SKIP;
5240
5241 r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);
5242 if (r == NULL)
5243 return NL_SKIP;
5244 if (bss[NL80211_BSS_BSSID])
5245 os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),
5246 ETH_ALEN);
5247 if (bss[NL80211_BSS_FREQUENCY])
5248 r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
5249 if (bss[NL80211_BSS_BEACON_INTERVAL])
5250 r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);
5251 if (bss[NL80211_BSS_CAPABILITY])
5252 r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
5253 r->flags |= WPA_SCAN_NOISE_INVALID;
5254 if (bss[NL80211_BSS_SIGNAL_MBM]) {
5255 r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
5256 r->level /= 100; /* mBm to dBm */
5257 r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;
5258 } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
5259 r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005260 r->flags |= WPA_SCAN_QUAL_INVALID;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005261 } else
5262 r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;
5263 if (bss[NL80211_BSS_TSF])
5264 r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);
5265 if (bss[NL80211_BSS_SEEN_MS_AGO])
5266 r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
5267 r->ie_len = ie_len;
5268 pos = (u8 *) (r + 1);
5269 if (ie) {
5270 os_memcpy(pos, ie, ie_len);
5271 pos += ie_len;
5272 }
5273 r->beacon_ie_len = beacon_ie_len;
5274 if (beacon_ie)
5275 os_memcpy(pos, beacon_ie, beacon_ie_len);
5276
5277 if (bss[NL80211_BSS_STATUS]) {
5278 enum nl80211_bss_status status;
5279 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
5280 switch (status) {
5281 case NL80211_BSS_STATUS_AUTHENTICATED:
5282 r->flags |= WPA_SCAN_AUTHENTICATED;
5283 break;
5284 case NL80211_BSS_STATUS_ASSOCIATED:
5285 r->flags |= WPA_SCAN_ASSOCIATED;
5286 break;
5287 default:
5288 break;
5289 }
5290 }
5291
Jouni Malinen87fd2792011-05-16 18:35:42 +03005292 /*
5293 * cfg80211 maintains separate BSS table entries for APs if the same
5294 * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does
5295 * not use frequency as a separate key in the BSS table, so filter out
5296 * duplicated entries. Prefer associated BSS entry in such a case in
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005297 * order to get the correct frequency into the BSS table. Similarly,
5298 * prefer newer entries over older.
Jouni Malinen87fd2792011-05-16 18:35:42 +03005299 */
5300 for (i = 0; i < res->num; i++) {
5301 const u8 *s1, *s2;
5302 if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)
5303 continue;
5304
5305 s1 = nl80211_get_ie((u8 *) (res->res[i] + 1),
5306 res->res[i]->ie_len, WLAN_EID_SSID);
5307 s2 = nl80211_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
5308 if (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||
5309 os_memcmp(s1, s2, 2 + s1[1]) != 0)
5310 continue;
5311
5312 /* Same BSSID,SSID was already included in scan results */
5313 wpa_printf(MSG_DEBUG, "nl80211: Remove duplicated scan result "
5314 "for " MACSTR, MAC2STR(r->bssid));
5315
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005316 if (((r->flags & WPA_SCAN_ASSOCIATED) &&
5317 !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) ||
5318 r->age < res->res[i]->age) {
Jouni Malinen87fd2792011-05-16 18:35:42 +03005319 os_free(res->res[i]);
5320 res->res[i] = r;
5321 } else
5322 os_free(r);
5323 return NL_SKIP;
5324 }
5325
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005326 tmp = os_realloc_array(res->res, res->num + 1,
5327 sizeof(struct wpa_scan_res *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005328 if (tmp == NULL) {
5329 os_free(r);
5330 return NL_SKIP;
5331 }
5332 tmp[res->num++] = r;
5333 res->res = tmp;
5334
5335 return NL_SKIP;
5336}
5337
5338
5339static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
5340 const u8 *addr)
5341{
5342 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
5343 wpa_printf(MSG_DEBUG, "nl80211: Clear possible state "
5344 "mismatch (" MACSTR ")", MAC2STR(addr));
5345 wpa_driver_nl80211_mlme(drv, addr,
5346 NL80211_CMD_DEAUTHENTICATE,
5347 WLAN_REASON_PREV_AUTH_NOT_VALID, 1);
5348 }
5349}
5350
5351
5352static void wpa_driver_nl80211_check_bss_status(
5353 struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res)
5354{
5355 size_t i;
5356
5357 for (i = 0; i < res->num; i++) {
5358 struct wpa_scan_res *r = res->res[i];
5359 if (r->flags & WPA_SCAN_AUTHENTICATED) {
5360 wpa_printf(MSG_DEBUG, "nl80211: Scan results "
5361 "indicates BSS status with " MACSTR
5362 " as authenticated",
5363 MAC2STR(r->bssid));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005364 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005365 os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&
5366 os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=
5367 0) {
5368 wpa_printf(MSG_DEBUG, "nl80211: Unknown BSSID"
5369 " in local state (auth=" MACSTR
5370 " assoc=" MACSTR ")",
5371 MAC2STR(drv->auth_bssid),
5372 MAC2STR(drv->bssid));
5373 clear_state_mismatch(drv, r->bssid);
5374 }
5375 }
5376
5377 if (r->flags & WPA_SCAN_ASSOCIATED) {
5378 wpa_printf(MSG_DEBUG, "nl80211: Scan results "
5379 "indicate BSS status with " MACSTR
5380 " as associated",
5381 MAC2STR(r->bssid));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005382 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005383 !drv->associated) {
5384 wpa_printf(MSG_DEBUG, "nl80211: Local state "
5385 "(not associated) does not match "
5386 "with BSS state");
5387 clear_state_mismatch(drv, r->bssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005388 } else if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005389 os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
5390 0) {
5391 wpa_printf(MSG_DEBUG, "nl80211: Local state "
5392 "(associated with " MACSTR ") does "
5393 "not match with BSS state",
5394 MAC2STR(drv->bssid));
5395 clear_state_mismatch(drv, r->bssid);
5396 clear_state_mismatch(drv, drv->bssid);
5397 }
5398 }
5399 }
5400}
5401
5402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005403static struct wpa_scan_results *
5404nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
5405{
5406 struct nl_msg *msg;
5407 struct wpa_scan_results *res;
5408 int ret;
5409 struct nl80211_bss_info_arg arg;
5410
5411 res = os_zalloc(sizeof(*res));
5412 if (res == NULL)
5413 return NULL;
5414 msg = nlmsg_alloc();
5415 if (!msg)
5416 goto nla_put_failure;
5417
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005418 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005419 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005420 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005421
5422 arg.drv = drv;
5423 arg.res = res;
5424 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
5425 msg = NULL;
5426 if (ret == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005427 wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu "
5428 "BSSes)", (unsigned long) res->num);
5429 nl80211_get_noise_for_scan_results(drv, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005430 return res;
5431 }
5432 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
5433 "(%s)", ret, strerror(-ret));
5434nla_put_failure:
5435 nlmsg_free(msg);
5436 wpa_scan_results_free(res);
5437 return NULL;
5438}
5439
5440
5441/**
5442 * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
5443 * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
5444 * Returns: Scan results on success, -1 on failure
5445 */
5446static struct wpa_scan_results *
5447wpa_driver_nl80211_get_scan_results(void *priv)
5448{
5449 struct i802_bss *bss = priv;
5450 struct wpa_driver_nl80211_data *drv = bss->drv;
5451 struct wpa_scan_results *res;
5452
5453 res = nl80211_get_scan_results(drv);
5454 if (res)
5455 wpa_driver_nl80211_check_bss_status(drv, res);
5456 return res;
5457}
5458
5459
5460static void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv)
5461{
5462 struct wpa_scan_results *res;
5463 size_t i;
5464
5465 res = nl80211_get_scan_results(drv);
5466 if (res == NULL) {
5467 wpa_printf(MSG_DEBUG, "nl80211: Failed to get scan results");
5468 return;
5469 }
5470
5471 wpa_printf(MSG_DEBUG, "nl80211: Scan result dump");
5472 for (i = 0; i < res->num; i++) {
5473 struct wpa_scan_res *r = res->res[i];
5474 wpa_printf(MSG_DEBUG, "nl80211: %d/%d " MACSTR "%s%s",
5475 (int) i, (int) res->num, MAC2STR(r->bssid),
5476 r->flags & WPA_SCAN_AUTHENTICATED ? " [auth]" : "",
5477 r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : "");
5478 }
5479
5480 wpa_scan_results_free(res);
5481}
5482
5483
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005484static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len)
5485{
5486 switch (alg) {
5487 case WPA_ALG_WEP:
5488 if (key_len == 5)
5489 return WLAN_CIPHER_SUITE_WEP40;
5490 return WLAN_CIPHER_SUITE_WEP104;
5491 case WPA_ALG_TKIP:
5492 return WLAN_CIPHER_SUITE_TKIP;
5493 case WPA_ALG_CCMP:
5494 return WLAN_CIPHER_SUITE_CCMP;
5495 case WPA_ALG_GCMP:
5496 return WLAN_CIPHER_SUITE_GCMP;
5497 case WPA_ALG_CCMP_256:
5498 return WLAN_CIPHER_SUITE_CCMP_256;
5499 case WPA_ALG_GCMP_256:
5500 return WLAN_CIPHER_SUITE_GCMP_256;
5501 case WPA_ALG_IGTK:
5502 return WLAN_CIPHER_SUITE_AES_CMAC;
5503 case WPA_ALG_BIP_GMAC_128:
5504 return WLAN_CIPHER_SUITE_BIP_GMAC_128;
5505 case WPA_ALG_BIP_GMAC_256:
5506 return WLAN_CIPHER_SUITE_BIP_GMAC_256;
5507 case WPA_ALG_BIP_CMAC_256:
5508 return WLAN_CIPHER_SUITE_BIP_CMAC_256;
5509 case WPA_ALG_SMS4:
5510 return WLAN_CIPHER_SUITE_SMS4;
5511 case WPA_ALG_KRK:
5512 return WLAN_CIPHER_SUITE_KRK;
5513 case WPA_ALG_NONE:
5514 case WPA_ALG_PMK:
5515 wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d",
5516 alg);
5517 return 0;
5518 }
5519
5520 wpa_printf(MSG_ERROR, "nl80211: Unsupported encryption algorithm %d",
5521 alg);
5522 return 0;
5523}
5524
5525
5526static u32 wpa_cipher_to_cipher_suite(unsigned int cipher)
5527{
5528 switch (cipher) {
5529 case WPA_CIPHER_CCMP_256:
5530 return WLAN_CIPHER_SUITE_CCMP_256;
5531 case WPA_CIPHER_GCMP_256:
5532 return WLAN_CIPHER_SUITE_GCMP_256;
5533 case WPA_CIPHER_CCMP:
5534 return WLAN_CIPHER_SUITE_CCMP;
5535 case WPA_CIPHER_GCMP:
5536 return WLAN_CIPHER_SUITE_GCMP;
5537 case WPA_CIPHER_TKIP:
5538 return WLAN_CIPHER_SUITE_TKIP;
5539 case WPA_CIPHER_WEP104:
5540 return WLAN_CIPHER_SUITE_WEP104;
5541 case WPA_CIPHER_WEP40:
5542 return WLAN_CIPHER_SUITE_WEP40;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08005543 case WPA_CIPHER_GTK_NOT_USED:
5544 return WLAN_CIPHER_SUITE_NO_GROUP_ADDR;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005545 }
5546
5547 return 0;
5548}
5549
5550
5551static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[],
5552 int max_suites)
5553{
5554 int num_suites = 0;
5555
5556 if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP_256)
5557 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP_256;
5558 if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP_256)
5559 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP_256;
5560 if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP)
5561 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
5562 if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP)
5563 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;
5564 if (num_suites < max_suites && ciphers & WPA_CIPHER_TKIP)
5565 suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
5566 if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP104)
5567 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
5568 if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP40)
5569 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
5570
5571 return num_suites;
5572}
5573
5574
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005575static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005576 enum wpa_alg alg, const u8 *addr,
5577 int key_idx, int set_tx,
5578 const u8 *seq, size_t seq_len,
5579 const u8 *key, size_t key_len)
5580{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005581 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005582 int ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005583 struct nl_msg *msg;
5584 int ret;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005585 int tdls = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005586
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005587 /* Ignore for P2P Device */
5588 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
5589 return 0;
5590
5591 ifindex = if_nametoindex(ifname);
5592 wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005593 "set_tx=%d seq_len=%lu key_len=%lu",
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005594 __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005595 (unsigned long) seq_len, (unsigned long) key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005596#ifdef CONFIG_TDLS
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005597 if (key_idx == -1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005598 key_idx = 0;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005599 tdls = 1;
5600 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005601#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005602
5603 msg = nlmsg_alloc();
5604 if (!msg)
5605 return -ENOMEM;
5606
5607 if (alg == WPA_ALG_NONE) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005608 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005609 } else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005610 nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005611 NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005612 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5613 wpa_alg_to_cipher_suite(alg, key_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614 }
5615
5616 if (seq && seq_len)
5617 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq);
5618
5619 if (addr && !is_broadcast_ether_addr(addr)) {
5620 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
5621 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
5622
5623 if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
5624 wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK");
5625 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE,
5626 NL80211_KEYTYPE_GROUP);
5627 }
5628 } else if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005629 struct nlattr *types;
5630
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005631 wpa_printf(MSG_DEBUG, " broadcast key");
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005632
5633 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005634 if (!types)
5635 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005636 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
5637 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005638 }
5639 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
5640 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
5641
5642 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5643 if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
5644 ret = 0;
5645 if (ret)
5646 wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)",
5647 ret, strerror(-ret));
5648
5649 /*
5650 * If we failed or don't need to set the default TX key (below),
5651 * we're done here.
5652 */
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005653 if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005654 return ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005655 if (is_ap_interface(drv->nlmode) && addr &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005656 !is_broadcast_ether_addr(addr))
5657 return ret;
5658
5659 msg = nlmsg_alloc();
5660 if (!msg)
5661 return -ENOMEM;
5662
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005663 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005664 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
5665 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
5666 if (alg == WPA_ALG_IGTK)
5667 NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT);
5668 else
5669 NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
5670 if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005671 struct nlattr *types;
5672
5673 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005674 if (!types)
5675 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005676 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
5677 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005678 } else if (addr) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005679 struct nlattr *types;
5680
5681 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005682 if (!types)
5683 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005684 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST);
5685 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005686 }
5687
5688 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5689 if (ret == -ENOENT)
5690 ret = 0;
5691 if (ret)
5692 wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
5693 "err=%d %s)", ret, strerror(-ret));
5694 return ret;
5695
5696nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005697 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005698 return -ENOBUFS;
5699}
5700
5701
5702static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,
5703 int key_idx, int defkey,
5704 const u8 *seq, size_t seq_len,
5705 const u8 *key, size_t key_len)
5706{
5707 struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);
5708 if (!key_attr)
5709 return -1;
5710
5711 if (defkey && alg == WPA_ALG_IGTK)
5712 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT);
5713 else if (defkey)
5714 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
5715
5716 NLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);
5717
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005718 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5719 wpa_alg_to_cipher_suite(alg, key_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005720
5721 if (seq && seq_len)
5722 NLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);
5723
5724 NLA_PUT(msg, NL80211_KEY_DATA, key_len, key);
5725
5726 nla_nest_end(msg, key_attr);
5727
5728 return 0;
5729 nla_put_failure:
5730 return -1;
5731}
5732
5733
5734static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
5735 struct nl_msg *msg)
5736{
5737 int i, privacy = 0;
5738 struct nlattr *nl_keys, *nl_key;
5739
5740 for (i = 0; i < 4; i++) {
5741 if (!params->wep_key[i])
5742 continue;
5743 privacy = 1;
5744 break;
5745 }
5746 if (params->wps == WPS_MODE_PRIVACY)
5747 privacy = 1;
5748 if (params->pairwise_suite &&
5749 params->pairwise_suite != WPA_CIPHER_NONE)
5750 privacy = 1;
5751
5752 if (!privacy)
5753 return 0;
5754
5755 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
5756
5757 nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
5758 if (!nl_keys)
5759 goto nla_put_failure;
5760
5761 for (i = 0; i < 4; i++) {
5762 if (!params->wep_key[i])
5763 continue;
5764
5765 nl_key = nla_nest_start(msg, i);
5766 if (!nl_key)
5767 goto nla_put_failure;
5768
5769 NLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],
5770 params->wep_key[i]);
5771 if (params->wep_key_len[i] == 5)
5772 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5773 WLAN_CIPHER_SUITE_WEP40);
5774 else
5775 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5776 WLAN_CIPHER_SUITE_WEP104);
5777
5778 NLA_PUT_U8(msg, NL80211_KEY_IDX, i);
5779
5780 if (i == params->wep_tx_keyidx)
5781 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
5782
5783 nla_nest_end(msg, nl_key);
5784 }
5785 nla_nest_end(msg, nl_keys);
5786
5787 return 0;
5788
5789nla_put_failure:
5790 return -ENOBUFS;
5791}
5792
5793
5794static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
5795 const u8 *addr, int cmd, u16 reason_code,
5796 int local_state_change)
5797{
5798 int ret = -1;
5799 struct nl_msg *msg;
5800
5801 msg = nlmsg_alloc();
5802 if (!msg)
5803 return -1;
5804
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005805 nl80211_cmd(drv, msg, 0, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005806
5807 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5808 NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005809 if (addr)
5810 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005811 if (local_state_change)
5812 NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);
5813
5814 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5815 msg = NULL;
5816 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005817 wpa_dbg(drv->ctx, MSG_DEBUG,
5818 "nl80211: MLME command failed: reason=%u ret=%d (%s)",
5819 reason_code, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005820 goto nla_put_failure;
5821 }
5822 ret = 0;
5823
5824nla_put_failure:
5825 nlmsg_free(msg);
5826 return ret;
5827}
5828
5829
5830static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005831 int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005832{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005833 int ret;
5834
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005835 wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005836 nl80211_mark_disconnected(drv);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005837 /* Disconnect command doesn't need BSSID - it uses cached value */
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005838 ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
5839 reason_code, 0);
5840 /*
5841 * For locally generated disconnect, supplicant already generates a
5842 * DEAUTH event, so ignore the event from NL80211.
5843 */
5844 drv->ignore_next_local_disconnect = ret == 0;
5845
5846 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005847}
5848
5849
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005850static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
5851 const u8 *addr, int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005852{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005853 struct wpa_driver_nl80211_data *drv = bss->drv;
5854 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005855 return wpa_driver_nl80211_disconnect(drv, reason_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005856 wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
5857 __func__, MAC2STR(addr), reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005858 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005859 if (drv->nlmode == NL80211_IFTYPE_ADHOC)
5860 return nl80211_leave_ibss(drv);
5861 return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
5862 reason_code, 0);
5863}
5864
5865
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005866static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
5867 struct wpa_driver_auth_params *params)
5868{
5869 int i;
5870
5871 drv->auth_freq = params->freq;
5872 drv->auth_alg = params->auth_alg;
5873 drv->auth_wep_tx_keyidx = params->wep_tx_keyidx;
5874 drv->auth_local_state_change = params->local_state_change;
5875 drv->auth_p2p = params->p2p;
5876
5877 if (params->bssid)
5878 os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);
5879 else
5880 os_memset(drv->auth_bssid_, 0, ETH_ALEN);
5881
5882 if (params->ssid) {
5883 os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);
5884 drv->auth_ssid_len = params->ssid_len;
5885 } else
5886 drv->auth_ssid_len = 0;
5887
5888
5889 os_free(drv->auth_ie);
5890 drv->auth_ie = NULL;
5891 drv->auth_ie_len = 0;
5892 if (params->ie) {
5893 drv->auth_ie = os_malloc(params->ie_len);
5894 if (drv->auth_ie) {
5895 os_memcpy(drv->auth_ie, params->ie, params->ie_len);
5896 drv->auth_ie_len = params->ie_len;
5897 }
5898 }
5899
5900 for (i = 0; i < 4; i++) {
5901 if (params->wep_key[i] && params->wep_key_len[i] &&
5902 params->wep_key_len[i] <= 16) {
5903 os_memcpy(drv->auth_wep_key[i], params->wep_key[i],
5904 params->wep_key_len[i]);
5905 drv->auth_wep_key_len[i] = params->wep_key_len[i];
5906 } else
5907 drv->auth_wep_key_len[i] = 0;
5908 }
5909}
5910
5911
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005912static int wpa_driver_nl80211_authenticate(
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005913 struct i802_bss *bss, struct wpa_driver_auth_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005914{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005915 struct wpa_driver_nl80211_data *drv = bss->drv;
5916 int ret = -1, i;
5917 struct nl_msg *msg;
5918 enum nl80211_auth_type type;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005919 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005920 int count = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005921 int is_retry;
5922
5923 is_retry = drv->retry_auth;
5924 drv->retry_auth = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005925
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005926 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005927 os_memset(drv->auth_bssid, 0, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005928 if (params->bssid)
5929 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
5930 else
5931 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005932 /* FIX: IBSS mode */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005933 nlmode = params->p2p ?
5934 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
5935 if (drv->nlmode != nlmode &&
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005936 wpa_driver_nl80211_set_mode(bss, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005937 return -1;
5938
5939retry:
5940 msg = nlmsg_alloc();
5941 if (!msg)
5942 return -1;
5943
5944 wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
5945 drv->ifindex);
5946
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005947 nl80211_cmd(drv, msg, 0, NL80211_CMD_AUTHENTICATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005948
5949 for (i = 0; i < 4; i++) {
5950 if (!params->wep_key[i])
5951 continue;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005952 wpa_driver_nl80211_set_key(bss->ifname, bss, WPA_ALG_WEP,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005953 NULL, i,
5954 i == params->wep_tx_keyidx, NULL, 0,
5955 params->wep_key[i],
5956 params->wep_key_len[i]);
5957 if (params->wep_tx_keyidx != i)
5958 continue;
5959 if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
5960 params->wep_key[i], params->wep_key_len[i])) {
5961 nlmsg_free(msg);
5962 return -1;
5963 }
5964 }
5965
5966 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5967 if (params->bssid) {
5968 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
5969 MAC2STR(params->bssid));
5970 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
5971 }
5972 if (params->freq) {
5973 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
5974 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
5975 }
5976 if (params->ssid) {
5977 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
5978 params->ssid, params->ssid_len);
5979 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
5980 params->ssid);
5981 }
5982 wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len);
5983 if (params->ie)
5984 NLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005985 if (params->sae_data) {
5986 wpa_hexdump(MSG_DEBUG, " * SAE data", params->sae_data,
5987 params->sae_data_len);
5988 NLA_PUT(msg, NL80211_ATTR_SAE_DATA, params->sae_data_len,
5989 params->sae_data);
5990 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005991 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
5992 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
5993 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
5994 type = NL80211_AUTHTYPE_SHARED_KEY;
5995 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
5996 type = NL80211_AUTHTYPE_NETWORK_EAP;
5997 else if (params->auth_alg & WPA_AUTH_ALG_FT)
5998 type = NL80211_AUTHTYPE_FT;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005999 else if (params->auth_alg & WPA_AUTH_ALG_SAE)
6000 type = NL80211_AUTHTYPE_SAE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006001 else
6002 goto nla_put_failure;
6003 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
6004 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
6005 if (params->local_state_change) {
6006 wpa_printf(MSG_DEBUG, " * Local state change only");
6007 NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);
6008 }
6009
6010 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6011 msg = NULL;
6012 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006013 wpa_dbg(drv->ctx, MSG_DEBUG,
6014 "nl80211: MLME command failed (auth): ret=%d (%s)",
6015 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006016 count++;
6017 if (ret == -EALREADY && count == 1 && params->bssid &&
6018 !params->local_state_change) {
6019 /*
6020 * mac80211 does not currently accept new
6021 * authentication if we are already authenticated. As a
6022 * workaround, force deauthentication and try again.
6023 */
6024 wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
6025 "after forced deauthentication");
6026 wpa_driver_nl80211_deauthenticate(
6027 bss, params->bssid,
6028 WLAN_REASON_PREV_AUTH_NOT_VALID);
6029 nlmsg_free(msg);
6030 goto retry;
6031 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006032
6033 if (ret == -ENOENT && params->freq && !is_retry) {
6034 /*
6035 * cfg80211 has likely expired the BSS entry even
6036 * though it was previously available in our internal
6037 * BSS table. To recover quickly, start a single
6038 * channel scan on the specified channel.
6039 */
6040 struct wpa_driver_scan_params scan;
6041 int freqs[2];
6042
6043 os_memset(&scan, 0, sizeof(scan));
6044 scan.num_ssids = 1;
6045 if (params->ssid) {
6046 scan.ssids[0].ssid = params->ssid;
6047 scan.ssids[0].ssid_len = params->ssid_len;
6048 }
6049 freqs[0] = params->freq;
6050 freqs[1] = 0;
6051 scan.freqs = freqs;
6052 wpa_printf(MSG_DEBUG, "nl80211: Trigger single "
6053 "channel scan to refresh cfg80211 BSS "
6054 "entry");
6055 ret = wpa_driver_nl80211_scan(bss, &scan);
6056 if (ret == 0) {
6057 nl80211_copy_auth_params(drv, params);
6058 drv->scan_for_auth = 1;
6059 }
6060 } else if (is_retry) {
6061 /*
6062 * Need to indicate this with an event since the return
6063 * value from the retry is not delivered to core code.
6064 */
6065 union wpa_event_data event;
6066 wpa_printf(MSG_DEBUG, "nl80211: Authentication retry "
6067 "failed");
6068 os_memset(&event, 0, sizeof(event));
6069 os_memcpy(event.timeout_event.addr, drv->auth_bssid_,
6070 ETH_ALEN);
6071 wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,
6072 &event);
6073 }
6074
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006075 goto nla_put_failure;
6076 }
6077 ret = 0;
6078 wpa_printf(MSG_DEBUG, "nl80211: Authentication request send "
6079 "successfully");
6080
6081nla_put_failure:
6082 nlmsg_free(msg);
6083 return ret;
6084}
6085
6086
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006087static int wpa_driver_nl80211_authenticate_retry(
6088 struct wpa_driver_nl80211_data *drv)
6089{
6090 struct wpa_driver_auth_params params;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08006091 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006092 int i;
6093
6094 wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
6095
6096 os_memset(&params, 0, sizeof(params));
6097 params.freq = drv->auth_freq;
6098 params.auth_alg = drv->auth_alg;
6099 params.wep_tx_keyidx = drv->auth_wep_tx_keyidx;
6100 params.local_state_change = drv->auth_local_state_change;
6101 params.p2p = drv->auth_p2p;
6102
6103 if (!is_zero_ether_addr(drv->auth_bssid_))
6104 params.bssid = drv->auth_bssid_;
6105
6106 if (drv->auth_ssid_len) {
6107 params.ssid = drv->auth_ssid;
6108 params.ssid_len = drv->auth_ssid_len;
6109 }
6110
6111 params.ie = drv->auth_ie;
6112 params.ie_len = drv->auth_ie_len;
6113
6114 for (i = 0; i < 4; i++) {
6115 if (drv->auth_wep_key_len[i]) {
6116 params.wep_key[i] = drv->auth_wep_key[i];
6117 params.wep_key_len[i] = drv->auth_wep_key_len[i];
6118 }
6119 }
6120
6121 drv->retry_auth = 1;
6122 return wpa_driver_nl80211_authenticate(bss, &params);
6123}
6124
6125
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006126struct phy_info_arg {
6127 u16 *num_modes;
6128 struct hostapd_hw_modes *modes;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006129 int last_mode, last_chan_idx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006130};
6131
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006132static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
6133 struct nlattr *ampdu_factor,
6134 struct nlattr *ampdu_density,
6135 struct nlattr *mcs_set)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006136{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006137 if (capa)
6138 mode->ht_capab = nla_get_u16(capa);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006139
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006140 if (ampdu_factor)
6141 mode->a_mpdu_params |= nla_get_u8(ampdu_factor) & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006142
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006143 if (ampdu_density)
6144 mode->a_mpdu_params |= nla_get_u8(ampdu_density) << 2;
6145
6146 if (mcs_set && nla_len(mcs_set) >= 16) {
6147 u8 *mcs;
6148 mcs = nla_data(mcs_set);
6149 os_memcpy(mode->mcs_set, mcs, 16);
6150 }
6151}
6152
6153
6154static void phy_info_vht_capa(struct hostapd_hw_modes *mode,
6155 struct nlattr *capa,
6156 struct nlattr *mcs_set)
6157{
6158 if (capa)
6159 mode->vht_capab = nla_get_u32(capa);
6160
6161 if (mcs_set && nla_len(mcs_set) >= 8) {
6162 u8 *mcs;
6163 mcs = nla_data(mcs_set);
6164 os_memcpy(mode->vht_mcs_set, mcs, 8);
6165 }
6166}
6167
6168
6169static void phy_info_freq(struct hostapd_hw_modes *mode,
6170 struct hostapd_channel_data *chan,
6171 struct nlattr *tb_freq[])
6172{
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006173 u8 channel;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006174 chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
6175 chan->flag = 0;
Dmitry Shmidt4b060592013-04-29 16:42:49 -07006176 if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
6177 chan->chan = channel;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006178
6179 if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
6180 chan->flag |= HOSTAPD_CHAN_DISABLED;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006181 if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR])
6182 chan->flag |= HOSTAPD_CHAN_PASSIVE_SCAN | HOSTAPD_CHAN_NO_IBSS;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006183 if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
6184 chan->flag |= HOSTAPD_CHAN_RADAR;
6185
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006186 if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) {
6187 enum nl80211_dfs_state state =
6188 nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]);
6189
6190 switch (state) {
6191 case NL80211_DFS_USABLE:
6192 chan->flag |= HOSTAPD_CHAN_DFS_USABLE;
6193 break;
6194 case NL80211_DFS_AVAILABLE:
6195 chan->flag |= HOSTAPD_CHAN_DFS_AVAILABLE;
6196 break;
6197 case NL80211_DFS_UNAVAILABLE:
6198 chan->flag |= HOSTAPD_CHAN_DFS_UNAVAILABLE;
6199 break;
6200 }
6201 }
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006202}
6203
6204
6205static int phy_info_freqs(struct phy_info_arg *phy_info,
6206 struct hostapd_hw_modes *mode, struct nlattr *tb)
6207{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006208 static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
6209 [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
6210 [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006211 [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006212 [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
6213 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
Dmitry Shmidtea69e842013-05-13 14:52:28 -07006214 [NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006215 };
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006216 int new_channels = 0;
6217 struct hostapd_channel_data *channel;
6218 struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006219 struct nlattr *nl_freq;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006220 int rem_freq, idx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006221
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006222 if (tb == NULL)
6223 return NL_OK;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006224
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006225 nla_for_each_nested(nl_freq, tb, rem_freq) {
6226 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
6227 nla_data(nl_freq), nla_len(nl_freq), freq_policy);
6228 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
6229 continue;
6230 new_channels++;
6231 }
6232
6233 channel = os_realloc_array(mode->channels,
6234 mode->num_channels + new_channels,
6235 sizeof(struct hostapd_channel_data));
6236 if (!channel)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006237 return NL_SKIP;
6238
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006239 mode->channels = channel;
6240 mode->num_channels += new_channels;
6241
6242 idx = phy_info->last_chan_idx;
6243
6244 nla_for_each_nested(nl_freq, tb, rem_freq) {
6245 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
6246 nla_data(nl_freq), nla_len(nl_freq), freq_policy);
6247 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
6248 continue;
6249 phy_info_freq(mode, &mode->channels[idx], tb_freq);
6250 idx++;
6251 }
6252 phy_info->last_chan_idx = idx;
6253
6254 return NL_OK;
6255}
6256
6257
6258static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
6259{
6260 static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {
6261 [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },
6262 [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] =
6263 { .type = NLA_FLAG },
6264 };
6265 struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
6266 struct nlattr *nl_rate;
6267 int rem_rate, idx;
6268
6269 if (tb == NULL)
6270 return NL_OK;
6271
6272 nla_for_each_nested(nl_rate, tb, rem_rate) {
6273 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
6274 nla_data(nl_rate), nla_len(nl_rate),
6275 rate_policy);
6276 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
6277 continue;
6278 mode->num_rates++;
6279 }
6280
6281 mode->rates = os_calloc(mode->num_rates, sizeof(int));
6282 if (!mode->rates)
6283 return NL_SKIP;
6284
6285 idx = 0;
6286
6287 nla_for_each_nested(nl_rate, tb, rem_rate) {
6288 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
6289 nla_data(nl_rate), nla_len(nl_rate),
6290 rate_policy);
6291 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
6292 continue;
6293 mode->rates[idx] = nla_get_u32(
6294 tb_rate[NL80211_BITRATE_ATTR_RATE]);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006295 idx++;
6296 }
6297
6298 return NL_OK;
6299}
6300
6301
6302static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
6303{
6304 struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
6305 struct hostapd_hw_modes *mode;
6306 int ret;
6307
6308 if (phy_info->last_mode != nl_band->nla_type) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006309 mode = os_realloc_array(phy_info->modes,
6310 *phy_info->num_modes + 1,
6311 sizeof(*mode));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006312 if (!mode)
6313 return NL_SKIP;
6314 phy_info->modes = mode;
6315
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006316 mode = &phy_info->modes[*(phy_info->num_modes)];
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006317 os_memset(mode, 0, sizeof(*mode));
6318 mode->mode = NUM_HOSTAPD_MODES;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006319 mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN |
6320 HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN;
6321
6322 /*
6323 * Unsupported VHT MCS stream is defined as value 3, so the VHT
6324 * MCS RX/TX map must be initialized with 0xffff to mark all 8
6325 * possible streams as unsupported. This will be overridden if
6326 * driver advertises VHT support.
6327 */
6328 mode->vht_mcs_set[0] = 0xff;
6329 mode->vht_mcs_set[1] = 0xff;
6330 mode->vht_mcs_set[4] = 0xff;
6331 mode->vht_mcs_set[5] = 0xff;
6332
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006333 *(phy_info->num_modes) += 1;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006334 phy_info->last_mode = nl_band->nla_type;
6335 phy_info->last_chan_idx = 0;
6336 } else
6337 mode = &phy_info->modes[*(phy_info->num_modes) - 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006338
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006339 nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
6340 nla_len(nl_band), NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006341
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006342 phy_info_ht_capa(mode, tb_band[NL80211_BAND_ATTR_HT_CAPA],
6343 tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR],
6344 tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY],
6345 tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);
6346 phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
6347 tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
6348 ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]);
6349 if (ret != NL_OK)
6350 return ret;
6351 ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
6352 if (ret != NL_OK)
6353 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006354
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006355 return NL_OK;
6356}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006357
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006358
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006359static int phy_info_handler(struct nl_msg *msg, void *arg)
6360{
6361 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
6362 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6363 struct phy_info_arg *phy_info = arg;
6364 struct nlattr *nl_band;
6365 int rem_band;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006366
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006367 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6368 genlmsg_attrlen(gnlh, 0), NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006369
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006370 if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
6371 return NL_SKIP;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006372
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006373 nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band)
6374 {
6375 int res = phy_info_band(phy_info, nl_band);
6376 if (res != NL_OK)
6377 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006378 }
6379
6380 return NL_SKIP;
6381}
6382
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006384static struct hostapd_hw_modes *
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006385wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
6386 u16 *num_modes)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006387{
6388 u16 m;
6389 struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
6390 int i, mode11g_idx = -1;
6391
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006392 /* heuristic to set up modes */
6393 for (m = 0; m < *num_modes; m++) {
6394 if (!modes[m].num_channels)
6395 continue;
6396 if (modes[m].channels[0].freq < 4000) {
6397 modes[m].mode = HOSTAPD_MODE_IEEE80211B;
6398 for (i = 0; i < modes[m].num_rates; i++) {
6399 if (modes[m].rates[i] > 200) {
6400 modes[m].mode = HOSTAPD_MODE_IEEE80211G;
6401 break;
6402 }
6403 }
6404 } else if (modes[m].channels[0].freq > 50000)
6405 modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
6406 else
6407 modes[m].mode = HOSTAPD_MODE_IEEE80211A;
6408 }
6409
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006410 /* If only 802.11g mode is included, use it to construct matching
6411 * 802.11b mode data. */
6412
6413 for (m = 0; m < *num_modes; m++) {
6414 if (modes[m].mode == HOSTAPD_MODE_IEEE80211B)
6415 return modes; /* 802.11b already included */
6416 if (modes[m].mode == HOSTAPD_MODE_IEEE80211G)
6417 mode11g_idx = m;
6418 }
6419
6420 if (mode11g_idx < 0)
6421 return modes; /* 2.4 GHz band not supported at all */
6422
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006423 nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006424 if (nmodes == NULL)
6425 return modes; /* Could not add 802.11b mode */
6426
6427 mode = &nmodes[*num_modes];
6428 os_memset(mode, 0, sizeof(*mode));
6429 (*num_modes)++;
6430 modes = nmodes;
6431
6432 mode->mode = HOSTAPD_MODE_IEEE80211B;
6433
6434 mode11g = &modes[mode11g_idx];
6435 mode->num_channels = mode11g->num_channels;
6436 mode->channels = os_malloc(mode11g->num_channels *
6437 sizeof(struct hostapd_channel_data));
6438 if (mode->channels == NULL) {
6439 (*num_modes)--;
6440 return modes; /* Could not add 802.11b mode */
6441 }
6442 os_memcpy(mode->channels, mode11g->channels,
6443 mode11g->num_channels * sizeof(struct hostapd_channel_data));
6444
6445 mode->num_rates = 0;
6446 mode->rates = os_malloc(4 * sizeof(int));
6447 if (mode->rates == NULL) {
6448 os_free(mode->channels);
6449 (*num_modes)--;
6450 return modes; /* Could not add 802.11b mode */
6451 }
6452
6453 for (i = 0; i < mode11g->num_rates; i++) {
6454 if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&
6455 mode11g->rates[i] != 55 && mode11g->rates[i] != 110)
6456 continue;
6457 mode->rates[mode->num_rates] = mode11g->rates[i];
6458 mode->num_rates++;
6459 if (mode->num_rates == 4)
6460 break;
6461 }
6462
6463 if (mode->num_rates == 0) {
6464 os_free(mode->channels);
6465 os_free(mode->rates);
6466 (*num_modes)--;
6467 return modes; /* No 802.11b rates */
6468 }
6469
6470 wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g "
6471 "information");
6472
6473 return modes;
6474}
6475
6476
6477static void nl80211_set_ht40_mode(struct hostapd_hw_modes *mode, int start,
6478 int end)
6479{
6480 int c;
6481
6482 for (c = 0; c < mode->num_channels; c++) {
6483 struct hostapd_channel_data *chan = &mode->channels[c];
6484 if (chan->freq - 10 >= start && chan->freq + 10 <= end)
6485 chan->flag |= HOSTAPD_CHAN_HT40;
6486 }
6487}
6488
6489
6490static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,
6491 int end)
6492{
6493 int c;
6494
6495 for (c = 0; c < mode->num_channels; c++) {
6496 struct hostapd_channel_data *chan = &mode->channels[c];
6497 if (!(chan->flag & HOSTAPD_CHAN_HT40))
6498 continue;
6499 if (chan->freq - 30 >= start && chan->freq - 10 <= end)
6500 chan->flag |= HOSTAPD_CHAN_HT40MINUS;
6501 if (chan->freq + 10 >= start && chan->freq + 30 <= end)
6502 chan->flag |= HOSTAPD_CHAN_HT40PLUS;
6503 }
6504}
6505
6506
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006507static void nl80211_reg_rule_max_eirp(u32 start, u32 end, u32 max_eirp,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006508 struct phy_info_arg *results)
6509{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006510 u16 m;
6511
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006512 for (m = 0; m < *results->num_modes; m++) {
6513 int c;
6514 struct hostapd_hw_modes *mode = &results->modes[m];
6515
6516 for (c = 0; c < mode->num_channels; c++) {
6517 struct hostapd_channel_data *chan = &mode->channels[c];
6518 if ((u32) chan->freq - 10 >= start &&
6519 (u32) chan->freq + 10 <= end)
6520 chan->max_tx_power = max_eirp;
6521 }
6522 }
6523}
6524
6525
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006526static void nl80211_reg_rule_ht40(u32 start, u32 end,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006527 struct phy_info_arg *results)
6528{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006529 u16 m;
6530
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006531 for (m = 0; m < *results->num_modes; m++) {
6532 if (!(results->modes[m].ht_capab &
6533 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6534 continue;
6535 nl80211_set_ht40_mode(&results->modes[m], start, end);
6536 }
6537}
6538
6539
6540static void nl80211_reg_rule_sec(struct nlattr *tb[],
6541 struct phy_info_arg *results)
6542{
6543 u32 start, end, max_bw;
6544 u16 m;
6545
6546 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6547 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
6548 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
6549 return;
6550
6551 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6552 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6553 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
6554
6555 if (max_bw < 20)
6556 return;
6557
6558 for (m = 0; m < *results->num_modes; m++) {
6559 if (!(results->modes[m].ht_capab &
6560 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6561 continue;
6562 nl80211_set_ht40_mode_sec(&results->modes[m], start, end);
6563 }
6564}
6565
6566
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006567static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
6568 int end)
6569{
6570 int c;
6571
6572 for (c = 0; c < mode->num_channels; c++) {
6573 struct hostapd_channel_data *chan = &mode->channels[c];
6574 if (chan->freq - 10 >= start && chan->freq + 70 <= end)
6575 chan->flag |= HOSTAPD_CHAN_VHT_10_70;
6576
6577 if (chan->freq - 30 >= start && chan->freq + 50 <= end)
6578 chan->flag |= HOSTAPD_CHAN_VHT_30_50;
6579
6580 if (chan->freq - 50 >= start && chan->freq + 30 <= end)
6581 chan->flag |= HOSTAPD_CHAN_VHT_50_30;
6582
6583 if (chan->freq - 70 >= start && chan->freq + 10 <= end)
6584 chan->flag |= HOSTAPD_CHAN_VHT_70_10;
6585 }
6586}
6587
6588
6589static void nl80211_reg_rule_vht(struct nlattr *tb[],
6590 struct phy_info_arg *results)
6591{
6592 u32 start, end, max_bw;
6593 u16 m;
6594
6595 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6596 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
6597 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
6598 return;
6599
6600 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6601 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6602 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
6603
6604 if (max_bw < 80)
6605 return;
6606
6607 for (m = 0; m < *results->num_modes; m++) {
6608 if (!(results->modes[m].ht_capab &
6609 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6610 continue;
6611 /* TODO: use a real VHT support indication */
6612 if (!results->modes[m].vht_capab)
6613 continue;
6614
6615 nl80211_set_vht_mode(&results->modes[m], start, end);
6616 }
6617}
6618
6619
Dmitry Shmidt97672262014-02-03 13:02:54 -08006620static const char * dfs_domain_name(enum nl80211_dfs_regions region)
6621{
6622 switch (region) {
6623 case NL80211_DFS_UNSET:
6624 return "DFS-UNSET";
6625 case NL80211_DFS_FCC:
6626 return "DFS-FCC";
6627 case NL80211_DFS_ETSI:
6628 return "DFS-ETSI";
6629 case NL80211_DFS_JP:
6630 return "DFS-JP";
6631 default:
6632 return "DFS-invalid";
6633 }
6634}
6635
6636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006637static int nl80211_get_reg(struct nl_msg *msg, void *arg)
6638{
6639 struct phy_info_arg *results = arg;
6640 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
6641 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6642 struct nlattr *nl_rule;
6643 struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
6644 int rem_rule;
6645 static struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
6646 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
6647 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
6648 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
6649 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
6650 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
6651 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
6652 };
6653
6654 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6655 genlmsg_attrlen(gnlh, 0), NULL);
6656 if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
6657 !tb_msg[NL80211_ATTR_REG_RULES]) {
6658 wpa_printf(MSG_DEBUG, "nl80211: No regulatory information "
6659 "available");
6660 return NL_SKIP;
6661 }
6662
Dmitry Shmidt97672262014-02-03 13:02:54 -08006663 if (tb_msg[NL80211_ATTR_DFS_REGION]) {
6664 enum nl80211_dfs_regions dfs_domain;
6665 dfs_domain = nla_get_u8(tb_msg[NL80211_ATTR_DFS_REGION]);
6666 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s (%s)",
6667 (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]),
6668 dfs_domain_name(dfs_domain));
6669 } else {
6670 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s",
6671 (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));
6672 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006673
6674 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6675 {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006676 u32 start, end, max_eirp = 0, max_bw = 0, flags = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006677 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6678 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006679 if (tb_rule[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6680 tb_rule[NL80211_ATTR_FREQ_RANGE_END] == NULL)
6681 continue;
6682 start = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6683 end = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6684 if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
6685 max_eirp = nla_get_u32(tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP]) / 100;
6686 if (tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW])
6687 max_bw = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006688 if (tb_rule[NL80211_ATTR_REG_RULE_FLAGS])
6689 flags = nla_get_u32(tb_rule[NL80211_ATTR_REG_RULE_FLAGS]);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006690
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08006691 wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s",
6692 start, end, max_bw, max_eirp,
6693 flags & NL80211_RRF_NO_OFDM ? " (no OFDM)" : "",
6694 flags & NL80211_RRF_NO_CCK ? " (no CCK)" : "",
6695 flags & NL80211_RRF_NO_INDOOR ? " (no indoor)" : "",
6696 flags & NL80211_RRF_NO_OUTDOOR ? " (no outdoor)" :
6697 "",
6698 flags & NL80211_RRF_DFS ? " (DFS)" : "",
6699 flags & NL80211_RRF_PTP_ONLY ? " (PTP only)" : "",
6700 flags & NL80211_RRF_PTMP_ONLY ? " (PTMP only)" : "",
6701 flags & NL80211_RRF_NO_IR ? " (no IR)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006702 if (max_bw >= 40)
6703 nl80211_reg_rule_ht40(start, end, results);
6704 if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
6705 nl80211_reg_rule_max_eirp(start, end, max_eirp,
6706 results);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006707 }
6708
6709 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6710 {
6711 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6712 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
6713 nl80211_reg_rule_sec(tb_rule, results);
6714 }
6715
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006716 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6717 {
6718 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6719 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
6720 nl80211_reg_rule_vht(tb_rule, results);
6721 }
6722
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006723 return NL_SKIP;
6724}
6725
6726
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006727static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv,
6728 struct phy_info_arg *results)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006729{
6730 struct nl_msg *msg;
6731
6732 msg = nlmsg_alloc();
6733 if (!msg)
6734 return -ENOMEM;
6735
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006736 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006737 return send_and_recv_msgs(drv, msg, nl80211_get_reg, results);
6738}
6739
6740
6741static struct hostapd_hw_modes *
6742wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
6743{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006744 u32 feat;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006745 struct i802_bss *bss = priv;
6746 struct wpa_driver_nl80211_data *drv = bss->drv;
6747 struct nl_msg *msg;
6748 struct phy_info_arg result = {
6749 .num_modes = num_modes,
6750 .modes = NULL,
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006751 .last_mode = -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006752 };
6753
6754 *num_modes = 0;
6755 *flags = 0;
6756
6757 msg = nlmsg_alloc();
6758 if (!msg)
6759 return NULL;
6760
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006761 feat = get_nl80211_protocol_features(drv);
6762 if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
6763 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_WIPHY);
6764 else
6765 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006766
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006767 NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08006768 if (nl80211_set_iface_id(msg, bss) < 0)
6769 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006770
6771 if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006772 nl80211_set_regulatory_flags(drv, &result);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006773 return wpa_driver_nl80211_postprocess_modes(result.modes,
6774 num_modes);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006775 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006776 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006777 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006778 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006779 return NULL;
6780}
6781
6782
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006783static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv,
6784 const void *data, size_t len,
6785 int encrypt, int noack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006786{
6787 __u8 rtap_hdr[] = {
6788 0x00, 0x00, /* radiotap version */
6789 0x0e, 0x00, /* radiotap length */
6790 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
6791 IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
6792 0x00, /* padding */
6793 0x00, 0x00, /* RX and TX flags to indicate that */
6794 0x00, 0x00, /* this is the injected frame directly */
6795 };
6796 struct iovec iov[2] = {
6797 {
6798 .iov_base = &rtap_hdr,
6799 .iov_len = sizeof(rtap_hdr),
6800 },
6801 {
6802 .iov_base = (void *) data,
6803 .iov_len = len,
6804 }
6805 };
6806 struct msghdr msg = {
6807 .msg_name = NULL,
6808 .msg_namelen = 0,
6809 .msg_iov = iov,
6810 .msg_iovlen = 2,
6811 .msg_control = NULL,
6812 .msg_controllen = 0,
6813 .msg_flags = 0,
6814 };
6815 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006816 u16 txflags = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006817
6818 if (encrypt)
6819 rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
6820
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07006821 if (drv->monitor_sock < 0) {
6822 wpa_printf(MSG_DEBUG, "nl80211: No monitor socket available "
6823 "for %s", __func__);
6824 return -1;
6825 }
6826
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006827 if (noack)
6828 txflags |= IEEE80211_RADIOTAP_F_TX_NOACK;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006829 WPA_PUT_LE16(&rtap_hdr[12], txflags);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006830
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006831 res = sendmsg(drv->monitor_sock, &msg, 0);
6832 if (res < 0) {
6833 wpa_printf(MSG_INFO, "nl80211: sendmsg: %s", strerror(errno));
6834 return -1;
6835 }
6836 return 0;
6837}
6838
6839
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006840static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
6841 const void *data, size_t len,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006842 int encrypt, int noack,
6843 unsigned int freq, int no_cck,
6844 int offchanok, unsigned int wait_time)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006845{
6846 struct wpa_driver_nl80211_data *drv = bss->drv;
6847 u64 cookie;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006848 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006849
Dmitry Shmidt56052862013-10-04 10:23:25 -07006850 if (freq == 0) {
6851 wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u",
6852 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006853 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07006854 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006855
Dmitry Shmidt56052862013-10-04 10:23:25 -07006856 if (drv->use_monitor) {
6857 wpa_printf(MSG_DEBUG, "nl80211: send_frame(freq=%u bss->freq=%u) -> send_mntr",
6858 freq, bss->freq);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006859 return wpa_driver_nl80211_send_mntr(drv, data, len,
6860 encrypt, noack);
Dmitry Shmidt56052862013-10-04 10:23:25 -07006861 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006862
Dmitry Shmidt56052862013-10-04 10:23:25 -07006863 wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
Dmitry Shmidt051af732013-10-22 13:52:46 -07006864 res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
6865 &cookie, no_cck, noack, offchanok);
6866 if (res == 0 && !noack) {
6867 const struct ieee80211_mgmt *mgmt;
6868 u16 fc;
6869
6870 mgmt = (const struct ieee80211_mgmt *) data;
6871 fc = le_to_host16(mgmt->frame_control);
6872 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
6873 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
6874 wpa_printf(MSG_MSGDUMP,
6875 "nl80211: Update send_action_cookie from 0x%llx to 0x%llx",
6876 (long long unsigned int)
6877 drv->send_action_cookie,
6878 (long long unsigned int) cookie);
6879 drv->send_action_cookie = cookie;
6880 }
6881 }
6882
6883 return res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006884}
6885
6886
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006887static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
6888 size_t data_len, int noack,
6889 unsigned int freq, int no_cck,
6890 int offchanok,
6891 unsigned int wait_time)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006892{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006893 struct wpa_driver_nl80211_data *drv = bss->drv;
6894 struct ieee80211_mgmt *mgmt;
6895 int encrypt = 1;
6896 u16 fc;
6897
6898 mgmt = (struct ieee80211_mgmt *) data;
6899 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt56052862013-10-04 10:23:25 -07006900 wpa_printf(MSG_DEBUG, "nl80211: send_mlme - noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x nlmode=%d",
6901 noack, freq, no_cck, offchanok, wait_time, fc, drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006902
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006903 if ((is_sta_interface(drv->nlmode) ||
6904 drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006905 WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
6906 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
6907 /*
6908 * The use of last_mgmt_freq is a bit of a hack,
6909 * but it works due to the single-threaded nature
6910 * of wpa_supplicant.
6911 */
Dmitry Shmidt56052862013-10-04 10:23:25 -07006912 if (freq == 0) {
6913 wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d",
6914 drv->last_mgmt_freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006915 freq = drv->last_mgmt_freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07006916 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006917 return nl80211_send_frame_cmd(bss, freq, 0,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006918 data, data_len, NULL, 1, noack,
6919 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006920 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006921
6922 if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
Dmitry Shmidt56052862013-10-04 10:23:25 -07006923 if (freq == 0) {
6924 wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d",
6925 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006926 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07006927 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006928 return nl80211_send_frame_cmd(bss, freq,
6929 (int) freq == bss->freq ? 0 :
6930 wait_time,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006931 data, data_len,
6932 &drv->send_action_cookie,
6933 no_cck, noack, offchanok);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07006934 }
Dmitry Shmidtb638fe72012-03-20 12:51:25 -07006935
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006936 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
6937 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {
6938 /*
6939 * Only one of the authentication frame types is encrypted.
6940 * In order for static WEP encryption to work properly (i.e.,
6941 * to not encrypt the frame), we need to tell mac80211 about
6942 * the frames that must not be encrypted.
6943 */
6944 u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
6945 u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);
6946 if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)
6947 encrypt = 0;
6948 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006949
Dmitry Shmidt56052862013-10-04 10:23:25 -07006950 wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006951 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006952 noack, freq, no_cck, offchanok,
6953 wait_time);
6954}
6955
6956
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006957static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
6958 int slot, int ht_opmode, int ap_isolate,
6959 int *basic_rates)
6960{
6961 struct wpa_driver_nl80211_data *drv = bss->drv;
6962 struct nl_msg *msg;
6963
6964 msg = nlmsg_alloc();
6965 if (!msg)
6966 return -ENOMEM;
6967
6968 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);
6969
6970 if (cts >= 0)
6971 NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);
6972 if (preamble >= 0)
6973 NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);
6974 if (slot >= 0)
6975 NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
6976 if (ht_opmode >= 0)
6977 NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);
6978 if (ap_isolate >= 0)
6979 NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate);
6980
6981 if (basic_rates) {
6982 u8 rates[NL80211_MAX_SUPP_RATES];
6983 u8 rates_len = 0;
6984 int i;
6985
6986 for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0;
6987 i++)
6988 rates[rates_len++] = basic_rates[i] / 5;
6989
6990 NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
6991 }
6992
6993 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
6994
6995 return send_and_recv_msgs(drv, msg, NULL, NULL);
6996 nla_put_failure:
6997 nlmsg_free(msg);
6998 return -ENOBUFS;
6999}
7000
7001
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07007002static int wpa_driver_nl80211_set_acl(void *priv,
7003 struct hostapd_acl_params *params)
7004{
7005 struct i802_bss *bss = priv;
7006 struct wpa_driver_nl80211_data *drv = bss->drv;
7007 struct nl_msg *msg;
7008 struct nlattr *acl;
7009 unsigned int i;
7010 int ret = 0;
7011
7012 if (!(drv->capa.max_acl_mac_addrs))
7013 return -ENOTSUP;
7014
7015 if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
7016 return -ENOTSUP;
7017
7018 msg = nlmsg_alloc();
7019 if (!msg)
7020 return -ENOMEM;
7021
7022 wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
7023 params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
7024
7025 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_MAC_ACL);
7026
7027 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7028
7029 NLA_PUT_U32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
7030 NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
7031 NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED);
7032
7033 acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
7034 if (acl == NULL)
7035 goto nla_put_failure;
7036
7037 for (i = 0; i < params->num_mac_acl; i++)
7038 NLA_PUT(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr);
7039
7040 nla_nest_end(msg, acl);
7041
7042 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7043 msg = NULL;
7044 if (ret) {
7045 wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
7046 ret, strerror(-ret));
7047 }
7048
7049nla_put_failure:
7050 nlmsg_free(msg);
7051
7052 return ret;
7053}
7054
7055
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007056static int wpa_driver_nl80211_set_ap(void *priv,
7057 struct wpa_driver_ap_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007058{
7059 struct i802_bss *bss = priv;
7060 struct wpa_driver_nl80211_data *drv = bss->drv;
7061 struct nl_msg *msg;
7062 u8 cmd = NL80211_CMD_NEW_BEACON;
7063 int ret;
7064 int beacon_set;
7065 int ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007066 int num_suites;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007067 u32 suites[10], suite;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007068 u32 ver;
7069
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07007070 beacon_set = bss->beacon_set;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007071
7072 msg = nlmsg_alloc();
7073 if (!msg)
7074 return -ENOMEM;
7075
7076 wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
7077 beacon_set);
7078 if (beacon_set)
7079 cmd = NL80211_CMD_SET_BEACON;
7080
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007081 nl80211_cmd(drv, msg, 0, cmd);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007082 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
7083 params->head, params->head_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007084 NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007085 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon tail",
7086 params->tail, params->tail_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007087 NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007088 wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007089 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007090 wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007091 NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007092 wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007093 NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007094 wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid",
7095 params->ssid, params->ssid_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007096 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
7097 params->ssid);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007098 if (params->proberesp && params->proberesp_len) {
7099 wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)",
7100 params->proberesp, params->proberesp_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007101 NLA_PUT(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
7102 params->proberesp);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007103 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007104 switch (params->hide_ssid) {
7105 case NO_SSID_HIDING:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007106 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID not in use");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007107 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
7108 NL80211_HIDDEN_SSID_NOT_IN_USE);
7109 break;
7110 case HIDDEN_SSID_ZERO_LEN:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007111 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero len");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007112 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
7113 NL80211_HIDDEN_SSID_ZERO_LEN);
7114 break;
7115 case HIDDEN_SSID_ZERO_CONTENTS:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007116 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero contents");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007117 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
7118 NL80211_HIDDEN_SSID_ZERO_CONTENTS);
7119 break;
7120 }
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007121 wpa_printf(MSG_DEBUG, "nl80211: privacy=%d", params->privacy);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007122 if (params->privacy)
7123 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007124 wpa_printf(MSG_DEBUG, "nl80211: auth_algs=0x%x", params->auth_algs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007125 if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
7126 (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
7127 /* Leave out the attribute */
7128 } else if (params->auth_algs & WPA_AUTH_ALG_SHARED)
7129 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
7130 NL80211_AUTHTYPE_SHARED_KEY);
7131 else
7132 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
7133 NL80211_AUTHTYPE_OPEN_SYSTEM);
7134
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007135 wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007136 ver = 0;
7137 if (params->wpa_version & WPA_PROTO_WPA)
7138 ver |= NL80211_WPA_VERSION_1;
7139 if (params->wpa_version & WPA_PROTO_RSN)
7140 ver |= NL80211_WPA_VERSION_2;
7141 if (ver)
7142 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
7143
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007144 wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x",
7145 params->key_mgmt_suites);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007146 num_suites = 0;
7147 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
7148 suites[num_suites++] = WLAN_AKM_SUITE_8021X;
7149 if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
7150 suites[num_suites++] = WLAN_AKM_SUITE_PSK;
7151 if (num_suites) {
7152 NLA_PUT(msg, NL80211_ATTR_AKM_SUITES,
7153 num_suites * sizeof(u32), suites);
7154 }
7155
7156 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X &&
7157 params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40))
7158 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
7159
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007160 wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
7161 params->pairwise_ciphers);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007162 num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers,
7163 suites, ARRAY_SIZE(suites));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007164 if (num_suites) {
7165 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
7166 num_suites * sizeof(u32), suites);
7167 }
7168
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007169 wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x",
7170 params->group_cipher);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007171 suite = wpa_cipher_to_cipher_suite(params->group_cipher);
7172 if (suite)
7173 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007174
7175 if (params->beacon_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007176 wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
7177 params->beacon_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007178 NLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
7179 wpabuf_head(params->beacon_ies));
7180 }
7181 if (params->proberesp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007182 wpa_hexdump_buf(MSG_DEBUG, "nl80211: proberesp_ies",
7183 params->proberesp_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007184 NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
7185 wpabuf_len(params->proberesp_ies),
7186 wpabuf_head(params->proberesp_ies));
7187 }
7188 if (params->assocresp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007189 wpa_hexdump_buf(MSG_DEBUG, "nl80211: assocresp_ies",
7190 params->assocresp_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007191 NLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,
7192 wpabuf_len(params->assocresp_ies),
7193 wpabuf_head(params->assocresp_ies));
7194 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007195
Dmitry Shmidt04949592012-07-19 12:16:46 -07007196 if (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07007197 wpa_printf(MSG_DEBUG, "nl80211: ap_max_inactivity=%d",
7198 params->ap_max_inactivity);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007199 NLA_PUT_U16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT,
7200 params->ap_max_inactivity);
7201 }
7202
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007203 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7204 if (ret) {
7205 wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
7206 ret, strerror(-ret));
7207 } else {
7208 bss->beacon_set = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007209 nl80211_set_bss(bss, params->cts_protect, params->preamble,
7210 params->short_slot_time, params->ht_opmode,
7211 params->isolate, params->basic_rates);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007212 }
7213 return ret;
7214 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007215 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007216 return -ENOBUFS;
7217}
7218
7219
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007220static int nl80211_put_freq_params(struct nl_msg *msg,
7221 struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007222{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007223 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq);
7224 if (freq->vht_enabled) {
7225 switch (freq->bandwidth) {
7226 case 20:
7227 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7228 NL80211_CHAN_WIDTH_20);
7229 break;
7230 case 40:
7231 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7232 NL80211_CHAN_WIDTH_40);
7233 break;
7234 case 80:
7235 if (freq->center_freq2)
7236 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7237 NL80211_CHAN_WIDTH_80P80);
7238 else
7239 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7240 NL80211_CHAN_WIDTH_80);
7241 break;
7242 case 160:
7243 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
7244 NL80211_CHAN_WIDTH_160);
7245 break;
7246 default:
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007247 return -EINVAL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007248 }
7249 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1);
7250 if (freq->center_freq2)
7251 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2,
7252 freq->center_freq2);
7253 } else if (freq->ht_enabled) {
7254 switch (freq->sec_channel_offset) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007255 case -1:
7256 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
7257 NL80211_CHAN_HT40MINUS);
7258 break;
7259 case 1:
7260 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
7261 NL80211_CHAN_HT40PLUS);
7262 break;
7263 default:
7264 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
7265 NL80211_CHAN_HT20);
7266 break;
7267 }
7268 }
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08007269 return 0;
7270
7271nla_put_failure:
7272 return -ENOBUFS;
7273}
7274
7275
7276static int wpa_driver_nl80211_set_freq(struct i802_bss *bss,
7277 struct hostapd_freq_params *freq)
7278{
7279 struct wpa_driver_nl80211_data *drv = bss->drv;
7280 struct nl_msg *msg;
7281 int ret;
7282
7283 wpa_printf(MSG_DEBUG,
7284 "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
7285 freq->freq, freq->ht_enabled, freq->vht_enabled,
7286 freq->bandwidth, freq->center_freq1, freq->center_freq2);
7287 msg = nlmsg_alloc();
7288 if (!msg)
7289 return -1;
7290
7291 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
7292
7293 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7294 if (nl80211_put_freq_params(msg, freq) < 0)
7295 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007296
7297 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007298 msg = NULL;
7299 if (ret == 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007300 bss->freq = freq->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007301 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007302 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007303 wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007304 "%d (%s)", freq->freq, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007305nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007306 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007307 return -1;
7308}
7309
7310
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007311static u32 sta_flags_nl80211(int flags)
7312{
7313 u32 f = 0;
7314
7315 if (flags & WPA_STA_AUTHORIZED)
7316 f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
7317 if (flags & WPA_STA_WMM)
7318 f |= BIT(NL80211_STA_FLAG_WME);
7319 if (flags & WPA_STA_SHORT_PREAMBLE)
7320 f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
7321 if (flags & WPA_STA_MFP)
7322 f |= BIT(NL80211_STA_FLAG_MFP);
7323 if (flags & WPA_STA_TDLS_PEER)
7324 f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
7325
7326 return f;
7327}
7328
7329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007330static int wpa_driver_nl80211_sta_add(void *priv,
7331 struct hostapd_sta_add_params *params)
7332{
7333 struct i802_bss *bss = priv;
7334 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007335 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007336 struct nl80211_sta_flag_update upd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007337 int ret = -ENOBUFS;
7338
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007339 if ((params->flags & WPA_STA_TDLS_PEER) &&
7340 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
7341 return -EOPNOTSUPP;
7342
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007343 msg = nlmsg_alloc();
7344 if (!msg)
7345 return -ENOMEM;
7346
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007347 wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR,
7348 params->set ? "Set" : "Add", MAC2STR(params->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007349 nl80211_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION :
7350 NL80211_CMD_NEW_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007351
7352 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
7353 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007354 NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,
7355 params->supp_rates);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007356 wpa_hexdump(MSG_DEBUG, " * supported rates", params->supp_rates,
7357 params->supp_rates_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007358 if (!params->set) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07007359 if (params->aid) {
7360 wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
7361 NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
7362 } else {
7363 /*
7364 * cfg80211 validates that AID is non-zero, so we have
7365 * to make this a non-zero value for the TDLS case where
7366 * a dummy STA entry is used for now.
7367 */
7368 wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)");
7369 NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, 1);
7370 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007371 wpa_printf(MSG_DEBUG, " * listen_interval=%u",
7372 params->listen_interval);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007373 NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
7374 params->listen_interval);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07007375 } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
7376 wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
7377 NLA_PUT_U16(msg, NL80211_ATTR_PEER_AID, params->aid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007378 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007379 if (params->ht_capabilities) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007380 wpa_hexdump(MSG_DEBUG, " * ht_capabilities",
7381 (u8 *) params->ht_capabilities,
7382 sizeof(*params->ht_capabilities));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007383 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,
7384 sizeof(*params->ht_capabilities),
7385 params->ht_capabilities);
7386 }
7387
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007388 if (params->vht_capabilities) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007389 wpa_hexdump(MSG_DEBUG, " * vht_capabilities",
7390 (u8 *) params->vht_capabilities,
7391 sizeof(*params->vht_capabilities));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007392 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY,
7393 sizeof(*params->vht_capabilities),
7394 params->vht_capabilities);
7395 }
7396
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08007397 if (params->vht_opmode_enabled) {
7398 wpa_printf(MSG_DEBUG, " * opmode=%u", params->vht_opmode);
7399 NLA_PUT_U8(msg, NL80211_ATTR_OPMODE_NOTIF,
7400 params->vht_opmode);
7401 }
7402
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007403 wpa_printf(MSG_DEBUG, " * capability=0x%x", params->capability);
7404 NLA_PUT_U16(msg, NL80211_ATTR_STA_CAPABILITY, params->capability);
7405
7406 if (params->ext_capab) {
7407 wpa_hexdump(MSG_DEBUG, " * ext_capab",
7408 params->ext_capab, params->ext_capab_len);
7409 NLA_PUT(msg, NL80211_ATTR_STA_EXT_CAPABILITY,
7410 params->ext_capab_len, params->ext_capab);
7411 }
7412
Dmitry Shmidt344abd32014-01-14 13:17:00 -08007413 if (params->supp_channels) {
7414 wpa_hexdump(MSG_DEBUG, " * supported channels",
7415 params->supp_channels, params->supp_channels_len);
7416 NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_CHANNELS,
7417 params->supp_channels_len, params->supp_channels);
7418 }
7419
7420 if (params->supp_oper_classes) {
7421 wpa_hexdump(MSG_DEBUG, " * supported operating classes",
7422 params->supp_oper_classes,
7423 params->supp_oper_classes_len);
7424 NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
7425 params->supp_oper_classes_len,
7426 params->supp_oper_classes);
7427 }
7428
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007429 os_memset(&upd, 0, sizeof(upd));
7430 upd.mask = sta_flags_nl80211(params->flags);
7431 upd.set = upd.mask;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007432 wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x",
7433 upd.set, upd.mask);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007434 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
7435
7436 if (params->flags & WPA_STA_WMM) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007437 struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME);
7438
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007439 if (!wme)
7440 goto nla_put_failure;
7441
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007442 wpa_printf(MSG_DEBUG, " * qosinfo=0x%x", params->qosinfo);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007443 NLA_PUT_U8(msg, NL80211_STA_WME_UAPSD_QUEUES,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007444 params->qosinfo & WMM_QOSINFO_STA_AC_MASK);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007445 NLA_PUT_U8(msg, NL80211_STA_WME_MAX_SP,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08007446 (params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007447 WMM_QOSINFO_STA_SP_MASK);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007448 nla_nest_end(msg, wme);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007449 }
7450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007451 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007452 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007453 if (ret)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007454 wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
7455 "result: %d (%s)", params->set ? "SET" : "NEW", ret,
7456 strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007457 if (ret == -EEXIST)
7458 ret = 0;
7459 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007460 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007461 return ret;
7462}
7463
7464
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007465static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007466{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007467 struct wpa_driver_nl80211_data *drv = bss->drv;
7468 struct nl_msg *msg;
7469 int ret;
7470
7471 msg = nlmsg_alloc();
7472 if (!msg)
7473 return -ENOMEM;
7474
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007475 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007476
7477 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
7478 if_nametoindex(bss->ifname));
7479 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
7480
7481 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007482 wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
7483 " --> %d (%s)",
7484 bss->ifname, MAC2STR(addr), ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007485 if (ret == -ENOENT)
7486 return 0;
7487 return ret;
7488 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007489 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007490 return -ENOBUFS;
7491}
7492
7493
7494static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
7495 int ifidx)
7496{
7497 struct nl_msg *msg;
7498
7499 wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx);
7500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007501 /* stop listening for EAPOL on this interface */
7502 del_ifidx(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007503
7504 msg = nlmsg_alloc();
7505 if (!msg)
7506 goto nla_put_failure;
7507
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007508 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007509 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
7510
7511 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
7512 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007513 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007514 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007515 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007516 wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
7517}
7518
7519
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007520static const char * nl80211_iftype_str(enum nl80211_iftype mode)
7521{
7522 switch (mode) {
7523 case NL80211_IFTYPE_ADHOC:
7524 return "ADHOC";
7525 case NL80211_IFTYPE_STATION:
7526 return "STATION";
7527 case NL80211_IFTYPE_AP:
7528 return "AP";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07007529 case NL80211_IFTYPE_AP_VLAN:
7530 return "AP_VLAN";
7531 case NL80211_IFTYPE_WDS:
7532 return "WDS";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007533 case NL80211_IFTYPE_MONITOR:
7534 return "MONITOR";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07007535 case NL80211_IFTYPE_MESH_POINT:
7536 return "MESH_POINT";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007537 case NL80211_IFTYPE_P2P_CLIENT:
7538 return "P2P_CLIENT";
7539 case NL80211_IFTYPE_P2P_GO:
7540 return "P2P_GO";
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007541 case NL80211_IFTYPE_P2P_DEVICE:
7542 return "P2P_DEVICE";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007543 default:
7544 return "unknown";
7545 }
7546}
7547
7548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007549static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
7550 const char *ifname,
7551 enum nl80211_iftype iftype,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007552 const u8 *addr, int wds,
7553 int (*handler)(struct nl_msg *, void *),
7554 void *arg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007555{
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007556 struct nl_msg *msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007557 int ifidx;
7558 int ret = -ENOBUFS;
7559
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007560 wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)",
7561 iftype, nl80211_iftype_str(iftype));
7562
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007563 msg = nlmsg_alloc();
7564 if (!msg)
7565 return -1;
7566
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007567 nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007568 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007569 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007570 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);
7571 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
7572
7573 if (iftype == NL80211_IFTYPE_MONITOR) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007574 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007575
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007576 flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007577 if (!flags)
7578 goto nla_put_failure;
7579
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007580 NLA_PUT_FLAG(msg, NL80211_MNTR_FLAG_COOK_FRAMES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007581
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007582 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007583 } else if (wds) {
7584 NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
7585 }
7586
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007587 ret = send_and_recv_msgs(drv, msg, handler, arg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007588 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007589 if (ret) {
7590 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007591 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007592 wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)",
7593 ifname, ret, strerror(-ret));
7594 return ret;
7595 }
7596
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007597 if (iftype == NL80211_IFTYPE_P2P_DEVICE)
7598 return 0;
7599
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007600 ifidx = if_nametoindex(ifname);
7601 wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d",
7602 ifname, ifidx);
7603
7604 if (ifidx <= 0)
7605 return -1;
7606
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007607 /* start listening for EAPOL on this interface */
7608 add_ifidx(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007609
7610 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007611 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007612 nl80211_remove_iface(drv, ifidx);
7613 return -1;
7614 }
7615
7616 return ifidx;
7617}
7618
7619
7620static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
7621 const char *ifname, enum nl80211_iftype iftype,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007622 const u8 *addr, int wds,
7623 int (*handler)(struct nl_msg *, void *),
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007624 void *arg, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007625{
7626 int ret;
7627
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007628 ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler,
7629 arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007630
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007631 /* if error occurred and interface exists already */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007632 if (ret == -ENFILE && if_nametoindex(ifname)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007633 if (use_existing) {
7634 wpa_printf(MSG_DEBUG, "nl80211: Continue using existing interface %s",
7635 ifname);
7636 return -ENFILE;
7637 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007638 wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname);
7639
7640 /* Try to remove the interface that was already there. */
7641 nl80211_remove_iface(drv, if_nametoindex(ifname));
7642
7643 /* Try to create the interface again */
7644 ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007645 wds, handler, arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007646 }
7647
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007648 if (ret >= 0 && is_p2p_net_interface(iftype))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007649 nl80211_disable_11b_rates(drv, ret, 1);
7650
7651 return ret;
7652}
7653
7654
7655static void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)
7656{
7657 struct ieee80211_hdr *hdr;
7658 u16 fc;
7659 union wpa_event_data event;
7660
7661 hdr = (struct ieee80211_hdr *) buf;
7662 fc = le_to_host16(hdr->frame_control);
7663
7664 os_memset(&event, 0, sizeof(event));
7665 event.tx_status.type = WLAN_FC_GET_TYPE(fc);
7666 event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
7667 event.tx_status.dst = hdr->addr1;
7668 event.tx_status.data = buf;
7669 event.tx_status.data_len = len;
7670 event.tx_status.ack = ok;
7671 wpa_supplicant_event(ctx, EVENT_TX_STATUS, &event);
7672}
7673
7674
7675static void from_unknown_sta(struct wpa_driver_nl80211_data *drv,
7676 u8 *buf, size_t len)
7677{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007678 struct ieee80211_hdr *hdr = (void *)buf;
7679 u16 fc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007680 union wpa_event_data event;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007681
7682 if (len < sizeof(*hdr))
7683 return;
7684
7685 fc = le_to_host16(hdr->frame_control);
7686
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007687 os_memset(&event, 0, sizeof(event));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007688 event.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);
7689 event.rx_from_unknown.addr = hdr->addr2;
7690 event.rx_from_unknown.wds = (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) ==
7691 (WLAN_FC_FROMDS | WLAN_FC_TODS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007692 wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
7693}
7694
7695
7696static void handle_frame(struct wpa_driver_nl80211_data *drv,
7697 u8 *buf, size_t len, int datarate, int ssi_signal)
7698{
7699 struct ieee80211_hdr *hdr;
7700 u16 fc;
7701 union wpa_event_data event;
7702
7703 hdr = (struct ieee80211_hdr *) buf;
7704 fc = le_to_host16(hdr->frame_control);
7705
7706 switch (WLAN_FC_GET_TYPE(fc)) {
7707 case WLAN_FC_TYPE_MGMT:
7708 os_memset(&event, 0, sizeof(event));
7709 event.rx_mgmt.frame = buf;
7710 event.rx_mgmt.frame_len = len;
7711 event.rx_mgmt.datarate = datarate;
7712 event.rx_mgmt.ssi_signal = ssi_signal;
7713 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
7714 break;
7715 case WLAN_FC_TYPE_CTRL:
7716 /* can only get here with PS-Poll frames */
7717 wpa_printf(MSG_DEBUG, "CTRL");
7718 from_unknown_sta(drv, buf, len);
7719 break;
7720 case WLAN_FC_TYPE_DATA:
7721 from_unknown_sta(drv, buf, len);
7722 break;
7723 }
7724}
7725
7726
7727static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
7728{
7729 struct wpa_driver_nl80211_data *drv = eloop_ctx;
7730 int len;
7731 unsigned char buf[3000];
7732 struct ieee80211_radiotap_iterator iter;
7733 int ret;
7734 int datarate = 0, ssi_signal = 0;
7735 int injected = 0, failed = 0, rxflags = 0;
7736
7737 len = recv(sock, buf, sizeof(buf), 0);
7738 if (len < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007739 wpa_printf(MSG_ERROR, "nl80211: Monitor socket recv failed: %s",
7740 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007741 return;
7742 }
7743
7744 if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007745 wpa_printf(MSG_INFO, "nl80211: received invalid radiotap frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007746 return;
7747 }
7748
7749 while (1) {
7750 ret = ieee80211_radiotap_iterator_next(&iter);
7751 if (ret == -ENOENT)
7752 break;
7753 if (ret) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007754 wpa_printf(MSG_INFO, "nl80211: received invalid radiotap frame (%d)",
7755 ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007756 return;
7757 }
7758 switch (iter.this_arg_index) {
7759 case IEEE80211_RADIOTAP_FLAGS:
7760 if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
7761 len -= 4;
7762 break;
7763 case IEEE80211_RADIOTAP_RX_FLAGS:
7764 rxflags = 1;
7765 break;
7766 case IEEE80211_RADIOTAP_TX_FLAGS:
7767 injected = 1;
7768 failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
7769 IEEE80211_RADIOTAP_F_TX_FAIL;
7770 break;
7771 case IEEE80211_RADIOTAP_DATA_RETRIES:
7772 break;
7773 case IEEE80211_RADIOTAP_CHANNEL:
7774 /* TODO: convert from freq/flags to channel number */
7775 break;
7776 case IEEE80211_RADIOTAP_RATE:
7777 datarate = *iter.this_arg * 5;
7778 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007779 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
7780 ssi_signal = (s8) *iter.this_arg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007781 break;
7782 }
7783 }
7784
7785 if (rxflags && injected)
7786 return;
7787
7788 if (!injected)
7789 handle_frame(drv, buf + iter.max_length,
7790 len - iter.max_length, datarate, ssi_signal);
7791 else
7792 handle_tx_callback(drv->ctx, buf + iter.max_length,
7793 len - iter.max_length, !failed);
7794}
7795
7796
7797/*
7798 * we post-process the filter code later and rewrite
7799 * this to the offset to the last instruction
7800 */
7801#define PASS 0xFF
7802#define FAIL 0xFE
7803
7804static struct sock_filter msock_filter_insns[] = {
7805 /*
7806 * do a little-endian load of the radiotap length field
7807 */
7808 /* load lower byte into A */
7809 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 2),
7810 /* put it into X (== index register) */
7811 BPF_STMT(BPF_MISC| BPF_TAX, 0),
7812 /* load upper byte into A */
7813 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 3),
7814 /* left-shift it by 8 */
7815 BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8),
7816 /* or with X */
7817 BPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0),
7818 /* put result into X */
7819 BPF_STMT(BPF_MISC| BPF_TAX, 0),
7820
7821 /*
7822 * Allow management frames through, this also gives us those
7823 * management frames that we sent ourselves with status
7824 */
7825 /* load the lower byte of the IEEE 802.11 frame control field */
7826 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
7827 /* mask off frame type and version */
7828 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF),
7829 /* accept frame if it's both 0, fall through otherwise */
7830 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0),
7831
7832 /*
7833 * TODO: add a bit to radiotap RX flags that indicates
7834 * that the sending station is not associated, then
7835 * add a filter here that filters on our DA and that flag
7836 * to allow us to deauth frames to that bad station.
7837 *
7838 * For now allow all To DS data frames through.
7839 */
7840 /* load the IEEE 802.11 frame control field */
7841 BPF_STMT(BPF_LD | BPF_H | BPF_IND, 0),
7842 /* mask off frame type, version and DS status */
7843 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03),
7844 /* accept frame if version 0, type 2 and To DS, fall through otherwise
7845 */
7846 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0),
7847
7848#if 0
7849 /*
7850 * drop non-data frames
7851 */
7852 /* load the lower byte of the frame control field */
7853 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
7854 /* mask off QoS bit */
7855 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c),
7856 /* drop non-data frames */
7857 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL),
7858#endif
7859 /* load the upper byte of the frame control field */
7860 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1),
7861 /* mask off toDS/fromDS */
7862 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03),
7863 /* accept WDS frames */
7864 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0),
7865
7866 /*
7867 * add header length to index
7868 */
7869 /* load the lower byte of the frame control field */
7870 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
7871 /* mask off QoS bit */
7872 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x80),
7873 /* right shift it by 6 to give 0 or 2 */
7874 BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 6),
7875 /* add data frame header length */
7876 BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 24),
7877 /* add index, was start of 802.11 header */
7878 BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0),
7879 /* move to index, now start of LL header */
7880 BPF_STMT(BPF_MISC | BPF_TAX, 0),
7881
7882 /*
7883 * Accept empty data frames, we use those for
7884 * polling activity.
7885 */
7886 BPF_STMT(BPF_LD | BPF_W | BPF_LEN, 0),
7887 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0),
7888
7889 /*
7890 * Accept EAPOL frames
7891 */
7892 BPF_STMT(BPF_LD | BPF_W | BPF_IND, 0),
7893 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL),
7894 BPF_STMT(BPF_LD | BPF_W | BPF_IND, 4),
7895 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL),
7896
7897 /* keep these last two statements or change the code below */
7898 /* return 0 == "DROP" */
7899 BPF_STMT(BPF_RET | BPF_K, 0),
7900 /* return ~0 == "keep all" */
7901 BPF_STMT(BPF_RET | BPF_K, ~0),
7902};
7903
7904static struct sock_fprog msock_filter = {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007905 .len = ARRAY_SIZE(msock_filter_insns),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007906 .filter = msock_filter_insns,
7907};
7908
7909
7910static int add_monitor_filter(int s)
7911{
7912 int idx;
7913
7914 /* rewrite all PASS/FAIL jump offsets */
7915 for (idx = 0; idx < msock_filter.len; idx++) {
7916 struct sock_filter *insn = &msock_filter_insns[idx];
7917
7918 if (BPF_CLASS(insn->code) == BPF_JMP) {
7919 if (insn->code == (BPF_JMP|BPF_JA)) {
7920 if (insn->k == PASS)
7921 insn->k = msock_filter.len - idx - 2;
7922 else if (insn->k == FAIL)
7923 insn->k = msock_filter.len - idx - 3;
7924 }
7925
7926 if (insn->jt == PASS)
7927 insn->jt = msock_filter.len - idx - 2;
7928 else if (insn->jt == FAIL)
7929 insn->jt = msock_filter.len - idx - 3;
7930
7931 if (insn->jf == PASS)
7932 insn->jf = msock_filter.len - idx - 2;
7933 else if (insn->jf == FAIL)
7934 insn->jf = msock_filter.len - idx - 3;
7935 }
7936 }
7937
7938 if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER,
7939 &msock_filter, sizeof(msock_filter))) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007940 wpa_printf(MSG_ERROR, "nl80211: setsockopt(SO_ATTACH_FILTER) failed: %s",
7941 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007942 return -1;
7943 }
7944
7945 return 0;
7946}
7947
7948
7949static void nl80211_remove_monitor_interface(
7950 struct wpa_driver_nl80211_data *drv)
7951{
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007952 if (drv->monitor_refcount > 0)
7953 drv->monitor_refcount--;
7954 wpa_printf(MSG_DEBUG, "nl80211: Remove monitor interface: refcount=%d",
7955 drv->monitor_refcount);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007956 if (drv->monitor_refcount > 0)
7957 return;
7958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007959 if (drv->monitor_ifidx >= 0) {
7960 nl80211_remove_iface(drv, drv->monitor_ifidx);
7961 drv->monitor_ifidx = -1;
7962 }
7963 if (drv->monitor_sock >= 0) {
7964 eloop_unregister_read_sock(drv->monitor_sock);
7965 close(drv->monitor_sock);
7966 drv->monitor_sock = -1;
7967 }
7968}
7969
7970
7971static int
7972nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
7973{
7974 char buf[IFNAMSIZ];
7975 struct sockaddr_ll ll;
7976 int optval;
7977 socklen_t optlen;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007978
7979 if (drv->monitor_ifidx >= 0) {
7980 drv->monitor_refcount++;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007981 wpa_printf(MSG_DEBUG, "nl80211: Re-use existing monitor interface: refcount=%d",
7982 drv->monitor_refcount);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007983 return 0;
7984 }
7985
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007986 if (os_strncmp(drv->first_bss->ifname, "p2p-", 4) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007987 /*
7988 * P2P interface name is of the format p2p-%s-%d. For monitor
7989 * interface name corresponding to P2P GO, replace "p2p-" with
7990 * "mon-" to retain the same interface name length and to
7991 * indicate that it is a monitor interface.
7992 */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007993 snprintf(buf, IFNAMSIZ, "mon-%s", drv->first_bss->ifname + 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007994 } else {
7995 /* Non-P2P interface with AP functionality. */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007996 snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007997 }
7998
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007999 buf[IFNAMSIZ - 1] = '\0';
8000
8001 drv->monitor_ifidx =
8002 nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008003 0, NULL, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008004
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07008005 if (drv->monitor_ifidx == -EOPNOTSUPP) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008006 /*
8007 * This is backward compatibility for a few versions of
8008 * the kernel only that didn't advertise the right
8009 * attributes for the only driver that then supported
8010 * AP mode w/o monitor -- ath6kl.
8011 */
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07008012 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support "
8013 "monitor interface type - try to run without it");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008014 drv->device_ap_sme = 1;
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07008015 }
8016
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008017 if (drv->monitor_ifidx < 0)
8018 return -1;
8019
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008020 if (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008021 goto error;
8022
8023 memset(&ll, 0, sizeof(ll));
8024 ll.sll_family = AF_PACKET;
8025 ll.sll_ifindex = drv->monitor_ifidx;
8026 drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
8027 if (drv->monitor_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008028 wpa_printf(MSG_ERROR, "nl80211: socket[PF_PACKET,SOCK_RAW] failed: %s",
8029 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008030 goto error;
8031 }
8032
8033 if (add_monitor_filter(drv->monitor_sock)) {
8034 wpa_printf(MSG_INFO, "Failed to set socket filter for monitor "
8035 "interface; do filtering in user space");
8036 /* This works, but will cost in performance. */
8037 }
8038
8039 if (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008040 wpa_printf(MSG_ERROR, "nl80211: monitor socket bind failed: %s",
8041 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008042 goto error;
8043 }
8044
8045 optlen = sizeof(optval);
8046 optval = 20;
8047 if (setsockopt
8048 (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008049 wpa_printf(MSG_ERROR, "nl80211: Failed to set socket priority: %s",
8050 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008051 goto error;
8052 }
8053
8054 if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,
8055 drv, NULL)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008056 wpa_printf(MSG_INFO, "nl80211: Could not register monitor read socket");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008057 goto error;
8058 }
8059
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008060 drv->monitor_refcount++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008061 return 0;
8062 error:
8063 nl80211_remove_monitor_interface(drv);
8064 return -1;
8065}
8066
8067
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008068static int nl80211_setup_ap(struct i802_bss *bss)
8069{
8070 struct wpa_driver_nl80211_data *drv = bss->drv;
8071
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008072 wpa_printf(MSG_DEBUG, "nl80211: Setup AP(%s) - device_ap_sme=%d use_monitor=%d",
8073 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008074
8075 /*
8076 * Disable Probe Request reporting unless we need it in this way for
8077 * devices that include the AP SME, in the other case (unless using
8078 * monitor iface) we'll get it through the nl_mgmt socket instead.
8079 */
8080 if (!drv->device_ap_sme)
8081 wpa_driver_nl80211_probe_req_report(bss, 0);
8082
8083 if (!drv->device_ap_sme && !drv->use_monitor)
8084 if (nl80211_mgmt_subscribe_ap(bss))
8085 return -1;
8086
8087 if (drv->device_ap_sme && !drv->use_monitor)
8088 if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
8089 return -1;
8090
8091 if (!drv->device_ap_sme && drv->use_monitor &&
8092 nl80211_create_monitor_interface(drv) &&
8093 !drv->device_ap_sme)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008094 return -1;
8095
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008096 if (drv->device_ap_sme &&
8097 wpa_driver_nl80211_probe_req_report(bss, 1) < 0) {
8098 wpa_printf(MSG_DEBUG, "nl80211: Failed to enable "
8099 "Probe Request frame reporting in AP mode");
8100 /* Try to survive without this */
8101 }
8102
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008103 return 0;
8104}
8105
8106
8107static void nl80211_teardown_ap(struct i802_bss *bss)
8108{
8109 struct wpa_driver_nl80211_data *drv = bss->drv;
8110
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008111 wpa_printf(MSG_DEBUG, "nl80211: Teardown AP(%s) - device_ap_sme=%d use_monitor=%d",
8112 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008113 if (drv->device_ap_sme) {
8114 wpa_driver_nl80211_probe_req_report(bss, 0);
8115 if (!drv->use_monitor)
8116 nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)");
8117 } else if (drv->use_monitor)
8118 nl80211_remove_monitor_interface(drv);
8119 else
8120 nl80211_mgmt_unsubscribe(bss, "AP teardown");
8121
8122 bss->beacon_set = 0;
8123}
8124
8125
8126static int nl80211_send_eapol_data(struct i802_bss *bss,
8127 const u8 *addr, const u8 *data,
8128 size_t data_len)
8129{
8130 struct sockaddr_ll ll;
8131 int ret;
8132
8133 if (bss->drv->eapol_tx_sock < 0) {
8134 wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL");
8135 return -1;
8136 }
8137
8138 os_memset(&ll, 0, sizeof(ll));
8139 ll.sll_family = AF_PACKET;
8140 ll.sll_ifindex = bss->ifindex;
8141 ll.sll_protocol = htons(ETH_P_PAE);
8142 ll.sll_halen = ETH_ALEN;
8143 os_memcpy(ll.sll_addr, addr, ETH_ALEN);
8144 ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,
8145 (struct sockaddr *) &ll, sizeof(ll));
8146 if (ret < 0)
8147 wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s",
8148 strerror(errno));
8149
8150 return ret;
8151}
8152
8153
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008154static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
8155
8156static int wpa_driver_nl80211_hapd_send_eapol(
8157 void *priv, const u8 *addr, const u8 *data,
8158 size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
8159{
8160 struct i802_bss *bss = priv;
8161 struct wpa_driver_nl80211_data *drv = bss->drv;
8162 struct ieee80211_hdr *hdr;
8163 size_t len;
8164 u8 *pos;
8165 int res;
8166 int qos = flags & WPA_STA_WMM;
Dmitry Shmidt641185e2013-11-06 15:17:13 -08008167
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008168 if (drv->device_ap_sme || !drv->use_monitor)
8169 return nl80211_send_eapol_data(bss, addr, data, data_len);
8170
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008171 len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
8172 data_len;
8173 hdr = os_zalloc(len);
8174 if (hdr == NULL) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008175 wpa_printf(MSG_INFO, "nl80211: Failed to allocate EAPOL buffer(len=%lu)",
8176 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008177 return -1;
8178 }
8179
8180 hdr->frame_control =
8181 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
8182 hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
8183 if (encrypt)
8184 hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
8185 if (qos) {
8186 hdr->frame_control |=
8187 host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
8188 }
8189
8190 memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
8191 memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
8192 memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
8193 pos = (u8 *) (hdr + 1);
8194
8195 if (qos) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07008196 /* Set highest priority in QoS header */
8197 pos[0] = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008198 pos[1] = 0;
8199 pos += 2;
8200 }
8201
8202 memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
8203 pos += sizeof(rfc1042_header);
8204 WPA_PUT_BE16(pos, ETH_P_PAE);
8205 pos += 2;
8206 memcpy(pos, data, data_len);
8207
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008208 res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
8209 0, 0, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008210 if (res < 0) {
8211 wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
8212 "failed: %d (%s)",
8213 (unsigned long) len, errno, strerror(errno));
8214 }
8215 os_free(hdr);
8216
8217 return res;
8218}
8219
8220
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008221static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
8222 int total_flags,
8223 int flags_or, int flags_and)
8224{
8225 struct i802_bss *bss = priv;
8226 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008227 struct nl_msg *msg;
8228 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008229 struct nl80211_sta_flag_update upd;
8230
8231 msg = nlmsg_alloc();
8232 if (!msg)
8233 return -ENOMEM;
8234
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008235 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008236
8237 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
8238 if_nametoindex(bss->ifname));
8239 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
8240
8241 /*
8242 * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
8243 * can be removed eventually.
8244 */
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008245 flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS);
8246 if (!flags)
8247 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008248 if (total_flags & WPA_STA_AUTHORIZED)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008249 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_AUTHORIZED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008250
8251 if (total_flags & WPA_STA_WMM)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008252 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_WME);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008253
8254 if (total_flags & WPA_STA_SHORT_PREAMBLE)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008255 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_SHORT_PREAMBLE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008256
8257 if (total_flags & WPA_STA_MFP)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008258 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_MFP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008259
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008260 if (total_flags & WPA_STA_TDLS_PEER)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008261 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_TDLS_PEER);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008262
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07008263 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008264
8265 os_memset(&upd, 0, sizeof(upd));
8266 upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
8267 upd.set = sta_flags_nl80211(flags_or);
8268 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
8269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008270 return send_and_recv_msgs(drv, msg, NULL, NULL);
8271 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008272 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008273 return -ENOBUFS;
8274}
8275
8276
8277static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
8278 struct wpa_driver_associate_params *params)
8279{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008280 enum nl80211_iftype nlmode, old_mode;
8281 struct hostapd_freq_params freq = {
8282 .freq = params->freq,
8283 };
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008284
8285 if (params->p2p) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008286 wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
8287 "group (GO)");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008288 nlmode = NL80211_IFTYPE_P2P_GO;
8289 } else
8290 nlmode = NL80211_IFTYPE_AP;
8291
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008292 old_mode = drv->nlmode;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008293 if (wpa_driver_nl80211_set_mode(drv->first_bss, nlmode)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008294 nl80211_remove_monitor_interface(drv);
8295 return -1;
8296 }
8297
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008298 if (wpa_driver_nl80211_set_freq(drv->first_bss, &freq)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008299 if (old_mode != nlmode)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008300 wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008301 nl80211_remove_monitor_interface(drv);
8302 return -1;
8303 }
8304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008305 return 0;
8306}
8307
8308
8309static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv)
8310{
8311 struct nl_msg *msg;
8312 int ret = -1;
8313
8314 msg = nlmsg_alloc();
8315 if (!msg)
8316 return -1;
8317
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008318 nl80211_cmd(drv, msg, 0, NL80211_CMD_LEAVE_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008319 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8320 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8321 msg = NULL;
8322 if (ret) {
8323 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
8324 "(%s)", ret, strerror(-ret));
8325 goto nla_put_failure;
8326 }
8327
8328 ret = 0;
8329 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS request sent successfully");
8330
8331nla_put_failure:
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008332 if (wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt56052862013-10-04 10:23:25 -07008333 NL80211_IFTYPE_STATION)) {
8334 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
8335 "station mode");
8336 }
8337
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008338 nlmsg_free(msg);
8339 return ret;
8340}
8341
8342
8343static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
8344 struct wpa_driver_associate_params *params)
8345{
8346 struct nl_msg *msg;
8347 int ret = -1;
8348 int count = 0;
8349
8350 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
8351
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008352 if (wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008353 NL80211_IFTYPE_ADHOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008354 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
8355 "IBSS mode");
8356 return -1;
8357 }
8358
8359retry:
8360 msg = nlmsg_alloc();
8361 if (!msg)
8362 return -1;
8363
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008364 nl80211_cmd(drv, msg, 0, NL80211_CMD_JOIN_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008365 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8366
8367 if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
8368 goto nla_put_failure;
8369
8370 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
8371 params->ssid, params->ssid_len);
8372 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
8373 params->ssid);
8374 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
8375 drv->ssid_len = params->ssid_len;
8376
8377 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
8378 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
8379
8380 ret = nl80211_set_conn_keys(params, msg);
8381 if (ret)
8382 goto nla_put_failure;
8383
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008384 if (params->bssid && params->fixed_bssid) {
8385 wpa_printf(MSG_DEBUG, " * BSSID=" MACSTR,
8386 MAC2STR(params->bssid));
8387 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
8388 }
8389
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008390 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
8391 params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
8392 params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
8393 params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008394 wpa_printf(MSG_DEBUG, " * control port");
8395 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
8396 }
8397
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008398 if (params->wpa_ie) {
8399 wpa_hexdump(MSG_DEBUG,
8400 " * Extra IEs for Beacon/Probe Response frames",
8401 params->wpa_ie, params->wpa_ie_len);
8402 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
8403 params->wpa_ie);
8404 }
8405
8406 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8407 msg = NULL;
8408 if (ret) {
8409 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
8410 ret, strerror(-ret));
8411 count++;
8412 if (ret == -EALREADY && count == 1) {
8413 wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after "
8414 "forced leave");
8415 nl80211_leave_ibss(drv);
8416 nlmsg_free(msg);
8417 goto retry;
8418 }
8419
8420 goto nla_put_failure;
8421 }
8422 ret = 0;
8423 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS request sent successfully");
8424
8425nla_put_failure:
8426 nlmsg_free(msg);
8427 return ret;
8428}
8429
8430
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008431static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
8432 struct wpa_driver_associate_params *params,
8433 struct nl_msg *msg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008434{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008435 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008436
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008437 if (params->bssid) {
8438 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
8439 MAC2STR(params->bssid));
8440 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
8441 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008442
Dmitry Shmidt96be6222014-02-13 10:16:51 -08008443 if (params->bssid_hint) {
8444 wpa_printf(MSG_DEBUG, " * bssid_hint=" MACSTR,
8445 MAC2STR(params->bssid_hint));
8446 NLA_PUT(msg, NL80211_ATTR_MAC_HINT, ETH_ALEN,
8447 params->bssid_hint);
8448 }
8449
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008450 if (params->freq) {
8451 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
8452 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07008453 drv->assoc_freq = params->freq;
8454 } else
8455 drv->assoc_freq = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008456
Dmitry Shmidt96be6222014-02-13 10:16:51 -08008457 if (params->freq_hint) {
8458 wpa_printf(MSG_DEBUG, " * freq_hint=%d", params->freq_hint);
8459 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ_HINT,
8460 params->freq_hint);
8461 }
8462
Dmitry Shmidt04949592012-07-19 12:16:46 -07008463 if (params->bg_scan_period >= 0) {
8464 wpa_printf(MSG_DEBUG, " * bg scan period=%d",
8465 params->bg_scan_period);
8466 NLA_PUT_U16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
8467 params->bg_scan_period);
8468 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008469
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008470 if (params->ssid) {
8471 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
8472 params->ssid, params->ssid_len);
8473 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
8474 params->ssid);
8475 if (params->ssid_len > sizeof(drv->ssid))
8476 goto nla_put_failure;
8477 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
8478 drv->ssid_len = params->ssid_len;
8479 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008480
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008481 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
8482 if (params->wpa_ie)
8483 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
8484 params->wpa_ie);
8485
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008486 if (params->wpa_proto) {
8487 enum nl80211_wpa_versions ver = 0;
8488
8489 if (params->wpa_proto & WPA_PROTO_WPA)
8490 ver |= NL80211_WPA_VERSION_1;
8491 if (params->wpa_proto & WPA_PROTO_RSN)
8492 ver |= NL80211_WPA_VERSION_2;
8493
8494 wpa_printf(MSG_DEBUG, " * WPA Versions 0x%x", ver);
8495 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
8496 }
8497
8498 if (params->pairwise_suite != WPA_CIPHER_NONE) {
8499 u32 cipher = wpa_cipher_to_cipher_suite(params->pairwise_suite);
8500 wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher);
8501 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
8502 }
8503
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008504 if (params->group_suite == WPA_CIPHER_GTK_NOT_USED &&
8505 !(drv->capa.enc & WPA_DRIVER_CAPA_ENC_GTK_NOT_USED)) {
8506 /*
8507 * This is likely to work even though many drivers do not
8508 * advertise support for operations without GTK.
8509 */
8510 wpa_printf(MSG_DEBUG, " * skip group cipher configuration for GTK_NOT_USED due to missing driver support advertisement");
8511 } else if (params->group_suite != WPA_CIPHER_NONE) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008512 u32 cipher = wpa_cipher_to_cipher_suite(params->group_suite);
8513 wpa_printf(MSG_DEBUG, " * group=0x%x", cipher);
8514 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
8515 }
8516
8517 if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
8518 params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
8519 params->key_mgmt_suite == WPA_KEY_MGMT_FT_IEEE8021X ||
8520 params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
8521 params->key_mgmt_suite == WPA_KEY_MGMT_CCKM) {
8522 int mgmt = WLAN_AKM_SUITE_PSK;
8523
8524 switch (params->key_mgmt_suite) {
8525 case WPA_KEY_MGMT_CCKM:
8526 mgmt = WLAN_AKM_SUITE_CCKM;
8527 break;
8528 case WPA_KEY_MGMT_IEEE8021X:
8529 mgmt = WLAN_AKM_SUITE_8021X;
8530 break;
8531 case WPA_KEY_MGMT_FT_IEEE8021X:
8532 mgmt = WLAN_AKM_SUITE_FT_8021X;
8533 break;
8534 case WPA_KEY_MGMT_FT_PSK:
8535 mgmt = WLAN_AKM_SUITE_FT_PSK;
8536 break;
8537 case WPA_KEY_MGMT_PSK:
8538 default:
8539 mgmt = WLAN_AKM_SUITE_PSK;
8540 break;
8541 }
8542 NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);
8543 }
8544
8545 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
8546
8547 if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)
8548 NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);
8549
8550 if (params->disable_ht)
8551 NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);
8552
8553 if (params->htcaps && params->htcaps_mask) {
8554 int sz = sizeof(struct ieee80211_ht_capabilities);
8555 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);
8556 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
8557 params->htcaps_mask);
8558 }
8559
8560#ifdef CONFIG_VHT_OVERRIDES
8561 if (params->disable_vht) {
8562 wpa_printf(MSG_DEBUG, " * VHT disabled");
8563 NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
8564 }
8565
8566 if (params->vhtcaps && params->vhtcaps_mask) {
8567 int sz = sizeof(struct ieee80211_vht_capabilities);
8568 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
8569 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
8570 params->vhtcaps_mask);
8571 }
8572#endif /* CONFIG_VHT_OVERRIDES */
8573
8574 if (params->p2p)
8575 wpa_printf(MSG_DEBUG, " * P2P group");
8576
8577 return 0;
8578nla_put_failure:
8579 return -1;
8580}
8581
8582
8583static int wpa_driver_nl80211_try_connect(
8584 struct wpa_driver_nl80211_data *drv,
8585 struct wpa_driver_associate_params *params)
8586{
8587 struct nl_msg *msg;
8588 enum nl80211_auth_type type;
8589 int ret;
8590 int algs;
8591
8592 msg = nlmsg_alloc();
8593 if (!msg)
8594 return -1;
8595
8596 wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
8597 nl80211_cmd(drv, msg, 0, NL80211_CMD_CONNECT);
8598
8599 ret = nl80211_connect_common(drv, params, msg);
8600 if (ret)
8601 goto nla_put_failure;
8602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008603 algs = 0;
8604 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
8605 algs++;
8606 if (params->auth_alg & WPA_AUTH_ALG_SHARED)
8607 algs++;
8608 if (params->auth_alg & WPA_AUTH_ALG_LEAP)
8609 algs++;
8610 if (algs > 1) {
8611 wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic "
8612 "selection");
8613 goto skip_auth_type;
8614 }
8615
8616 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
8617 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
8618 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
8619 type = NL80211_AUTHTYPE_SHARED_KEY;
8620 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
8621 type = NL80211_AUTHTYPE_NETWORK_EAP;
8622 else if (params->auth_alg & WPA_AUTH_ALG_FT)
8623 type = NL80211_AUTHTYPE_FT;
8624 else
8625 goto nla_put_failure;
8626
8627 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
8628 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
8629
8630skip_auth_type:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008631 ret = nl80211_set_conn_keys(params, msg);
8632 if (ret)
8633 goto nla_put_failure;
8634
8635 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8636 msg = NULL;
8637 if (ret) {
8638 wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
8639 "(%s)", ret, strerror(-ret));
8640 goto nla_put_failure;
8641 }
8642 ret = 0;
8643 wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully");
8644
8645nla_put_failure:
8646 nlmsg_free(msg);
8647 return ret;
8648
8649}
8650
8651
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008652static int wpa_driver_nl80211_connect(
8653 struct wpa_driver_nl80211_data *drv,
8654 struct wpa_driver_associate_params *params)
8655{
8656 int ret = wpa_driver_nl80211_try_connect(drv, params);
8657 if (ret == -EALREADY) {
8658 /*
8659 * cfg80211 does not currently accept new connections if
8660 * we are already connected. As a workaround, force
8661 * disconnection and try again.
8662 */
8663 wpa_printf(MSG_DEBUG, "nl80211: Explicitly "
8664 "disconnecting before reassociation "
8665 "attempt");
8666 if (wpa_driver_nl80211_disconnect(
8667 drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
8668 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008669 ret = wpa_driver_nl80211_try_connect(drv, params);
8670 }
8671 return ret;
8672}
8673
8674
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008675static int wpa_driver_nl80211_associate(
8676 void *priv, struct wpa_driver_associate_params *params)
8677{
8678 struct i802_bss *bss = priv;
8679 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008680 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008681 struct nl_msg *msg;
8682
8683 if (params->mode == IEEE80211_MODE_AP)
8684 return wpa_driver_nl80211_ap(drv, params);
8685
8686 if (params->mode == IEEE80211_MODE_IBSS)
8687 return wpa_driver_nl80211_ibss(drv, params);
8688
8689 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008690 enum nl80211_iftype nlmode = params->p2p ?
8691 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
8692
8693 if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008694 return -1;
8695 return wpa_driver_nl80211_connect(drv, params);
8696 }
8697
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008698 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008699
8700 msg = nlmsg_alloc();
8701 if (!msg)
8702 return -1;
8703
8704 wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)",
8705 drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008706 nl80211_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008707
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008708 ret = nl80211_connect_common(drv, params, msg);
8709 if (ret)
8710 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008711
8712 if (params->prev_bssid) {
8713 wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
8714 MAC2STR(params->prev_bssid));
8715 NLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
8716 params->prev_bssid);
8717 }
8718
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008719 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8720 msg = NULL;
8721 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008722 wpa_dbg(drv->ctx, MSG_DEBUG,
8723 "nl80211: MLME command failed (assoc): ret=%d (%s)",
8724 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008725 nl80211_dump_scan(drv);
8726 goto nla_put_failure;
8727 }
8728 ret = 0;
8729 wpa_printf(MSG_DEBUG, "nl80211: Association request send "
8730 "successfully");
8731
8732nla_put_failure:
8733 nlmsg_free(msg);
8734 return ret;
8735}
8736
8737
8738static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008739 int ifindex, enum nl80211_iftype mode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008740{
8741 struct nl_msg *msg;
8742 int ret = -ENOBUFS;
8743
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008744 wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)",
8745 ifindex, mode, nl80211_iftype_str(mode));
8746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008747 msg = nlmsg_alloc();
8748 if (!msg)
8749 return -ENOMEM;
8750
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008751 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008752 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008753 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008754 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);
8755
8756 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008757 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008758 if (!ret)
8759 return 0;
8760nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008761 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008762 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
8763 " %d (%s)", ifindex, mode, ret, strerror(-ret));
8764 return ret;
8765}
8766
8767
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008768static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
8769 enum nl80211_iftype nlmode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008770{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008771 struct wpa_driver_nl80211_data *drv = bss->drv;
8772 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008773 int i;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008774 int was_ap = is_ap_interface(drv->nlmode);
8775 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008776
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008777 res = nl80211_set_mode(drv, drv->ifindex, nlmode);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008778 if (res && nlmode == nl80211_get_ifmode(bss))
8779 res = 0;
8780
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008781 if (res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008782 drv->nlmode = nlmode;
8783 ret = 0;
8784 goto done;
8785 }
8786
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008787 if (res == -ENODEV)
8788 return -1;
8789
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008790 if (nlmode == drv->nlmode) {
8791 wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
8792 "requested mode - ignore error");
8793 ret = 0;
8794 goto done; /* Already in the requested mode */
8795 }
8796
8797 /* mac80211 doesn't allow mode changes while the device is up, so
8798 * take the device down, try to set the mode again, and bring the
8799 * device back up.
8800 */
8801 wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
8802 "interface down");
8803 for (i = 0; i < 10; i++) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008804 res = i802_set_iface_flags(bss, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008805 if (res == -EACCES || res == -ENODEV)
8806 break;
8807 if (res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008808 /* Try to set the mode again while the interface is
8809 * down */
8810 ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008811 if (ret == -EACCES)
8812 break;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008813 res = i802_set_iface_flags(bss, 1);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008814 if (res && !ret)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008815 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008816 else if (ret != -EBUSY)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008817 break;
8818 } else
8819 wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
8820 "interface down");
8821 os_sleep(0, 100000);
8822 }
8823
8824 if (!ret) {
8825 wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
8826 "interface is down");
8827 drv->nlmode = nlmode;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008828 drv->ignore_if_down_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008829 }
8830
8831done:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008832 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008833 wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
8834 "from %d failed", nlmode, drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008835 return ret;
8836 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008837
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008838 if (is_p2p_net_interface(nlmode))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008839 nl80211_disable_11b_rates(drv, drv->ifindex, 1);
8840 else if (drv->disabled_11b_rates)
8841 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
8842
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008843 if (is_ap_interface(nlmode)) {
8844 nl80211_mgmt_unsubscribe(bss, "start AP");
8845 /* Setup additional AP mode functionality if needed */
8846 if (nl80211_setup_ap(bss))
8847 return -1;
8848 } else if (was_ap) {
8849 /* Remove additional AP mode functionality */
8850 nl80211_teardown_ap(bss);
8851 } else {
8852 nl80211_mgmt_unsubscribe(bss, "mode change");
8853 }
8854
Dmitry Shmidt04949592012-07-19 12:16:46 -07008855 if (!bss->in_deinit && !is_ap_interface(nlmode) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008856 nl80211_mgmt_subscribe_non_ap(bss) < 0)
8857 wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
8858 "frame processing - ignore for now");
8859
8860 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008861}
8862
8863
8864static int wpa_driver_nl80211_get_capa(void *priv,
8865 struct wpa_driver_capa *capa)
8866{
8867 struct i802_bss *bss = priv;
8868 struct wpa_driver_nl80211_data *drv = bss->drv;
8869 if (!drv->has_capability)
8870 return -1;
8871 os_memcpy(capa, &drv->capa, sizeof(*capa));
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008872 if (drv->extended_capa && drv->extended_capa_mask) {
8873 capa->extended_capa = drv->extended_capa;
8874 capa->extended_capa_mask = drv->extended_capa_mask;
8875 capa->extended_capa_len = drv->extended_capa_len;
8876 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008877
8878 if ((capa->flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
8879 !drv->allow_p2p_device) {
8880 wpa_printf(MSG_DEBUG, "nl80211: Do not indicate P2P_DEVICE support (p2p_device=1 driver param not specified)");
8881 capa->flags &= ~WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
8882 }
8883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008884 return 0;
8885}
8886
8887
8888static int wpa_driver_nl80211_set_operstate(void *priv, int state)
8889{
8890 struct i802_bss *bss = priv;
8891 struct wpa_driver_nl80211_data *drv = bss->drv;
8892
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008893 wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)",
8894 bss->ifname, drv->operstate, state,
8895 state ? "UP" : "DORMANT");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008896 drv->operstate = state;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008897 return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008898 state ? IF_OPER_UP : IF_OPER_DORMANT);
8899}
8900
8901
8902static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
8903{
8904 struct i802_bss *bss = priv;
8905 struct wpa_driver_nl80211_data *drv = bss->drv;
8906 struct nl_msg *msg;
8907 struct nl80211_sta_flag_update upd;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008908 int ret = -ENOBUFS;
8909
8910 if (!drv->associated && is_zero_ether_addr(drv->bssid) && !authorized) {
8911 wpa_printf(MSG_DEBUG, "nl80211: Skip set_supp_port(unauthorized) while not associated");
8912 return 0;
8913 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008914
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008915 wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
8916 MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
8917
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008918 msg = nlmsg_alloc();
8919 if (!msg)
8920 return -ENOMEM;
8921
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008922 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008923
8924 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
8925 if_nametoindex(bss->ifname));
8926 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
8927
8928 os_memset(&upd, 0, sizeof(upd));
8929 upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);
8930 if (authorized)
8931 upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);
8932 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
8933
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008934 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8935 msg = NULL;
8936 if (!ret)
8937 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008938 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008939 nlmsg_free(msg);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008940 wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)",
8941 ret, strerror(-ret));
8942 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008943}
8944
8945
Jouni Malinen75ecf522011-06-27 15:19:46 -07008946/* Set kernel driver on given frequency (MHz) */
8947static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008948{
Jouni Malinen75ecf522011-06-27 15:19:46 -07008949 struct i802_bss *bss = priv;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008950 return wpa_driver_nl80211_set_freq(bss, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008951}
8952
8953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008954static inline int min_int(int a, int b)
8955{
8956 if (a < b)
8957 return a;
8958 return b;
8959}
8960
8961
8962static int get_key_handler(struct nl_msg *msg, void *arg)
8963{
8964 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8965 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8966
8967 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8968 genlmsg_attrlen(gnlh, 0), NULL);
8969
8970 /*
8971 * TODO: validate the key index and mac address!
8972 * Otherwise, there's a race condition as soon as
8973 * the kernel starts sending key notifications.
8974 */
8975
8976 if (tb[NL80211_ATTR_KEY_SEQ])
8977 memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
8978 min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
8979 return NL_SKIP;
8980}
8981
8982
8983static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
8984 int idx, u8 *seq)
8985{
8986 struct i802_bss *bss = priv;
8987 struct wpa_driver_nl80211_data *drv = bss->drv;
8988 struct nl_msg *msg;
8989
8990 msg = nlmsg_alloc();
8991 if (!msg)
8992 return -ENOMEM;
8993
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008994 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008995
8996 if (addr)
8997 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
8998 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
8999 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
9000
9001 memset(seq, 0, 6);
9002
9003 return send_and_recv_msgs(drv, msg, get_key_handler, seq);
9004 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009005 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009006 return -ENOBUFS;
9007}
9008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009009
9010static int i802_set_rts(void *priv, int rts)
9011{
9012 struct i802_bss *bss = priv;
9013 struct wpa_driver_nl80211_data *drv = bss->drv;
9014 struct nl_msg *msg;
9015 int ret = -ENOBUFS;
9016 u32 val;
9017
9018 msg = nlmsg_alloc();
9019 if (!msg)
9020 return -ENOMEM;
9021
9022 if (rts >= 2347)
9023 val = (u32) -1;
9024 else
9025 val = rts;
9026
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009027 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009028 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
9029 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val);
9030
9031 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009032 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009033 if (!ret)
9034 return 0;
9035nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009036 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009037 wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
9038 "%d (%s)", rts, ret, strerror(-ret));
9039 return ret;
9040}
9041
9042
9043static int i802_set_frag(void *priv, int frag)
9044{
9045 struct i802_bss *bss = priv;
9046 struct wpa_driver_nl80211_data *drv = bss->drv;
9047 struct nl_msg *msg;
9048 int ret = -ENOBUFS;
9049 u32 val;
9050
9051 msg = nlmsg_alloc();
9052 if (!msg)
9053 return -ENOMEM;
9054
9055 if (frag >= 2346)
9056 val = (u32) -1;
9057 else
9058 val = frag;
9059
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009060 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009061 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
9062 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val);
9063
9064 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009065 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009066 if (!ret)
9067 return 0;
9068nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009069 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009070 wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
9071 "%d: %d (%s)", frag, ret, strerror(-ret));
9072 return ret;
9073}
9074
9075
9076static int i802_flush(void *priv)
9077{
9078 struct i802_bss *bss = priv;
9079 struct wpa_driver_nl80211_data *drv = bss->drv;
9080 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009081 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009082
9083 msg = nlmsg_alloc();
9084 if (!msg)
9085 return -1;
9086
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07009087 wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
9088 bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009089 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009090
9091 /*
9092 * XXX: FIX! this needs to flush all VLANs too
9093 */
9094 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
9095 if_nametoindex(bss->ifname));
9096
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009097 res = send_and_recv_msgs(drv, msg, NULL, NULL);
9098 if (res) {
9099 wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
9100 "(%s)", res, strerror(-res));
9101 }
9102 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009103 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009104 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009105 return -ENOBUFS;
9106}
9107
9108
9109static int get_sta_handler(struct nl_msg *msg, void *arg)
9110{
9111 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9112 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9113 struct hostap_sta_driver_data *data = arg;
9114 struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
9115 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9116 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
9117 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
9118 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
9119 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
9120 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03009121 [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009122 };
9123
9124 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9125 genlmsg_attrlen(gnlh, 0), NULL);
9126
9127 /*
9128 * TODO: validate the interface and mac address!
9129 * Otherwise, there's a race condition as soon as
9130 * the kernel starts sending station notifications.
9131 */
9132
9133 if (!tb[NL80211_ATTR_STA_INFO]) {
9134 wpa_printf(MSG_DEBUG, "sta stats missing!");
9135 return NL_SKIP;
9136 }
9137 if (nla_parse_nested(stats, NL80211_STA_INFO_MAX,
9138 tb[NL80211_ATTR_STA_INFO],
9139 stats_policy)) {
9140 wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
9141 return NL_SKIP;
9142 }
9143
9144 if (stats[NL80211_STA_INFO_INACTIVE_TIME])
9145 data->inactive_msec =
9146 nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);
9147 if (stats[NL80211_STA_INFO_RX_BYTES])
9148 data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
9149 if (stats[NL80211_STA_INFO_TX_BYTES])
9150 data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
9151 if (stats[NL80211_STA_INFO_RX_PACKETS])
9152 data->rx_packets =
9153 nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
9154 if (stats[NL80211_STA_INFO_TX_PACKETS])
9155 data->tx_packets =
9156 nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03009157 if (stats[NL80211_STA_INFO_TX_FAILED])
9158 data->tx_retry_failed =
9159 nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009160
9161 return NL_SKIP;
9162}
9163
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009164static int i802_read_sta_data(struct i802_bss *bss,
9165 struct hostap_sta_driver_data *data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009166 const u8 *addr)
9167{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009168 struct wpa_driver_nl80211_data *drv = bss->drv;
9169 struct nl_msg *msg;
9170
9171 os_memset(data, 0, sizeof(*data));
9172 msg = nlmsg_alloc();
9173 if (!msg)
9174 return -ENOMEM;
9175
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009176 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009177
9178 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
9179 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
9180
9181 return send_and_recv_msgs(drv, msg, get_sta_handler, data);
9182 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009183 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009184 return -ENOBUFS;
9185}
9186
9187
9188static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
9189 int cw_min, int cw_max, int burst_time)
9190{
9191 struct i802_bss *bss = priv;
9192 struct wpa_driver_nl80211_data *drv = bss->drv;
9193 struct nl_msg *msg;
9194 struct nlattr *txq, *params;
9195
9196 msg = nlmsg_alloc();
9197 if (!msg)
9198 return -1;
9199
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009200 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009201
9202 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
9203
9204 txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);
9205 if (!txq)
9206 goto nla_put_failure;
9207
9208 /* We are only sending parameters for a single TXQ at a time */
9209 params = nla_nest_start(msg, 1);
9210 if (!params)
9211 goto nla_put_failure;
9212
9213 switch (queue) {
9214 case 0:
9215 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO);
9216 break;
9217 case 1:
9218 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI);
9219 break;
9220 case 2:
9221 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE);
9222 break;
9223 case 3:
9224 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK);
9225 break;
9226 }
9227 /* Burst time is configured in units of 0.1 msec and TXOP parameter in
9228 * 32 usec, so need to convert the value here. */
9229 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32);
9230 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min);
9231 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max);
9232 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs);
9233
9234 nla_nest_end(msg, params);
9235
9236 nla_nest_end(msg, txq);
9237
9238 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
9239 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009240 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009241 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009242 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009243 return -1;
9244}
9245
9246
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009247static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009248 const char *ifname, int vlan_id)
9249{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009250 struct wpa_driver_nl80211_data *drv = bss->drv;
9251 struct nl_msg *msg;
9252 int ret = -ENOBUFS;
9253
9254 msg = nlmsg_alloc();
9255 if (!msg)
9256 return -ENOMEM;
9257
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009258 wpa_printf(MSG_DEBUG, "nl80211: %s[%d]: set_sta_vlan(" MACSTR
9259 ", ifname=%s[%d], vlan_id=%d)",
9260 bss->ifname, if_nametoindex(bss->ifname),
9261 MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009262 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009263
9264 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
9265 if_nametoindex(bss->ifname));
9266 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
9267 NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN,
9268 if_nametoindex(ifname));
9269
9270 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009271 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009272 if (ret < 0) {
9273 wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
9274 MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
9275 MAC2STR(addr), ifname, vlan_id, ret,
9276 strerror(-ret));
9277 }
9278 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009279 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009280 return ret;
9281}
9282
9283
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009284static int i802_get_inact_sec(void *priv, const u8 *addr)
9285{
9286 struct hostap_sta_driver_data data;
9287 int ret;
9288
9289 data.inactive_msec = (unsigned long) -1;
9290 ret = i802_read_sta_data(priv, &data, addr);
9291 if (ret || data.inactive_msec == (unsigned long) -1)
9292 return -1;
9293 return data.inactive_msec / 1000;
9294}
9295
9296
9297static int i802_sta_clear_stats(void *priv, const u8 *addr)
9298{
9299#if 0
9300 /* TODO */
9301#endif
9302 return 0;
9303}
9304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009305
9306static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
9307 int reason)
9308{
9309 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07009310 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009311 struct ieee80211_mgmt mgmt;
9312
Dmitry Shmidt04949592012-07-19 12:16:46 -07009313 if (drv->device_ap_sme)
9314 return wpa_driver_nl80211_sta_remove(bss, addr);
9315
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009316 memset(&mgmt, 0, sizeof(mgmt));
9317 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
9318 WLAN_FC_STYPE_DEAUTH);
9319 memcpy(mgmt.da, addr, ETH_ALEN);
9320 memcpy(mgmt.sa, own_addr, ETH_ALEN);
9321 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
9322 mgmt.u.deauth.reason_code = host_to_le16(reason);
9323 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
9324 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009325 sizeof(mgmt.u.deauth), 0, 0, 0, 0,
9326 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009327}
9328
9329
9330static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
9331 int reason)
9332{
9333 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07009334 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009335 struct ieee80211_mgmt mgmt;
9336
Dmitry Shmidt04949592012-07-19 12:16:46 -07009337 if (drv->device_ap_sme)
9338 return wpa_driver_nl80211_sta_remove(bss, addr);
9339
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009340 memset(&mgmt, 0, sizeof(mgmt));
9341 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
9342 WLAN_FC_STYPE_DISASSOC);
9343 memcpy(mgmt.da, addr, ETH_ALEN);
9344 memcpy(mgmt.sa, own_addr, ETH_ALEN);
9345 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
9346 mgmt.u.disassoc.reason_code = host_to_le16(reason);
9347 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
9348 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009349 sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
9350 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009351}
9352
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009353
Jouni Malinen75ecf522011-06-27 15:19:46 -07009354static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9355{
9356 int i;
9357 int *old;
9358
9359 wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
9360 ifidx);
9361 for (i = 0; i < drv->num_if_indices; i++) {
9362 if (drv->if_indices[i] == 0) {
9363 drv->if_indices[i] = ifidx;
9364 return;
9365 }
9366 }
9367
9368 if (drv->if_indices != drv->default_if_indices)
9369 old = drv->if_indices;
9370 else
9371 old = NULL;
9372
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009373 drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
9374 sizeof(int));
Jouni Malinen75ecf522011-06-27 15:19:46 -07009375 if (!drv->if_indices) {
9376 if (!old)
9377 drv->if_indices = drv->default_if_indices;
9378 else
9379 drv->if_indices = old;
9380 wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
9381 "interfaces");
9382 wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
9383 return;
9384 } else if (!old)
9385 os_memcpy(drv->if_indices, drv->default_if_indices,
9386 sizeof(drv->default_if_indices));
9387 drv->if_indices[drv->num_if_indices] = ifidx;
9388 drv->num_if_indices++;
9389}
9390
9391
9392static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9393{
9394 int i;
9395
9396 for (i = 0; i < drv->num_if_indices; i++) {
9397 if (drv->if_indices[i] == ifidx) {
9398 drv->if_indices[i] = 0;
9399 break;
9400 }
9401 }
9402}
9403
9404
9405static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9406{
9407 int i;
9408
9409 for (i = 0; i < drv->num_if_indices; i++)
9410 if (drv->if_indices[i] == ifidx)
9411 return 1;
9412
9413 return 0;
9414}
9415
9416
9417static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009418 const char *bridge_ifname, char *ifname_wds)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009419{
9420 struct i802_bss *bss = priv;
9421 struct wpa_driver_nl80211_data *drv = bss->drv;
9422 char name[IFNAMSIZ + 1];
9423
9424 os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009425 if (ifname_wds)
9426 os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
9427
Jouni Malinen75ecf522011-06-27 15:19:46 -07009428 wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
9429 " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
9430 if (val) {
9431 if (!if_nametoindex(name)) {
9432 if (nl80211_create_iface(drv, name,
9433 NL80211_IFTYPE_AP_VLAN,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009434 bss->addr, 1, NULL, NULL, 0) <
9435 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009436 return -1;
9437 if (bridge_ifname &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009438 linux_br_add_if(drv->global->ioctl_sock,
9439 bridge_ifname, name) < 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009440 return -1;
9441 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009442 if (linux_set_iface_flags(drv->global->ioctl_sock, name, 1)) {
9443 wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA "
9444 "interface %s up", name);
9445 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07009446 return i802_set_sta_vlan(priv, addr, name, 0);
9447 } else {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07009448 if (bridge_ifname)
9449 linux_br_del_if(drv->global->ioctl_sock, bridge_ifname,
9450 name);
9451
Jouni Malinen75ecf522011-06-27 15:19:46 -07009452 i802_set_sta_vlan(priv, addr, bss->ifname, 0);
Dmitry Shmidta38abf92014-03-06 13:38:44 -08009453 nl80211_remove_iface(drv, if_nametoindex(name));
9454 return 0;
Jouni Malinen75ecf522011-06-27 15:19:46 -07009455 }
9456}
9457
9458
9459static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
9460{
9461 struct wpa_driver_nl80211_data *drv = eloop_ctx;
9462 struct sockaddr_ll lladdr;
9463 unsigned char buf[3000];
9464 int len;
9465 socklen_t fromlen = sizeof(lladdr);
9466
9467 len = recvfrom(sock, buf, sizeof(buf), 0,
9468 (struct sockaddr *)&lladdr, &fromlen);
9469 if (len < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009470 wpa_printf(MSG_ERROR, "nl80211: EAPOL recv failed: %s",
9471 strerror(errno));
Jouni Malinen75ecf522011-06-27 15:19:46 -07009472 return;
9473 }
9474
9475 if (have_ifidx(drv, lladdr.sll_ifindex))
9476 drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
9477}
9478
9479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009480static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
9481 struct i802_bss *bss,
9482 const char *brname, const char *ifname)
9483{
9484 int ifindex;
9485 char in_br[IFNAMSIZ];
9486
9487 os_strlcpy(bss->brname, brname, IFNAMSIZ);
9488 ifindex = if_nametoindex(brname);
9489 if (ifindex == 0) {
9490 /*
9491 * Bridge was configured, but the bridge device does
9492 * not exist. Try to add it now.
9493 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009494 if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009495 wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
9496 "bridge interface %s: %s",
9497 brname, strerror(errno));
9498 return -1;
9499 }
9500 bss->added_bridge = 1;
9501 add_ifidx(drv, if_nametoindex(brname));
9502 }
9503
9504 if (linux_br_get(in_br, ifname) == 0) {
9505 if (os_strcmp(in_br, brname) == 0)
9506 return 0; /* already in the bridge */
9507
9508 wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
9509 "bridge %s", ifname, in_br);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009510 if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
9511 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009512 wpa_printf(MSG_ERROR, "nl80211: Failed to "
9513 "remove interface %s from bridge "
9514 "%s: %s",
9515 ifname, brname, strerror(errno));
9516 return -1;
9517 }
9518 }
9519
9520 wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
9521 ifname, brname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009522 if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009523 wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
9524 "into bridge %s: %s",
9525 ifname, brname, strerror(errno));
9526 return -1;
9527 }
9528 bss->added_if_into_bridge = 1;
9529
9530 return 0;
9531}
9532
9533
9534static void *i802_init(struct hostapd_data *hapd,
9535 struct wpa_init_params *params)
9536{
9537 struct wpa_driver_nl80211_data *drv;
9538 struct i802_bss *bss;
9539 size_t i;
9540 char brname[IFNAMSIZ];
9541 int ifindex, br_ifindex;
9542 int br_added = 0;
9543
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08009544 bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
9545 params->global_priv, 1,
9546 params->bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009547 if (bss == NULL)
9548 return NULL;
9549
9550 drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009552 if (linux_br_get(brname, params->ifname) == 0) {
9553 wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
9554 params->ifname, brname);
9555 br_ifindex = if_nametoindex(brname);
9556 } else {
9557 brname[0] = '\0';
9558 br_ifindex = 0;
9559 }
9560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009561 for (i = 0; i < params->num_bridge; i++) {
9562 if (params->bridge[i]) {
9563 ifindex = if_nametoindex(params->bridge[i]);
9564 if (ifindex)
9565 add_ifidx(drv, ifindex);
9566 if (ifindex == br_ifindex)
9567 br_added = 1;
9568 }
9569 }
9570 if (!br_added && br_ifindex &&
9571 (params->num_bridge == 0 || !params->bridge[0]))
9572 add_ifidx(drv, br_ifindex);
9573
9574 /* start listening for EAPOL on the default AP interface */
9575 add_ifidx(drv, drv->ifindex);
9576
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009577 if (params->num_bridge && params->bridge[0] &&
9578 i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)
9579 goto failed;
9580
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009581 drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
9582 if (drv->eapol_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009583 wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s",
9584 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009585 goto failed;
9586 }
9587
9588 if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
9589 {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009590 wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009591 goto failed;
9592 }
9593
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009594 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
9595 params->own_addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009596 goto failed;
9597
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009598 memcpy(bss->addr, params->own_addr, ETH_ALEN);
9599
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009600 return bss;
9601
9602failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009603 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009604 return NULL;
9605}
9606
9607
9608static void i802_deinit(void *priv)
9609{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009610 struct i802_bss *bss = priv;
9611 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009612}
9613
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009614
9615static enum nl80211_iftype wpa_driver_nl80211_if_type(
9616 enum wpa_driver_if_type type)
9617{
9618 switch (type) {
9619 case WPA_IF_STATION:
9620 return NL80211_IFTYPE_STATION;
9621 case WPA_IF_P2P_CLIENT:
9622 case WPA_IF_P2P_GROUP:
9623 return NL80211_IFTYPE_P2P_CLIENT;
9624 case WPA_IF_AP_VLAN:
9625 return NL80211_IFTYPE_AP_VLAN;
9626 case WPA_IF_AP_BSS:
9627 return NL80211_IFTYPE_AP;
9628 case WPA_IF_P2P_GO:
9629 return NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009630 case WPA_IF_P2P_DEVICE:
9631 return NL80211_IFTYPE_P2P_DEVICE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009632 }
9633 return -1;
9634}
9635
9636
9637#ifdef CONFIG_P2P
9638
9639static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr)
9640{
9641 struct wpa_driver_nl80211_data *drv;
9642 dl_list_for_each(drv, &global->interfaces,
9643 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009644 if (os_memcmp(addr, drv->first_bss->addr, ETH_ALEN) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009645 return 1;
9646 }
9647 return 0;
9648}
9649
9650
9651static int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv,
9652 u8 *new_addr)
9653{
9654 unsigned int idx;
9655
9656 if (!drv->global)
9657 return -1;
9658
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009659 os_memcpy(new_addr, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009660 for (idx = 0; idx < 64; idx++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009661 new_addr[0] = drv->first_bss->addr[0] | 0x02;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009662 new_addr[0] ^= idx << 2;
9663 if (!nl80211_addr_in_use(drv->global, new_addr))
9664 break;
9665 }
9666 if (idx == 64)
9667 return -1;
9668
9669 wpa_printf(MSG_DEBUG, "nl80211: Assigned new P2P Interface Address "
9670 MACSTR, MAC2STR(new_addr));
9671
9672 return 0;
9673}
9674
9675#endif /* CONFIG_P2P */
9676
9677
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009678struct wdev_info {
9679 u64 wdev_id;
9680 int wdev_id_set;
9681 u8 macaddr[ETH_ALEN];
9682};
9683
9684static int nl80211_wdev_handler(struct nl_msg *msg, void *arg)
9685{
9686 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9687 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9688 struct wdev_info *wi = arg;
9689
9690 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9691 genlmsg_attrlen(gnlh, 0), NULL);
9692 if (tb[NL80211_ATTR_WDEV]) {
9693 wi->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
9694 wi->wdev_id_set = 1;
9695 }
9696
9697 if (tb[NL80211_ATTR_MAC])
9698 os_memcpy(wi->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
9699 ETH_ALEN);
9700
9701 return NL_SKIP;
9702}
9703
9704
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009705static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
9706 const char *ifname, const u8 *addr,
9707 void *bss_ctx, void **drv_priv,
9708 char *force_ifname, u8 *if_addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009709 const char *bridge, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009710{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009711 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009712 struct i802_bss *bss = priv;
9713 struct wpa_driver_nl80211_data *drv = bss->drv;
9714 int ifidx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009715 int added = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009716
9717 if (addr)
9718 os_memcpy(if_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009719 nlmode = wpa_driver_nl80211_if_type(type);
9720 if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
9721 struct wdev_info p2pdev_info;
9722
9723 os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
9724 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
9725 0, nl80211_wdev_handler,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009726 &p2pdev_info, use_existing);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009727 if (!p2pdev_info.wdev_id_set || ifidx != 0) {
9728 wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s",
9729 ifname);
9730 return -1;
9731 }
9732
9733 drv->global->if_add_wdevid = p2pdev_info.wdev_id;
9734 drv->global->if_add_wdevid_set = p2pdev_info.wdev_id_set;
9735 if (!is_zero_ether_addr(p2pdev_info.macaddr))
9736 os_memcpy(if_addr, p2pdev_info.macaddr, ETH_ALEN);
9737 wpa_printf(MSG_DEBUG, "nl80211: New P2P Device interface %s (0x%llx) created",
9738 ifname,
9739 (long long unsigned int) p2pdev_info.wdev_id);
9740 } else {
9741 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009742 0, NULL, NULL, use_existing);
9743 if (use_existing && ifidx == -ENFILE) {
9744 added = 0;
9745 ifidx = if_nametoindex(ifname);
9746 } else if (ifidx < 0) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009747 return -1;
9748 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009749 }
9750
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009751 if (!addr) {
9752 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
9753 os_memcpy(if_addr, bss->addr, ETH_ALEN);
9754 else if (linux_get_ifhwaddr(drv->global->ioctl_sock,
9755 bss->ifname, if_addr) < 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009756 if (added)
9757 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009758 return -1;
9759 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009760 }
9761
9762#ifdef CONFIG_P2P
9763 if (!addr &&
9764 (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||
9765 type == WPA_IF_P2P_GO)) {
9766 /* Enforce unique P2P Interface Address */
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009767 u8 new_addr[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009768
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009769 if (linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009770 new_addr) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009771 nl80211_remove_iface(drv, ifidx);
9772 return -1;
9773 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009774 if (nl80211_addr_in_use(drv->global, new_addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009775 wpa_printf(MSG_DEBUG, "nl80211: Allocate new address "
9776 "for P2P group interface");
9777 if (nl80211_p2p_interface_addr(drv, new_addr) < 0) {
9778 nl80211_remove_iface(drv, ifidx);
9779 return -1;
9780 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009781 if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009782 new_addr) < 0) {
9783 nl80211_remove_iface(drv, ifidx);
9784 return -1;
9785 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009786 }
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009787 os_memcpy(if_addr, new_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009788 }
9789#endif /* CONFIG_P2P */
9790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009791 if (type == WPA_IF_AP_BSS) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009792 struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
9793 if (new_bss == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009794 if (added)
9795 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009796 return -1;
9797 }
9798
9799 if (bridge &&
9800 i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
9801 wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
9802 "interface %s to a bridge %s",
9803 ifname, bridge);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009804 if (added)
9805 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009806 os_free(new_bss);
9807 return -1;
9808 }
9809
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009810 if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
9811 {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009812 nl80211_remove_iface(drv, ifidx);
9813 os_free(new_bss);
9814 return -1;
9815 }
9816 os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009817 os_memcpy(new_bss->addr, if_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009818 new_bss->ifindex = ifidx;
9819 new_bss->drv = drv;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009820 new_bss->next = drv->first_bss->next;
9821 new_bss->freq = drv->first_bss->freq;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08009822 new_bss->ctx = bss_ctx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009823 new_bss->added_if = added;
9824 drv->first_bss->next = new_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009825 if (drv_priv)
9826 *drv_priv = new_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009827 nl80211_init_bss(new_bss);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009828
9829 /* Subscribe management frames for this WPA_IF_AP_BSS */
9830 if (nl80211_setup_ap(new_bss))
9831 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009832 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009833
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009834 if (drv->global)
9835 drv->global->if_add_ifindex = ifidx;
9836
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009837 return 0;
9838}
9839
9840
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009841static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009842 enum wpa_driver_if_type type,
9843 const char *ifname)
9844{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009845 struct wpa_driver_nl80211_data *drv = bss->drv;
9846 int ifindex = if_nametoindex(ifname);
9847
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009848 wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d",
9849 __func__, type, ifname, ifindex, bss->added_if);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08009850 if (ifindex > 0 && (bss->added_if || bss->ifindex != ifindex))
Dmitry Shmidt051af732013-10-22 13:52:46 -07009851 nl80211_remove_iface(drv, ifindex);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07009852
Dmitry Shmidtaa532512012-09-24 10:35:31 -07009853 if (type != WPA_IF_AP_BSS)
9854 return 0;
9855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009856 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009857 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
9858 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009859 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
9860 "interface %s from bridge %s: %s",
9861 bss->ifname, bss->brname, strerror(errno));
9862 }
9863 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009864 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009865 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
9866 "bridge %s: %s",
9867 bss->brname, strerror(errno));
9868 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009869
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009870 if (bss != drv->first_bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009871 struct i802_bss *tbss;
9872
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009873 wpa_printf(MSG_DEBUG, "nl80211: Not the first BSS - remove it");
9874 for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009875 if (tbss->next == bss) {
9876 tbss->next = bss->next;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009877 /* Unsubscribe management frames */
9878 nl80211_teardown_ap(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009879 nl80211_destroy_bss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009880 os_free(bss);
9881 bss = NULL;
9882 break;
9883 }
9884 }
9885 if (bss)
9886 wpa_printf(MSG_INFO, "nl80211: %s - could not find "
9887 "BSS %p in the list", __func__, bss);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009888 } else {
9889 wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
9890 nl80211_teardown_ap(bss);
9891 if (!bss->added_if && !drv->first_bss->next)
9892 wpa_driver_nl80211_del_beacon(drv);
9893 nl80211_destroy_bss(bss);
9894 if (!bss->added_if)
9895 i802_set_iface_flags(bss, 0);
9896 if (drv->first_bss->next) {
9897 drv->first_bss = drv->first_bss->next;
9898 drv->ctx = drv->first_bss->ctx;
9899 os_free(bss);
9900 } else {
9901 wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
9902 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009903 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009904
9905 return 0;
9906}
9907
9908
9909static int cookie_handler(struct nl_msg *msg, void *arg)
9910{
9911 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9912 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9913 u64 *cookie = arg;
9914 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9915 genlmsg_attrlen(gnlh, 0), NULL);
9916 if (tb[NL80211_ATTR_COOKIE])
9917 *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
9918 return NL_SKIP;
9919}
9920
9921
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009922static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009923 unsigned int freq, unsigned int wait,
9924 const u8 *buf, size_t buf_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009925 u64 *cookie_out, int no_cck, int no_ack,
9926 int offchanok)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009927{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009928 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009929 struct nl_msg *msg;
9930 u64 cookie;
9931 int ret = -1;
9932
9933 msg = nlmsg_alloc();
9934 if (!msg)
9935 return -1;
9936
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07009937 wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
Dmitry Shmidt04949592012-07-19 12:16:46 -07009938 "no_ack=%d offchanok=%d",
9939 freq, wait, no_cck, no_ack, offchanok);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009940 wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009941 nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009942
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009943 if (nl80211_set_iface_id(msg, bss) < 0)
9944 goto nla_put_failure;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009945 if (freq)
9946 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009947 if (wait)
9948 NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08009949 if (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
9950 drv->test_use_roc_tx))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009951 NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
9952 if (no_cck)
9953 NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
9954 if (no_ack)
9955 NLA_PUT_FLAG(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK);
9956
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009957 NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);
9958
9959 cookie = 0;
9960 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
9961 msg = NULL;
9962 if (ret) {
9963 wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009964 "(%s) (freq=%u wait=%u)", ret, strerror(-ret),
9965 freq, wait);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009966 goto nla_put_failure;
9967 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07009968 wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009969 "cookie 0x%llx", no_ack ? " (no ACK)" : "",
9970 (long long unsigned int) cookie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009971
9972 if (cookie_out)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009973 *cookie_out = no_ack ? (u64) -1 : cookie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009974
9975nla_put_failure:
9976 nlmsg_free(msg);
9977 return ret;
9978}
9979
9980
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009981static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
9982 unsigned int freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009983 unsigned int wait_time,
9984 const u8 *dst, const u8 *src,
9985 const u8 *bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009986 const u8 *data, size_t data_len,
9987 int no_cck)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009988{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009989 struct wpa_driver_nl80211_data *drv = bss->drv;
9990 int ret = -1;
9991 u8 *buf;
9992 struct ieee80211_hdr *hdr;
9993
9994 wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009995 "freq=%u MHz wait=%d ms no_cck=%d)",
9996 drv->ifindex, freq, wait_time, no_cck);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009997
9998 buf = os_zalloc(24 + data_len);
9999 if (buf == NULL)
10000 return ret;
10001 os_memcpy(buf + 24, data, data_len);
10002 hdr = (struct ieee80211_hdr *) buf;
10003 hdr->frame_control =
10004 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);
10005 os_memcpy(hdr->addr1, dst, ETH_ALEN);
10006 os_memcpy(hdr->addr2, src, ETH_ALEN);
10007 os_memcpy(hdr->addr3, bssid, ETH_ALEN);
10008
Dmitry Shmidt56052862013-10-04 10:23:25 -070010009 if (is_ap_interface(drv->nlmode) &&
10010 (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
10011 (int) freq == bss->freq || drv->device_ap_sme ||
10012 !drv->use_monitor))
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010013 ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
10014 0, freq, no_cck, 1,
10015 wait_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010016 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010017 ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010018 24 + data_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010019 &drv->send_action_cookie,
10020 no_cck, 0, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010021
10022 os_free(buf);
10023 return ret;
10024}
10025
10026
10027static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
10028{
10029 struct i802_bss *bss = priv;
10030 struct wpa_driver_nl80211_data *drv = bss->drv;
10031 struct nl_msg *msg;
10032 int ret;
10033
10034 msg = nlmsg_alloc();
10035 if (!msg)
10036 return;
10037
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -080010038 wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx",
10039 (long long unsigned int) drv->send_action_cookie);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010040 nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010041
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010042 if (nl80211_set_iface_id(msg, bss) < 0)
10043 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010044 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);
10045
10046 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
10047 msg = NULL;
10048 if (ret)
10049 wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
10050 "(%s)", ret, strerror(-ret));
10051
10052 nla_put_failure:
10053 nlmsg_free(msg);
10054}
10055
10056
10057static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
10058 unsigned int duration)
10059{
10060 struct i802_bss *bss = priv;
10061 struct wpa_driver_nl80211_data *drv = bss->drv;
10062 struct nl_msg *msg;
10063 int ret;
10064 u64 cookie;
10065
10066 msg = nlmsg_alloc();
10067 if (!msg)
10068 return -1;
10069
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010070 nl80211_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010071
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010072 if (nl80211_set_iface_id(msg, bss) < 0)
10073 goto nla_put_failure;
10074
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010075 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
10076 NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);
10077
10078 cookie = 0;
10079 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010080 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010081 if (ret == 0) {
10082 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
10083 "0x%llx for freq=%u MHz duration=%u",
10084 (long long unsigned int) cookie, freq, duration);
10085 drv->remain_on_chan_cookie = cookie;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010086 drv->pending_remain_on_chan = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010087 return 0;
10088 }
10089 wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel "
10090 "(freq=%d duration=%u): %d (%s)",
10091 freq, duration, ret, strerror(-ret));
10092nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010093 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010094 return -1;
10095}
10096
10097
10098static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
10099{
10100 struct i802_bss *bss = priv;
10101 struct wpa_driver_nl80211_data *drv = bss->drv;
10102 struct nl_msg *msg;
10103 int ret;
10104
10105 if (!drv->pending_remain_on_chan) {
10106 wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel "
10107 "to cancel");
10108 return -1;
10109 }
10110
10111 wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie "
10112 "0x%llx",
10113 (long long unsigned int) drv->remain_on_chan_cookie);
10114
10115 msg = nlmsg_alloc();
10116 if (!msg)
10117 return -1;
10118
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010119 nl80211_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010120
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010121 if (nl80211_set_iface_id(msg, bss) < 0)
10122 goto nla_put_failure;
10123
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010124 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);
10125
10126 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010127 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010128 if (ret == 0)
10129 return 0;
10130 wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
10131 "%d (%s)", ret, strerror(-ret));
10132nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010133 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010134 return -1;
10135}
10136
10137
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010138static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010139{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010140 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070010141
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010142 if (!report) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010143 if (bss->nl_preq && drv->device_ap_sme &&
10144 is_ap_interface(drv->nlmode)) {
10145 /*
10146 * Do not disable Probe Request reporting that was
10147 * enabled in nl80211_setup_ap().
10148 */
10149 wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of "
10150 "Probe Request reporting nl_preq=%p while "
10151 "in AP mode", bss->nl_preq);
10152 } else if (bss->nl_preq) {
10153 wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
10154 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010155 nl80211_destroy_eloop_handle(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010156 }
10157 return 0;
10158 }
10159
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010160 if (bss->nl_preq) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010161 wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010162 "already on! nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010163 return 0;
10164 }
10165
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010166 bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq");
10167 if (bss->nl_preq == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010168 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010169 wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request "
10170 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010171
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010172 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010173 (WLAN_FC_TYPE_MGMT << 2) |
10174 (WLAN_FC_STYPE_PROBE_REQ << 4),
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010175 NULL, 0) < 0)
10176 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -070010177
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010178 nl80211_register_eloop_read(&bss->nl_preq,
10179 wpa_driver_nl80211_event_receive,
10180 bss->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010181
10182 return 0;
10183
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010184 out_err:
10185 nl_destroy_handles(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010186 return -1;
10187}
10188
10189
10190static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
10191 int ifindex, int disabled)
10192{
10193 struct nl_msg *msg;
10194 struct nlattr *bands, *band;
10195 int ret;
10196
10197 msg = nlmsg_alloc();
10198 if (!msg)
10199 return -1;
10200
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010201 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_TX_BITRATE_MASK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010202 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
10203
10204 bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
10205 if (!bands)
10206 goto nla_put_failure;
10207
10208 /*
10209 * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything
10210 * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS
10211 * rates. All 5 GHz rates are left enabled.
10212 */
10213 band = nla_nest_start(msg, NL80211_BAND_2GHZ);
10214 if (!band)
10215 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010216 if (disabled) {
10217 NLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,
10218 "\x0c\x12\x18\x24\x30\x48\x60\x6c");
10219 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010220 nla_nest_end(msg, band);
10221
10222 nla_nest_end(msg, bands);
10223
10224 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
10225 msg = NULL;
10226 if (ret) {
10227 wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
10228 "(%s)", ret, strerror(-ret));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010229 } else
10230 drv->disabled_11b_rates = disabled;
10231
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010232 return ret;
10233
10234nla_put_failure:
10235 nlmsg_free(msg);
10236 return -1;
10237}
10238
10239
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010240static int wpa_driver_nl80211_deinit_ap(void *priv)
10241{
10242 struct i802_bss *bss = priv;
10243 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010244 if (!is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010245 return -1;
10246 wpa_driver_nl80211_del_beacon(drv);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070010247
10248 /*
10249 * If the P2P GO interface was dynamically added, then it is
10250 * possible that the interface change to station is not possible.
10251 */
10252 if (drv->nlmode == NL80211_IFTYPE_P2P_GO && bss->if_dynamic)
10253 return 0;
10254
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010255 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010256}
10257
10258
Dmitry Shmidtea69e842013-05-13 14:52:28 -070010259static int wpa_driver_nl80211_stop_ap(void *priv)
10260{
10261 struct i802_bss *bss = priv;
10262 struct wpa_driver_nl80211_data *drv = bss->drv;
10263 if (!is_ap_interface(drv->nlmode))
10264 return -1;
10265 wpa_driver_nl80211_del_beacon(drv);
10266 bss->beacon_set = 0;
10267 return 0;
10268}
10269
10270
Dmitry Shmidt04949592012-07-19 12:16:46 -070010271static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
10272{
10273 struct i802_bss *bss = priv;
10274 struct wpa_driver_nl80211_data *drv = bss->drv;
10275 if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)
10276 return -1;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070010277
10278 /*
10279 * If the P2P Client interface was dynamically added, then it is
10280 * possible that the interface change to station is not possible.
10281 */
10282 if (bss->if_dynamic)
10283 return 0;
10284
Dmitry Shmidt04949592012-07-19 12:16:46 -070010285 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
10286}
10287
10288
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010289static void wpa_driver_nl80211_resume(void *priv)
10290{
10291 struct i802_bss *bss = priv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010292
10293 if (i802_set_iface_flags(bss, 1))
10294 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010295}
10296
10297
10298static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
10299 const u8 *ies, size_t ies_len)
10300{
10301 struct i802_bss *bss = priv;
10302 struct wpa_driver_nl80211_data *drv = bss->drv;
10303 int ret;
10304 u8 *data, *pos;
10305 size_t data_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010306 const u8 *own_addr = bss->addr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010307
10308 if (action != 1) {
10309 wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action "
10310 "action %d", action);
10311 return -1;
10312 }
10313
10314 /*
10315 * Action frame payload:
10316 * Category[1] = 6 (Fast BSS Transition)
10317 * Action[1] = 1 (Fast BSS Transition Request)
10318 * STA Address
10319 * Target AP Address
10320 * FT IEs
10321 */
10322
10323 data_len = 2 + 2 * ETH_ALEN + ies_len;
10324 data = os_malloc(data_len);
10325 if (data == NULL)
10326 return -1;
10327 pos = data;
10328 *pos++ = 0x06; /* FT Action category */
10329 *pos++ = action;
10330 os_memcpy(pos, own_addr, ETH_ALEN);
10331 pos += ETH_ALEN;
10332 os_memcpy(pos, target_ap, ETH_ALEN);
10333 pos += ETH_ALEN;
10334 os_memcpy(pos, ies, ies_len);
10335
10336 ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0,
10337 drv->bssid, own_addr, drv->bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010338 data, data_len, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010339 os_free(data);
10340
10341 return ret;
10342}
10343
10344
10345static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
10346{
10347 struct i802_bss *bss = priv;
10348 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010349 struct nl_msg *msg;
10350 struct nlattr *cqm;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010351 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010352
10353 wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
10354 "hysteresis=%d", threshold, hysteresis);
10355
10356 msg = nlmsg_alloc();
10357 if (!msg)
10358 return -1;
10359
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010360 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_CQM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010361
10362 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10363
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010364 cqm = nla_nest_start(msg, NL80211_ATTR_CQM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010365 if (cqm == NULL)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010366 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010367
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010368 NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
10369 NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);
10370 nla_nest_end(msg, cqm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010371
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010372 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010373 msg = NULL;
10374
10375nla_put_failure:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010376 nlmsg_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010377 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010378}
10379
10380
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010381static int get_channel_width(struct nl_msg *msg, void *arg)
10382{
10383 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10384 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10385 struct wpa_signal_info *sig_change = arg;
10386
10387 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10388 genlmsg_attrlen(gnlh, 0), NULL);
10389
10390 sig_change->center_frq1 = -1;
10391 sig_change->center_frq2 = -1;
10392 sig_change->chanwidth = CHAN_WIDTH_UNKNOWN;
10393
10394 if (tb[NL80211_ATTR_CHANNEL_WIDTH]) {
10395 sig_change->chanwidth = convert2width(
10396 nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
10397 if (tb[NL80211_ATTR_CENTER_FREQ1])
10398 sig_change->center_frq1 =
10399 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
10400 if (tb[NL80211_ATTR_CENTER_FREQ2])
10401 sig_change->center_frq2 =
10402 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
10403 }
10404
10405 return NL_SKIP;
10406}
10407
10408
10409static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
10410 struct wpa_signal_info *sig)
10411{
10412 struct nl_msg *msg;
10413
10414 msg = nlmsg_alloc();
10415 if (!msg)
10416 return -ENOMEM;
10417
10418 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_INTERFACE);
10419 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
10420
10421 return send_and_recv_msgs(drv, msg, get_channel_width, sig);
10422
10423nla_put_failure:
10424 nlmsg_free(msg);
10425 return -ENOBUFS;
10426}
10427
10428
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010429static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
10430{
10431 struct i802_bss *bss = priv;
10432 struct wpa_driver_nl80211_data *drv = bss->drv;
10433 int res;
10434
10435 os_memset(si, 0, sizeof(*si));
10436 res = nl80211_get_link_signal(drv, si);
10437 if (res != 0)
10438 return res;
10439
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010440 res = nl80211_get_channel_width(drv, si);
10441 if (res != 0)
10442 return res;
10443
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010444 return nl80211_get_link_noise(drv, si);
10445}
10446
10447
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010448static int wpa_driver_nl80211_shared_freq(void *priv)
10449{
10450 struct i802_bss *bss = priv;
10451 struct wpa_driver_nl80211_data *drv = bss->drv;
10452 struct wpa_driver_nl80211_data *driver;
10453 int freq = 0;
10454
10455 /*
10456 * If the same PHY is in connected state with some other interface,
10457 * then retrieve the assoc freq.
10458 */
10459 wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s",
10460 drv->phyname);
10461
10462 dl_list_for_each(driver, &drv->global->interfaces,
10463 struct wpa_driver_nl80211_data, list) {
10464 if (drv == driver ||
10465 os_strcmp(drv->phyname, driver->phyname) != 0 ||
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010466 !driver->associated)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010467 continue;
10468
10469 wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
10470 MACSTR,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010471 driver->phyname, driver->first_bss->ifname,
10472 MAC2STR(driver->first_bss->addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -070010473 if (is_ap_interface(driver->nlmode))
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010474 freq = driver->first_bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010475 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010476 freq = nl80211_get_assoc_freq(driver);
10477 wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
10478 drv->phyname, freq);
10479 }
10480
10481 if (!freq)
10482 wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
10483 "PHY (%s) in associated state", drv->phyname);
10484
10485 return freq;
10486}
10487
10488
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010489static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
10490 int encrypt)
10491{
10492 struct i802_bss *bss = priv;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010493 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
10494 0, 0, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010495}
10496
10497
10498static int nl80211_set_param(void *priv, const char *param)
10499{
10500 wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
10501 if (param == NULL)
10502 return 0;
10503
10504#ifdef CONFIG_P2P
10505 if (os_strstr(param, "use_p2p_group_interface=1")) {
10506 struct i802_bss *bss = priv;
10507 struct wpa_driver_nl80211_data *drv = bss->drv;
10508
10509 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
10510 "interface");
10511 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
10512 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
10513 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010514
10515 if (os_strstr(param, "p2p_device=1")) {
10516 struct i802_bss *bss = priv;
10517 struct wpa_driver_nl80211_data *drv = bss->drv;
10518 drv->allow_p2p_device = 1;
10519 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010520#endif /* CONFIG_P2P */
10521
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080010522 if (os_strstr(param, "use_monitor=1")) {
10523 struct i802_bss *bss = priv;
10524 struct wpa_driver_nl80211_data *drv = bss->drv;
10525 drv->use_monitor = 1;
10526 }
10527
10528 if (os_strstr(param, "force_connect_cmd=1")) {
10529 struct i802_bss *bss = priv;
10530 struct wpa_driver_nl80211_data *drv = bss->drv;
10531 drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
10532 }
10533
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -080010534 if (os_strstr(param, "no_offchannel_tx=1")) {
10535 struct i802_bss *bss = priv;
10536 struct wpa_driver_nl80211_data *drv = bss->drv;
10537 drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
10538 drv->test_use_roc_tx = 1;
10539 }
10540
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010541 return 0;
10542}
10543
10544
10545static void * nl80211_global_init(void)
10546{
10547 struct nl80211_global *global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010548 struct netlink_config *cfg;
10549
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010550 global = os_zalloc(sizeof(*global));
10551 if (global == NULL)
10552 return NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010553 global->ioctl_sock = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010554 dl_list_init(&global->interfaces);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010555 global->if_add_ifindex = -1;
10556
10557 cfg = os_zalloc(sizeof(*cfg));
10558 if (cfg == NULL)
10559 goto err;
10560
10561 cfg->ctx = global;
10562 cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
10563 cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
10564 global->netlink = netlink_init(cfg);
10565 if (global->netlink == NULL) {
10566 os_free(cfg);
10567 goto err;
10568 }
10569
10570 if (wpa_driver_nl80211_init_nl_global(global) < 0)
10571 goto err;
10572
10573 global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
10574 if (global->ioctl_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010575 wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",
10576 strerror(errno));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010577 goto err;
10578 }
10579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010580 return global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010581
10582err:
10583 nl80211_global_deinit(global);
10584 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010585}
10586
10587
10588static void nl80211_global_deinit(void *priv)
10589{
10590 struct nl80211_global *global = priv;
10591 if (global == NULL)
10592 return;
10593 if (!dl_list_empty(&global->interfaces)) {
10594 wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at "
10595 "nl80211_global_deinit",
10596 dl_list_len(&global->interfaces));
10597 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010598
10599 if (global->netlink)
10600 netlink_deinit(global->netlink);
10601
10602 nl_destroy_handles(&global->nl);
10603
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010604 if (global->nl_event)
10605 nl80211_destroy_eloop_handle(&global->nl_event);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010606
10607 nl_cb_put(global->nl_cb);
10608
10609 if (global->ioctl_sock >= 0)
10610 close(global->ioctl_sock);
10611
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010612 os_free(global);
10613}
10614
10615
10616static const char * nl80211_get_radio_name(void *priv)
10617{
10618 struct i802_bss *bss = priv;
10619 struct wpa_driver_nl80211_data *drv = bss->drv;
10620 return drv->phyname;
10621}
10622
10623
Jouni Malinen75ecf522011-06-27 15:19:46 -070010624static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,
10625 const u8 *pmkid)
10626{
10627 struct nl_msg *msg;
10628
10629 msg = nlmsg_alloc();
10630 if (!msg)
10631 return -ENOMEM;
10632
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010633 nl80211_cmd(bss->drv, msg, 0, cmd);
Jouni Malinen75ecf522011-06-27 15:19:46 -070010634
10635 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
10636 if (pmkid)
10637 NLA_PUT(msg, NL80211_ATTR_PMKID, 16, pmkid);
10638 if (bssid)
10639 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
10640
10641 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
10642 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010643 nlmsg_free(msg);
Jouni Malinen75ecf522011-06-27 15:19:46 -070010644 return -ENOBUFS;
10645}
10646
10647
10648static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
10649{
10650 struct i802_bss *bss = priv;
10651 wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR, MAC2STR(bssid));
10652 return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);
10653}
10654
10655
10656static int nl80211_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
10657{
10658 struct i802_bss *bss = priv;
10659 wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR,
10660 MAC2STR(bssid));
10661 return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);
10662}
10663
10664
10665static int nl80211_flush_pmkid(void *priv)
10666{
10667 struct i802_bss *bss = priv;
10668 wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs");
10669 return nl80211_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);
10670}
10671
10672
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070010673static void clean_survey_results(struct survey_results *survey_results)
10674{
10675 struct freq_survey *survey, *tmp;
10676
10677 if (dl_list_empty(&survey_results->survey_list))
10678 return;
10679
10680 dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
10681 struct freq_survey, list) {
10682 dl_list_del(&survey->list);
10683 os_free(survey);
10684 }
10685}
10686
10687
10688static void add_survey(struct nlattr **sinfo, u32 ifidx,
10689 struct dl_list *survey_list)
10690{
10691 struct freq_survey *survey;
10692
10693 survey = os_zalloc(sizeof(struct freq_survey));
10694 if (!survey)
10695 return;
10696
10697 survey->ifidx = ifidx;
10698 survey->freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10699 survey->filled = 0;
10700
10701 if (sinfo[NL80211_SURVEY_INFO_NOISE]) {
10702 survey->nf = (int8_t)
10703 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10704 survey->filled |= SURVEY_HAS_NF;
10705 }
10706
10707 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]) {
10708 survey->channel_time =
10709 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]);
10710 survey->filled |= SURVEY_HAS_CHAN_TIME;
10711 }
10712
10713 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]) {
10714 survey->channel_time_busy =
10715 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]);
10716 survey->filled |= SURVEY_HAS_CHAN_TIME_BUSY;
10717 }
10718
10719 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]) {
10720 survey->channel_time_rx =
10721 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]);
10722 survey->filled |= SURVEY_HAS_CHAN_TIME_RX;
10723 }
10724
10725 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]) {
10726 survey->channel_time_tx =
10727 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]);
10728 survey->filled |= SURVEY_HAS_CHAN_TIME_TX;
10729 }
10730
10731 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)",
10732 survey->freq,
10733 survey->nf,
10734 (unsigned long int) survey->channel_time,
10735 (unsigned long int) survey->channel_time_busy,
10736 (unsigned long int) survey->channel_time_tx,
10737 (unsigned long int) survey->channel_time_rx,
10738 survey->filled);
10739
10740 dl_list_add_tail(survey_list, &survey->list);
10741}
10742
10743
10744static int check_survey_ok(struct nlattr **sinfo, u32 surveyed_freq,
10745 unsigned int freq_filter)
10746{
10747 if (!freq_filter)
10748 return 1;
10749
10750 return freq_filter == surveyed_freq;
10751}
10752
10753
10754static int survey_handler(struct nl_msg *msg, void *arg)
10755{
10756 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10757 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10758 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10759 struct survey_results *survey_results;
10760 u32 surveyed_freq = 0;
10761 u32 ifidx;
10762
10763 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10764 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
10765 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
10766 };
10767
10768 survey_results = (struct survey_results *) arg;
10769
10770 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10771 genlmsg_attrlen(gnlh, 0), NULL);
10772
Dmitry Shmidt97672262014-02-03 13:02:54 -080010773 if (!tb[NL80211_ATTR_IFINDEX])
10774 return NL_SKIP;
10775
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070010776 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
10777
10778 if (!tb[NL80211_ATTR_SURVEY_INFO])
10779 return NL_SKIP;
10780
10781 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
10782 tb[NL80211_ATTR_SURVEY_INFO],
10783 survey_policy))
10784 return NL_SKIP;
10785
10786 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) {
10787 wpa_printf(MSG_ERROR, "nl80211: Invalid survey data");
10788 return NL_SKIP;
10789 }
10790
10791 surveyed_freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10792
10793 if (!check_survey_ok(sinfo, surveyed_freq,
10794 survey_results->freq_filter))
10795 return NL_SKIP;
10796
10797 if (survey_results->freq_filter &&
10798 survey_results->freq_filter != surveyed_freq) {
10799 wpa_printf(MSG_EXCESSIVE, "nl80211: Ignoring survey data for freq %d MHz",
10800 surveyed_freq);
10801 return NL_SKIP;
10802 }
10803
10804 add_survey(sinfo, ifidx, &survey_results->survey_list);
10805
10806 return NL_SKIP;
10807}
10808
10809
10810static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
10811{
10812 struct i802_bss *bss = priv;
10813 struct wpa_driver_nl80211_data *drv = bss->drv;
10814 struct nl_msg *msg;
10815 int err = -ENOBUFS;
10816 union wpa_event_data data;
10817 struct survey_results *survey_results;
10818
10819 os_memset(&data, 0, sizeof(data));
10820 survey_results = &data.survey_results;
10821
10822 dl_list_init(&survey_results->survey_list);
10823
10824 msg = nlmsg_alloc();
10825 if (!msg)
10826 goto nla_put_failure;
10827
10828 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
10829
10830 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
10831
10832 if (freq)
10833 data.survey_results.freq_filter = freq;
10834
10835 do {
10836 wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data");
10837 err = send_and_recv_msgs(drv, msg, survey_handler,
10838 survey_results);
10839 } while (err > 0);
10840
10841 if (err) {
10842 wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
10843 goto out_clean;
10844 }
10845
10846 wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data);
10847
10848out_clean:
10849 clean_survey_results(survey_results);
10850nla_put_failure:
10851 return err;
10852}
10853
10854
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010855static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
10856 const u8 *replay_ctr)
10857{
10858 struct i802_bss *bss = priv;
10859 struct wpa_driver_nl80211_data *drv = bss->drv;
10860 struct nlattr *replay_nested;
10861 struct nl_msg *msg;
10862
10863 msg = nlmsg_alloc();
10864 if (!msg)
10865 return;
10866
10867 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
10868
10869 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10870
10871 replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
10872 if (!replay_nested)
10873 goto nla_put_failure;
10874
10875 NLA_PUT(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek);
10876 NLA_PUT(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck);
10877 NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
10878 replay_ctr);
10879
10880 nla_nest_end(msg, replay_nested);
10881
10882 send_and_recv_msgs(drv, msg, NULL, NULL);
10883 return;
10884 nla_put_failure:
10885 nlmsg_free(msg);
10886}
10887
10888
10889static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
10890 const u8 *addr, int qos)
10891{
10892 /* send data frame to poll STA and check whether
10893 * this frame is ACKed */
10894 struct {
10895 struct ieee80211_hdr hdr;
10896 u16 qos_ctl;
10897 } STRUCT_PACKED nulldata;
10898 size_t size;
10899
10900 /* Send data frame to poll STA and check whether this frame is ACKed */
10901
10902 os_memset(&nulldata, 0, sizeof(nulldata));
10903
10904 if (qos) {
10905 nulldata.hdr.frame_control =
10906 IEEE80211_FC(WLAN_FC_TYPE_DATA,
10907 WLAN_FC_STYPE_QOS_NULL);
10908 size = sizeof(nulldata);
10909 } else {
10910 nulldata.hdr.frame_control =
10911 IEEE80211_FC(WLAN_FC_TYPE_DATA,
10912 WLAN_FC_STYPE_NULLFUNC);
10913 size = sizeof(struct ieee80211_hdr);
10914 }
10915
10916 nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
10917 os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
10918 os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
10919 os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
10920
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010921 if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
10922 0, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010923 wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
10924 "send poll frame");
10925}
10926
10927static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
10928 int qos)
10929{
10930 struct i802_bss *bss = priv;
10931 struct wpa_driver_nl80211_data *drv = bss->drv;
10932 struct nl_msg *msg;
10933
10934 if (!drv->poll_command_supported) {
10935 nl80211_send_null_frame(bss, own_addr, addr, qos);
10936 return;
10937 }
10938
10939 msg = nlmsg_alloc();
10940 if (!msg)
10941 return;
10942
10943 nl80211_cmd(drv, msg, 0, NL80211_CMD_PROBE_CLIENT);
10944
10945 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10946 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
10947
10948 send_and_recv_msgs(drv, msg, NULL, NULL);
10949 return;
10950 nla_put_failure:
10951 nlmsg_free(msg);
10952}
10953
10954
10955static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
10956{
10957 struct nl_msg *msg;
10958
10959 msg = nlmsg_alloc();
10960 if (!msg)
10961 return -ENOMEM;
10962
10963 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_SET_POWER_SAVE);
10964 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10965 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE,
10966 enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);
10967 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
10968nla_put_failure:
10969 nlmsg_free(msg);
10970 return -ENOBUFS;
10971}
10972
10973
10974static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,
10975 int ctwindow)
10976{
10977 struct i802_bss *bss = priv;
10978
10979 wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d "
10980 "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow);
10981
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080010982 if (opp_ps != -1 || ctwindow != -1) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010983#ifdef ANDROID_P2P
10984 wpa_driver_set_p2p_ps(priv, legacy_ps, opp_ps, ctwindow);
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080010985#else /* ANDROID_P2P */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010986 return -1; /* Not yet supported */
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080010987#endif /* ANDROID_P2P */
10988 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010989
10990 if (legacy_ps == -1)
10991 return 0;
10992 if (legacy_ps != 0 && legacy_ps != 1)
10993 return -1; /* Not yet supported */
10994
10995 return nl80211_set_power_save(bss, legacy_ps);
10996}
10997
10998
Dmitry Shmidt051af732013-10-22 13:52:46 -070010999static int nl80211_start_radar_detection(void *priv,
11000 struct hostapd_freq_params *freq)
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011001{
11002 struct i802_bss *bss = priv;
11003 struct wpa_driver_nl80211_data *drv = bss->drv;
11004 struct nl_msg *msg;
11005 int ret;
11006
Dmitry Shmidt051af732013-10-22 13:52:46 -070011007 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)",
11008 freq->freq, freq->ht_enabled, freq->vht_enabled,
11009 freq->bandwidth, freq->center_freq1, freq->center_freq2);
11010
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011011 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
11012 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar "
11013 "detection");
11014 return -1;
11015 }
11016
11017 msg = nlmsg_alloc();
11018 if (!msg)
11019 return -1;
11020
11021 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_RADAR_DETECT);
11022 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
Dmitry Shmidt051af732013-10-22 13:52:46 -070011023 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq);
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011024
Dmitry Shmidt051af732013-10-22 13:52:46 -070011025 if (freq->vht_enabled) {
11026 switch (freq->bandwidth) {
11027 case 20:
11028 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11029 NL80211_CHAN_WIDTH_20);
11030 break;
11031 case 40:
11032 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11033 NL80211_CHAN_WIDTH_40);
11034 break;
11035 case 80:
11036 if (freq->center_freq2)
11037 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11038 NL80211_CHAN_WIDTH_80P80);
11039 else
11040 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11041 NL80211_CHAN_WIDTH_80);
11042 break;
11043 case 160:
11044 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
11045 NL80211_CHAN_WIDTH_160);
11046 break;
11047 default:
11048 return -1;
11049 }
11050 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1);
11051 if (freq->center_freq2)
11052 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2,
11053 freq->center_freq2);
11054 } else if (freq->ht_enabled) {
11055 switch (freq->sec_channel_offset) {
11056 case -1:
11057 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
11058 NL80211_CHAN_HT40MINUS);
11059 break;
11060 case 1:
11061 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
11062 NL80211_CHAN_HT40PLUS);
11063 break;
11064 default:
11065 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
11066 NL80211_CHAN_HT20);
11067 break;
11068 }
11069 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011070
11071 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
11072 if (ret == 0)
11073 return 0;
11074 wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
11075 "%d (%s)", ret, strerror(-ret));
11076nla_put_failure:
11077 return -1;
11078}
11079
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011080#ifdef CONFIG_TDLS
11081
11082static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
11083 u8 dialog_token, u16 status_code,
11084 const u8 *buf, size_t len)
11085{
11086 struct i802_bss *bss = priv;
11087 struct wpa_driver_nl80211_data *drv = bss->drv;
11088 struct nl_msg *msg;
11089
11090 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
11091 return -EOPNOTSUPP;
11092
11093 if (!dst)
11094 return -EINVAL;
11095
11096 msg = nlmsg_alloc();
11097 if (!msg)
11098 return -ENOMEM;
11099
11100 nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_MGMT);
11101 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11102 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
11103 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code);
11104 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token);
11105 NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code);
11106 NLA_PUT(msg, NL80211_ATTR_IE, len, buf);
11107
11108 return send_and_recv_msgs(drv, msg, NULL, NULL);
11109
11110nla_put_failure:
11111 nlmsg_free(msg);
11112 return -ENOBUFS;
11113}
11114
11115
11116static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
11117{
11118 struct i802_bss *bss = priv;
11119 struct wpa_driver_nl80211_data *drv = bss->drv;
11120 struct nl_msg *msg;
11121 enum nl80211_tdls_operation nl80211_oper;
11122
11123 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
11124 return -EOPNOTSUPP;
11125
11126 switch (oper) {
11127 case TDLS_DISCOVERY_REQ:
11128 nl80211_oper = NL80211_TDLS_DISCOVERY_REQ;
11129 break;
11130 case TDLS_SETUP:
11131 nl80211_oper = NL80211_TDLS_SETUP;
11132 break;
11133 case TDLS_TEARDOWN:
11134 nl80211_oper = NL80211_TDLS_TEARDOWN;
11135 break;
11136 case TDLS_ENABLE_LINK:
11137 nl80211_oper = NL80211_TDLS_ENABLE_LINK;
11138 break;
11139 case TDLS_DISABLE_LINK:
11140 nl80211_oper = NL80211_TDLS_DISABLE_LINK;
11141 break;
11142 case TDLS_ENABLE:
11143 return 0;
11144 case TDLS_DISABLE:
11145 return 0;
11146 default:
11147 return -EINVAL;
11148 }
11149
11150 msg = nlmsg_alloc();
11151 if (!msg)
11152 return -ENOMEM;
11153
11154 nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_OPER);
11155 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper);
11156 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11157 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer);
11158
11159 return send_and_recv_msgs(drv, msg, NULL, NULL);
11160
11161nla_put_failure:
11162 nlmsg_free(msg);
11163 return -ENOBUFS;
11164}
11165
11166#endif /* CONFIG TDLS */
11167
11168
11169#ifdef ANDROID
11170
11171typedef struct android_wifi_priv_cmd {
11172 char *buf;
11173 int used_len;
11174 int total_len;
11175} android_wifi_priv_cmd;
11176
11177static int drv_errors = 0;
11178
11179static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
11180{
11181 drv_errors++;
11182 if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
11183 drv_errors = 0;
11184 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
11185 }
11186}
11187
11188
11189static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
11190{
11191 struct wpa_driver_nl80211_data *drv = bss->drv;
11192 struct ifreq ifr;
11193 android_wifi_priv_cmd priv_cmd;
11194 char buf[MAX_DRV_CMD_SIZE];
11195 int ret;
11196
11197 os_memset(&ifr, 0, sizeof(ifr));
11198 os_memset(&priv_cmd, 0, sizeof(priv_cmd));
11199 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
11200
11201 os_memset(buf, 0, sizeof(buf));
11202 os_strlcpy(buf, cmd, sizeof(buf));
11203
11204 priv_cmd.buf = buf;
11205 priv_cmd.used_len = sizeof(buf);
11206 priv_cmd.total_len = sizeof(buf);
11207 ifr.ifr_data = &priv_cmd;
11208
11209 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
11210 if (ret < 0) {
11211 wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
11212 __func__);
11213 wpa_driver_send_hang_msg(drv);
11214 return ret;
11215 }
11216
11217 drv_errors = 0;
11218 return 0;
11219}
11220
11221
11222static int android_pno_start(struct i802_bss *bss,
11223 struct wpa_driver_scan_params *params)
11224{
11225 struct wpa_driver_nl80211_data *drv = bss->drv;
11226 struct ifreq ifr;
11227 android_wifi_priv_cmd priv_cmd;
11228 int ret = 0, i = 0, bp;
11229 char buf[WEXT_PNO_MAX_COMMAND_SIZE];
11230
11231 bp = WEXT_PNOSETUP_HEADER_SIZE;
11232 os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
11233 buf[bp++] = WEXT_PNO_TLV_PREFIX;
11234 buf[bp++] = WEXT_PNO_TLV_VERSION;
11235 buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
11236 buf[bp++] = WEXT_PNO_TLV_RESERVED;
11237
11238 while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
11239 /* Check that there is enough space needed for 1 more SSID, the
11240 * other sections and null termination */
11241 if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
11242 WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
11243 break;
11244 wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
11245 params->ssids[i].ssid,
11246 params->ssids[i].ssid_len);
11247 buf[bp++] = WEXT_PNO_SSID_SECTION;
11248 buf[bp++] = params->ssids[i].ssid_len;
11249 os_memcpy(&buf[bp], params->ssids[i].ssid,
11250 params->ssids[i].ssid_len);
11251 bp += params->ssids[i].ssid_len;
11252 i++;
11253 }
11254
11255 buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
11256 os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
11257 WEXT_PNO_SCAN_INTERVAL);
11258 bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
11259
11260 buf[bp++] = WEXT_PNO_REPEAT_SECTION;
11261 os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
11262 WEXT_PNO_REPEAT);
11263 bp += WEXT_PNO_REPEAT_LENGTH;
11264
11265 buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
11266 os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
11267 WEXT_PNO_MAX_REPEAT);
11268 bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
11269
11270 memset(&ifr, 0, sizeof(ifr));
11271 memset(&priv_cmd, 0, sizeof(priv_cmd));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070011272 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011273
11274 priv_cmd.buf = buf;
11275 priv_cmd.used_len = bp;
11276 priv_cmd.total_len = bp;
11277 ifr.ifr_data = &priv_cmd;
11278
11279 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
11280
11281 if (ret < 0) {
11282 wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
11283 ret);
11284 wpa_driver_send_hang_msg(drv);
11285 return ret;
11286 }
11287
11288 drv_errors = 0;
11289
11290 return android_priv_cmd(bss, "PNOFORCE 1");
11291}
11292
11293
11294static int android_pno_stop(struct i802_bss *bss)
11295{
11296 return android_priv_cmd(bss, "PNOFORCE 0");
11297}
11298
11299#endif /* ANDROID */
11300
11301
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011302static int driver_nl80211_set_key(const char *ifname, void *priv,
11303 enum wpa_alg alg, const u8 *addr,
11304 int key_idx, int set_tx,
11305 const u8 *seq, size_t seq_len,
11306 const u8 *key, size_t key_len)
11307{
11308 struct i802_bss *bss = priv;
11309 return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx,
11310 set_tx, seq, seq_len, key, key_len);
11311}
11312
11313
11314static int driver_nl80211_scan2(void *priv,
11315 struct wpa_driver_scan_params *params)
11316{
11317 struct i802_bss *bss = priv;
11318 return wpa_driver_nl80211_scan(bss, params);
11319}
11320
11321
11322static int driver_nl80211_deauthenticate(void *priv, const u8 *addr,
11323 int reason_code)
11324{
11325 struct i802_bss *bss = priv;
11326 return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code);
11327}
11328
11329
11330static int driver_nl80211_authenticate(void *priv,
11331 struct wpa_driver_auth_params *params)
11332{
11333 struct i802_bss *bss = priv;
11334 return wpa_driver_nl80211_authenticate(bss, params);
11335}
11336
11337
11338static void driver_nl80211_deinit(void *priv)
11339{
11340 struct i802_bss *bss = priv;
11341 wpa_driver_nl80211_deinit(bss);
11342}
11343
11344
11345static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
11346 const char *ifname)
11347{
11348 struct i802_bss *bss = priv;
11349 return wpa_driver_nl80211_if_remove(bss, type, ifname);
11350}
11351
11352
11353static int driver_nl80211_send_mlme(void *priv, const u8 *data,
11354 size_t data_len, int noack)
11355{
11356 struct i802_bss *bss = priv;
11357 return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
11358 0, 0, 0, 0);
11359}
11360
11361
11362static int driver_nl80211_sta_remove(void *priv, const u8 *addr)
11363{
11364 struct i802_bss *bss = priv;
11365 return wpa_driver_nl80211_sta_remove(bss, addr);
11366}
11367
11368
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011369static int driver_nl80211_set_sta_vlan(void *priv, const u8 *addr,
11370 const char *ifname, int vlan_id)
11371{
11372 struct i802_bss *bss = priv;
11373 return i802_set_sta_vlan(bss, addr, ifname, vlan_id);
11374}
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011375
11376
11377static int driver_nl80211_read_sta_data(void *priv,
11378 struct hostap_sta_driver_data *data,
11379 const u8 *addr)
11380{
11381 struct i802_bss *bss = priv;
11382 return i802_read_sta_data(bss, data, addr);
11383}
11384
11385
11386static int driver_nl80211_send_action(void *priv, unsigned int freq,
11387 unsigned int wait_time,
11388 const u8 *dst, const u8 *src,
11389 const u8 *bssid,
11390 const u8 *data, size_t data_len,
11391 int no_cck)
11392{
11393 struct i802_bss *bss = priv;
11394 return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src,
11395 bssid, data, data_len, no_cck);
11396}
11397
11398
11399static int driver_nl80211_probe_req_report(void *priv, int report)
11400{
11401 struct i802_bss *bss = priv;
11402 return wpa_driver_nl80211_probe_req_report(bss, report);
11403}
11404
11405
Dmitry Shmidt700a1372013-03-15 14:14:44 -070011406static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
11407 const u8 *ies, size_t ies_len)
11408{
11409 int ret;
11410 struct nl_msg *msg;
11411 struct i802_bss *bss = priv;
11412 struct wpa_driver_nl80211_data *drv = bss->drv;
11413 u16 mdid = WPA_GET_LE16(md);
11414
11415 msg = nlmsg_alloc();
11416 if (!msg)
11417 return -ENOMEM;
11418
11419 wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
11420 nl80211_cmd(drv, msg, 0, NL80211_CMD_UPDATE_FT_IES);
11421 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11422 NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies);
11423 NLA_PUT_U16(msg, NL80211_ATTR_MDID, mdid);
11424
11425 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
11426 if (ret) {
11427 wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
11428 "err=%d (%s)", ret, strerror(-ret));
11429 }
11430
11431 return ret;
11432
11433nla_put_failure:
11434 nlmsg_free(msg);
11435 return -ENOBUFS;
11436}
11437
11438
Dmitry Shmidt34af3062013-07-11 10:46:32 -070011439const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
11440{
11441 struct i802_bss *bss = priv;
11442 struct wpa_driver_nl80211_data *drv = bss->drv;
11443
11444 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE)
11445 return NULL;
11446
11447 return bss->addr;
11448}
11449
11450
Dmitry Shmidt56052862013-10-04 10:23:25 -070011451static const char * scan_state_str(enum scan_states scan_state)
11452{
11453 switch (scan_state) {
11454 case NO_SCAN:
11455 return "NO_SCAN";
11456 case SCAN_REQUESTED:
11457 return "SCAN_REQUESTED";
11458 case SCAN_STARTED:
11459 return "SCAN_STARTED";
11460 case SCAN_COMPLETED:
11461 return "SCAN_COMPLETED";
11462 case SCAN_ABORTED:
11463 return "SCAN_ABORTED";
11464 case SCHED_SCAN_STARTED:
11465 return "SCHED_SCAN_STARTED";
11466 case SCHED_SCAN_STOPPED:
11467 return "SCHED_SCAN_STOPPED";
11468 case SCHED_SCAN_RESULTS:
11469 return "SCHED_SCAN_RESULTS";
11470 }
11471
11472 return "??";
11473}
11474
11475
11476static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
11477{
11478 struct i802_bss *bss = priv;
11479 struct wpa_driver_nl80211_data *drv = bss->drv;
11480 int res;
11481 char *pos, *end;
11482
11483 pos = buf;
11484 end = buf + buflen;
11485
11486 res = os_snprintf(pos, end - pos,
11487 "ifindex=%d\n"
11488 "ifname=%s\n"
11489 "brname=%s\n"
11490 "addr=" MACSTR "\n"
11491 "freq=%d\n"
11492 "%s%s%s%s%s",
11493 bss->ifindex,
11494 bss->ifname,
11495 bss->brname,
11496 MAC2STR(bss->addr),
11497 bss->freq,
11498 bss->beacon_set ? "beacon_set=1\n" : "",
11499 bss->added_if_into_bridge ?
11500 "added_if_into_bridge=1\n" : "",
11501 bss->added_bridge ? "added_bridge=1\n" : "",
11502 bss->in_deinit ? "in_deinit=1\n" : "",
11503 bss->if_dynamic ? "if_dynamic=1\n" : "");
11504 if (res < 0 || res >= end - pos)
11505 return pos - buf;
11506 pos += res;
11507
11508 if (bss->wdev_id_set) {
11509 res = os_snprintf(pos, end - pos, "wdev_id=%llu\n",
11510 (unsigned long long) bss->wdev_id);
11511 if (res < 0 || res >= end - pos)
11512 return pos - buf;
11513 pos += res;
11514 }
11515
11516 res = os_snprintf(pos, end - pos,
11517 "phyname=%s\n"
11518 "drv_ifindex=%d\n"
11519 "operstate=%d\n"
11520 "scan_state=%s\n"
11521 "auth_bssid=" MACSTR "\n"
11522 "auth_attempt_bssid=" MACSTR "\n"
11523 "bssid=" MACSTR "\n"
11524 "prev_bssid=" MACSTR "\n"
11525 "associated=%d\n"
11526 "assoc_freq=%u\n"
11527 "monitor_sock=%d\n"
11528 "monitor_ifidx=%d\n"
11529 "monitor_refcount=%d\n"
11530 "last_mgmt_freq=%u\n"
11531 "eapol_tx_sock=%d\n"
11532 "%s%s%s%s%s%s%s%s%s%s%s%s%s",
11533 drv->phyname,
11534 drv->ifindex,
11535 drv->operstate,
11536 scan_state_str(drv->scan_state),
11537 MAC2STR(drv->auth_bssid),
11538 MAC2STR(drv->auth_attempt_bssid),
11539 MAC2STR(drv->bssid),
11540 MAC2STR(drv->prev_bssid),
11541 drv->associated,
11542 drv->assoc_freq,
11543 drv->monitor_sock,
11544 drv->monitor_ifidx,
11545 drv->monitor_refcount,
11546 drv->last_mgmt_freq,
11547 drv->eapol_tx_sock,
11548 drv->ignore_if_down_event ?
11549 "ignore_if_down_event=1\n" : "",
11550 drv->scan_complete_events ?
11551 "scan_complete_events=1\n" : "",
11552 drv->disabled_11b_rates ?
11553 "disabled_11b_rates=1\n" : "",
11554 drv->pending_remain_on_chan ?
11555 "pending_remain_on_chan=1\n" : "",
11556 drv->in_interface_list ? "in_interface_list=1\n" : "",
11557 drv->device_ap_sme ? "device_ap_sme=1\n" : "",
11558 drv->poll_command_supported ?
11559 "poll_command_supported=1\n" : "",
11560 drv->data_tx_status ? "data_tx_status=1\n" : "",
11561 drv->scan_for_auth ? "scan_for_auth=1\n" : "",
11562 drv->retry_auth ? "retry_auth=1\n" : "",
11563 drv->use_monitor ? "use_monitor=1\n" : "",
11564 drv->ignore_next_local_disconnect ?
11565 "ignore_next_local_disconnect=1\n" : "",
11566 drv->allow_p2p_device ? "allow_p2p_device=1\n" : "");
11567 if (res < 0 || res >= end - pos)
11568 return pos - buf;
11569 pos += res;
11570
11571 if (drv->has_capability) {
11572 res = os_snprintf(pos, end - pos,
11573 "capa.key_mgmt=0x%x\n"
11574 "capa.enc=0x%x\n"
11575 "capa.auth=0x%x\n"
11576 "capa.flags=0x%x\n"
11577 "capa.max_scan_ssids=%d\n"
11578 "capa.max_sched_scan_ssids=%d\n"
11579 "capa.sched_scan_supported=%d\n"
11580 "capa.max_match_sets=%d\n"
11581 "capa.max_remain_on_chan=%u\n"
11582 "capa.max_stations=%u\n"
11583 "capa.probe_resp_offloads=0x%x\n"
11584 "capa.max_acl_mac_addrs=%u\n"
11585 "capa.num_multichan_concurrent=%u\n",
11586 drv->capa.key_mgmt,
11587 drv->capa.enc,
11588 drv->capa.auth,
11589 drv->capa.flags,
11590 drv->capa.max_scan_ssids,
11591 drv->capa.max_sched_scan_ssids,
11592 drv->capa.sched_scan_supported,
11593 drv->capa.max_match_sets,
11594 drv->capa.max_remain_on_chan,
11595 drv->capa.max_stations,
11596 drv->capa.probe_resp_offloads,
11597 drv->capa.max_acl_mac_addrs,
11598 drv->capa.num_multichan_concurrent);
11599 if (res < 0 || res >= end - pos)
11600 return pos - buf;
11601 pos += res;
11602 }
11603
11604 return pos - buf;
11605}
11606
11607
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080011608static int set_beacon_data(struct nl_msg *msg, struct beacon_data *settings)
11609{
11610 if (settings->head)
11611 NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD,
11612 settings->head_len, settings->head);
11613
11614 if (settings->tail)
11615 NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL,
11616 settings->tail_len, settings->tail);
11617
11618 if (settings->beacon_ies)
11619 NLA_PUT(msg, NL80211_ATTR_IE,
11620 settings->beacon_ies_len, settings->beacon_ies);
11621
11622 if (settings->proberesp_ies)
11623 NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
11624 settings->proberesp_ies_len, settings->proberesp_ies);
11625
11626 if (settings->assocresp_ies)
11627 NLA_PUT(msg,
11628 NL80211_ATTR_IE_ASSOC_RESP,
11629 settings->assocresp_ies_len, settings->assocresp_ies);
11630
11631 if (settings->probe_resp)
11632 NLA_PUT(msg, NL80211_ATTR_PROBE_RESP,
11633 settings->probe_resp_len, settings->probe_resp);
11634
11635 return 0;
11636
11637nla_put_failure:
11638 return -ENOBUFS;
11639}
11640
11641
11642static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
11643{
11644 struct nl_msg *msg;
11645 struct i802_bss *bss = priv;
11646 struct wpa_driver_nl80211_data *drv = bss->drv;
11647 struct nlattr *beacon_csa;
11648 int ret = -ENOBUFS;
11649
Dmitry Shmidt04f534e2013-12-09 15:50:16 -080011650 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 -080011651 settings->cs_count, settings->block_tx,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -080011652 settings->freq_params.freq, settings->freq_params.bandwidth,
11653 settings->freq_params.center_freq1,
11654 settings->freq_params.center_freq2);
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080011655
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080011656 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080011657 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command");
11658 return -EOPNOTSUPP;
11659 }
11660
11661 if ((drv->nlmode != NL80211_IFTYPE_AP) &&
11662 (drv->nlmode != NL80211_IFTYPE_P2P_GO))
11663 return -EOPNOTSUPP;
11664
11665 /* check settings validity */
11666 if (!settings->beacon_csa.tail ||
11667 ((settings->beacon_csa.tail_len <=
11668 settings->counter_offset_beacon) ||
11669 (settings->beacon_csa.tail[settings->counter_offset_beacon] !=
11670 settings->cs_count)))
11671 return -EINVAL;
11672
11673 if (settings->beacon_csa.probe_resp &&
11674 ((settings->beacon_csa.probe_resp_len <=
11675 settings->counter_offset_presp) ||
11676 (settings->beacon_csa.probe_resp[settings->counter_offset_presp] !=
11677 settings->cs_count)))
11678 return -EINVAL;
11679
11680 msg = nlmsg_alloc();
11681 if (!msg)
11682 return -ENOMEM;
11683
11684 nl80211_cmd(drv, msg, 0, NL80211_CMD_CHANNEL_SWITCH);
11685 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11686 NLA_PUT_U32(msg, NL80211_ATTR_CH_SWITCH_COUNT, settings->cs_count);
11687 ret = nl80211_put_freq_params(msg, &settings->freq_params);
11688 if (ret)
11689 goto error;
11690
11691 if (settings->block_tx)
11692 NLA_PUT_FLAG(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX);
11693
11694 /* beacon_after params */
11695 ret = set_beacon_data(msg, &settings->beacon_after);
11696 if (ret)
11697 goto error;
11698
11699 /* beacon_csa params */
11700 beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
11701 if (!beacon_csa)
11702 goto nla_put_failure;
11703
11704 ret = set_beacon_data(msg, &settings->beacon_csa);
11705 if (ret)
11706 goto error;
11707
11708 NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_BEACON,
11709 settings->counter_offset_beacon);
11710
11711 if (settings->beacon_csa.probe_resp)
11712 NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_PRESP,
11713 settings->counter_offset_presp);
11714
11715 nla_nest_end(msg, beacon_csa);
11716 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
11717 if (ret) {
11718 wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)",
11719 ret, strerror(-ret));
11720 }
11721 return ret;
11722
11723nla_put_failure:
11724 ret = -ENOBUFS;
11725error:
11726 nlmsg_free(msg);
11727 wpa_printf(MSG_DEBUG, "nl80211: Could not build channel switch request");
11728 return ret;
11729}
11730
11731
Dmitry Shmidta38abf92014-03-06 13:38:44 -080011732#ifdef CONFIG_TESTING_OPTIONS
11733static int cmd_reply_handler(struct nl_msg *msg, void *arg)
11734{
11735 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11736 struct wpabuf *buf = arg;
11737
11738 if (!buf)
11739 return NL_SKIP;
11740
11741 if ((size_t) genlmsg_attrlen(gnlh, 0) > wpabuf_tailroom(buf)) {
11742 wpa_printf(MSG_INFO, "nl80211: insufficient buffer space for reply");
11743 return NL_SKIP;
11744 }
11745
11746 wpabuf_put_data(buf, genlmsg_attrdata(gnlh, 0),
11747 genlmsg_attrlen(gnlh, 0));
11748
11749 return NL_SKIP;
11750}
11751#endif /* CONFIG_TESTING_OPTIONS */
11752
11753
11754static int vendor_reply_handler(struct nl_msg *msg, void *arg)
11755{
11756 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11757 struct nlattr *nl_vendor_reply, *nl;
11758 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11759 struct wpabuf *buf = arg;
11760 int rem;
11761
11762 if (!buf)
11763 return NL_SKIP;
11764
11765 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
11766 genlmsg_attrlen(gnlh, 0), NULL);
11767 nl_vendor_reply = tb[NL80211_ATTR_VENDOR_DATA];
11768
11769 if (!nl_vendor_reply)
11770 return NL_SKIP;
11771
11772 if ((size_t) nla_len(nl_vendor_reply) > wpabuf_tailroom(buf)) {
11773 wpa_printf(MSG_INFO, "nl80211: Vendor command: insufficient buffer space for reply");
11774 return NL_SKIP;
11775 }
11776
11777 nla_for_each_nested(nl, nl_vendor_reply, rem) {
11778 wpabuf_put_data(buf, nla_data(nl), nla_len(nl));
11779 }
11780
11781 return NL_SKIP;
11782}
11783
11784
11785static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
11786 unsigned int subcmd, const u8 *data,
11787 size_t data_len, struct wpabuf *buf)
11788{
11789 struct i802_bss *bss = priv;
11790 struct wpa_driver_nl80211_data *drv = bss->drv;
11791 struct nl_msg *msg;
11792 int ret;
11793
11794 msg = nlmsg_alloc();
11795 if (!msg)
11796 return -ENOMEM;
11797
11798#ifdef CONFIG_TESTING_OPTIONS
11799 if (vendor_id == 0xffffffff) {
11800 nl80211_cmd(drv, msg, 0, subcmd);
11801 if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) <
11802 0)
11803 goto nla_put_failure;
11804 ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf);
11805 if (ret)
11806 wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d",
11807 ret);
11808 return ret;
11809 }
11810#endif /* CONFIG_TESTING_OPTIONS */
11811
11812 nl80211_cmd(drv, msg, 0, NL80211_CMD_VENDOR);
11813 if (nl80211_set_iface_id(msg, bss) < 0)
11814 goto nla_put_failure;
11815 NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, vendor_id);
11816 NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd);
11817 if (data)
11818 NLA_PUT(msg, NL80211_ATTR_VENDOR_DATA, data_len, data);
11819
11820 ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf);
11821 if (ret)
11822 wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d",
11823 ret);
11824 return ret;
11825
11826nla_put_failure:
11827 nlmsg_free(msg);
11828 return -ENOBUFS;
11829}
11830
11831
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080011832static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set,
11833 u8 qos_map_set_len)
11834{
11835 struct i802_bss *bss = priv;
11836 struct wpa_driver_nl80211_data *drv = bss->drv;
11837 struct nl_msg *msg;
11838 int ret;
11839
11840 msg = nlmsg_alloc();
11841 if (!msg)
11842 return -ENOMEM;
11843
11844 wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map",
11845 qos_map_set, qos_map_set_len);
11846
11847 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_QOS_MAP);
11848 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11849 NLA_PUT(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set);
11850
11851 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
11852 if (ret)
11853 wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed");
11854
11855 return ret;
11856
11857nla_put_failure:
11858 nlmsg_free(msg);
11859 return -ENOBUFS;
11860}
11861
11862
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011863const struct wpa_driver_ops wpa_driver_nl80211_ops = {
11864 .name = "nl80211",
11865 .desc = "Linux nl80211/cfg80211",
11866 .get_bssid = wpa_driver_nl80211_get_bssid,
11867 .get_ssid = wpa_driver_nl80211_get_ssid,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011868 .set_key = driver_nl80211_set_key,
11869 .scan2 = driver_nl80211_scan2,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011870 .sched_scan = wpa_driver_nl80211_sched_scan,
11871 .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011872 .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011873 .deauthenticate = driver_nl80211_deauthenticate,
11874 .authenticate = driver_nl80211_authenticate,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011875 .associate = wpa_driver_nl80211_associate,
11876 .global_init = nl80211_global_init,
11877 .global_deinit = nl80211_global_deinit,
11878 .init2 = wpa_driver_nl80211_init,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011879 .deinit = driver_nl80211_deinit,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011880 .get_capa = wpa_driver_nl80211_get_capa,
11881 .set_operstate = wpa_driver_nl80211_set_operstate,
11882 .set_supp_port = wpa_driver_nl80211_set_supp_port,
11883 .set_country = wpa_driver_nl80211_set_country,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080011884 .get_country = wpa_driver_nl80211_get_country,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011885 .set_ap = wpa_driver_nl80211_set_ap,
Dmitry Shmidt8bae4132013-06-06 11:25:10 -070011886 .set_acl = wpa_driver_nl80211_set_acl,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011887 .if_add = wpa_driver_nl80211_if_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011888 .if_remove = driver_nl80211_if_remove,
11889 .send_mlme = driver_nl80211_send_mlme,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011890 .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data,
11891 .sta_add = wpa_driver_nl80211_sta_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011892 .sta_remove = driver_nl80211_sta_remove,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011893 .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
11894 .sta_set_flags = wpa_driver_nl80211_sta_set_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011895 .hapd_init = i802_init,
11896 .hapd_deinit = i802_deinit,
Jouni Malinen75ecf522011-06-27 15:19:46 -070011897 .set_wds_sta = i802_set_wds_sta,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011898 .get_seqnum = i802_get_seqnum,
11899 .flush = i802_flush,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011900 .get_inact_sec = i802_get_inact_sec,
11901 .sta_clear_stats = i802_sta_clear_stats,
11902 .set_rts = i802_set_rts,
11903 .set_frag = i802_set_frag,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011904 .set_tx_queue_params = i802_set_tx_queue_params,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011905 .set_sta_vlan = driver_nl80211_set_sta_vlan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011906 .sta_deauth = i802_sta_deauth,
11907 .sta_disassoc = i802_sta_disassoc,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011908 .read_sta_data = driver_nl80211_read_sta_data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011909 .set_freq = i802_set_freq,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011910 .send_action = driver_nl80211_send_action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011911 .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
11912 .remain_on_channel = wpa_driver_nl80211_remain_on_channel,
11913 .cancel_remain_on_channel =
11914 wpa_driver_nl80211_cancel_remain_on_channel,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011915 .probe_req_report = driver_nl80211_probe_req_report,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011916 .deinit_ap = wpa_driver_nl80211_deinit_ap,
Dmitry Shmidt04949592012-07-19 12:16:46 -070011917 .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011918 .resume = wpa_driver_nl80211_resume,
11919 .send_ft_action = nl80211_send_ft_action,
11920 .signal_monitor = nl80211_signal_monitor,
11921 .signal_poll = nl80211_signal_poll,
11922 .send_frame = nl80211_send_frame,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011923 .shared_freq = wpa_driver_nl80211_shared_freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011924 .set_param = nl80211_set_param,
11925 .get_radio_name = nl80211_get_radio_name,
Jouni Malinen75ecf522011-06-27 15:19:46 -070011926 .add_pmkid = nl80211_add_pmkid,
11927 .remove_pmkid = nl80211_remove_pmkid,
11928 .flush_pmkid = nl80211_flush_pmkid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011929 .set_rekey_info = nl80211_set_rekey_info,
11930 .poll_client = nl80211_poll_client,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011931 .set_p2p_powersave = nl80211_set_p2p_powersave,
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011932 .start_dfs_cac = nl80211_start_radar_detection,
11933 .stop_ap = wpa_driver_nl80211_stop_ap,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011934#ifdef CONFIG_TDLS
11935 .send_tdls_mgmt = nl80211_send_tdls_mgmt,
11936 .tdls_oper = nl80211_tdls_oper,
11937#endif /* CONFIG_TDLS */
Dmitry Shmidt700a1372013-03-15 14:14:44 -070011938 .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
Dmitry Shmidt34af3062013-07-11 10:46:32 -070011939 .get_mac_addr = wpa_driver_nl80211_get_macaddr,
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070011940 .get_survey = wpa_driver_nl80211_get_survey,
Dmitry Shmidt56052862013-10-04 10:23:25 -070011941 .status = wpa_driver_nl80211_status,
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080011942 .switch_channel = nl80211_switch_channel,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011943#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070011944 .set_noa = wpa_driver_set_p2p_noa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011945 .get_noa = wpa_driver_get_p2p_noa,
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070011946 .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080011947#endif /* ANDROID_P2P */
Dmitry Shmidt738a26e2011-07-07 14:22:14 -070011948#ifdef ANDROID
11949 .driver_cmd = wpa_driver_nl80211_driver_cmd,
Dmitry Shmidt292b0c32013-11-22 12:54:42 -080011950#endif /* ANDROID */
Dmitry Shmidta38abf92014-03-06 13:38:44 -080011951 .vendor_cmd = nl80211_vendor_cmd,
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080011952 .set_qos_map = nl80211_set_qos_map,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011953};