blob: fd0514987ea435a083698f9286e30b2015dfb084 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Driver interaction with Linux nl80211/cfg80211
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003 * Copyright (c) 2002-2012, 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"
31#include "common/ieee802_11_defs.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080032#include "common/ieee802_11_common.h"
33#include "l2_packet/l2_packet.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034#include "netlink.h"
35#include "linux_ioctl.h"
36#include "radiotap.h"
37#include "radiotap_iter.h"
38#include "rfkill.h"
39#include "driver.h"
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080040
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080041#ifndef SO_WIFI_STATUS
42# if defined(__sparc__)
43# define SO_WIFI_STATUS 0x0025
44# elif defined(__parisc__)
45# define SO_WIFI_STATUS 0x4022
46# else
47# define SO_WIFI_STATUS 41
48# endif
49
50# define SCM_WIFI_STATUS SO_WIFI_STATUS
51#endif
52
53#ifndef SO_EE_ORIGIN_TXSTATUS
54#define SO_EE_ORIGIN_TXSTATUS 4
55#endif
56
57#ifndef PACKET_TX_TIMESTAMP
58#define PACKET_TX_TIMESTAMP 16
59#endif
60
61#ifdef ANDROID
62#include "android_drv.h"
63#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064#ifdef CONFIG_LIBNL20
65/* libnl 2.0 compatibility code */
66#define nl_handle nl_sock
67#define nl80211_handle_alloc nl_socket_alloc_cb
68#define nl80211_handle_destroy nl_socket_free
69#else
70/*
71 * libnl 1.1 has a bug, it tries to allocate socket numbers densely
72 * but when you free a socket again it will mess up its bitmap and
73 * and use the wrong number the next time it needs a socket ID.
74 * Therefore, we wrap the handle alloc/destroy and add our own pid
75 * accounting.
76 */
77static uint32_t port_bitmap[32] = { 0 };
78
79static struct nl_handle *nl80211_handle_alloc(void *cb)
80{
81 struct nl_handle *handle;
82 uint32_t pid = getpid() & 0x3FFFFF;
83 int i;
84
85 handle = nl_handle_alloc_cb(cb);
86
87 for (i = 0; i < 1024; i++) {
88 if (port_bitmap[i / 32] & (1 << (i % 32)))
89 continue;
90 port_bitmap[i / 32] |= 1 << (i % 32);
91 pid += i << 22;
92 break;
93 }
94
95 nl_socket_set_local_port(handle, pid);
96
97 return handle;
98}
99
100static void nl80211_handle_destroy(struct nl_handle *handle)
101{
102 uint32_t port = nl_socket_get_local_port(handle);
103
104 port >>= 22;
105 port_bitmap[port / 32] &= ~(1 << (port % 32));
106
107 nl_handle_destroy(handle);
108}
109#endif /* CONFIG_LIBNL20 */
110
111
Dmitry Shmidt54605472013-11-08 11:10:19 -0800112#ifdef ANDROID
113/* system/core/libnl_2 does not include nl_socket_set_nonblocking() */
114static int android_nl_socket_set_nonblocking(struct nl_handle *handle)
115{
116 return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
117}
118#undef nl_socket_set_nonblocking
119#define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h)
120#endif /* ANDROID */
121
122
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800123static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
124{
125 struct nl_handle *handle;
126
127 handle = nl80211_handle_alloc(cb);
128 if (handle == NULL) {
129 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
130 "callbacks (%s)", dbg);
131 return NULL;
132 }
133
134 if (genl_connect(handle)) {
135 wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
136 "netlink (%s)", dbg);
137 nl80211_handle_destroy(handle);
138 return NULL;
139 }
140
141 return handle;
142}
143
144
145static void nl_destroy_handles(struct nl_handle **handle)
146{
147 if (*handle == NULL)
148 return;
149 nl80211_handle_destroy(*handle);
150 *handle = NULL;
151}
152
153
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700154#if __WORDSIZE == 64
155#define ELOOP_SOCKET_INVALID (intptr_t) 0x8888888888888889ULL
156#else
157#define ELOOP_SOCKET_INVALID (intptr_t) 0x88888889ULL
158#endif
159
160static void nl80211_register_eloop_read(struct nl_handle **handle,
161 eloop_sock_handler handler,
162 void *eloop_data)
163{
164 nl_socket_set_nonblocking(*handle);
165 eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
166 eloop_data, *handle);
167 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
168}
169
170
171static void nl80211_destroy_eloop_handle(struct nl_handle **handle)
172{
173 *handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
174 eloop_unregister_read_sock(nl_socket_get_fd(*handle));
175 nl_destroy_handles(handle);
176}
177
178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700179#ifndef IFF_LOWER_UP
180#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
181#endif
182#ifndef IFF_DORMANT
183#define IFF_DORMANT 0x20000 /* driver signals dormant */
184#endif
185
186#ifndef IF_OPER_DORMANT
187#define IF_OPER_DORMANT 5
188#endif
189#ifndef IF_OPER_UP
190#define IF_OPER_UP 6
191#endif
192
193struct nl80211_global {
194 struct dl_list interfaces;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800195 int if_add_ifindex;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700196 u64 if_add_wdevid;
197 int if_add_wdevid_set;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800198 struct netlink_data *netlink;
199 struct nl_cb *nl_cb;
200 struct nl_handle *nl;
201 int nl80211_id;
202 int ioctl_sock; /* socket for ioctl() use */
203
204 struct nl_handle *nl_event;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700205};
206
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800207struct nl80211_wiphy_data {
208 struct dl_list list;
209 struct dl_list bsss;
210 struct dl_list drvs;
211
212 struct nl_handle *nl_beacons;
213 struct nl_cb *nl_cb;
214
215 int wiphy_idx;
216};
217
218static void nl80211_global_deinit(void *priv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800219
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700220struct i802_bss {
221 struct wpa_driver_nl80211_data *drv;
222 struct i802_bss *next;
223 int ifindex;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700224 u64 wdev_id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700225 char ifname[IFNAMSIZ + 1];
226 char brname[IFNAMSIZ];
227 unsigned int beacon_set:1;
228 unsigned int added_if_into_bridge:1;
229 unsigned int added_bridge:1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700230 unsigned int in_deinit:1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700231 unsigned int wdev_id_set:1;
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800232 unsigned int added_if:1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800233
234 u8 addr[ETH_ALEN];
235
236 int freq;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -0700237 int if_dynamic;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800238
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800239 void *ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800240 struct nl_handle *nl_preq, *nl_mgmt;
241 struct nl_cb *nl_cb;
242
243 struct nl80211_wiphy_data *wiphy_data;
244 struct dl_list wiphy_list;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700245};
246
247struct wpa_driver_nl80211_data {
248 struct nl80211_global *global;
249 struct dl_list list;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800250 struct dl_list wiphy_list;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700251 char phyname[32];
252 void *ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700253 int ifindex;
254 int if_removed;
255 int if_disabled;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800256 int ignore_if_down_event;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257 struct rfkill_data *rfkill;
258 struct wpa_driver_capa capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -0700259 u8 *extended_capa, *extended_capa_mask;
260 unsigned int extended_capa_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700261 int has_capability;
262
263 int operstate;
264
265 int scan_complete_events;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700266 enum scan_states {
267 NO_SCAN, SCAN_REQUESTED, SCAN_STARTED, SCAN_COMPLETED,
268 SCAN_ABORTED, SCHED_SCAN_STARTED, SCHED_SCAN_STOPPED,
269 SCHED_SCAN_RESULTS
270 } scan_state;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700271
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700272 struct nl_cb *nl_cb;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700273
274 u8 auth_bssid[ETH_ALEN];
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700275 u8 auth_attempt_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276 u8 bssid[ETH_ALEN];
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700277 u8 prev_bssid[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700278 int associated;
279 u8 ssid[32];
280 size_t ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800281 enum nl80211_iftype nlmode;
282 enum nl80211_iftype ap_scan_as_station;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700283 unsigned int assoc_freq;
284
285 int monitor_sock;
286 int monitor_ifidx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800287 int monitor_refcount;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700288
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800289 unsigned int disabled_11b_rates:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700290 unsigned int pending_remain_on_chan:1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800291 unsigned int in_interface_list:1;
292 unsigned int device_ap_sme:1;
293 unsigned int poll_command_supported:1;
294 unsigned int data_tx_status:1;
295 unsigned int scan_for_auth:1;
296 unsigned int retry_auth:1;
297 unsigned int use_monitor:1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800298 unsigned int ignore_next_local_disconnect:1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700299 unsigned int allow_p2p_device:1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800300 unsigned int hostapd:1;
301 unsigned int start_mode_ap:1;
302 unsigned int start_iface_up:1;
303 unsigned int channel_switch_supported:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700304
305 u64 remain_on_chan_cookie;
306 u64 send_action_cookie;
307
308 unsigned int last_mgmt_freq;
309
310 struct wpa_driver_scan_filter *filter_ssids;
311 size_t num_filter_ssids;
312
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800313 struct i802_bss *first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700314
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800315 int eapol_tx_sock;
316
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700317 int eapol_sock; /* socket for EAPOL frames */
318
319 int default_if_indices[16];
320 int *if_indices;
321 int num_if_indices;
322
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800323 /* From failed authentication command */
324 int auth_freq;
325 u8 auth_bssid_[ETH_ALEN];
326 u8 auth_ssid[32];
327 size_t auth_ssid_len;
328 int auth_alg;
329 u8 *auth_ie;
330 size_t auth_ie_len;
331 u8 auth_wep_key[4][16];
332 size_t auth_wep_key_len[4];
333 int auth_wep_tx_keyidx;
334 int auth_local_state_change;
335 int auth_p2p;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700336};
337
338
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800339static void wpa_driver_nl80211_deinit(struct i802_bss *bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700340static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
341 void *timeout_ctx);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800342static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
343 enum nl80211_iftype nlmode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700344static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800345wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
346 const u8 *set_addr, int first);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700347static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
348 const u8 *addr, int cmd, u16 reason_code,
349 int local_state_change);
350static void nl80211_remove_monitor_interface(
351 struct wpa_driver_nl80211_data *drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800352static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700353 unsigned int freq, unsigned int wait,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800354 const u8 *buf, size_t buf_len, u64 *cookie,
355 int no_cck, int no_ack, int offchanok);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700356static int nl80211_register_frame(struct i802_bss *bss,
357 struct nl_handle *hl_handle,
358 u16 type, const u8 *match, size_t match_len);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800359static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
360 int report);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800361#ifdef ANDROID
362static int android_pno_start(struct i802_bss *bss,
363 struct wpa_driver_scan_params *params);
364static int android_pno_stop(struct i802_bss *bss);
365#endif /* ANDROID */
366#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -0700367int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800368int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -0700369int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow);
370int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
371 const struct wpabuf *proberesp,
372 const struct wpabuf *assocresp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700373
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800374#endif
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800375#ifdef ANDROID
376extern int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
377 size_t buf_len);
378#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
380static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
381static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800382static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383 enum wpa_driver_if_type type,
384 const char *ifname);
Dmitry Shmidt738a26e2011-07-07 14:22:14 -0700385
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -0800386static int wpa_driver_nl80211_set_freq(struct i802_bss *bss,
387 struct hostapd_freq_params *freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
389 int ifindex, int disabled);
390
391static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800392static int wpa_driver_nl80211_authenticate_retry(
393 struct wpa_driver_nl80211_data *drv);
394
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -0700395static int i802_set_iface_flags(struct i802_bss *bss, int up);
396
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800397
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700398static const char * nl80211_command_to_string(enum nl80211_commands cmd)
399{
400#define C2S(x) case x: return #x;
401 switch (cmd) {
402 C2S(NL80211_CMD_UNSPEC)
403 C2S(NL80211_CMD_GET_WIPHY)
404 C2S(NL80211_CMD_SET_WIPHY)
405 C2S(NL80211_CMD_NEW_WIPHY)
406 C2S(NL80211_CMD_DEL_WIPHY)
407 C2S(NL80211_CMD_GET_INTERFACE)
408 C2S(NL80211_CMD_SET_INTERFACE)
409 C2S(NL80211_CMD_NEW_INTERFACE)
410 C2S(NL80211_CMD_DEL_INTERFACE)
411 C2S(NL80211_CMD_GET_KEY)
412 C2S(NL80211_CMD_SET_KEY)
413 C2S(NL80211_CMD_NEW_KEY)
414 C2S(NL80211_CMD_DEL_KEY)
415 C2S(NL80211_CMD_GET_BEACON)
416 C2S(NL80211_CMD_SET_BEACON)
417 C2S(NL80211_CMD_START_AP)
418 C2S(NL80211_CMD_STOP_AP)
419 C2S(NL80211_CMD_GET_STATION)
420 C2S(NL80211_CMD_SET_STATION)
421 C2S(NL80211_CMD_NEW_STATION)
422 C2S(NL80211_CMD_DEL_STATION)
423 C2S(NL80211_CMD_GET_MPATH)
424 C2S(NL80211_CMD_SET_MPATH)
425 C2S(NL80211_CMD_NEW_MPATH)
426 C2S(NL80211_CMD_DEL_MPATH)
427 C2S(NL80211_CMD_SET_BSS)
428 C2S(NL80211_CMD_SET_REG)
429 C2S(NL80211_CMD_REQ_SET_REG)
430 C2S(NL80211_CMD_GET_MESH_CONFIG)
431 C2S(NL80211_CMD_SET_MESH_CONFIG)
432 C2S(NL80211_CMD_SET_MGMT_EXTRA_IE)
433 C2S(NL80211_CMD_GET_REG)
434 C2S(NL80211_CMD_GET_SCAN)
435 C2S(NL80211_CMD_TRIGGER_SCAN)
436 C2S(NL80211_CMD_NEW_SCAN_RESULTS)
437 C2S(NL80211_CMD_SCAN_ABORTED)
438 C2S(NL80211_CMD_REG_CHANGE)
439 C2S(NL80211_CMD_AUTHENTICATE)
440 C2S(NL80211_CMD_ASSOCIATE)
441 C2S(NL80211_CMD_DEAUTHENTICATE)
442 C2S(NL80211_CMD_DISASSOCIATE)
443 C2S(NL80211_CMD_MICHAEL_MIC_FAILURE)
444 C2S(NL80211_CMD_REG_BEACON_HINT)
445 C2S(NL80211_CMD_JOIN_IBSS)
446 C2S(NL80211_CMD_LEAVE_IBSS)
447 C2S(NL80211_CMD_TESTMODE)
448 C2S(NL80211_CMD_CONNECT)
449 C2S(NL80211_CMD_ROAM)
450 C2S(NL80211_CMD_DISCONNECT)
451 C2S(NL80211_CMD_SET_WIPHY_NETNS)
452 C2S(NL80211_CMD_GET_SURVEY)
453 C2S(NL80211_CMD_NEW_SURVEY_RESULTS)
454 C2S(NL80211_CMD_SET_PMKSA)
455 C2S(NL80211_CMD_DEL_PMKSA)
456 C2S(NL80211_CMD_FLUSH_PMKSA)
457 C2S(NL80211_CMD_REMAIN_ON_CHANNEL)
458 C2S(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL)
459 C2S(NL80211_CMD_SET_TX_BITRATE_MASK)
460 C2S(NL80211_CMD_REGISTER_FRAME)
461 C2S(NL80211_CMD_FRAME)
462 C2S(NL80211_CMD_FRAME_TX_STATUS)
463 C2S(NL80211_CMD_SET_POWER_SAVE)
464 C2S(NL80211_CMD_GET_POWER_SAVE)
465 C2S(NL80211_CMD_SET_CQM)
466 C2S(NL80211_CMD_NOTIFY_CQM)
467 C2S(NL80211_CMD_SET_CHANNEL)
468 C2S(NL80211_CMD_SET_WDS_PEER)
469 C2S(NL80211_CMD_FRAME_WAIT_CANCEL)
470 C2S(NL80211_CMD_JOIN_MESH)
471 C2S(NL80211_CMD_LEAVE_MESH)
472 C2S(NL80211_CMD_UNPROT_DEAUTHENTICATE)
473 C2S(NL80211_CMD_UNPROT_DISASSOCIATE)
474 C2S(NL80211_CMD_NEW_PEER_CANDIDATE)
475 C2S(NL80211_CMD_GET_WOWLAN)
476 C2S(NL80211_CMD_SET_WOWLAN)
477 C2S(NL80211_CMD_START_SCHED_SCAN)
478 C2S(NL80211_CMD_STOP_SCHED_SCAN)
479 C2S(NL80211_CMD_SCHED_SCAN_RESULTS)
480 C2S(NL80211_CMD_SCHED_SCAN_STOPPED)
481 C2S(NL80211_CMD_SET_REKEY_OFFLOAD)
482 C2S(NL80211_CMD_PMKSA_CANDIDATE)
483 C2S(NL80211_CMD_TDLS_OPER)
484 C2S(NL80211_CMD_TDLS_MGMT)
485 C2S(NL80211_CMD_UNEXPECTED_FRAME)
486 C2S(NL80211_CMD_PROBE_CLIENT)
487 C2S(NL80211_CMD_REGISTER_BEACONS)
488 C2S(NL80211_CMD_UNEXPECTED_4ADDR_FRAME)
489 C2S(NL80211_CMD_SET_NOACK_MAP)
490 C2S(NL80211_CMD_CH_SWITCH_NOTIFY)
491 C2S(NL80211_CMD_START_P2P_DEVICE)
492 C2S(NL80211_CMD_STOP_P2P_DEVICE)
493 C2S(NL80211_CMD_CONN_FAILED)
494 C2S(NL80211_CMD_SET_MCAST_RATE)
495 C2S(NL80211_CMD_SET_MAC_ACL)
496 C2S(NL80211_CMD_RADAR_DETECT)
497 C2S(NL80211_CMD_GET_PROTOCOL_FEATURES)
498 C2S(NL80211_CMD_UPDATE_FT_IES)
499 C2S(NL80211_CMD_FT_EVENT)
500 C2S(NL80211_CMD_CRIT_PROTOCOL_START)
501 C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
502 default:
503 return "NL80211_CMD_UNKNOWN";
504 }
505#undef C2S
506}
507
508
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800509static int is_ap_interface(enum nl80211_iftype nlmode)
510{
511 return (nlmode == NL80211_IFTYPE_AP ||
512 nlmode == NL80211_IFTYPE_P2P_GO);
513}
514
515
516static int is_sta_interface(enum nl80211_iftype nlmode)
517{
518 return (nlmode == NL80211_IFTYPE_STATION ||
519 nlmode == NL80211_IFTYPE_P2P_CLIENT);
520}
521
522
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700523static int is_p2p_net_interface(enum nl80211_iftype nlmode)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800524{
525 return (nlmode == NL80211_IFTYPE_P2P_CLIENT ||
526 nlmode == NL80211_IFTYPE_P2P_GO);
527}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700528
529
Dmitry Shmidt8bae4132013-06-06 11:25:10 -0700530static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
531{
532 if (drv->associated)
533 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
534 drv->associated = 0;
535 os_memset(drv->bssid, 0, ETH_ALEN);
536}
537
538
Jouni Malinen87fd2792011-05-16 18:35:42 +0300539struct nl80211_bss_info_arg {
540 struct wpa_driver_nl80211_data *drv;
541 struct wpa_scan_results *res;
542 unsigned int assoc_freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800543 u8 assoc_bssid[ETH_ALEN];
Jouni Malinen87fd2792011-05-16 18:35:42 +0300544};
545
546static int bss_info_handler(struct nl_msg *msg, void *arg);
547
548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549/* nl80211 code */
550static int ack_handler(struct nl_msg *msg, void *arg)
551{
552 int *err = arg;
553 *err = 0;
554 return NL_STOP;
555}
556
557static int finish_handler(struct nl_msg *msg, void *arg)
558{
559 int *ret = arg;
560 *ret = 0;
561 return NL_SKIP;
562}
563
564static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
565 void *arg)
566{
567 int *ret = arg;
568 *ret = err->error;
569 return NL_SKIP;
570}
571
572
573static int no_seq_check(struct nl_msg *msg, void *arg)
574{
575 return NL_OK;
576}
577
578
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800579static int send_and_recv(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580 struct nl_handle *nl_handle, struct nl_msg *msg,
581 int (*valid_handler)(struct nl_msg *, void *),
582 void *valid_data)
583{
584 struct nl_cb *cb;
585 int err = -ENOMEM;
586
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800587 cb = nl_cb_clone(global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700588 if (!cb)
589 goto out;
590
591 err = nl_send_auto_complete(nl_handle, msg);
592 if (err < 0)
593 goto out;
594
595 err = 1;
596
597 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
598 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
599 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
600
601 if (valid_handler)
602 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
603 valid_handler, valid_data);
604
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700605 while (err > 0) {
606 int res = nl_recvmsgs(nl_handle, cb);
607 if (res) {
608 wpa_printf(MSG_INFO,
609 "nl80211: %s->nl_recvmsgs failed: %d",
610 __func__, res);
611 }
612 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700613 out:
614 nl_cb_put(cb);
615 nlmsg_free(msg);
616 return err;
617}
618
619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800620static int send_and_recv_msgs_global(struct nl80211_global *global,
621 struct nl_msg *msg,
622 int (*valid_handler)(struct nl_msg *, void *),
623 void *valid_data)
624{
625 return send_and_recv(global, global->nl, msg, valid_handler,
626 valid_data);
627}
628
Dmitry Shmidt04949592012-07-19 12:16:46 -0700629
Dmitry Shmidt641185e2013-11-06 15:17:13 -0800630static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700631 struct nl_msg *msg,
632 int (*valid_handler)(struct nl_msg *, void *),
633 void *valid_data)
634{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800635 return send_and_recv(drv->global, drv->global->nl, msg,
636 valid_handler, valid_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637}
638
639
640struct family_data {
641 const char *group;
642 int id;
643};
644
645
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700646static int nl80211_set_iface_id(struct nl_msg *msg, struct i802_bss *bss)
647{
648 if (bss->wdev_id_set)
649 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
650 else
651 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
652 return 0;
653
654nla_put_failure:
655 return -1;
656}
657
658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700659static int family_handler(struct nl_msg *msg, void *arg)
660{
661 struct family_data *res = arg;
662 struct nlattr *tb[CTRL_ATTR_MAX + 1];
663 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
664 struct nlattr *mcgrp;
665 int i;
666
667 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
668 genlmsg_attrlen(gnlh, 0), NULL);
669 if (!tb[CTRL_ATTR_MCAST_GROUPS])
670 return NL_SKIP;
671
672 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
673 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
674 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
675 nla_len(mcgrp), NULL);
676 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
677 !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
678 os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
679 res->group,
680 nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
681 continue;
682 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
683 break;
684 };
685
686 return NL_SKIP;
687}
688
689
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800690static int nl_get_multicast_id(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691 const char *family, const char *group)
692{
693 struct nl_msg *msg;
694 int ret = -1;
695 struct family_data res = { group, -ENOENT };
696
697 msg = nlmsg_alloc();
698 if (!msg)
699 return -ENOMEM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800700 genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700701 0, 0, CTRL_CMD_GETFAMILY, 0);
702 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
703
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800704 ret = send_and_recv_msgs_global(global, msg, family_handler, &res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705 msg = NULL;
706 if (ret == 0)
707 ret = res.id;
708
709nla_put_failure:
710 nlmsg_free(msg);
711 return ret;
712}
713
714
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800715static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
716 struct nl_msg *msg, int flags, uint8_t cmd)
717{
718 return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
719 0, flags, cmd, 0);
720}
721
722
723struct wiphy_idx_data {
724 int wiphy_idx;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700725 enum nl80211_iftype nlmode;
726 u8 *macaddr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800727};
728
729
730static int netdev_info_handler(struct nl_msg *msg, void *arg)
731{
732 struct nlattr *tb[NL80211_ATTR_MAX + 1];
733 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
734 struct wiphy_idx_data *info = arg;
735
736 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
737 genlmsg_attrlen(gnlh, 0), NULL);
738
739 if (tb[NL80211_ATTR_WIPHY])
740 info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
741
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700742 if (tb[NL80211_ATTR_IFTYPE])
743 info->nlmode = nla_get_u32(tb[NL80211_ATTR_IFTYPE]);
744
745 if (tb[NL80211_ATTR_MAC] && info->macaddr)
746 os_memcpy(info->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
747 ETH_ALEN);
748
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800749 return NL_SKIP;
750}
751
752
753static int nl80211_get_wiphy_index(struct i802_bss *bss)
754{
755 struct nl_msg *msg;
756 struct wiphy_idx_data data = {
757 .wiphy_idx = -1,
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700758 .macaddr = NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800759 };
760
761 msg = nlmsg_alloc();
762 if (!msg)
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700763 return NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800764
765 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
766
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700767 if (nl80211_set_iface_id(msg, bss) < 0)
768 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800769
770 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
771 return data.wiphy_idx;
772 msg = NULL;
773nla_put_failure:
774 nlmsg_free(msg);
775 return -1;
776}
777
778
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700779static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss)
780{
781 struct nl_msg *msg;
782 struct wiphy_idx_data data = {
783 .nlmode = NL80211_IFTYPE_UNSPECIFIED,
784 .macaddr = NULL,
785 };
786
787 msg = nlmsg_alloc();
788 if (!msg)
789 return -1;
790
791 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
792
793 if (nl80211_set_iface_id(msg, bss) < 0)
794 goto nla_put_failure;
795
796 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
797 return data.nlmode;
798 msg = NULL;
799nla_put_failure:
800 nlmsg_free(msg);
801 return NL80211_IFTYPE_UNSPECIFIED;
802}
803
804
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700805static int nl80211_get_macaddr(struct i802_bss *bss)
806{
807 struct nl_msg *msg;
808 struct wiphy_idx_data data = {
809 .macaddr = bss->addr,
810 };
811
812 msg = nlmsg_alloc();
813 if (!msg)
814 return NL80211_IFTYPE_UNSPECIFIED;
815
816 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
817 if (nl80211_set_iface_id(msg, bss) < 0)
818 goto nla_put_failure;
819
820 return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data);
821
822nla_put_failure:
823 nlmsg_free(msg);
824 return NL80211_IFTYPE_UNSPECIFIED;
825}
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700826
827
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800828static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
829 struct nl80211_wiphy_data *w)
830{
831 struct nl_msg *msg;
832 int ret = -1;
833
834 msg = nlmsg_alloc();
835 if (!msg)
836 return -1;
837
838 nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS);
839
840 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx);
841
842 ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);
843 msg = NULL;
844 if (ret) {
845 wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
846 "failed: ret=%d (%s)",
847 ret, strerror(-ret));
848 goto nla_put_failure;
849 }
850 ret = 0;
851nla_put_failure:
852 nlmsg_free(msg);
853 return ret;
854}
855
856
857static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle)
858{
859 struct nl80211_wiphy_data *w = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700860 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800861
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800862 wpa_printf(MSG_EXCESSIVE, "nl80211: Beacon event message available");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800863
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700864 res = nl_recvmsgs(handle, w->nl_cb);
865 if (res) {
866 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
867 __func__, res);
868 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800869}
870
871
872static int process_beacon_event(struct nl_msg *msg, void *arg)
873{
874 struct nl80211_wiphy_data *w = arg;
875 struct wpa_driver_nl80211_data *drv;
876 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
877 struct nlattr *tb[NL80211_ATTR_MAX + 1];
878 union wpa_event_data event;
879
880 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
881 genlmsg_attrlen(gnlh, 0), NULL);
882
883 if (gnlh->cmd != NL80211_CMD_FRAME) {
884 wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)",
885 gnlh->cmd);
886 return NL_SKIP;
887 }
888
889 if (!tb[NL80211_ATTR_FRAME])
890 return NL_SKIP;
891
892 dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data,
893 wiphy_list) {
894 os_memset(&event, 0, sizeof(event));
895 event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);
896 event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);
897 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
898 }
899
900 return NL_SKIP;
901}
902
903
904static struct nl80211_wiphy_data *
905nl80211_get_wiphy_data_ap(struct i802_bss *bss)
906{
907 static DEFINE_DL_LIST(nl80211_wiphys);
908 struct nl80211_wiphy_data *w;
909 int wiphy_idx, found = 0;
910 struct i802_bss *tmp_bss;
911
912 if (bss->wiphy_data != NULL)
913 return bss->wiphy_data;
914
915 wiphy_idx = nl80211_get_wiphy_index(bss);
916
917 dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) {
918 if (w->wiphy_idx == wiphy_idx)
919 goto add;
920 }
921
922 /* alloc new one */
923 w = os_zalloc(sizeof(*w));
924 if (w == NULL)
925 return NULL;
926 w->wiphy_idx = wiphy_idx;
927 dl_list_init(&w->bsss);
928 dl_list_init(&w->drvs);
929
930 w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
931 if (!w->nl_cb) {
932 os_free(w);
933 return NULL;
934 }
935 nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
936 nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,
937 w);
938
939 w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
940 "wiphy beacons");
941 if (w->nl_beacons == NULL) {
942 os_free(w);
943 return NULL;
944 }
945
946 if (nl80211_register_beacons(bss->drv, w)) {
947 nl_destroy_handles(&w->nl_beacons);
948 os_free(w);
949 return NULL;
950 }
951
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700952 nl80211_register_eloop_read(&w->nl_beacons, nl80211_recv_beacons, w);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800953
954 dl_list_add(&nl80211_wiphys, &w->list);
955
956add:
957 /* drv entry for this bss already there? */
958 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
959 if (tmp_bss->drv == bss->drv) {
960 found = 1;
961 break;
962 }
963 }
964 /* if not add it */
965 if (!found)
966 dl_list_add(&w->drvs, &bss->drv->wiphy_list);
967
968 dl_list_add(&w->bsss, &bss->wiphy_list);
969 bss->wiphy_data = w;
970 return w;
971}
972
973
974static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
975{
976 struct nl80211_wiphy_data *w = bss->wiphy_data;
977 struct i802_bss *tmp_bss;
978 int found = 0;
979
980 if (w == NULL)
981 return;
982 bss->wiphy_data = NULL;
983 dl_list_del(&bss->wiphy_list);
984
985 /* still any for this drv present? */
986 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
987 if (tmp_bss->drv == bss->drv) {
988 found = 1;
989 break;
990 }
991 }
992 /* if not remove it */
993 if (!found)
994 dl_list_del(&bss->drv->wiphy_list);
995
996 if (!dl_list_empty(&w->bsss))
997 return;
998
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700999 nl80211_destroy_eloop_handle(&w->nl_beacons);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001000
1001 nl_cb_put(w->nl_cb);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001002 dl_list_del(&w->list);
1003 os_free(w);
1004}
1005
1006
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
1008{
1009 struct i802_bss *bss = priv;
1010 struct wpa_driver_nl80211_data *drv = bss->drv;
1011 if (!drv->associated)
1012 return -1;
1013 os_memcpy(bssid, drv->bssid, ETH_ALEN);
1014 return 0;
1015}
1016
1017
1018static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
1019{
1020 struct i802_bss *bss = priv;
1021 struct wpa_driver_nl80211_data *drv = bss->drv;
1022 if (!drv->associated)
1023 return -1;
1024 os_memcpy(ssid, drv->ssid, drv->ssid_len);
1025 return drv->ssid_len;
1026}
1027
1028
1029static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv,
1030 char *buf, size_t len, int del)
1031{
1032 union wpa_event_data event;
1033
1034 os_memset(&event, 0, sizeof(event));
1035 if (len > sizeof(event.interface_status.ifname))
1036 len = sizeof(event.interface_status.ifname) - 1;
1037 os_memcpy(event.interface_status.ifname, buf, len);
1038 event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
1039 EVENT_INTERFACE_ADDED;
1040
1041 wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
1042 del ? "DEL" : "NEW",
1043 event.interface_status.ifname,
1044 del ? "removed" : "added");
1045
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001046 if (os_strcmp(drv->first_bss->ifname, event.interface_status.ifname) ==
1047 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001048 if (del) {
1049 if (drv->if_removed) {
1050 wpa_printf(MSG_DEBUG, "nl80211: if_removed "
1051 "already set - ignore event");
1052 return;
1053 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001054 drv->if_removed = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001055 } else {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001056 if (if_nametoindex(drv->first_bss->ifname) == 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001057 wpa_printf(MSG_DEBUG, "nl80211: Interface %s "
1058 "does not exist - ignore "
1059 "RTM_NEWLINK",
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001060 drv->first_bss->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001061 return;
1062 }
1063 if (!drv->if_removed) {
1064 wpa_printf(MSG_DEBUG, "nl80211: if_removed "
1065 "already cleared - ignore event");
1066 return;
1067 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001068 drv->if_removed = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001069 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070 }
1071
1072 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
1073}
1074
1075
1076static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
1077 u8 *buf, size_t len)
1078{
1079 int attrlen, rta_len;
1080 struct rtattr *attr;
1081
1082 attrlen = len;
1083 attr = (struct rtattr *) buf;
1084
1085 rta_len = RTA_ALIGN(sizeof(struct rtattr));
1086 while (RTA_OK(attr, attrlen)) {
1087 if (attr->rta_type == IFLA_IFNAME) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001088 if (os_strcmp(((char *) attr) + rta_len,
1089 drv->first_bss->ifname) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090 return 1;
1091 else
1092 break;
1093 }
1094 attr = RTA_NEXT(attr, attrlen);
1095 }
1096
1097 return 0;
1098}
1099
1100
1101static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
1102 int ifindex, u8 *buf, size_t len)
1103{
1104 if (drv->ifindex == ifindex)
1105 return 1;
1106
1107 if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108 wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
1109 "interface");
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001110 wpa_driver_nl80211_finish_drv_init(drv, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111 return 1;
1112 }
1113
1114 return 0;
1115}
1116
1117
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001118static struct wpa_driver_nl80211_data *
1119nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
1120{
1121 struct wpa_driver_nl80211_data *drv;
1122 dl_list_for_each(drv, &global->interfaces,
1123 struct wpa_driver_nl80211_data, list) {
1124 if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
1125 have_ifidx(drv, idx))
1126 return drv;
1127 }
1128 return NULL;
1129}
1130
1131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
1133 struct ifinfomsg *ifi,
1134 u8 *buf, size_t len)
1135{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001136 struct nl80211_global *global = ctx;
1137 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 int attrlen, rta_len;
1139 struct rtattr *attr;
1140 u32 brid = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001141 char namebuf[IFNAMSIZ];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001143 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
1144 if (!drv) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001145 wpa_printf(MSG_DEBUG, "nl80211: Ignore event for foreign "
1146 "ifindex %d", ifi->ifi_index);
1147 return;
1148 }
1149
1150 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
1151 "(%s%s%s%s)",
1152 drv->operstate, ifi->ifi_flags,
1153 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
1154 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
1155 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
1156 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
1157
1158 if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001159 if (if_indextoname(ifi->ifi_index, namebuf) &&
1160 linux_iface_up(drv->global->ioctl_sock,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001161 drv->first_bss->ifname) > 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001162 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
1163 "event since interface %s is up", namebuf);
1164 return;
1165 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001166 wpa_printf(MSG_DEBUG, "nl80211: Interface down");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001167 if (drv->ignore_if_down_event) {
1168 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
1169 "event generated by mode change");
1170 drv->ignore_if_down_event = 0;
1171 } else {
1172 drv->if_disabled = 1;
1173 wpa_supplicant_event(drv->ctx,
1174 EVENT_INTERFACE_DISABLED, NULL);
1175 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001176 }
1177
1178 if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001179 if (if_indextoname(ifi->ifi_index, namebuf) &&
1180 linux_iface_up(drv->global->ioctl_sock,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001181 drv->first_bss->ifname) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001182 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1183 "event since interface %s is down",
1184 namebuf);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001185 } else if (if_nametoindex(drv->first_bss->ifname) == 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001186 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1187 "event since interface %s does not exist",
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001188 drv->first_bss->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001189 } else if (drv->if_removed) {
1190 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
1191 "event since interface %s is marked "
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001192 "removed", drv->first_bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001193 } else {
1194 wpa_printf(MSG_DEBUG, "nl80211: Interface up");
1195 drv->if_disabled = 0;
1196 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
1197 NULL);
1198 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001199 }
1200
1201 /*
1202 * Some drivers send the association event before the operup event--in
1203 * this case, lifting operstate in wpa_driver_nl80211_set_operstate()
1204 * fails. This will hit us when wpa_supplicant does not need to do
1205 * IEEE 802.1X authentication
1206 */
1207 if (drv->operstate == 1 &&
1208 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
1209 !(ifi->ifi_flags & IFF_RUNNING))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001210 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001211 -1, IF_OPER_UP);
1212
1213 attrlen = len;
1214 attr = (struct rtattr *) buf;
1215 rta_len = RTA_ALIGN(sizeof(struct rtattr));
1216 while (RTA_OK(attr, attrlen)) {
1217 if (attr->rta_type == IFLA_IFNAME) {
1218 wpa_driver_nl80211_event_link(
1219 drv,
1220 ((char *) attr) + rta_len,
1221 attr->rta_len - rta_len, 0);
1222 } else if (attr->rta_type == IFLA_MASTER)
1223 brid = nla_get_u32((struct nlattr *) attr);
1224 attr = RTA_NEXT(attr, attrlen);
1225 }
1226
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001227 if (ifi->ifi_family == AF_BRIDGE && brid) {
1228 /* device has been added to bridge */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001229 if_indextoname(brid, namebuf);
1230 wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
1231 brid, namebuf);
1232 add_ifidx(drv, brid);
1233 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001234}
1235
1236
1237static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
1238 struct ifinfomsg *ifi,
1239 u8 *buf, size_t len)
1240{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001241 struct nl80211_global *global = ctx;
1242 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001243 int attrlen, rta_len;
1244 struct rtattr *attr;
1245 u32 brid = 0;
1246
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001247 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
1248 if (!drv) {
1249 wpa_printf(MSG_DEBUG, "nl80211: Ignore dellink event for "
1250 "foreign ifindex %d", ifi->ifi_index);
1251 return;
1252 }
1253
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001254 attrlen = len;
1255 attr = (struct rtattr *) buf;
1256
1257 rta_len = RTA_ALIGN(sizeof(struct rtattr));
1258 while (RTA_OK(attr, attrlen)) {
1259 if (attr->rta_type == IFLA_IFNAME) {
1260 wpa_driver_nl80211_event_link(
1261 drv,
1262 ((char *) attr) + rta_len,
1263 attr->rta_len - rta_len, 1);
1264 } else if (attr->rta_type == IFLA_MASTER)
1265 brid = nla_get_u32((struct nlattr *) attr);
1266 attr = RTA_NEXT(attr, attrlen);
1267 }
1268
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001269 if (ifi->ifi_family == AF_BRIDGE && brid) {
1270 /* device has been removed from bridge */
1271 char namebuf[IFNAMSIZ];
1272 if_indextoname(brid, namebuf);
1273 wpa_printf(MSG_DEBUG, "nl80211: Remove ifindex %u for bridge "
1274 "%s", brid, namebuf);
1275 del_ifidx(drv, brid);
1276 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001277}
1278
1279
1280static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
1281 const u8 *frame, size_t len)
1282{
1283 const struct ieee80211_mgmt *mgmt;
1284 union wpa_event_data event;
1285
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001286 wpa_printf(MSG_DEBUG, "nl80211: Authenticate event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001287 mgmt = (const struct ieee80211_mgmt *) frame;
1288 if (len < 24 + sizeof(mgmt->u.auth)) {
1289 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1290 "frame");
1291 return;
1292 }
1293
1294 os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001295 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296 os_memset(&event, 0, sizeof(event));
1297 os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
1298 event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001299 event.auth.auth_transaction =
1300 le_to_host16(mgmt->u.auth.auth_transaction);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001301 event.auth.status_code = le_to_host16(mgmt->u.auth.status_code);
1302 if (len > 24 + sizeof(mgmt->u.auth)) {
1303 event.auth.ies = mgmt->u.auth.variable;
1304 event.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);
1305 }
1306
1307 wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);
1308}
1309
1310
Jouni Malinen87fd2792011-05-16 18:35:42 +03001311static unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
1312{
1313 struct nl_msg *msg;
1314 int ret;
1315 struct nl80211_bss_info_arg arg;
1316
1317 os_memset(&arg, 0, sizeof(arg));
1318 msg = nlmsg_alloc();
1319 if (!msg)
1320 goto nla_put_failure;
1321
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001322 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Jouni Malinen87fd2792011-05-16 18:35:42 +03001323 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
1324
1325 arg.drv = drv;
1326 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
1327 msg = NULL;
1328 if (ret == 0) {
1329 wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
1330 "associated BSS from scan results: %u MHz",
1331 arg.assoc_freq);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07001332 if (arg.assoc_freq)
1333 drv->assoc_freq = arg.assoc_freq;
1334 return drv->assoc_freq;
Jouni Malinen87fd2792011-05-16 18:35:42 +03001335 }
1336 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
1337 "(%s)", ret, strerror(-ret));
1338nla_put_failure:
1339 nlmsg_free(msg);
1340 return drv->assoc_freq;
1341}
1342
1343
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
1345 const u8 *frame, size_t len)
1346{
1347 const struct ieee80211_mgmt *mgmt;
1348 union wpa_event_data event;
1349 u16 status;
1350
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001351 wpa_printf(MSG_DEBUG, "nl80211: Associate event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001352 mgmt = (const struct ieee80211_mgmt *) frame;
1353 if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
1354 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1355 "frame");
1356 return;
1357 }
1358
1359 status = le_to_host16(mgmt->u.assoc_resp.status_code);
1360 if (status != WLAN_STATUS_SUCCESS) {
1361 os_memset(&event, 0, sizeof(event));
1362 event.assoc_reject.bssid = mgmt->bssid;
1363 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
1364 event.assoc_reject.resp_ies =
1365 (u8 *) mgmt->u.assoc_resp.variable;
1366 event.assoc_reject.resp_ies_len =
1367 len - 24 - sizeof(mgmt->u.assoc_resp);
1368 }
1369 event.assoc_reject.status_code = status;
1370
1371 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
1372 return;
1373 }
1374
1375 drv->associated = 1;
1376 os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001377 os_memcpy(drv->prev_bssid, mgmt->sa, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001378
1379 os_memset(&event, 0, sizeof(event));
1380 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
1381 event.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;
1382 event.assoc_info.resp_ies_len =
1383 len - 24 - sizeof(mgmt->u.assoc_resp);
1384 }
1385
1386 event.assoc_info.freq = drv->assoc_freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001387
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001388 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
1389}
1390
1391
1392static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
1393 enum nl80211_commands cmd, struct nlattr *status,
1394 struct nlattr *addr, struct nlattr *req_ie,
1395 struct nlattr *resp_ie)
1396{
1397 union wpa_event_data event;
1398
1399 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
1400 /*
1401 * Avoid reporting two association events that would confuse
1402 * the core code.
1403 */
1404 wpa_printf(MSG_DEBUG, "nl80211: Ignore connect event (cmd=%d) "
1405 "when using userspace SME", cmd);
1406 return;
1407 }
1408
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001409 if (cmd == NL80211_CMD_CONNECT)
1410 wpa_printf(MSG_DEBUG, "nl80211: Connect event");
1411 else if (cmd == NL80211_CMD_ROAM)
1412 wpa_printf(MSG_DEBUG, "nl80211: Roam event");
1413
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414 os_memset(&event, 0, sizeof(event));
1415 if (cmd == NL80211_CMD_CONNECT &&
1416 nla_get_u16(status) != WLAN_STATUS_SUCCESS) {
1417 if (addr)
1418 event.assoc_reject.bssid = nla_data(addr);
1419 if (resp_ie) {
1420 event.assoc_reject.resp_ies = nla_data(resp_ie);
1421 event.assoc_reject.resp_ies_len = nla_len(resp_ie);
1422 }
1423 event.assoc_reject.status_code = nla_get_u16(status);
1424 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
1425 return;
1426 }
1427
1428 drv->associated = 1;
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001429 if (addr) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001430 os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001431 os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
1432 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001433
1434 if (req_ie) {
1435 event.assoc_info.req_ies = nla_data(req_ie);
1436 event.assoc_info.req_ies_len = nla_len(req_ie);
1437 }
1438 if (resp_ie) {
1439 event.assoc_info.resp_ies = nla_data(resp_ie);
1440 event.assoc_info.resp_ies_len = nla_len(resp_ie);
1441 }
1442
Jouni Malinen87fd2792011-05-16 18:35:42 +03001443 event.assoc_info.freq = nl80211_get_assoc_freq(drv);
1444
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
1446}
1447
1448
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001449static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001450 struct nlattr *reason, struct nlattr *addr,
1451 struct nlattr *by_ap)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001452{
1453 union wpa_event_data data;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001454 unsigned int locally_generated = by_ap == NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001455
1456 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
1457 /*
1458 * Avoid reporting two disassociation events that could
1459 * confuse the core code.
1460 */
1461 wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
1462 "event when using userspace SME");
1463 return;
1464 }
1465
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001466 if (drv->ignore_next_local_disconnect) {
1467 drv->ignore_next_local_disconnect = 0;
1468 if (locally_generated) {
1469 wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
1470 "event triggered during reassociation");
1471 return;
1472 }
1473 wpa_printf(MSG_WARNING, "nl80211: Was expecting local "
1474 "disconnect but got another disconnect "
1475 "event first");
1476 }
1477
1478 wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001479 nl80211_mark_disconnected(drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001480 os_memset(&data, 0, sizeof(data));
1481 if (reason)
Dmitry Shmidt04949592012-07-19 12:16:46 -07001482 data.deauth_info.reason_code = nla_get_u16(reason);
1483 data.deauth_info.locally_generated = by_ap == NULL;
1484 wpa_supplicant_event(drv->ctx, EVENT_DEAUTH, &data);
1485}
1486
1487
1488static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
1489 struct nlattr *freq, struct nlattr *type)
1490{
1491 union wpa_event_data data;
1492 int ht_enabled = 1;
1493 int chan_offset = 0;
1494
1495 wpa_printf(MSG_DEBUG, "nl80211: Channel switch event");
1496
1497 if (!freq || !type)
1498 return;
1499
1500 switch (nla_get_u32(type)) {
1501 case NL80211_CHAN_NO_HT:
1502 ht_enabled = 0;
1503 break;
1504 case NL80211_CHAN_HT20:
1505 break;
1506 case NL80211_CHAN_HT40PLUS:
1507 chan_offset = 1;
1508 break;
1509 case NL80211_CHAN_HT40MINUS:
1510 chan_offset = -1;
1511 break;
1512 }
1513
1514 data.ch_switch.freq = nla_get_u32(freq);
1515 data.ch_switch.ht_enabled = ht_enabled;
1516 data.ch_switch.ch_offset = chan_offset;
1517
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001518 drv->first_bss->freq = data.ch_switch.freq;
1519
Dmitry Shmidt04949592012-07-19 12:16:46 -07001520 wpa_supplicant_event(drv->ctx, EVENT_CH_SWITCH, &data);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001521}
1522
1523
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001524static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
1525 enum nl80211_commands cmd, struct nlattr *addr)
1526{
1527 union wpa_event_data event;
1528 enum wpa_event_type ev;
1529
1530 if (nla_len(addr) != ETH_ALEN)
1531 return;
1532
1533 wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR,
1534 cmd, MAC2STR((u8 *) nla_data(addr)));
1535
1536 if (cmd == NL80211_CMD_AUTHENTICATE)
1537 ev = EVENT_AUTH_TIMED_OUT;
1538 else if (cmd == NL80211_CMD_ASSOCIATE)
1539 ev = EVENT_ASSOC_TIMED_OUT;
1540 else
1541 return;
1542
1543 os_memset(&event, 0, sizeof(event));
1544 os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);
1545 wpa_supplicant_event(drv->ctx, ev, &event);
1546}
1547
1548
1549static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt04949592012-07-19 12:16:46 -07001550 struct nlattr *freq, struct nlattr *sig,
1551 const u8 *frame, size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552{
1553 const struct ieee80211_mgmt *mgmt;
1554 union wpa_event_data event;
1555 u16 fc, stype;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001556 int ssi_signal = 0;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001557 int rx_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001559 wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001560 mgmt = (const struct ieee80211_mgmt *) frame;
1561 if (len < 24) {
1562 wpa_printf(MSG_DEBUG, "nl80211: Too short action frame");
1563 return;
1564 }
1565
1566 fc = le_to_host16(mgmt->frame_control);
1567 stype = WLAN_FC_GET_STYPE(fc);
1568
Dmitry Shmidt04949592012-07-19 12:16:46 -07001569 if (sig)
1570 ssi_signal = (s32) nla_get_u32(sig);
1571
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001572 os_memset(&event, 0, sizeof(event));
1573 if (freq) {
1574 event.rx_action.freq = nla_get_u32(freq);
Dmitry Shmidt56052862013-10-04 10:23:25 -07001575 rx_freq = drv->last_mgmt_freq = event.rx_action.freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001576 }
Dmitry Shmidt56052862013-10-04 10:23:25 -07001577 wpa_printf(MSG_DEBUG,
1578 "nl80211: RX frame freq=%d ssi_signal=%d stype=%u len=%u",
1579 rx_freq, ssi_signal, stype, (unsigned int) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 if (stype == WLAN_FC_STYPE_ACTION) {
1581 event.rx_action.da = mgmt->da;
1582 event.rx_action.sa = mgmt->sa;
1583 event.rx_action.bssid = mgmt->bssid;
1584 event.rx_action.category = mgmt->u.action.category;
1585 event.rx_action.data = &mgmt->u.action.category + 1;
1586 event.rx_action.len = frame + len - event.rx_action.data;
1587 wpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event);
1588 } else {
1589 event.rx_mgmt.frame = frame;
1590 event.rx_mgmt.frame_len = len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001591 event.rx_mgmt.ssi_signal = ssi_signal;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001592 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
1593 }
1594}
1595
1596
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001597static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
1598 struct nlattr *cookie, const u8 *frame,
1599 size_t len, struct nlattr *ack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001600{
1601 union wpa_event_data event;
1602 const struct ieee80211_hdr *hdr;
1603 u16 fc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001605 wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001606 if (!is_ap_interface(drv->nlmode)) {
1607 u64 cookie_val;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001608
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001609 if (!cookie)
1610 return;
1611
1612 cookie_val = nla_get_u64(cookie);
1613 wpa_printf(MSG_DEBUG, "nl80211: Action TX status:"
1614 " cookie=0%llx%s (ack=%d)",
1615 (long long unsigned int) cookie_val,
1616 cookie_val == drv->send_action_cookie ?
1617 " (match)" : " (unknown)", ack != NULL);
1618 if (cookie_val != drv->send_action_cookie)
1619 return;
1620 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001621
1622 hdr = (const struct ieee80211_hdr *) frame;
1623 fc = le_to_host16(hdr->frame_control);
1624
1625 os_memset(&event, 0, sizeof(event));
1626 event.tx_status.type = WLAN_FC_GET_TYPE(fc);
1627 event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
1628 event.tx_status.dst = hdr->addr1;
1629 event.tx_status.data = frame;
1630 event.tx_status.data_len = len;
1631 event.tx_status.ack = ack != NULL;
1632 wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
1633}
1634
1635
1636static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
1637 enum wpa_event_type type,
1638 const u8 *frame, size_t len)
1639{
1640 const struct ieee80211_mgmt *mgmt;
1641 union wpa_event_data event;
1642 const u8 *bssid = NULL;
1643 u16 reason_code = 0;
1644
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001645 if (type == EVENT_DEAUTH)
1646 wpa_printf(MSG_DEBUG, "nl80211: Deauthenticate event");
1647 else
1648 wpa_printf(MSG_DEBUG, "nl80211: Disassociate event");
1649
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001650 mgmt = (const struct ieee80211_mgmt *) frame;
1651 if (len >= 24) {
1652 bssid = mgmt->bssid;
1653
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001654 if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
1655 !drv->associated &&
1656 os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
1657 os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
1658 os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
1659 /*
1660 * Avoid issues with some roaming cases where
1661 * disconnection event for the old AP may show up after
1662 * we have started connection with the new AP.
1663 */
1664 wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
1665 MAC2STR(bssid),
1666 MAC2STR(drv->auth_attempt_bssid));
1667 return;
1668 }
1669
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001670 if (drv->associated != 0 &&
1671 os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
1672 os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
1673 /*
1674 * We have presumably received this deauth as a
1675 * response to a clear_state_mismatch() outgoing
1676 * deauth. Don't let it take us offline!
1677 */
1678 wpa_printf(MSG_DEBUG, "nl80211: Deauth received "
1679 "from Unknown BSSID " MACSTR " -- ignoring",
1680 MAC2STR(bssid));
1681 return;
1682 }
1683 }
1684
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07001685 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001686 os_memset(&event, 0, sizeof(event));
1687
1688 /* Note: Same offset for Reason Code in both frame subtypes */
1689 if (len >= 24 + sizeof(mgmt->u.deauth))
1690 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1691
1692 if (type == EVENT_DISASSOC) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001693 event.disassoc_info.locally_generated =
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001694 !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001695 event.disassoc_info.addr = bssid;
1696 event.disassoc_info.reason_code = reason_code;
1697 if (frame + len > mgmt->u.disassoc.variable) {
1698 event.disassoc_info.ie = mgmt->u.disassoc.variable;
1699 event.disassoc_info.ie_len = frame + len -
1700 mgmt->u.disassoc.variable;
1701 }
1702 } else {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001703 event.deauth_info.locally_generated =
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001704 !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001705 event.deauth_info.addr = bssid;
1706 event.deauth_info.reason_code = reason_code;
1707 if (frame + len > mgmt->u.deauth.variable) {
1708 event.deauth_info.ie = mgmt->u.deauth.variable;
1709 event.deauth_info.ie_len = frame + len -
1710 mgmt->u.deauth.variable;
1711 }
1712 }
1713
1714 wpa_supplicant_event(drv->ctx, type, &event);
1715}
1716
1717
1718static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv,
1719 enum wpa_event_type type,
1720 const u8 *frame, size_t len)
1721{
1722 const struct ieee80211_mgmt *mgmt;
1723 union wpa_event_data event;
1724 u16 reason_code = 0;
1725
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001726 if (type == EVENT_UNPROT_DEAUTH)
1727 wpa_printf(MSG_DEBUG, "nl80211: Unprot Deauthenticate event");
1728 else
1729 wpa_printf(MSG_DEBUG, "nl80211: Unprot Disassociate event");
1730
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001731 if (len < 24)
1732 return;
1733
1734 mgmt = (const struct ieee80211_mgmt *) frame;
1735
1736 os_memset(&event, 0, sizeof(event));
1737 /* Note: Same offset for Reason Code in both frame subtypes */
1738 if (len >= 24 + sizeof(mgmt->u.deauth))
1739 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1740
1741 if (type == EVENT_UNPROT_DISASSOC) {
1742 event.unprot_disassoc.sa = mgmt->sa;
1743 event.unprot_disassoc.da = mgmt->da;
1744 event.unprot_disassoc.reason_code = reason_code;
1745 } else {
1746 event.unprot_deauth.sa = mgmt->sa;
1747 event.unprot_deauth.da = mgmt->da;
1748 event.unprot_deauth.reason_code = reason_code;
1749 }
1750
1751 wpa_supplicant_event(drv->ctx, type, &event);
1752}
1753
1754
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001755static void mlme_event(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001756 enum nl80211_commands cmd, struct nlattr *frame,
1757 struct nlattr *addr, struct nlattr *timed_out,
1758 struct nlattr *freq, struct nlattr *ack,
Dmitry Shmidt04949592012-07-19 12:16:46 -07001759 struct nlattr *cookie, struct nlattr *sig)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760{
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001761 struct wpa_driver_nl80211_data *drv = bss->drv;
1762 const u8 *data;
1763 size_t len;
1764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001765 if (timed_out && addr) {
1766 mlme_timeout_event(drv, cmd, addr);
1767 return;
1768 }
1769
1770 if (frame == NULL) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001771 wpa_printf(MSG_DEBUG,
1772 "nl80211: MLME event %d (%s) without frame data",
1773 cmd, nl80211_command_to_string(cmd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001774 return;
1775 }
1776
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001777 data = nla_data(frame);
1778 len = nla_len(frame);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001779 if (len < 4 + 2 * ETH_ALEN) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001780 wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s("
1781 MACSTR ") - too short",
1782 cmd, nl80211_command_to_string(cmd), bss->ifname,
1783 MAC2STR(bss->addr));
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001784 return;
1785 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001786 wpa_printf(MSG_MSGDUMP, "nl80211: MLME event %d (%s) on %s(" MACSTR
1787 ") A1=" MACSTR " A2=" MACSTR, cmd,
1788 nl80211_command_to_string(cmd), bss->ifname,
1789 MAC2STR(bss->addr), MAC2STR(data + 4),
1790 MAC2STR(data + 4 + ETH_ALEN));
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001791 if (cmd != NL80211_CMD_FRAME_TX_STATUS && !(data[4] & 0x01) &&
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001792 os_memcmp(bss->addr, data + 4, ETH_ALEN) != 0 &&
1793 os_memcmp(bss->addr, data + 4 + ETH_ALEN, ETH_ALEN) != 0) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001794 wpa_printf(MSG_MSGDUMP, "nl80211: %s: Ignore MLME frame event "
1795 "for foreign address", bss->ifname);
1796 return;
1797 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001798 wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame",
1799 nla_data(frame), nla_len(frame));
1800
1801 switch (cmd) {
1802 case NL80211_CMD_AUTHENTICATE:
1803 mlme_event_auth(drv, nla_data(frame), nla_len(frame));
1804 break;
1805 case NL80211_CMD_ASSOCIATE:
1806 mlme_event_assoc(drv, nla_data(frame), nla_len(frame));
1807 break;
1808 case NL80211_CMD_DEAUTHENTICATE:
1809 mlme_event_deauth_disassoc(drv, EVENT_DEAUTH,
1810 nla_data(frame), nla_len(frame));
1811 break;
1812 case NL80211_CMD_DISASSOCIATE:
1813 mlme_event_deauth_disassoc(drv, EVENT_DISASSOC,
1814 nla_data(frame), nla_len(frame));
1815 break;
1816 case NL80211_CMD_FRAME:
Dmitry Shmidt04949592012-07-19 12:16:46 -07001817 mlme_event_mgmt(drv, freq, sig, nla_data(frame),
1818 nla_len(frame));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819 break;
1820 case NL80211_CMD_FRAME_TX_STATUS:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001821 mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
1822 nla_len(frame), ack);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823 break;
1824 case NL80211_CMD_UNPROT_DEAUTHENTICATE:
1825 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,
1826 nla_data(frame), nla_len(frame));
1827 break;
1828 case NL80211_CMD_UNPROT_DISASSOCIATE:
1829 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,
1830 nla_data(frame), nla_len(frame));
1831 break;
1832 default:
1833 break;
1834 }
1835}
1836
1837
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001838static void mlme_event_michael_mic_failure(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001839 struct nlattr *tb[])
1840{
1841 union wpa_event_data data;
1842
1843 wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure");
1844 os_memset(&data, 0, sizeof(data));
1845 if (tb[NL80211_ATTR_MAC]) {
1846 wpa_hexdump(MSG_DEBUG, "nl80211: Source MAC address",
1847 nla_data(tb[NL80211_ATTR_MAC]),
1848 nla_len(tb[NL80211_ATTR_MAC]));
1849 data.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);
1850 }
1851 if (tb[NL80211_ATTR_KEY_SEQ]) {
1852 wpa_hexdump(MSG_DEBUG, "nl80211: TSC",
1853 nla_data(tb[NL80211_ATTR_KEY_SEQ]),
1854 nla_len(tb[NL80211_ATTR_KEY_SEQ]));
1855 }
1856 if (tb[NL80211_ATTR_KEY_TYPE]) {
1857 enum nl80211_key_type key_type =
1858 nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);
1859 wpa_printf(MSG_DEBUG, "nl80211: Key Type %d", key_type);
1860 if (key_type == NL80211_KEYTYPE_PAIRWISE)
1861 data.michael_mic_failure.unicast = 1;
1862 } else
1863 data.michael_mic_failure.unicast = 1;
1864
1865 if (tb[NL80211_ATTR_KEY_IDX]) {
1866 u8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);
1867 wpa_printf(MSG_DEBUG, "nl80211: Key Id %d", key_id);
1868 }
1869
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001870 wpa_supplicant_event(bss->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001871}
1872
1873
1874static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
1875 struct nlattr *tb[])
1876{
1877 if (tb[NL80211_ATTR_MAC] == NULL) {
1878 wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
1879 "event");
1880 return;
1881 }
1882 os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07001883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001884 drv->associated = 1;
1885 wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined",
1886 MAC2STR(drv->bssid));
1887
1888 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1889}
1890
1891
1892static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
1893 int cancel_event, struct nlattr *tb[])
1894{
1895 unsigned int freq, chan_type, duration;
1896 union wpa_event_data data;
1897 u64 cookie;
1898
1899 if (tb[NL80211_ATTR_WIPHY_FREQ])
1900 freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
1901 else
1902 freq = 0;
1903
1904 if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
1905 chan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
1906 else
1907 chan_type = 0;
1908
1909 if (tb[NL80211_ATTR_DURATION])
1910 duration = nla_get_u32(tb[NL80211_ATTR_DURATION]);
1911 else
1912 duration = 0;
1913
1914 if (tb[NL80211_ATTR_COOKIE])
1915 cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
1916 else
1917 cookie = 0;
1918
1919 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel event (cancel=%d "
1920 "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))",
1921 cancel_event, freq, chan_type, duration,
1922 (long long unsigned int) cookie,
1923 cookie == drv->remain_on_chan_cookie ? "match" : "unknown");
1924
1925 if (cookie != drv->remain_on_chan_cookie)
1926 return; /* not for us */
1927
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001928 if (cancel_event)
1929 drv->pending_remain_on_chan = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001930
1931 os_memset(&data, 0, sizeof(data));
1932 data.remain_on_channel.freq = freq;
1933 data.remain_on_channel.duration = duration;
1934 wpa_supplicant_event(drv->ctx, cancel_event ?
1935 EVENT_CANCEL_REMAIN_ON_CHANNEL :
1936 EVENT_REMAIN_ON_CHANNEL, &data);
1937}
1938
1939
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001940static void mlme_event_ft_event(struct wpa_driver_nl80211_data *drv,
1941 struct nlattr *tb[])
1942{
1943 union wpa_event_data data;
1944
1945 os_memset(&data, 0, sizeof(data));
1946
1947 if (tb[NL80211_ATTR_IE]) {
1948 data.ft_ies.ies = nla_data(tb[NL80211_ATTR_IE]);
1949 data.ft_ies.ies_len = nla_len(tb[NL80211_ATTR_IE]);
1950 }
1951
1952 if (tb[NL80211_ATTR_IE_RIC]) {
1953 data.ft_ies.ric_ies = nla_data(tb[NL80211_ATTR_IE_RIC]);
1954 data.ft_ies.ric_ies_len = nla_len(tb[NL80211_ATTR_IE_RIC]);
1955 }
1956
1957 if (tb[NL80211_ATTR_MAC])
1958 os_memcpy(data.ft_ies.target_ap,
1959 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
1960
1961 wpa_printf(MSG_DEBUG, "nl80211: FT event target_ap " MACSTR,
1962 MAC2STR(data.ft_ies.target_ap));
1963
1964 wpa_supplicant_event(drv->ctx, EVENT_FT_RESPONSE, &data);
1965}
1966
1967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
1969 struct nlattr *tb[])
1970{
1971 union wpa_event_data event;
1972 struct nlattr *nl;
1973 int rem;
1974 struct scan_info *info;
1975#define MAX_REPORT_FREQS 50
1976 int freqs[MAX_REPORT_FREQS];
1977 int num_freqs = 0;
1978
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001979 if (drv->scan_for_auth) {
1980 drv->scan_for_auth = 0;
1981 wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
1982 "cfg80211 BSS entry");
1983 wpa_driver_nl80211_authenticate_retry(drv);
1984 return;
1985 }
1986
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001987 os_memset(&event, 0, sizeof(event));
1988 info = &event.scan_info;
1989 info->aborted = aborted;
1990
1991 if (tb[NL80211_ATTR_SCAN_SSIDS]) {
1992 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {
1993 struct wpa_driver_scan_ssid *s =
1994 &info->ssids[info->num_ssids];
1995 s->ssid = nla_data(nl);
1996 s->ssid_len = nla_len(nl);
1997 info->num_ssids++;
1998 if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
1999 break;
2000 }
2001 }
2002 if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
2003 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)
2004 {
2005 freqs[num_freqs] = nla_get_u32(nl);
2006 num_freqs++;
2007 if (num_freqs == MAX_REPORT_FREQS - 1)
2008 break;
2009 }
2010 info->freqs = freqs;
2011 info->num_freqs = num_freqs;
2012 }
2013 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
2014}
2015
2016
2017static int get_link_signal(struct nl_msg *msg, void *arg)
2018{
2019 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2020 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2021 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
2022 static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
2023 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002024 [NL80211_STA_INFO_SIGNAL_AVG] = { .type = NLA_U8 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002025 };
2026 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
2027 static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
2028 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
2029 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
2030 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
2031 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
2032 };
2033 struct wpa_signal_info *sig_change = arg;
2034
2035 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2036 genlmsg_attrlen(gnlh, 0), NULL);
2037 if (!tb[NL80211_ATTR_STA_INFO] ||
2038 nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
2039 tb[NL80211_ATTR_STA_INFO], policy))
2040 return NL_SKIP;
2041 if (!sinfo[NL80211_STA_INFO_SIGNAL])
2042 return NL_SKIP;
2043
2044 sig_change->current_signal =
2045 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
2046
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002047 if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
2048 sig_change->avg_signal =
2049 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
2050 else
2051 sig_change->avg_signal = 0;
2052
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
2054 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
2055 sinfo[NL80211_STA_INFO_TX_BITRATE],
2056 rate_policy)) {
2057 sig_change->current_txrate = 0;
2058 } else {
2059 if (rinfo[NL80211_RATE_INFO_BITRATE]) {
2060 sig_change->current_txrate =
2061 nla_get_u16(rinfo[
2062 NL80211_RATE_INFO_BITRATE]) * 100;
2063 }
2064 }
2065 }
2066
2067 return NL_SKIP;
2068}
2069
2070
2071static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
2072 struct wpa_signal_info *sig)
2073{
2074 struct nl_msg *msg;
2075
2076 sig->current_signal = -9999;
2077 sig->current_txrate = 0;
2078
2079 msg = nlmsg_alloc();
2080 if (!msg)
2081 return -ENOMEM;
2082
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002083 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002084
2085 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2086 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
2087
2088 return send_and_recv_msgs(drv, msg, get_link_signal, sig);
2089 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002090 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002091 return -ENOBUFS;
2092}
2093
2094
2095static int get_link_noise(struct nl_msg *msg, void *arg)
2096{
2097 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2098 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2099 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
2100 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
2101 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
2102 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
2103 };
2104 struct wpa_signal_info *sig_change = arg;
2105
2106 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2107 genlmsg_attrlen(gnlh, 0), NULL);
2108
2109 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
2110 wpa_printf(MSG_DEBUG, "nl80211: survey data missing!");
2111 return NL_SKIP;
2112 }
2113
2114 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
2115 tb[NL80211_ATTR_SURVEY_INFO],
2116 survey_policy)) {
2117 wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested "
2118 "attributes!");
2119 return NL_SKIP;
2120 }
2121
2122 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
2123 return NL_SKIP;
2124
2125 if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
2126 sig_change->frequency)
2127 return NL_SKIP;
2128
2129 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
2130 return NL_SKIP;
2131
2132 sig_change->current_noise =
2133 (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
2134
2135 return NL_SKIP;
2136}
2137
2138
2139static int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
2140 struct wpa_signal_info *sig_change)
2141{
2142 struct nl_msg *msg;
2143
2144 sig_change->current_noise = 9999;
2145 sig_change->frequency = drv->assoc_freq;
2146
2147 msg = nlmsg_alloc();
2148 if (!msg)
2149 return -ENOMEM;
2150
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002151 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152
2153 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2154
2155 return send_and_recv_msgs(drv, msg, get_link_noise, sig_change);
2156 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002157 nlmsg_free(msg);
2158 return -ENOBUFS;
2159}
2160
2161
2162static int get_noise_for_scan_results(struct nl_msg *msg, void *arg)
2163{
2164 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2165 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2166 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
2167 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
2168 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
2169 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
2170 };
2171 struct wpa_scan_results *scan_results = arg;
2172 struct wpa_scan_res *scan_res;
2173 size_t i;
2174
2175 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2176 genlmsg_attrlen(gnlh, 0), NULL);
2177
2178 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
2179 wpa_printf(MSG_DEBUG, "nl80211: Survey data missing");
2180 return NL_SKIP;
2181 }
2182
2183 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
2184 tb[NL80211_ATTR_SURVEY_INFO],
2185 survey_policy)) {
2186 wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested "
2187 "attributes");
2188 return NL_SKIP;
2189 }
2190
2191 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
2192 return NL_SKIP;
2193
2194 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
2195 return NL_SKIP;
2196
2197 for (i = 0; i < scan_results->num; ++i) {
2198 scan_res = scan_results->res[i];
2199 if (!scan_res)
2200 continue;
2201 if ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
2202 scan_res->freq)
2203 continue;
2204 if (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))
2205 continue;
2206 scan_res->noise = (s8)
2207 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
2208 scan_res->flags &= ~WPA_SCAN_NOISE_INVALID;
2209 }
2210
2211 return NL_SKIP;
2212}
2213
2214
2215static int nl80211_get_noise_for_scan_results(
2216 struct wpa_driver_nl80211_data *drv,
2217 struct wpa_scan_results *scan_res)
2218{
2219 struct nl_msg *msg;
2220
2221 msg = nlmsg_alloc();
2222 if (!msg)
2223 return -ENOMEM;
2224
2225 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
2226
2227 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
2228
2229 return send_and_recv_msgs(drv, msg, get_noise_for_scan_results,
2230 scan_res);
2231 nla_put_failure:
2232 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002233 return -ENOBUFS;
2234}
2235
2236
2237static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
2238 struct nlattr *tb[])
2239{
2240 static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
2241 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
2242 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
2243 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
2244 [NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },
2245 };
2246 struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
2247 enum nl80211_cqm_rssi_threshold_event event;
2248 union wpa_event_data ed;
2249 struct wpa_signal_info sig;
2250 int res;
2251
2252 if (tb[NL80211_ATTR_CQM] == NULL ||
2253 nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],
2254 cqm_policy)) {
2255 wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid CQM event");
2256 return;
2257 }
2258
2259 os_memset(&ed, 0, sizeof(ed));
2260
2261 if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {
2262 if (!tb[NL80211_ATTR_MAC])
2263 return;
2264 os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),
2265 ETH_ALEN);
2266 wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
2267 return;
2268 }
2269
2270 if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)
2271 return;
2272 event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
2273
2274 if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
2275 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
2276 "event: RSSI high");
2277 ed.signal_change.above_threshold = 1;
2278 } else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {
2279 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
2280 "event: RSSI low");
2281 ed.signal_change.above_threshold = 0;
2282 } else
2283 return;
2284
2285 res = nl80211_get_link_signal(drv, &sig);
2286 if (res == 0) {
2287 ed.signal_change.current_signal = sig.current_signal;
2288 ed.signal_change.current_txrate = sig.current_txrate;
2289 wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d",
2290 sig.current_signal, sig.current_txrate);
2291 }
2292
2293 res = nl80211_get_link_noise(drv, &sig);
2294 if (res == 0) {
2295 ed.signal_change.current_noise = sig.current_noise;
2296 wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm",
2297 sig.current_noise);
2298 }
2299
2300 wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);
2301}
2302
2303
2304static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
2305 struct nlattr **tb)
2306{
2307 u8 *addr;
2308 union wpa_event_data data;
2309
2310 if (tb[NL80211_ATTR_MAC] == NULL)
2311 return;
2312 addr = nla_data(tb[NL80211_ATTR_MAC]);
2313 wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr));
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002314
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002315 if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002316 u8 *ies = NULL;
2317 size_t ies_len = 0;
2318 if (tb[NL80211_ATTR_IE]) {
2319 ies = nla_data(tb[NL80211_ATTR_IE]);
2320 ies_len = nla_len(tb[NL80211_ATTR_IE]);
2321 }
2322 wpa_hexdump(MSG_DEBUG, "nl80211: Assoc Req IEs", ies, ies_len);
2323 drv_event_assoc(drv->ctx, addr, ies, ies_len, 0);
2324 return;
2325 }
2326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002327 if (drv->nlmode != NL80211_IFTYPE_ADHOC)
2328 return;
2329
2330 os_memset(&data, 0, sizeof(data));
2331 os_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);
2332 wpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data);
2333}
2334
2335
2336static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
2337 struct nlattr **tb)
2338{
2339 u8 *addr;
2340 union wpa_event_data data;
2341
2342 if (tb[NL80211_ATTR_MAC] == NULL)
2343 return;
2344 addr = nla_data(tb[NL80211_ATTR_MAC]);
2345 wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR,
2346 MAC2STR(addr));
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002347
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002348 if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002349 drv_event_disassoc(drv->ctx, addr);
2350 return;
2351 }
2352
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002353 if (drv->nlmode != NL80211_IFTYPE_ADHOC)
2354 return;
2355
2356 os_memset(&data, 0, sizeof(data));
2357 os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);
2358 wpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);
2359}
2360
2361
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002362static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data *drv,
2363 struct nlattr **tb)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002364{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002365 struct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];
2366 static struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {
2367 [NL80211_REKEY_DATA_KEK] = {
2368 .minlen = NL80211_KEK_LEN,
2369 .maxlen = NL80211_KEK_LEN,
2370 },
2371 [NL80211_REKEY_DATA_KCK] = {
2372 .minlen = NL80211_KCK_LEN,
2373 .maxlen = NL80211_KCK_LEN,
2374 },
2375 [NL80211_REKEY_DATA_REPLAY_CTR] = {
2376 .minlen = NL80211_REPLAY_CTR_LEN,
2377 .maxlen = NL80211_REPLAY_CTR_LEN,
2378 },
2379 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380 union wpa_event_data data;
2381
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002382 if (!tb[NL80211_ATTR_MAC])
2383 return;
2384 if (!tb[NL80211_ATTR_REKEY_DATA])
2385 return;
2386 if (nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,
2387 tb[NL80211_ATTR_REKEY_DATA], rekey_policy))
2388 return;
2389 if (!rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])
2390 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002391
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002392 os_memset(&data, 0, sizeof(data));
2393 data.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);
2394 wpa_printf(MSG_DEBUG, "nl80211: Rekey offload event for BSSID " MACSTR,
2395 MAC2STR(data.driver_gtk_rekey.bssid));
2396 data.driver_gtk_rekey.replay_ctr =
2397 nla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);
2398 wpa_hexdump(MSG_DEBUG, "nl80211: Rekey offload - Replay Counter",
2399 data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);
2400 wpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);
2401}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002403
2404static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
2405 struct nlattr **tb)
2406{
2407 struct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];
2408 static struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {
2409 [NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },
2410 [NL80211_PMKSA_CANDIDATE_BSSID] = {
2411 .minlen = ETH_ALEN,
2412 .maxlen = ETH_ALEN,
2413 },
2414 [NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },
2415 };
2416 union wpa_event_data data;
2417
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002418 wpa_printf(MSG_DEBUG, "nl80211: PMKSA candidate event");
2419
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002420 if (!tb[NL80211_ATTR_PMKSA_CANDIDATE])
2421 return;
2422 if (nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,
2423 tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy))
2424 return;
2425 if (!cand[NL80211_PMKSA_CANDIDATE_INDEX] ||
2426 !cand[NL80211_PMKSA_CANDIDATE_BSSID])
2427 return;
2428
2429 os_memset(&data, 0, sizeof(data));
2430 os_memcpy(data.pmkid_candidate.bssid,
2431 nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);
2432 data.pmkid_candidate.index =
2433 nla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);
2434 data.pmkid_candidate.preauth =
2435 cand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;
2436 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
2437}
2438
2439
2440static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv,
2441 struct nlattr **tb)
2442{
2443 union wpa_event_data data;
2444
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002445 wpa_printf(MSG_DEBUG, "nl80211: Probe client event");
2446
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002447 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
2448 return;
2449
2450 os_memset(&data, 0, sizeof(data));
2451 os_memcpy(data.client_poll.addr,
2452 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2453
2454 wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
2455}
2456
2457
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002458static void nl80211_tdls_oper_event(struct wpa_driver_nl80211_data *drv,
2459 struct nlattr **tb)
2460{
2461 union wpa_event_data data;
2462
2463 wpa_printf(MSG_DEBUG, "nl80211: TDLS operation event");
2464
2465 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_TDLS_OPERATION])
2466 return;
2467
2468 os_memset(&data, 0, sizeof(data));
2469 os_memcpy(data.tdls.peer, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2470 switch (nla_get_u8(tb[NL80211_ATTR_TDLS_OPERATION])) {
2471 case NL80211_TDLS_SETUP:
2472 wpa_printf(MSG_DEBUG, "nl80211: TDLS setup request for peer "
2473 MACSTR, MAC2STR(data.tdls.peer));
2474 data.tdls.oper = TDLS_REQUEST_SETUP;
2475 break;
2476 case NL80211_TDLS_TEARDOWN:
2477 wpa_printf(MSG_DEBUG, "nl80211: TDLS teardown request for peer "
2478 MACSTR, MAC2STR(data.tdls.peer));
2479 data.tdls.oper = TDLS_REQUEST_TEARDOWN;
2480 break;
2481 default:
2482 wpa_printf(MSG_DEBUG, "nl80211: Unsupported TDLS operatione "
2483 "event");
2484 return;
2485 }
2486 if (tb[NL80211_ATTR_REASON_CODE]) {
2487 data.tdls.reason_code =
2488 nla_get_u16(tb[NL80211_ATTR_REASON_CODE]);
2489 }
2490
2491 wpa_supplicant_event(drv->ctx, EVENT_TDLS, &data);
2492}
2493
2494
Dmitry Shmidt5393a0f2013-08-08 11:23:34 -07002495static void nl80211_stop_ap(struct wpa_driver_nl80211_data *drv,
2496 struct nlattr **tb)
2497{
2498 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_UNAVAILABLE, NULL);
2499}
2500
2501
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002502static void nl80211_connect_failed_event(struct wpa_driver_nl80211_data *drv,
2503 struct nlattr **tb)
2504{
2505 union wpa_event_data data;
2506 u32 reason;
2507
2508 wpa_printf(MSG_DEBUG, "nl80211: Connect failed event");
2509
2510 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_CONN_FAILED_REASON])
2511 return;
2512
2513 os_memset(&data, 0, sizeof(data));
2514 os_memcpy(data.connect_failed_reason.addr,
2515 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2516
2517 reason = nla_get_u32(tb[NL80211_ATTR_CONN_FAILED_REASON]);
2518 switch (reason) {
2519 case NL80211_CONN_FAIL_MAX_CLIENTS:
2520 wpa_printf(MSG_DEBUG, "nl80211: Max client reached");
2521 data.connect_failed_reason.code = MAX_CLIENT_REACHED;
2522 break;
2523 case NL80211_CONN_FAIL_BLOCKED_CLIENT:
2524 wpa_printf(MSG_DEBUG, "nl80211: Blocked client " MACSTR
2525 " tried to connect",
2526 MAC2STR(data.connect_failed_reason.addr));
2527 data.connect_failed_reason.code = BLOCKED_CLIENT;
2528 break;
2529 default:
2530 wpa_printf(MSG_DEBUG, "nl8021l: Unknown connect failed reason "
2531 "%u", reason);
2532 return;
2533 }
2534
2535 wpa_supplicant_event(drv->ctx, EVENT_CONNECT_FAILED_REASON, &data);
2536}
2537
2538
Dmitry Shmidt051af732013-10-22 13:52:46 -07002539static enum chan_width convert2width(int width);
2540
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002541static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
2542 struct nlattr **tb)
2543{
2544 union wpa_event_data data;
2545 enum nl80211_radar_event event_type;
2546
2547 if (!tb[NL80211_ATTR_WIPHY_FREQ] || !tb[NL80211_ATTR_RADAR_EVENT])
2548 return;
2549
2550 os_memset(&data, 0, sizeof(data));
Dmitry Shmidt051af732013-10-22 13:52:46 -07002551 data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
2552 event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002553
Dmitry Shmidt051af732013-10-22 13:52:46 -07002554 /* Check HT params */
2555 if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
2556 data.dfs_event.ht_enabled = 1;
2557 data.dfs_event.chan_offset = 0;
2558
2559 switch (nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
2560 case NL80211_CHAN_NO_HT:
2561 data.dfs_event.ht_enabled = 0;
2562 break;
2563 case NL80211_CHAN_HT20:
2564 break;
2565 case NL80211_CHAN_HT40PLUS:
2566 data.dfs_event.chan_offset = 1;
2567 break;
2568 case NL80211_CHAN_HT40MINUS:
2569 data.dfs_event.chan_offset = -1;
2570 break;
2571 }
2572 }
2573
2574 /* Get VHT params */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002575 if (tb[NL80211_ATTR_CHANNEL_WIDTH])
2576 data.dfs_event.chan_width =
2577 convert2width(nla_get_u32(
2578 tb[NL80211_ATTR_CHANNEL_WIDTH]));
2579 if (tb[NL80211_ATTR_CENTER_FREQ1])
2580 data.dfs_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002581 if (tb[NL80211_ATTR_CENTER_FREQ2])
2582 data.dfs_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
2583
2584 wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
2585 data.dfs_event.freq, data.dfs_event.ht_enabled,
2586 data.dfs_event.chan_offset, data.dfs_event.chan_width,
2587 data.dfs_event.cf1, data.dfs_event.cf2);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002588
2589 switch (event_type) {
2590 case NL80211_RADAR_DETECTED:
2591 wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
2592 break;
2593 case NL80211_RADAR_CAC_FINISHED:
2594 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
2595 break;
2596 case NL80211_RADAR_CAC_ABORTED:
2597 wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
2598 break;
2599 case NL80211_RADAR_NOP_FINISHED:
2600 wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
2601 break;
2602 default:
2603 wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
2604 "received", event_type);
2605 break;
2606 }
2607}
2608
2609
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002610static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
2611 int wds)
2612{
2613 struct wpa_driver_nl80211_data *drv = bss->drv;
2614 union wpa_event_data event;
2615
2616 if (!tb[NL80211_ATTR_MAC])
2617 return;
2618
2619 os_memset(&event, 0, sizeof(event));
2620 event.rx_from_unknown.bssid = bss->addr;
2621 event.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]);
2622 event.rx_from_unknown.wds = wds;
2623
2624 wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
2625}
2626
2627
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002628static void do_process_drv_event(struct i802_bss *bss, int cmd,
2629 struct nlattr **tb)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002630{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002631 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002632 union wpa_event_data data;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002633
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002634 wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
2635 cmd, nl80211_command_to_string(cmd), bss->ifname);
2636
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002637 if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
2638 (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
2639 cmd == NL80211_CMD_SCAN_ABORTED)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002640 wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002641 drv->ap_scan_as_station);
2642 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 }
2644
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002645 switch (cmd) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 case NL80211_CMD_TRIGGER_SCAN:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002647 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002648 drv->scan_state = SCAN_STARTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002649 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002650 case NL80211_CMD_START_SCHED_SCAN:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002651 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002652 drv->scan_state = SCHED_SCAN_STARTED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002653 break;
2654 case NL80211_CMD_SCHED_SCAN_STOPPED:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002655 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002656 drv->scan_state = SCHED_SCAN_STOPPED;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002657 wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
2658 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 case NL80211_CMD_NEW_SCAN_RESULTS:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002660 wpa_dbg(drv->ctx, MSG_DEBUG,
2661 "nl80211: New scan results available");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002662 drv->scan_state = SCAN_COMPLETED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663 drv->scan_complete_events = 1;
2664 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
2665 drv->ctx);
2666 send_scan_event(drv, 0, tb);
2667 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002668 case NL80211_CMD_SCHED_SCAN_RESULTS:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002669 wpa_dbg(drv->ctx, MSG_DEBUG,
2670 "nl80211: New sched scan results available");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002671 drv->scan_state = SCHED_SCAN_RESULTS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002672 send_scan_event(drv, 0, tb);
2673 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674 case NL80211_CMD_SCAN_ABORTED:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002675 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
Dmitry Shmidt56052862013-10-04 10:23:25 -07002676 drv->scan_state = SCAN_ABORTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 /*
2678 * Need to indicate that scan results are available in order
2679 * not to make wpa_supplicant stop its scanning.
2680 */
2681 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
2682 drv->ctx);
2683 send_scan_event(drv, 1, tb);
2684 break;
2685 case NL80211_CMD_AUTHENTICATE:
2686 case NL80211_CMD_ASSOCIATE:
2687 case NL80211_CMD_DEAUTHENTICATE:
2688 case NL80211_CMD_DISASSOCIATE:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689 case NL80211_CMD_FRAME_TX_STATUS:
2690 case NL80211_CMD_UNPROT_DEAUTHENTICATE:
2691 case NL80211_CMD_UNPROT_DISASSOCIATE:
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002692 mlme_event(bss, cmd, tb[NL80211_ATTR_FRAME],
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
2694 tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
Dmitry Shmidt04949592012-07-19 12:16:46 -07002695 tb[NL80211_ATTR_COOKIE],
2696 tb[NL80211_ATTR_RX_SIGNAL_DBM]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002697 break;
2698 case NL80211_CMD_CONNECT:
2699 case NL80211_CMD_ROAM:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002700 mlme_event_connect(drv, cmd,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 tb[NL80211_ATTR_STATUS_CODE],
2702 tb[NL80211_ATTR_MAC],
2703 tb[NL80211_ATTR_REQ_IE],
2704 tb[NL80211_ATTR_RESP_IE]);
2705 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002706 case NL80211_CMD_CH_SWITCH_NOTIFY:
2707 mlme_event_ch_switch(drv, tb[NL80211_ATTR_WIPHY_FREQ],
2708 tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
2709 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002710 case NL80211_CMD_DISCONNECT:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002711 mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002712 tb[NL80211_ATTR_MAC],
2713 tb[NL80211_ATTR_DISCONNECTED_BY_AP]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 break;
2715 case NL80211_CMD_MICHAEL_MIC_FAILURE:
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002716 mlme_event_michael_mic_failure(bss, tb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717 break;
2718 case NL80211_CMD_JOIN_IBSS:
2719 mlme_event_join_ibss(drv, tb);
2720 break;
2721 case NL80211_CMD_REMAIN_ON_CHANNEL:
2722 mlme_event_remain_on_channel(drv, 0, tb);
2723 break;
2724 case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:
2725 mlme_event_remain_on_channel(drv, 1, tb);
2726 break;
2727 case NL80211_CMD_NOTIFY_CQM:
2728 nl80211_cqm_event(drv, tb);
2729 break;
2730 case NL80211_CMD_REG_CHANGE:
2731 wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002732 if (tb[NL80211_ATTR_REG_INITIATOR] == NULL)
2733 break;
2734 os_memset(&data, 0, sizeof(data));
2735 switch (nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])) {
2736 case NL80211_REGDOM_SET_BY_CORE:
2737 data.channel_list_changed.initiator =
2738 REGDOM_SET_BY_CORE;
2739 break;
2740 case NL80211_REGDOM_SET_BY_USER:
2741 data.channel_list_changed.initiator =
2742 REGDOM_SET_BY_USER;
2743 break;
2744 case NL80211_REGDOM_SET_BY_DRIVER:
2745 data.channel_list_changed.initiator =
2746 REGDOM_SET_BY_DRIVER;
2747 break;
2748 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
2749 data.channel_list_changed.initiator =
2750 REGDOM_SET_BY_COUNTRY_IE;
2751 break;
2752 default:
2753 wpa_printf(MSG_DEBUG, "nl80211: Unknown reg change initiator %d received",
2754 nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]));
2755 break;
2756 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002758 &data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002759 break;
2760 case NL80211_CMD_REG_BEACON_HINT:
2761 wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint");
2762 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
2763 NULL);
2764 break;
2765 case NL80211_CMD_NEW_STATION:
2766 nl80211_new_station_event(drv, tb);
2767 break;
2768 case NL80211_CMD_DEL_STATION:
2769 nl80211_del_station_event(drv, tb);
2770 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002771 case NL80211_CMD_SET_REKEY_OFFLOAD:
2772 nl80211_rekey_offload_event(drv, tb);
2773 break;
2774 case NL80211_CMD_PMKSA_CANDIDATE:
2775 nl80211_pmksa_candidate_event(drv, tb);
2776 break;
2777 case NL80211_CMD_PROBE_CLIENT:
2778 nl80211_client_probe_event(drv, tb);
2779 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002780 case NL80211_CMD_TDLS_OPER:
2781 nl80211_tdls_oper_event(drv, tb);
2782 break;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002783 case NL80211_CMD_CONN_FAILED:
2784 nl80211_connect_failed_event(drv, tb);
2785 break;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002786 case NL80211_CMD_FT_EVENT:
2787 mlme_event_ft_event(drv, tb);
2788 break;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002789 case NL80211_CMD_RADAR_DETECT:
2790 nl80211_radar_event(drv, tb);
2791 break;
Dmitry Shmidt5393a0f2013-08-08 11:23:34 -07002792 case NL80211_CMD_STOP_AP:
2793 nl80211_stop_ap(drv, tb);
2794 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002795 default:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002796 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
2797 "(cmd=%d)", cmd);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002798 break;
2799 }
2800}
2801
2802
2803static int process_drv_event(struct nl_msg *msg, void *arg)
2804{
2805 struct wpa_driver_nl80211_data *drv = arg;
2806 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2807 struct nlattr *tb[NL80211_ATTR_MAX + 1];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002808 struct i802_bss *bss;
2809 int ifidx = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002810
2811 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2812 genlmsg_attrlen(gnlh, 0), NULL);
2813
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002814 if (tb[NL80211_ATTR_IFINDEX]) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002815 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
2816
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002817 for (bss = drv->first_bss; bss; bss = bss->next)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002818 if (ifidx == -1 || ifidx == bss->ifindex) {
2819 do_process_drv_event(bss, gnlh->cmd, tb);
2820 return NL_SKIP;
2821 }
2822 wpa_printf(MSG_DEBUG,
2823 "nl80211: Ignored event (cmd=%d) for foreign interface (ifindex %d)",
2824 gnlh->cmd, ifidx);
2825 } else if (tb[NL80211_ATTR_WDEV]) {
2826 u64 wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
2827 wpa_printf(MSG_DEBUG, "nl80211: Process event on P2P device");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002828 for (bss = drv->first_bss; bss; bss = bss->next) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002829 if (bss->wdev_id_set && wdev_id == bss->wdev_id) {
2830 do_process_drv_event(bss, gnlh->cmd, tb);
2831 return NL_SKIP;
2832 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002833 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002834 wpa_printf(MSG_DEBUG,
2835 "nl80211: Ignored event (cmd=%d) for foreign interface (wdev 0x%llx)",
2836 gnlh->cmd, (long long unsigned int) wdev_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002837 }
2838
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002839 return NL_SKIP;
2840}
2841
2842
2843static int process_global_event(struct nl_msg *msg, void *arg)
2844{
2845 struct nl80211_global *global = arg;
2846 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2847 struct nlattr *tb[NL80211_ATTR_MAX + 1];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002848 struct wpa_driver_nl80211_data *drv, *tmp;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002849 int ifidx = -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002850 struct i802_bss *bss;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002851 u64 wdev_id = 0;
2852 int wdev_id_set = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002853
2854 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2855 genlmsg_attrlen(gnlh, 0), NULL);
2856
2857 if (tb[NL80211_ATTR_IFINDEX])
2858 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002859 else if (tb[NL80211_ATTR_WDEV]) {
2860 wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
2861 wdev_id_set = 1;
2862 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002863
Dmitry Shmidt04949592012-07-19 12:16:46 -07002864 dl_list_for_each_safe(drv, tmp, &global->interfaces,
2865 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002866 for (bss = drv->first_bss; bss; bss = bss->next) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002867 if ((ifidx == -1 && !wdev_id_set) ||
2868 ifidx == bss->ifindex ||
2869 (wdev_id_set && bss->wdev_id_set &&
2870 wdev_id == bss->wdev_id)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002871 do_process_drv_event(bss, gnlh->cmd, tb);
2872 return NL_SKIP;
2873 }
2874 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002875 }
2876
2877 return NL_SKIP;
2878}
2879
2880
2881static int process_bss_event(struct nl_msg *msg, void *arg)
2882{
2883 struct i802_bss *bss = arg;
2884 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2885 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2886
2887 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2888 genlmsg_attrlen(gnlh, 0), NULL);
2889
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002890 wpa_printf(MSG_DEBUG, "nl80211: BSS Event %d (%s) received for %s",
2891 gnlh->cmd, nl80211_command_to_string(gnlh->cmd),
2892 bss->ifname);
2893
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002894 switch (gnlh->cmd) {
2895 case NL80211_CMD_FRAME:
2896 case NL80211_CMD_FRAME_TX_STATUS:
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002897 mlme_event(bss, gnlh->cmd, tb[NL80211_ATTR_FRAME],
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002898 tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
2899 tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
Dmitry Shmidt04949592012-07-19 12:16:46 -07002900 tb[NL80211_ATTR_COOKIE],
2901 tb[NL80211_ATTR_RX_SIGNAL_DBM]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002902 break;
2903 case NL80211_CMD_UNEXPECTED_FRAME:
2904 nl80211_spurious_frame(bss, tb, 0);
2905 break;
2906 case NL80211_CMD_UNEXPECTED_4ADDR_FRAME:
2907 nl80211_spurious_frame(bss, tb, 1);
2908 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002909 default:
2910 wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
2911 "(cmd=%d)", gnlh->cmd);
2912 break;
2913 }
2914
2915 return NL_SKIP;
2916}
2917
2918
2919static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
2920 void *handle)
2921{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002922 struct nl_cb *cb = eloop_ctx;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002923 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002925 wpa_printf(MSG_MSGDUMP, "nl80211: Event message available");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002926
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002927 res = nl_recvmsgs(handle, cb);
2928 if (res) {
2929 wpa_printf(MSG_INFO, "nl80211: %s->nl_recvmsgs failed: %d",
2930 __func__, res);
2931 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002932}
2933
2934
2935/**
2936 * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
2937 * @priv: driver_nl80211 private data
2938 * @alpha2_arg: country to which to switch to
2939 * Returns: 0 on success, -1 on failure
2940 *
2941 * This asks nl80211 to set the regulatory domain for given
2942 * country ISO / IEC alpha2.
2943 */
2944static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
2945{
2946 struct i802_bss *bss = priv;
2947 struct wpa_driver_nl80211_data *drv = bss->drv;
2948 char alpha2[3];
2949 struct nl_msg *msg;
2950
2951 msg = nlmsg_alloc();
2952 if (!msg)
2953 return -ENOMEM;
2954
2955 alpha2[0] = alpha2_arg[0];
2956 alpha2[1] = alpha2_arg[1];
2957 alpha2[2] = '\0';
2958
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002959 nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002960
2961 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
2962 if (send_and_recv_msgs(drv, msg, NULL, NULL))
2963 return -EINVAL;
2964 return 0;
2965nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002966 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002967 return -EINVAL;
2968}
2969
2970
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002971static int nl80211_get_country(struct nl_msg *msg, void *arg)
2972{
2973 char *alpha2 = arg;
2974 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
2975 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2976
2977 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2978 genlmsg_attrlen(gnlh, 0), NULL);
2979 if (!tb_msg[NL80211_ATTR_REG_ALPHA2]) {
2980 wpa_printf(MSG_DEBUG, "nl80211: No country information available");
2981 return NL_SKIP;
2982 }
2983 os_strlcpy(alpha2, nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]), 3);
2984 return NL_SKIP;
2985}
2986
2987
2988static int wpa_driver_nl80211_get_country(void *priv, char *alpha2)
2989{
2990 struct i802_bss *bss = priv;
2991 struct wpa_driver_nl80211_data *drv = bss->drv;
2992 struct nl_msg *msg;
2993 int ret;
2994
2995 msg = nlmsg_alloc();
2996 if (!msg)
2997 return -ENOMEM;
2998
2999 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
3000 alpha2[0] = '\0';
3001 ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2);
3002 if (!alpha2[0])
3003 ret = -1;
3004
3005 return ret;
3006}
3007
3008
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003009static int protocol_feature_handler(struct nl_msg *msg, void *arg)
3010{
3011 u32 *feat = arg;
3012 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
3013 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3014
3015 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3016 genlmsg_attrlen(gnlh, 0), NULL);
3017
3018 if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES])
3019 *feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]);
3020
3021 return NL_SKIP;
3022}
3023
3024
3025static u32 get_nl80211_protocol_features(struct wpa_driver_nl80211_data *drv)
3026{
3027 u32 feat = 0;
3028 struct nl_msg *msg;
3029
3030 msg = nlmsg_alloc();
3031 if (!msg)
3032 goto nla_put_failure;
3033
3034 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_PROTOCOL_FEATURES);
3035 if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat) == 0)
3036 return feat;
3037
3038 msg = NULL;
3039nla_put_failure:
3040 nlmsg_free(msg);
3041 return 0;
3042}
3043
3044
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003045struct wiphy_info_data {
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003046 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003047 struct wpa_driver_capa *capa;
3048
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003049 unsigned int num_multichan_concurrent;
3050
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003051 unsigned int error:1;
3052 unsigned int device_ap_sme:1;
3053 unsigned int poll_command_supported:1;
3054 unsigned int data_tx_status:1;
3055 unsigned int monitor_supported:1;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003056 unsigned int auth_supported:1;
3057 unsigned int connect_supported:1;
3058 unsigned int p2p_go_supported:1;
3059 unsigned int p2p_client_supported:1;
3060 unsigned int p2p_concurrent:1;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003061 unsigned int channel_switch_supported:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003062};
3063
3064
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003065static unsigned int probe_resp_offload_support(int supp_protocols)
3066{
3067 unsigned int prot = 0;
3068
3069 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS)
3070 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS;
3071 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)
3072 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2;
3073 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P)
3074 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P;
3075 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U)
3076 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING;
3077
3078 return prot;
3079}
3080
3081
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003082static void wiphy_info_supported_iftypes(struct wiphy_info_data *info,
3083 struct nlattr *tb)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003085 struct nlattr *nl_mode;
3086 int i;
3087
3088 if (tb == NULL)
3089 return;
3090
3091 nla_for_each_nested(nl_mode, tb, i) {
3092 switch (nla_type(nl_mode)) {
3093 case NL80211_IFTYPE_AP:
3094 info->capa->flags |= WPA_DRIVER_FLAGS_AP;
3095 break;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003096 case NL80211_IFTYPE_ADHOC:
3097 info->capa->flags |= WPA_DRIVER_FLAGS_IBSS;
3098 break;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003099 case NL80211_IFTYPE_P2P_DEVICE:
3100 info->capa->flags |=
3101 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
3102 break;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003103 case NL80211_IFTYPE_P2P_GO:
3104 info->p2p_go_supported = 1;
3105 break;
3106 case NL80211_IFTYPE_P2P_CLIENT:
3107 info->p2p_client_supported = 1;
3108 break;
3109 case NL80211_IFTYPE_MONITOR:
3110 info->monitor_supported = 1;
3111 break;
3112 }
3113 }
3114}
3115
3116
3117static int wiphy_info_iface_comb_process(struct wiphy_info_data *info,
3118 struct nlattr *nl_combi)
3119{
3120 struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
3121 struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
3122 struct nlattr *nl_limit, *nl_mode;
3123 int err, rem_limit, rem_mode;
3124 int combination_has_p2p = 0, combination_has_mgd = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003125 static struct nla_policy
3126 iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
3127 [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
3128 [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
3129 [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
3130 [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003131 [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003132 },
3133 iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
3134 [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
3135 [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
3136 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003137
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003138 err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
3139 nl_combi, iface_combination_policy);
3140 if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
3141 !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
3142 !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
3143 return 0; /* broken combination */
3144
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003145 if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS])
3146 info->capa->flags |= WPA_DRIVER_FLAGS_RADAR;
3147
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003148 nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS],
3149 rem_limit) {
3150 err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
3151 nl_limit, iface_limit_policy);
3152 if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES])
3153 return 0; /* broken combination */
3154
3155 nla_for_each_nested(nl_mode,
3156 tb_limit[NL80211_IFACE_LIMIT_TYPES],
3157 rem_mode) {
3158 int ift = nla_type(nl_mode);
3159 if (ift == NL80211_IFTYPE_P2P_GO ||
3160 ift == NL80211_IFTYPE_P2P_CLIENT)
3161 combination_has_p2p = 1;
3162 if (ift == NL80211_IFTYPE_STATION)
3163 combination_has_mgd = 1;
3164 }
3165 if (combination_has_p2p && combination_has_mgd)
3166 break;
3167 }
3168
3169 if (combination_has_p2p && combination_has_mgd) {
3170 info->p2p_concurrent = 1;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003171 info->num_multichan_concurrent =
3172 nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003173 return 1;
3174 }
3175
3176 return 0;
3177}
3178
3179
3180static void wiphy_info_iface_comb(struct wiphy_info_data *info,
3181 struct nlattr *tb)
3182{
3183 struct nlattr *nl_combi;
3184 int rem_combi;
3185
3186 if (tb == NULL)
3187 return;
3188
3189 nla_for_each_nested(nl_combi, tb, rem_combi) {
3190 if (wiphy_info_iface_comb_process(info, nl_combi) > 0)
3191 break;
3192 }
3193}
3194
3195
3196static void wiphy_info_supp_cmds(struct wiphy_info_data *info,
3197 struct nlattr *tb)
3198{
3199 struct nlattr *nl_cmd;
3200 int i;
3201
3202 if (tb == NULL)
3203 return;
3204
3205 nla_for_each_nested(nl_cmd, tb, i) {
3206 switch (nla_get_u32(nl_cmd)) {
3207 case NL80211_CMD_AUTHENTICATE:
3208 info->auth_supported = 1;
3209 break;
3210 case NL80211_CMD_CONNECT:
3211 info->connect_supported = 1;
3212 break;
3213 case NL80211_CMD_START_SCHED_SCAN:
3214 info->capa->sched_scan_supported = 1;
3215 break;
3216 case NL80211_CMD_PROBE_CLIENT:
3217 info->poll_command_supported = 1;
3218 break;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003219 case NL80211_CMD_CHANNEL_SWITCH:
3220 info->channel_switch_supported = 1;
3221 break;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003222 }
3223 }
3224}
3225
3226
3227static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
3228 struct nlattr *tb)
3229{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003230 if (tb)
3231 capa->max_remain_on_chan = nla_get_u32(tb);
3232}
3233
3234
3235static void wiphy_info_tdls(struct wpa_driver_capa *capa, struct nlattr *tdls,
3236 struct nlattr *ext_setup)
3237{
3238 if (tdls == NULL)
3239 return;
3240
3241 wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
3242 capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
3243
3244 if (ext_setup) {
3245 wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
3246 capa->flags |= WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
3247 }
3248}
3249
3250
3251static void wiphy_info_feature_flags(struct wiphy_info_data *info,
3252 struct nlattr *tb)
3253{
3254 u32 flags;
3255 struct wpa_driver_capa *capa = info->capa;
3256
3257 if (tb == NULL)
3258 return;
3259
3260 flags = nla_get_u32(tb);
3261
3262 if (flags & NL80211_FEATURE_SK_TX_STATUS)
3263 info->data_tx_status = 1;
3264
3265 if (flags & NL80211_FEATURE_INACTIVITY_TIMER)
3266 capa->flags |= WPA_DRIVER_FLAGS_INACTIVITY_TIMER;
3267
3268 if (flags & NL80211_FEATURE_SAE)
3269 capa->flags |= WPA_DRIVER_FLAGS_SAE;
3270
3271 if (flags & NL80211_FEATURE_NEED_OBSS_SCAN)
3272 capa->flags |= WPA_DRIVER_FLAGS_OBSS_SCAN;
3273}
3274
3275
3276static void wiphy_info_probe_resp_offload(struct wpa_driver_capa *capa,
3277 struct nlattr *tb)
3278{
3279 u32 protocols;
3280
3281 if (tb == NULL)
3282 return;
3283
3284 protocols = nla_get_u32(tb);
3285 wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response offload in AP "
3286 "mode");
3287 capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
3288 capa->probe_resp_offloads = probe_resp_offload_support(protocols);
3289}
3290
3291
3292static int wiphy_info_handler(struct nl_msg *msg, void *arg)
3293{
3294 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3295 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3296 struct wiphy_info_data *info = arg;
3297 struct wpa_driver_capa *capa = info->capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003298 struct wpa_driver_nl80211_data *drv = info->drv;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003299
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003300 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3301 genlmsg_attrlen(gnlh, 0), NULL);
3302
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003303 if (tb[NL80211_ATTR_WIPHY_NAME])
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003304 os_strlcpy(drv->phyname,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003305 nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
3306 sizeof(drv->phyname));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003307 if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003308 capa->max_scan_ssids =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003309 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
3310
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003311 if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])
3312 capa->max_sched_scan_ssids =
3313 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
3314
3315 if (tb[NL80211_ATTR_MAX_MATCH_SETS])
3316 capa->max_match_sets =
3317 nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
3318
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07003319 if (tb[NL80211_ATTR_MAC_ACL_MAX])
3320 capa->max_acl_mac_addrs =
3321 nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
3322
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003323 wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
3324 wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
3325 wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003326
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003327 if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
3328 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
3329 "off-channel TX");
3330 capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
3331 }
3332
3333 if (tb[NL80211_ATTR_ROAM_SUPPORT]) {
3334 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming");
3335 capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
3336 }
3337
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003338 wiphy_info_max_roc(capa,
3339 tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003340
3341 if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
3342 capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003343
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003344 wiphy_info_tdls(capa, tb[NL80211_ATTR_TDLS_SUPPORT],
3345 tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]);
Dmitry Shmidtad266fb2012-08-24 17:03:35 -07003346
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003347 if (tb[NL80211_ATTR_DEVICE_AP_SME])
3348 info->device_ap_sme = 1;
3349
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003350 wiphy_info_feature_flags(info, tb[NL80211_ATTR_FEATURE_FLAGS]);
3351 wiphy_info_probe_resp_offload(capa,
3352 tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003353
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003354 if (tb[NL80211_ATTR_EXT_CAPA] && tb[NL80211_ATTR_EXT_CAPA_MASK] &&
3355 drv->extended_capa == NULL) {
3356 drv->extended_capa =
3357 os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3358 if (drv->extended_capa) {
3359 os_memcpy(drv->extended_capa,
3360 nla_data(tb[NL80211_ATTR_EXT_CAPA]),
3361 nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3362 drv->extended_capa_len =
3363 nla_len(tb[NL80211_ATTR_EXT_CAPA]);
3364 }
3365 drv->extended_capa_mask =
3366 os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3367 if (drv->extended_capa_mask) {
3368 os_memcpy(drv->extended_capa_mask,
3369 nla_data(tb[NL80211_ATTR_EXT_CAPA]),
3370 nla_len(tb[NL80211_ATTR_EXT_CAPA]));
3371 } else {
3372 os_free(drv->extended_capa);
3373 drv->extended_capa = NULL;
3374 drv->extended_capa_len = 0;
3375 }
3376 }
3377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003378 return NL_SKIP;
3379}
3380
3381
3382static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
3383 struct wiphy_info_data *info)
3384{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003385 u32 feat;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003386 struct nl_msg *msg;
3387
3388 os_memset(info, 0, sizeof(*info));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003389 info->capa = &drv->capa;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003390 info->drv = drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003391
3392 msg = nlmsg_alloc();
3393 if (!msg)
3394 return -1;
3395
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003396 feat = get_nl80211_protocol_features(drv);
3397 if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
3398 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_WIPHY);
3399 else
3400 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003402 NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003403 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003404 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003405
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003406 if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info))
3407 return -1;
3408
3409 if (info->auth_supported)
3410 drv->capa.flags |= WPA_DRIVER_FLAGS_SME;
3411 else if (!info->connect_supported) {
3412 wpa_printf(MSG_INFO, "nl80211: Driver does not support "
3413 "authentication/association or connect commands");
3414 info->error = 1;
3415 }
3416
3417 if (info->p2p_go_supported && info->p2p_client_supported)
3418 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
3419 if (info->p2p_concurrent) {
3420 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
3421 "interface (driver advertised support)");
3422 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
3423 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
3424 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003425 if (info->num_multichan_concurrent > 1) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003426 wpa_printf(MSG_DEBUG, "nl80211: Enable multi-channel "
3427 "concurrent (driver advertised support)");
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003428 drv->capa.num_multichan_concurrent =
3429 info->num_multichan_concurrent;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003430 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003431
3432 /* default to 5000 since early versions of mac80211 don't set it */
3433 if (!drv->capa.max_remain_on_chan)
3434 drv->capa.max_remain_on_chan = 5000;
3435
Dmitry Shmidt2f023192013-03-12 12:44:17 -07003436 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003437nla_put_failure:
3438 nlmsg_free(msg);
3439 return -1;
3440}
3441
3442
3443static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
3444{
3445 struct wiphy_info_data info;
3446 if (wpa_driver_nl80211_get_info(drv, &info))
3447 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003448
3449 if (info.error)
3450 return -1;
3451
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003452 drv->has_capability = 1;
3453 /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */
3454 drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
3455 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
3456 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
3457 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
3458 drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 |
3459 WPA_DRIVER_CAPA_ENC_WEP104 |
3460 WPA_DRIVER_CAPA_ENC_TKIP |
3461 WPA_DRIVER_CAPA_ENC_CCMP;
3462 drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
3463 WPA_DRIVER_AUTH_SHARED |
3464 WPA_DRIVER_AUTH_LEAP;
3465
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466 drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
3467 drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468 drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
Dmitry Shmidtad266fb2012-08-24 17:03:35 -07003469
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003470 if (!info.device_ap_sme) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003471 drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003472
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003473 /*
3474 * No AP SME is currently assumed to also indicate no AP MLME
3475 * in the driver/firmware.
3476 */
3477 drv->capa.flags |= WPA_DRIVER_FLAGS_AP_MLME;
3478 }
3479
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003480 drv->device_ap_sme = info.device_ap_sme;
3481 drv->poll_command_supported = info.poll_command_supported;
3482 drv->data_tx_status = info.data_tx_status;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003483 drv->channel_switch_supported = info.channel_switch_supported;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003484
3485 /*
Dmitry Shmidtaa532512012-09-24 10:35:31 -07003486 * If poll command and tx status are supported, mac80211 is new enough
3487 * to have everything we need to not need monitor interfaces.
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003488 */
Dmitry Shmidtaa532512012-09-24 10:35:31 -07003489 drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003490
3491 if (drv->device_ap_sme && drv->use_monitor) {
3492 /*
3493 * Non-mac80211 drivers may not support monitor interface.
3494 * Make sure we do not get stuck with incorrect capability here
3495 * by explicitly testing this.
3496 */
3497 if (!info.monitor_supported) {
3498 wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor "
3499 "with device_ap_sme since no monitor mode "
3500 "support detected");
3501 drv->use_monitor = 0;
3502 }
3503 }
3504
3505 /*
3506 * If we aren't going to use monitor interfaces, but the
3507 * driver doesn't support data TX status, we won't get TX
3508 * status for EAPOL frames.
3509 */
3510 if (!drv->use_monitor && !info.data_tx_status)
3511 drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003512
3513 return 0;
3514}
3515
3516
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003517#ifdef ANDROID
3518static int android_genl_ctrl_resolve(struct nl_handle *handle,
3519 const char *name)
3520{
3521 /*
3522 * Android ICS has very minimal genl_ctrl_resolve() implementation, so
3523 * need to work around that.
3524 */
3525 struct nl_cache *cache = NULL;
3526 struct genl_family *nl80211 = NULL;
3527 int id = -1;
3528
3529 if (genl_ctrl_alloc_cache(handle, &cache) < 0) {
3530 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
3531 "netlink cache");
3532 goto fail;
3533 }
3534
3535 nl80211 = genl_ctrl_search_by_name(cache, name);
3536 if (nl80211 == NULL)
3537 goto fail;
3538
3539 id = genl_family_get_id(nl80211);
3540
3541fail:
3542 if (nl80211)
3543 genl_family_put(nl80211);
3544 if (cache)
3545 nl_cache_free(cache);
3546
3547 return id;
3548}
3549#define genl_ctrl_resolve android_genl_ctrl_resolve
3550#endif /* ANDROID */
3551
3552
3553static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554{
3555 int ret;
3556
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003557 global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
3558 if (global->nl_cb == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003559 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
3560 "callbacks");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003561 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562 }
3563
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003564 global->nl = nl_create_handle(global->nl_cb, "nl");
3565 if (global->nl == NULL)
3566 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003567
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003568 global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
3569 if (global->nl80211_id < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003570 wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
3571 "found");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003572 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003573 }
3574
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003575 global->nl_event = nl_create_handle(global->nl_cb, "event");
3576 if (global->nl_event == NULL)
3577 goto err;
3578
3579 ret = nl_get_multicast_id(global, "nl80211", "scan");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003580 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003581 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003582 if (ret < 0) {
3583 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
3584 "membership for scan events: %d (%s)",
3585 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003586 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587 }
3588
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003589 ret = nl_get_multicast_id(global, "nl80211", "mlme");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003590 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003591 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003592 if (ret < 0) {
3593 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
3594 "membership for mlme events: %d (%s)",
3595 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003596 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003597 }
3598
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003599 ret = nl_get_multicast_id(global, "nl80211", "regulatory");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003600 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003601 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003602 if (ret < 0) {
3603 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
3604 "membership for regulatory events: %d (%s)",
3605 ret, strerror(-ret));
3606 /* Continue without regulatory events */
3607 }
3608
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003609 nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
3610 no_seq_check, NULL);
3611 nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
3612 process_global_event, global);
3613
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003614 nl80211_register_eloop_read(&global->nl_event,
3615 wpa_driver_nl80211_event_receive,
3616 global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003617
3618 return 0;
3619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003620err:
3621 nl_destroy_handles(&global->nl_event);
3622 nl_destroy_handles(&global->nl);
3623 nl_cb_put(global->nl_cb);
3624 global->nl_cb = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003625 return -1;
3626}
3627
3628
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003629static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
3630{
3631 drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
3632 if (!drv->nl_cb) {
3633 wpa_printf(MSG_ERROR, "nl80211: Failed to alloc cb struct");
3634 return -1;
3635 }
3636
3637 nl_cb_set(drv->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
3638 no_seq_check, NULL);
3639 nl_cb_set(drv->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
3640 process_drv_event, drv);
3641
3642 return 0;
3643}
3644
3645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
3647{
3648 wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
3649 /*
3650 * This may be for any interface; use ifdown event to disable
3651 * interface.
3652 */
3653}
3654
3655
3656static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
3657{
3658 struct wpa_driver_nl80211_data *drv = ctx;
3659 wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003660 if (i802_set_iface_flags(drv->first_bss, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003661 wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
3662 "after rfkill unblock");
3663 return;
3664 }
3665 /* rtnetlink ifup handler will report interface as enabled */
3666}
3667
3668
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003669static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
3670 void *eloop_ctx,
3671 void *handle)
3672{
3673 struct wpa_driver_nl80211_data *drv = eloop_ctx;
3674 u8 data[2048];
3675 struct msghdr msg;
3676 struct iovec entry;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003677 u8 control[512];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003678 struct cmsghdr *cmsg;
3679 int res, found_ee = 0, found_wifi = 0, acked = 0;
3680 union wpa_event_data event;
3681
3682 memset(&msg, 0, sizeof(msg));
3683 msg.msg_iov = &entry;
3684 msg.msg_iovlen = 1;
3685 entry.iov_base = data;
3686 entry.iov_len = sizeof(data);
3687 msg.msg_control = &control;
3688 msg.msg_controllen = sizeof(control);
3689
3690 res = recvmsg(sock, &msg, MSG_ERRQUEUE);
3691 /* if error or not fitting 802.3 header, return */
3692 if (res < 14)
3693 return;
3694
3695 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
3696 {
3697 if (cmsg->cmsg_level == SOL_SOCKET &&
3698 cmsg->cmsg_type == SCM_WIFI_STATUS) {
3699 int *ack;
3700
3701 found_wifi = 1;
3702 ack = (void *)CMSG_DATA(cmsg);
3703 acked = *ack;
3704 }
3705
3706 if (cmsg->cmsg_level == SOL_PACKET &&
3707 cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
3708 struct sock_extended_err *err =
3709 (struct sock_extended_err *)CMSG_DATA(cmsg);
3710
3711 if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
3712 found_ee = 1;
3713 }
3714 }
3715
3716 if (!found_ee || !found_wifi)
3717 return;
3718
3719 memset(&event, 0, sizeof(event));
3720 event.eapol_tx_status.dst = data;
3721 event.eapol_tx_status.data = data + 14;
3722 event.eapol_tx_status.data_len = res - 14;
3723 event.eapol_tx_status.ack = acked;
3724 wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
3725}
3726
3727
3728static int nl80211_init_bss(struct i802_bss *bss)
3729{
3730 bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
3731 if (!bss->nl_cb)
3732 return -1;
3733
3734 nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
3735 no_seq_check, NULL);
3736 nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
3737 process_bss_event, bss);
3738
3739 return 0;
3740}
3741
3742
3743static void nl80211_destroy_bss(struct i802_bss *bss)
3744{
3745 nl_cb_put(bss->nl_cb);
3746 bss->nl_cb = NULL;
3747}
3748
3749
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003750static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
3751 void *global_priv, int hostapd,
3752 const u8 *set_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003753{
3754 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003755 struct rfkill_config *rcfg;
3756 struct i802_bss *bss;
3757
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003758 if (global_priv == NULL)
3759 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003760 drv = os_zalloc(sizeof(*drv));
3761 if (drv == NULL)
3762 return NULL;
3763 drv->global = global_priv;
3764 drv->ctx = ctx;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003765 drv->hostapd = !!hostapd;
3766 drv->eapol_sock = -1;
3767 drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
3768 drv->if_indices = drv->default_if_indices;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003769
3770 drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
3771 if (!drv->first_bss) {
3772 os_free(drv);
3773 return NULL;
3774 }
3775 bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003776 bss->drv = drv;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003777 bss->ctx = ctx;
3778
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003779 os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
3780 drv->monitor_ifidx = -1;
3781 drv->monitor_sock = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003782 drv->eapol_tx_sock = -1;
3783 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003784
3785 if (wpa_driver_nl80211_init_nl(drv)) {
3786 os_free(drv);
3787 return NULL;
3788 }
3789
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003790 if (nl80211_init_bss(bss))
3791 goto failed;
3792
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003793 rcfg = os_zalloc(sizeof(*rcfg));
3794 if (rcfg == NULL)
3795 goto failed;
3796 rcfg->ctx = drv;
3797 os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
3798 rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
3799 rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
3800 drv->rfkill = rfkill_init(rcfg);
3801 if (drv->rfkill == NULL) {
3802 wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
3803 os_free(rcfg);
3804 }
3805
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003806 if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0)
3807 drv->start_iface_up = 1;
3808
3809 if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003810 goto failed;
3811
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003812 drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
3813 if (drv->eapol_tx_sock < 0)
3814 goto failed;
3815
3816 if (drv->data_tx_status) {
3817 int enabled = 1;
3818
3819 if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
3820 &enabled, sizeof(enabled)) < 0) {
3821 wpa_printf(MSG_DEBUG,
3822 "nl80211: wifi status sockopt failed\n");
3823 drv->data_tx_status = 0;
3824 if (!drv->use_monitor)
3825 drv->capa.flags &=
3826 ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
3827 } else {
3828 eloop_register_read_sock(drv->eapol_tx_sock,
3829 wpa_driver_nl80211_handle_eapol_tx_status,
3830 drv, NULL);
3831 }
3832 }
3833
3834 if (drv->global) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003835 dl_list_add(&drv->global->interfaces, &drv->list);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003836 drv->in_interface_list = 1;
3837 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003838
3839 return bss;
3840
3841failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003842 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003843 return NULL;
3844}
3845
3846
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08003847/**
3848 * wpa_driver_nl80211_init - Initialize nl80211 driver interface
3849 * @ctx: context to be used when calling wpa_supplicant functions,
3850 * e.g., wpa_supplicant_event()
3851 * @ifname: interface name, e.g., wlan0
3852 * @global_priv: private driver global data from global_init()
3853 * Returns: Pointer to private data, %NULL on failure
3854 */
3855static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
3856 void *global_priv)
3857{
3858 return wpa_driver_nl80211_drv_init(ctx, ifname, global_priv, 0, NULL);
3859}
3860
3861
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003862static int nl80211_register_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003863 struct nl_handle *nl_handle,
3864 u16 type, const u8 *match, size_t match_len)
3865{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003866 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003867 struct nl_msg *msg;
3868 int ret = -1;
3869
3870 msg = nlmsg_alloc();
3871 if (!msg)
3872 return -1;
3873
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003874 wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x nl_handle=%p",
3875 type, nl_handle);
3876 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
3877 match, match_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003878
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003879 nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
3880
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003881 if (nl80211_set_iface_id(msg, bss) < 0)
3882 goto nla_put_failure;
3883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003884 NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
3885 NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);
3886
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003887 ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003888 msg = NULL;
3889 if (ret) {
3890 wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
3891 "failed (type=%u): ret=%d (%s)",
3892 type, ret, strerror(-ret));
3893 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
3894 match, match_len);
3895 goto nla_put_failure;
3896 }
3897 ret = 0;
3898nla_put_failure:
3899 nlmsg_free(msg);
3900 return ret;
3901}
3902
3903
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003904static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
3905{
3906 struct wpa_driver_nl80211_data *drv = bss->drv;
3907
3908 if (bss->nl_mgmt) {
3909 wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting "
3910 "already on! (nl_mgmt=%p)", bss->nl_mgmt);
3911 return -1;
3912 }
3913
3914 bss->nl_mgmt = nl_create_handle(drv->nl_cb, "mgmt");
3915 if (bss->nl_mgmt == NULL)
3916 return -1;
3917
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003918 return 0;
3919}
3920
3921
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003922static void nl80211_mgmt_handle_register_eloop(struct i802_bss *bss)
3923{
3924 nl80211_register_eloop_read(&bss->nl_mgmt,
3925 wpa_driver_nl80211_event_receive,
3926 bss->nl_cb);
3927}
3928
3929
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003930static int nl80211_register_action_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003931 const u8 *match, size_t match_len)
3932{
3933 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003934 return nl80211_register_frame(bss, bss->nl_mgmt,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003935 type, match, match_len);
3936}
3937
3938
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003939static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003941 struct wpa_driver_nl80211_data *drv = bss->drv;
3942
3943 if (nl80211_alloc_mgmt_handle(bss))
3944 return -1;
3945 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
3946 "handle %p", bss->nl_mgmt);
3947
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003948 if (drv->nlmode == NL80211_IFTYPE_ADHOC) {
3949 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4);
3950
3951 /* register for any AUTH message */
3952 nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0);
3953 }
3954
Dmitry Shmidt051af732013-10-22 13:52:46 -07003955#ifdef CONFIG_INTERWORKING
3956 /* QoS Map Configure */
3957 if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
3958 return -1;
3959#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003960#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003961 /* GAS Initial Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003962 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003963 return -1;
3964 /* GAS Initial Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003965 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003966 return -1;
3967 /* GAS Comeback Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003968 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003969 return -1;
3970 /* GAS Comeback Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003971 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003972 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003973#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
3974#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003975 /* P2P Public Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003976 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003977 (u8 *) "\x04\x09\x50\x6f\x9a\x09",
3978 6) < 0)
3979 return -1;
3980 /* P2P Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003981 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003982 (u8 *) "\x7f\x50\x6f\x9a\x09",
3983 5) < 0)
3984 return -1;
3985#endif /* CONFIG_P2P */
3986#ifdef CONFIG_IEEE80211W
3987 /* SA Query Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003988 if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003989 return -1;
3990#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003991#ifdef CONFIG_TDLS
3992 if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
3993 /* TDLS Discovery Response */
3994 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
3995 0)
3996 return -1;
3997 }
3998#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003999
4000 /* FT Action frames */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004001 if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004002 return -1;
4003 else
4004 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
4005 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
4006
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004007 /* WNM - BSS Transition Management Request */
4008 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
4009 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004010 /* WNM-Sleep Mode Response */
4011 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
4012 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004013
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004014 nl80211_mgmt_handle_register_eloop(bss);
4015
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004016 return 0;
4017}
4018
4019
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004020static int nl80211_register_spurious_class3(struct i802_bss *bss)
4021{
4022 struct wpa_driver_nl80211_data *drv = bss->drv;
4023 struct nl_msg *msg;
4024 int ret = -1;
4025
4026 msg = nlmsg_alloc();
4027 if (!msg)
4028 return -1;
4029
4030 nl80211_cmd(drv, msg, 0, NL80211_CMD_UNEXPECTED_FRAME);
4031
4032 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
4033
4034 ret = send_and_recv(drv->global, bss->nl_mgmt, msg, NULL, NULL);
4035 msg = NULL;
4036 if (ret) {
4037 wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
4038 "failed: ret=%d (%s)",
4039 ret, strerror(-ret));
4040 goto nla_put_failure;
4041 }
4042 ret = 0;
4043nla_put_failure:
4044 nlmsg_free(msg);
4045 return ret;
4046}
4047
4048
4049static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
4050{
4051 static const int stypes[] = {
4052 WLAN_FC_STYPE_AUTH,
4053 WLAN_FC_STYPE_ASSOC_REQ,
4054 WLAN_FC_STYPE_REASSOC_REQ,
4055 WLAN_FC_STYPE_DISASSOC,
4056 WLAN_FC_STYPE_DEAUTH,
4057 WLAN_FC_STYPE_ACTION,
4058 WLAN_FC_STYPE_PROBE_REQ,
4059/* Beacon doesn't work as mac80211 doesn't currently allow
4060 * it, but it wouldn't really be the right thing anyway as
4061 * it isn't per interface ... maybe just dump the scan
4062 * results periodically for OLBC?
4063 */
4064// WLAN_FC_STYPE_BEACON,
4065 };
4066 unsigned int i;
4067
4068 if (nl80211_alloc_mgmt_handle(bss))
4069 return -1;
4070 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
4071 "handle %p", bss->nl_mgmt);
4072
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004073 for (i = 0; i < ARRAY_SIZE(stypes); i++) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004074 if (nl80211_register_frame(bss, bss->nl_mgmt,
4075 (WLAN_FC_TYPE_MGMT << 2) |
4076 (stypes[i] << 4),
4077 NULL, 0) < 0) {
4078 goto out_err;
4079 }
4080 }
4081
4082 if (nl80211_register_spurious_class3(bss))
4083 goto out_err;
4084
4085 if (nl80211_get_wiphy_data_ap(bss) == NULL)
4086 goto out_err;
4087
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004088 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004089 return 0;
4090
4091out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004092 nl_destroy_handles(&bss->nl_mgmt);
4093 return -1;
4094}
4095
4096
4097static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)
4098{
4099 if (nl80211_alloc_mgmt_handle(bss))
4100 return -1;
4101 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
4102 "handle %p (device SME)", bss->nl_mgmt);
4103
4104 if (nl80211_register_frame(bss, bss->nl_mgmt,
4105 (WLAN_FC_TYPE_MGMT << 2) |
4106 (WLAN_FC_STYPE_ACTION << 4),
4107 NULL, 0) < 0)
4108 goto out_err;
4109
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004110 nl80211_mgmt_handle_register_eloop(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004111 return 0;
4112
4113out_err:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004114 nl_destroy_handles(&bss->nl_mgmt);
4115 return -1;
4116}
4117
4118
4119static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
4120{
4121 if (bss->nl_mgmt == NULL)
4122 return;
4123 wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
4124 "(%s)", bss->nl_mgmt, reason);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004125 nl80211_destroy_eloop_handle(&bss->nl_mgmt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004126
4127 nl80211_put_wiphy_data_ap(bss);
4128}
4129
4130
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004131static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
4132{
4133 wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
4134}
4135
4136
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004137static void nl80211_del_p2pdev(struct i802_bss *bss)
4138{
4139 struct wpa_driver_nl80211_data *drv = bss->drv;
4140 struct nl_msg *msg;
4141 int ret;
4142
4143 msg = nlmsg_alloc();
4144 if (!msg)
4145 return;
4146
4147 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
4148 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
4149
4150 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4151 msg = NULL;
4152
4153 wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s",
4154 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004155 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004156
4157nla_put_failure:
4158 nlmsg_free(msg);
4159}
4160
4161
4162static int nl80211_set_p2pdev(struct i802_bss *bss, int start)
4163{
4164 struct wpa_driver_nl80211_data *drv = bss->drv;
4165 struct nl_msg *msg;
4166 int ret = -1;
4167
4168 msg = nlmsg_alloc();
4169 if (!msg)
4170 return -1;
4171
4172 if (start)
4173 nl80211_cmd(drv, msg, 0, NL80211_CMD_START_P2P_DEVICE);
4174 else
4175 nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_P2P_DEVICE);
4176
4177 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, bss->wdev_id);
4178
4179 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4180 msg = NULL;
4181
4182 wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s",
4183 start ? "Start" : "Stop",
4184 bss->ifname, (long long unsigned int) bss->wdev_id,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004185 strerror(-ret));
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004186
4187nla_put_failure:
4188 nlmsg_free(msg);
4189 return ret;
4190}
4191
4192
4193static int i802_set_iface_flags(struct i802_bss *bss, int up)
4194{
4195 enum nl80211_iftype nlmode;
4196
4197 nlmode = nl80211_get_ifmode(bss);
4198 if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
4199 return linux_set_iface_flags(bss->drv->global->ioctl_sock,
4200 bss->ifname, up);
4201 }
4202
4203 /* P2P Device has start/stop which is equivalent */
4204 return nl80211_set_p2pdev(bss, up);
4205}
4206
4207
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004208static int
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004209wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
4210 const u8 *set_addr, int first)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004211{
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004212 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004213 int send_rfkill_event = 0;
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004214 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004215
4216 drv->ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004217 bss->ifindex = drv->ifindex;
4218 bss->wdev_id = drv->global->if_add_wdevid;
4219 bss->wdev_id_set = drv->global->if_add_wdevid_set;
4220
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004221 bss->if_dynamic = drv->ifindex == drv->global->if_add_ifindex;
4222 bss->if_dynamic = bss->if_dynamic || drv->global->if_add_wdevid_set;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004223 drv->global->if_add_wdevid_set = 0;
4224
4225 if (wpa_driver_nl80211_capa(drv))
4226 return -1;
4227
4228 wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
4229 bss->ifname, drv->phyname);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004230
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004231 if (set_addr &&
4232 (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) ||
4233 linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
4234 set_addr)))
4235 return -1;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004236
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004237 if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
4238 drv->start_mode_ap = 1;
4239
4240 if (drv->hostapd)
4241 nlmode = NL80211_IFTYPE_AP;
4242 else if (bss->if_dynamic)
4243 nlmode = nl80211_get_ifmode(bss);
4244 else
4245 nlmode = NL80211_IFTYPE_STATION;
4246
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004247 if (wpa_driver_nl80211_set_mode(bss, nlmode) < 0) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004248 wpa_printf(MSG_ERROR, "nl80211: Could not configure driver mode");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004249 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004250 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004251
4252 if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
4253 int ret = nl80211_set_p2pdev(bss, 1);
4254 if (ret < 0)
4255 wpa_printf(MSG_ERROR, "nl80211: Could not start P2P device");
4256 nl80211_get_macaddr(bss);
4257 return ret;
4258 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004259
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004260 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004261 if (rfkill_is_blocked(drv->rfkill)) {
4262 wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
4263 "interface '%s' due to rfkill",
4264 bss->ifname);
4265 drv->if_disabled = 1;
4266 send_rfkill_event = 1;
4267 } else {
4268 wpa_printf(MSG_ERROR, "nl80211: Could not set "
4269 "interface '%s' UP", bss->ifname);
4270 return -1;
4271 }
4272 }
4273
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004274 if (!drv->hostapd)
4275 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
4276 1, IF_OPER_DORMANT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004277
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004278 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
4279 bss->addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004280 return -1;
4281
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004282 if (send_rfkill_event) {
4283 eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
4284 drv, drv->ctx);
4285 }
4286
4287 return 0;
4288}
4289
4290
4291static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
4292{
4293 struct nl_msg *msg;
4294
4295 msg = nlmsg_alloc();
4296 if (!msg)
4297 return -ENOMEM;
4298
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004299 wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
4300 drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004301 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004302 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4303
4304 return send_and_recv_msgs(drv, msg, NULL, NULL);
4305 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004306 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004307 return -ENOBUFS;
4308}
4309
4310
4311/**
4312 * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004313 * @bss: Pointer to private nl80211 data from wpa_driver_nl80211_init()
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004314 *
4315 * Shut down driver interface and processing of driver events. Free
4316 * private data buffer if one was allocated in wpa_driver_nl80211_init().
4317 */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004318static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004319{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004320 struct wpa_driver_nl80211_data *drv = bss->drv;
4321
Dmitry Shmidt04949592012-07-19 12:16:46 -07004322 bss->in_deinit = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004323 if (drv->data_tx_status)
4324 eloop_unregister_read_sock(drv->eapol_tx_sock);
4325 if (drv->eapol_tx_sock >= 0)
4326 close(drv->eapol_tx_sock);
4327
4328 if (bss->nl_preq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004329 wpa_driver_nl80211_probe_req_report(bss, 0);
4330 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004331 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
4332 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004333 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
4334 "interface %s from bridge %s: %s",
4335 bss->ifname, bss->brname, strerror(errno));
4336 }
4337 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004338 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004339 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
4340 "bridge %s: %s",
4341 bss->brname, strerror(errno));
4342 }
4343
4344 nl80211_remove_monitor_interface(drv);
4345
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004346 if (is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004347 wpa_driver_nl80211_del_beacon(drv);
4348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004349 if (drv->eapol_sock >= 0) {
4350 eloop_unregister_read_sock(drv->eapol_sock);
4351 close(drv->eapol_sock);
4352 }
4353
4354 if (drv->if_indices != drv->default_if_indices)
4355 os_free(drv->if_indices);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004356
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004357 if (drv->disabled_11b_rates)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004358 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
4359
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004360 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
4361 IF_OPER_UP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004362 rfkill_deinit(drv->rfkill);
4363
4364 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
4365
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004366 if (!drv->start_iface_up)
4367 (void) i802_set_iface_flags(bss, 0);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004368 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004369 if (!drv->hostapd || !drv->start_mode_ap)
4370 wpa_driver_nl80211_set_mode(bss,
4371 NL80211_IFTYPE_STATION);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07004372 nl80211_mgmt_unsubscribe(bss, "deinit");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004373 } else {
4374 nl80211_mgmt_unsubscribe(bss, "deinit");
4375 nl80211_del_p2pdev(bss);
4376 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004377 nl_cb_put(drv->nl_cb);
4378
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004379 nl80211_destroy_bss(drv->first_bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004380
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004381 os_free(drv->filter_ssids);
4382
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004383 os_free(drv->auth_ie);
4384
4385 if (drv->in_interface_list)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004386 dl_list_del(&drv->list);
4387
Dmitry Shmidt444d5672013-04-01 13:08:44 -07004388 os_free(drv->extended_capa);
4389 os_free(drv->extended_capa_mask);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004390 os_free(drv->first_bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004391 os_free(drv);
4392}
4393
4394
4395/**
4396 * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion
4397 * @eloop_ctx: Driver private data
4398 * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init()
4399 *
4400 * This function can be used as registered timeout when starting a scan to
4401 * generate a scan completed event if the driver does not report this.
4402 */
4403static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
4404{
4405 struct wpa_driver_nl80211_data *drv = eloop_ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004406 if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004407 wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004408 drv->ap_scan_as_station);
4409 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004410 }
4411 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
4412 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
4413}
4414
4415
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004416static struct nl_msg *
4417nl80211_scan_common(struct wpa_driver_nl80211_data *drv, u8 cmd,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004418 struct wpa_driver_scan_params *params, u64 *wdev_id)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004419{
4420 struct nl_msg *msg;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004421 size_t i;
4422
4423 msg = nlmsg_alloc();
4424 if (!msg)
4425 return NULL;
4426
4427 nl80211_cmd(drv, msg, 0, cmd);
4428
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004429 if (!wdev_id)
4430 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4431 else
4432 NLA_PUT_U64(msg, NL80211_ATTR_WDEV, *wdev_id);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004433
4434 if (params->num_ssids) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004435 struct nlattr *ssids;
4436
4437 ssids = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004438 if (ssids == NULL)
4439 goto fail;
4440 for (i = 0; i < params->num_ssids; i++) {
4441 wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
4442 params->ssids[i].ssid,
4443 params->ssids[i].ssid_len);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004444 if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
4445 params->ssids[i].ssid) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004446 goto fail;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004447 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004448 nla_nest_end(msg, ssids);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004449 }
4450
4451 if (params->extra_ies) {
4452 wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
4453 params->extra_ies, params->extra_ies_len);
4454 if (nla_put(msg, NL80211_ATTR_IE, params->extra_ies_len,
4455 params->extra_ies) < 0)
4456 goto fail;
4457 }
4458
4459 if (params->freqs) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004460 struct nlattr *freqs;
4461 freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004462 if (freqs == NULL)
4463 goto fail;
4464 for (i = 0; params->freqs[i]; i++) {
4465 wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
4466 "MHz", params->freqs[i]);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004467 if (nla_put_u32(msg, i + 1, params->freqs[i]) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004468 goto fail;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004469 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004470 nla_nest_end(msg, freqs);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004471 }
4472
4473 os_free(drv->filter_ssids);
4474 drv->filter_ssids = params->filter_ssids;
4475 params->filter_ssids = NULL;
4476 drv->num_filter_ssids = params->num_filter_ssids;
4477
4478 return msg;
4479
4480fail:
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004481nla_put_failure:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004482 nlmsg_free(msg);
4483 return NULL;
4484}
4485
4486
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004487/**
4488 * wpa_driver_nl80211_scan - Request the driver to initiate scan
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004489 * @bss: Pointer to private driver data from wpa_driver_nl80211_init()
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004490 * @params: Scan parameters
4491 * Returns: 0 on success, -1 on failure
4492 */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004493static int wpa_driver_nl80211_scan(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004494 struct wpa_driver_scan_params *params)
4495{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004496 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004497 int ret = -1, timeout;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004498 struct nl_msg *msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004499
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004500 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004501 drv->scan_for_auth = 0;
4502
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004503 msg = nl80211_scan_common(drv, NL80211_CMD_TRIGGER_SCAN, params,
4504 bss->wdev_id_set ? &bss->wdev_id : NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004505 if (!msg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004506 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004507
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004508 if (params->p2p_probe) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004509 struct nlattr *rates;
4510
Dmitry Shmidt04949592012-07-19 12:16:46 -07004511 wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
4512
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004513 rates = nla_nest_start(msg, NL80211_ATTR_SCAN_SUPP_RATES);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004514 if (rates == NULL)
4515 goto nla_put_failure;
4516
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004517 /*
4518 * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
4519 * by masking out everything else apart from the OFDM rates 6,
4520 * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
4521 * rates are left enabled.
4522 */
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004523 NLA_PUT(msg, NL80211_BAND_2GHZ, 8,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004524 "\x0c\x12\x18\x24\x30\x48\x60\x6c");
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004525 nla_nest_end(msg, rates);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004526
4527 NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
4528 }
4529
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004530 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4531 msg = NULL;
4532 if (ret) {
4533 wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
4534 "(%s)", ret, strerror(-ret));
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08004535 if (drv->hostapd && is_ap_interface(drv->nlmode)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004536 /*
4537 * mac80211 does not allow scan requests in AP mode, so
4538 * try to do this in station mode.
4539 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004540 if (wpa_driver_nl80211_set_mode(
4541 bss, NL80211_IFTYPE_STATION))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004542 goto nla_put_failure;
4543
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004544 if (wpa_driver_nl80211_scan(bss, params)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004545 wpa_driver_nl80211_set_mode(bss, drv->nlmode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004546 goto nla_put_failure;
4547 }
4548
4549 /* Restore AP mode when processing scan results */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004550 drv->ap_scan_as_station = drv->nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004551 ret = 0;
4552 } else
4553 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004554 }
4555
Dmitry Shmidt56052862013-10-04 10:23:25 -07004556 drv->scan_state = SCAN_REQUESTED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557 /* Not all drivers generate "scan completed" wireless event, so try to
4558 * read results after a timeout. */
4559 timeout = 10;
4560 if (drv->scan_complete_events) {
4561 /*
4562 * The driver seems to deliver events to notify when scan is
4563 * complete, so use longer timeout to avoid race conditions
4564 * with scanning and following association request.
4565 */
4566 timeout = 30;
4567 }
4568 wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
4569 "seconds", ret, timeout);
4570 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
4571 eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
4572 drv, drv->ctx);
4573
4574nla_put_failure:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004575 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004576 return ret;
4577}
4578
4579
4580/**
4581 * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
4582 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
4583 * @params: Scan parameters
4584 * @interval: Interval between scan cycles in milliseconds
4585 * Returns: 0 on success, -1 on failure or if not supported
4586 */
4587static int wpa_driver_nl80211_sched_scan(void *priv,
4588 struct wpa_driver_scan_params *params,
4589 u32 interval)
4590{
4591 struct i802_bss *bss = priv;
4592 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004593 int ret = -1;
4594 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004595 size_t i;
4596
Dmitry Shmidt700a1372013-03-15 14:14:44 -07004597 wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: sched_scan request");
4598
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004599#ifdef ANDROID
4600 if (!drv->capa.sched_scan_supported)
4601 return android_pno_start(bss, params);
4602#endif /* ANDROID */
4603
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004604 msg = nl80211_scan_common(drv, NL80211_CMD_START_SCHED_SCAN, params,
4605 bss->wdev_id_set ? &bss->wdev_id : NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004606 if (!msg)
4607 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004608
4609 NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);
4610
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004611 if ((drv->num_filter_ssids &&
4612 (int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
4613 params->filter_rssi) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004614 struct nlattr *match_sets;
4615 match_sets = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004616 if (match_sets == NULL)
4617 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004618
4619 for (i = 0; i < drv->num_filter_ssids; i++) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004620 struct nlattr *match_set_ssid;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004621 wpa_hexdump_ascii(MSG_MSGDUMP,
4622 "nl80211: Sched scan filter SSID",
4623 drv->filter_ssids[i].ssid,
4624 drv->filter_ssids[i].ssid_len);
4625
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004626 match_set_ssid = nla_nest_start(msg, i + 1);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004627 if (match_set_ssid == NULL)
4628 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004629 NLA_PUT(msg, NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004630 drv->filter_ssids[i].ssid_len,
4631 drv->filter_ssids[i].ssid);
4632
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004633 nla_nest_end(msg, match_set_ssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004634 }
4635
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004636 if (params->filter_rssi) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004637 struct nlattr *match_set_rssi;
4638 match_set_rssi = nla_nest_start(msg, 0);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004639 if (match_set_rssi == NULL)
4640 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004641 NLA_PUT_U32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004642 params->filter_rssi);
4643 wpa_printf(MSG_MSGDUMP,
4644 "nl80211: Sched scan RSSI filter %d dBm",
4645 params->filter_rssi);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004646 nla_nest_end(msg, match_set_rssi);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004647 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004648
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004649 nla_nest_end(msg, match_sets);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004650 }
4651
4652 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4653
4654 /* TODO: if we get an error here, we should fall back to normal scan */
4655
4656 msg = NULL;
4657 if (ret) {
4658 wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: "
4659 "ret=%d (%s)", ret, strerror(-ret));
4660 goto nla_put_failure;
4661 }
4662
4663 wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) - "
4664 "scan interval %d msec", ret, interval);
4665
4666nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004667 nlmsg_free(msg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004668 return ret;
4669}
4670
4671
4672/**
4673 * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan
4674 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
4675 * Returns: 0 on success, -1 on failure or if not supported
4676 */
4677static int wpa_driver_nl80211_stop_sched_scan(void *priv)
4678{
4679 struct i802_bss *bss = priv;
4680 struct wpa_driver_nl80211_data *drv = bss->drv;
4681 int ret = 0;
4682 struct nl_msg *msg;
4683
4684#ifdef ANDROID
4685 if (!drv->capa.sched_scan_supported)
4686 return android_pno_stop(bss);
4687#endif /* ANDROID */
4688
4689 msg = nlmsg_alloc();
4690 if (!msg)
4691 return -1;
4692
4693 nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_SCHED_SCAN);
4694
4695 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4696
4697 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4698 msg = NULL;
4699 if (ret) {
4700 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop failed: "
4701 "ret=%d (%s)", ret, strerror(-ret));
4702 goto nla_put_failure;
4703 }
4704
4705 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop sent (ret=%d)", ret);
4706
4707nla_put_failure:
4708 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004709 return ret;
4710}
4711
4712
4713static const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
4714{
4715 const u8 *end, *pos;
4716
4717 if (ies == NULL)
4718 return NULL;
4719
4720 pos = ies;
4721 end = ies + ies_len;
4722
4723 while (pos + 1 < end) {
4724 if (pos + 2 + pos[1] > end)
4725 break;
4726 if (pos[0] == ie)
4727 return pos;
4728 pos += 2 + pos[1];
4729 }
4730
4731 return NULL;
4732}
4733
4734
4735static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
4736 const u8 *ie, size_t ie_len)
4737{
4738 const u8 *ssid;
4739 size_t i;
4740
4741 if (drv->filter_ssids == NULL)
4742 return 0;
4743
4744 ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID);
4745 if (ssid == NULL)
4746 return 1;
4747
4748 for (i = 0; i < drv->num_filter_ssids; i++) {
4749 if (ssid[1] == drv->filter_ssids[i].ssid_len &&
4750 os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==
4751 0)
4752 return 0;
4753 }
4754
4755 return 1;
4756}
4757
4758
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004759static int bss_info_handler(struct nl_msg *msg, void *arg)
4760{
4761 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4762 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4763 struct nlattr *bss[NL80211_BSS_MAX + 1];
4764 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
4765 [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
4766 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
4767 [NL80211_BSS_TSF] = { .type = NLA_U64 },
4768 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
4769 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
4770 [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
4771 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
4772 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
4773 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
4774 [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
4775 [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
4776 };
4777 struct nl80211_bss_info_arg *_arg = arg;
4778 struct wpa_scan_results *res = _arg->res;
4779 struct wpa_scan_res **tmp;
4780 struct wpa_scan_res *r;
4781 const u8 *ie, *beacon_ie;
4782 size_t ie_len, beacon_ie_len;
4783 u8 *pos;
Jouni Malinen87fd2792011-05-16 18:35:42 +03004784 size_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004785
4786 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
4787 genlmsg_attrlen(gnlh, 0), NULL);
4788 if (!tb[NL80211_ATTR_BSS])
4789 return NL_SKIP;
4790 if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
4791 bss_policy))
4792 return NL_SKIP;
Jouni Malinen87fd2792011-05-16 18:35:42 +03004793 if (bss[NL80211_BSS_STATUS]) {
4794 enum nl80211_bss_status status;
4795 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
4796 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
4797 bss[NL80211_BSS_FREQUENCY]) {
4798 _arg->assoc_freq =
4799 nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
4800 wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
4801 _arg->assoc_freq);
4802 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004803 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
4804 bss[NL80211_BSS_BSSID]) {
4805 os_memcpy(_arg->assoc_bssid,
4806 nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
4807 wpa_printf(MSG_DEBUG, "nl80211: Associated with "
4808 MACSTR, MAC2STR(_arg->assoc_bssid));
4809 }
Jouni Malinen87fd2792011-05-16 18:35:42 +03004810 }
4811 if (!res)
4812 return NL_SKIP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004813 if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
4814 ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
4815 ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
4816 } else {
4817 ie = NULL;
4818 ie_len = 0;
4819 }
4820 if (bss[NL80211_BSS_BEACON_IES]) {
4821 beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);
4822 beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);
4823 } else {
4824 beacon_ie = NULL;
4825 beacon_ie_len = 0;
4826 }
4827
4828 if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie,
4829 ie ? ie_len : beacon_ie_len))
4830 return NL_SKIP;
4831
4832 r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);
4833 if (r == NULL)
4834 return NL_SKIP;
4835 if (bss[NL80211_BSS_BSSID])
4836 os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),
4837 ETH_ALEN);
4838 if (bss[NL80211_BSS_FREQUENCY])
4839 r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
4840 if (bss[NL80211_BSS_BEACON_INTERVAL])
4841 r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);
4842 if (bss[NL80211_BSS_CAPABILITY])
4843 r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
4844 r->flags |= WPA_SCAN_NOISE_INVALID;
4845 if (bss[NL80211_BSS_SIGNAL_MBM]) {
4846 r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
4847 r->level /= 100; /* mBm to dBm */
4848 r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;
4849 } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
4850 r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004851 r->flags |= WPA_SCAN_QUAL_INVALID;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004852 } else
4853 r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;
4854 if (bss[NL80211_BSS_TSF])
4855 r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);
4856 if (bss[NL80211_BSS_SEEN_MS_AGO])
4857 r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
4858 r->ie_len = ie_len;
4859 pos = (u8 *) (r + 1);
4860 if (ie) {
4861 os_memcpy(pos, ie, ie_len);
4862 pos += ie_len;
4863 }
4864 r->beacon_ie_len = beacon_ie_len;
4865 if (beacon_ie)
4866 os_memcpy(pos, beacon_ie, beacon_ie_len);
4867
4868 if (bss[NL80211_BSS_STATUS]) {
4869 enum nl80211_bss_status status;
4870 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
4871 switch (status) {
4872 case NL80211_BSS_STATUS_AUTHENTICATED:
4873 r->flags |= WPA_SCAN_AUTHENTICATED;
4874 break;
4875 case NL80211_BSS_STATUS_ASSOCIATED:
4876 r->flags |= WPA_SCAN_ASSOCIATED;
4877 break;
4878 default:
4879 break;
4880 }
4881 }
4882
Jouni Malinen87fd2792011-05-16 18:35:42 +03004883 /*
4884 * cfg80211 maintains separate BSS table entries for APs if the same
4885 * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does
4886 * not use frequency as a separate key in the BSS table, so filter out
4887 * duplicated entries. Prefer associated BSS entry in such a case in
4888 * order to get the correct frequency into the BSS table.
4889 */
4890 for (i = 0; i < res->num; i++) {
4891 const u8 *s1, *s2;
4892 if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)
4893 continue;
4894
4895 s1 = nl80211_get_ie((u8 *) (res->res[i] + 1),
4896 res->res[i]->ie_len, WLAN_EID_SSID);
4897 s2 = nl80211_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
4898 if (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||
4899 os_memcmp(s1, s2, 2 + s1[1]) != 0)
4900 continue;
4901
4902 /* Same BSSID,SSID was already included in scan results */
4903 wpa_printf(MSG_DEBUG, "nl80211: Remove duplicated scan result "
4904 "for " MACSTR, MAC2STR(r->bssid));
4905
4906 if ((r->flags & WPA_SCAN_ASSOCIATED) &&
4907 !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) {
4908 os_free(res->res[i]);
4909 res->res[i] = r;
4910 } else
4911 os_free(r);
4912 return NL_SKIP;
4913 }
4914
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004915 tmp = os_realloc_array(res->res, res->num + 1,
4916 sizeof(struct wpa_scan_res *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004917 if (tmp == NULL) {
4918 os_free(r);
4919 return NL_SKIP;
4920 }
4921 tmp[res->num++] = r;
4922 res->res = tmp;
4923
4924 return NL_SKIP;
4925}
4926
4927
4928static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
4929 const u8 *addr)
4930{
4931 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
4932 wpa_printf(MSG_DEBUG, "nl80211: Clear possible state "
4933 "mismatch (" MACSTR ")", MAC2STR(addr));
4934 wpa_driver_nl80211_mlme(drv, addr,
4935 NL80211_CMD_DEAUTHENTICATE,
4936 WLAN_REASON_PREV_AUTH_NOT_VALID, 1);
4937 }
4938}
4939
4940
4941static void wpa_driver_nl80211_check_bss_status(
4942 struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res)
4943{
4944 size_t i;
4945
4946 for (i = 0; i < res->num; i++) {
4947 struct wpa_scan_res *r = res->res[i];
4948 if (r->flags & WPA_SCAN_AUTHENTICATED) {
4949 wpa_printf(MSG_DEBUG, "nl80211: Scan results "
4950 "indicates BSS status with " MACSTR
4951 " as authenticated",
4952 MAC2STR(r->bssid));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004953 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004954 os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&
4955 os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=
4956 0) {
4957 wpa_printf(MSG_DEBUG, "nl80211: Unknown BSSID"
4958 " in local state (auth=" MACSTR
4959 " assoc=" MACSTR ")",
4960 MAC2STR(drv->auth_bssid),
4961 MAC2STR(drv->bssid));
4962 clear_state_mismatch(drv, r->bssid);
4963 }
4964 }
4965
4966 if (r->flags & WPA_SCAN_ASSOCIATED) {
4967 wpa_printf(MSG_DEBUG, "nl80211: Scan results "
4968 "indicate BSS status with " MACSTR
4969 " as associated",
4970 MAC2STR(r->bssid));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004971 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004972 !drv->associated) {
4973 wpa_printf(MSG_DEBUG, "nl80211: Local state "
4974 "(not associated) does not match "
4975 "with BSS state");
4976 clear_state_mismatch(drv, r->bssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004977 } else if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004978 os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
4979 0) {
4980 wpa_printf(MSG_DEBUG, "nl80211: Local state "
4981 "(associated with " MACSTR ") does "
4982 "not match with BSS state",
4983 MAC2STR(drv->bssid));
4984 clear_state_mismatch(drv, r->bssid);
4985 clear_state_mismatch(drv, drv->bssid);
4986 }
4987 }
4988 }
4989}
4990
4991
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004992static struct wpa_scan_results *
4993nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
4994{
4995 struct nl_msg *msg;
4996 struct wpa_scan_results *res;
4997 int ret;
4998 struct nl80211_bss_info_arg arg;
4999
5000 res = os_zalloc(sizeof(*res));
5001 if (res == NULL)
5002 return NULL;
5003 msg = nlmsg_alloc();
5004 if (!msg)
5005 goto nla_put_failure;
5006
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005007 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005008 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005009 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005010
5011 arg.drv = drv;
5012 arg.res = res;
5013 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
5014 msg = NULL;
5015 if (ret == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005016 wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu "
5017 "BSSes)", (unsigned long) res->num);
5018 nl80211_get_noise_for_scan_results(drv, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005019 return res;
5020 }
5021 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
5022 "(%s)", ret, strerror(-ret));
5023nla_put_failure:
5024 nlmsg_free(msg);
5025 wpa_scan_results_free(res);
5026 return NULL;
5027}
5028
5029
5030/**
5031 * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
5032 * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
5033 * Returns: Scan results on success, -1 on failure
5034 */
5035static struct wpa_scan_results *
5036wpa_driver_nl80211_get_scan_results(void *priv)
5037{
5038 struct i802_bss *bss = priv;
5039 struct wpa_driver_nl80211_data *drv = bss->drv;
5040 struct wpa_scan_results *res;
5041
5042 res = nl80211_get_scan_results(drv);
5043 if (res)
5044 wpa_driver_nl80211_check_bss_status(drv, res);
5045 return res;
5046}
5047
5048
5049static void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv)
5050{
5051 struct wpa_scan_results *res;
5052 size_t i;
5053
5054 res = nl80211_get_scan_results(drv);
5055 if (res == NULL) {
5056 wpa_printf(MSG_DEBUG, "nl80211: Failed to get scan results");
5057 return;
5058 }
5059
5060 wpa_printf(MSG_DEBUG, "nl80211: Scan result dump");
5061 for (i = 0; i < res->num; i++) {
5062 struct wpa_scan_res *r = res->res[i];
5063 wpa_printf(MSG_DEBUG, "nl80211: %d/%d " MACSTR "%s%s",
5064 (int) i, (int) res->num, MAC2STR(r->bssid),
5065 r->flags & WPA_SCAN_AUTHENTICATED ? " [auth]" : "",
5066 r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : "");
5067 }
5068
5069 wpa_scan_results_free(res);
5070}
5071
5072
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005073static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005074 enum wpa_alg alg, const u8 *addr,
5075 int key_idx, int set_tx,
5076 const u8 *seq, size_t seq_len,
5077 const u8 *key, size_t key_len)
5078{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005079 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005080 int ifindex;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005081 struct nl_msg *msg;
5082 int ret;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005083 int tdls = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005084
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005085 /* Ignore for P2P Device */
5086 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
5087 return 0;
5088
5089 ifindex = if_nametoindex(ifname);
5090 wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005091 "set_tx=%d seq_len=%lu key_len=%lu",
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005092 __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005093 (unsigned long) seq_len, (unsigned long) key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005094#ifdef CONFIG_TDLS
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005095 if (key_idx == -1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005096 key_idx = 0;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005097 tdls = 1;
5098 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005099#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005100
5101 msg = nlmsg_alloc();
5102 if (!msg)
5103 return -ENOMEM;
5104
5105 if (alg == WPA_ALG_NONE) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005106 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005107 } else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005108 nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005109 NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);
5110 switch (alg) {
5111 case WPA_ALG_WEP:
5112 if (key_len == 5)
5113 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5114 WLAN_CIPHER_SUITE_WEP40);
5115 else
5116 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5117 WLAN_CIPHER_SUITE_WEP104);
5118 break;
5119 case WPA_ALG_TKIP:
5120 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5121 WLAN_CIPHER_SUITE_TKIP);
5122 break;
5123 case WPA_ALG_CCMP:
5124 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5125 WLAN_CIPHER_SUITE_CCMP);
5126 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005127 case WPA_ALG_GCMP:
5128 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5129 WLAN_CIPHER_SUITE_GCMP);
5130 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005131 case WPA_ALG_IGTK:
5132 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5133 WLAN_CIPHER_SUITE_AES_CMAC);
5134 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005135 case WPA_ALG_SMS4:
5136 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5137 WLAN_CIPHER_SUITE_SMS4);
5138 break;
5139 case WPA_ALG_KRK:
5140 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
5141 WLAN_CIPHER_SUITE_KRK);
5142 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005143 default:
5144 wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
5145 "algorithm %d", __func__, alg);
5146 nlmsg_free(msg);
5147 return -1;
5148 }
5149 }
5150
5151 if (seq && seq_len)
5152 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq);
5153
5154 if (addr && !is_broadcast_ether_addr(addr)) {
5155 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
5156 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
5157
5158 if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
5159 wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK");
5160 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE,
5161 NL80211_KEYTYPE_GROUP);
5162 }
5163 } else if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005164 struct nlattr *types;
5165
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005166 wpa_printf(MSG_DEBUG, " broadcast key");
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005167
5168 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005169 if (!types)
5170 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005171 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
5172 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005173 }
5174 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
5175 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
5176
5177 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5178 if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
5179 ret = 0;
5180 if (ret)
5181 wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)",
5182 ret, strerror(-ret));
5183
5184 /*
5185 * If we failed or don't need to set the default TX key (below),
5186 * we're done here.
5187 */
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07005188 if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005189 return ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005190 if (is_ap_interface(drv->nlmode) && addr &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005191 !is_broadcast_ether_addr(addr))
5192 return ret;
5193
5194 msg = nlmsg_alloc();
5195 if (!msg)
5196 return -ENOMEM;
5197
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005198 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005199 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
5200 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
5201 if (alg == WPA_ALG_IGTK)
5202 NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT);
5203 else
5204 NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
5205 if (addr && is_broadcast_ether_addr(addr)) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005206 struct nlattr *types;
5207
5208 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005209 if (!types)
5210 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005211 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
5212 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005213 } else if (addr) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005214 struct nlattr *types;
5215
5216 types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005217 if (!types)
5218 goto nla_put_failure;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07005219 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST);
5220 nla_nest_end(msg, types);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005221 }
5222
5223 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5224 if (ret == -ENOENT)
5225 ret = 0;
5226 if (ret)
5227 wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
5228 "err=%d %s)", ret, strerror(-ret));
5229 return ret;
5230
5231nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005232 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233 return -ENOBUFS;
5234}
5235
5236
5237static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,
5238 int key_idx, int defkey,
5239 const u8 *seq, size_t seq_len,
5240 const u8 *key, size_t key_len)
5241{
5242 struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);
5243 if (!key_attr)
5244 return -1;
5245
5246 if (defkey && alg == WPA_ALG_IGTK)
5247 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT);
5248 else if (defkey)
5249 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
5250
5251 NLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);
5252
5253 switch (alg) {
5254 case WPA_ALG_WEP:
5255 if (key_len == 5)
5256 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5257 WLAN_CIPHER_SUITE_WEP40);
5258 else
5259 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5260 WLAN_CIPHER_SUITE_WEP104);
5261 break;
5262 case WPA_ALG_TKIP:
5263 NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_TKIP);
5264 break;
5265 case WPA_ALG_CCMP:
5266 NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP);
5267 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005268 case WPA_ALG_GCMP:
5269 NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_GCMP);
5270 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005271 case WPA_ALG_IGTK:
5272 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5273 WLAN_CIPHER_SUITE_AES_CMAC);
5274 break;
5275 default:
5276 wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
5277 "algorithm %d", __func__, alg);
5278 return -1;
5279 }
5280
5281 if (seq && seq_len)
5282 NLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);
5283
5284 NLA_PUT(msg, NL80211_KEY_DATA, key_len, key);
5285
5286 nla_nest_end(msg, key_attr);
5287
5288 return 0;
5289 nla_put_failure:
5290 return -1;
5291}
5292
5293
5294static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
5295 struct nl_msg *msg)
5296{
5297 int i, privacy = 0;
5298 struct nlattr *nl_keys, *nl_key;
5299
5300 for (i = 0; i < 4; i++) {
5301 if (!params->wep_key[i])
5302 continue;
5303 privacy = 1;
5304 break;
5305 }
5306 if (params->wps == WPS_MODE_PRIVACY)
5307 privacy = 1;
5308 if (params->pairwise_suite &&
5309 params->pairwise_suite != WPA_CIPHER_NONE)
5310 privacy = 1;
5311
5312 if (!privacy)
5313 return 0;
5314
5315 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
5316
5317 nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
5318 if (!nl_keys)
5319 goto nla_put_failure;
5320
5321 for (i = 0; i < 4; i++) {
5322 if (!params->wep_key[i])
5323 continue;
5324
5325 nl_key = nla_nest_start(msg, i);
5326 if (!nl_key)
5327 goto nla_put_failure;
5328
5329 NLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],
5330 params->wep_key[i]);
5331 if (params->wep_key_len[i] == 5)
5332 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5333 WLAN_CIPHER_SUITE_WEP40);
5334 else
5335 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
5336 WLAN_CIPHER_SUITE_WEP104);
5337
5338 NLA_PUT_U8(msg, NL80211_KEY_IDX, i);
5339
5340 if (i == params->wep_tx_keyidx)
5341 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
5342
5343 nla_nest_end(msg, nl_key);
5344 }
5345 nla_nest_end(msg, nl_keys);
5346
5347 return 0;
5348
5349nla_put_failure:
5350 return -ENOBUFS;
5351}
5352
5353
5354static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
5355 const u8 *addr, int cmd, u16 reason_code,
5356 int local_state_change)
5357{
5358 int ret = -1;
5359 struct nl_msg *msg;
5360
5361 msg = nlmsg_alloc();
5362 if (!msg)
5363 return -1;
5364
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005365 nl80211_cmd(drv, msg, 0, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005366
5367 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5368 NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005369 if (addr)
5370 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005371 if (local_state_change)
5372 NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);
5373
5374 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5375 msg = NULL;
5376 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005377 wpa_dbg(drv->ctx, MSG_DEBUG,
5378 "nl80211: MLME command failed: reason=%u ret=%d (%s)",
5379 reason_code, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005380 goto nla_put_failure;
5381 }
5382 ret = 0;
5383
5384nla_put_failure:
5385 nlmsg_free(msg);
5386 return ret;
5387}
5388
5389
5390static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005391 int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005392{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005393 int ret;
5394
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005395 wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005396 nl80211_mark_disconnected(drv);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005397 /* Disconnect command doesn't need BSSID - it uses cached value */
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005398 ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
5399 reason_code, 0);
5400 /*
5401 * For locally generated disconnect, supplicant already generates a
5402 * DEAUTH event, so ignore the event from NL80211.
5403 */
5404 drv->ignore_next_local_disconnect = ret == 0;
5405
5406 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005407}
5408
5409
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005410static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
5411 const u8 *addr, int reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005412{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005413 struct wpa_driver_nl80211_data *drv = bss->drv;
5414 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005415 return wpa_driver_nl80211_disconnect(drv, reason_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005416 wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
5417 __func__, MAC2STR(addr), reason_code);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005418 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005419 if (drv->nlmode == NL80211_IFTYPE_ADHOC)
5420 return nl80211_leave_ibss(drv);
5421 return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
5422 reason_code, 0);
5423}
5424
5425
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005426static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
5427 struct wpa_driver_auth_params *params)
5428{
5429 int i;
5430
5431 drv->auth_freq = params->freq;
5432 drv->auth_alg = params->auth_alg;
5433 drv->auth_wep_tx_keyidx = params->wep_tx_keyidx;
5434 drv->auth_local_state_change = params->local_state_change;
5435 drv->auth_p2p = params->p2p;
5436
5437 if (params->bssid)
5438 os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);
5439 else
5440 os_memset(drv->auth_bssid_, 0, ETH_ALEN);
5441
5442 if (params->ssid) {
5443 os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);
5444 drv->auth_ssid_len = params->ssid_len;
5445 } else
5446 drv->auth_ssid_len = 0;
5447
5448
5449 os_free(drv->auth_ie);
5450 drv->auth_ie = NULL;
5451 drv->auth_ie_len = 0;
5452 if (params->ie) {
5453 drv->auth_ie = os_malloc(params->ie_len);
5454 if (drv->auth_ie) {
5455 os_memcpy(drv->auth_ie, params->ie, params->ie_len);
5456 drv->auth_ie_len = params->ie_len;
5457 }
5458 }
5459
5460 for (i = 0; i < 4; i++) {
5461 if (params->wep_key[i] && params->wep_key_len[i] &&
5462 params->wep_key_len[i] <= 16) {
5463 os_memcpy(drv->auth_wep_key[i], params->wep_key[i],
5464 params->wep_key_len[i]);
5465 drv->auth_wep_key_len[i] = params->wep_key_len[i];
5466 } else
5467 drv->auth_wep_key_len[i] = 0;
5468 }
5469}
5470
5471
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005472static int wpa_driver_nl80211_authenticate(
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005473 struct i802_bss *bss, struct wpa_driver_auth_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005474{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005475 struct wpa_driver_nl80211_data *drv = bss->drv;
5476 int ret = -1, i;
5477 struct nl_msg *msg;
5478 enum nl80211_auth_type type;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005479 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005480 int count = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005481 int is_retry;
5482
5483 is_retry = drv->retry_auth;
5484 drv->retry_auth = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005485
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005486 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005487 os_memset(drv->auth_bssid, 0, ETH_ALEN);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07005488 if (params->bssid)
5489 os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
5490 else
5491 os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005492 /* FIX: IBSS mode */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005493 nlmode = params->p2p ?
5494 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
5495 if (drv->nlmode != nlmode &&
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005496 wpa_driver_nl80211_set_mode(bss, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005497 return -1;
5498
5499retry:
5500 msg = nlmsg_alloc();
5501 if (!msg)
5502 return -1;
5503
5504 wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
5505 drv->ifindex);
5506
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005507 nl80211_cmd(drv, msg, 0, NL80211_CMD_AUTHENTICATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005508
5509 for (i = 0; i < 4; i++) {
5510 if (!params->wep_key[i])
5511 continue;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08005512 wpa_driver_nl80211_set_key(bss->ifname, bss, WPA_ALG_WEP,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005513 NULL, i,
5514 i == params->wep_tx_keyidx, NULL, 0,
5515 params->wep_key[i],
5516 params->wep_key_len[i]);
5517 if (params->wep_tx_keyidx != i)
5518 continue;
5519 if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
5520 params->wep_key[i], params->wep_key_len[i])) {
5521 nlmsg_free(msg);
5522 return -1;
5523 }
5524 }
5525
5526 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5527 if (params->bssid) {
5528 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
5529 MAC2STR(params->bssid));
5530 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
5531 }
5532 if (params->freq) {
5533 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
5534 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
5535 }
5536 if (params->ssid) {
5537 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
5538 params->ssid, params->ssid_len);
5539 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
5540 params->ssid);
5541 }
5542 wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len);
5543 if (params->ie)
5544 NLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005545 if (params->sae_data) {
5546 wpa_hexdump(MSG_DEBUG, " * SAE data", params->sae_data,
5547 params->sae_data_len);
5548 NLA_PUT(msg, NL80211_ATTR_SAE_DATA, params->sae_data_len,
5549 params->sae_data);
5550 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005551 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
5552 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
5553 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
5554 type = NL80211_AUTHTYPE_SHARED_KEY;
5555 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
5556 type = NL80211_AUTHTYPE_NETWORK_EAP;
5557 else if (params->auth_alg & WPA_AUTH_ALG_FT)
5558 type = NL80211_AUTHTYPE_FT;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005559 else if (params->auth_alg & WPA_AUTH_ALG_SAE)
5560 type = NL80211_AUTHTYPE_SAE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005561 else
5562 goto nla_put_failure;
5563 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
5564 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
5565 if (params->local_state_change) {
5566 wpa_printf(MSG_DEBUG, " * Local state change only");
5567 NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);
5568 }
5569
5570 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5571 msg = NULL;
5572 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005573 wpa_dbg(drv->ctx, MSG_DEBUG,
5574 "nl80211: MLME command failed (auth): ret=%d (%s)",
5575 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005576 count++;
5577 if (ret == -EALREADY && count == 1 && params->bssid &&
5578 !params->local_state_change) {
5579 /*
5580 * mac80211 does not currently accept new
5581 * authentication if we are already authenticated. As a
5582 * workaround, force deauthentication and try again.
5583 */
5584 wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
5585 "after forced deauthentication");
5586 wpa_driver_nl80211_deauthenticate(
5587 bss, params->bssid,
5588 WLAN_REASON_PREV_AUTH_NOT_VALID);
5589 nlmsg_free(msg);
5590 goto retry;
5591 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005592
5593 if (ret == -ENOENT && params->freq && !is_retry) {
5594 /*
5595 * cfg80211 has likely expired the BSS entry even
5596 * though it was previously available in our internal
5597 * BSS table. To recover quickly, start a single
5598 * channel scan on the specified channel.
5599 */
5600 struct wpa_driver_scan_params scan;
5601 int freqs[2];
5602
5603 os_memset(&scan, 0, sizeof(scan));
5604 scan.num_ssids = 1;
5605 if (params->ssid) {
5606 scan.ssids[0].ssid = params->ssid;
5607 scan.ssids[0].ssid_len = params->ssid_len;
5608 }
5609 freqs[0] = params->freq;
5610 freqs[1] = 0;
5611 scan.freqs = freqs;
5612 wpa_printf(MSG_DEBUG, "nl80211: Trigger single "
5613 "channel scan to refresh cfg80211 BSS "
5614 "entry");
5615 ret = wpa_driver_nl80211_scan(bss, &scan);
5616 if (ret == 0) {
5617 nl80211_copy_auth_params(drv, params);
5618 drv->scan_for_auth = 1;
5619 }
5620 } else if (is_retry) {
5621 /*
5622 * Need to indicate this with an event since the return
5623 * value from the retry is not delivered to core code.
5624 */
5625 union wpa_event_data event;
5626 wpa_printf(MSG_DEBUG, "nl80211: Authentication retry "
5627 "failed");
5628 os_memset(&event, 0, sizeof(event));
5629 os_memcpy(event.timeout_event.addr, drv->auth_bssid_,
5630 ETH_ALEN);
5631 wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,
5632 &event);
5633 }
5634
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005635 goto nla_put_failure;
5636 }
5637 ret = 0;
5638 wpa_printf(MSG_DEBUG, "nl80211: Authentication request send "
5639 "successfully");
5640
5641nla_put_failure:
5642 nlmsg_free(msg);
5643 return ret;
5644}
5645
5646
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005647static int wpa_driver_nl80211_authenticate_retry(
5648 struct wpa_driver_nl80211_data *drv)
5649{
5650 struct wpa_driver_auth_params params;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005651 struct i802_bss *bss = drv->first_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005652 int i;
5653
5654 wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
5655
5656 os_memset(&params, 0, sizeof(params));
5657 params.freq = drv->auth_freq;
5658 params.auth_alg = drv->auth_alg;
5659 params.wep_tx_keyidx = drv->auth_wep_tx_keyidx;
5660 params.local_state_change = drv->auth_local_state_change;
5661 params.p2p = drv->auth_p2p;
5662
5663 if (!is_zero_ether_addr(drv->auth_bssid_))
5664 params.bssid = drv->auth_bssid_;
5665
5666 if (drv->auth_ssid_len) {
5667 params.ssid = drv->auth_ssid;
5668 params.ssid_len = drv->auth_ssid_len;
5669 }
5670
5671 params.ie = drv->auth_ie;
5672 params.ie_len = drv->auth_ie_len;
5673
5674 for (i = 0; i < 4; i++) {
5675 if (drv->auth_wep_key_len[i]) {
5676 params.wep_key[i] = drv->auth_wep_key[i];
5677 params.wep_key_len[i] = drv->auth_wep_key_len[i];
5678 }
5679 }
5680
5681 drv->retry_auth = 1;
5682 return wpa_driver_nl80211_authenticate(bss, &params);
5683}
5684
5685
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005686struct phy_info_arg {
5687 u16 *num_modes;
5688 struct hostapd_hw_modes *modes;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005689 int last_mode, last_chan_idx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005690};
5691
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005692static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
5693 struct nlattr *ampdu_factor,
5694 struct nlattr *ampdu_density,
5695 struct nlattr *mcs_set)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005696{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005697 if (capa)
5698 mode->ht_capab = nla_get_u16(capa);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005699
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005700 if (ampdu_factor)
5701 mode->a_mpdu_params |= nla_get_u8(ampdu_factor) & 0x03;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005702
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005703 if (ampdu_density)
5704 mode->a_mpdu_params |= nla_get_u8(ampdu_density) << 2;
5705
5706 if (mcs_set && nla_len(mcs_set) >= 16) {
5707 u8 *mcs;
5708 mcs = nla_data(mcs_set);
5709 os_memcpy(mode->mcs_set, mcs, 16);
5710 }
5711}
5712
5713
5714static void phy_info_vht_capa(struct hostapd_hw_modes *mode,
5715 struct nlattr *capa,
5716 struct nlattr *mcs_set)
5717{
5718 if (capa)
5719 mode->vht_capab = nla_get_u32(capa);
5720
5721 if (mcs_set && nla_len(mcs_set) >= 8) {
5722 u8 *mcs;
5723 mcs = nla_data(mcs_set);
5724 os_memcpy(mode->vht_mcs_set, mcs, 8);
5725 }
5726}
5727
5728
5729static void phy_info_freq(struct hostapd_hw_modes *mode,
5730 struct hostapd_channel_data *chan,
5731 struct nlattr *tb_freq[])
5732{
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005733 u8 channel;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005734 chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
5735 chan->flag = 0;
Dmitry Shmidt4b060592013-04-29 16:42:49 -07005736 if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
5737 chan->chan = channel;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005738
5739 if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
5740 chan->flag |= HOSTAPD_CHAN_DISABLED;
5741 if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])
5742 chan->flag |= HOSTAPD_CHAN_PASSIVE_SCAN;
5743 if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])
5744 chan->flag |= HOSTAPD_CHAN_NO_IBSS;
5745 if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
5746 chan->flag |= HOSTAPD_CHAN_RADAR;
5747
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005748 if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) {
5749 enum nl80211_dfs_state state =
5750 nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]);
5751
5752 switch (state) {
5753 case NL80211_DFS_USABLE:
5754 chan->flag |= HOSTAPD_CHAN_DFS_USABLE;
5755 break;
5756 case NL80211_DFS_AVAILABLE:
5757 chan->flag |= HOSTAPD_CHAN_DFS_AVAILABLE;
5758 break;
5759 case NL80211_DFS_UNAVAILABLE:
5760 chan->flag |= HOSTAPD_CHAN_DFS_UNAVAILABLE;
5761 break;
5762 }
5763 }
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005764}
5765
5766
5767static int phy_info_freqs(struct phy_info_arg *phy_info,
5768 struct hostapd_hw_modes *mode, struct nlattr *tb)
5769{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005770 static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
5771 [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
5772 [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
5773 [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
5774 [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
5775 [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
5776 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
Dmitry Shmidtea69e842013-05-13 14:52:28 -07005777 [NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005778 };
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005779 int new_channels = 0;
5780 struct hostapd_channel_data *channel;
5781 struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005782 struct nlattr *nl_freq;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005783 int rem_freq, idx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005784
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005785 if (tb == NULL)
5786 return NL_OK;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005787
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005788 nla_for_each_nested(nl_freq, tb, rem_freq) {
5789 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
5790 nla_data(nl_freq), nla_len(nl_freq), freq_policy);
5791 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
5792 continue;
5793 new_channels++;
5794 }
5795
5796 channel = os_realloc_array(mode->channels,
5797 mode->num_channels + new_channels,
5798 sizeof(struct hostapd_channel_data));
5799 if (!channel)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005800 return NL_SKIP;
5801
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005802 mode->channels = channel;
5803 mode->num_channels += new_channels;
5804
5805 idx = phy_info->last_chan_idx;
5806
5807 nla_for_each_nested(nl_freq, tb, rem_freq) {
5808 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX,
5809 nla_data(nl_freq), nla_len(nl_freq), freq_policy);
5810 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
5811 continue;
5812 phy_info_freq(mode, &mode->channels[idx], tb_freq);
5813 idx++;
5814 }
5815 phy_info->last_chan_idx = idx;
5816
5817 return NL_OK;
5818}
5819
5820
5821static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
5822{
5823 static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {
5824 [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },
5825 [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] =
5826 { .type = NLA_FLAG },
5827 };
5828 struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
5829 struct nlattr *nl_rate;
5830 int rem_rate, idx;
5831
5832 if (tb == NULL)
5833 return NL_OK;
5834
5835 nla_for_each_nested(nl_rate, tb, rem_rate) {
5836 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
5837 nla_data(nl_rate), nla_len(nl_rate),
5838 rate_policy);
5839 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
5840 continue;
5841 mode->num_rates++;
5842 }
5843
5844 mode->rates = os_calloc(mode->num_rates, sizeof(int));
5845 if (!mode->rates)
5846 return NL_SKIP;
5847
5848 idx = 0;
5849
5850 nla_for_each_nested(nl_rate, tb, rem_rate) {
5851 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX,
5852 nla_data(nl_rate), nla_len(nl_rate),
5853 rate_policy);
5854 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
5855 continue;
5856 mode->rates[idx] = nla_get_u32(
5857 tb_rate[NL80211_BITRATE_ATTR_RATE]);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005858 idx++;
5859 }
5860
5861 return NL_OK;
5862}
5863
5864
5865static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
5866{
5867 struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
5868 struct hostapd_hw_modes *mode;
5869 int ret;
5870
5871 if (phy_info->last_mode != nl_band->nla_type) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005872 mode = os_realloc_array(phy_info->modes,
5873 *phy_info->num_modes + 1,
5874 sizeof(*mode));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005875 if (!mode)
5876 return NL_SKIP;
5877 phy_info->modes = mode;
5878
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005879 mode = &phy_info->modes[*(phy_info->num_modes)];
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005880 os_memset(mode, 0, sizeof(*mode));
5881 mode->mode = NUM_HOSTAPD_MODES;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005882 mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN |
5883 HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN;
5884
5885 /*
5886 * Unsupported VHT MCS stream is defined as value 3, so the VHT
5887 * MCS RX/TX map must be initialized with 0xffff to mark all 8
5888 * possible streams as unsupported. This will be overridden if
5889 * driver advertises VHT support.
5890 */
5891 mode->vht_mcs_set[0] = 0xff;
5892 mode->vht_mcs_set[1] = 0xff;
5893 mode->vht_mcs_set[4] = 0xff;
5894 mode->vht_mcs_set[5] = 0xff;
5895
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005896 *(phy_info->num_modes) += 1;
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005897 phy_info->last_mode = nl_band->nla_type;
5898 phy_info->last_chan_idx = 0;
5899 } else
5900 mode = &phy_info->modes[*(phy_info->num_modes) - 1];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005901
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005902 nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
5903 nla_len(nl_band), NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005904
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005905 phy_info_ht_capa(mode, tb_band[NL80211_BAND_ATTR_HT_CAPA],
5906 tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR],
5907 tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY],
5908 tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);
5909 phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
5910 tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
5911 ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]);
5912 if (ret != NL_OK)
5913 return ret;
5914 ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
5915 if (ret != NL_OK)
5916 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005917
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005918 return NL_OK;
5919}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005920
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005921
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005922static int phy_info_handler(struct nl_msg *msg, void *arg)
5923{
5924 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
5925 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5926 struct phy_info_arg *phy_info = arg;
5927 struct nlattr *nl_band;
5928 int rem_band;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005929
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005930 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5931 genlmsg_attrlen(gnlh, 0), NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005932
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005933 if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
5934 return NL_SKIP;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005935
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005936 nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band)
5937 {
5938 int res = phy_info_band(phy_info, nl_band);
5939 if (res != NL_OK)
5940 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005941 }
5942
5943 return NL_SKIP;
5944}
5945
Dmitry Shmidt2f023192013-03-12 12:44:17 -07005946
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005947static struct hostapd_hw_modes *
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07005948wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes,
5949 u16 *num_modes)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005950{
5951 u16 m;
5952 struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
5953 int i, mode11g_idx = -1;
5954
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07005955 /* heuristic to set up modes */
5956 for (m = 0; m < *num_modes; m++) {
5957 if (!modes[m].num_channels)
5958 continue;
5959 if (modes[m].channels[0].freq < 4000) {
5960 modes[m].mode = HOSTAPD_MODE_IEEE80211B;
5961 for (i = 0; i < modes[m].num_rates; i++) {
5962 if (modes[m].rates[i] > 200) {
5963 modes[m].mode = HOSTAPD_MODE_IEEE80211G;
5964 break;
5965 }
5966 }
5967 } else if (modes[m].channels[0].freq > 50000)
5968 modes[m].mode = HOSTAPD_MODE_IEEE80211AD;
5969 else
5970 modes[m].mode = HOSTAPD_MODE_IEEE80211A;
5971 }
5972
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005973 /* If only 802.11g mode is included, use it to construct matching
5974 * 802.11b mode data. */
5975
5976 for (m = 0; m < *num_modes; m++) {
5977 if (modes[m].mode == HOSTAPD_MODE_IEEE80211B)
5978 return modes; /* 802.11b already included */
5979 if (modes[m].mode == HOSTAPD_MODE_IEEE80211G)
5980 mode11g_idx = m;
5981 }
5982
5983 if (mode11g_idx < 0)
5984 return modes; /* 2.4 GHz band not supported at all */
5985
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005986 nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005987 if (nmodes == NULL)
5988 return modes; /* Could not add 802.11b mode */
5989
5990 mode = &nmodes[*num_modes];
5991 os_memset(mode, 0, sizeof(*mode));
5992 (*num_modes)++;
5993 modes = nmodes;
5994
5995 mode->mode = HOSTAPD_MODE_IEEE80211B;
5996
5997 mode11g = &modes[mode11g_idx];
5998 mode->num_channels = mode11g->num_channels;
5999 mode->channels = os_malloc(mode11g->num_channels *
6000 sizeof(struct hostapd_channel_data));
6001 if (mode->channels == NULL) {
6002 (*num_modes)--;
6003 return modes; /* Could not add 802.11b mode */
6004 }
6005 os_memcpy(mode->channels, mode11g->channels,
6006 mode11g->num_channels * sizeof(struct hostapd_channel_data));
6007
6008 mode->num_rates = 0;
6009 mode->rates = os_malloc(4 * sizeof(int));
6010 if (mode->rates == NULL) {
6011 os_free(mode->channels);
6012 (*num_modes)--;
6013 return modes; /* Could not add 802.11b mode */
6014 }
6015
6016 for (i = 0; i < mode11g->num_rates; i++) {
6017 if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&
6018 mode11g->rates[i] != 55 && mode11g->rates[i] != 110)
6019 continue;
6020 mode->rates[mode->num_rates] = mode11g->rates[i];
6021 mode->num_rates++;
6022 if (mode->num_rates == 4)
6023 break;
6024 }
6025
6026 if (mode->num_rates == 0) {
6027 os_free(mode->channels);
6028 os_free(mode->rates);
6029 (*num_modes)--;
6030 return modes; /* No 802.11b rates */
6031 }
6032
6033 wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g "
6034 "information");
6035
6036 return modes;
6037}
6038
6039
6040static void nl80211_set_ht40_mode(struct hostapd_hw_modes *mode, int start,
6041 int end)
6042{
6043 int c;
6044
6045 for (c = 0; c < mode->num_channels; c++) {
6046 struct hostapd_channel_data *chan = &mode->channels[c];
6047 if (chan->freq - 10 >= start && chan->freq + 10 <= end)
6048 chan->flag |= HOSTAPD_CHAN_HT40;
6049 }
6050}
6051
6052
6053static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,
6054 int end)
6055{
6056 int c;
6057
6058 for (c = 0; c < mode->num_channels; c++) {
6059 struct hostapd_channel_data *chan = &mode->channels[c];
6060 if (!(chan->flag & HOSTAPD_CHAN_HT40))
6061 continue;
6062 if (chan->freq - 30 >= start && chan->freq - 10 <= end)
6063 chan->flag |= HOSTAPD_CHAN_HT40MINUS;
6064 if (chan->freq + 10 >= start && chan->freq + 30 <= end)
6065 chan->flag |= HOSTAPD_CHAN_HT40PLUS;
6066 }
6067}
6068
6069
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006070static void nl80211_reg_rule_max_eirp(struct nlattr *tb[],
6071 struct phy_info_arg *results)
6072{
6073 u32 start, end, max_eirp;
6074 u16 m;
6075
6076 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6077 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
6078 tb[NL80211_ATTR_POWER_RULE_MAX_EIRP] == NULL)
6079 return;
6080
6081 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6082 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6083 max_eirp = nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) / 100;
6084
6085 wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u mBm",
6086 start, end, max_eirp);
6087
6088 for (m = 0; m < *results->num_modes; m++) {
6089 int c;
6090 struct hostapd_hw_modes *mode = &results->modes[m];
6091
6092 for (c = 0; c < mode->num_channels; c++) {
6093 struct hostapd_channel_data *chan = &mode->channels[c];
6094 if ((u32) chan->freq - 10 >= start &&
6095 (u32) chan->freq + 10 <= end)
6096 chan->max_tx_power = max_eirp;
6097 }
6098 }
6099}
6100
6101
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006102static void nl80211_reg_rule_ht40(struct nlattr *tb[],
6103 struct phy_info_arg *results)
6104{
6105 u32 start, end, max_bw;
6106 u16 m;
6107
6108 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6109 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
6110 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
6111 return;
6112
6113 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6114 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6115 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
6116
6117 wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz",
6118 start, end, max_bw);
6119 if (max_bw < 40)
6120 return;
6121
6122 for (m = 0; m < *results->num_modes; m++) {
6123 if (!(results->modes[m].ht_capab &
6124 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6125 continue;
6126 nl80211_set_ht40_mode(&results->modes[m], start, end);
6127 }
6128}
6129
6130
6131static void nl80211_reg_rule_sec(struct nlattr *tb[],
6132 struct phy_info_arg *results)
6133{
6134 u32 start, end, max_bw;
6135 u16 m;
6136
6137 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6138 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
6139 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
6140 return;
6141
6142 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6143 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6144 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
6145
6146 if (max_bw < 20)
6147 return;
6148
6149 for (m = 0; m < *results->num_modes; m++) {
6150 if (!(results->modes[m].ht_capab &
6151 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6152 continue;
6153 nl80211_set_ht40_mode_sec(&results->modes[m], start, end);
6154 }
6155}
6156
6157
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006158static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
6159 int end)
6160{
6161 int c;
6162
6163 for (c = 0; c < mode->num_channels; c++) {
6164 struct hostapd_channel_data *chan = &mode->channels[c];
6165 if (chan->freq - 10 >= start && chan->freq + 70 <= end)
6166 chan->flag |= HOSTAPD_CHAN_VHT_10_70;
6167
6168 if (chan->freq - 30 >= start && chan->freq + 50 <= end)
6169 chan->flag |= HOSTAPD_CHAN_VHT_30_50;
6170
6171 if (chan->freq - 50 >= start && chan->freq + 30 <= end)
6172 chan->flag |= HOSTAPD_CHAN_VHT_50_30;
6173
6174 if (chan->freq - 70 >= start && chan->freq + 10 <= end)
6175 chan->flag |= HOSTAPD_CHAN_VHT_70_10;
6176 }
6177}
6178
6179
6180static void nl80211_reg_rule_vht(struct nlattr *tb[],
6181 struct phy_info_arg *results)
6182{
6183 u32 start, end, max_bw;
6184 u16 m;
6185
6186 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
6187 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
6188 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
6189 return;
6190
6191 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
6192 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
6193 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
6194
6195 if (max_bw < 80)
6196 return;
6197
6198 for (m = 0; m < *results->num_modes; m++) {
6199 if (!(results->modes[m].ht_capab &
6200 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
6201 continue;
6202 /* TODO: use a real VHT support indication */
6203 if (!results->modes[m].vht_capab)
6204 continue;
6205
6206 nl80211_set_vht_mode(&results->modes[m], start, end);
6207 }
6208}
6209
6210
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006211static int nl80211_get_reg(struct nl_msg *msg, void *arg)
6212{
6213 struct phy_info_arg *results = arg;
6214 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
6215 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6216 struct nlattr *nl_rule;
6217 struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
6218 int rem_rule;
6219 static struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
6220 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
6221 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
6222 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
6223 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
6224 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
6225 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
6226 };
6227
6228 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6229 genlmsg_attrlen(gnlh, 0), NULL);
6230 if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
6231 !tb_msg[NL80211_ATTR_REG_RULES]) {
6232 wpa_printf(MSG_DEBUG, "nl80211: No regulatory information "
6233 "available");
6234 return NL_SKIP;
6235 }
6236
6237 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s",
6238 (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));
6239
6240 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6241 {
6242 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6243 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
6244 nl80211_reg_rule_ht40(tb_rule, results);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006245 nl80211_reg_rule_max_eirp(tb_rule, results);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006246 }
6247
6248 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6249 {
6250 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6251 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
6252 nl80211_reg_rule_sec(tb_rule, results);
6253 }
6254
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006255 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
6256 {
6257 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
6258 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
6259 nl80211_reg_rule_vht(tb_rule, results);
6260 }
6261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006262 return NL_SKIP;
6263}
6264
6265
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006266static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv,
6267 struct phy_info_arg *results)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006268{
6269 struct nl_msg *msg;
6270
6271 msg = nlmsg_alloc();
6272 if (!msg)
6273 return -ENOMEM;
6274
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006275 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006276 return send_and_recv_msgs(drv, msg, nl80211_get_reg, results);
6277}
6278
6279
6280static struct hostapd_hw_modes *
6281wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
6282{
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006283 u32 feat;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006284 struct i802_bss *bss = priv;
6285 struct wpa_driver_nl80211_data *drv = bss->drv;
6286 struct nl_msg *msg;
6287 struct phy_info_arg result = {
6288 .num_modes = num_modes,
6289 .modes = NULL,
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006290 .last_mode = -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006291 };
6292
6293 *num_modes = 0;
6294 *flags = 0;
6295
6296 msg = nlmsg_alloc();
6297 if (!msg)
6298 return NULL;
6299
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006300 feat = get_nl80211_protocol_features(drv);
6301 if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
6302 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_WIPHY);
6303 else
6304 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006305
Dmitry Shmidt2f023192013-03-12 12:44:17 -07006306 NLA_PUT_FLAG(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006307 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6308
6309 if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006310 nl80211_set_regulatory_flags(drv, &result);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006311 return wpa_driver_nl80211_postprocess_modes(result.modes,
6312 num_modes);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006313 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006314 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006315 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006316 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006317 return NULL;
6318}
6319
6320
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006321static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv,
6322 const void *data, size_t len,
6323 int encrypt, int noack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006324{
6325 __u8 rtap_hdr[] = {
6326 0x00, 0x00, /* radiotap version */
6327 0x0e, 0x00, /* radiotap length */
6328 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
6329 IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
6330 0x00, /* padding */
6331 0x00, 0x00, /* RX and TX flags to indicate that */
6332 0x00, 0x00, /* this is the injected frame directly */
6333 };
6334 struct iovec iov[2] = {
6335 {
6336 .iov_base = &rtap_hdr,
6337 .iov_len = sizeof(rtap_hdr),
6338 },
6339 {
6340 .iov_base = (void *) data,
6341 .iov_len = len,
6342 }
6343 };
6344 struct msghdr msg = {
6345 .msg_name = NULL,
6346 .msg_namelen = 0,
6347 .msg_iov = iov,
6348 .msg_iovlen = 2,
6349 .msg_control = NULL,
6350 .msg_controllen = 0,
6351 .msg_flags = 0,
6352 };
6353 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006354 u16 txflags = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006355
6356 if (encrypt)
6357 rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
6358
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07006359 if (drv->monitor_sock < 0) {
6360 wpa_printf(MSG_DEBUG, "nl80211: No monitor socket available "
6361 "for %s", __func__);
6362 return -1;
6363 }
6364
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006365 if (noack)
6366 txflags |= IEEE80211_RADIOTAP_F_TX_NOACK;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006367 WPA_PUT_LE16(&rtap_hdr[12], txflags);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006369 res = sendmsg(drv->monitor_sock, &msg, 0);
6370 if (res < 0) {
6371 wpa_printf(MSG_INFO, "nl80211: sendmsg: %s", strerror(errno));
6372 return -1;
6373 }
6374 return 0;
6375}
6376
6377
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006378static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
6379 const void *data, size_t len,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006380 int encrypt, int noack,
6381 unsigned int freq, int no_cck,
6382 int offchanok, unsigned int wait_time)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006383{
6384 struct wpa_driver_nl80211_data *drv = bss->drv;
6385 u64 cookie;
Dmitry Shmidt051af732013-10-22 13:52:46 -07006386 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006387
Dmitry Shmidt56052862013-10-04 10:23:25 -07006388 if (freq == 0) {
6389 wpa_printf(MSG_DEBUG, "nl80211: send_frame - Use bss->freq=%u",
6390 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006391 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07006392 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006393
Dmitry Shmidt56052862013-10-04 10:23:25 -07006394 if (drv->use_monitor) {
6395 wpa_printf(MSG_DEBUG, "nl80211: send_frame(freq=%u bss->freq=%u) -> send_mntr",
6396 freq, bss->freq);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006397 return wpa_driver_nl80211_send_mntr(drv, data, len,
6398 encrypt, noack);
Dmitry Shmidt56052862013-10-04 10:23:25 -07006399 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006400
Dmitry Shmidt56052862013-10-04 10:23:25 -07006401 wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
Dmitry Shmidt051af732013-10-22 13:52:46 -07006402 res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
6403 &cookie, no_cck, noack, offchanok);
6404 if (res == 0 && !noack) {
6405 const struct ieee80211_mgmt *mgmt;
6406 u16 fc;
6407
6408 mgmt = (const struct ieee80211_mgmt *) data;
6409 fc = le_to_host16(mgmt->frame_control);
6410 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
6411 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
6412 wpa_printf(MSG_MSGDUMP,
6413 "nl80211: Update send_action_cookie from 0x%llx to 0x%llx",
6414 (long long unsigned int)
6415 drv->send_action_cookie,
6416 (long long unsigned int) cookie);
6417 drv->send_action_cookie = cookie;
6418 }
6419 }
6420
6421 return res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006422}
6423
6424
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08006425static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
6426 size_t data_len, int noack,
6427 unsigned int freq, int no_cck,
6428 int offchanok,
6429 unsigned int wait_time)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006430{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006431 struct wpa_driver_nl80211_data *drv = bss->drv;
6432 struct ieee80211_mgmt *mgmt;
6433 int encrypt = 1;
6434 u16 fc;
6435
6436 mgmt = (struct ieee80211_mgmt *) data;
6437 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt56052862013-10-04 10:23:25 -07006438 wpa_printf(MSG_DEBUG, "nl80211: send_mlme - noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u fc=0x%x nlmode=%d",
6439 noack, freq, no_cck, offchanok, wait_time, fc, drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006440
Dmitry Shmidt34af3062013-07-11 10:46:32 -07006441 if ((is_sta_interface(drv->nlmode) ||
6442 drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006443 WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
6444 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
6445 /*
6446 * The use of last_mgmt_freq is a bit of a hack,
6447 * but it works due to the single-threaded nature
6448 * of wpa_supplicant.
6449 */
Dmitry Shmidt56052862013-10-04 10:23:25 -07006450 if (freq == 0) {
6451 wpa_printf(MSG_DEBUG, "nl80211: Use last_mgmt_freq=%d",
6452 drv->last_mgmt_freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006453 freq = drv->last_mgmt_freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07006454 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006455 return nl80211_send_frame_cmd(bss, freq, 0,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006456 data, data_len, NULL, 1, noack,
6457 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006458 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006459
6460 if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
Dmitry Shmidt56052862013-10-04 10:23:25 -07006461 if (freq == 0) {
6462 wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d",
6463 bss->freq);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006464 freq = bss->freq;
Dmitry Shmidt56052862013-10-04 10:23:25 -07006465 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006466 return nl80211_send_frame_cmd(bss, freq,
6467 (int) freq == bss->freq ? 0 :
6468 wait_time,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006469 data, data_len,
6470 &drv->send_action_cookie,
6471 no_cck, noack, offchanok);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07006472 }
Dmitry Shmidtb638fe72012-03-20 12:51:25 -07006473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006474 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
6475 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {
6476 /*
6477 * Only one of the authentication frame types is encrypted.
6478 * In order for static WEP encryption to work properly (i.e.,
6479 * to not encrypt the frame), we need to tell mac80211 about
6480 * the frames that must not be encrypted.
6481 */
6482 u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
6483 u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);
6484 if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)
6485 encrypt = 0;
6486 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006487
Dmitry Shmidt56052862013-10-04 10:23:25 -07006488 wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006489 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006490 noack, freq, no_cck, offchanok,
6491 wait_time);
6492}
6493
6494
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006495static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
6496 int slot, int ht_opmode, int ap_isolate,
6497 int *basic_rates)
6498{
6499 struct wpa_driver_nl80211_data *drv = bss->drv;
6500 struct nl_msg *msg;
6501
6502 msg = nlmsg_alloc();
6503 if (!msg)
6504 return -ENOMEM;
6505
6506 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);
6507
6508 if (cts >= 0)
6509 NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);
6510 if (preamble >= 0)
6511 NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);
6512 if (slot >= 0)
6513 NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
6514 if (ht_opmode >= 0)
6515 NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);
6516 if (ap_isolate >= 0)
6517 NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate);
6518
6519 if (basic_rates) {
6520 u8 rates[NL80211_MAX_SUPP_RATES];
6521 u8 rates_len = 0;
6522 int i;
6523
6524 for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0;
6525 i++)
6526 rates[rates_len++] = basic_rates[i] / 5;
6527
6528 NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
6529 }
6530
6531 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
6532
6533 return send_and_recv_msgs(drv, msg, NULL, NULL);
6534 nla_put_failure:
6535 nlmsg_free(msg);
6536 return -ENOBUFS;
6537}
6538
6539
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006540static int wpa_driver_nl80211_set_acl(void *priv,
6541 struct hostapd_acl_params *params)
6542{
6543 struct i802_bss *bss = priv;
6544 struct wpa_driver_nl80211_data *drv = bss->drv;
6545 struct nl_msg *msg;
6546 struct nlattr *acl;
6547 unsigned int i;
6548 int ret = 0;
6549
6550 if (!(drv->capa.max_acl_mac_addrs))
6551 return -ENOTSUP;
6552
6553 if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
6554 return -ENOTSUP;
6555
6556 msg = nlmsg_alloc();
6557 if (!msg)
6558 return -ENOMEM;
6559
6560 wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
6561 params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
6562
6563 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_MAC_ACL);
6564
6565 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6566
6567 NLA_PUT_U32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
6568 NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
6569 NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED);
6570
6571 acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
6572 if (acl == NULL)
6573 goto nla_put_failure;
6574
6575 for (i = 0; i < params->num_mac_acl; i++)
6576 NLA_PUT(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr);
6577
6578 nla_nest_end(msg, acl);
6579
6580 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6581 msg = NULL;
6582 if (ret) {
6583 wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
6584 ret, strerror(-ret));
6585 }
6586
6587nla_put_failure:
6588 nlmsg_free(msg);
6589
6590 return ret;
6591}
6592
6593
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006594static int wpa_driver_nl80211_set_ap(void *priv,
6595 struct wpa_driver_ap_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006596{
6597 struct i802_bss *bss = priv;
6598 struct wpa_driver_nl80211_data *drv = bss->drv;
6599 struct nl_msg *msg;
6600 u8 cmd = NL80211_CMD_NEW_BEACON;
6601 int ret;
6602 int beacon_set;
6603 int ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006604 int num_suites;
6605 u32 suites[10];
6606 u32 ver;
6607
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07006608 beacon_set = bss->beacon_set;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006609
6610 msg = nlmsg_alloc();
6611 if (!msg)
6612 return -ENOMEM;
6613
6614 wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
6615 beacon_set);
6616 if (beacon_set)
6617 cmd = NL80211_CMD_SET_BEACON;
6618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006619 nl80211_cmd(drv, msg, 0, cmd);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006620 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon head",
6621 params->head, params->head_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006622 NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006623 wpa_hexdump(MSG_DEBUG, "nl80211: Beacon tail",
6624 params->tail, params->tail_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006625 NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006626 wpa_printf(MSG_DEBUG, "nl80211: ifindex=%d", ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006627 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006628 wpa_printf(MSG_DEBUG, "nl80211: beacon_int=%d", params->beacon_int);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006629 NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006630 wpa_printf(MSG_DEBUG, "nl80211: dtim_period=%d", params->dtim_period);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006631 NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006632 wpa_hexdump_ascii(MSG_DEBUG, "nl80211: ssid",
6633 params->ssid, params->ssid_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006634 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
6635 params->ssid);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006636 if (params->proberesp && params->proberesp_len) {
6637 wpa_hexdump(MSG_DEBUG, "nl80211: proberesp (offload)",
6638 params->proberesp, params->proberesp_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006639 NLA_PUT(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
6640 params->proberesp);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006641 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006642 switch (params->hide_ssid) {
6643 case NO_SSID_HIDING:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006644 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID not in use");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006645 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
6646 NL80211_HIDDEN_SSID_NOT_IN_USE);
6647 break;
6648 case HIDDEN_SSID_ZERO_LEN:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006649 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero len");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006650 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
6651 NL80211_HIDDEN_SSID_ZERO_LEN);
6652 break;
6653 case HIDDEN_SSID_ZERO_CONTENTS:
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006654 wpa_printf(MSG_DEBUG, "nl80211: hidden SSID zero contents");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006655 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
6656 NL80211_HIDDEN_SSID_ZERO_CONTENTS);
6657 break;
6658 }
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006659 wpa_printf(MSG_DEBUG, "nl80211: privacy=%d", params->privacy);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006660 if (params->privacy)
6661 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006662 wpa_printf(MSG_DEBUG, "nl80211: auth_algs=0x%x", params->auth_algs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006663 if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
6664 (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
6665 /* Leave out the attribute */
6666 } else if (params->auth_algs & WPA_AUTH_ALG_SHARED)
6667 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
6668 NL80211_AUTHTYPE_SHARED_KEY);
6669 else
6670 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
6671 NL80211_AUTHTYPE_OPEN_SYSTEM);
6672
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006673 wpa_printf(MSG_DEBUG, "nl80211: wpa_version=0x%x", params->wpa_version);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006674 ver = 0;
6675 if (params->wpa_version & WPA_PROTO_WPA)
6676 ver |= NL80211_WPA_VERSION_1;
6677 if (params->wpa_version & WPA_PROTO_RSN)
6678 ver |= NL80211_WPA_VERSION_2;
6679 if (ver)
6680 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
6681
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006682 wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x",
6683 params->key_mgmt_suites);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006684 num_suites = 0;
6685 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
6686 suites[num_suites++] = WLAN_AKM_SUITE_8021X;
6687 if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
6688 suites[num_suites++] = WLAN_AKM_SUITE_PSK;
6689 if (num_suites) {
6690 NLA_PUT(msg, NL80211_ATTR_AKM_SUITES,
6691 num_suites * sizeof(u32), suites);
6692 }
6693
6694 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X &&
6695 params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40))
6696 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
6697
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006698 wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
6699 params->pairwise_ciphers);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006700 num_suites = 0;
6701 if (params->pairwise_ciphers & WPA_CIPHER_CCMP)
6702 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006703 if (params->pairwise_ciphers & WPA_CIPHER_GCMP)
6704 suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006705 if (params->pairwise_ciphers & WPA_CIPHER_TKIP)
6706 suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
6707 if (params->pairwise_ciphers & WPA_CIPHER_WEP104)
6708 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
6709 if (params->pairwise_ciphers & WPA_CIPHER_WEP40)
6710 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
6711 if (num_suites) {
6712 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
6713 num_suites * sizeof(u32), suites);
6714 }
6715
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006716 wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x",
6717 params->group_cipher);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006718 switch (params->group_cipher) {
6719 case WPA_CIPHER_CCMP:
6720 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
6721 WLAN_CIPHER_SUITE_CCMP);
6722 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006723 case WPA_CIPHER_GCMP:
6724 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
6725 WLAN_CIPHER_SUITE_GCMP);
6726 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006727 case WPA_CIPHER_TKIP:
6728 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
6729 WLAN_CIPHER_SUITE_TKIP);
6730 break;
6731 case WPA_CIPHER_WEP104:
6732 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
6733 WLAN_CIPHER_SUITE_WEP104);
6734 break;
6735 case WPA_CIPHER_WEP40:
6736 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
6737 WLAN_CIPHER_SUITE_WEP40);
6738 break;
6739 }
6740
6741 if (params->beacon_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006742 wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
6743 params->beacon_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006744 NLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
6745 wpabuf_head(params->beacon_ies));
6746 }
6747 if (params->proberesp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006748 wpa_hexdump_buf(MSG_DEBUG, "nl80211: proberesp_ies",
6749 params->proberesp_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006750 NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
6751 wpabuf_len(params->proberesp_ies),
6752 wpabuf_head(params->proberesp_ies));
6753 }
6754 if (params->assocresp_ies) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006755 wpa_hexdump_buf(MSG_DEBUG, "nl80211: assocresp_ies",
6756 params->assocresp_ies);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006757 NLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,
6758 wpabuf_len(params->assocresp_ies),
6759 wpabuf_head(params->assocresp_ies));
6760 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006761
Dmitry Shmidt04949592012-07-19 12:16:46 -07006762 if (drv->capa.flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER) {
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07006763 wpa_printf(MSG_DEBUG, "nl80211: ap_max_inactivity=%d",
6764 params->ap_max_inactivity);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006765 NLA_PUT_U16(msg, NL80211_ATTR_INACTIVITY_TIMEOUT,
6766 params->ap_max_inactivity);
6767 }
6768
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006769 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6770 if (ret) {
6771 wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
6772 ret, strerror(-ret));
6773 } else {
6774 bss->beacon_set = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006775 nl80211_set_bss(bss, params->cts_protect, params->preamble,
6776 params->short_slot_time, params->ht_opmode,
6777 params->isolate, params->basic_rates);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006778 }
6779 return ret;
6780 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006781 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006782 return -ENOBUFS;
6783}
6784
6785
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006786static int nl80211_put_freq_params(struct nl_msg *msg,
6787 struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006788{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006789 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq);
6790 if (freq->vht_enabled) {
6791 switch (freq->bandwidth) {
6792 case 20:
6793 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
6794 NL80211_CHAN_WIDTH_20);
6795 break;
6796 case 40:
6797 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
6798 NL80211_CHAN_WIDTH_40);
6799 break;
6800 case 80:
6801 if (freq->center_freq2)
6802 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
6803 NL80211_CHAN_WIDTH_80P80);
6804 else
6805 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
6806 NL80211_CHAN_WIDTH_80);
6807 break;
6808 case 160:
6809 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
6810 NL80211_CHAN_WIDTH_160);
6811 break;
6812 default:
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006813 return -EINVAL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006814 }
6815 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1);
6816 if (freq->center_freq2)
6817 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2,
6818 freq->center_freq2);
6819 } else if (freq->ht_enabled) {
6820 switch (freq->sec_channel_offset) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006821 case -1:
6822 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
6823 NL80211_CHAN_HT40MINUS);
6824 break;
6825 case 1:
6826 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
6827 NL80211_CHAN_HT40PLUS);
6828 break;
6829 default:
6830 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
6831 NL80211_CHAN_HT20);
6832 break;
6833 }
6834 }
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006835 return 0;
6836
6837nla_put_failure:
6838 return -ENOBUFS;
6839}
6840
6841
6842static int wpa_driver_nl80211_set_freq(struct i802_bss *bss,
6843 struct hostapd_freq_params *freq)
6844{
6845 struct wpa_driver_nl80211_data *drv = bss->drv;
6846 struct nl_msg *msg;
6847 int ret;
6848
6849 wpa_printf(MSG_DEBUG,
6850 "nl80211: Set freq %d (ht_enabled=%d, vht_enabled=%d, bandwidth=%d MHz, cf1=%d MHz, cf2=%d MHz)",
6851 freq->freq, freq->ht_enabled, freq->vht_enabled,
6852 freq->bandwidth, freq->center_freq1, freq->center_freq2);
6853 msg = nlmsg_alloc();
6854 if (!msg)
6855 return -1;
6856
6857 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
6858
6859 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6860 if (nl80211_put_freq_params(msg, freq) < 0)
6861 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006862
6863 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006864 msg = NULL;
6865 if (ret == 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006866 bss->freq = freq->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006867 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006868 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006869 wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006870 "%d (%s)", freq->freq, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006871nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006872 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006873 return -1;
6874}
6875
6876
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006877static u32 sta_flags_nl80211(int flags)
6878{
6879 u32 f = 0;
6880
6881 if (flags & WPA_STA_AUTHORIZED)
6882 f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
6883 if (flags & WPA_STA_WMM)
6884 f |= BIT(NL80211_STA_FLAG_WME);
6885 if (flags & WPA_STA_SHORT_PREAMBLE)
6886 f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
6887 if (flags & WPA_STA_MFP)
6888 f |= BIT(NL80211_STA_FLAG_MFP);
6889 if (flags & WPA_STA_TDLS_PEER)
6890 f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
6891
6892 return f;
6893}
6894
6895
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006896static int wpa_driver_nl80211_sta_add(void *priv,
6897 struct hostapd_sta_add_params *params)
6898{
6899 struct i802_bss *bss = priv;
6900 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006901 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006902 struct nl80211_sta_flag_update upd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006903 int ret = -ENOBUFS;
6904
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006905 if ((params->flags & WPA_STA_TDLS_PEER) &&
6906 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
6907 return -EOPNOTSUPP;
6908
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006909 msg = nlmsg_alloc();
6910 if (!msg)
6911 return -ENOMEM;
6912
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006913 wpa_printf(MSG_DEBUG, "nl80211: %s STA " MACSTR,
6914 params->set ? "Set" : "Add", MAC2STR(params->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006915 nl80211_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION :
6916 NL80211_CMD_NEW_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006917
6918 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
6919 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006920 NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,
6921 params->supp_rates);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006922 wpa_hexdump(MSG_DEBUG, " * supported rates", params->supp_rates,
6923 params->supp_rates_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006924 if (!params->set) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07006925 if (params->aid) {
6926 wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
6927 NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
6928 } else {
6929 /*
6930 * cfg80211 validates that AID is non-zero, so we have
6931 * to make this a non-zero value for the TDLS case where
6932 * a dummy STA entry is used for now.
6933 */
6934 wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)");
6935 NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, 1);
6936 }
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006937 wpa_printf(MSG_DEBUG, " * listen_interval=%u",
6938 params->listen_interval);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006939 NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
6940 params->listen_interval);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006941 } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
6942 wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
6943 NLA_PUT_U16(msg, NL80211_ATTR_PEER_AID, params->aid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006944 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006945 if (params->ht_capabilities) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006946 wpa_hexdump(MSG_DEBUG, " * ht_capabilities",
6947 (u8 *) params->ht_capabilities,
6948 sizeof(*params->ht_capabilities));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006949 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,
6950 sizeof(*params->ht_capabilities),
6951 params->ht_capabilities);
6952 }
6953
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006954 if (params->vht_capabilities) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006955 wpa_hexdump(MSG_DEBUG, " * vht_capabilities",
6956 (u8 *) params->vht_capabilities,
6957 sizeof(*params->vht_capabilities));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006958 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY,
6959 sizeof(*params->vht_capabilities),
6960 params->vht_capabilities);
6961 }
6962
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006963 wpa_printf(MSG_DEBUG, " * capability=0x%x", params->capability);
6964 NLA_PUT_U16(msg, NL80211_ATTR_STA_CAPABILITY, params->capability);
6965
6966 if (params->ext_capab) {
6967 wpa_hexdump(MSG_DEBUG, " * ext_capab",
6968 params->ext_capab, params->ext_capab_len);
6969 NLA_PUT(msg, NL80211_ATTR_STA_EXT_CAPABILITY,
6970 params->ext_capab_len, params->ext_capab);
6971 }
6972
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006973 os_memset(&upd, 0, sizeof(upd));
6974 upd.mask = sta_flags_nl80211(params->flags);
6975 upd.set = upd.mask;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006976 wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x",
6977 upd.set, upd.mask);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006978 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
6979
6980 if (params->flags & WPA_STA_WMM) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006981 struct nlattr *wme = nla_nest_start(msg, NL80211_ATTR_STA_WME);
6982
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006983 if (!wme)
6984 goto nla_put_failure;
6985
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006986 wpa_printf(MSG_DEBUG, " * qosinfo=0x%x", params->qosinfo);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006987 NLA_PUT_U8(msg, NL80211_STA_WME_UAPSD_QUEUES,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006988 params->qosinfo & WMM_QOSINFO_STA_AC_MASK);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006989 NLA_PUT_U8(msg, NL80211_STA_WME_MAX_SP,
Dmitry Shmidtf8623282013-02-20 14:34:59 -08006990 (params->qosinfo >> WMM_QOSINFO_STA_SP_SHIFT) &
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006991 WMM_QOSINFO_STA_SP_MASK);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07006992 nla_nest_end(msg, wme);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006993 }
6994
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006995 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006996 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006997 if (ret)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006998 wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
6999 "result: %d (%s)", params->set ? "SET" : "NEW", ret,
7000 strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007001 if (ret == -EEXIST)
7002 ret = 0;
7003 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007004 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007005 return ret;
7006}
7007
7008
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08007009static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007010{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007011 struct wpa_driver_nl80211_data *drv = bss->drv;
7012 struct nl_msg *msg;
7013 int ret;
7014
7015 msg = nlmsg_alloc();
7016 if (!msg)
7017 return -ENOMEM;
7018
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007019 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007020
7021 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
7022 if_nametoindex(bss->ifname));
7023 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
7024
7025 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07007026 wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
7027 " --> %d (%s)",
7028 bss->ifname, MAC2STR(addr), ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007029 if (ret == -ENOENT)
7030 return 0;
7031 return ret;
7032 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007033 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007034 return -ENOBUFS;
7035}
7036
7037
7038static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
7039 int ifidx)
7040{
7041 struct nl_msg *msg;
7042
7043 wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx);
7044
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007045 /* stop listening for EAPOL on this interface */
7046 del_ifidx(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007047
7048 msg = nlmsg_alloc();
7049 if (!msg)
7050 goto nla_put_failure;
7051
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007052 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007053 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
7054
7055 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
7056 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007057 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007058 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007059 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007060 wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
7061}
7062
7063
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007064static const char * nl80211_iftype_str(enum nl80211_iftype mode)
7065{
7066 switch (mode) {
7067 case NL80211_IFTYPE_ADHOC:
7068 return "ADHOC";
7069 case NL80211_IFTYPE_STATION:
7070 return "STATION";
7071 case NL80211_IFTYPE_AP:
7072 return "AP";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07007073 case NL80211_IFTYPE_AP_VLAN:
7074 return "AP_VLAN";
7075 case NL80211_IFTYPE_WDS:
7076 return "WDS";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007077 case NL80211_IFTYPE_MONITOR:
7078 return "MONITOR";
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07007079 case NL80211_IFTYPE_MESH_POINT:
7080 return "MESH_POINT";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007081 case NL80211_IFTYPE_P2P_CLIENT:
7082 return "P2P_CLIENT";
7083 case NL80211_IFTYPE_P2P_GO:
7084 return "P2P_GO";
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007085 case NL80211_IFTYPE_P2P_DEVICE:
7086 return "P2P_DEVICE";
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007087 default:
7088 return "unknown";
7089 }
7090}
7091
7092
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007093static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
7094 const char *ifname,
7095 enum nl80211_iftype iftype,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007096 const u8 *addr, int wds,
7097 int (*handler)(struct nl_msg *, void *),
7098 void *arg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007099{
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007100 struct nl_msg *msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007101 int ifidx;
7102 int ret = -ENOBUFS;
7103
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007104 wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)",
7105 iftype, nl80211_iftype_str(iftype));
7106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007107 msg = nlmsg_alloc();
7108 if (!msg)
7109 return -1;
7110
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007111 nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007112 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007113 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007114 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);
7115 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
7116
7117 if (iftype == NL80211_IFTYPE_MONITOR) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007118 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007119
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007120 flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007121 if (!flags)
7122 goto nla_put_failure;
7123
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007124 NLA_PUT_FLAG(msg, NL80211_MNTR_FLAG_COOK_FRAMES);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007125
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007126 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007127 } else if (wds) {
7128 NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
7129 }
7130
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007131 ret = send_and_recv_msgs(drv, msg, handler, arg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007132 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007133 if (ret) {
7134 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007135 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007136 wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)",
7137 ifname, ret, strerror(-ret));
7138 return ret;
7139 }
7140
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007141 if (iftype == NL80211_IFTYPE_P2P_DEVICE)
7142 return 0;
7143
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007144 ifidx = if_nametoindex(ifname);
7145 wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d",
7146 ifname, ifidx);
7147
7148 if (ifidx <= 0)
7149 return -1;
7150
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007151 /* start listening for EAPOL on this interface */
7152 add_ifidx(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007153
7154 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007155 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007156 nl80211_remove_iface(drv, ifidx);
7157 return -1;
7158 }
7159
7160 return ifidx;
7161}
7162
7163
7164static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
7165 const char *ifname, enum nl80211_iftype iftype,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007166 const u8 *addr, int wds,
7167 int (*handler)(struct nl_msg *, void *),
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007168 void *arg, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007169{
7170 int ret;
7171
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007172 ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds, handler,
7173 arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007174
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007175 /* if error occurred and interface exists already */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007176 if (ret == -ENFILE && if_nametoindex(ifname)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007177 if (use_existing) {
7178 wpa_printf(MSG_DEBUG, "nl80211: Continue using existing interface %s",
7179 ifname);
7180 return -ENFILE;
7181 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007182 wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname);
7183
7184 /* Try to remove the interface that was already there. */
7185 nl80211_remove_iface(drv, if_nametoindex(ifname));
7186
7187 /* Try to create the interface again */
7188 ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007189 wds, handler, arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007190 }
7191
Dmitry Shmidt34af3062013-07-11 10:46:32 -07007192 if (ret >= 0 && is_p2p_net_interface(iftype))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007193 nl80211_disable_11b_rates(drv, ret, 1);
7194
7195 return ret;
7196}
7197
7198
7199static void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)
7200{
7201 struct ieee80211_hdr *hdr;
7202 u16 fc;
7203 union wpa_event_data event;
7204
7205 hdr = (struct ieee80211_hdr *) buf;
7206 fc = le_to_host16(hdr->frame_control);
7207
7208 os_memset(&event, 0, sizeof(event));
7209 event.tx_status.type = WLAN_FC_GET_TYPE(fc);
7210 event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
7211 event.tx_status.dst = hdr->addr1;
7212 event.tx_status.data = buf;
7213 event.tx_status.data_len = len;
7214 event.tx_status.ack = ok;
7215 wpa_supplicant_event(ctx, EVENT_TX_STATUS, &event);
7216}
7217
7218
7219static void from_unknown_sta(struct wpa_driver_nl80211_data *drv,
7220 u8 *buf, size_t len)
7221{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007222 struct ieee80211_hdr *hdr = (void *)buf;
7223 u16 fc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007224 union wpa_event_data event;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007225
7226 if (len < sizeof(*hdr))
7227 return;
7228
7229 fc = le_to_host16(hdr->frame_control);
7230
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007231 os_memset(&event, 0, sizeof(event));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007232 event.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);
7233 event.rx_from_unknown.addr = hdr->addr2;
7234 event.rx_from_unknown.wds = (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) ==
7235 (WLAN_FC_FROMDS | WLAN_FC_TODS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007236 wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
7237}
7238
7239
7240static void handle_frame(struct wpa_driver_nl80211_data *drv,
7241 u8 *buf, size_t len, int datarate, int ssi_signal)
7242{
7243 struct ieee80211_hdr *hdr;
7244 u16 fc;
7245 union wpa_event_data event;
7246
7247 hdr = (struct ieee80211_hdr *) buf;
7248 fc = le_to_host16(hdr->frame_control);
7249
7250 switch (WLAN_FC_GET_TYPE(fc)) {
7251 case WLAN_FC_TYPE_MGMT:
7252 os_memset(&event, 0, sizeof(event));
7253 event.rx_mgmt.frame = buf;
7254 event.rx_mgmt.frame_len = len;
7255 event.rx_mgmt.datarate = datarate;
7256 event.rx_mgmt.ssi_signal = ssi_signal;
7257 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
7258 break;
7259 case WLAN_FC_TYPE_CTRL:
7260 /* can only get here with PS-Poll frames */
7261 wpa_printf(MSG_DEBUG, "CTRL");
7262 from_unknown_sta(drv, buf, len);
7263 break;
7264 case WLAN_FC_TYPE_DATA:
7265 from_unknown_sta(drv, buf, len);
7266 break;
7267 }
7268}
7269
7270
7271static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
7272{
7273 struct wpa_driver_nl80211_data *drv = eloop_ctx;
7274 int len;
7275 unsigned char buf[3000];
7276 struct ieee80211_radiotap_iterator iter;
7277 int ret;
7278 int datarate = 0, ssi_signal = 0;
7279 int injected = 0, failed = 0, rxflags = 0;
7280
7281 len = recv(sock, buf, sizeof(buf), 0);
7282 if (len < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007283 wpa_printf(MSG_ERROR, "nl80211: Monitor socket recv failed: %s",
7284 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007285 return;
7286 }
7287
7288 if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007289 wpa_printf(MSG_INFO, "nl80211: received invalid radiotap frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007290 return;
7291 }
7292
7293 while (1) {
7294 ret = ieee80211_radiotap_iterator_next(&iter);
7295 if (ret == -ENOENT)
7296 break;
7297 if (ret) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007298 wpa_printf(MSG_INFO, "nl80211: received invalid radiotap frame (%d)",
7299 ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007300 return;
7301 }
7302 switch (iter.this_arg_index) {
7303 case IEEE80211_RADIOTAP_FLAGS:
7304 if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
7305 len -= 4;
7306 break;
7307 case IEEE80211_RADIOTAP_RX_FLAGS:
7308 rxflags = 1;
7309 break;
7310 case IEEE80211_RADIOTAP_TX_FLAGS:
7311 injected = 1;
7312 failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
7313 IEEE80211_RADIOTAP_F_TX_FAIL;
7314 break;
7315 case IEEE80211_RADIOTAP_DATA_RETRIES:
7316 break;
7317 case IEEE80211_RADIOTAP_CHANNEL:
7318 /* TODO: convert from freq/flags to channel number */
7319 break;
7320 case IEEE80211_RADIOTAP_RATE:
7321 datarate = *iter.this_arg * 5;
7322 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007323 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
7324 ssi_signal = (s8) *iter.this_arg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007325 break;
7326 }
7327 }
7328
7329 if (rxflags && injected)
7330 return;
7331
7332 if (!injected)
7333 handle_frame(drv, buf + iter.max_length,
7334 len - iter.max_length, datarate, ssi_signal);
7335 else
7336 handle_tx_callback(drv->ctx, buf + iter.max_length,
7337 len - iter.max_length, !failed);
7338}
7339
7340
7341/*
7342 * we post-process the filter code later and rewrite
7343 * this to the offset to the last instruction
7344 */
7345#define PASS 0xFF
7346#define FAIL 0xFE
7347
7348static struct sock_filter msock_filter_insns[] = {
7349 /*
7350 * do a little-endian load of the radiotap length field
7351 */
7352 /* load lower byte into A */
7353 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 2),
7354 /* put it into X (== index register) */
7355 BPF_STMT(BPF_MISC| BPF_TAX, 0),
7356 /* load upper byte into A */
7357 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 3),
7358 /* left-shift it by 8 */
7359 BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8),
7360 /* or with X */
7361 BPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0),
7362 /* put result into X */
7363 BPF_STMT(BPF_MISC| BPF_TAX, 0),
7364
7365 /*
7366 * Allow management frames through, this also gives us those
7367 * management frames that we sent ourselves with status
7368 */
7369 /* load the lower byte of the IEEE 802.11 frame control field */
7370 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
7371 /* mask off frame type and version */
7372 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF),
7373 /* accept frame if it's both 0, fall through otherwise */
7374 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0),
7375
7376 /*
7377 * TODO: add a bit to radiotap RX flags that indicates
7378 * that the sending station is not associated, then
7379 * add a filter here that filters on our DA and that flag
7380 * to allow us to deauth frames to that bad station.
7381 *
7382 * For now allow all To DS data frames through.
7383 */
7384 /* load the IEEE 802.11 frame control field */
7385 BPF_STMT(BPF_LD | BPF_H | BPF_IND, 0),
7386 /* mask off frame type, version and DS status */
7387 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03),
7388 /* accept frame if version 0, type 2 and To DS, fall through otherwise
7389 */
7390 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0),
7391
7392#if 0
7393 /*
7394 * drop non-data frames
7395 */
7396 /* load the lower byte of the frame control field */
7397 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
7398 /* mask off QoS bit */
7399 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c),
7400 /* drop non-data frames */
7401 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL),
7402#endif
7403 /* load the upper byte of the frame control field */
7404 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1),
7405 /* mask off toDS/fromDS */
7406 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03),
7407 /* accept WDS frames */
7408 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0),
7409
7410 /*
7411 * add header length to index
7412 */
7413 /* load the lower byte of the frame control field */
7414 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
7415 /* mask off QoS bit */
7416 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x80),
7417 /* right shift it by 6 to give 0 or 2 */
7418 BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 6),
7419 /* add data frame header length */
7420 BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 24),
7421 /* add index, was start of 802.11 header */
7422 BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0),
7423 /* move to index, now start of LL header */
7424 BPF_STMT(BPF_MISC | BPF_TAX, 0),
7425
7426 /*
7427 * Accept empty data frames, we use those for
7428 * polling activity.
7429 */
7430 BPF_STMT(BPF_LD | BPF_W | BPF_LEN, 0),
7431 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0),
7432
7433 /*
7434 * Accept EAPOL frames
7435 */
7436 BPF_STMT(BPF_LD | BPF_W | BPF_IND, 0),
7437 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL),
7438 BPF_STMT(BPF_LD | BPF_W | BPF_IND, 4),
7439 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL),
7440
7441 /* keep these last two statements or change the code below */
7442 /* return 0 == "DROP" */
7443 BPF_STMT(BPF_RET | BPF_K, 0),
7444 /* return ~0 == "keep all" */
7445 BPF_STMT(BPF_RET | BPF_K, ~0),
7446};
7447
7448static struct sock_fprog msock_filter = {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007449 .len = ARRAY_SIZE(msock_filter_insns),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007450 .filter = msock_filter_insns,
7451};
7452
7453
7454static int add_monitor_filter(int s)
7455{
7456 int idx;
7457
7458 /* rewrite all PASS/FAIL jump offsets */
7459 for (idx = 0; idx < msock_filter.len; idx++) {
7460 struct sock_filter *insn = &msock_filter_insns[idx];
7461
7462 if (BPF_CLASS(insn->code) == BPF_JMP) {
7463 if (insn->code == (BPF_JMP|BPF_JA)) {
7464 if (insn->k == PASS)
7465 insn->k = msock_filter.len - idx - 2;
7466 else if (insn->k == FAIL)
7467 insn->k = msock_filter.len - idx - 3;
7468 }
7469
7470 if (insn->jt == PASS)
7471 insn->jt = msock_filter.len - idx - 2;
7472 else if (insn->jt == FAIL)
7473 insn->jt = msock_filter.len - idx - 3;
7474
7475 if (insn->jf == PASS)
7476 insn->jf = msock_filter.len - idx - 2;
7477 else if (insn->jf == FAIL)
7478 insn->jf = msock_filter.len - idx - 3;
7479 }
7480 }
7481
7482 if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER,
7483 &msock_filter, sizeof(msock_filter))) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007484 wpa_printf(MSG_ERROR, "nl80211: setsockopt(SO_ATTACH_FILTER) failed: %s",
7485 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007486 return -1;
7487 }
7488
7489 return 0;
7490}
7491
7492
7493static void nl80211_remove_monitor_interface(
7494 struct wpa_driver_nl80211_data *drv)
7495{
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007496 if (drv->monitor_refcount > 0)
7497 drv->monitor_refcount--;
7498 wpa_printf(MSG_DEBUG, "nl80211: Remove monitor interface: refcount=%d",
7499 drv->monitor_refcount);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007500 if (drv->monitor_refcount > 0)
7501 return;
7502
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007503 if (drv->monitor_ifidx >= 0) {
7504 nl80211_remove_iface(drv, drv->monitor_ifidx);
7505 drv->monitor_ifidx = -1;
7506 }
7507 if (drv->monitor_sock >= 0) {
7508 eloop_unregister_read_sock(drv->monitor_sock);
7509 close(drv->monitor_sock);
7510 drv->monitor_sock = -1;
7511 }
7512}
7513
7514
7515static int
7516nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
7517{
7518 char buf[IFNAMSIZ];
7519 struct sockaddr_ll ll;
7520 int optval;
7521 socklen_t optlen;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007522
7523 if (drv->monitor_ifidx >= 0) {
7524 drv->monitor_refcount++;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007525 wpa_printf(MSG_DEBUG, "nl80211: Re-use existing monitor interface: refcount=%d",
7526 drv->monitor_refcount);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007527 return 0;
7528 }
7529
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007530 if (os_strncmp(drv->first_bss->ifname, "p2p-", 4) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007531 /*
7532 * P2P interface name is of the format p2p-%s-%d. For monitor
7533 * interface name corresponding to P2P GO, replace "p2p-" with
7534 * "mon-" to retain the same interface name length and to
7535 * indicate that it is a monitor interface.
7536 */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007537 snprintf(buf, IFNAMSIZ, "mon-%s", drv->first_bss->ifname + 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007538 } else {
7539 /* Non-P2P interface with AP functionality. */
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007540 snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007541 }
7542
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007543 buf[IFNAMSIZ - 1] = '\0';
7544
7545 drv->monitor_ifidx =
7546 nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007547 0, NULL, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007548
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07007549 if (drv->monitor_ifidx == -EOPNOTSUPP) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007550 /*
7551 * This is backward compatibility for a few versions of
7552 * the kernel only that didn't advertise the right
7553 * attributes for the only driver that then supported
7554 * AP mode w/o monitor -- ath6kl.
7555 */
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07007556 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support "
7557 "monitor interface type - try to run without it");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007558 drv->device_ap_sme = 1;
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07007559 }
7560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007561 if (drv->monitor_ifidx < 0)
7562 return -1;
7563
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007564 if (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007565 goto error;
7566
7567 memset(&ll, 0, sizeof(ll));
7568 ll.sll_family = AF_PACKET;
7569 ll.sll_ifindex = drv->monitor_ifidx;
7570 drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
7571 if (drv->monitor_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007572 wpa_printf(MSG_ERROR, "nl80211: socket[PF_PACKET,SOCK_RAW] failed: %s",
7573 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007574 goto error;
7575 }
7576
7577 if (add_monitor_filter(drv->monitor_sock)) {
7578 wpa_printf(MSG_INFO, "Failed to set socket filter for monitor "
7579 "interface; do filtering in user space");
7580 /* This works, but will cost in performance. */
7581 }
7582
7583 if (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007584 wpa_printf(MSG_ERROR, "nl80211: monitor socket bind failed: %s",
7585 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007586 goto error;
7587 }
7588
7589 optlen = sizeof(optval);
7590 optval = 20;
7591 if (setsockopt
7592 (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007593 wpa_printf(MSG_ERROR, "nl80211: Failed to set socket priority: %s",
7594 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007595 goto error;
7596 }
7597
7598 if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,
7599 drv, NULL)) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007600 wpa_printf(MSG_INFO, "nl80211: Could not register monitor read socket");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007601 goto error;
7602 }
7603
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007604 drv->monitor_refcount++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007605 return 0;
7606 error:
7607 nl80211_remove_monitor_interface(drv);
7608 return -1;
7609}
7610
7611
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007612static int nl80211_setup_ap(struct i802_bss *bss)
7613{
7614 struct wpa_driver_nl80211_data *drv = bss->drv;
7615
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007616 wpa_printf(MSG_DEBUG, "nl80211: Setup AP(%s) - device_ap_sme=%d use_monitor=%d",
7617 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007618
7619 /*
7620 * Disable Probe Request reporting unless we need it in this way for
7621 * devices that include the AP SME, in the other case (unless using
7622 * monitor iface) we'll get it through the nl_mgmt socket instead.
7623 */
7624 if (!drv->device_ap_sme)
7625 wpa_driver_nl80211_probe_req_report(bss, 0);
7626
7627 if (!drv->device_ap_sme && !drv->use_monitor)
7628 if (nl80211_mgmt_subscribe_ap(bss))
7629 return -1;
7630
7631 if (drv->device_ap_sme && !drv->use_monitor)
7632 if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
7633 return -1;
7634
7635 if (!drv->device_ap_sme && drv->use_monitor &&
7636 nl80211_create_monitor_interface(drv) &&
7637 !drv->device_ap_sme)
Dmitry Shmidt04949592012-07-19 12:16:46 -07007638 return -1;
7639
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007640 if (drv->device_ap_sme &&
7641 wpa_driver_nl80211_probe_req_report(bss, 1) < 0) {
7642 wpa_printf(MSG_DEBUG, "nl80211: Failed to enable "
7643 "Probe Request frame reporting in AP mode");
7644 /* Try to survive without this */
7645 }
7646
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007647 return 0;
7648}
7649
7650
7651static void nl80211_teardown_ap(struct i802_bss *bss)
7652{
7653 struct wpa_driver_nl80211_data *drv = bss->drv;
7654
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007655 wpa_printf(MSG_DEBUG, "nl80211: Teardown AP(%s) - device_ap_sme=%d use_monitor=%d",
7656 bss->ifname, drv->device_ap_sme, drv->use_monitor);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007657 if (drv->device_ap_sme) {
7658 wpa_driver_nl80211_probe_req_report(bss, 0);
7659 if (!drv->use_monitor)
7660 nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)");
7661 } else if (drv->use_monitor)
7662 nl80211_remove_monitor_interface(drv);
7663 else
7664 nl80211_mgmt_unsubscribe(bss, "AP teardown");
7665
7666 bss->beacon_set = 0;
7667}
7668
7669
7670static int nl80211_send_eapol_data(struct i802_bss *bss,
7671 const u8 *addr, const u8 *data,
7672 size_t data_len)
7673{
7674 struct sockaddr_ll ll;
7675 int ret;
7676
7677 if (bss->drv->eapol_tx_sock < 0) {
7678 wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL");
7679 return -1;
7680 }
7681
7682 os_memset(&ll, 0, sizeof(ll));
7683 ll.sll_family = AF_PACKET;
7684 ll.sll_ifindex = bss->ifindex;
7685 ll.sll_protocol = htons(ETH_P_PAE);
7686 ll.sll_halen = ETH_ALEN;
7687 os_memcpy(ll.sll_addr, addr, ETH_ALEN);
7688 ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,
7689 (struct sockaddr *) &ll, sizeof(ll));
7690 if (ret < 0)
7691 wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s",
7692 strerror(errno));
7693
7694 return ret;
7695}
7696
7697
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007698static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
7699
7700static int wpa_driver_nl80211_hapd_send_eapol(
7701 void *priv, const u8 *addr, const u8 *data,
7702 size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
7703{
7704 struct i802_bss *bss = priv;
7705 struct wpa_driver_nl80211_data *drv = bss->drv;
7706 struct ieee80211_hdr *hdr;
7707 size_t len;
7708 u8 *pos;
7709 int res;
7710 int qos = flags & WPA_STA_WMM;
Dmitry Shmidt641185e2013-11-06 15:17:13 -08007711
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007712 if (drv->device_ap_sme || !drv->use_monitor)
7713 return nl80211_send_eapol_data(bss, addr, data, data_len);
7714
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007715 len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
7716 data_len;
7717 hdr = os_zalloc(len);
7718 if (hdr == NULL) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007719 wpa_printf(MSG_INFO, "nl80211: Failed to allocate EAPOL buffer(len=%lu)",
7720 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007721 return -1;
7722 }
7723
7724 hdr->frame_control =
7725 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
7726 hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
7727 if (encrypt)
7728 hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
7729 if (qos) {
7730 hdr->frame_control |=
7731 host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
7732 }
7733
7734 memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
7735 memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
7736 memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
7737 pos = (u8 *) (hdr + 1);
7738
7739 if (qos) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07007740 /* Set highest priority in QoS header */
7741 pos[0] = 7;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007742 pos[1] = 0;
7743 pos += 2;
7744 }
7745
7746 memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
7747 pos += sizeof(rfc1042_header);
7748 WPA_PUT_BE16(pos, ETH_P_PAE);
7749 pos += 2;
7750 memcpy(pos, data, data_len);
7751
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007752 res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
7753 0, 0, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007754 if (res < 0) {
7755 wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
7756 "failed: %d (%s)",
7757 (unsigned long) len, errno, strerror(errno));
7758 }
7759 os_free(hdr);
7760
7761 return res;
7762}
7763
7764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007765static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
7766 int total_flags,
7767 int flags_or, int flags_and)
7768{
7769 struct i802_bss *bss = priv;
7770 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007771 struct nl_msg *msg;
7772 struct nlattr *flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007773 struct nl80211_sta_flag_update upd;
7774
7775 msg = nlmsg_alloc();
7776 if (!msg)
7777 return -ENOMEM;
7778
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007779 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007780
7781 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
7782 if_nametoindex(bss->ifname));
7783 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
7784
7785 /*
7786 * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
7787 * can be removed eventually.
7788 */
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007789 flags = nla_nest_start(msg, NL80211_ATTR_STA_FLAGS);
7790 if (!flags)
7791 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007792 if (total_flags & WPA_STA_AUTHORIZED)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007793 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_AUTHORIZED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007794
7795 if (total_flags & WPA_STA_WMM)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007796 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_WME);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007797
7798 if (total_flags & WPA_STA_SHORT_PREAMBLE)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007799 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_SHORT_PREAMBLE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007800
7801 if (total_flags & WPA_STA_MFP)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007802 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_MFP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007803
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007804 if (total_flags & WPA_STA_TDLS_PEER)
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007805 NLA_PUT_FLAG(msg, NL80211_STA_FLAG_TDLS_PEER);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007806
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07007807 nla_nest_end(msg, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007808
7809 os_memset(&upd, 0, sizeof(upd));
7810 upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
7811 upd.set = sta_flags_nl80211(flags_or);
7812 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
7813
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007814 return send_and_recv_msgs(drv, msg, NULL, NULL);
7815 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007816 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007817 return -ENOBUFS;
7818}
7819
7820
7821static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
7822 struct wpa_driver_associate_params *params)
7823{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007824 enum nl80211_iftype nlmode, old_mode;
7825 struct hostapd_freq_params freq = {
7826 .freq = params->freq,
7827 };
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007828
7829 if (params->p2p) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007830 wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
7831 "group (GO)");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007832 nlmode = NL80211_IFTYPE_P2P_GO;
7833 } else
7834 nlmode = NL80211_IFTYPE_AP;
7835
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007836 old_mode = drv->nlmode;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007837 if (wpa_driver_nl80211_set_mode(drv->first_bss, nlmode)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007838 nl80211_remove_monitor_interface(drv);
7839 return -1;
7840 }
7841
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007842 if (wpa_driver_nl80211_set_freq(drv->first_bss, &freq)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007843 if (old_mode != nlmode)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007844 wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007845 nl80211_remove_monitor_interface(drv);
7846 return -1;
7847 }
7848
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007849 return 0;
7850}
7851
7852
7853static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv)
7854{
7855 struct nl_msg *msg;
7856 int ret = -1;
7857
7858 msg = nlmsg_alloc();
7859 if (!msg)
7860 return -1;
7861
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007862 nl80211_cmd(drv, msg, 0, NL80211_CMD_LEAVE_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007863 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7864 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7865 msg = NULL;
7866 if (ret) {
7867 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
7868 "(%s)", ret, strerror(-ret));
7869 goto nla_put_failure;
7870 }
7871
7872 ret = 0;
7873 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS request sent successfully");
7874
7875nla_put_failure:
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007876 if (wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt56052862013-10-04 10:23:25 -07007877 NL80211_IFTYPE_STATION)) {
7878 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
7879 "station mode");
7880 }
7881
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007882 nlmsg_free(msg);
7883 return ret;
7884}
7885
7886
7887static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
7888 struct wpa_driver_associate_params *params)
7889{
7890 struct nl_msg *msg;
7891 int ret = -1;
7892 int count = 0;
7893
7894 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
7895
Dmitry Shmidtcce06662013-11-04 18:44:24 -08007896 if (wpa_driver_nl80211_set_mode(drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007897 NL80211_IFTYPE_ADHOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007898 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
7899 "IBSS mode");
7900 return -1;
7901 }
7902
7903retry:
7904 msg = nlmsg_alloc();
7905 if (!msg)
7906 return -1;
7907
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007908 nl80211_cmd(drv, msg, 0, NL80211_CMD_JOIN_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007909 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7910
7911 if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
7912 goto nla_put_failure;
7913
7914 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
7915 params->ssid, params->ssid_len);
7916 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
7917 params->ssid);
7918 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
7919 drv->ssid_len = params->ssid_len;
7920
7921 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
7922 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
7923
7924 ret = nl80211_set_conn_keys(params, msg);
7925 if (ret)
7926 goto nla_put_failure;
7927
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007928 if (params->bssid && params->fixed_bssid) {
7929 wpa_printf(MSG_DEBUG, " * BSSID=" MACSTR,
7930 MAC2STR(params->bssid));
7931 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
7932 }
7933
7934 if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
7935 params->key_mgmt_suite == KEY_MGMT_PSK ||
7936 params->key_mgmt_suite == KEY_MGMT_802_1X_SHA256 ||
7937 params->key_mgmt_suite == KEY_MGMT_PSK_SHA256) {
7938 wpa_printf(MSG_DEBUG, " * control port");
7939 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
7940 }
7941
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007942 if (params->wpa_ie) {
7943 wpa_hexdump(MSG_DEBUG,
7944 " * Extra IEs for Beacon/Probe Response frames",
7945 params->wpa_ie, params->wpa_ie_len);
7946 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
7947 params->wpa_ie);
7948 }
7949
7950 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
7951 msg = NULL;
7952 if (ret) {
7953 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
7954 ret, strerror(-ret));
7955 count++;
7956 if (ret == -EALREADY && count == 1) {
7957 wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after "
7958 "forced leave");
7959 nl80211_leave_ibss(drv);
7960 nlmsg_free(msg);
7961 goto retry;
7962 }
7963
7964 goto nla_put_failure;
7965 }
7966 ret = 0;
7967 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS request sent successfully");
7968
7969nla_put_failure:
7970 nlmsg_free(msg);
7971 return ret;
7972}
7973
7974
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007975static int wpa_driver_nl80211_try_connect(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007976 struct wpa_driver_nl80211_data *drv,
7977 struct wpa_driver_associate_params *params)
7978{
7979 struct nl_msg *msg;
7980 enum nl80211_auth_type type;
7981 int ret = 0;
7982 int algs;
7983
7984 msg = nlmsg_alloc();
7985 if (!msg)
7986 return -1;
7987
7988 wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007989 nl80211_cmd(drv, msg, 0, NL80211_CMD_CONNECT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007990
7991 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7992 if (params->bssid) {
7993 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
7994 MAC2STR(params->bssid));
7995 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
7996 }
7997 if (params->freq) {
7998 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
7999 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07008000 drv->assoc_freq = params->freq;
8001 } else
8002 drv->assoc_freq = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008003 if (params->bg_scan_period >= 0) {
8004 wpa_printf(MSG_DEBUG, " * bg scan period=%d",
8005 params->bg_scan_period);
8006 NLA_PUT_U16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
8007 params->bg_scan_period);
8008 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008009 if (params->ssid) {
8010 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
8011 params->ssid, params->ssid_len);
8012 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
8013 params->ssid);
8014 if (params->ssid_len > sizeof(drv->ssid))
8015 goto nla_put_failure;
8016 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
8017 drv->ssid_len = params->ssid_len;
8018 }
8019 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
8020 if (params->wpa_ie)
8021 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
8022 params->wpa_ie);
8023
8024 algs = 0;
8025 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
8026 algs++;
8027 if (params->auth_alg & WPA_AUTH_ALG_SHARED)
8028 algs++;
8029 if (params->auth_alg & WPA_AUTH_ALG_LEAP)
8030 algs++;
8031 if (algs > 1) {
8032 wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic "
8033 "selection");
8034 goto skip_auth_type;
8035 }
8036
8037 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
8038 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
8039 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
8040 type = NL80211_AUTHTYPE_SHARED_KEY;
8041 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
8042 type = NL80211_AUTHTYPE_NETWORK_EAP;
8043 else if (params->auth_alg & WPA_AUTH_ALG_FT)
8044 type = NL80211_AUTHTYPE_FT;
8045 else
8046 goto nla_put_failure;
8047
8048 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
8049 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
8050
8051skip_auth_type:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008052 if (params->wpa_proto) {
8053 enum nl80211_wpa_versions ver = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008054
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008055 if (params->wpa_proto & WPA_PROTO_WPA)
8056 ver |= NL80211_WPA_VERSION_1;
8057 if (params->wpa_proto & WPA_PROTO_RSN)
8058 ver |= NL80211_WPA_VERSION_2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008059
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008060 wpa_printf(MSG_DEBUG, " * WPA Versions 0x%x", ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008061 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
8062 }
8063
8064 if (params->pairwise_suite != CIPHER_NONE) {
8065 int cipher;
8066
8067 switch (params->pairwise_suite) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008068 case CIPHER_SMS4:
8069 cipher = WLAN_CIPHER_SUITE_SMS4;
8070 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008071 case CIPHER_WEP40:
8072 cipher = WLAN_CIPHER_SUITE_WEP40;
8073 break;
8074 case CIPHER_WEP104:
8075 cipher = WLAN_CIPHER_SUITE_WEP104;
8076 break;
8077 case CIPHER_CCMP:
8078 cipher = WLAN_CIPHER_SUITE_CCMP;
8079 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008080 case CIPHER_GCMP:
8081 cipher = WLAN_CIPHER_SUITE_GCMP;
8082 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008083 case CIPHER_TKIP:
8084 default:
8085 cipher = WLAN_CIPHER_SUITE_TKIP;
8086 break;
8087 }
8088 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
8089 }
8090
8091 if (params->group_suite != CIPHER_NONE) {
8092 int cipher;
8093
8094 switch (params->group_suite) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008095 case CIPHER_SMS4:
8096 cipher = WLAN_CIPHER_SUITE_SMS4;
8097 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008098 case CIPHER_WEP40:
8099 cipher = WLAN_CIPHER_SUITE_WEP40;
8100 break;
8101 case CIPHER_WEP104:
8102 cipher = WLAN_CIPHER_SUITE_WEP104;
8103 break;
8104 case CIPHER_CCMP:
8105 cipher = WLAN_CIPHER_SUITE_CCMP;
8106 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008107 case CIPHER_GCMP:
8108 cipher = WLAN_CIPHER_SUITE_GCMP;
8109 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008110 case CIPHER_TKIP:
8111 default:
8112 cipher = WLAN_CIPHER_SUITE_TKIP;
8113 break;
8114 }
8115 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
8116 }
8117
8118 if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008119 params->key_mgmt_suite == KEY_MGMT_PSK ||
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008120 params->key_mgmt_suite == KEY_MGMT_FT_802_1X ||
8121 params->key_mgmt_suite == KEY_MGMT_FT_PSK ||
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008122 params->key_mgmt_suite == KEY_MGMT_CCKM) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008123 int mgmt = WLAN_AKM_SUITE_PSK;
8124
8125 switch (params->key_mgmt_suite) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008126 case KEY_MGMT_CCKM:
8127 mgmt = WLAN_AKM_SUITE_CCKM;
8128 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008129 case KEY_MGMT_802_1X:
8130 mgmt = WLAN_AKM_SUITE_8021X;
8131 break;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07008132 case KEY_MGMT_FT_802_1X:
8133 mgmt = WLAN_AKM_SUITE_FT_8021X;
8134 break;
8135 case KEY_MGMT_FT_PSK:
8136 mgmt = WLAN_AKM_SUITE_FT_PSK;
8137 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008138 case KEY_MGMT_PSK:
8139 default:
8140 mgmt = WLAN_AKM_SUITE_PSK;
8141 break;
8142 }
8143 NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);
8144 }
8145
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008146#ifdef CONFIG_IEEE80211W
8147 if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)
8148 NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);
8149#endif /* CONFIG_IEEE80211W */
8150
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008151 if (params->disable_ht)
8152 NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);
8153
8154 if (params->htcaps && params->htcaps_mask) {
8155 int sz = sizeof(struct ieee80211_ht_capabilities);
8156 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);
8157 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
8158 params->htcaps_mask);
8159 }
8160
Dmitry Shmidt2f023192013-03-12 12:44:17 -07008161#ifdef CONFIG_VHT_OVERRIDES
8162 if (params->disable_vht) {
8163 wpa_printf(MSG_DEBUG, " * VHT disabled");
8164 NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
8165 }
8166
8167 if (params->vhtcaps && params->vhtcaps_mask) {
8168 int sz = sizeof(struct ieee80211_vht_capabilities);
8169 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
8170 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
8171 params->vhtcaps_mask);
8172 }
8173#endif /* CONFIG_VHT_OVERRIDES */
8174
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008175 ret = nl80211_set_conn_keys(params, msg);
8176 if (ret)
8177 goto nla_put_failure;
8178
8179 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8180 msg = NULL;
8181 if (ret) {
8182 wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
8183 "(%s)", ret, strerror(-ret));
8184 goto nla_put_failure;
8185 }
8186 ret = 0;
8187 wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully");
8188
8189nla_put_failure:
8190 nlmsg_free(msg);
8191 return ret;
8192
8193}
8194
8195
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008196static int wpa_driver_nl80211_connect(
8197 struct wpa_driver_nl80211_data *drv,
8198 struct wpa_driver_associate_params *params)
8199{
8200 int ret = wpa_driver_nl80211_try_connect(drv, params);
8201 if (ret == -EALREADY) {
8202 /*
8203 * cfg80211 does not currently accept new connections if
8204 * we are already connected. As a workaround, force
8205 * disconnection and try again.
8206 */
8207 wpa_printf(MSG_DEBUG, "nl80211: Explicitly "
8208 "disconnecting before reassociation "
8209 "attempt");
8210 if (wpa_driver_nl80211_disconnect(
8211 drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
8212 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008213 ret = wpa_driver_nl80211_try_connect(drv, params);
8214 }
8215 return ret;
8216}
8217
8218
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008219static int wpa_driver_nl80211_associate(
8220 void *priv, struct wpa_driver_associate_params *params)
8221{
8222 struct i802_bss *bss = priv;
8223 struct wpa_driver_nl80211_data *drv = bss->drv;
8224 int ret = -1;
8225 struct nl_msg *msg;
8226
8227 if (params->mode == IEEE80211_MODE_AP)
8228 return wpa_driver_nl80211_ap(drv, params);
8229
8230 if (params->mode == IEEE80211_MODE_IBSS)
8231 return wpa_driver_nl80211_ibss(drv, params);
8232
8233 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008234 enum nl80211_iftype nlmode = params->p2p ?
8235 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
8236
8237 if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008238 return -1;
8239 return wpa_driver_nl80211_connect(drv, params);
8240 }
8241
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008242 nl80211_mark_disconnected(drv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008243
8244 msg = nlmsg_alloc();
8245 if (!msg)
8246 return -1;
8247
8248 wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)",
8249 drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008250 nl80211_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008251
8252 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8253 if (params->bssid) {
8254 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
8255 MAC2STR(params->bssid));
8256 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
8257 }
8258 if (params->freq) {
8259 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
8260 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
8261 drv->assoc_freq = params->freq;
8262 } else
8263 drv->assoc_freq = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008264 if (params->bg_scan_period >= 0) {
8265 wpa_printf(MSG_DEBUG, " * bg scan period=%d",
8266 params->bg_scan_period);
8267 NLA_PUT_U16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
8268 params->bg_scan_period);
8269 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008270 if (params->ssid) {
8271 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
8272 params->ssid, params->ssid_len);
8273 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
8274 params->ssid);
8275 if (params->ssid_len > sizeof(drv->ssid))
8276 goto nla_put_failure;
8277 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
8278 drv->ssid_len = params->ssid_len;
8279 }
8280 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
8281 if (params->wpa_ie)
8282 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
8283 params->wpa_ie);
8284
8285 if (params->pairwise_suite != CIPHER_NONE) {
8286 int cipher;
8287
8288 switch (params->pairwise_suite) {
8289 case CIPHER_WEP40:
8290 cipher = WLAN_CIPHER_SUITE_WEP40;
8291 break;
8292 case CIPHER_WEP104:
8293 cipher = WLAN_CIPHER_SUITE_WEP104;
8294 break;
8295 case CIPHER_CCMP:
8296 cipher = WLAN_CIPHER_SUITE_CCMP;
8297 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008298 case CIPHER_GCMP:
8299 cipher = WLAN_CIPHER_SUITE_GCMP;
8300 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008301 case CIPHER_TKIP:
8302 default:
8303 cipher = WLAN_CIPHER_SUITE_TKIP;
8304 break;
8305 }
8306 wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher);
8307 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
8308 }
8309
8310 if (params->group_suite != CIPHER_NONE) {
8311 int cipher;
8312
8313 switch (params->group_suite) {
8314 case CIPHER_WEP40:
8315 cipher = WLAN_CIPHER_SUITE_WEP40;
8316 break;
8317 case CIPHER_WEP104:
8318 cipher = WLAN_CIPHER_SUITE_WEP104;
8319 break;
8320 case CIPHER_CCMP:
8321 cipher = WLAN_CIPHER_SUITE_CCMP;
8322 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008323 case CIPHER_GCMP:
8324 cipher = WLAN_CIPHER_SUITE_GCMP;
8325 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008326 case CIPHER_TKIP:
8327 default:
8328 cipher = WLAN_CIPHER_SUITE_TKIP;
8329 break;
8330 }
8331 wpa_printf(MSG_DEBUG, " * group=0x%x", cipher);
8332 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
8333 }
8334
8335#ifdef CONFIG_IEEE80211W
8336 if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)
8337 NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);
8338#endif /* CONFIG_IEEE80211W */
8339
8340 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
8341
8342 if (params->prev_bssid) {
8343 wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
8344 MAC2STR(params->prev_bssid));
8345 NLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
8346 params->prev_bssid);
8347 }
8348
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008349 if (params->disable_ht)
8350 NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);
8351
8352 if (params->htcaps && params->htcaps_mask) {
8353 int sz = sizeof(struct ieee80211_ht_capabilities);
8354 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);
8355 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
8356 params->htcaps_mask);
8357 }
8358
Dmitry Shmidt2f023192013-03-12 12:44:17 -07008359#ifdef CONFIG_VHT_OVERRIDES
8360 if (params->disable_vht) {
8361 wpa_printf(MSG_DEBUG, " * VHT disabled");
8362 NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
8363 }
8364
8365 if (params->vhtcaps && params->vhtcaps_mask) {
8366 int sz = sizeof(struct ieee80211_vht_capabilities);
8367 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
8368 NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
8369 params->vhtcaps_mask);
8370 }
8371#endif /* CONFIG_VHT_OVERRIDES */
8372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008373 if (params->p2p)
8374 wpa_printf(MSG_DEBUG, " * P2P group");
8375
8376 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8377 msg = NULL;
8378 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008379 wpa_dbg(drv->ctx, MSG_DEBUG,
8380 "nl80211: MLME command failed (assoc): ret=%d (%s)",
8381 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008382 nl80211_dump_scan(drv);
8383 goto nla_put_failure;
8384 }
8385 ret = 0;
8386 wpa_printf(MSG_DEBUG, "nl80211: Association request send "
8387 "successfully");
8388
8389nla_put_failure:
8390 nlmsg_free(msg);
8391 return ret;
8392}
8393
8394
8395static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008396 int ifindex, enum nl80211_iftype mode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008397{
8398 struct nl_msg *msg;
8399 int ret = -ENOBUFS;
8400
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008401 wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)",
8402 ifindex, mode, nl80211_iftype_str(mode));
8403
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008404 msg = nlmsg_alloc();
8405 if (!msg)
8406 return -ENOMEM;
8407
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008408 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008409 if (nl80211_set_iface_id(msg, drv->first_bss) < 0)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008410 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008411 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);
8412
8413 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008414 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008415 if (!ret)
8416 return 0;
8417nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008418 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008419 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
8420 " %d (%s)", ifindex, mode, ret, strerror(-ret));
8421 return ret;
8422}
8423
8424
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008425static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
8426 enum nl80211_iftype nlmode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008427{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008428 struct wpa_driver_nl80211_data *drv = bss->drv;
8429 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008430 int i;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008431 int was_ap = is_ap_interface(drv->nlmode);
8432 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008433
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008434 res = nl80211_set_mode(drv, drv->ifindex, nlmode);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008435 if (res && nlmode == nl80211_get_ifmode(bss))
8436 res = 0;
8437
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008438 if (res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008439 drv->nlmode = nlmode;
8440 ret = 0;
8441 goto done;
8442 }
8443
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008444 if (res == -ENODEV)
8445 return -1;
8446
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008447 if (nlmode == drv->nlmode) {
8448 wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
8449 "requested mode - ignore error");
8450 ret = 0;
8451 goto done; /* Already in the requested mode */
8452 }
8453
8454 /* mac80211 doesn't allow mode changes while the device is up, so
8455 * take the device down, try to set the mode again, and bring the
8456 * device back up.
8457 */
8458 wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
8459 "interface down");
8460 for (i = 0; i < 10; i++) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008461 res = i802_set_iface_flags(bss, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008462 if (res == -EACCES || res == -ENODEV)
8463 break;
8464 if (res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008465 /* Try to set the mode again while the interface is
8466 * down */
8467 ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008468 if (ret == -EACCES)
8469 break;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008470 res = i802_set_iface_flags(bss, 1);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008471 if (res && !ret)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008472 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008473 else if (ret != -EBUSY)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008474 break;
8475 } else
8476 wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
8477 "interface down");
8478 os_sleep(0, 100000);
8479 }
8480
8481 if (!ret) {
8482 wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
8483 "interface is down");
8484 drv->nlmode = nlmode;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008485 drv->ignore_if_down_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008486 }
8487
8488done:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008489 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008490 wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
8491 "from %d failed", nlmode, drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008492 return ret;
8493 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008494
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008495 if (is_p2p_net_interface(nlmode))
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008496 nl80211_disable_11b_rates(drv, drv->ifindex, 1);
8497 else if (drv->disabled_11b_rates)
8498 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
8499
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008500 if (is_ap_interface(nlmode)) {
8501 nl80211_mgmt_unsubscribe(bss, "start AP");
8502 /* Setup additional AP mode functionality if needed */
8503 if (nl80211_setup_ap(bss))
8504 return -1;
8505 } else if (was_ap) {
8506 /* Remove additional AP mode functionality */
8507 nl80211_teardown_ap(bss);
8508 } else {
8509 nl80211_mgmt_unsubscribe(bss, "mode change");
8510 }
8511
Dmitry Shmidt04949592012-07-19 12:16:46 -07008512 if (!bss->in_deinit && !is_ap_interface(nlmode) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008513 nl80211_mgmt_subscribe_non_ap(bss) < 0)
8514 wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
8515 "frame processing - ignore for now");
8516
8517 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008518}
8519
8520
8521static int wpa_driver_nl80211_get_capa(void *priv,
8522 struct wpa_driver_capa *capa)
8523{
8524 struct i802_bss *bss = priv;
8525 struct wpa_driver_nl80211_data *drv = bss->drv;
8526 if (!drv->has_capability)
8527 return -1;
8528 os_memcpy(capa, &drv->capa, sizeof(*capa));
Dmitry Shmidt444d5672013-04-01 13:08:44 -07008529 if (drv->extended_capa && drv->extended_capa_mask) {
8530 capa->extended_capa = drv->extended_capa;
8531 capa->extended_capa_mask = drv->extended_capa_mask;
8532 capa->extended_capa_len = drv->extended_capa_len;
8533 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07008534
8535 if ((capa->flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
8536 !drv->allow_p2p_device) {
8537 wpa_printf(MSG_DEBUG, "nl80211: Do not indicate P2P_DEVICE support (p2p_device=1 driver param not specified)");
8538 capa->flags &= ~WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE;
8539 }
8540
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008541 return 0;
8542}
8543
8544
8545static int wpa_driver_nl80211_set_operstate(void *priv, int state)
8546{
8547 struct i802_bss *bss = priv;
8548 struct wpa_driver_nl80211_data *drv = bss->drv;
8549
8550 wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
8551 __func__, drv->operstate, state, state ? "UP" : "DORMANT");
8552 drv->operstate = state;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008553 return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008554 state ? IF_OPER_UP : IF_OPER_DORMANT);
8555}
8556
8557
8558static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
8559{
8560 struct i802_bss *bss = priv;
8561 struct wpa_driver_nl80211_data *drv = bss->drv;
8562 struct nl_msg *msg;
8563 struct nl80211_sta_flag_update upd;
8564
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07008565 wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
8566 MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
8567
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008568 msg = nlmsg_alloc();
8569 if (!msg)
8570 return -ENOMEM;
8571
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008572 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008573
8574 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
8575 if_nametoindex(bss->ifname));
8576 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
8577
8578 os_memset(&upd, 0, sizeof(upd));
8579 upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);
8580 if (authorized)
8581 upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);
8582 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
8583
8584 return send_and_recv_msgs(drv, msg, NULL, NULL);
8585 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008586 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008587 return -ENOBUFS;
8588}
8589
8590
Jouni Malinen75ecf522011-06-27 15:19:46 -07008591/* Set kernel driver on given frequency (MHz) */
8592static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008593{
Jouni Malinen75ecf522011-06-27 15:19:46 -07008594 struct i802_bss *bss = priv;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008595 return wpa_driver_nl80211_set_freq(bss, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008596}
8597
8598
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008599static inline int min_int(int a, int b)
8600{
8601 if (a < b)
8602 return a;
8603 return b;
8604}
8605
8606
8607static int get_key_handler(struct nl_msg *msg, void *arg)
8608{
8609 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8610 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8611
8612 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8613 genlmsg_attrlen(gnlh, 0), NULL);
8614
8615 /*
8616 * TODO: validate the key index and mac address!
8617 * Otherwise, there's a race condition as soon as
8618 * the kernel starts sending key notifications.
8619 */
8620
8621 if (tb[NL80211_ATTR_KEY_SEQ])
8622 memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
8623 min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
8624 return NL_SKIP;
8625}
8626
8627
8628static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
8629 int idx, u8 *seq)
8630{
8631 struct i802_bss *bss = priv;
8632 struct wpa_driver_nl80211_data *drv = bss->drv;
8633 struct nl_msg *msg;
8634
8635 msg = nlmsg_alloc();
8636 if (!msg)
8637 return -ENOMEM;
8638
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008639 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008640
8641 if (addr)
8642 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
8643 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
8644 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
8645
8646 memset(seq, 0, 6);
8647
8648 return send_and_recv_msgs(drv, msg, get_key_handler, seq);
8649 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008650 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008651 return -ENOBUFS;
8652}
8653
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008654
8655static int i802_set_rts(void *priv, int rts)
8656{
8657 struct i802_bss *bss = priv;
8658 struct wpa_driver_nl80211_data *drv = bss->drv;
8659 struct nl_msg *msg;
8660 int ret = -ENOBUFS;
8661 u32 val;
8662
8663 msg = nlmsg_alloc();
8664 if (!msg)
8665 return -ENOMEM;
8666
8667 if (rts >= 2347)
8668 val = (u32) -1;
8669 else
8670 val = rts;
8671
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008672 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008673 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8674 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val);
8675
8676 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008677 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008678 if (!ret)
8679 return 0;
8680nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008681 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008682 wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
8683 "%d (%s)", rts, ret, strerror(-ret));
8684 return ret;
8685}
8686
8687
8688static int i802_set_frag(void *priv, int frag)
8689{
8690 struct i802_bss *bss = priv;
8691 struct wpa_driver_nl80211_data *drv = bss->drv;
8692 struct nl_msg *msg;
8693 int ret = -ENOBUFS;
8694 u32 val;
8695
8696 msg = nlmsg_alloc();
8697 if (!msg)
8698 return -ENOMEM;
8699
8700 if (frag >= 2346)
8701 val = (u32) -1;
8702 else
8703 val = frag;
8704
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008705 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008706 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8707 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val);
8708
8709 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008710 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008711 if (!ret)
8712 return 0;
8713nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008714 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008715 wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
8716 "%d: %d (%s)", frag, ret, strerror(-ret));
8717 return ret;
8718}
8719
8720
8721static int i802_flush(void *priv)
8722{
8723 struct i802_bss *bss = priv;
8724 struct wpa_driver_nl80211_data *drv = bss->drv;
8725 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008726 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008727
8728 msg = nlmsg_alloc();
8729 if (!msg)
8730 return -1;
8731
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07008732 wpa_printf(MSG_DEBUG, "nl80211: flush -> DEL_STATION %s (all)",
8733 bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008734 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008735
8736 /*
8737 * XXX: FIX! this needs to flush all VLANs too
8738 */
8739 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
8740 if_nametoindex(bss->ifname));
8741
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008742 res = send_and_recv_msgs(drv, msg, NULL, NULL);
8743 if (res) {
8744 wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
8745 "(%s)", res, strerror(-res));
8746 }
8747 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008748 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008749 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008750 return -ENOBUFS;
8751}
8752
8753
8754static int get_sta_handler(struct nl_msg *msg, void *arg)
8755{
8756 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8757 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8758 struct hostap_sta_driver_data *data = arg;
8759 struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
8760 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
8761 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
8762 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
8763 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
8764 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
8765 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03008766 [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008767 };
8768
8769 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8770 genlmsg_attrlen(gnlh, 0), NULL);
8771
8772 /*
8773 * TODO: validate the interface and mac address!
8774 * Otherwise, there's a race condition as soon as
8775 * the kernel starts sending station notifications.
8776 */
8777
8778 if (!tb[NL80211_ATTR_STA_INFO]) {
8779 wpa_printf(MSG_DEBUG, "sta stats missing!");
8780 return NL_SKIP;
8781 }
8782 if (nla_parse_nested(stats, NL80211_STA_INFO_MAX,
8783 tb[NL80211_ATTR_STA_INFO],
8784 stats_policy)) {
8785 wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
8786 return NL_SKIP;
8787 }
8788
8789 if (stats[NL80211_STA_INFO_INACTIVE_TIME])
8790 data->inactive_msec =
8791 nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);
8792 if (stats[NL80211_STA_INFO_RX_BYTES])
8793 data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
8794 if (stats[NL80211_STA_INFO_TX_BYTES])
8795 data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
8796 if (stats[NL80211_STA_INFO_RX_PACKETS])
8797 data->rx_packets =
8798 nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
8799 if (stats[NL80211_STA_INFO_TX_PACKETS])
8800 data->tx_packets =
8801 nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
Jouni Malinen1e6c57f2012-09-05 17:07:03 +03008802 if (stats[NL80211_STA_INFO_TX_FAILED])
8803 data->tx_retry_failed =
8804 nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008805
8806 return NL_SKIP;
8807}
8808
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008809static int i802_read_sta_data(struct i802_bss *bss,
8810 struct hostap_sta_driver_data *data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008811 const u8 *addr)
8812{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008813 struct wpa_driver_nl80211_data *drv = bss->drv;
8814 struct nl_msg *msg;
8815
8816 os_memset(data, 0, sizeof(*data));
8817 msg = nlmsg_alloc();
8818 if (!msg)
8819 return -ENOMEM;
8820
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008821 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008822
8823 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
8824 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
8825
8826 return send_and_recv_msgs(drv, msg, get_sta_handler, data);
8827 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008828 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008829 return -ENOBUFS;
8830}
8831
8832
8833static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
8834 int cw_min, int cw_max, int burst_time)
8835{
8836 struct i802_bss *bss = priv;
8837 struct wpa_driver_nl80211_data *drv = bss->drv;
8838 struct nl_msg *msg;
8839 struct nlattr *txq, *params;
8840
8841 msg = nlmsg_alloc();
8842 if (!msg)
8843 return -1;
8844
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008845 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008846
8847 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
8848
8849 txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);
8850 if (!txq)
8851 goto nla_put_failure;
8852
8853 /* We are only sending parameters for a single TXQ at a time */
8854 params = nla_nest_start(msg, 1);
8855 if (!params)
8856 goto nla_put_failure;
8857
8858 switch (queue) {
8859 case 0:
8860 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO);
8861 break;
8862 case 1:
8863 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI);
8864 break;
8865 case 2:
8866 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE);
8867 break;
8868 case 3:
8869 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK);
8870 break;
8871 }
8872 /* Burst time is configured in units of 0.1 msec and TXOP parameter in
8873 * 32 usec, so need to convert the value here. */
8874 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32);
8875 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min);
8876 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max);
8877 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs);
8878
8879 nla_nest_end(msg, params);
8880
8881 nla_nest_end(msg, txq);
8882
8883 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
8884 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008885 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008886 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008887 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008888 return -1;
8889}
8890
8891
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008892static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008893 const char *ifname, int vlan_id)
8894{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008895 struct wpa_driver_nl80211_data *drv = bss->drv;
8896 struct nl_msg *msg;
8897 int ret = -ENOBUFS;
8898
8899 msg = nlmsg_alloc();
8900 if (!msg)
8901 return -ENOMEM;
8902
Dmitry Shmidtcce06662013-11-04 18:44:24 -08008903 wpa_printf(MSG_DEBUG, "nl80211: %s[%d]: set_sta_vlan(" MACSTR
8904 ", ifname=%s[%d], vlan_id=%d)",
8905 bss->ifname, if_nametoindex(bss->ifname),
8906 MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008907 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008908
8909 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
8910 if_nametoindex(bss->ifname));
8911 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
8912 NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN,
8913 if_nametoindex(ifname));
8914
8915 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008916 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008917 if (ret < 0) {
8918 wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
8919 MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
8920 MAC2STR(addr), ifname, vlan_id, ret,
8921 strerror(-ret));
8922 }
8923 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008924 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008925 return ret;
8926}
8927
8928
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008929static int i802_get_inact_sec(void *priv, const u8 *addr)
8930{
8931 struct hostap_sta_driver_data data;
8932 int ret;
8933
8934 data.inactive_msec = (unsigned long) -1;
8935 ret = i802_read_sta_data(priv, &data, addr);
8936 if (ret || data.inactive_msec == (unsigned long) -1)
8937 return -1;
8938 return data.inactive_msec / 1000;
8939}
8940
8941
8942static int i802_sta_clear_stats(void *priv, const u8 *addr)
8943{
8944#if 0
8945 /* TODO */
8946#endif
8947 return 0;
8948}
8949
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008950
8951static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
8952 int reason)
8953{
8954 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008955 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008956 struct ieee80211_mgmt mgmt;
8957
Dmitry Shmidt04949592012-07-19 12:16:46 -07008958 if (drv->device_ap_sme)
8959 return wpa_driver_nl80211_sta_remove(bss, addr);
8960
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008961 memset(&mgmt, 0, sizeof(mgmt));
8962 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
8963 WLAN_FC_STYPE_DEAUTH);
8964 memcpy(mgmt.da, addr, ETH_ALEN);
8965 memcpy(mgmt.sa, own_addr, ETH_ALEN);
8966 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
8967 mgmt.u.deauth.reason_code = host_to_le16(reason);
8968 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
8969 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008970 sizeof(mgmt.u.deauth), 0, 0, 0, 0,
8971 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008972}
8973
8974
8975static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
8976 int reason)
8977{
8978 struct i802_bss *bss = priv;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008979 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008980 struct ieee80211_mgmt mgmt;
8981
Dmitry Shmidt04949592012-07-19 12:16:46 -07008982 if (drv->device_ap_sme)
8983 return wpa_driver_nl80211_sta_remove(bss, addr);
8984
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008985 memset(&mgmt, 0, sizeof(mgmt));
8986 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
8987 WLAN_FC_STYPE_DISASSOC);
8988 memcpy(mgmt.da, addr, ETH_ALEN);
8989 memcpy(mgmt.sa, own_addr, ETH_ALEN);
8990 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
8991 mgmt.u.disassoc.reason_code = host_to_le16(reason);
8992 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
8993 IEEE80211_HDRLEN +
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08008994 sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
8995 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008996}
8997
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008998
Jouni Malinen75ecf522011-06-27 15:19:46 -07008999static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9000{
9001 int i;
9002 int *old;
9003
9004 wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
9005 ifidx);
9006 for (i = 0; i < drv->num_if_indices; i++) {
9007 if (drv->if_indices[i] == 0) {
9008 drv->if_indices[i] = ifidx;
9009 return;
9010 }
9011 }
9012
9013 if (drv->if_indices != drv->default_if_indices)
9014 old = drv->if_indices;
9015 else
9016 old = NULL;
9017
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009018 drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
9019 sizeof(int));
Jouni Malinen75ecf522011-06-27 15:19:46 -07009020 if (!drv->if_indices) {
9021 if (!old)
9022 drv->if_indices = drv->default_if_indices;
9023 else
9024 drv->if_indices = old;
9025 wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
9026 "interfaces");
9027 wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
9028 return;
9029 } else if (!old)
9030 os_memcpy(drv->if_indices, drv->default_if_indices,
9031 sizeof(drv->default_if_indices));
9032 drv->if_indices[drv->num_if_indices] = ifidx;
9033 drv->num_if_indices++;
9034}
9035
9036
9037static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9038{
9039 int i;
9040
9041 for (i = 0; i < drv->num_if_indices; i++) {
9042 if (drv->if_indices[i] == ifidx) {
9043 drv->if_indices[i] = 0;
9044 break;
9045 }
9046 }
9047}
9048
9049
9050static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
9051{
9052 int i;
9053
9054 for (i = 0; i < drv->num_if_indices; i++)
9055 if (drv->if_indices[i] == ifidx)
9056 return 1;
9057
9058 return 0;
9059}
9060
9061
9062static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009063 const char *bridge_ifname, char *ifname_wds)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009064{
9065 struct i802_bss *bss = priv;
9066 struct wpa_driver_nl80211_data *drv = bss->drv;
9067 char name[IFNAMSIZ + 1];
9068
9069 os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009070 if (ifname_wds)
9071 os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
9072
Jouni Malinen75ecf522011-06-27 15:19:46 -07009073 wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
9074 " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
9075 if (val) {
9076 if (!if_nametoindex(name)) {
9077 if (nl80211_create_iface(drv, name,
9078 NL80211_IFTYPE_AP_VLAN,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009079 bss->addr, 1, NULL, NULL, 0) <
9080 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009081 return -1;
9082 if (bridge_ifname &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009083 linux_br_add_if(drv->global->ioctl_sock,
9084 bridge_ifname, name) < 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07009085 return -1;
9086 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009087 if (linux_set_iface_flags(drv->global->ioctl_sock, name, 1)) {
9088 wpa_printf(MSG_ERROR, "nl80211: Failed to set WDS STA "
9089 "interface %s up", name);
9090 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07009091 return i802_set_sta_vlan(priv, addr, name, 0);
9092 } else {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07009093 if (bridge_ifname)
9094 linux_br_del_if(drv->global->ioctl_sock, bridge_ifname,
9095 name);
9096
Jouni Malinen75ecf522011-06-27 15:19:46 -07009097 i802_set_sta_vlan(priv, addr, bss->ifname, 0);
9098 return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN,
9099 name);
9100 }
9101}
9102
9103
9104static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
9105{
9106 struct wpa_driver_nl80211_data *drv = eloop_ctx;
9107 struct sockaddr_ll lladdr;
9108 unsigned char buf[3000];
9109 int len;
9110 socklen_t fromlen = sizeof(lladdr);
9111
9112 len = recvfrom(sock, buf, sizeof(buf), 0,
9113 (struct sockaddr *)&lladdr, &fromlen);
9114 if (len < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009115 wpa_printf(MSG_ERROR, "nl80211: EAPOL recv failed: %s",
9116 strerror(errno));
Jouni Malinen75ecf522011-06-27 15:19:46 -07009117 return;
9118 }
9119
9120 if (have_ifidx(drv, lladdr.sll_ifindex))
9121 drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
9122}
9123
9124
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009125static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
9126 struct i802_bss *bss,
9127 const char *brname, const char *ifname)
9128{
9129 int ifindex;
9130 char in_br[IFNAMSIZ];
9131
9132 os_strlcpy(bss->brname, brname, IFNAMSIZ);
9133 ifindex = if_nametoindex(brname);
9134 if (ifindex == 0) {
9135 /*
9136 * Bridge was configured, but the bridge device does
9137 * not exist. Try to add it now.
9138 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009139 if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009140 wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
9141 "bridge interface %s: %s",
9142 brname, strerror(errno));
9143 return -1;
9144 }
9145 bss->added_bridge = 1;
9146 add_ifidx(drv, if_nametoindex(brname));
9147 }
9148
9149 if (linux_br_get(in_br, ifname) == 0) {
9150 if (os_strcmp(in_br, brname) == 0)
9151 return 0; /* already in the bridge */
9152
9153 wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
9154 "bridge %s", ifname, in_br);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009155 if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
9156 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009157 wpa_printf(MSG_ERROR, "nl80211: Failed to "
9158 "remove interface %s from bridge "
9159 "%s: %s",
9160 ifname, brname, strerror(errno));
9161 return -1;
9162 }
9163 }
9164
9165 wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
9166 ifname, brname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009167 if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009168 wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
9169 "into bridge %s: %s",
9170 ifname, brname, strerror(errno));
9171 return -1;
9172 }
9173 bss->added_if_into_bridge = 1;
9174
9175 return 0;
9176}
9177
9178
9179static void *i802_init(struct hostapd_data *hapd,
9180 struct wpa_init_params *params)
9181{
9182 struct wpa_driver_nl80211_data *drv;
9183 struct i802_bss *bss;
9184 size_t i;
9185 char brname[IFNAMSIZ];
9186 int ifindex, br_ifindex;
9187 int br_added = 0;
9188
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08009189 bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
9190 params->global_priv, 1,
9191 params->bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009192 if (bss == NULL)
9193 return NULL;
9194
9195 drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009196
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009197 if (linux_br_get(brname, params->ifname) == 0) {
9198 wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
9199 params->ifname, brname);
9200 br_ifindex = if_nametoindex(brname);
9201 } else {
9202 brname[0] = '\0';
9203 br_ifindex = 0;
9204 }
9205
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009206 for (i = 0; i < params->num_bridge; i++) {
9207 if (params->bridge[i]) {
9208 ifindex = if_nametoindex(params->bridge[i]);
9209 if (ifindex)
9210 add_ifidx(drv, ifindex);
9211 if (ifindex == br_ifindex)
9212 br_added = 1;
9213 }
9214 }
9215 if (!br_added && br_ifindex &&
9216 (params->num_bridge == 0 || !params->bridge[0]))
9217 add_ifidx(drv, br_ifindex);
9218
9219 /* start listening for EAPOL on the default AP interface */
9220 add_ifidx(drv, drv->ifindex);
9221
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009222 if (params->num_bridge && params->bridge[0] &&
9223 i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)
9224 goto failed;
9225
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009226 drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
9227 if (drv->eapol_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009228 wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s",
9229 strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009230 goto failed;
9231 }
9232
9233 if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
9234 {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009235 wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009236 goto failed;
9237 }
9238
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009239 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
9240 params->own_addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009241 goto failed;
9242
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009243 memcpy(bss->addr, params->own_addr, ETH_ALEN);
9244
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009245 return bss;
9246
9247failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009248 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009249 return NULL;
9250}
9251
9252
9253static void i802_deinit(void *priv)
9254{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009255 struct i802_bss *bss = priv;
9256 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009257}
9258
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009259
9260static enum nl80211_iftype wpa_driver_nl80211_if_type(
9261 enum wpa_driver_if_type type)
9262{
9263 switch (type) {
9264 case WPA_IF_STATION:
9265 return NL80211_IFTYPE_STATION;
9266 case WPA_IF_P2P_CLIENT:
9267 case WPA_IF_P2P_GROUP:
9268 return NL80211_IFTYPE_P2P_CLIENT;
9269 case WPA_IF_AP_VLAN:
9270 return NL80211_IFTYPE_AP_VLAN;
9271 case WPA_IF_AP_BSS:
9272 return NL80211_IFTYPE_AP;
9273 case WPA_IF_P2P_GO:
9274 return NL80211_IFTYPE_P2P_GO;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009275 case WPA_IF_P2P_DEVICE:
9276 return NL80211_IFTYPE_P2P_DEVICE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009277 }
9278 return -1;
9279}
9280
9281
9282#ifdef CONFIG_P2P
9283
9284static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr)
9285{
9286 struct wpa_driver_nl80211_data *drv;
9287 dl_list_for_each(drv, &global->interfaces,
9288 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009289 if (os_memcmp(addr, drv->first_bss->addr, ETH_ALEN) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009290 return 1;
9291 }
9292 return 0;
9293}
9294
9295
9296static int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv,
9297 u8 *new_addr)
9298{
9299 unsigned int idx;
9300
9301 if (!drv->global)
9302 return -1;
9303
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009304 os_memcpy(new_addr, drv->first_bss->addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009305 for (idx = 0; idx < 64; idx++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009306 new_addr[0] = drv->first_bss->addr[0] | 0x02;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009307 new_addr[0] ^= idx << 2;
9308 if (!nl80211_addr_in_use(drv->global, new_addr))
9309 break;
9310 }
9311 if (idx == 64)
9312 return -1;
9313
9314 wpa_printf(MSG_DEBUG, "nl80211: Assigned new P2P Interface Address "
9315 MACSTR, MAC2STR(new_addr));
9316
9317 return 0;
9318}
9319
9320#endif /* CONFIG_P2P */
9321
9322
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009323struct wdev_info {
9324 u64 wdev_id;
9325 int wdev_id_set;
9326 u8 macaddr[ETH_ALEN];
9327};
9328
9329static int nl80211_wdev_handler(struct nl_msg *msg, void *arg)
9330{
9331 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9332 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9333 struct wdev_info *wi = arg;
9334
9335 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9336 genlmsg_attrlen(gnlh, 0), NULL);
9337 if (tb[NL80211_ATTR_WDEV]) {
9338 wi->wdev_id = nla_get_u64(tb[NL80211_ATTR_WDEV]);
9339 wi->wdev_id_set = 1;
9340 }
9341
9342 if (tb[NL80211_ATTR_MAC])
9343 os_memcpy(wi->macaddr, nla_data(tb[NL80211_ATTR_MAC]),
9344 ETH_ALEN);
9345
9346 return NL_SKIP;
9347}
9348
9349
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009350static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
9351 const char *ifname, const u8 *addr,
9352 void *bss_ctx, void **drv_priv,
9353 char *force_ifname, u8 *if_addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009354 const char *bridge, int use_existing)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009355{
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009356 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009357 struct i802_bss *bss = priv;
9358 struct wpa_driver_nl80211_data *drv = bss->drv;
9359 int ifidx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009360 int added = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009361
9362 if (addr)
9363 os_memcpy(if_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009364 nlmode = wpa_driver_nl80211_if_type(type);
9365 if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
9366 struct wdev_info p2pdev_info;
9367
9368 os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
9369 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
9370 0, nl80211_wdev_handler,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009371 &p2pdev_info, use_existing);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009372 if (!p2pdev_info.wdev_id_set || ifidx != 0) {
9373 wpa_printf(MSG_ERROR, "nl80211: Failed to create a P2P Device interface %s",
9374 ifname);
9375 return -1;
9376 }
9377
9378 drv->global->if_add_wdevid = p2pdev_info.wdev_id;
9379 drv->global->if_add_wdevid_set = p2pdev_info.wdev_id_set;
9380 if (!is_zero_ether_addr(p2pdev_info.macaddr))
9381 os_memcpy(if_addr, p2pdev_info.macaddr, ETH_ALEN);
9382 wpa_printf(MSG_DEBUG, "nl80211: New P2P Device interface %s (0x%llx) created",
9383 ifname,
9384 (long long unsigned int) p2pdev_info.wdev_id);
9385 } else {
9386 ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009387 0, NULL, NULL, use_existing);
9388 if (use_existing && ifidx == -ENFILE) {
9389 added = 0;
9390 ifidx = if_nametoindex(ifname);
9391 } else if (ifidx < 0) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009392 return -1;
9393 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009394 }
9395
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009396 if (!addr) {
9397 if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
9398 os_memcpy(if_addr, bss->addr, ETH_ALEN);
9399 else if (linux_get_ifhwaddr(drv->global->ioctl_sock,
9400 bss->ifname, if_addr) < 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009401 if (added)
9402 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009403 return -1;
9404 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009405 }
9406
9407#ifdef CONFIG_P2P
9408 if (!addr &&
9409 (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||
9410 type == WPA_IF_P2P_GO)) {
9411 /* Enforce unique P2P Interface Address */
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009412 u8 new_addr[ETH_ALEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009413
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009414 if (linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009415 new_addr) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009416 nl80211_remove_iface(drv, ifidx);
9417 return -1;
9418 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009419 if (nl80211_addr_in_use(drv->global, new_addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009420 wpa_printf(MSG_DEBUG, "nl80211: Allocate new address "
9421 "for P2P group interface");
9422 if (nl80211_p2p_interface_addr(drv, new_addr) < 0) {
9423 nl80211_remove_iface(drv, ifidx);
9424 return -1;
9425 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009426 if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009427 new_addr) < 0) {
9428 nl80211_remove_iface(drv, ifidx);
9429 return -1;
9430 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009431 }
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009432 os_memcpy(if_addr, new_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009433 }
9434#endif /* CONFIG_P2P */
9435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009436 if (type == WPA_IF_AP_BSS) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009437 struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
9438 if (new_bss == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009439 if (added)
9440 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009441 return -1;
9442 }
9443
9444 if (bridge &&
9445 i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
9446 wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
9447 "interface %s to a bridge %s",
9448 ifname, bridge);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009449 if (added)
9450 nl80211_remove_iface(drv, ifidx);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009451 os_free(new_bss);
9452 return -1;
9453 }
9454
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009455 if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
9456 {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009457 nl80211_remove_iface(drv, ifidx);
9458 os_free(new_bss);
9459 return -1;
9460 }
9461 os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009462 os_memcpy(new_bss->addr, if_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009463 new_bss->ifindex = ifidx;
9464 new_bss->drv = drv;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009465 new_bss->next = drv->first_bss->next;
9466 new_bss->freq = drv->first_bss->freq;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08009467 new_bss->ctx = bss_ctx;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009468 new_bss->added_if = added;
9469 drv->first_bss->next = new_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009470 if (drv_priv)
9471 *drv_priv = new_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009472 nl80211_init_bss(new_bss);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009473
9474 /* Subscribe management frames for this WPA_IF_AP_BSS */
9475 if (nl80211_setup_ap(new_bss))
9476 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009477 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009478
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009479 if (drv->global)
9480 drv->global->if_add_ifindex = ifidx;
9481
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009482 return 0;
9483}
9484
9485
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009486static int wpa_driver_nl80211_if_remove(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009487 enum wpa_driver_if_type type,
9488 const char *ifname)
9489{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009490 struct wpa_driver_nl80211_data *drv = bss->drv;
9491 int ifindex = if_nametoindex(ifname);
9492
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009493 wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d",
9494 __func__, type, ifname, ifindex, bss->added_if);
9495 if (ifindex > 0 && bss->added_if)
Dmitry Shmidt051af732013-10-22 13:52:46 -07009496 nl80211_remove_iface(drv, ifindex);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07009497
Dmitry Shmidtaa532512012-09-24 10:35:31 -07009498 if (type != WPA_IF_AP_BSS)
9499 return 0;
9500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009501 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009502 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
9503 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009504 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
9505 "interface %s from bridge %s: %s",
9506 bss->ifname, bss->brname, strerror(errno));
9507 }
9508 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009509 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009510 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
9511 "bridge %s: %s",
9512 bss->brname, strerror(errno));
9513 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009514
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009515 if (bss != drv->first_bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009516 struct i802_bss *tbss;
9517
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009518 wpa_printf(MSG_DEBUG, "nl80211: Not the first BSS - remove it");
9519 for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009520 if (tbss->next == bss) {
9521 tbss->next = bss->next;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009522 /* Unsubscribe management frames */
9523 nl80211_teardown_ap(bss);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009524 nl80211_destroy_bss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009525 os_free(bss);
9526 bss = NULL;
9527 break;
9528 }
9529 }
9530 if (bss)
9531 wpa_printf(MSG_INFO, "nl80211: %s - could not find "
9532 "BSS %p in the list", __func__, bss);
Dmitry Shmidtcce06662013-11-04 18:44:24 -08009533 } else {
9534 wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
9535 nl80211_teardown_ap(bss);
9536 if (!bss->added_if && !drv->first_bss->next)
9537 wpa_driver_nl80211_del_beacon(drv);
9538 nl80211_destroy_bss(bss);
9539 if (!bss->added_if)
9540 i802_set_iface_flags(bss, 0);
9541 if (drv->first_bss->next) {
9542 drv->first_bss = drv->first_bss->next;
9543 drv->ctx = drv->first_bss->ctx;
9544 os_free(bss);
9545 } else {
9546 wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
9547 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009548 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009549
9550 return 0;
9551}
9552
9553
9554static int cookie_handler(struct nl_msg *msg, void *arg)
9555{
9556 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9557 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9558 u64 *cookie = arg;
9559 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9560 genlmsg_attrlen(gnlh, 0), NULL);
9561 if (tb[NL80211_ATTR_COOKIE])
9562 *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
9563 return NL_SKIP;
9564}
9565
9566
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009567static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009568 unsigned int freq, unsigned int wait,
9569 const u8 *buf, size_t buf_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009570 u64 *cookie_out, int no_cck, int no_ack,
9571 int offchanok)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009572{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009573 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009574 struct nl_msg *msg;
9575 u64 cookie;
9576 int ret = -1;
9577
9578 msg = nlmsg_alloc();
9579 if (!msg)
9580 return -1;
9581
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07009582 wpa_printf(MSG_MSGDUMP, "nl80211: CMD_FRAME freq=%u wait=%u no_cck=%d "
Dmitry Shmidt04949592012-07-19 12:16:46 -07009583 "no_ack=%d offchanok=%d",
9584 freq, wait, no_cck, no_ack, offchanok);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009585 wpa_hexdump(MSG_MSGDUMP, "CMD_FRAME", buf, buf_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009586 nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009587
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009588 if (nl80211_set_iface_id(msg, bss) < 0)
9589 goto nla_put_failure;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07009590 if (freq)
9591 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009592 if (wait)
9593 NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009594 if (offchanok && (drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009595 NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
9596 if (no_cck)
9597 NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
9598 if (no_ack)
9599 NLA_PUT_FLAG(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK);
9600
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009601 NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);
9602
9603 cookie = 0;
9604 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
9605 msg = NULL;
9606 if (ret) {
9607 wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009608 "(%s) (freq=%u wait=%u)", ret, strerror(-ret),
9609 freq, wait);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009610 goto nla_put_failure;
9611 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07009612 wpa_printf(MSG_MSGDUMP, "nl80211: Frame TX command accepted%s; "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009613 "cookie 0x%llx", no_ack ? " (no ACK)" : "",
9614 (long long unsigned int) cookie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009615
9616 if (cookie_out)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009617 *cookie_out = no_ack ? (u64) -1 : cookie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009618
9619nla_put_failure:
9620 nlmsg_free(msg);
9621 return ret;
9622}
9623
9624
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009625static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
9626 unsigned int freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009627 unsigned int wait_time,
9628 const u8 *dst, const u8 *src,
9629 const u8 *bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009630 const u8 *data, size_t data_len,
9631 int no_cck)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009632{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009633 struct wpa_driver_nl80211_data *drv = bss->drv;
9634 int ret = -1;
9635 u8 *buf;
9636 struct ieee80211_hdr *hdr;
9637
9638 wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08009639 "freq=%u MHz wait=%d ms no_cck=%d)",
9640 drv->ifindex, freq, wait_time, no_cck);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009641
9642 buf = os_zalloc(24 + data_len);
9643 if (buf == NULL)
9644 return ret;
9645 os_memcpy(buf + 24, data, data_len);
9646 hdr = (struct ieee80211_hdr *) buf;
9647 hdr->frame_control =
9648 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);
9649 os_memcpy(hdr->addr1, dst, ETH_ALEN);
9650 os_memcpy(hdr->addr2, src, ETH_ALEN);
9651 os_memcpy(hdr->addr3, bssid, ETH_ALEN);
9652
Dmitry Shmidt56052862013-10-04 10:23:25 -07009653 if (is_ap_interface(drv->nlmode) &&
9654 (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
9655 (int) freq == bss->freq || drv->device_ap_sme ||
9656 !drv->use_monitor))
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009657 ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
9658 0, freq, no_cck, 1,
9659 wait_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009660 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009661 ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009662 24 + data_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009663 &drv->send_action_cookie,
9664 no_cck, 0, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009665
9666 os_free(buf);
9667 return ret;
9668}
9669
9670
9671static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
9672{
9673 struct i802_bss *bss = priv;
9674 struct wpa_driver_nl80211_data *drv = bss->drv;
9675 struct nl_msg *msg;
9676 int ret;
9677
9678 msg = nlmsg_alloc();
9679 if (!msg)
9680 return;
9681
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08009682 wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx",
9683 (long long unsigned int) drv->send_action_cookie);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009684 nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009685
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009686 if (nl80211_set_iface_id(msg, bss) < 0)
9687 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009688 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);
9689
9690 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9691 msg = NULL;
9692 if (ret)
9693 wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
9694 "(%s)", ret, strerror(-ret));
9695
9696 nla_put_failure:
9697 nlmsg_free(msg);
9698}
9699
9700
9701static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
9702 unsigned int duration)
9703{
9704 struct i802_bss *bss = priv;
9705 struct wpa_driver_nl80211_data *drv = bss->drv;
9706 struct nl_msg *msg;
9707 int ret;
9708 u64 cookie;
9709
9710 msg = nlmsg_alloc();
9711 if (!msg)
9712 return -1;
9713
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009714 nl80211_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009715
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009716 if (nl80211_set_iface_id(msg, bss) < 0)
9717 goto nla_put_failure;
9718
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009719 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
9720 NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);
9721
9722 cookie = 0;
9723 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009724 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009725 if (ret == 0) {
9726 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
9727 "0x%llx for freq=%u MHz duration=%u",
9728 (long long unsigned int) cookie, freq, duration);
9729 drv->remain_on_chan_cookie = cookie;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009730 drv->pending_remain_on_chan = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009731 return 0;
9732 }
9733 wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel "
9734 "(freq=%d duration=%u): %d (%s)",
9735 freq, duration, ret, strerror(-ret));
9736nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009737 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009738 return -1;
9739}
9740
9741
9742static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
9743{
9744 struct i802_bss *bss = priv;
9745 struct wpa_driver_nl80211_data *drv = bss->drv;
9746 struct nl_msg *msg;
9747 int ret;
9748
9749 if (!drv->pending_remain_on_chan) {
9750 wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel "
9751 "to cancel");
9752 return -1;
9753 }
9754
9755 wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie "
9756 "0x%llx",
9757 (long long unsigned int) drv->remain_on_chan_cookie);
9758
9759 msg = nlmsg_alloc();
9760 if (!msg)
9761 return -1;
9762
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009763 nl80211_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009764
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009765 if (nl80211_set_iface_id(msg, bss) < 0)
9766 goto nla_put_failure;
9767
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009768 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);
9769
9770 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009771 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009772 if (ret == 0)
9773 return 0;
9774 wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
9775 "%d (%s)", ret, strerror(-ret));
9776nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009777 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009778 return -1;
9779}
9780
9781
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08009782static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009783{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009784 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009785
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009786 if (!report) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009787 if (bss->nl_preq && drv->device_ap_sme &&
9788 is_ap_interface(drv->nlmode)) {
9789 /*
9790 * Do not disable Probe Request reporting that was
9791 * enabled in nl80211_setup_ap().
9792 */
9793 wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of "
9794 "Probe Request reporting nl_preq=%p while "
9795 "in AP mode", bss->nl_preq);
9796 } else if (bss->nl_preq) {
9797 wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
9798 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009799 nl80211_destroy_eloop_handle(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009800 }
9801 return 0;
9802 }
9803
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009804 if (bss->nl_preq) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009805 wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009806 "already on! nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009807 return 0;
9808 }
9809
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009810 bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq");
9811 if (bss->nl_preq == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009812 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009813 wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request "
9814 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009815
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009816 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009817 (WLAN_FC_TYPE_MGMT << 2) |
9818 (WLAN_FC_STYPE_PROBE_REQ << 4),
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009819 NULL, 0) < 0)
9820 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07009821
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07009822 nl80211_register_eloop_read(&bss->nl_preq,
9823 wpa_driver_nl80211_event_receive,
9824 bss->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009825
9826 return 0;
9827
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009828 out_err:
9829 nl_destroy_handles(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009830 return -1;
9831}
9832
9833
9834static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
9835 int ifindex, int disabled)
9836{
9837 struct nl_msg *msg;
9838 struct nlattr *bands, *band;
9839 int ret;
9840
9841 msg = nlmsg_alloc();
9842 if (!msg)
9843 return -1;
9844
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009845 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_TX_BITRATE_MASK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009846 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
9847
9848 bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
9849 if (!bands)
9850 goto nla_put_failure;
9851
9852 /*
9853 * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything
9854 * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS
9855 * rates. All 5 GHz rates are left enabled.
9856 */
9857 band = nla_nest_start(msg, NL80211_BAND_2GHZ);
9858 if (!band)
9859 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009860 if (disabled) {
9861 NLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,
9862 "\x0c\x12\x18\x24\x30\x48\x60\x6c");
9863 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009864 nla_nest_end(msg, band);
9865
9866 nla_nest_end(msg, bands);
9867
9868 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
9869 msg = NULL;
9870 if (ret) {
9871 wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
9872 "(%s)", ret, strerror(-ret));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009873 } else
9874 drv->disabled_11b_rates = disabled;
9875
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009876 return ret;
9877
9878nla_put_failure:
9879 nlmsg_free(msg);
9880 return -1;
9881}
9882
9883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009884static int wpa_driver_nl80211_deinit_ap(void *priv)
9885{
9886 struct i802_bss *bss = priv;
9887 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009888 if (!is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009889 return -1;
9890 wpa_driver_nl80211_del_beacon(drv);
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07009891
9892 /*
9893 * If the P2P GO interface was dynamically added, then it is
9894 * possible that the interface change to station is not possible.
9895 */
9896 if (drv->nlmode == NL80211_IFTYPE_P2P_GO && bss->if_dynamic)
9897 return 0;
9898
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009899 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009900}
9901
9902
Dmitry Shmidtea69e842013-05-13 14:52:28 -07009903static int wpa_driver_nl80211_stop_ap(void *priv)
9904{
9905 struct i802_bss *bss = priv;
9906 struct wpa_driver_nl80211_data *drv = bss->drv;
9907 if (!is_ap_interface(drv->nlmode))
9908 return -1;
9909 wpa_driver_nl80211_del_beacon(drv);
9910 bss->beacon_set = 0;
9911 return 0;
9912}
9913
9914
Dmitry Shmidt04949592012-07-19 12:16:46 -07009915static int wpa_driver_nl80211_deinit_p2p_cli(void *priv)
9916{
9917 struct i802_bss *bss = priv;
9918 struct wpa_driver_nl80211_data *drv = bss->drv;
9919 if (drv->nlmode != NL80211_IFTYPE_P2P_CLIENT)
9920 return -1;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07009921
9922 /*
9923 * If the P2P Client interface was dynamically added, then it is
9924 * possible that the interface change to station is not possible.
9925 */
9926 if (bss->if_dynamic)
9927 return 0;
9928
Dmitry Shmidt04949592012-07-19 12:16:46 -07009929 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
9930}
9931
9932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009933static void wpa_driver_nl80211_resume(void *priv)
9934{
9935 struct i802_bss *bss = priv;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07009936
9937 if (i802_set_iface_flags(bss, 1))
9938 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009939}
9940
9941
9942static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
9943 const u8 *ies, size_t ies_len)
9944{
9945 struct i802_bss *bss = priv;
9946 struct wpa_driver_nl80211_data *drv = bss->drv;
9947 int ret;
9948 u8 *data, *pos;
9949 size_t data_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009950 const u8 *own_addr = bss->addr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009951
9952 if (action != 1) {
9953 wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action "
9954 "action %d", action);
9955 return -1;
9956 }
9957
9958 /*
9959 * Action frame payload:
9960 * Category[1] = 6 (Fast BSS Transition)
9961 * Action[1] = 1 (Fast BSS Transition Request)
9962 * STA Address
9963 * Target AP Address
9964 * FT IEs
9965 */
9966
9967 data_len = 2 + 2 * ETH_ALEN + ies_len;
9968 data = os_malloc(data_len);
9969 if (data == NULL)
9970 return -1;
9971 pos = data;
9972 *pos++ = 0x06; /* FT Action category */
9973 *pos++ = action;
9974 os_memcpy(pos, own_addr, ETH_ALEN);
9975 pos += ETH_ALEN;
9976 os_memcpy(pos, target_ap, ETH_ALEN);
9977 pos += ETH_ALEN;
9978 os_memcpy(pos, ies, ies_len);
9979
9980 ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0,
9981 drv->bssid, own_addr, drv->bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009982 data, data_len, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009983 os_free(data);
9984
9985 return ret;
9986}
9987
9988
9989static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
9990{
9991 struct i802_bss *bss = priv;
9992 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07009993 struct nl_msg *msg;
9994 struct nlattr *cqm;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07009995 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009996
9997 wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
9998 "hysteresis=%d", threshold, hysteresis);
9999
10000 msg = nlmsg_alloc();
10001 if (!msg)
10002 return -1;
10003
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010004 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_CQM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010005
10006 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10007
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010008 cqm = nla_nest_start(msg, NL80211_ATTR_CQM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010009 if (cqm == NULL)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010010 goto nla_put_failure;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010011
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070010012 NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
10013 NLA_PUT_U32(msg, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);
10014 nla_nest_end(msg, cqm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010015
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010016 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010017 msg = NULL;
10018
10019nla_put_failure:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010020 nlmsg_free(msg);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070010021 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010022}
10023
10024
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010025/* Converts nl80211_chan_width to a common format */
10026static enum chan_width convert2width(int width)
10027{
10028 switch (width) {
10029 case NL80211_CHAN_WIDTH_20_NOHT:
10030 return CHAN_WIDTH_20_NOHT;
10031 case NL80211_CHAN_WIDTH_20:
10032 return CHAN_WIDTH_20;
10033 case NL80211_CHAN_WIDTH_40:
10034 return CHAN_WIDTH_40;
10035 case NL80211_CHAN_WIDTH_80:
10036 return CHAN_WIDTH_80;
10037 case NL80211_CHAN_WIDTH_80P80:
10038 return CHAN_WIDTH_80P80;
10039 case NL80211_CHAN_WIDTH_160:
10040 return CHAN_WIDTH_160;
10041 }
10042 return CHAN_WIDTH_UNKNOWN;
10043}
10044
10045
10046static int get_channel_width(struct nl_msg *msg, void *arg)
10047{
10048 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10049 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10050 struct wpa_signal_info *sig_change = arg;
10051
10052 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10053 genlmsg_attrlen(gnlh, 0), NULL);
10054
10055 sig_change->center_frq1 = -1;
10056 sig_change->center_frq2 = -1;
10057 sig_change->chanwidth = CHAN_WIDTH_UNKNOWN;
10058
10059 if (tb[NL80211_ATTR_CHANNEL_WIDTH]) {
10060 sig_change->chanwidth = convert2width(
10061 nla_get_u32(tb[NL80211_ATTR_CHANNEL_WIDTH]));
10062 if (tb[NL80211_ATTR_CENTER_FREQ1])
10063 sig_change->center_frq1 =
10064 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
10065 if (tb[NL80211_ATTR_CENTER_FREQ2])
10066 sig_change->center_frq2 =
10067 nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
10068 }
10069
10070 return NL_SKIP;
10071}
10072
10073
10074static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv,
10075 struct wpa_signal_info *sig)
10076{
10077 struct nl_msg *msg;
10078
10079 msg = nlmsg_alloc();
10080 if (!msg)
10081 return -ENOMEM;
10082
10083 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_INTERFACE);
10084 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
10085
10086 return send_and_recv_msgs(drv, msg, get_channel_width, sig);
10087
10088nla_put_failure:
10089 nlmsg_free(msg);
10090 return -ENOBUFS;
10091}
10092
10093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010094static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
10095{
10096 struct i802_bss *bss = priv;
10097 struct wpa_driver_nl80211_data *drv = bss->drv;
10098 int res;
10099
10100 os_memset(si, 0, sizeof(*si));
10101 res = nl80211_get_link_signal(drv, si);
10102 if (res != 0)
10103 return res;
10104
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010105 res = nl80211_get_channel_width(drv, si);
10106 if (res != 0)
10107 return res;
10108
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010109 return nl80211_get_link_noise(drv, si);
10110}
10111
10112
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010113static int wpa_driver_nl80211_shared_freq(void *priv)
10114{
10115 struct i802_bss *bss = priv;
10116 struct wpa_driver_nl80211_data *drv = bss->drv;
10117 struct wpa_driver_nl80211_data *driver;
10118 int freq = 0;
10119
10120 /*
10121 * If the same PHY is in connected state with some other interface,
10122 * then retrieve the assoc freq.
10123 */
10124 wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s",
10125 drv->phyname);
10126
10127 dl_list_for_each(driver, &drv->global->interfaces,
10128 struct wpa_driver_nl80211_data, list) {
10129 if (drv == driver ||
10130 os_strcmp(drv->phyname, driver->phyname) != 0 ||
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010131 !driver->associated)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010132 continue;
10133
10134 wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
10135 MACSTR,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010136 driver->phyname, driver->first_bss->ifname,
10137 MAC2STR(driver->first_bss->addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -070010138 if (is_ap_interface(driver->nlmode))
Dmitry Shmidtcce06662013-11-04 18:44:24 -080010139 freq = driver->first_bss->freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010140 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010141 freq = nl80211_get_assoc_freq(driver);
10142 wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
10143 drv->phyname, freq);
10144 }
10145
10146 if (!freq)
10147 wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
10148 "PHY (%s) in associated state", drv->phyname);
10149
10150 return freq;
10151}
10152
10153
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010154static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
10155 int encrypt)
10156{
10157 struct i802_bss *bss = priv;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010158 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
10159 0, 0, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010160}
10161
10162
10163static int nl80211_set_param(void *priv, const char *param)
10164{
10165 wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
10166 if (param == NULL)
10167 return 0;
10168
10169#ifdef CONFIG_P2P
10170 if (os_strstr(param, "use_p2p_group_interface=1")) {
10171 struct i802_bss *bss = priv;
10172 struct wpa_driver_nl80211_data *drv = bss->drv;
10173
10174 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
10175 "interface");
10176 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
10177 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
10178 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -070010179
10180 if (os_strstr(param, "p2p_device=1")) {
10181 struct i802_bss *bss = priv;
10182 struct wpa_driver_nl80211_data *drv = bss->drv;
10183 drv->allow_p2p_device = 1;
10184 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010185#endif /* CONFIG_P2P */
10186
10187 return 0;
10188}
10189
10190
10191static void * nl80211_global_init(void)
10192{
10193 struct nl80211_global *global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010194 struct netlink_config *cfg;
10195
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010196 global = os_zalloc(sizeof(*global));
10197 if (global == NULL)
10198 return NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010199 global->ioctl_sock = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010200 dl_list_init(&global->interfaces);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010201 global->if_add_ifindex = -1;
10202
10203 cfg = os_zalloc(sizeof(*cfg));
10204 if (cfg == NULL)
10205 goto err;
10206
10207 cfg->ctx = global;
10208 cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
10209 cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
10210 global->netlink = netlink_init(cfg);
10211 if (global->netlink == NULL) {
10212 os_free(cfg);
10213 goto err;
10214 }
10215
10216 if (wpa_driver_nl80211_init_nl_global(global) < 0)
10217 goto err;
10218
10219 global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
10220 if (global->ioctl_sock < 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010221 wpa_printf(MSG_ERROR, "nl80211: socket(PF_INET,SOCK_DGRAM) failed: %s",
10222 strerror(errno));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010223 goto err;
10224 }
10225
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010226 return global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010227
10228err:
10229 nl80211_global_deinit(global);
10230 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010231}
10232
10233
10234static void nl80211_global_deinit(void *priv)
10235{
10236 struct nl80211_global *global = priv;
10237 if (global == NULL)
10238 return;
10239 if (!dl_list_empty(&global->interfaces)) {
10240 wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at "
10241 "nl80211_global_deinit",
10242 dl_list_len(&global->interfaces));
10243 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010244
10245 if (global->netlink)
10246 netlink_deinit(global->netlink);
10247
10248 nl_destroy_handles(&global->nl);
10249
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010250 if (global->nl_event)
10251 nl80211_destroy_eloop_handle(&global->nl_event);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010252
10253 nl_cb_put(global->nl_cb);
10254
10255 if (global->ioctl_sock >= 0)
10256 close(global->ioctl_sock);
10257
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070010258 os_free(global);
10259}
10260
10261
10262static const char * nl80211_get_radio_name(void *priv)
10263{
10264 struct i802_bss *bss = priv;
10265 struct wpa_driver_nl80211_data *drv = bss->drv;
10266 return drv->phyname;
10267}
10268
10269
Jouni Malinen75ecf522011-06-27 15:19:46 -070010270static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,
10271 const u8 *pmkid)
10272{
10273 struct nl_msg *msg;
10274
10275 msg = nlmsg_alloc();
10276 if (!msg)
10277 return -ENOMEM;
10278
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010279 nl80211_cmd(bss->drv, msg, 0, cmd);
Jouni Malinen75ecf522011-06-27 15:19:46 -070010280
10281 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
10282 if (pmkid)
10283 NLA_PUT(msg, NL80211_ATTR_PMKID, 16, pmkid);
10284 if (bssid)
10285 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
10286
10287 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
10288 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010289 nlmsg_free(msg);
Jouni Malinen75ecf522011-06-27 15:19:46 -070010290 return -ENOBUFS;
10291}
10292
10293
10294static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
10295{
10296 struct i802_bss *bss = priv;
10297 wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR, MAC2STR(bssid));
10298 return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);
10299}
10300
10301
10302static int nl80211_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
10303{
10304 struct i802_bss *bss = priv;
10305 wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR,
10306 MAC2STR(bssid));
10307 return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);
10308}
10309
10310
10311static int nl80211_flush_pmkid(void *priv)
10312{
10313 struct i802_bss *bss = priv;
10314 wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs");
10315 return nl80211_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);
10316}
10317
10318
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070010319static void clean_survey_results(struct survey_results *survey_results)
10320{
10321 struct freq_survey *survey, *tmp;
10322
10323 if (dl_list_empty(&survey_results->survey_list))
10324 return;
10325
10326 dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
10327 struct freq_survey, list) {
10328 dl_list_del(&survey->list);
10329 os_free(survey);
10330 }
10331}
10332
10333
10334static void add_survey(struct nlattr **sinfo, u32 ifidx,
10335 struct dl_list *survey_list)
10336{
10337 struct freq_survey *survey;
10338
10339 survey = os_zalloc(sizeof(struct freq_survey));
10340 if (!survey)
10341 return;
10342
10343 survey->ifidx = ifidx;
10344 survey->freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10345 survey->filled = 0;
10346
10347 if (sinfo[NL80211_SURVEY_INFO_NOISE]) {
10348 survey->nf = (int8_t)
10349 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10350 survey->filled |= SURVEY_HAS_NF;
10351 }
10352
10353 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]) {
10354 survey->channel_time =
10355 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME]);
10356 survey->filled |= SURVEY_HAS_CHAN_TIME;
10357 }
10358
10359 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]) {
10360 survey->channel_time_busy =
10361 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY]);
10362 survey->filled |= SURVEY_HAS_CHAN_TIME_BUSY;
10363 }
10364
10365 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]) {
10366 survey->channel_time_rx =
10367 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_RX]);
10368 survey->filled |= SURVEY_HAS_CHAN_TIME_RX;
10369 }
10370
10371 if (sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]) {
10372 survey->channel_time_tx =
10373 nla_get_u64(sinfo[NL80211_SURVEY_INFO_CHANNEL_TIME_TX]);
10374 survey->filled |= SURVEY_HAS_CHAN_TIME_TX;
10375 }
10376
10377 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)",
10378 survey->freq,
10379 survey->nf,
10380 (unsigned long int) survey->channel_time,
10381 (unsigned long int) survey->channel_time_busy,
10382 (unsigned long int) survey->channel_time_tx,
10383 (unsigned long int) survey->channel_time_rx,
10384 survey->filled);
10385
10386 dl_list_add_tail(survey_list, &survey->list);
10387}
10388
10389
10390static int check_survey_ok(struct nlattr **sinfo, u32 surveyed_freq,
10391 unsigned int freq_filter)
10392{
10393 if (!freq_filter)
10394 return 1;
10395
10396 return freq_filter == surveyed_freq;
10397}
10398
10399
10400static int survey_handler(struct nl_msg *msg, void *arg)
10401{
10402 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10403 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10404 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10405 struct survey_results *survey_results;
10406 u32 surveyed_freq = 0;
10407 u32 ifidx;
10408
10409 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10410 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
10411 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
10412 };
10413
10414 survey_results = (struct survey_results *) arg;
10415
10416 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10417 genlmsg_attrlen(gnlh, 0), NULL);
10418
10419 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
10420
10421 if (!tb[NL80211_ATTR_SURVEY_INFO])
10422 return NL_SKIP;
10423
10424 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
10425 tb[NL80211_ATTR_SURVEY_INFO],
10426 survey_policy))
10427 return NL_SKIP;
10428
10429 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY]) {
10430 wpa_printf(MSG_ERROR, "nl80211: Invalid survey data");
10431 return NL_SKIP;
10432 }
10433
10434 surveyed_freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10435
10436 if (!check_survey_ok(sinfo, surveyed_freq,
10437 survey_results->freq_filter))
10438 return NL_SKIP;
10439
10440 if (survey_results->freq_filter &&
10441 survey_results->freq_filter != surveyed_freq) {
10442 wpa_printf(MSG_EXCESSIVE, "nl80211: Ignoring survey data for freq %d MHz",
10443 surveyed_freq);
10444 return NL_SKIP;
10445 }
10446
10447 add_survey(sinfo, ifidx, &survey_results->survey_list);
10448
10449 return NL_SKIP;
10450}
10451
10452
10453static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
10454{
10455 struct i802_bss *bss = priv;
10456 struct wpa_driver_nl80211_data *drv = bss->drv;
10457 struct nl_msg *msg;
10458 int err = -ENOBUFS;
10459 union wpa_event_data data;
10460 struct survey_results *survey_results;
10461
10462 os_memset(&data, 0, sizeof(data));
10463 survey_results = &data.survey_results;
10464
10465 dl_list_init(&survey_results->survey_list);
10466
10467 msg = nlmsg_alloc();
10468 if (!msg)
10469 goto nla_put_failure;
10470
10471 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
10472
10473 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
10474
10475 if (freq)
10476 data.survey_results.freq_filter = freq;
10477
10478 do {
10479 wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data");
10480 err = send_and_recv_msgs(drv, msg, survey_handler,
10481 survey_results);
10482 } while (err > 0);
10483
10484 if (err) {
10485 wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
10486 goto out_clean;
10487 }
10488
10489 wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data);
10490
10491out_clean:
10492 clean_survey_results(survey_results);
10493nla_put_failure:
10494 return err;
10495}
10496
10497
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010498static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
10499 const u8 *replay_ctr)
10500{
10501 struct i802_bss *bss = priv;
10502 struct wpa_driver_nl80211_data *drv = bss->drv;
10503 struct nlattr *replay_nested;
10504 struct nl_msg *msg;
10505
10506 msg = nlmsg_alloc();
10507 if (!msg)
10508 return;
10509
10510 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
10511
10512 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10513
10514 replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
10515 if (!replay_nested)
10516 goto nla_put_failure;
10517
10518 NLA_PUT(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek);
10519 NLA_PUT(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck);
10520 NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
10521 replay_ctr);
10522
10523 nla_nest_end(msg, replay_nested);
10524
10525 send_and_recv_msgs(drv, msg, NULL, NULL);
10526 return;
10527 nla_put_failure:
10528 nlmsg_free(msg);
10529}
10530
10531
10532static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
10533 const u8 *addr, int qos)
10534{
10535 /* send data frame to poll STA and check whether
10536 * this frame is ACKed */
10537 struct {
10538 struct ieee80211_hdr hdr;
10539 u16 qos_ctl;
10540 } STRUCT_PACKED nulldata;
10541 size_t size;
10542
10543 /* Send data frame to poll STA and check whether this frame is ACKed */
10544
10545 os_memset(&nulldata, 0, sizeof(nulldata));
10546
10547 if (qos) {
10548 nulldata.hdr.frame_control =
10549 IEEE80211_FC(WLAN_FC_TYPE_DATA,
10550 WLAN_FC_STYPE_QOS_NULL);
10551 size = sizeof(nulldata);
10552 } else {
10553 nulldata.hdr.frame_control =
10554 IEEE80211_FC(WLAN_FC_TYPE_DATA,
10555 WLAN_FC_STYPE_NULLFUNC);
10556 size = sizeof(struct ieee80211_hdr);
10557 }
10558
10559 nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
10560 os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
10561 os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
10562 os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
10563
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010564 if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
10565 0, 0) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010566 wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
10567 "send poll frame");
10568}
10569
10570static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
10571 int qos)
10572{
10573 struct i802_bss *bss = priv;
10574 struct wpa_driver_nl80211_data *drv = bss->drv;
10575 struct nl_msg *msg;
10576
10577 if (!drv->poll_command_supported) {
10578 nl80211_send_null_frame(bss, own_addr, addr, qos);
10579 return;
10580 }
10581
10582 msg = nlmsg_alloc();
10583 if (!msg)
10584 return;
10585
10586 nl80211_cmd(drv, msg, 0, NL80211_CMD_PROBE_CLIENT);
10587
10588 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10589 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
10590
10591 send_and_recv_msgs(drv, msg, NULL, NULL);
10592 return;
10593 nla_put_failure:
10594 nlmsg_free(msg);
10595}
10596
10597
10598static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
10599{
10600 struct nl_msg *msg;
10601
10602 msg = nlmsg_alloc();
10603 if (!msg)
10604 return -ENOMEM;
10605
10606 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_SET_POWER_SAVE);
10607 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
10608 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE,
10609 enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);
10610 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
10611nla_put_failure:
10612 nlmsg_free(msg);
10613 return -ENOBUFS;
10614}
10615
10616
10617static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,
10618 int ctwindow)
10619{
10620 struct i802_bss *bss = priv;
10621
10622 wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d "
10623 "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow);
10624
10625 if (opp_ps != -1 || ctwindow != -1)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010626#ifdef ANDROID_P2P
10627 wpa_driver_set_p2p_ps(priv, legacy_ps, opp_ps, ctwindow);
10628#else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010629 return -1; /* Not yet supported */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080010630#endif
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010631
10632 if (legacy_ps == -1)
10633 return 0;
10634 if (legacy_ps != 0 && legacy_ps != 1)
10635 return -1; /* Not yet supported */
10636
10637 return nl80211_set_power_save(bss, legacy_ps);
10638}
10639
10640
Dmitry Shmidt051af732013-10-22 13:52:46 -070010641static int nl80211_start_radar_detection(void *priv,
10642 struct hostapd_freq_params *freq)
Dmitry Shmidtea69e842013-05-13 14:52:28 -070010643{
10644 struct i802_bss *bss = priv;
10645 struct wpa_driver_nl80211_data *drv = bss->drv;
10646 struct nl_msg *msg;
10647 int ret;
10648
Dmitry Shmidt051af732013-10-22 13:52:46 -070010649 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)",
10650 freq->freq, freq->ht_enabled, freq->vht_enabled,
10651 freq->bandwidth, freq->center_freq1, freq->center_freq2);
10652
Dmitry Shmidtea69e842013-05-13 14:52:28 -070010653 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_RADAR)) {
10654 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support radar "
10655 "detection");
10656 return -1;
10657 }
10658
10659 msg = nlmsg_alloc();
10660 if (!msg)
10661 return -1;
10662
10663 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_RADAR_DETECT);
10664 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
Dmitry Shmidt051af732013-10-22 13:52:46 -070010665 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq);
Dmitry Shmidtea69e842013-05-13 14:52:28 -070010666
Dmitry Shmidt051af732013-10-22 13:52:46 -070010667 if (freq->vht_enabled) {
10668 switch (freq->bandwidth) {
10669 case 20:
10670 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
10671 NL80211_CHAN_WIDTH_20);
10672 break;
10673 case 40:
10674 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
10675 NL80211_CHAN_WIDTH_40);
10676 break;
10677 case 80:
10678 if (freq->center_freq2)
10679 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
10680 NL80211_CHAN_WIDTH_80P80);
10681 else
10682 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
10683 NL80211_CHAN_WIDTH_80);
10684 break;
10685 case 160:
10686 NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
10687 NL80211_CHAN_WIDTH_160);
10688 break;
10689 default:
10690 return -1;
10691 }
10692 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1);
10693 if (freq->center_freq2)
10694 NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2,
10695 freq->center_freq2);
10696 } else if (freq->ht_enabled) {
10697 switch (freq->sec_channel_offset) {
10698 case -1:
10699 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
10700 NL80211_CHAN_HT40MINUS);
10701 break;
10702 case 1:
10703 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
10704 NL80211_CHAN_HT40PLUS);
10705 break;
10706 default:
10707 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
10708 NL80211_CHAN_HT20);
10709 break;
10710 }
10711 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -070010712
10713 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
10714 if (ret == 0)
10715 return 0;
10716 wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
10717 "%d (%s)", ret, strerror(-ret));
10718nla_put_failure:
10719 return -1;
10720}
10721
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010722#ifdef CONFIG_TDLS
10723
10724static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
10725 u8 dialog_token, u16 status_code,
10726 const u8 *buf, size_t len)
10727{
10728 struct i802_bss *bss = priv;
10729 struct wpa_driver_nl80211_data *drv = bss->drv;
10730 struct nl_msg *msg;
10731
10732 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
10733 return -EOPNOTSUPP;
10734
10735 if (!dst)
10736 return -EINVAL;
10737
10738 msg = nlmsg_alloc();
10739 if (!msg)
10740 return -ENOMEM;
10741
10742 nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_MGMT);
10743 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
10744 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
10745 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code);
10746 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token);
10747 NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code);
10748 NLA_PUT(msg, NL80211_ATTR_IE, len, buf);
10749
10750 return send_and_recv_msgs(drv, msg, NULL, NULL);
10751
10752nla_put_failure:
10753 nlmsg_free(msg);
10754 return -ENOBUFS;
10755}
10756
10757
10758static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
10759{
10760 struct i802_bss *bss = priv;
10761 struct wpa_driver_nl80211_data *drv = bss->drv;
10762 struct nl_msg *msg;
10763 enum nl80211_tdls_operation nl80211_oper;
10764
10765 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
10766 return -EOPNOTSUPP;
10767
10768 switch (oper) {
10769 case TDLS_DISCOVERY_REQ:
10770 nl80211_oper = NL80211_TDLS_DISCOVERY_REQ;
10771 break;
10772 case TDLS_SETUP:
10773 nl80211_oper = NL80211_TDLS_SETUP;
10774 break;
10775 case TDLS_TEARDOWN:
10776 nl80211_oper = NL80211_TDLS_TEARDOWN;
10777 break;
10778 case TDLS_ENABLE_LINK:
10779 nl80211_oper = NL80211_TDLS_ENABLE_LINK;
10780 break;
10781 case TDLS_DISABLE_LINK:
10782 nl80211_oper = NL80211_TDLS_DISABLE_LINK;
10783 break;
10784 case TDLS_ENABLE:
10785 return 0;
10786 case TDLS_DISABLE:
10787 return 0;
10788 default:
10789 return -EINVAL;
10790 }
10791
10792 msg = nlmsg_alloc();
10793 if (!msg)
10794 return -ENOMEM;
10795
10796 nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_OPER);
10797 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper);
10798 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
10799 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer);
10800
10801 return send_and_recv_msgs(drv, msg, NULL, NULL);
10802
10803nla_put_failure:
10804 nlmsg_free(msg);
10805 return -ENOBUFS;
10806}
10807
10808#endif /* CONFIG TDLS */
10809
10810
10811#ifdef ANDROID
10812
10813typedef struct android_wifi_priv_cmd {
10814 char *buf;
10815 int used_len;
10816 int total_len;
10817} android_wifi_priv_cmd;
10818
10819static int drv_errors = 0;
10820
10821static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
10822{
10823 drv_errors++;
10824 if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
10825 drv_errors = 0;
10826 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
10827 }
10828}
10829
10830
10831static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
10832{
10833 struct wpa_driver_nl80211_data *drv = bss->drv;
10834 struct ifreq ifr;
10835 android_wifi_priv_cmd priv_cmd;
10836 char buf[MAX_DRV_CMD_SIZE];
10837 int ret;
10838
10839 os_memset(&ifr, 0, sizeof(ifr));
10840 os_memset(&priv_cmd, 0, sizeof(priv_cmd));
10841 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
10842
10843 os_memset(buf, 0, sizeof(buf));
10844 os_strlcpy(buf, cmd, sizeof(buf));
10845
10846 priv_cmd.buf = buf;
10847 priv_cmd.used_len = sizeof(buf);
10848 priv_cmd.total_len = sizeof(buf);
10849 ifr.ifr_data = &priv_cmd;
10850
10851 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
10852 if (ret < 0) {
10853 wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
10854 __func__);
10855 wpa_driver_send_hang_msg(drv);
10856 return ret;
10857 }
10858
10859 drv_errors = 0;
10860 return 0;
10861}
10862
10863
10864static int android_pno_start(struct i802_bss *bss,
10865 struct wpa_driver_scan_params *params)
10866{
10867 struct wpa_driver_nl80211_data *drv = bss->drv;
10868 struct ifreq ifr;
10869 android_wifi_priv_cmd priv_cmd;
10870 int ret = 0, i = 0, bp;
10871 char buf[WEXT_PNO_MAX_COMMAND_SIZE];
10872
10873 bp = WEXT_PNOSETUP_HEADER_SIZE;
10874 os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
10875 buf[bp++] = WEXT_PNO_TLV_PREFIX;
10876 buf[bp++] = WEXT_PNO_TLV_VERSION;
10877 buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
10878 buf[bp++] = WEXT_PNO_TLV_RESERVED;
10879
10880 while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
10881 /* Check that there is enough space needed for 1 more SSID, the
10882 * other sections and null termination */
10883 if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
10884 WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
10885 break;
10886 wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
10887 params->ssids[i].ssid,
10888 params->ssids[i].ssid_len);
10889 buf[bp++] = WEXT_PNO_SSID_SECTION;
10890 buf[bp++] = params->ssids[i].ssid_len;
10891 os_memcpy(&buf[bp], params->ssids[i].ssid,
10892 params->ssids[i].ssid_len);
10893 bp += params->ssids[i].ssid_len;
10894 i++;
10895 }
10896
10897 buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
10898 os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
10899 WEXT_PNO_SCAN_INTERVAL);
10900 bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
10901
10902 buf[bp++] = WEXT_PNO_REPEAT_SECTION;
10903 os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
10904 WEXT_PNO_REPEAT);
10905 bp += WEXT_PNO_REPEAT_LENGTH;
10906
10907 buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
10908 os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
10909 WEXT_PNO_MAX_REPEAT);
10910 bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
10911
10912 memset(&ifr, 0, sizeof(ifr));
10913 memset(&priv_cmd, 0, sizeof(priv_cmd));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -070010914 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080010915
10916 priv_cmd.buf = buf;
10917 priv_cmd.used_len = bp;
10918 priv_cmd.total_len = bp;
10919 ifr.ifr_data = &priv_cmd;
10920
10921 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
10922
10923 if (ret < 0) {
10924 wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
10925 ret);
10926 wpa_driver_send_hang_msg(drv);
10927 return ret;
10928 }
10929
10930 drv_errors = 0;
10931
10932 return android_priv_cmd(bss, "PNOFORCE 1");
10933}
10934
10935
10936static int android_pno_stop(struct i802_bss *bss)
10937{
10938 return android_priv_cmd(bss, "PNOFORCE 0");
10939}
10940
10941#endif /* ANDROID */
10942
10943
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080010944static int driver_nl80211_set_key(const char *ifname, void *priv,
10945 enum wpa_alg alg, const u8 *addr,
10946 int key_idx, int set_tx,
10947 const u8 *seq, size_t seq_len,
10948 const u8 *key, size_t key_len)
10949{
10950 struct i802_bss *bss = priv;
10951 return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx,
10952 set_tx, seq, seq_len, key, key_len);
10953}
10954
10955
10956static int driver_nl80211_scan2(void *priv,
10957 struct wpa_driver_scan_params *params)
10958{
10959 struct i802_bss *bss = priv;
10960 return wpa_driver_nl80211_scan(bss, params);
10961}
10962
10963
10964static int driver_nl80211_deauthenticate(void *priv, const u8 *addr,
10965 int reason_code)
10966{
10967 struct i802_bss *bss = priv;
10968 return wpa_driver_nl80211_deauthenticate(bss, addr, reason_code);
10969}
10970
10971
10972static int driver_nl80211_authenticate(void *priv,
10973 struct wpa_driver_auth_params *params)
10974{
10975 struct i802_bss *bss = priv;
10976 return wpa_driver_nl80211_authenticate(bss, params);
10977}
10978
10979
10980static void driver_nl80211_deinit(void *priv)
10981{
10982 struct i802_bss *bss = priv;
10983 wpa_driver_nl80211_deinit(bss);
10984}
10985
10986
10987static int driver_nl80211_if_remove(void *priv, enum wpa_driver_if_type type,
10988 const char *ifname)
10989{
10990 struct i802_bss *bss = priv;
10991 return wpa_driver_nl80211_if_remove(bss, type, ifname);
10992}
10993
10994
10995static int driver_nl80211_send_mlme(void *priv, const u8 *data,
10996 size_t data_len, int noack)
10997{
10998 struct i802_bss *bss = priv;
10999 return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
11000 0, 0, 0, 0);
11001}
11002
11003
11004static int driver_nl80211_sta_remove(void *priv, const u8 *addr)
11005{
11006 struct i802_bss *bss = priv;
11007 return wpa_driver_nl80211_sta_remove(bss, addr);
11008}
11009
11010
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011011static int driver_nl80211_set_sta_vlan(void *priv, const u8 *addr,
11012 const char *ifname, int vlan_id)
11013{
11014 struct i802_bss *bss = priv;
11015 return i802_set_sta_vlan(bss, addr, ifname, vlan_id);
11016}
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011017
11018
11019static int driver_nl80211_read_sta_data(void *priv,
11020 struct hostap_sta_driver_data *data,
11021 const u8 *addr)
11022{
11023 struct i802_bss *bss = priv;
11024 return i802_read_sta_data(bss, data, addr);
11025}
11026
11027
11028static int driver_nl80211_send_action(void *priv, unsigned int freq,
11029 unsigned int wait_time,
11030 const u8 *dst, const u8 *src,
11031 const u8 *bssid,
11032 const u8 *data, size_t data_len,
11033 int no_cck)
11034{
11035 struct i802_bss *bss = priv;
11036 return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src,
11037 bssid, data, data_len, no_cck);
11038}
11039
11040
11041static int driver_nl80211_probe_req_report(void *priv, int report)
11042{
11043 struct i802_bss *bss = priv;
11044 return wpa_driver_nl80211_probe_req_report(bss, report);
11045}
11046
11047
Dmitry Shmidt700a1372013-03-15 14:14:44 -070011048static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md,
11049 const u8 *ies, size_t ies_len)
11050{
11051 int ret;
11052 struct nl_msg *msg;
11053 struct i802_bss *bss = priv;
11054 struct wpa_driver_nl80211_data *drv = bss->drv;
11055 u16 mdid = WPA_GET_LE16(md);
11056
11057 msg = nlmsg_alloc();
11058 if (!msg)
11059 return -ENOMEM;
11060
11061 wpa_printf(MSG_DEBUG, "nl80211: Updating FT IEs");
11062 nl80211_cmd(drv, msg, 0, NL80211_CMD_UPDATE_FT_IES);
11063 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11064 NLA_PUT(msg, NL80211_ATTR_IE, ies_len, ies);
11065 NLA_PUT_U16(msg, NL80211_ATTR_MDID, mdid);
11066
11067 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
11068 if (ret) {
11069 wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed "
11070 "err=%d (%s)", ret, strerror(-ret));
11071 }
11072
11073 return ret;
11074
11075nla_put_failure:
11076 nlmsg_free(msg);
11077 return -ENOBUFS;
11078}
11079
11080
Dmitry Shmidt34af3062013-07-11 10:46:32 -070011081const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
11082{
11083 struct i802_bss *bss = priv;
11084 struct wpa_driver_nl80211_data *drv = bss->drv;
11085
11086 if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE)
11087 return NULL;
11088
11089 return bss->addr;
11090}
11091
11092
Dmitry Shmidt56052862013-10-04 10:23:25 -070011093static const char * scan_state_str(enum scan_states scan_state)
11094{
11095 switch (scan_state) {
11096 case NO_SCAN:
11097 return "NO_SCAN";
11098 case SCAN_REQUESTED:
11099 return "SCAN_REQUESTED";
11100 case SCAN_STARTED:
11101 return "SCAN_STARTED";
11102 case SCAN_COMPLETED:
11103 return "SCAN_COMPLETED";
11104 case SCAN_ABORTED:
11105 return "SCAN_ABORTED";
11106 case SCHED_SCAN_STARTED:
11107 return "SCHED_SCAN_STARTED";
11108 case SCHED_SCAN_STOPPED:
11109 return "SCHED_SCAN_STOPPED";
11110 case SCHED_SCAN_RESULTS:
11111 return "SCHED_SCAN_RESULTS";
11112 }
11113
11114 return "??";
11115}
11116
11117
11118static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
11119{
11120 struct i802_bss *bss = priv;
11121 struct wpa_driver_nl80211_data *drv = bss->drv;
11122 int res;
11123 char *pos, *end;
11124
11125 pos = buf;
11126 end = buf + buflen;
11127
11128 res = os_snprintf(pos, end - pos,
11129 "ifindex=%d\n"
11130 "ifname=%s\n"
11131 "brname=%s\n"
11132 "addr=" MACSTR "\n"
11133 "freq=%d\n"
11134 "%s%s%s%s%s",
11135 bss->ifindex,
11136 bss->ifname,
11137 bss->brname,
11138 MAC2STR(bss->addr),
11139 bss->freq,
11140 bss->beacon_set ? "beacon_set=1\n" : "",
11141 bss->added_if_into_bridge ?
11142 "added_if_into_bridge=1\n" : "",
11143 bss->added_bridge ? "added_bridge=1\n" : "",
11144 bss->in_deinit ? "in_deinit=1\n" : "",
11145 bss->if_dynamic ? "if_dynamic=1\n" : "");
11146 if (res < 0 || res >= end - pos)
11147 return pos - buf;
11148 pos += res;
11149
11150 if (bss->wdev_id_set) {
11151 res = os_snprintf(pos, end - pos, "wdev_id=%llu\n",
11152 (unsigned long long) bss->wdev_id);
11153 if (res < 0 || res >= end - pos)
11154 return pos - buf;
11155 pos += res;
11156 }
11157
11158 res = os_snprintf(pos, end - pos,
11159 "phyname=%s\n"
11160 "drv_ifindex=%d\n"
11161 "operstate=%d\n"
11162 "scan_state=%s\n"
11163 "auth_bssid=" MACSTR "\n"
11164 "auth_attempt_bssid=" MACSTR "\n"
11165 "bssid=" MACSTR "\n"
11166 "prev_bssid=" MACSTR "\n"
11167 "associated=%d\n"
11168 "assoc_freq=%u\n"
11169 "monitor_sock=%d\n"
11170 "monitor_ifidx=%d\n"
11171 "monitor_refcount=%d\n"
11172 "last_mgmt_freq=%u\n"
11173 "eapol_tx_sock=%d\n"
11174 "%s%s%s%s%s%s%s%s%s%s%s%s%s",
11175 drv->phyname,
11176 drv->ifindex,
11177 drv->operstate,
11178 scan_state_str(drv->scan_state),
11179 MAC2STR(drv->auth_bssid),
11180 MAC2STR(drv->auth_attempt_bssid),
11181 MAC2STR(drv->bssid),
11182 MAC2STR(drv->prev_bssid),
11183 drv->associated,
11184 drv->assoc_freq,
11185 drv->monitor_sock,
11186 drv->monitor_ifidx,
11187 drv->monitor_refcount,
11188 drv->last_mgmt_freq,
11189 drv->eapol_tx_sock,
11190 drv->ignore_if_down_event ?
11191 "ignore_if_down_event=1\n" : "",
11192 drv->scan_complete_events ?
11193 "scan_complete_events=1\n" : "",
11194 drv->disabled_11b_rates ?
11195 "disabled_11b_rates=1\n" : "",
11196 drv->pending_remain_on_chan ?
11197 "pending_remain_on_chan=1\n" : "",
11198 drv->in_interface_list ? "in_interface_list=1\n" : "",
11199 drv->device_ap_sme ? "device_ap_sme=1\n" : "",
11200 drv->poll_command_supported ?
11201 "poll_command_supported=1\n" : "",
11202 drv->data_tx_status ? "data_tx_status=1\n" : "",
11203 drv->scan_for_auth ? "scan_for_auth=1\n" : "",
11204 drv->retry_auth ? "retry_auth=1\n" : "",
11205 drv->use_monitor ? "use_monitor=1\n" : "",
11206 drv->ignore_next_local_disconnect ?
11207 "ignore_next_local_disconnect=1\n" : "",
11208 drv->allow_p2p_device ? "allow_p2p_device=1\n" : "");
11209 if (res < 0 || res >= end - pos)
11210 return pos - buf;
11211 pos += res;
11212
11213 if (drv->has_capability) {
11214 res = os_snprintf(pos, end - pos,
11215 "capa.key_mgmt=0x%x\n"
11216 "capa.enc=0x%x\n"
11217 "capa.auth=0x%x\n"
11218 "capa.flags=0x%x\n"
11219 "capa.max_scan_ssids=%d\n"
11220 "capa.max_sched_scan_ssids=%d\n"
11221 "capa.sched_scan_supported=%d\n"
11222 "capa.max_match_sets=%d\n"
11223 "capa.max_remain_on_chan=%u\n"
11224 "capa.max_stations=%u\n"
11225 "capa.probe_resp_offloads=0x%x\n"
11226 "capa.max_acl_mac_addrs=%u\n"
11227 "capa.num_multichan_concurrent=%u\n",
11228 drv->capa.key_mgmt,
11229 drv->capa.enc,
11230 drv->capa.auth,
11231 drv->capa.flags,
11232 drv->capa.max_scan_ssids,
11233 drv->capa.max_sched_scan_ssids,
11234 drv->capa.sched_scan_supported,
11235 drv->capa.max_match_sets,
11236 drv->capa.max_remain_on_chan,
11237 drv->capa.max_stations,
11238 drv->capa.probe_resp_offloads,
11239 drv->capa.max_acl_mac_addrs,
11240 drv->capa.num_multichan_concurrent);
11241 if (res < 0 || res >= end - pos)
11242 return pos - buf;
11243 pos += res;
11244 }
11245
11246 return pos - buf;
11247}
11248
11249
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080011250static int set_beacon_data(struct nl_msg *msg, struct beacon_data *settings)
11251{
11252 if (settings->head)
11253 NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD,
11254 settings->head_len, settings->head);
11255
11256 if (settings->tail)
11257 NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL,
11258 settings->tail_len, settings->tail);
11259
11260 if (settings->beacon_ies)
11261 NLA_PUT(msg, NL80211_ATTR_IE,
11262 settings->beacon_ies_len, settings->beacon_ies);
11263
11264 if (settings->proberesp_ies)
11265 NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
11266 settings->proberesp_ies_len, settings->proberesp_ies);
11267
11268 if (settings->assocresp_ies)
11269 NLA_PUT(msg,
11270 NL80211_ATTR_IE_ASSOC_RESP,
11271 settings->assocresp_ies_len, settings->assocresp_ies);
11272
11273 if (settings->probe_resp)
11274 NLA_PUT(msg, NL80211_ATTR_PROBE_RESP,
11275 settings->probe_resp_len, settings->probe_resp);
11276
11277 return 0;
11278
11279nla_put_failure:
11280 return -ENOBUFS;
11281}
11282
11283
11284static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
11285{
11286 struct nl_msg *msg;
11287 struct i802_bss *bss = priv;
11288 struct wpa_driver_nl80211_data *drv = bss->drv;
11289 struct nlattr *beacon_csa;
11290 int ret = -ENOBUFS;
11291
11292 wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d)",
11293 settings->cs_count, settings->block_tx,
11294 settings->freq_params.freq);
11295
11296 if (!drv->channel_switch_supported) {
11297 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command");
11298 return -EOPNOTSUPP;
11299 }
11300
11301 if ((drv->nlmode != NL80211_IFTYPE_AP) &&
11302 (drv->nlmode != NL80211_IFTYPE_P2P_GO))
11303 return -EOPNOTSUPP;
11304
11305 /* check settings validity */
11306 if (!settings->beacon_csa.tail ||
11307 ((settings->beacon_csa.tail_len <=
11308 settings->counter_offset_beacon) ||
11309 (settings->beacon_csa.tail[settings->counter_offset_beacon] !=
11310 settings->cs_count)))
11311 return -EINVAL;
11312
11313 if (settings->beacon_csa.probe_resp &&
11314 ((settings->beacon_csa.probe_resp_len <=
11315 settings->counter_offset_presp) ||
11316 (settings->beacon_csa.probe_resp[settings->counter_offset_presp] !=
11317 settings->cs_count)))
11318 return -EINVAL;
11319
11320 msg = nlmsg_alloc();
11321 if (!msg)
11322 return -ENOMEM;
11323
11324 nl80211_cmd(drv, msg, 0, NL80211_CMD_CHANNEL_SWITCH);
11325 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
11326 NLA_PUT_U32(msg, NL80211_ATTR_CH_SWITCH_COUNT, settings->cs_count);
11327 ret = nl80211_put_freq_params(msg, &settings->freq_params);
11328 if (ret)
11329 goto error;
11330
11331 if (settings->block_tx)
11332 NLA_PUT_FLAG(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX);
11333
11334 /* beacon_after params */
11335 ret = set_beacon_data(msg, &settings->beacon_after);
11336 if (ret)
11337 goto error;
11338
11339 /* beacon_csa params */
11340 beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
11341 if (!beacon_csa)
11342 goto nla_put_failure;
11343
11344 ret = set_beacon_data(msg, &settings->beacon_csa);
11345 if (ret)
11346 goto error;
11347
11348 NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_BEACON,
11349 settings->counter_offset_beacon);
11350
11351 if (settings->beacon_csa.probe_resp)
11352 NLA_PUT_U16(msg, NL80211_ATTR_CSA_C_OFF_PRESP,
11353 settings->counter_offset_presp);
11354
11355 nla_nest_end(msg, beacon_csa);
11356 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
11357 if (ret) {
11358 wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)",
11359 ret, strerror(-ret));
11360 }
11361 return ret;
11362
11363nla_put_failure:
11364 ret = -ENOBUFS;
11365error:
11366 nlmsg_free(msg);
11367 wpa_printf(MSG_DEBUG, "nl80211: Could not build channel switch request");
11368 return ret;
11369}
11370
11371
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011372const struct wpa_driver_ops wpa_driver_nl80211_ops = {
11373 .name = "nl80211",
11374 .desc = "Linux nl80211/cfg80211",
11375 .get_bssid = wpa_driver_nl80211_get_bssid,
11376 .get_ssid = wpa_driver_nl80211_get_ssid,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011377 .set_key = driver_nl80211_set_key,
11378 .scan2 = driver_nl80211_scan2,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011379 .sched_scan = wpa_driver_nl80211_sched_scan,
11380 .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011381 .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011382 .deauthenticate = driver_nl80211_deauthenticate,
11383 .authenticate = driver_nl80211_authenticate,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011384 .associate = wpa_driver_nl80211_associate,
11385 .global_init = nl80211_global_init,
11386 .global_deinit = nl80211_global_deinit,
11387 .init2 = wpa_driver_nl80211_init,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011388 .deinit = driver_nl80211_deinit,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011389 .get_capa = wpa_driver_nl80211_get_capa,
11390 .set_operstate = wpa_driver_nl80211_set_operstate,
11391 .set_supp_port = wpa_driver_nl80211_set_supp_port,
11392 .set_country = wpa_driver_nl80211_set_country,
Dmitry Shmidtcce06662013-11-04 18:44:24 -080011393 .get_country = wpa_driver_nl80211_get_country,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011394 .set_ap = wpa_driver_nl80211_set_ap,
Dmitry Shmidt8bae4132013-06-06 11:25:10 -070011395 .set_acl = wpa_driver_nl80211_set_acl,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011396 .if_add = wpa_driver_nl80211_if_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011397 .if_remove = driver_nl80211_if_remove,
11398 .send_mlme = driver_nl80211_send_mlme,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011399 .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data,
11400 .sta_add = wpa_driver_nl80211_sta_add,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011401 .sta_remove = driver_nl80211_sta_remove,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011402 .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
11403 .sta_set_flags = wpa_driver_nl80211_sta_set_flags,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011404 .hapd_init = i802_init,
11405 .hapd_deinit = i802_deinit,
Jouni Malinen75ecf522011-06-27 15:19:46 -070011406 .set_wds_sta = i802_set_wds_sta,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011407 .get_seqnum = i802_get_seqnum,
11408 .flush = i802_flush,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011409 .get_inact_sec = i802_get_inact_sec,
11410 .sta_clear_stats = i802_sta_clear_stats,
11411 .set_rts = i802_set_rts,
11412 .set_frag = i802_set_frag,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011413 .set_tx_queue_params = i802_set_tx_queue_params,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011414 .set_sta_vlan = driver_nl80211_set_sta_vlan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011415 .sta_deauth = i802_sta_deauth,
11416 .sta_disassoc = i802_sta_disassoc,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011417 .read_sta_data = driver_nl80211_read_sta_data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011418 .set_freq = i802_set_freq,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011419 .send_action = driver_nl80211_send_action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011420 .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
11421 .remain_on_channel = wpa_driver_nl80211_remain_on_channel,
11422 .cancel_remain_on_channel =
11423 wpa_driver_nl80211_cancel_remain_on_channel,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080011424 .probe_req_report = driver_nl80211_probe_req_report,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011425 .deinit_ap = wpa_driver_nl80211_deinit_ap,
Dmitry Shmidt04949592012-07-19 12:16:46 -070011426 .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011427 .resume = wpa_driver_nl80211_resume,
11428 .send_ft_action = nl80211_send_ft_action,
11429 .signal_monitor = nl80211_signal_monitor,
11430 .signal_poll = nl80211_signal_poll,
11431 .send_frame = nl80211_send_frame,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011432 .shared_freq = wpa_driver_nl80211_shared_freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011433 .set_param = nl80211_set_param,
11434 .get_radio_name = nl80211_get_radio_name,
Jouni Malinen75ecf522011-06-27 15:19:46 -070011435 .add_pmkid = nl80211_add_pmkid,
11436 .remove_pmkid = nl80211_remove_pmkid,
11437 .flush_pmkid = nl80211_flush_pmkid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011438 .set_rekey_info = nl80211_set_rekey_info,
11439 .poll_client = nl80211_poll_client,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011440 .set_p2p_powersave = nl80211_set_p2p_powersave,
Dmitry Shmidtea69e842013-05-13 14:52:28 -070011441 .start_dfs_cac = nl80211_start_radar_detection,
11442 .stop_ap = wpa_driver_nl80211_stop_ap,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011443#ifdef CONFIG_TDLS
11444 .send_tdls_mgmt = nl80211_send_tdls_mgmt,
11445 .tdls_oper = nl80211_tdls_oper,
11446#endif /* CONFIG_TDLS */
Dmitry Shmidt700a1372013-03-15 14:14:44 -070011447 .update_ft_ies = wpa_driver_nl80211_update_ft_ies,
Dmitry Shmidt34af3062013-07-11 10:46:32 -070011448 .get_mac_addr = wpa_driver_nl80211_get_macaddr,
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -070011449 .get_survey = wpa_driver_nl80211_get_survey,
Dmitry Shmidt56052862013-10-04 10:23:25 -070011450 .status = wpa_driver_nl80211_status,
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -080011451 .switch_channel = nl80211_switch_channel,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011452#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070011453 .set_noa = wpa_driver_set_p2p_noa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080011454 .get_noa = wpa_driver_get_p2p_noa,
Dmitry Shmidt6e933c12011-09-27 12:29:26 -070011455 .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
11456#endif
Dmitry Shmidt738a26e2011-07-07 14:22:14 -070011457#ifdef ANDROID
11458 .driver_cmd = wpa_driver_nl80211_driver_cmd,
11459#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070011460};