blob: a00f7034708bae037a46c1859d061a209c367980 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Driver interaction with Linux nl80211/cfg80211
3 * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
4 * 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 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * Alternatively, this software may be distributed under the terms of BSD
14 * license.
15 *
16 * See README and COPYING for more details.
17 */
18
19#include "includes.h"
20#include <sys/ioctl.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <net/if.h>
25#include <netlink/genl/genl.h>
26#include <netlink/genl/family.h>
27#include <netlink/genl/ctrl.h>
28#include <linux/rtnetlink.h>
29#include <netpacket/packet.h>
30#include <linux/filter.h>
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080031#include <linux/errqueue.h>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032#include "nl80211_copy.h"
33
34#include "common.h"
35#include "eloop.h"
36#include "utils/list.h"
37#include "common/ieee802_11_defs.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080038#include "common/ieee802_11_common.h"
39#include "l2_packet/l2_packet.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040#include "netlink.h"
41#include "linux_ioctl.h"
42#include "radiotap.h"
43#include "radiotap_iter.h"
44#include "rfkill.h"
45#include "driver.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080046#if defined(ANDROID_P2P) && !defined(HOSTAPD)
Dmitry Shmidt497c1d52011-07-21 15:19:46 -070047#include "wpa_supplicant_i.h"
48#endif
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080049#ifndef SO_WIFI_STATUS
50# if defined(__sparc__)
51# define SO_WIFI_STATUS 0x0025
52# elif defined(__parisc__)
53# define SO_WIFI_STATUS 0x4022
54# else
55# define SO_WIFI_STATUS 41
56# endif
57
58# define SCM_WIFI_STATUS SO_WIFI_STATUS
59#endif
60
61#ifndef SO_EE_ORIGIN_TXSTATUS
62#define SO_EE_ORIGIN_TXSTATUS 4
63#endif
64
65#ifndef PACKET_TX_TIMESTAMP
66#define PACKET_TX_TIMESTAMP 16
67#endif
68
69#ifdef ANDROID
70#include "android_drv.h"
71#endif /* ANDROID */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072#ifdef CONFIG_LIBNL20
73/* libnl 2.0 compatibility code */
74#define nl_handle nl_sock
75#define nl80211_handle_alloc nl_socket_alloc_cb
76#define nl80211_handle_destroy nl_socket_free
77#else
78/*
79 * libnl 1.1 has a bug, it tries to allocate socket numbers densely
80 * but when you free a socket again it will mess up its bitmap and
81 * and use the wrong number the next time it needs a socket ID.
82 * Therefore, we wrap the handle alloc/destroy and add our own pid
83 * accounting.
84 */
85static uint32_t port_bitmap[32] = { 0 };
86
87static struct nl_handle *nl80211_handle_alloc(void *cb)
88{
89 struct nl_handle *handle;
90 uint32_t pid = getpid() & 0x3FFFFF;
91 int i;
92
93 handle = nl_handle_alloc_cb(cb);
94
95 for (i = 0; i < 1024; i++) {
96 if (port_bitmap[i / 32] & (1 << (i % 32)))
97 continue;
98 port_bitmap[i / 32] |= 1 << (i % 32);
99 pid += i << 22;
100 break;
101 }
102
103 nl_socket_set_local_port(handle, pid);
104
105 return handle;
106}
107
108static void nl80211_handle_destroy(struct nl_handle *handle)
109{
110 uint32_t port = nl_socket_get_local_port(handle);
111
112 port >>= 22;
113 port_bitmap[port / 32] &= ~(1 << (port % 32));
114
115 nl_handle_destroy(handle);
116}
117#endif /* CONFIG_LIBNL20 */
118
119
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800120static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
121{
122 struct nl_handle *handle;
123
124 handle = nl80211_handle_alloc(cb);
125 if (handle == NULL) {
126 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
127 "callbacks (%s)", dbg);
128 return NULL;
129 }
130
131 if (genl_connect(handle)) {
132 wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
133 "netlink (%s)", dbg);
134 nl80211_handle_destroy(handle);
135 return NULL;
136 }
137
138 return handle;
139}
140
141
142static void nl_destroy_handles(struct nl_handle **handle)
143{
144 if (*handle == NULL)
145 return;
146 nl80211_handle_destroy(*handle);
147 *handle = NULL;
148}
149
150
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700151#ifndef IFF_LOWER_UP
152#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
153#endif
154#ifndef IFF_DORMANT
155#define IFF_DORMANT 0x20000 /* driver signals dormant */
156#endif
157
158#ifndef IF_OPER_DORMANT
159#define IF_OPER_DORMANT 5
160#endif
161#ifndef IF_OPER_UP
162#define IF_OPER_UP 6
163#endif
164
165struct nl80211_global {
166 struct dl_list interfaces;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800167 int if_add_ifindex;
168 struct netlink_data *netlink;
169 struct nl_cb *nl_cb;
170 struct nl_handle *nl;
171 int nl80211_id;
172 int ioctl_sock; /* socket for ioctl() use */
173
174 struct nl_handle *nl_event;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700175};
176
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800177struct nl80211_wiphy_data {
178 struct dl_list list;
179 struct dl_list bsss;
180 struct dl_list drvs;
181
182 struct nl_handle *nl_beacons;
183 struct nl_cb *nl_cb;
184
185 int wiphy_idx;
186};
187
188static void nl80211_global_deinit(void *priv);
189static void wpa_driver_nl80211_deinit(void *priv);
190
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700191struct i802_bss {
192 struct wpa_driver_nl80211_data *drv;
193 struct i802_bss *next;
194 int ifindex;
195 char ifname[IFNAMSIZ + 1];
196 char brname[IFNAMSIZ];
197 unsigned int beacon_set:1;
198 unsigned int added_if_into_bridge:1;
199 unsigned int added_bridge:1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800200
201 u8 addr[ETH_ALEN];
202
203 int freq;
204
205 struct nl_handle *nl_preq, *nl_mgmt;
206 struct nl_cb *nl_cb;
207
208 struct nl80211_wiphy_data *wiphy_data;
209 struct dl_list wiphy_list;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700210};
211
212struct wpa_driver_nl80211_data {
213 struct nl80211_global *global;
214 struct dl_list list;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800215 struct dl_list wiphy_list;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700216 char phyname[32];
217 void *ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700218 int ifindex;
219 int if_removed;
220 int if_disabled;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800221 int ignore_if_down_event;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700222 struct rfkill_data *rfkill;
223 struct wpa_driver_capa capa;
224 int has_capability;
225
226 int operstate;
227
228 int scan_complete_events;
229
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700230 struct nl_cb *nl_cb;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231
232 u8 auth_bssid[ETH_ALEN];
233 u8 bssid[ETH_ALEN];
234 int associated;
235 u8 ssid[32];
236 size_t ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800237 enum nl80211_iftype nlmode;
238 enum nl80211_iftype ap_scan_as_station;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700239 unsigned int assoc_freq;
240
241 int monitor_sock;
242 int monitor_ifidx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 int monitor_refcount;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700244
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800245 unsigned int disabled_11b_rates:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700246 unsigned int pending_remain_on_chan:1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800247 unsigned int in_interface_list:1;
248 unsigned int device_ap_sme:1;
249 unsigned int poll_command_supported:1;
250 unsigned int data_tx_status:1;
251 unsigned int scan_for_auth:1;
252 unsigned int retry_auth:1;
253 unsigned int use_monitor:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254
255 u64 remain_on_chan_cookie;
256 u64 send_action_cookie;
257
258 unsigned int last_mgmt_freq;
259
260 struct wpa_driver_scan_filter *filter_ssids;
261 size_t num_filter_ssids;
262
263 struct i802_bss first_bss;
264
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800265 int eapol_tx_sock;
266
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700267#ifdef HOSTAPD
268 int eapol_sock; /* socket for EAPOL frames */
269
270 int default_if_indices[16];
271 int *if_indices;
272 int num_if_indices;
273
274 int last_freq;
275 int last_freq_ht;
276#endif /* HOSTAPD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800277
278 /* From failed authentication command */
279 int auth_freq;
280 u8 auth_bssid_[ETH_ALEN];
281 u8 auth_ssid[32];
282 size_t auth_ssid_len;
283 int auth_alg;
284 u8 *auth_ie;
285 size_t auth_ie_len;
286 u8 auth_wep_key[4][16];
287 size_t auth_wep_key_len[4];
288 int auth_wep_tx_keyidx;
289 int auth_local_state_change;
290 int auth_p2p;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700291};
292
293
294static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
295 void *timeout_ctx);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800296static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
297 enum nl80211_iftype nlmode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298static int
299wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv);
300static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
301 const u8 *addr, int cmd, u16 reason_code,
302 int local_state_change);
303static void nl80211_remove_monitor_interface(
304 struct wpa_driver_nl80211_data *drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800305static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700306 unsigned int freq, unsigned int wait,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800307 const u8 *buf, size_t buf_len, u64 *cookie,
308 int no_cck, int no_ack, int offchanok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700309static int wpa_driver_nl80211_probe_req_report(void *priv, int report);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800310#ifdef ANDROID
311static int android_pno_start(struct i802_bss *bss,
312 struct wpa_driver_scan_params *params);
313static int android_pno_stop(struct i802_bss *bss);
314#endif /* ANDROID */
315#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -0700316static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
317 enum wpa_event_type type,
318 const u8 *frame, size_t len);
319int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800320int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -0700321int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow);
322int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
323 const struct wpabuf *proberesp,
324 const struct wpabuf *assocresp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700325
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800326#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700327#ifdef HOSTAPD
328static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
329static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
330static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
331static int wpa_driver_nl80211_if_remove(void *priv,
332 enum wpa_driver_if_type type,
333 const char *ifname);
334#else /* HOSTAPD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800335static inline void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
336{
337}
338
339static inline void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
340{
341}
342
343static inline int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700344{
345 return 0;
346}
347#endif /* HOSTAPD */
Dmitry Shmidt738a26e2011-07-07 14:22:14 -0700348#ifdef ANDROID
349extern int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
350 size_t buf_len);
351#endif
352
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700353static int i802_set_freq(void *priv, struct hostapd_freq_params *freq);
354static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
355 int ifindex, int disabled);
356
357static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800358static int wpa_driver_nl80211_authenticate_retry(
359 struct wpa_driver_nl80211_data *drv);
360
361
362static int is_ap_interface(enum nl80211_iftype nlmode)
363{
364 return (nlmode == NL80211_IFTYPE_AP ||
365 nlmode == NL80211_IFTYPE_P2P_GO);
366}
367
368
369static int is_sta_interface(enum nl80211_iftype nlmode)
370{
371 return (nlmode == NL80211_IFTYPE_STATION ||
372 nlmode == NL80211_IFTYPE_P2P_CLIENT);
373}
374
375
376static int is_p2p_interface(enum nl80211_iftype nlmode)
377{
378 return (nlmode == NL80211_IFTYPE_P2P_CLIENT ||
379 nlmode == NL80211_IFTYPE_P2P_GO);
380}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700381
382
Jouni Malinen87fd2792011-05-16 18:35:42 +0300383struct nl80211_bss_info_arg {
384 struct wpa_driver_nl80211_data *drv;
385 struct wpa_scan_results *res;
386 unsigned int assoc_freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800387 u8 assoc_bssid[ETH_ALEN];
Jouni Malinen87fd2792011-05-16 18:35:42 +0300388};
389
390static int bss_info_handler(struct nl_msg *msg, void *arg);
391
392
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700393/* nl80211 code */
394static int ack_handler(struct nl_msg *msg, void *arg)
395{
396 int *err = arg;
397 *err = 0;
398 return NL_STOP;
399}
400
401static int finish_handler(struct nl_msg *msg, void *arg)
402{
403 int *ret = arg;
404 *ret = 0;
405 return NL_SKIP;
406}
407
408static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
409 void *arg)
410{
411 int *ret = arg;
412 *ret = err->error;
413 return NL_SKIP;
414}
415
416
417static int no_seq_check(struct nl_msg *msg, void *arg)
418{
419 return NL_OK;
420}
421
422
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800423static int send_and_recv(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 struct nl_handle *nl_handle, struct nl_msg *msg,
425 int (*valid_handler)(struct nl_msg *, void *),
426 void *valid_data)
427{
428 struct nl_cb *cb;
429 int err = -ENOMEM;
430
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800431 cb = nl_cb_clone(global->nl_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432 if (!cb)
433 goto out;
434
435 err = nl_send_auto_complete(nl_handle, msg);
436 if (err < 0)
437 goto out;
438
439 err = 1;
440
441 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
442 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
443 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
444
445 if (valid_handler)
446 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
447 valid_handler, valid_data);
448
449 while (err > 0)
450 nl_recvmsgs(nl_handle, cb);
451 out:
452 nl_cb_put(cb);
453 nlmsg_free(msg);
454 return err;
455}
456
457
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800458static int send_and_recv_msgs_global(struct nl80211_global *global,
459 struct nl_msg *msg,
460 int (*valid_handler)(struct nl_msg *, void *),
461 void *valid_data)
462{
463 return send_and_recv(global, global->nl, msg, valid_handler,
464 valid_data);
465}
466
Dmitry Shmidt738a26e2011-07-07 14:22:14 -0700467int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700468 struct nl_msg *msg,
469 int (*valid_handler)(struct nl_msg *, void *),
470 void *valid_data)
471{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800472 return send_and_recv(drv->global, drv->global->nl, msg,
473 valid_handler, valid_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700474}
475
476
477struct family_data {
478 const char *group;
479 int id;
480};
481
482
483static int family_handler(struct nl_msg *msg, void *arg)
484{
485 struct family_data *res = arg;
486 struct nlattr *tb[CTRL_ATTR_MAX + 1];
487 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
488 struct nlattr *mcgrp;
489 int i;
490
491 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
492 genlmsg_attrlen(gnlh, 0), NULL);
493 if (!tb[CTRL_ATTR_MCAST_GROUPS])
494 return NL_SKIP;
495
496 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
497 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
498 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
499 nla_len(mcgrp), NULL);
500 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
501 !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
502 os_strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
503 res->group,
504 nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
505 continue;
506 res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
507 break;
508 };
509
510 return NL_SKIP;
511}
512
513
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800514static int nl_get_multicast_id(struct nl80211_global *global,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515 const char *family, const char *group)
516{
517 struct nl_msg *msg;
518 int ret = -1;
519 struct family_data res = { group, -ENOENT };
520
521 msg = nlmsg_alloc();
522 if (!msg)
523 return -ENOMEM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800524 genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700525 0, 0, CTRL_CMD_GETFAMILY, 0);
526 NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
527
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800528 ret = send_and_recv_msgs_global(global, msg, family_handler, &res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700529 msg = NULL;
530 if (ret == 0)
531 ret = res.id;
532
533nla_put_failure:
534 nlmsg_free(msg);
535 return ret;
536}
537
538
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800539static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
540 struct nl_msg *msg, int flags, uint8_t cmd)
541{
542 return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
543 0, flags, cmd, 0);
544}
545
546
547struct wiphy_idx_data {
548 int wiphy_idx;
549};
550
551
552static int netdev_info_handler(struct nl_msg *msg, void *arg)
553{
554 struct nlattr *tb[NL80211_ATTR_MAX + 1];
555 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
556 struct wiphy_idx_data *info = arg;
557
558 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
559 genlmsg_attrlen(gnlh, 0), NULL);
560
561 if (tb[NL80211_ATTR_WIPHY])
562 info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
563
564 return NL_SKIP;
565}
566
567
568static int nl80211_get_wiphy_index(struct i802_bss *bss)
569{
570 struct nl_msg *msg;
571 struct wiphy_idx_data data = {
572 .wiphy_idx = -1,
573 };
574
575 msg = nlmsg_alloc();
576 if (!msg)
577 return -1;
578
579 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
580
581 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
582
583 if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
584 return data.wiphy_idx;
585 msg = NULL;
586nla_put_failure:
587 nlmsg_free(msg);
588 return -1;
589}
590
591
592static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
593 struct nl80211_wiphy_data *w)
594{
595 struct nl_msg *msg;
596 int ret = -1;
597
598 msg = nlmsg_alloc();
599 if (!msg)
600 return -1;
601
602 nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS);
603
604 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx);
605
606 ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);
607 msg = NULL;
608 if (ret) {
609 wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
610 "failed: ret=%d (%s)",
611 ret, strerror(-ret));
612 goto nla_put_failure;
613 }
614 ret = 0;
615nla_put_failure:
616 nlmsg_free(msg);
617 return ret;
618}
619
620
621static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle)
622{
623 struct nl80211_wiphy_data *w = eloop_ctx;
624
625 wpa_printf(MSG_DEBUG, "nl80211: Beacon event message available");
626
627 nl_recvmsgs(handle, w->nl_cb);
628}
629
630
631static int process_beacon_event(struct nl_msg *msg, void *arg)
632{
633 struct nl80211_wiphy_data *w = arg;
634 struct wpa_driver_nl80211_data *drv;
635 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
636 struct nlattr *tb[NL80211_ATTR_MAX + 1];
637 union wpa_event_data event;
638
639 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
640 genlmsg_attrlen(gnlh, 0), NULL);
641
642 if (gnlh->cmd != NL80211_CMD_FRAME) {
643 wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)",
644 gnlh->cmd);
645 return NL_SKIP;
646 }
647
648 if (!tb[NL80211_ATTR_FRAME])
649 return NL_SKIP;
650
651 dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data,
652 wiphy_list) {
653 os_memset(&event, 0, sizeof(event));
654 event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);
655 event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);
656 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
657 }
658
659 return NL_SKIP;
660}
661
662
663static struct nl80211_wiphy_data *
664nl80211_get_wiphy_data_ap(struct i802_bss *bss)
665{
666 static DEFINE_DL_LIST(nl80211_wiphys);
667 struct nl80211_wiphy_data *w;
668 int wiphy_idx, found = 0;
669 struct i802_bss *tmp_bss;
670
671 if (bss->wiphy_data != NULL)
672 return bss->wiphy_data;
673
674 wiphy_idx = nl80211_get_wiphy_index(bss);
675
676 dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) {
677 if (w->wiphy_idx == wiphy_idx)
678 goto add;
679 }
680
681 /* alloc new one */
682 w = os_zalloc(sizeof(*w));
683 if (w == NULL)
684 return NULL;
685 w->wiphy_idx = wiphy_idx;
686 dl_list_init(&w->bsss);
687 dl_list_init(&w->drvs);
688
689 w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
690 if (!w->nl_cb) {
691 os_free(w);
692 return NULL;
693 }
694 nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
695 nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,
696 w);
697
698 w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
699 "wiphy beacons");
700 if (w->nl_beacons == NULL) {
701 os_free(w);
702 return NULL;
703 }
704
705 if (nl80211_register_beacons(bss->drv, w)) {
706 nl_destroy_handles(&w->nl_beacons);
707 os_free(w);
708 return NULL;
709 }
710
711 eloop_register_read_sock(nl_socket_get_fd(w->nl_beacons),
712 nl80211_recv_beacons, w, w->nl_beacons);
713
714 dl_list_add(&nl80211_wiphys, &w->list);
715
716add:
717 /* drv entry for this bss already there? */
718 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
719 if (tmp_bss->drv == bss->drv) {
720 found = 1;
721 break;
722 }
723 }
724 /* if not add it */
725 if (!found)
726 dl_list_add(&w->drvs, &bss->drv->wiphy_list);
727
728 dl_list_add(&w->bsss, &bss->wiphy_list);
729 bss->wiphy_data = w;
730 return w;
731}
732
733
734static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
735{
736 struct nl80211_wiphy_data *w = bss->wiphy_data;
737 struct i802_bss *tmp_bss;
738 int found = 0;
739
740 if (w == NULL)
741 return;
742 bss->wiphy_data = NULL;
743 dl_list_del(&bss->wiphy_list);
744
745 /* still any for this drv present? */
746 dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
747 if (tmp_bss->drv == bss->drv) {
748 found = 1;
749 break;
750 }
751 }
752 /* if not remove it */
753 if (!found)
754 dl_list_del(&bss->drv->wiphy_list);
755
756 if (!dl_list_empty(&w->bsss))
757 return;
758
759 eloop_unregister_read_sock(nl_socket_get_fd(w->nl_beacons));
760
761 nl_cb_put(w->nl_cb);
762 nl_destroy_handles(&w->nl_beacons);
763 dl_list_del(&w->list);
764 os_free(w);
765}
766
767
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700768static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
769{
770 struct i802_bss *bss = priv;
771 struct wpa_driver_nl80211_data *drv = bss->drv;
772 if (!drv->associated)
773 return -1;
774 os_memcpy(bssid, drv->bssid, ETH_ALEN);
775 return 0;
776}
777
778
779static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
780{
781 struct i802_bss *bss = priv;
782 struct wpa_driver_nl80211_data *drv = bss->drv;
783 if (!drv->associated)
784 return -1;
785 os_memcpy(ssid, drv->ssid, drv->ssid_len);
786 return drv->ssid_len;
787}
788
789
790static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv,
791 char *buf, size_t len, int del)
792{
793 union wpa_event_data event;
794
795 os_memset(&event, 0, sizeof(event));
796 if (len > sizeof(event.interface_status.ifname))
797 len = sizeof(event.interface_status.ifname) - 1;
798 os_memcpy(event.interface_status.ifname, buf, len);
799 event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
800 EVENT_INTERFACE_ADDED;
801
802 wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
803 del ? "DEL" : "NEW",
804 event.interface_status.ifname,
805 del ? "removed" : "added");
806
807 if (os_strcmp(drv->first_bss.ifname, event.interface_status.ifname) == 0) {
808 if (del)
809 drv->if_removed = 1;
810 else
811 drv->if_removed = 0;
812 }
813
814 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
815}
816
817
818static int wpa_driver_nl80211_own_ifname(struct wpa_driver_nl80211_data *drv,
819 u8 *buf, size_t len)
820{
821 int attrlen, rta_len;
822 struct rtattr *attr;
823
824 attrlen = len;
825 attr = (struct rtattr *) buf;
826
827 rta_len = RTA_ALIGN(sizeof(struct rtattr));
828 while (RTA_OK(attr, attrlen)) {
829 if (attr->rta_type == IFLA_IFNAME) {
830 if (os_strcmp(((char *) attr) + rta_len, drv->first_bss.ifname)
831 == 0)
832 return 1;
833 else
834 break;
835 }
836 attr = RTA_NEXT(attr, attrlen);
837 }
838
839 return 0;
840}
841
842
843static int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
844 int ifindex, u8 *buf, size_t len)
845{
846 if (drv->ifindex == ifindex)
847 return 1;
848
849 if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
850 drv->first_bss.ifindex = if_nametoindex(drv->first_bss.ifname);
851 wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
852 "interface");
853 wpa_driver_nl80211_finish_drv_init(drv);
854 return 1;
855 }
856
857 return 0;
858}
859
860
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800861static struct wpa_driver_nl80211_data *
862nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
863{
864 struct wpa_driver_nl80211_data *drv;
865 dl_list_for_each(drv, &global->interfaces,
866 struct wpa_driver_nl80211_data, list) {
867 if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
868 have_ifidx(drv, idx))
869 return drv;
870 }
871 return NULL;
872}
873
874
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700875static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
876 struct ifinfomsg *ifi,
877 u8 *buf, size_t len)
878{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800879 struct nl80211_global *global = ctx;
880 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700881 int attrlen, rta_len;
882 struct rtattr *attr;
883 u32 brid = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800884 char namebuf[IFNAMSIZ];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800886 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
887 if (!drv) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700888 wpa_printf(MSG_DEBUG, "nl80211: Ignore event for foreign "
889 "ifindex %d", ifi->ifi_index);
890 return;
891 }
892
893 wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
894 "(%s%s%s%s)",
895 drv->operstate, ifi->ifi_flags,
896 (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
897 (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
898 (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
899 (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
900
901 if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800902 if (if_indextoname(ifi->ifi_index, namebuf) &&
903 linux_iface_up(drv->global->ioctl_sock,
904 drv->first_bss.ifname) > 0) {
905 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
906 "event since interface %s is up", namebuf);
907 return;
908 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700909 wpa_printf(MSG_DEBUG, "nl80211: Interface down");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800910 if (drv->ignore_if_down_event) {
911 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
912 "event generated by mode change");
913 drv->ignore_if_down_event = 0;
914 } else {
915 drv->if_disabled = 1;
916 wpa_supplicant_event(drv->ctx,
917 EVENT_INTERFACE_DISABLED, NULL);
918 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919 }
920
921 if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800922 if (if_indextoname(ifi->ifi_index, namebuf) &&
923 linux_iface_up(drv->global->ioctl_sock,
924 drv->first_bss.ifname) == 0) {
925 wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
926 "event since interface %s is down",
927 namebuf);
928 } else {
929 wpa_printf(MSG_DEBUG, "nl80211: Interface up");
930 drv->if_disabled = 0;
931 wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
932 NULL);
933 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700934 }
935
936 /*
937 * Some drivers send the association event before the operup event--in
938 * this case, lifting operstate in wpa_driver_nl80211_set_operstate()
939 * fails. This will hit us when wpa_supplicant does not need to do
940 * IEEE 802.1X authentication
941 */
942 if (drv->operstate == 1 &&
943 (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
944 !(ifi->ifi_flags & IFF_RUNNING))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800945 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700946 -1, IF_OPER_UP);
947
948 attrlen = len;
949 attr = (struct rtattr *) buf;
950 rta_len = RTA_ALIGN(sizeof(struct rtattr));
951 while (RTA_OK(attr, attrlen)) {
952 if (attr->rta_type == IFLA_IFNAME) {
953 wpa_driver_nl80211_event_link(
954 drv,
955 ((char *) attr) + rta_len,
956 attr->rta_len - rta_len, 0);
957 } else if (attr->rta_type == IFLA_MASTER)
958 brid = nla_get_u32((struct nlattr *) attr);
959 attr = RTA_NEXT(attr, attrlen);
960 }
961
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700962 if (ifi->ifi_family == AF_BRIDGE && brid) {
963 /* device has been added to bridge */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700964 if_indextoname(brid, namebuf);
965 wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
966 brid, namebuf);
967 add_ifidx(drv, brid);
968 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700969}
970
971
972static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
973 struct ifinfomsg *ifi,
974 u8 *buf, size_t len)
975{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800976 struct nl80211_global *global = ctx;
977 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700978 int attrlen, rta_len;
979 struct rtattr *attr;
980 u32 brid = 0;
981
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800982 drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
983 if (!drv) {
984 wpa_printf(MSG_DEBUG, "nl80211: Ignore dellink event for "
985 "foreign ifindex %d", ifi->ifi_index);
986 return;
987 }
988
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 attrlen = len;
990 attr = (struct rtattr *) buf;
991
992 rta_len = RTA_ALIGN(sizeof(struct rtattr));
993 while (RTA_OK(attr, attrlen)) {
994 if (attr->rta_type == IFLA_IFNAME) {
995 wpa_driver_nl80211_event_link(
996 drv,
997 ((char *) attr) + rta_len,
998 attr->rta_len - rta_len, 1);
999 } else if (attr->rta_type == IFLA_MASTER)
1000 brid = nla_get_u32((struct nlattr *) attr);
1001 attr = RTA_NEXT(attr, attrlen);
1002 }
1003
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001004 if (ifi->ifi_family == AF_BRIDGE && brid) {
1005 /* device has been removed from bridge */
1006 char namebuf[IFNAMSIZ];
1007 if_indextoname(brid, namebuf);
1008 wpa_printf(MSG_DEBUG, "nl80211: Remove ifindex %u for bridge "
1009 "%s", brid, namebuf);
1010 del_ifidx(drv, brid);
1011 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012}
1013
1014
1015static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
1016 const u8 *frame, size_t len)
1017{
1018 const struct ieee80211_mgmt *mgmt;
1019 union wpa_event_data event;
1020
1021 mgmt = (const struct ieee80211_mgmt *) frame;
1022 if (len < 24 + sizeof(mgmt->u.auth)) {
1023 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1024 "frame");
1025 return;
1026 }
1027
1028 os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
1029 os_memset(&event, 0, sizeof(event));
1030 os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
1031 event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
1032 event.auth.status_code = le_to_host16(mgmt->u.auth.status_code);
1033 if (len > 24 + sizeof(mgmt->u.auth)) {
1034 event.auth.ies = mgmt->u.auth.variable;
1035 event.auth.ies_len = len - 24 - sizeof(mgmt->u.auth);
1036 }
1037
1038 wpa_supplicant_event(drv->ctx, EVENT_AUTH, &event);
1039}
1040
1041
Jouni Malinen87fd2792011-05-16 18:35:42 +03001042static unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
1043{
1044 struct nl_msg *msg;
1045 int ret;
1046 struct nl80211_bss_info_arg arg;
1047
1048 os_memset(&arg, 0, sizeof(arg));
1049 msg = nlmsg_alloc();
1050 if (!msg)
1051 goto nla_put_failure;
1052
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001053 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Jouni Malinen87fd2792011-05-16 18:35:42 +03001054 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
1055
1056 arg.drv = drv;
1057 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
1058 msg = NULL;
1059 if (ret == 0) {
1060 wpa_printf(MSG_DEBUG, "nl80211: Operating frequency for the "
1061 "associated BSS from scan results: %u MHz",
1062 arg.assoc_freq);
1063 return arg.assoc_freq ? arg.assoc_freq : drv->assoc_freq;
1064 }
1065 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
1066 "(%s)", ret, strerror(-ret));
1067nla_put_failure:
1068 nlmsg_free(msg);
1069 return drv->assoc_freq;
1070}
1071
1072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
1074 const u8 *frame, size_t len)
1075{
1076 const struct ieee80211_mgmt *mgmt;
1077 union wpa_event_data event;
1078 u16 status;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001079#ifdef ANDROID_P2P
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001080 struct wpa_supplicant *wpa_s = drv->ctx;
1081#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001082
1083 mgmt = (const struct ieee80211_mgmt *) frame;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001084#if (defined (CONFIG_AP) || defined (HOSTAPD) ) && defined (ANDROID_P2P)
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001085 if (drv->nlmode == NL80211_IFTYPE_AP || drv->nlmode == NL80211_IFTYPE_P2P_GO) {
1086 if (len < 24 + sizeof(mgmt->u.assoc_req)) {
1087 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1088 "frame");
1089 return;
1090 }
1091 os_memset(&event, 0, sizeof(event));
1092 event.assoc_info.freq = drv->assoc_freq;
1093 event.assoc_info.req_ies = (u8 *) mgmt->u.assoc_req.variable;
1094 event.assoc_info.req_ies_len = len - 24 - sizeof(mgmt->u.assoc_req);
1095 event.assoc_info.addr = mgmt->sa;
1096 } else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001097#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001098 if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
1099 wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
1100 "frame");
1101 return;
1102 }
1103
1104 status = le_to_host16(mgmt->u.assoc_resp.status_code);
1105 if (status != WLAN_STATUS_SUCCESS) {
1106 os_memset(&event, 0, sizeof(event));
1107 event.assoc_reject.bssid = mgmt->bssid;
1108 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
1109 event.assoc_reject.resp_ies =
1110 (u8 *) mgmt->u.assoc_resp.variable;
1111 event.assoc_reject.resp_ies_len =
1112 len - 24 - sizeof(mgmt->u.assoc_resp);
1113 }
1114 event.assoc_reject.status_code = status;
1115
1116 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
1117 return;
1118 }
1119
1120 drv->associated = 1;
1121 os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
1122
1123 os_memset(&event, 0, sizeof(event));
1124 if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
1125 event.assoc_info.resp_ies = (u8 *) mgmt->u.assoc_resp.variable;
1126 event.assoc_info.resp_ies_len =
1127 len - 24 - sizeof(mgmt->u.assoc_resp);
1128 }
1129
1130 event.assoc_info.freq = drv->assoc_freq;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001131#if (defined (CONFIG_AP) || defined(HOSTAPD)) && defined (ANDROID_P2P)
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001132 }
1133#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001134 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
1135}
1136
1137
1138static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
1139 enum nl80211_commands cmd, struct nlattr *status,
1140 struct nlattr *addr, struct nlattr *req_ie,
1141 struct nlattr *resp_ie)
1142{
1143 union wpa_event_data event;
1144
1145 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
1146 /*
1147 * Avoid reporting two association events that would confuse
1148 * the core code.
1149 */
1150 wpa_printf(MSG_DEBUG, "nl80211: Ignore connect event (cmd=%d) "
1151 "when using userspace SME", cmd);
1152 return;
1153 }
1154
1155 os_memset(&event, 0, sizeof(event));
1156 if (cmd == NL80211_CMD_CONNECT &&
1157 nla_get_u16(status) != WLAN_STATUS_SUCCESS) {
1158 if (addr)
1159 event.assoc_reject.bssid = nla_data(addr);
1160 if (resp_ie) {
1161 event.assoc_reject.resp_ies = nla_data(resp_ie);
1162 event.assoc_reject.resp_ies_len = nla_len(resp_ie);
1163 }
1164 event.assoc_reject.status_code = nla_get_u16(status);
1165 wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
1166 return;
1167 }
1168
1169 drv->associated = 1;
1170 if (addr)
1171 os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
1172
1173 if (req_ie) {
1174 event.assoc_info.req_ies = nla_data(req_ie);
1175 event.assoc_info.req_ies_len = nla_len(req_ie);
1176 }
1177 if (resp_ie) {
1178 event.assoc_info.resp_ies = nla_data(resp_ie);
1179 event.assoc_info.resp_ies_len = nla_len(resp_ie);
1180 }
1181
Jouni Malinen87fd2792011-05-16 18:35:42 +03001182 event.assoc_info.freq = nl80211_get_assoc_freq(drv);
1183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
1185}
1186
1187
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001188static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
1189 struct nlattr *reason, struct nlattr *addr)
1190{
1191 union wpa_event_data data;
1192
1193 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
1194 /*
1195 * Avoid reporting two disassociation events that could
1196 * confuse the core code.
1197 */
1198 wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
1199 "event when using userspace SME");
1200 return;
1201 }
1202
1203 drv->associated = 0;
1204 os_memset(&data, 0, sizeof(data));
1205 if (reason)
1206 data.disassoc_info.reason_code = nla_get_u16(reason);
1207 wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data);
1208}
1209
1210
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001211static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
1212 enum nl80211_commands cmd, struct nlattr *addr)
1213{
1214 union wpa_event_data event;
1215 enum wpa_event_type ev;
1216
1217 if (nla_len(addr) != ETH_ALEN)
1218 return;
1219
1220 wpa_printf(MSG_DEBUG, "nl80211: MLME event %d; timeout with " MACSTR,
1221 cmd, MAC2STR((u8 *) nla_data(addr)));
1222
1223 if (cmd == NL80211_CMD_AUTHENTICATE)
1224 ev = EVENT_AUTH_TIMED_OUT;
1225 else if (cmd == NL80211_CMD_ASSOCIATE)
1226 ev = EVENT_ASSOC_TIMED_OUT;
1227 else
1228 return;
1229
1230 os_memset(&event, 0, sizeof(event));
1231 os_memcpy(event.timeout_event.addr, nla_data(addr), ETH_ALEN);
1232 wpa_supplicant_event(drv->ctx, ev, &event);
1233}
1234
1235
1236static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
1237 struct nlattr *freq, const u8 *frame, size_t len)
1238{
1239 const struct ieee80211_mgmt *mgmt;
1240 union wpa_event_data event;
1241 u16 fc, stype;
1242
1243 mgmt = (const struct ieee80211_mgmt *) frame;
1244 if (len < 24) {
1245 wpa_printf(MSG_DEBUG, "nl80211: Too short action frame");
1246 return;
1247 }
1248
1249 fc = le_to_host16(mgmt->frame_control);
1250 stype = WLAN_FC_GET_STYPE(fc);
1251
1252 os_memset(&event, 0, sizeof(event));
1253 if (freq) {
1254 event.rx_action.freq = nla_get_u32(freq);
1255 drv->last_mgmt_freq = event.rx_action.freq;
1256 }
1257 if (stype == WLAN_FC_STYPE_ACTION) {
1258 event.rx_action.da = mgmt->da;
1259 event.rx_action.sa = mgmt->sa;
1260 event.rx_action.bssid = mgmt->bssid;
1261 event.rx_action.category = mgmt->u.action.category;
1262 event.rx_action.data = &mgmt->u.action.category + 1;
1263 event.rx_action.len = frame + len - event.rx_action.data;
1264 wpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001265#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07001266 } else if (stype == WLAN_FC_STYPE_ASSOC_REQ) {
1267 mlme_event_assoc(drv, frame, len);
1268 } else if (stype == WLAN_FC_STYPE_DISASSOC) {
1269 mlme_event_deauth_disassoc(drv, EVENT_DISASSOC, frame, len);
1270 } else if (stype == WLAN_FC_STYPE_DEAUTH) {
1271 mlme_event_deauth_disassoc(drv, EVENT_DEAUTH, frame, len);
1272#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001273 } else {
1274 event.rx_mgmt.frame = frame;
1275 event.rx_mgmt.frame_len = len;
1276 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
1277 }
1278}
1279
1280
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001281static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
1282 struct nlattr *cookie, const u8 *frame,
1283 size_t len, struct nlattr *ack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001284{
1285 union wpa_event_data event;
1286 const struct ieee80211_hdr *hdr;
1287 u16 fc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001289 if (!is_ap_interface(drv->nlmode)) {
1290 u64 cookie_val;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001291
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001292 if (!cookie)
1293 return;
1294
1295 cookie_val = nla_get_u64(cookie);
1296 wpa_printf(MSG_DEBUG, "nl80211: Action TX status:"
1297 " cookie=0%llx%s (ack=%d)",
1298 (long long unsigned int) cookie_val,
1299 cookie_val == drv->send_action_cookie ?
1300 " (match)" : " (unknown)", ack != NULL);
1301 if (cookie_val != drv->send_action_cookie)
1302 return;
1303 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001304
1305 hdr = (const struct ieee80211_hdr *) frame;
1306 fc = le_to_host16(hdr->frame_control);
1307
1308 os_memset(&event, 0, sizeof(event));
1309 event.tx_status.type = WLAN_FC_GET_TYPE(fc);
1310 event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
1311 event.tx_status.dst = hdr->addr1;
1312 event.tx_status.data = frame;
1313 event.tx_status.data_len = len;
1314 event.tx_status.ack = ack != NULL;
1315 wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
1316}
1317
1318
1319static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
1320 enum wpa_event_type type,
1321 const u8 *frame, size_t len)
1322{
1323 const struct ieee80211_mgmt *mgmt;
1324 union wpa_event_data event;
1325 const u8 *bssid = NULL;
1326 u16 reason_code = 0;
1327
1328 mgmt = (const struct ieee80211_mgmt *) frame;
1329 if (len >= 24) {
1330 bssid = mgmt->bssid;
1331
1332 if (drv->associated != 0 &&
1333 os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
1334 os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
1335 /*
1336 * We have presumably received this deauth as a
1337 * response to a clear_state_mismatch() outgoing
1338 * deauth. Don't let it take us offline!
1339 */
1340 wpa_printf(MSG_DEBUG, "nl80211: Deauth received "
1341 "from Unknown BSSID " MACSTR " -- ignoring",
1342 MAC2STR(bssid));
1343 return;
1344 }
1345 }
1346
1347 drv->associated = 0;
1348 os_memset(&event, 0, sizeof(event));
1349
1350 /* Note: Same offset for Reason Code in both frame subtypes */
1351 if (len >= 24 + sizeof(mgmt->u.deauth))
1352 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1353
1354 if (type == EVENT_DISASSOC) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001355#ifdef ANDROID_P2P
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001356 if (drv->nlmode == NL80211_IFTYPE_AP ||
1357 drv->nlmode == NL80211_IFTYPE_P2P_GO) {
1358 event.disassoc_info.addr = mgmt->sa;
1359 } else
1360#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001361 event.disassoc_info.addr = bssid;
1362 event.disassoc_info.reason_code = reason_code;
1363 if (frame + len > mgmt->u.disassoc.variable) {
1364 event.disassoc_info.ie = mgmt->u.disassoc.variable;
1365 event.disassoc_info.ie_len = frame + len -
1366 mgmt->u.disassoc.variable;
1367 }
1368 } else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001369#ifdef ANDROID_P2P
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001370 if (drv->nlmode == NL80211_IFTYPE_AP ||
1371 drv->nlmode == NL80211_IFTYPE_P2P_GO) {
1372 event.deauth_info.addr = mgmt->sa;
1373 } else
1374#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375 event.deauth_info.addr = bssid;
1376 event.deauth_info.reason_code = reason_code;
1377 if (frame + len > mgmt->u.deauth.variable) {
1378 event.deauth_info.ie = mgmt->u.deauth.variable;
1379 event.deauth_info.ie_len = frame + len -
1380 mgmt->u.deauth.variable;
1381 }
1382 }
1383
1384 wpa_supplicant_event(drv->ctx, type, &event);
1385}
1386
1387
1388static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv,
1389 enum wpa_event_type type,
1390 const u8 *frame, size_t len)
1391{
1392 const struct ieee80211_mgmt *mgmt;
1393 union wpa_event_data event;
1394 u16 reason_code = 0;
1395
1396 if (len < 24)
1397 return;
1398
1399 mgmt = (const struct ieee80211_mgmt *) frame;
1400
1401 os_memset(&event, 0, sizeof(event));
1402 /* Note: Same offset for Reason Code in both frame subtypes */
1403 if (len >= 24 + sizeof(mgmt->u.deauth))
1404 reason_code = le_to_host16(mgmt->u.deauth.reason_code);
1405
1406 if (type == EVENT_UNPROT_DISASSOC) {
1407 event.unprot_disassoc.sa = mgmt->sa;
1408 event.unprot_disassoc.da = mgmt->da;
1409 event.unprot_disassoc.reason_code = reason_code;
1410 } else {
1411 event.unprot_deauth.sa = mgmt->sa;
1412 event.unprot_deauth.da = mgmt->da;
1413 event.unprot_deauth.reason_code = reason_code;
1414 }
1415
1416 wpa_supplicant_event(drv->ctx, type, &event);
1417}
1418
1419
1420static void mlme_event(struct wpa_driver_nl80211_data *drv,
1421 enum nl80211_commands cmd, struct nlattr *frame,
1422 struct nlattr *addr, struct nlattr *timed_out,
1423 struct nlattr *freq, struct nlattr *ack,
1424 struct nlattr *cookie)
1425{
1426 if (timed_out && addr) {
1427 mlme_timeout_event(drv, cmd, addr);
1428 return;
1429 }
1430
1431 if (frame == NULL) {
1432 wpa_printf(MSG_DEBUG, "nl80211: MLME event %d without frame "
1433 "data", cmd);
1434 return;
1435 }
1436
1437 wpa_printf(MSG_DEBUG, "nl80211: MLME event %d", cmd);
1438 wpa_hexdump(MSG_MSGDUMP, "nl80211: MLME event frame",
1439 nla_data(frame), nla_len(frame));
1440
1441 switch (cmd) {
1442 case NL80211_CMD_AUTHENTICATE:
1443 mlme_event_auth(drv, nla_data(frame), nla_len(frame));
1444 break;
1445 case NL80211_CMD_ASSOCIATE:
1446 mlme_event_assoc(drv, nla_data(frame), nla_len(frame));
1447 break;
1448 case NL80211_CMD_DEAUTHENTICATE:
1449 mlme_event_deauth_disassoc(drv, EVENT_DEAUTH,
1450 nla_data(frame), nla_len(frame));
1451 break;
1452 case NL80211_CMD_DISASSOCIATE:
1453 mlme_event_deauth_disassoc(drv, EVENT_DISASSOC,
1454 nla_data(frame), nla_len(frame));
1455 break;
1456 case NL80211_CMD_FRAME:
1457 mlme_event_mgmt(drv, freq, nla_data(frame), nla_len(frame));
1458 break;
1459 case NL80211_CMD_FRAME_TX_STATUS:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001460 mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
1461 nla_len(frame), ack);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001462 break;
1463 case NL80211_CMD_UNPROT_DEAUTHENTICATE:
1464 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,
1465 nla_data(frame), nla_len(frame));
1466 break;
1467 case NL80211_CMD_UNPROT_DISASSOCIATE:
1468 mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC,
1469 nla_data(frame), nla_len(frame));
1470 break;
1471 default:
1472 break;
1473 }
1474}
1475
1476
1477static void mlme_event_michael_mic_failure(struct wpa_driver_nl80211_data *drv,
1478 struct nlattr *tb[])
1479{
1480 union wpa_event_data data;
1481
1482 wpa_printf(MSG_DEBUG, "nl80211: MLME event Michael MIC failure");
1483 os_memset(&data, 0, sizeof(data));
1484 if (tb[NL80211_ATTR_MAC]) {
1485 wpa_hexdump(MSG_DEBUG, "nl80211: Source MAC address",
1486 nla_data(tb[NL80211_ATTR_MAC]),
1487 nla_len(tb[NL80211_ATTR_MAC]));
1488 data.michael_mic_failure.src = nla_data(tb[NL80211_ATTR_MAC]);
1489 }
1490 if (tb[NL80211_ATTR_KEY_SEQ]) {
1491 wpa_hexdump(MSG_DEBUG, "nl80211: TSC",
1492 nla_data(tb[NL80211_ATTR_KEY_SEQ]),
1493 nla_len(tb[NL80211_ATTR_KEY_SEQ]));
1494 }
1495 if (tb[NL80211_ATTR_KEY_TYPE]) {
1496 enum nl80211_key_type key_type =
1497 nla_get_u32(tb[NL80211_ATTR_KEY_TYPE]);
1498 wpa_printf(MSG_DEBUG, "nl80211: Key Type %d", key_type);
1499 if (key_type == NL80211_KEYTYPE_PAIRWISE)
1500 data.michael_mic_failure.unicast = 1;
1501 } else
1502 data.michael_mic_failure.unicast = 1;
1503
1504 if (tb[NL80211_ATTR_KEY_IDX]) {
1505 u8 key_id = nla_get_u8(tb[NL80211_ATTR_KEY_IDX]);
1506 wpa_printf(MSG_DEBUG, "nl80211: Key Id %d", key_id);
1507 }
1508
1509 wpa_supplicant_event(drv->ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
1510}
1511
1512
1513static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
1514 struct nlattr *tb[])
1515{
1516 if (tb[NL80211_ATTR_MAC] == NULL) {
1517 wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
1518 "event");
1519 return;
1520 }
1521 os_memcpy(drv->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
1522 drv->associated = 1;
1523 wpa_printf(MSG_DEBUG, "nl80211: IBSS " MACSTR " joined",
1524 MAC2STR(drv->bssid));
1525
1526 wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
1527}
1528
1529
1530static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
1531 int cancel_event, struct nlattr *tb[])
1532{
1533 unsigned int freq, chan_type, duration;
1534 union wpa_event_data data;
1535 u64 cookie;
1536
1537 if (tb[NL80211_ATTR_WIPHY_FREQ])
1538 freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
1539 else
1540 freq = 0;
1541
1542 if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
1543 chan_type = nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
1544 else
1545 chan_type = 0;
1546
1547 if (tb[NL80211_ATTR_DURATION])
1548 duration = nla_get_u32(tb[NL80211_ATTR_DURATION]);
1549 else
1550 duration = 0;
1551
1552 if (tb[NL80211_ATTR_COOKIE])
1553 cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
1554 else
1555 cookie = 0;
1556
1557 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel event (cancel=%d "
1558 "freq=%u channel_type=%u duration=%u cookie=0x%llx (%s))",
1559 cancel_event, freq, chan_type, duration,
1560 (long long unsigned int) cookie,
1561 cookie == drv->remain_on_chan_cookie ? "match" : "unknown");
1562
1563 if (cookie != drv->remain_on_chan_cookie)
1564 return; /* not for us */
1565
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001566 if (cancel_event)
1567 drv->pending_remain_on_chan = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001568
1569 os_memset(&data, 0, sizeof(data));
1570 data.remain_on_channel.freq = freq;
1571 data.remain_on_channel.duration = duration;
1572 wpa_supplicant_event(drv->ctx, cancel_event ?
1573 EVENT_CANCEL_REMAIN_ON_CHANNEL :
1574 EVENT_REMAIN_ON_CHANNEL, &data);
1575}
1576
1577
1578static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
1579 struct nlattr *tb[])
1580{
1581 union wpa_event_data event;
1582 struct nlattr *nl;
1583 int rem;
1584 struct scan_info *info;
1585#define MAX_REPORT_FREQS 50
1586 int freqs[MAX_REPORT_FREQS];
1587 int num_freqs = 0;
1588
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001589 if (drv->scan_for_auth) {
1590 drv->scan_for_auth = 0;
1591 wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
1592 "cfg80211 BSS entry");
1593 wpa_driver_nl80211_authenticate_retry(drv);
1594 return;
1595 }
1596
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001597 os_memset(&event, 0, sizeof(event));
1598 info = &event.scan_info;
1599 info->aborted = aborted;
1600
1601 if (tb[NL80211_ATTR_SCAN_SSIDS]) {
1602 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {
1603 struct wpa_driver_scan_ssid *s =
1604 &info->ssids[info->num_ssids];
1605 s->ssid = nla_data(nl);
1606 s->ssid_len = nla_len(nl);
1607 info->num_ssids++;
1608 if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
1609 break;
1610 }
1611 }
1612 if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
1613 nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)
1614 {
1615 freqs[num_freqs] = nla_get_u32(nl);
1616 num_freqs++;
1617 if (num_freqs == MAX_REPORT_FREQS - 1)
1618 break;
1619 }
1620 info->freqs = freqs;
1621 info->num_freqs = num_freqs;
1622 }
1623 wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
1624}
1625
1626
1627static int get_link_signal(struct nl_msg *msg, void *arg)
1628{
1629 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1630 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1631 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
1632 static struct nla_policy policy[NL80211_STA_INFO_MAX + 1] = {
1633 [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
1634 };
1635 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
1636 static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
1637 [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
1638 [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
1639 [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
1640 [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
1641 };
1642 struct wpa_signal_info *sig_change = arg;
1643
1644 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1645 genlmsg_attrlen(gnlh, 0), NULL);
1646 if (!tb[NL80211_ATTR_STA_INFO] ||
1647 nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
1648 tb[NL80211_ATTR_STA_INFO], policy))
1649 return NL_SKIP;
1650 if (!sinfo[NL80211_STA_INFO_SIGNAL])
1651 return NL_SKIP;
1652
1653 sig_change->current_signal =
1654 (s8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
1655
1656 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
1657 if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
1658 sinfo[NL80211_STA_INFO_TX_BITRATE],
1659 rate_policy)) {
1660 sig_change->current_txrate = 0;
1661 } else {
1662 if (rinfo[NL80211_RATE_INFO_BITRATE]) {
1663 sig_change->current_txrate =
1664 nla_get_u16(rinfo[
1665 NL80211_RATE_INFO_BITRATE]) * 100;
1666 }
1667 }
1668 }
1669
1670 return NL_SKIP;
1671}
1672
1673
1674static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
1675 struct wpa_signal_info *sig)
1676{
1677 struct nl_msg *msg;
1678
1679 sig->current_signal = -9999;
1680 sig->current_txrate = 0;
1681
1682 msg = nlmsg_alloc();
1683 if (!msg)
1684 return -ENOMEM;
1685
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001686 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001687
1688 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
1689 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
1690
1691 return send_and_recv_msgs(drv, msg, get_link_signal, sig);
1692 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001693 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001694 return -ENOBUFS;
1695}
1696
1697
1698static int get_link_noise(struct nl_msg *msg, void *arg)
1699{
1700 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1701 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1702 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
1703 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
1704 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
1705 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
1706 };
1707 struct wpa_signal_info *sig_change = arg;
1708
1709 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1710 genlmsg_attrlen(gnlh, 0), NULL);
1711
1712 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
1713 wpa_printf(MSG_DEBUG, "nl80211: survey data missing!");
1714 return NL_SKIP;
1715 }
1716
1717 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
1718 tb[NL80211_ATTR_SURVEY_INFO],
1719 survey_policy)) {
1720 wpa_printf(MSG_DEBUG, "nl80211: failed to parse nested "
1721 "attributes!");
1722 return NL_SKIP;
1723 }
1724
1725 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
1726 return NL_SKIP;
1727
1728 if (nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
1729 sig_change->frequency)
1730 return NL_SKIP;
1731
1732 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
1733 return NL_SKIP;
1734
1735 sig_change->current_noise =
1736 (s8) nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
1737
1738 return NL_SKIP;
1739}
1740
1741
1742static int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
1743 struct wpa_signal_info *sig_change)
1744{
1745 struct nl_msg *msg;
1746
1747 sig_change->current_noise = 9999;
1748 sig_change->frequency = drv->assoc_freq;
1749
1750 msg = nlmsg_alloc();
1751 if (!msg)
1752 return -ENOMEM;
1753
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001754 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001755
1756 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
1757
1758 return send_and_recv_msgs(drv, msg, get_link_noise, sig_change);
1759 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001760 nlmsg_free(msg);
1761 return -ENOBUFS;
1762}
1763
1764
1765static int get_noise_for_scan_results(struct nl_msg *msg, void *arg)
1766{
1767 struct nlattr *tb[NL80211_ATTR_MAX + 1];
1768 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1769 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
1770 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
1771 [NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
1772 [NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
1773 };
1774 struct wpa_scan_results *scan_results = arg;
1775 struct wpa_scan_res *scan_res;
1776 size_t i;
1777
1778 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1779 genlmsg_attrlen(gnlh, 0), NULL);
1780
1781 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
1782 wpa_printf(MSG_DEBUG, "nl80211: Survey data missing");
1783 return NL_SKIP;
1784 }
1785
1786 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
1787 tb[NL80211_ATTR_SURVEY_INFO],
1788 survey_policy)) {
1789 wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested "
1790 "attributes");
1791 return NL_SKIP;
1792 }
1793
1794 if (!sinfo[NL80211_SURVEY_INFO_NOISE])
1795 return NL_SKIP;
1796
1797 if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
1798 return NL_SKIP;
1799
1800 for (i = 0; i < scan_results->num; ++i) {
1801 scan_res = scan_results->res[i];
1802 if (!scan_res)
1803 continue;
1804 if ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
1805 scan_res->freq)
1806 continue;
1807 if (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))
1808 continue;
1809 scan_res->noise = (s8)
1810 nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
1811 scan_res->flags &= ~WPA_SCAN_NOISE_INVALID;
1812 }
1813
1814 return NL_SKIP;
1815}
1816
1817
1818static int nl80211_get_noise_for_scan_results(
1819 struct wpa_driver_nl80211_data *drv,
1820 struct wpa_scan_results *scan_res)
1821{
1822 struct nl_msg *msg;
1823
1824 msg = nlmsg_alloc();
1825 if (!msg)
1826 return -ENOMEM;
1827
1828 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
1829
1830 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
1831
1832 return send_and_recv_msgs(drv, msg, get_noise_for_scan_results,
1833 scan_res);
1834 nla_put_failure:
1835 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001836 return -ENOBUFS;
1837}
1838
1839
1840static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv,
1841 struct nlattr *tb[])
1842{
1843 static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
1844 [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
1845 [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
1846 [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
1847 [NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },
1848 };
1849 struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
1850 enum nl80211_cqm_rssi_threshold_event event;
1851 union wpa_event_data ed;
1852 struct wpa_signal_info sig;
1853 int res;
1854
1855 if (tb[NL80211_ATTR_CQM] == NULL ||
1856 nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb[NL80211_ATTR_CQM],
1857 cqm_policy)) {
1858 wpa_printf(MSG_DEBUG, "nl80211: Ignore invalid CQM event");
1859 return;
1860 }
1861
1862 os_memset(&ed, 0, sizeof(ed));
1863
1864 if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {
1865 if (!tb[NL80211_ATTR_MAC])
1866 return;
1867 os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),
1868 ETH_ALEN);
1869 wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
1870 return;
1871 }
1872
1873 if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)
1874 return;
1875 event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
1876
1877 if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
1878 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
1879 "event: RSSI high");
1880 ed.signal_change.above_threshold = 1;
1881 } else if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW) {
1882 wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
1883 "event: RSSI low");
1884 ed.signal_change.above_threshold = 0;
1885 } else
1886 return;
1887
1888 res = nl80211_get_link_signal(drv, &sig);
1889 if (res == 0) {
1890 ed.signal_change.current_signal = sig.current_signal;
1891 ed.signal_change.current_txrate = sig.current_txrate;
1892 wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d",
1893 sig.current_signal, sig.current_txrate);
1894 }
1895
1896 res = nl80211_get_link_noise(drv, &sig);
1897 if (res == 0) {
1898 ed.signal_change.current_noise = sig.current_noise;
1899 wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm",
1900 sig.current_noise);
1901 }
1902
1903 wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed);
1904}
1905
1906
1907static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
1908 struct nlattr **tb)
1909{
1910 u8 *addr;
1911 union wpa_event_data data;
1912
1913 if (tb[NL80211_ATTR_MAC] == NULL)
1914 return;
1915 addr = nla_data(tb[NL80211_ATTR_MAC]);
1916 wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr));
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07001917
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001918 if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07001919 u8 *ies = NULL;
1920 size_t ies_len = 0;
1921 if (tb[NL80211_ATTR_IE]) {
1922 ies = nla_data(tb[NL80211_ATTR_IE]);
1923 ies_len = nla_len(tb[NL80211_ATTR_IE]);
1924 }
1925 wpa_hexdump(MSG_DEBUG, "nl80211: Assoc Req IEs", ies, ies_len);
1926 drv_event_assoc(drv->ctx, addr, ies, ies_len, 0);
1927 return;
1928 }
1929
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001930 if (drv->nlmode != NL80211_IFTYPE_ADHOC)
1931 return;
1932
1933 os_memset(&data, 0, sizeof(data));
1934 os_memcpy(data.ibss_rsn_start.peer, addr, ETH_ALEN);
1935 wpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data);
1936}
1937
1938
1939static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
1940 struct nlattr **tb)
1941{
1942 u8 *addr;
1943 union wpa_event_data data;
1944
1945 if (tb[NL80211_ATTR_MAC] == NULL)
1946 return;
1947 addr = nla_data(tb[NL80211_ATTR_MAC]);
1948 wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR,
1949 MAC2STR(addr));
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07001950
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001951 if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07001952 drv_event_disassoc(drv->ctx, addr);
1953 return;
1954 }
1955
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001956 if (drv->nlmode != NL80211_IFTYPE_ADHOC)
1957 return;
1958
1959 os_memset(&data, 0, sizeof(data));
1960 os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);
1961 wpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);
1962}
1963
1964
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001965static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data *drv,
1966 struct nlattr **tb)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001967{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001968 struct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];
1969 static struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {
1970 [NL80211_REKEY_DATA_KEK] = {
1971 .minlen = NL80211_KEK_LEN,
1972 .maxlen = NL80211_KEK_LEN,
1973 },
1974 [NL80211_REKEY_DATA_KCK] = {
1975 .minlen = NL80211_KCK_LEN,
1976 .maxlen = NL80211_KCK_LEN,
1977 },
1978 [NL80211_REKEY_DATA_REPLAY_CTR] = {
1979 .minlen = NL80211_REPLAY_CTR_LEN,
1980 .maxlen = NL80211_REPLAY_CTR_LEN,
1981 },
1982 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001983 union wpa_event_data data;
1984
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001985 if (!tb[NL80211_ATTR_MAC])
1986 return;
1987 if (!tb[NL80211_ATTR_REKEY_DATA])
1988 return;
1989 if (nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,
1990 tb[NL80211_ATTR_REKEY_DATA], rekey_policy))
1991 return;
1992 if (!rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])
1993 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001994
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001995 os_memset(&data, 0, sizeof(data));
1996 data.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);
1997 wpa_printf(MSG_DEBUG, "nl80211: Rekey offload event for BSSID " MACSTR,
1998 MAC2STR(data.driver_gtk_rekey.bssid));
1999 data.driver_gtk_rekey.replay_ctr =
2000 nla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);
2001 wpa_hexdump(MSG_DEBUG, "nl80211: Rekey offload - Replay Counter",
2002 data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);
2003 wpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);
2004}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002005
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002006
2007static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
2008 struct nlattr **tb)
2009{
2010 struct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];
2011 static struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {
2012 [NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },
2013 [NL80211_PMKSA_CANDIDATE_BSSID] = {
2014 .minlen = ETH_ALEN,
2015 .maxlen = ETH_ALEN,
2016 },
2017 [NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },
2018 };
2019 union wpa_event_data data;
2020
2021 if (!tb[NL80211_ATTR_PMKSA_CANDIDATE])
2022 return;
2023 if (nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,
2024 tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy))
2025 return;
2026 if (!cand[NL80211_PMKSA_CANDIDATE_INDEX] ||
2027 !cand[NL80211_PMKSA_CANDIDATE_BSSID])
2028 return;
2029
2030 os_memset(&data, 0, sizeof(data));
2031 os_memcpy(data.pmkid_candidate.bssid,
2032 nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);
2033 data.pmkid_candidate.index =
2034 nla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);
2035 data.pmkid_candidate.preauth =
2036 cand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;
2037 wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
2038}
2039
2040
2041static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv,
2042 struct nlattr **tb)
2043{
2044 union wpa_event_data data;
2045
2046 if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
2047 return;
2048
2049 os_memset(&data, 0, sizeof(data));
2050 os_memcpy(data.client_poll.addr,
2051 nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
2052
2053 wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
2054}
2055
2056
2057static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
2058 int wds)
2059{
2060 struct wpa_driver_nl80211_data *drv = bss->drv;
2061 union wpa_event_data event;
2062
2063 if (!tb[NL80211_ATTR_MAC])
2064 return;
2065
2066 os_memset(&event, 0, sizeof(event));
2067 event.rx_from_unknown.bssid = bss->addr;
2068 event.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]);
2069 event.rx_from_unknown.wds = wds;
2070
2071 wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
2072}
2073
2074
2075static void do_process_drv_event(struct wpa_driver_nl80211_data *drv,
2076 int cmd, struct nlattr **tb)
2077{
2078 if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
2079 (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
2080 cmd == NL80211_CMD_SCAN_ABORTED)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002081 wpa_driver_nl80211_set_mode(&drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002082 drv->ap_scan_as_station);
2083 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002084 }
2085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002086 switch (cmd) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002087 case NL80211_CMD_TRIGGER_SCAN:
2088 wpa_printf(MSG_DEBUG, "nl80211: Scan trigger");
2089 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002090 case NL80211_CMD_START_SCHED_SCAN:
2091 wpa_printf(MSG_DEBUG, "nl80211: Sched scan started");
2092 break;
2093 case NL80211_CMD_SCHED_SCAN_STOPPED:
2094 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stopped");
2095 wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
2096 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097 case NL80211_CMD_NEW_SCAN_RESULTS:
2098 wpa_printf(MSG_DEBUG, "nl80211: New scan results available");
2099 drv->scan_complete_events = 1;
2100 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
2101 drv->ctx);
2102 send_scan_event(drv, 0, tb);
2103 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002104 case NL80211_CMD_SCHED_SCAN_RESULTS:
2105 wpa_printf(MSG_DEBUG,
2106 "nl80211: New sched scan results available");
2107 send_scan_event(drv, 0, tb);
2108 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002109 case NL80211_CMD_SCAN_ABORTED:
2110 wpa_printf(MSG_DEBUG, "nl80211: Scan aborted");
2111 /*
2112 * Need to indicate that scan results are available in order
2113 * not to make wpa_supplicant stop its scanning.
2114 */
2115 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
2116 drv->ctx);
2117 send_scan_event(drv, 1, tb);
2118 break;
2119 case NL80211_CMD_AUTHENTICATE:
2120 case NL80211_CMD_ASSOCIATE:
2121 case NL80211_CMD_DEAUTHENTICATE:
2122 case NL80211_CMD_DISASSOCIATE:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002123 case NL80211_CMD_FRAME_TX_STATUS:
2124 case NL80211_CMD_UNPROT_DEAUTHENTICATE:
2125 case NL80211_CMD_UNPROT_DISASSOCIATE:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002126 mlme_event(drv, cmd, tb[NL80211_ATTR_FRAME],
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127 tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
2128 tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
2129 tb[NL80211_ATTR_COOKIE]);
2130 break;
2131 case NL80211_CMD_CONNECT:
2132 case NL80211_CMD_ROAM:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002133 mlme_event_connect(drv, cmd,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002134 tb[NL80211_ATTR_STATUS_CODE],
2135 tb[NL80211_ATTR_MAC],
2136 tb[NL80211_ATTR_REQ_IE],
2137 tb[NL80211_ATTR_RESP_IE]);
2138 break;
2139 case NL80211_CMD_DISCONNECT:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002140 mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
2141 tb[NL80211_ATTR_MAC]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142 break;
2143 case NL80211_CMD_MICHAEL_MIC_FAILURE:
2144 mlme_event_michael_mic_failure(drv, tb);
2145 break;
2146 case NL80211_CMD_JOIN_IBSS:
2147 mlme_event_join_ibss(drv, tb);
2148 break;
2149 case NL80211_CMD_REMAIN_ON_CHANNEL:
2150 mlme_event_remain_on_channel(drv, 0, tb);
2151 break;
2152 case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:
2153 mlme_event_remain_on_channel(drv, 1, tb);
2154 break;
2155 case NL80211_CMD_NOTIFY_CQM:
2156 nl80211_cqm_event(drv, tb);
2157 break;
2158 case NL80211_CMD_REG_CHANGE:
2159 wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
2160 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
2161 NULL);
2162 break;
2163 case NL80211_CMD_REG_BEACON_HINT:
2164 wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint");
2165 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
2166 NULL);
2167 break;
2168 case NL80211_CMD_NEW_STATION:
2169 nl80211_new_station_event(drv, tb);
2170 break;
2171 case NL80211_CMD_DEL_STATION:
2172 nl80211_del_station_event(drv, tb);
2173 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002174 case NL80211_CMD_SET_REKEY_OFFLOAD:
2175 nl80211_rekey_offload_event(drv, tb);
2176 break;
2177 case NL80211_CMD_PMKSA_CANDIDATE:
2178 nl80211_pmksa_candidate_event(drv, tb);
2179 break;
2180 case NL80211_CMD_PROBE_CLIENT:
2181 nl80211_client_probe_event(drv, tb);
2182 break;
2183 default:
2184 wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
2185 "(cmd=%d)", cmd);
2186 break;
2187 }
2188}
2189
2190
2191static int process_drv_event(struct nl_msg *msg, void *arg)
2192{
2193 struct wpa_driver_nl80211_data *drv = arg;
2194 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2195 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2196
2197 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2198 genlmsg_attrlen(gnlh, 0), NULL);
2199
2200 if (tb[NL80211_ATTR_IFINDEX]) {
2201 int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
2202 if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) {
2203 wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)"
2204 " for foreign interface (ifindex %d)",
2205 gnlh->cmd, ifindex);
2206 return NL_SKIP;
2207 }
2208 }
2209
2210 do_process_drv_event(drv, gnlh->cmd, tb);
2211 return NL_SKIP;
2212}
2213
2214
2215static int process_global_event(struct nl_msg *msg, void *arg)
2216{
2217 struct nl80211_global *global = arg;
2218 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2219 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2220 struct wpa_driver_nl80211_data *drv;
2221 int ifidx = -1;
2222
2223 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2224 genlmsg_attrlen(gnlh, 0), NULL);
2225
2226 if (tb[NL80211_ATTR_IFINDEX])
2227 ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
2228
2229 dl_list_for_each(drv, &global->interfaces,
2230 struct wpa_driver_nl80211_data, list) {
2231 if (ifidx == -1 || ifidx == drv->ifindex ||
2232 have_ifidx(drv, ifidx))
2233 do_process_drv_event(drv, gnlh->cmd, tb);
2234 }
2235
2236 return NL_SKIP;
2237}
2238
2239
2240static int process_bss_event(struct nl_msg *msg, void *arg)
2241{
2242 struct i802_bss *bss = arg;
2243 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2244 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2245
2246 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2247 genlmsg_attrlen(gnlh, 0), NULL);
2248
2249 switch (gnlh->cmd) {
2250 case NL80211_CMD_FRAME:
2251 case NL80211_CMD_FRAME_TX_STATUS:
2252 mlme_event(bss->drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],
2253 tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
2254 tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
2255 tb[NL80211_ATTR_COOKIE]);
2256 break;
2257 case NL80211_CMD_UNEXPECTED_FRAME:
2258 nl80211_spurious_frame(bss, tb, 0);
2259 break;
2260 case NL80211_CMD_UNEXPECTED_4ADDR_FRAME:
2261 nl80211_spurious_frame(bss, tb, 1);
2262 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002263 default:
2264 wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
2265 "(cmd=%d)", gnlh->cmd);
2266 break;
2267 }
2268
2269 return NL_SKIP;
2270}
2271
2272
2273static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
2274 void *handle)
2275{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002276 struct nl_cb *cb = eloop_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002277
2278 wpa_printf(MSG_DEBUG, "nl80211: Event message available");
2279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002280 nl_recvmsgs(handle, cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002281}
2282
2283
2284/**
2285 * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
2286 * @priv: driver_nl80211 private data
2287 * @alpha2_arg: country to which to switch to
2288 * Returns: 0 on success, -1 on failure
2289 *
2290 * This asks nl80211 to set the regulatory domain for given
2291 * country ISO / IEC alpha2.
2292 */
2293static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
2294{
2295 struct i802_bss *bss = priv;
2296 struct wpa_driver_nl80211_data *drv = bss->drv;
2297 char alpha2[3];
2298 struct nl_msg *msg;
2299
2300 msg = nlmsg_alloc();
2301 if (!msg)
2302 return -ENOMEM;
2303
2304 alpha2[0] = alpha2_arg[0];
2305 alpha2[1] = alpha2_arg[1];
2306 alpha2[2] = '\0';
2307
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002308 nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002309
2310 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
2311 if (send_and_recv_msgs(drv, msg, NULL, NULL))
2312 return -EINVAL;
2313 return 0;
2314nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002315 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002316 return -EINVAL;
2317}
2318
2319
2320struct wiphy_info_data {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002321 struct wpa_driver_capa *capa;
2322
2323 unsigned int error:1;
2324 unsigned int device_ap_sme:1;
2325 unsigned int poll_command_supported:1;
2326 unsigned int data_tx_status:1;
2327 unsigned int monitor_supported:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002328};
2329
2330
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002331static unsigned int probe_resp_offload_support(int supp_protocols)
2332{
2333 unsigned int prot = 0;
2334
2335 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS)
2336 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS;
2337 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)
2338 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2;
2339 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P)
2340 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P;
2341 if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U)
2342 prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING;
2343
2344 return prot;
2345}
2346
2347
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348static int wiphy_info_handler(struct nl_msg *msg, void *arg)
2349{
2350 struct nlattr *tb[NL80211_ATTR_MAX + 1];
2351 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2352 struct wiphy_info_data *info = arg;
2353 int p2p_go_supported = 0, p2p_client_supported = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002354 int p2p_concurrent = 0;
2355 int auth_supported = 0, connect_supported = 0;
2356 struct wpa_driver_capa *capa = info->capa;
2357 static struct nla_policy
2358 iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
2359 [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
2360 [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
2361 [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
2362 [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
2363 },
2364 iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
2365 [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
2366 [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
2367 };
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002368
2369 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
2370 genlmsg_attrlen(gnlh, 0), NULL);
2371
2372 if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002373 capa->max_scan_ssids =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
2375
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002376 if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])
2377 capa->max_sched_scan_ssids =
2378 nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
2379
2380 if (tb[NL80211_ATTR_MAX_MATCH_SETS])
2381 capa->max_match_sets =
2382 nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
2383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384 if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) {
2385 struct nlattr *nl_mode;
2386 int i;
2387 nla_for_each_nested(nl_mode,
2388 tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {
2389 switch (nla_type(nl_mode)) {
2390 case NL80211_IFTYPE_AP:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002391 capa->flags |= WPA_DRIVER_FLAGS_AP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002392 break;
2393 case NL80211_IFTYPE_P2P_GO:
2394 p2p_go_supported = 1;
2395 break;
2396 case NL80211_IFTYPE_P2P_CLIENT:
2397 p2p_client_supported = 1;
2398 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002399 case NL80211_IFTYPE_MONITOR:
2400 info->monitor_supported = 1;
2401 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402 }
2403 }
2404 }
2405
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002406 if (tb[NL80211_ATTR_INTERFACE_COMBINATIONS]) {
2407 struct nlattr *nl_combi;
2408 int rem_combi;
2409
2410 nla_for_each_nested(nl_combi,
2411 tb[NL80211_ATTR_INTERFACE_COMBINATIONS],
2412 rem_combi) {
2413 struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
2414 struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
2415 struct nlattr *nl_limit, *nl_mode;
2416 int err, rem_limit, rem_mode;
2417 int combination_has_p2p = 0, combination_has_mgd = 0;
2418
2419 err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
2420 nl_combi,
2421 iface_combination_policy);
2422 if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
2423 !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
2424 !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
2425 goto broken_combination;
2426
2427 nla_for_each_nested(nl_limit,
2428 tb_comb[NL80211_IFACE_COMB_LIMITS],
2429 rem_limit) {
2430 err = nla_parse_nested(tb_limit,
2431 MAX_NL80211_IFACE_LIMIT,
2432 nl_limit,
2433 iface_limit_policy);
2434 if (err ||
2435 !tb_limit[NL80211_IFACE_LIMIT_TYPES])
2436 goto broken_combination;
2437
2438 nla_for_each_nested(
2439 nl_mode,
2440 tb_limit[NL80211_IFACE_LIMIT_TYPES],
2441 rem_mode) {
2442 int ift = nla_type(nl_mode);
2443 if (ift == NL80211_IFTYPE_P2P_GO ||
2444 ift == NL80211_IFTYPE_P2P_CLIENT)
2445 combination_has_p2p = 1;
2446 if (ift == NL80211_IFTYPE_STATION)
2447 combination_has_mgd = 1;
2448 }
2449 if (combination_has_p2p && combination_has_mgd)
2450 break;
2451 }
2452
2453 if (combination_has_p2p && combination_has_mgd) {
2454 p2p_concurrent = 1;
2455 break;
2456 }
2457
2458broken_combination:
2459 ;
2460 }
2461 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462
2463 if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {
2464 struct nlattr *nl_cmd;
2465 int i;
2466
2467 nla_for_each_nested(nl_cmd,
2468 tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002469 switch (nla_get_u32(nl_cmd)) {
2470 case NL80211_CMD_AUTHENTICATE:
2471 auth_supported = 1;
2472 break;
2473 case NL80211_CMD_CONNECT:
2474 connect_supported = 1;
2475 break;
2476 case NL80211_CMD_START_SCHED_SCAN:
2477 capa->sched_scan_supported = 1;
2478 break;
2479 case NL80211_CMD_PROBE_CLIENT:
2480 info->poll_command_supported = 1;
2481 break;
2482 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 }
2484 }
2485
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002486 if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
2487 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
2488 "off-channel TX");
2489 capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
2490 }
2491
2492 if (tb[NL80211_ATTR_ROAM_SUPPORT]) {
2493 wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming");
2494 capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
2495 }
2496
2497 /* default to 5000 since early versions of mac80211 don't set it */
2498 capa->max_remain_on_chan = 5000;
2499
2500 if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
2501 capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502
2503 if (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION])
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002504 capa->max_remain_on_chan =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 nla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
2506
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002507 if (auth_supported)
2508 capa->flags |= WPA_DRIVER_FLAGS_SME;
2509 else if (!connect_supported) {
2510 wpa_printf(MSG_INFO, "nl80211: Driver does not support "
2511 "authentication/association or connect commands");
2512 info->error = 1;
2513 }
2514
2515 if (p2p_go_supported && p2p_client_supported)
2516 capa->flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
2517 if (p2p_concurrent) {
2518 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
2519 "interface (driver advertised support)");
2520 capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
2521 capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
2522 }
2523
2524 if (tb[NL80211_ATTR_TDLS_SUPPORT]) {
2525 wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
2526 capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
2527
2528 if (tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]) {
2529 wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
2530 capa->flags |=
2531 WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
2532 }
2533 }
2534
2535 if (tb[NL80211_ATTR_DEVICE_AP_SME])
2536 info->device_ap_sme = 1;
2537
2538 if (tb[NL80211_ATTR_FEATURE_FLAGS]) {
2539 u32 flags = nla_get_u32(tb[NL80211_ATTR_FEATURE_FLAGS]);
2540
2541 if (flags & NL80211_FEATURE_SK_TX_STATUS)
2542 info->data_tx_status = 1;
2543 }
2544
2545 if (tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]) {
2546 int protocols =
2547 nla_get_u32(tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
2548 wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response "
2549 "offload in AP mode");
2550 capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
2551 capa->probe_resp_offloads =
2552 probe_resp_offload_support(protocols);
2553 }
2554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 return NL_SKIP;
2556}
2557
2558
2559static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
2560 struct wiphy_info_data *info)
2561{
2562 struct nl_msg *msg;
2563
2564 os_memset(info, 0, sizeof(*info));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002565 info->capa = &drv->capa;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566
2567 msg = nlmsg_alloc();
2568 if (!msg)
2569 return -1;
2570
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002571 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002572
2573 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->first_bss.ifindex);
2574
2575 if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info) == 0)
2576 return 0;
2577 msg = NULL;
2578nla_put_failure:
2579 nlmsg_free(msg);
2580 return -1;
2581}
2582
2583
2584static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
2585{
2586 struct wiphy_info_data info;
2587 if (wpa_driver_nl80211_get_info(drv, &info))
2588 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002589
2590 if (info.error)
2591 return -1;
2592
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002593 drv->has_capability = 1;
2594 /* For now, assume TKIP, CCMP, WPA, WPA2 are supported */
2595 drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
2596 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
2597 WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
2598 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
2599 drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 |
2600 WPA_DRIVER_CAPA_ENC_WEP104 |
2601 WPA_DRIVER_CAPA_ENC_TKIP |
2602 WPA_DRIVER_CAPA_ENC_CCMP;
2603 drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
2604 WPA_DRIVER_AUTH_SHARED |
2605 WPA_DRIVER_AUTH_LEAP;
2606
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
2608 drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002610 drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
2611
2612 drv->device_ap_sme = info.device_ap_sme;
2613 drv->poll_command_supported = info.poll_command_supported;
2614 drv->data_tx_status = info.data_tx_status;
2615
2616 /*
2617 * If poll command is supported mac80211 is new enough to
2618 * have everything we need to not need monitor interfaces.
2619 */
2620 drv->use_monitor = !info.poll_command_supported;
2621
2622 if (drv->device_ap_sme && drv->use_monitor) {
2623 /*
2624 * Non-mac80211 drivers may not support monitor interface.
2625 * Make sure we do not get stuck with incorrect capability here
2626 * by explicitly testing this.
2627 */
2628 if (!info.monitor_supported) {
2629 wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor "
2630 "with device_ap_sme since no monitor mode "
2631 "support detected");
2632 drv->use_monitor = 0;
2633 }
2634 }
2635
2636 /*
2637 * If we aren't going to use monitor interfaces, but the
2638 * driver doesn't support data TX status, we won't get TX
2639 * status for EAPOL frames.
2640 */
2641 if (!drv->use_monitor && !info.data_tx_status)
2642 drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643
2644 return 0;
2645}
2646
2647
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002648#ifdef ANDROID
2649static int android_genl_ctrl_resolve(struct nl_handle *handle,
2650 const char *name)
2651{
2652 /*
2653 * Android ICS has very minimal genl_ctrl_resolve() implementation, so
2654 * need to work around that.
2655 */
2656 struct nl_cache *cache = NULL;
2657 struct genl_family *nl80211 = NULL;
2658 int id = -1;
2659
2660 if (genl_ctrl_alloc_cache(handle, &cache) < 0) {
2661 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
2662 "netlink cache");
2663 goto fail;
2664 }
2665
2666 nl80211 = genl_ctrl_search_by_name(cache, name);
2667 if (nl80211 == NULL)
2668 goto fail;
2669
2670 id = genl_family_get_id(nl80211);
2671
2672fail:
2673 if (nl80211)
2674 genl_family_put(nl80211);
2675 if (cache)
2676 nl_cache_free(cache);
2677
2678 return id;
2679}
2680#define genl_ctrl_resolve android_genl_ctrl_resolve
2681#endif /* ANDROID */
2682
2683
2684static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002685{
2686 int ret;
2687
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002688 global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
2689 if (global->nl_cb == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
2691 "callbacks");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002692 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 }
2694
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002695 global->nl = nl_create_handle(global->nl_cb, "nl");
2696 if (global->nl == NULL)
2697 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002699 global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
2700 if (global->nl80211_id < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
2702 "found");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002703 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002704 }
2705
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002706 global->nl_event = nl_create_handle(global->nl_cb, "event");
2707 if (global->nl_event == NULL)
2708 goto err;
2709
2710 ret = nl_get_multicast_id(global, "nl80211", "scan");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002712 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 if (ret < 0) {
2714 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
2715 "membership for scan events: %d (%s)",
2716 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002717 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718 }
2719
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002720 ret = nl_get_multicast_id(global, "nl80211", "mlme");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002722 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002723 if (ret < 0) {
2724 wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
2725 "membership for mlme events: %d (%s)",
2726 ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002727 goto err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002728 }
2729
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002730 ret = nl_get_multicast_id(global, "nl80211", "regulatory");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 if (ret >= 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002732 ret = nl_socket_add_membership(global->nl_event, ret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002733 if (ret < 0) {
2734 wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
2735 "membership for regulatory events: %d (%s)",
2736 ret, strerror(-ret));
2737 /* Continue without regulatory events */
2738 }
2739
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002740 nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
2741 no_seq_check, NULL);
2742 nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
2743 process_global_event, global);
2744
2745 eloop_register_read_sock(nl_socket_get_fd(global->nl_event),
2746 wpa_driver_nl80211_event_receive,
2747 global->nl_cb, global->nl_event);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748
2749 return 0;
2750
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002751err:
2752 nl_destroy_handles(&global->nl_event);
2753 nl_destroy_handles(&global->nl);
2754 nl_cb_put(global->nl_cb);
2755 global->nl_cb = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002756 return -1;
2757}
2758
2759
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002760static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
2761{
2762 drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
2763 if (!drv->nl_cb) {
2764 wpa_printf(MSG_ERROR, "nl80211: Failed to alloc cb struct");
2765 return -1;
2766 }
2767
2768 nl_cb_set(drv->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
2769 no_seq_check, NULL);
2770 nl_cb_set(drv->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
2771 process_drv_event, drv);
2772
2773 return 0;
2774}
2775
2776
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002777static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
2778{
2779 wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
2780 /*
2781 * This may be for any interface; use ifdown event to disable
2782 * interface.
2783 */
2784}
2785
2786
2787static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
2788{
2789 struct wpa_driver_nl80211_data *drv = ctx;
2790 wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002791 if (linux_set_iface_flags(drv->global->ioctl_sock,
2792 drv->first_bss.ifname, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793 wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
2794 "after rfkill unblock");
2795 return;
2796 }
2797 /* rtnetlink ifup handler will report interface as enabled */
2798}
2799
2800
2801static void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv)
2802{
2803 /* Find phy (radio) to which this interface belongs */
2804 char buf[90], *pos;
2805 int f, rv;
2806
2807 drv->phyname[0] = '\0';
2808 snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name",
2809 drv->first_bss.ifname);
2810 f = open(buf, O_RDONLY);
2811 if (f < 0) {
2812 wpa_printf(MSG_DEBUG, "Could not open file %s: %s",
2813 buf, strerror(errno));
2814 return;
2815 }
2816
2817 rv = read(f, drv->phyname, sizeof(drv->phyname) - 1);
2818 close(f);
2819 if (rv < 0) {
2820 wpa_printf(MSG_DEBUG, "Could not read file %s: %s",
2821 buf, strerror(errno));
2822 return;
2823 }
2824
2825 drv->phyname[rv] = '\0';
2826 pos = os_strchr(drv->phyname, '\n');
2827 if (pos)
2828 *pos = '\0';
2829 wpa_printf(MSG_DEBUG, "nl80211: interface %s in phy %s",
2830 drv->first_bss.ifname, drv->phyname);
2831}
2832
2833
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002834static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
2835 void *eloop_ctx,
2836 void *handle)
2837{
2838 struct wpa_driver_nl80211_data *drv = eloop_ctx;
2839 u8 data[2048];
2840 struct msghdr msg;
2841 struct iovec entry;
2842 struct {
2843 struct cmsghdr cm;
2844 char control[512];
2845 } control;
2846 struct cmsghdr *cmsg;
2847 int res, found_ee = 0, found_wifi = 0, acked = 0;
2848 union wpa_event_data event;
2849
2850 memset(&msg, 0, sizeof(msg));
2851 msg.msg_iov = &entry;
2852 msg.msg_iovlen = 1;
2853 entry.iov_base = data;
2854 entry.iov_len = sizeof(data);
2855 msg.msg_control = &control;
2856 msg.msg_controllen = sizeof(control);
2857
2858 res = recvmsg(sock, &msg, MSG_ERRQUEUE);
2859 /* if error or not fitting 802.3 header, return */
2860 if (res < 14)
2861 return;
2862
2863 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
2864 {
2865 if (cmsg->cmsg_level == SOL_SOCKET &&
2866 cmsg->cmsg_type == SCM_WIFI_STATUS) {
2867 int *ack;
2868
2869 found_wifi = 1;
2870 ack = (void *)CMSG_DATA(cmsg);
2871 acked = *ack;
2872 }
2873
2874 if (cmsg->cmsg_level == SOL_PACKET &&
2875 cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
2876 struct sock_extended_err *err =
2877 (struct sock_extended_err *)CMSG_DATA(cmsg);
2878
2879 if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
2880 found_ee = 1;
2881 }
2882 }
2883
2884 if (!found_ee || !found_wifi)
2885 return;
2886
2887 memset(&event, 0, sizeof(event));
2888 event.eapol_tx_status.dst = data;
2889 event.eapol_tx_status.data = data + 14;
2890 event.eapol_tx_status.data_len = res - 14;
2891 event.eapol_tx_status.ack = acked;
2892 wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
2893}
2894
2895
2896static int nl80211_init_bss(struct i802_bss *bss)
2897{
2898 bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
2899 if (!bss->nl_cb)
2900 return -1;
2901
2902 nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
2903 no_seq_check, NULL);
2904 nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
2905 process_bss_event, bss);
2906
2907 return 0;
2908}
2909
2910
2911static void nl80211_destroy_bss(struct i802_bss *bss)
2912{
2913 nl_cb_put(bss->nl_cb);
2914 bss->nl_cb = NULL;
2915}
2916
2917
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002918/**
2919 * wpa_driver_nl80211_init - Initialize nl80211 driver interface
2920 * @ctx: context to be used when calling wpa_supplicant functions,
2921 * e.g., wpa_supplicant_event()
2922 * @ifname: interface name, e.g., wlan0
2923 * @global_priv: private driver global data from global_init()
2924 * Returns: Pointer to private data, %NULL on failure
2925 */
2926static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
2927 void *global_priv)
2928{
2929 struct wpa_driver_nl80211_data *drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002930 struct rfkill_config *rcfg;
2931 struct i802_bss *bss;
2932
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002933 if (global_priv == NULL)
2934 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002935 drv = os_zalloc(sizeof(*drv));
2936 if (drv == NULL)
2937 return NULL;
2938 drv->global = global_priv;
2939 drv->ctx = ctx;
2940 bss = &drv->first_bss;
2941 bss->drv = drv;
2942 os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
2943 drv->monitor_ifidx = -1;
2944 drv->monitor_sock = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002945 drv->eapol_tx_sock = -1;
2946 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002947
2948 if (wpa_driver_nl80211_init_nl(drv)) {
2949 os_free(drv);
2950 return NULL;
2951 }
2952
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002953 if (nl80211_init_bss(bss))
2954 goto failed;
2955
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002956 nl80211_get_phy_name(drv);
2957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002958 rcfg = os_zalloc(sizeof(*rcfg));
2959 if (rcfg == NULL)
2960 goto failed;
2961 rcfg->ctx = drv;
2962 os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
2963 rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
2964 rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
2965 drv->rfkill = rfkill_init(rcfg);
2966 if (drv->rfkill == NULL) {
2967 wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
2968 os_free(rcfg);
2969 }
2970
2971 if (wpa_driver_nl80211_finish_drv_init(drv))
2972 goto failed;
2973
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002974 drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
2975 if (drv->eapol_tx_sock < 0)
2976 goto failed;
2977
2978 if (drv->data_tx_status) {
2979 int enabled = 1;
2980
2981 if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
2982 &enabled, sizeof(enabled)) < 0) {
2983 wpa_printf(MSG_DEBUG,
2984 "nl80211: wifi status sockopt failed\n");
2985 drv->data_tx_status = 0;
2986 if (!drv->use_monitor)
2987 drv->capa.flags &=
2988 ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
2989 } else {
2990 eloop_register_read_sock(drv->eapol_tx_sock,
2991 wpa_driver_nl80211_handle_eapol_tx_status,
2992 drv, NULL);
2993 }
2994 }
2995
2996 if (drv->global) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002997 dl_list_add(&drv->global->interfaces, &drv->list);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002998 drv->in_interface_list = 1;
2999 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003000
3001 return bss;
3002
3003failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003004 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003005 return NULL;
3006}
3007
3008
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003009static int nl80211_register_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003010 struct nl_handle *nl_handle,
3011 u16 type, const u8 *match, size_t match_len)
3012{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003013 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014 struct nl_msg *msg;
3015 int ret = -1;
3016
3017 msg = nlmsg_alloc();
3018 if (!msg)
3019 return -1;
3020
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003021 wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x nl_handle=%p",
3022 type, nl_handle);
3023 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
3024 match, match_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003025
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003026 nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
3027
3028 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003029 NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
3030 NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);
3031
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003032 ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003033 msg = NULL;
3034 if (ret) {
3035 wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
3036 "failed (type=%u): ret=%d (%s)",
3037 type, ret, strerror(-ret));
3038 wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
3039 match, match_len);
3040 goto nla_put_failure;
3041 }
3042 ret = 0;
3043nla_put_failure:
3044 nlmsg_free(msg);
3045 return ret;
3046}
3047
3048
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003049static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
3050{
3051 struct wpa_driver_nl80211_data *drv = bss->drv;
3052
3053 if (bss->nl_mgmt) {
3054 wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting "
3055 "already on! (nl_mgmt=%p)", bss->nl_mgmt);
3056 return -1;
3057 }
3058
3059 bss->nl_mgmt = nl_create_handle(drv->nl_cb, "mgmt");
3060 if (bss->nl_mgmt == NULL)
3061 return -1;
3062
3063 eloop_register_read_sock(nl_socket_get_fd(bss->nl_mgmt),
3064 wpa_driver_nl80211_event_receive, bss->nl_cb,
3065 bss->nl_mgmt);
3066
3067 return 0;
3068}
3069
3070
3071static int nl80211_register_action_frame(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003072 const u8 *match, size_t match_len)
3073{
3074 u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003075 return nl80211_register_frame(bss, bss->nl_mgmt,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003076 type, match, match_len);
3077}
3078
3079
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003080static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003081{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003082 struct wpa_driver_nl80211_data *drv = bss->drv;
3083
3084 if (nl80211_alloc_mgmt_handle(bss))
3085 return -1;
3086 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
3087 "handle %p", bss->nl_mgmt);
3088
3089#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003090 /* GAS Initial Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003091 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003092 return -1;
3093 /* GAS Initial Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003094 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003095 return -1;
3096 /* GAS Comeback Request */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003097 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003098 return -1;
3099 /* GAS Comeback Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003100 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003101 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003102#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
3103#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003104 /* P2P Public Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003105 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003106 (u8 *) "\x04\x09\x50\x6f\x9a\x09",
3107 6) < 0)
3108 return -1;
3109 /* P2P Action */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003110 if (nl80211_register_action_frame(bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003111 (u8 *) "\x7f\x50\x6f\x9a\x09",
3112 5) < 0)
3113 return -1;
3114#endif /* CONFIG_P2P */
3115#ifdef CONFIG_IEEE80211W
3116 /* SA Query Response */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003117 if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003118 return -1;
3119#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003120#ifdef CONFIG_TDLS
3121 if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
3122 /* TDLS Discovery Response */
3123 if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
3124 0)
3125 return -1;
3126 }
3127#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003128
3129 /* FT Action frames */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003130 if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003131 return -1;
3132 else
3133 drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
3134 WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
3135
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003136 /* WNM - BSS Transition Management Request */
3137 if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
3138 return -1;
3139
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003140 return 0;
3141}
3142
3143
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003144static int nl80211_register_spurious_class3(struct i802_bss *bss)
3145{
3146 struct wpa_driver_nl80211_data *drv = bss->drv;
3147 struct nl_msg *msg;
3148 int ret = -1;
3149
3150 msg = nlmsg_alloc();
3151 if (!msg)
3152 return -1;
3153
3154 nl80211_cmd(drv, msg, 0, NL80211_CMD_UNEXPECTED_FRAME);
3155
3156 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
3157
3158 ret = send_and_recv(drv->global, bss->nl_mgmt, msg, NULL, NULL);
3159 msg = NULL;
3160 if (ret) {
3161 wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
3162 "failed: ret=%d (%s)",
3163 ret, strerror(-ret));
3164 goto nla_put_failure;
3165 }
3166 ret = 0;
3167nla_put_failure:
3168 nlmsg_free(msg);
3169 return ret;
3170}
3171
3172
3173static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
3174{
3175 static const int stypes[] = {
3176 WLAN_FC_STYPE_AUTH,
3177 WLAN_FC_STYPE_ASSOC_REQ,
3178 WLAN_FC_STYPE_REASSOC_REQ,
3179 WLAN_FC_STYPE_DISASSOC,
3180 WLAN_FC_STYPE_DEAUTH,
3181 WLAN_FC_STYPE_ACTION,
3182 WLAN_FC_STYPE_PROBE_REQ,
3183/* Beacon doesn't work as mac80211 doesn't currently allow
3184 * it, but it wouldn't really be the right thing anyway as
3185 * it isn't per interface ... maybe just dump the scan
3186 * results periodically for OLBC?
3187 */
3188// WLAN_FC_STYPE_BEACON,
3189 };
3190 unsigned int i;
3191
3192 if (nl80211_alloc_mgmt_handle(bss))
3193 return -1;
3194 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
3195 "handle %p", bss->nl_mgmt);
3196
3197 for (i = 0; i < sizeof(stypes) / sizeof(stypes[0]); i++) {
3198 if (nl80211_register_frame(bss, bss->nl_mgmt,
3199 (WLAN_FC_TYPE_MGMT << 2) |
3200 (stypes[i] << 4),
3201 NULL, 0) < 0) {
3202 goto out_err;
3203 }
3204 }
3205
3206 if (nl80211_register_spurious_class3(bss))
3207 goto out_err;
3208
3209 if (nl80211_get_wiphy_data_ap(bss) == NULL)
3210 goto out_err;
3211
3212 return 0;
3213
3214out_err:
3215 eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));
3216 nl_destroy_handles(&bss->nl_mgmt);
3217 return -1;
3218}
3219
3220
3221static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)
3222{
3223 if (nl80211_alloc_mgmt_handle(bss))
3224 return -1;
3225 wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
3226 "handle %p (device SME)", bss->nl_mgmt);
3227
3228 if (nl80211_register_frame(bss, bss->nl_mgmt,
3229 (WLAN_FC_TYPE_MGMT << 2) |
3230 (WLAN_FC_STYPE_ACTION << 4),
3231 NULL, 0) < 0)
3232 goto out_err;
3233
3234 return 0;
3235
3236out_err:
3237 eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));
3238 nl_destroy_handles(&bss->nl_mgmt);
3239 return -1;
3240}
3241
3242
3243static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
3244{
3245 if (bss->nl_mgmt == NULL)
3246 return;
3247 wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
3248 "(%s)", bss->nl_mgmt, reason);
3249 eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));
3250 nl_destroy_handles(&bss->nl_mgmt);
3251
3252 nl80211_put_wiphy_data_ap(bss);
3253}
3254
3255
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003256static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
3257{
3258 wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
3259}
3260
3261
3262static int
3263wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
3264{
3265 struct i802_bss *bss = &drv->first_bss;
3266 int send_rfkill_event = 0;
3267
3268 drv->ifindex = if_nametoindex(bss->ifname);
3269 drv->first_bss.ifindex = drv->ifindex;
3270
3271#ifndef HOSTAPD
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003272 /*
3273 * Make sure the interface starts up in station mode unless this is a
3274 * dynamically added interface (e.g., P2P) that was already configured
3275 * with proper iftype.
3276 */
3277 if (drv->ifindex != drv->global->if_add_ifindex &&
3278 wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {
3279 wpa_printf(MSG_ERROR, "nl80211: Could not configure driver to "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003280 "use managed mode");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003281 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003282 }
3283
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003284 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003285 if (rfkill_is_blocked(drv->rfkill)) {
3286 wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
3287 "interface '%s' due to rfkill",
3288 bss->ifname);
3289 drv->if_disabled = 1;
3290 send_rfkill_event = 1;
3291 } else {
3292 wpa_printf(MSG_ERROR, "nl80211: Could not set "
3293 "interface '%s' UP", bss->ifname);
3294 return -1;
3295 }
3296 }
3297
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003298 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003299 1, IF_OPER_DORMANT);
3300#endif /* HOSTAPD */
3301
3302 if (wpa_driver_nl80211_capa(drv))
3303 return -1;
3304
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003305 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
3306 bss->addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003307 return -1;
3308
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003309 if (send_rfkill_event) {
3310 eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
3311 drv, drv->ctx);
3312 }
3313
3314 return 0;
3315}
3316
3317
3318static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
3319{
3320 struct nl_msg *msg;
3321
3322 msg = nlmsg_alloc();
3323 if (!msg)
3324 return -ENOMEM;
3325
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003326 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
3328
3329 return send_and_recv_msgs(drv, msg, NULL, NULL);
3330 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003331 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003332 return -ENOBUFS;
3333}
3334
3335
3336/**
3337 * wpa_driver_nl80211_deinit - Deinitialize nl80211 driver interface
3338 * @priv: Pointer to private nl80211 data from wpa_driver_nl80211_init()
3339 *
3340 * Shut down driver interface and processing of driver events. Free
3341 * private data buffer if one was allocated in wpa_driver_nl80211_init().
3342 */
3343static void wpa_driver_nl80211_deinit(void *priv)
3344{
3345 struct i802_bss *bss = priv;
3346 struct wpa_driver_nl80211_data *drv = bss->drv;
3347
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003348 if (drv->data_tx_status)
3349 eloop_unregister_read_sock(drv->eapol_tx_sock);
3350 if (drv->eapol_tx_sock >= 0)
3351 close(drv->eapol_tx_sock);
3352
3353 if (bss->nl_preq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003354 wpa_driver_nl80211_probe_req_report(bss, 0);
3355 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003356 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
3357 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003358 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
3359 "interface %s from bridge %s: %s",
3360 bss->ifname, bss->brname, strerror(errno));
3361 }
3362 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003363 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003364 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
3365 "bridge %s: %s",
3366 bss->brname, strerror(errno));
3367 }
3368
3369 nl80211_remove_monitor_interface(drv);
3370
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003371 if (is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003372 wpa_driver_nl80211_del_beacon(drv);
3373
3374#ifdef HOSTAPD
3375 if (drv->last_freq_ht) {
3376 /* Clear HT flags from the driver */
3377 struct hostapd_freq_params freq;
3378 os_memset(&freq, 0, sizeof(freq));
3379 freq.freq = drv->last_freq;
3380 i802_set_freq(priv, &freq);
3381 }
3382
3383 if (drv->eapol_sock >= 0) {
3384 eloop_unregister_read_sock(drv->eapol_sock);
3385 close(drv->eapol_sock);
3386 }
3387
3388 if (drv->if_indices != drv->default_if_indices)
3389 os_free(drv->if_indices);
3390#endif /* HOSTAPD */
3391
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003392 if (drv->disabled_11b_rates)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003393 nl80211_disable_11b_rates(drv, drv->ifindex, 0);
3394
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003395 netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
3396 IF_OPER_UP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003397 rfkill_deinit(drv->rfkill);
3398
3399 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
3400
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003401 (void) linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
3402 wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION);
3403 nl80211_mgmt_unsubscribe(bss, "deinit");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003404
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003405 nl_cb_put(drv->nl_cb);
3406
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003407 nl80211_destroy_bss(&drv->first_bss);
3408
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003409 os_free(drv->filter_ssids);
3410
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003411 os_free(drv->auth_ie);
3412
3413 if (drv->in_interface_list)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003414 dl_list_del(&drv->list);
3415
3416 os_free(drv);
3417}
3418
3419
3420/**
3421 * wpa_driver_nl80211_scan_timeout - Scan timeout to report scan completion
3422 * @eloop_ctx: Driver private data
3423 * @timeout_ctx: ctx argument given to wpa_driver_nl80211_init()
3424 *
3425 * This function can be used as registered timeout when starting a scan to
3426 * generate a scan completed event if the driver does not report this.
3427 */
3428static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
3429{
3430 struct wpa_driver_nl80211_data *drv = eloop_ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003431 if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003432 wpa_driver_nl80211_set_mode(&drv->first_bss,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003433 drv->ap_scan_as_station);
3434 drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003435 }
3436 wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
3437 wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
3438}
3439
3440
3441/**
3442 * wpa_driver_nl80211_scan - Request the driver to initiate scan
3443 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
3444 * @params: Scan parameters
3445 * Returns: 0 on success, -1 on failure
3446 */
3447static int wpa_driver_nl80211_scan(void *priv,
3448 struct wpa_driver_scan_params *params)
3449{
3450 struct i802_bss *bss = priv;
3451 struct wpa_driver_nl80211_data *drv = bss->drv;
3452 int ret = 0, timeout;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003453 struct nl_msg *msg, *ssids, *freqs, *rates;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003454 size_t i;
3455
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003456 drv->scan_for_auth = 0;
3457
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003458 msg = nlmsg_alloc();
3459 ssids = nlmsg_alloc();
3460 freqs = nlmsg_alloc();
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003461 rates = nlmsg_alloc();
3462 if (!msg || !ssids || !freqs || !rates) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463 nlmsg_free(msg);
3464 nlmsg_free(ssids);
3465 nlmsg_free(freqs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003466 nlmsg_free(rates);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003467 return -1;
3468 }
3469
3470 os_free(drv->filter_ssids);
3471 drv->filter_ssids = params->filter_ssids;
3472 params->filter_ssids = NULL;
3473 drv->num_filter_ssids = params->num_filter_ssids;
3474
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003475 nl80211_cmd(drv, msg, 0, NL80211_CMD_TRIGGER_SCAN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003476
3477 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
3478
3479 for (i = 0; i < params->num_ssids; i++) {
3480 wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
3481 params->ssids[i].ssid,
3482 params->ssids[i].ssid_len);
3483 NLA_PUT(ssids, i + 1, params->ssids[i].ssid_len,
3484 params->ssids[i].ssid);
3485 }
3486 if (params->num_ssids)
3487 nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
3488
3489 if (params->extra_ies) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003490 wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
3491 params->extra_ies, params->extra_ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003492 NLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len,
3493 params->extra_ies);
3494 }
3495
3496 if (params->freqs) {
3497 for (i = 0; params->freqs[i]; i++) {
3498 wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
3499 "MHz", params->freqs[i]);
3500 NLA_PUT_U32(freqs, i + 1, params->freqs[i]);
3501 }
3502 nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
3503 }
3504
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003505 if (params->p2p_probe) {
3506 /*
3507 * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
3508 * by masking out everything else apart from the OFDM rates 6,
3509 * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
3510 * rates are left enabled.
3511 */
3512 NLA_PUT(rates, NL80211_BAND_2GHZ, 8,
3513 "\x0c\x12\x18\x24\x30\x48\x60\x6c");
3514 nla_put_nested(msg, NL80211_ATTR_SCAN_SUPP_RATES, rates);
3515
3516 NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
3517 }
3518
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003519 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
3520 msg = NULL;
3521 if (ret) {
3522 wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
3523 "(%s)", ret, strerror(-ret));
3524#ifdef HOSTAPD
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003525 if (is_ap_interface(drv->nlmode)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003526 /*
3527 * mac80211 does not allow scan requests in AP mode, so
3528 * try to do this in station mode.
3529 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003530 if (wpa_driver_nl80211_set_mode(
3531 bss, NL80211_IFTYPE_STATION))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003532 goto nla_put_failure;
3533
3534 if (wpa_driver_nl80211_scan(drv, params)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003535 wpa_driver_nl80211_set_mode(bss, drv->nlmode);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536 goto nla_put_failure;
3537 }
3538
3539 /* Restore AP mode when processing scan results */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003540 drv->ap_scan_as_station = drv->nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003541 ret = 0;
3542 } else
3543 goto nla_put_failure;
3544#else /* HOSTAPD */
3545 goto nla_put_failure;
3546#endif /* HOSTAPD */
3547 }
3548
3549 /* Not all drivers generate "scan completed" wireless event, so try to
3550 * read results after a timeout. */
3551 timeout = 10;
3552 if (drv->scan_complete_events) {
3553 /*
3554 * The driver seems to deliver events to notify when scan is
3555 * complete, so use longer timeout to avoid race conditions
3556 * with scanning and following association request.
3557 */
3558 timeout = 30;
3559 }
3560 wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
3561 "seconds", ret, timeout);
3562 eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
3563 eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
3564 drv, drv->ctx);
3565
3566nla_put_failure:
3567 nlmsg_free(ssids);
3568 nlmsg_free(msg);
3569 nlmsg_free(freqs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003570 nlmsg_free(rates);
3571 return ret;
3572}
3573
3574
3575/**
3576 * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
3577 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
3578 * @params: Scan parameters
3579 * @interval: Interval between scan cycles in milliseconds
3580 * Returns: 0 on success, -1 on failure or if not supported
3581 */
3582static int wpa_driver_nl80211_sched_scan(void *priv,
3583 struct wpa_driver_scan_params *params,
3584 u32 interval)
3585{
3586 struct i802_bss *bss = priv;
3587 struct wpa_driver_nl80211_data *drv = bss->drv;
3588 int ret = 0;
3589 struct nl_msg *msg, *ssids, *freqs, *match_set_ssid, *match_sets;
3590 size_t i;
3591
3592#ifdef ANDROID
3593 if (!drv->capa.sched_scan_supported)
3594 return android_pno_start(bss, params);
3595#endif /* ANDROID */
3596
3597 msg = nlmsg_alloc();
3598 ssids = nlmsg_alloc();
3599 freqs = nlmsg_alloc();
3600 if (!msg || !ssids || !freqs) {
3601 nlmsg_free(msg);
3602 nlmsg_free(ssids);
3603 nlmsg_free(freqs);
3604 return -1;
3605 }
3606
3607 os_free(drv->filter_ssids);
3608 drv->filter_ssids = params->filter_ssids;
3609 params->filter_ssids = NULL;
3610 drv->num_filter_ssids = params->num_filter_ssids;
3611
3612 nl80211_cmd(drv, msg, 0, NL80211_CMD_START_SCHED_SCAN);
3613
3614 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
3615
3616 NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);
3617
3618 if (drv->num_filter_ssids &&
3619 (int) drv->num_filter_ssids <= drv->capa.max_match_sets) {
3620 match_sets = nlmsg_alloc();
3621
3622 for (i = 0; i < drv->num_filter_ssids; i++) {
3623 wpa_hexdump_ascii(MSG_MSGDUMP,
3624 "nl80211: Sched scan filter SSID",
3625 drv->filter_ssids[i].ssid,
3626 drv->filter_ssids[i].ssid_len);
3627
3628 match_set_ssid = nlmsg_alloc();
3629 nla_put(match_set_ssid,
3630 NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
3631 drv->filter_ssids[i].ssid_len,
3632 drv->filter_ssids[i].ssid);
3633
3634 nla_put_nested(match_sets, i + 1, match_set_ssid);
3635
3636 nlmsg_free(match_set_ssid);
3637 }
3638
3639 nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH,
3640 match_sets);
3641 nlmsg_free(match_sets);
3642 }
3643
3644 for (i = 0; i < params->num_ssids; i++) {
3645 wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Sched scan SSID",
3646 params->ssids[i].ssid,
3647 params->ssids[i].ssid_len);
3648 NLA_PUT(ssids, i + 1, params->ssids[i].ssid_len,
3649 params->ssids[i].ssid);
3650 }
3651 if (params->num_ssids)
3652 nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
3653
3654 if (params->extra_ies) {
3655 wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Sched scan extra IEs",
3656 params->extra_ies, params->extra_ies_len);
3657 NLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len,
3658 params->extra_ies);
3659 }
3660
3661 if (params->freqs) {
3662 for (i = 0; params->freqs[i]; i++) {
3663 wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
3664 "MHz", params->freqs[i]);
3665 NLA_PUT_U32(freqs, i + 1, params->freqs[i]);
3666 }
3667 nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
3668 }
3669
3670 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
3671
3672 /* TODO: if we get an error here, we should fall back to normal scan */
3673
3674 msg = NULL;
3675 if (ret) {
3676 wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: "
3677 "ret=%d (%s)", ret, strerror(-ret));
3678 goto nla_put_failure;
3679 }
3680
3681 wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) - "
3682 "scan interval %d msec", ret, interval);
3683
3684nla_put_failure:
3685 nlmsg_free(ssids);
3686 nlmsg_free(msg);
3687 nlmsg_free(freqs);
3688 return ret;
3689}
3690
3691
3692/**
3693 * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan
3694 * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
3695 * Returns: 0 on success, -1 on failure or if not supported
3696 */
3697static int wpa_driver_nl80211_stop_sched_scan(void *priv)
3698{
3699 struct i802_bss *bss = priv;
3700 struct wpa_driver_nl80211_data *drv = bss->drv;
3701 int ret = 0;
3702 struct nl_msg *msg;
3703
3704#ifdef ANDROID
3705 if (!drv->capa.sched_scan_supported)
3706 return android_pno_stop(bss);
3707#endif /* ANDROID */
3708
3709 msg = nlmsg_alloc();
3710 if (!msg)
3711 return -1;
3712
3713 nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_SCHED_SCAN);
3714
3715 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
3716
3717 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
3718 msg = NULL;
3719 if (ret) {
3720 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop failed: "
3721 "ret=%d (%s)", ret, strerror(-ret));
3722 goto nla_put_failure;
3723 }
3724
3725 wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop sent (ret=%d)", ret);
3726
3727nla_put_failure:
3728 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003729 return ret;
3730}
3731
3732
3733static const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
3734{
3735 const u8 *end, *pos;
3736
3737 if (ies == NULL)
3738 return NULL;
3739
3740 pos = ies;
3741 end = ies + ies_len;
3742
3743 while (pos + 1 < end) {
3744 if (pos + 2 + pos[1] > end)
3745 break;
3746 if (pos[0] == ie)
3747 return pos;
3748 pos += 2 + pos[1];
3749 }
3750
3751 return NULL;
3752}
3753
3754
3755static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
3756 const u8 *ie, size_t ie_len)
3757{
3758 const u8 *ssid;
3759 size_t i;
3760
3761 if (drv->filter_ssids == NULL)
3762 return 0;
3763
3764 ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID);
3765 if (ssid == NULL)
3766 return 1;
3767
3768 for (i = 0; i < drv->num_filter_ssids; i++) {
3769 if (ssid[1] == drv->filter_ssids[i].ssid_len &&
3770 os_memcmp(ssid + 2, drv->filter_ssids[i].ssid, ssid[1]) ==
3771 0)
3772 return 0;
3773 }
3774
3775 return 1;
3776}
3777
3778
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003779static int bss_info_handler(struct nl_msg *msg, void *arg)
3780{
3781 struct nlattr *tb[NL80211_ATTR_MAX + 1];
3782 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
3783 struct nlattr *bss[NL80211_BSS_MAX + 1];
3784 static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
3785 [NL80211_BSS_BSSID] = { .type = NLA_UNSPEC },
3786 [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
3787 [NL80211_BSS_TSF] = { .type = NLA_U64 },
3788 [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
3789 [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
3790 [NL80211_BSS_INFORMATION_ELEMENTS] = { .type = NLA_UNSPEC },
3791 [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
3792 [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
3793 [NL80211_BSS_STATUS] = { .type = NLA_U32 },
3794 [NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
3795 [NL80211_BSS_BEACON_IES] = { .type = NLA_UNSPEC },
3796 };
3797 struct nl80211_bss_info_arg *_arg = arg;
3798 struct wpa_scan_results *res = _arg->res;
3799 struct wpa_scan_res **tmp;
3800 struct wpa_scan_res *r;
3801 const u8 *ie, *beacon_ie;
3802 size_t ie_len, beacon_ie_len;
3803 u8 *pos;
Jouni Malinen87fd2792011-05-16 18:35:42 +03003804 size_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003805
3806 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
3807 genlmsg_attrlen(gnlh, 0), NULL);
3808 if (!tb[NL80211_ATTR_BSS])
3809 return NL_SKIP;
3810 if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS],
3811 bss_policy))
3812 return NL_SKIP;
Jouni Malinen87fd2792011-05-16 18:35:42 +03003813 if (bss[NL80211_BSS_STATUS]) {
3814 enum nl80211_bss_status status;
3815 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
3816 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
3817 bss[NL80211_BSS_FREQUENCY]) {
3818 _arg->assoc_freq =
3819 nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
3820 wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
3821 _arg->assoc_freq);
3822 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003823 if (status == NL80211_BSS_STATUS_ASSOCIATED &&
3824 bss[NL80211_BSS_BSSID]) {
3825 os_memcpy(_arg->assoc_bssid,
3826 nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
3827 wpa_printf(MSG_DEBUG, "nl80211: Associated with "
3828 MACSTR, MAC2STR(_arg->assoc_bssid));
3829 }
Jouni Malinen87fd2792011-05-16 18:35:42 +03003830 }
3831 if (!res)
3832 return NL_SKIP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003833 if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) {
3834 ie = nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
3835 ie_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
3836 } else {
3837 ie = NULL;
3838 ie_len = 0;
3839 }
3840 if (bss[NL80211_BSS_BEACON_IES]) {
3841 beacon_ie = nla_data(bss[NL80211_BSS_BEACON_IES]);
3842 beacon_ie_len = nla_len(bss[NL80211_BSS_BEACON_IES]);
3843 } else {
3844 beacon_ie = NULL;
3845 beacon_ie_len = 0;
3846 }
3847
3848 if (nl80211_scan_filtered(_arg->drv, ie ? ie : beacon_ie,
3849 ie ? ie_len : beacon_ie_len))
3850 return NL_SKIP;
3851
3852 r = os_zalloc(sizeof(*r) + ie_len + beacon_ie_len);
3853 if (r == NULL)
3854 return NL_SKIP;
3855 if (bss[NL80211_BSS_BSSID])
3856 os_memcpy(r->bssid, nla_data(bss[NL80211_BSS_BSSID]),
3857 ETH_ALEN);
3858 if (bss[NL80211_BSS_FREQUENCY])
3859 r->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
3860 if (bss[NL80211_BSS_BEACON_INTERVAL])
3861 r->beacon_int = nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]);
3862 if (bss[NL80211_BSS_CAPABILITY])
3863 r->caps = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
3864 r->flags |= WPA_SCAN_NOISE_INVALID;
3865 if (bss[NL80211_BSS_SIGNAL_MBM]) {
3866 r->level = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
3867 r->level /= 100; /* mBm to dBm */
3868 r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;
3869 } else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
3870 r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003871 r->flags |= WPA_SCAN_QUAL_INVALID;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003872 } else
3873 r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;
3874 if (bss[NL80211_BSS_TSF])
3875 r->tsf = nla_get_u64(bss[NL80211_BSS_TSF]);
3876 if (bss[NL80211_BSS_SEEN_MS_AGO])
3877 r->age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
3878 r->ie_len = ie_len;
3879 pos = (u8 *) (r + 1);
3880 if (ie) {
3881 os_memcpy(pos, ie, ie_len);
3882 pos += ie_len;
3883 }
3884 r->beacon_ie_len = beacon_ie_len;
3885 if (beacon_ie)
3886 os_memcpy(pos, beacon_ie, beacon_ie_len);
3887
3888 if (bss[NL80211_BSS_STATUS]) {
3889 enum nl80211_bss_status status;
3890 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
3891 switch (status) {
3892 case NL80211_BSS_STATUS_AUTHENTICATED:
3893 r->flags |= WPA_SCAN_AUTHENTICATED;
3894 break;
3895 case NL80211_BSS_STATUS_ASSOCIATED:
3896 r->flags |= WPA_SCAN_ASSOCIATED;
3897 break;
3898 default:
3899 break;
3900 }
3901 }
3902
Jouni Malinen87fd2792011-05-16 18:35:42 +03003903 /*
3904 * cfg80211 maintains separate BSS table entries for APs if the same
3905 * BSSID,SSID pair is seen on multiple channels. wpa_supplicant does
3906 * not use frequency as a separate key in the BSS table, so filter out
3907 * duplicated entries. Prefer associated BSS entry in such a case in
3908 * order to get the correct frequency into the BSS table.
3909 */
3910 for (i = 0; i < res->num; i++) {
3911 const u8 *s1, *s2;
3912 if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)
3913 continue;
3914
3915 s1 = nl80211_get_ie((u8 *) (res->res[i] + 1),
3916 res->res[i]->ie_len, WLAN_EID_SSID);
3917 s2 = nl80211_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
3918 if (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||
3919 os_memcmp(s1, s2, 2 + s1[1]) != 0)
3920 continue;
3921
3922 /* Same BSSID,SSID was already included in scan results */
3923 wpa_printf(MSG_DEBUG, "nl80211: Remove duplicated scan result "
3924 "for " MACSTR, MAC2STR(r->bssid));
3925
3926 if ((r->flags & WPA_SCAN_ASSOCIATED) &&
3927 !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) {
3928 os_free(res->res[i]);
3929 res->res[i] = r;
3930 } else
3931 os_free(r);
3932 return NL_SKIP;
3933 }
3934
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003935 tmp = os_realloc(res->res,
3936 (res->num + 1) * sizeof(struct wpa_scan_res *));
3937 if (tmp == NULL) {
3938 os_free(r);
3939 return NL_SKIP;
3940 }
3941 tmp[res->num++] = r;
3942 res->res = tmp;
3943
3944 return NL_SKIP;
3945}
3946
3947
3948static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
3949 const u8 *addr)
3950{
3951 if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
3952 wpa_printf(MSG_DEBUG, "nl80211: Clear possible state "
3953 "mismatch (" MACSTR ")", MAC2STR(addr));
3954 wpa_driver_nl80211_mlme(drv, addr,
3955 NL80211_CMD_DEAUTHENTICATE,
3956 WLAN_REASON_PREV_AUTH_NOT_VALID, 1);
3957 }
3958}
3959
3960
3961static void wpa_driver_nl80211_check_bss_status(
3962 struct wpa_driver_nl80211_data *drv, struct wpa_scan_results *res)
3963{
3964 size_t i;
3965
3966 for (i = 0; i < res->num; i++) {
3967 struct wpa_scan_res *r = res->res[i];
3968 if (r->flags & WPA_SCAN_AUTHENTICATED) {
3969 wpa_printf(MSG_DEBUG, "nl80211: Scan results "
3970 "indicates BSS status with " MACSTR
3971 " as authenticated",
3972 MAC2STR(r->bssid));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003973 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003974 os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&
3975 os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=
3976 0) {
3977 wpa_printf(MSG_DEBUG, "nl80211: Unknown BSSID"
3978 " in local state (auth=" MACSTR
3979 " assoc=" MACSTR ")",
3980 MAC2STR(drv->auth_bssid),
3981 MAC2STR(drv->bssid));
3982 clear_state_mismatch(drv, r->bssid);
3983 }
3984 }
3985
3986 if (r->flags & WPA_SCAN_ASSOCIATED) {
3987 wpa_printf(MSG_DEBUG, "nl80211: Scan results "
3988 "indicate BSS status with " MACSTR
3989 " as associated",
3990 MAC2STR(r->bssid));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003991 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992 !drv->associated) {
3993 wpa_printf(MSG_DEBUG, "nl80211: Local state "
3994 "(not associated) does not match "
3995 "with BSS state");
3996 clear_state_mismatch(drv, r->bssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003997 } else if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003998 os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
3999 0) {
4000 wpa_printf(MSG_DEBUG, "nl80211: Local state "
4001 "(associated with " MACSTR ") does "
4002 "not match with BSS state",
4003 MAC2STR(drv->bssid));
4004 clear_state_mismatch(drv, r->bssid);
4005 clear_state_mismatch(drv, drv->bssid);
4006 }
4007 }
4008 }
4009}
4010
4011
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004012static struct wpa_scan_results *
4013nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
4014{
4015 struct nl_msg *msg;
4016 struct wpa_scan_results *res;
4017 int ret;
4018 struct nl80211_bss_info_arg arg;
4019
4020 res = os_zalloc(sizeof(*res));
4021 if (res == NULL)
4022 return NULL;
4023 msg = nlmsg_alloc();
4024 if (!msg)
4025 goto nla_put_failure;
4026
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004027 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004028 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4029
4030 arg.drv = drv;
4031 arg.res = res;
4032 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
4033 msg = NULL;
4034 if (ret == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004035 wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu "
4036 "BSSes)", (unsigned long) res->num);
4037 nl80211_get_noise_for_scan_results(drv, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004038 return res;
4039 }
4040 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
4041 "(%s)", ret, strerror(-ret));
4042nla_put_failure:
4043 nlmsg_free(msg);
4044 wpa_scan_results_free(res);
4045 return NULL;
4046}
4047
4048
4049/**
4050 * wpa_driver_nl80211_get_scan_results - Fetch the latest scan results
4051 * @priv: Pointer to private wext data from wpa_driver_nl80211_init()
4052 * Returns: Scan results on success, -1 on failure
4053 */
4054static struct wpa_scan_results *
4055wpa_driver_nl80211_get_scan_results(void *priv)
4056{
4057 struct i802_bss *bss = priv;
4058 struct wpa_driver_nl80211_data *drv = bss->drv;
4059 struct wpa_scan_results *res;
4060
4061 res = nl80211_get_scan_results(drv);
4062 if (res)
4063 wpa_driver_nl80211_check_bss_status(drv, res);
4064 return res;
4065}
4066
4067
4068static void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv)
4069{
4070 struct wpa_scan_results *res;
4071 size_t i;
4072
4073 res = nl80211_get_scan_results(drv);
4074 if (res == NULL) {
4075 wpa_printf(MSG_DEBUG, "nl80211: Failed to get scan results");
4076 return;
4077 }
4078
4079 wpa_printf(MSG_DEBUG, "nl80211: Scan result dump");
4080 for (i = 0; i < res->num; i++) {
4081 struct wpa_scan_res *r = res->res[i];
4082 wpa_printf(MSG_DEBUG, "nl80211: %d/%d " MACSTR "%s%s",
4083 (int) i, (int) res->num, MAC2STR(r->bssid),
4084 r->flags & WPA_SCAN_AUTHENTICATED ? " [auth]" : "",
4085 r->flags & WPA_SCAN_ASSOCIATED ? " [assoc]" : "");
4086 }
4087
4088 wpa_scan_results_free(res);
4089}
4090
4091
4092static int wpa_driver_nl80211_set_key(const char *ifname, void *priv,
4093 enum wpa_alg alg, const u8 *addr,
4094 int key_idx, int set_tx,
4095 const u8 *seq, size_t seq_len,
4096 const u8 *key, size_t key_len)
4097{
4098 struct i802_bss *bss = priv;
4099 struct wpa_driver_nl80211_data *drv = bss->drv;
4100 int ifindex = if_nametoindex(ifname);
4101 struct nl_msg *msg;
4102 int ret;
4103
4104 wpa_printf(MSG_DEBUG, "%s: ifindex=%d alg=%d addr=%p key_idx=%d "
4105 "set_tx=%d seq_len=%lu key_len=%lu",
4106 __func__, ifindex, alg, addr, key_idx, set_tx,
4107 (unsigned long) seq_len, (unsigned long) key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004108#ifdef CONFIG_TDLS
4109 if (key_idx == -1)
4110 key_idx = 0;
4111#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004112
4113 msg = nlmsg_alloc();
4114 if (!msg)
4115 return -ENOMEM;
4116
4117 if (alg == WPA_ALG_NONE) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004118 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004119 } else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004120 nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004121 NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);
4122 switch (alg) {
4123 case WPA_ALG_WEP:
4124 if (key_len == 5)
4125 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
4126 WLAN_CIPHER_SUITE_WEP40);
4127 else
4128 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
4129 WLAN_CIPHER_SUITE_WEP104);
4130 break;
4131 case WPA_ALG_TKIP:
4132 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
4133 WLAN_CIPHER_SUITE_TKIP);
4134 break;
4135 case WPA_ALG_CCMP:
4136 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
4137 WLAN_CIPHER_SUITE_CCMP);
4138 break;
4139 case WPA_ALG_IGTK:
4140 NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
4141 WLAN_CIPHER_SUITE_AES_CMAC);
4142 break;
4143 default:
4144 wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
4145 "algorithm %d", __func__, alg);
4146 nlmsg_free(msg);
4147 return -1;
4148 }
4149 }
4150
4151 if (seq && seq_len)
4152 NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq);
4153
4154 if (addr && !is_broadcast_ether_addr(addr)) {
4155 wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
4156 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
4157
4158 if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
4159 wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK");
4160 NLA_PUT_U32(msg, NL80211_ATTR_KEY_TYPE,
4161 NL80211_KEYTYPE_GROUP);
4162 }
4163 } else if (addr && is_broadcast_ether_addr(addr)) {
4164 struct nl_msg *types;
4165 int err;
4166 wpa_printf(MSG_DEBUG, " broadcast key");
4167 types = nlmsg_alloc();
4168 if (!types)
4169 goto nla_put_failure;
4170 NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
4171 err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
4172 types);
4173 nlmsg_free(types);
4174 if (err)
4175 goto nla_put_failure;
4176 }
4177 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
4178 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
4179
4180 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4181 if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
4182 ret = 0;
4183 if (ret)
4184 wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)",
4185 ret, strerror(-ret));
4186
4187 /*
4188 * If we failed or don't need to set the default TX key (below),
4189 * we're done here.
4190 */
4191 if (ret || !set_tx || alg == WPA_ALG_NONE)
4192 return ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004193 if (is_ap_interface(drv->nlmode) && addr &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004194 !is_broadcast_ether_addr(addr))
4195 return ret;
4196
4197 msg = nlmsg_alloc();
4198 if (!msg)
4199 return -ENOMEM;
4200
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004201 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004202 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
4203 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
4204 if (alg == WPA_ALG_IGTK)
4205 NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT_MGMT);
4206 else
4207 NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
4208 if (addr && is_broadcast_ether_addr(addr)) {
4209 struct nl_msg *types;
4210 int err;
4211 types = nlmsg_alloc();
4212 if (!types)
4213 goto nla_put_failure;
4214 NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_MULTICAST);
4215 err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
4216 types);
4217 nlmsg_free(types);
4218 if (err)
4219 goto nla_put_failure;
4220 } else if (addr) {
4221 struct nl_msg *types;
4222 int err;
4223 types = nlmsg_alloc();
4224 if (!types)
4225 goto nla_put_failure;
4226 NLA_PUT_FLAG(types, NL80211_KEY_DEFAULT_TYPE_UNICAST);
4227 err = nla_put_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES,
4228 types);
4229 nlmsg_free(types);
4230 if (err)
4231 goto nla_put_failure;
4232 }
4233
4234 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4235 if (ret == -ENOENT)
4236 ret = 0;
4237 if (ret)
4238 wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
4239 "err=%d %s)", ret, strerror(-ret));
4240 return ret;
4241
4242nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004243 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004244 return -ENOBUFS;
4245}
4246
4247
4248static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg,
4249 int key_idx, int defkey,
4250 const u8 *seq, size_t seq_len,
4251 const u8 *key, size_t key_len)
4252{
4253 struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);
4254 if (!key_attr)
4255 return -1;
4256
4257 if (defkey && alg == WPA_ALG_IGTK)
4258 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT);
4259 else if (defkey)
4260 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
4261
4262 NLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);
4263
4264 switch (alg) {
4265 case WPA_ALG_WEP:
4266 if (key_len == 5)
4267 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
4268 WLAN_CIPHER_SUITE_WEP40);
4269 else
4270 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
4271 WLAN_CIPHER_SUITE_WEP104);
4272 break;
4273 case WPA_ALG_TKIP:
4274 NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_TKIP);
4275 break;
4276 case WPA_ALG_CCMP:
4277 NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP);
4278 break;
4279 case WPA_ALG_IGTK:
4280 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
4281 WLAN_CIPHER_SUITE_AES_CMAC);
4282 break;
4283 default:
4284 wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
4285 "algorithm %d", __func__, alg);
4286 return -1;
4287 }
4288
4289 if (seq && seq_len)
4290 NLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);
4291
4292 NLA_PUT(msg, NL80211_KEY_DATA, key_len, key);
4293
4294 nla_nest_end(msg, key_attr);
4295
4296 return 0;
4297 nla_put_failure:
4298 return -1;
4299}
4300
4301
4302static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
4303 struct nl_msg *msg)
4304{
4305 int i, privacy = 0;
4306 struct nlattr *nl_keys, *nl_key;
4307
4308 for (i = 0; i < 4; i++) {
4309 if (!params->wep_key[i])
4310 continue;
4311 privacy = 1;
4312 break;
4313 }
4314 if (params->wps == WPS_MODE_PRIVACY)
4315 privacy = 1;
4316 if (params->pairwise_suite &&
4317 params->pairwise_suite != WPA_CIPHER_NONE)
4318 privacy = 1;
4319
4320 if (!privacy)
4321 return 0;
4322
4323 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
4324
4325 nl_keys = nla_nest_start(msg, NL80211_ATTR_KEYS);
4326 if (!nl_keys)
4327 goto nla_put_failure;
4328
4329 for (i = 0; i < 4; i++) {
4330 if (!params->wep_key[i])
4331 continue;
4332
4333 nl_key = nla_nest_start(msg, i);
4334 if (!nl_key)
4335 goto nla_put_failure;
4336
4337 NLA_PUT(msg, NL80211_KEY_DATA, params->wep_key_len[i],
4338 params->wep_key[i]);
4339 if (params->wep_key_len[i] == 5)
4340 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
4341 WLAN_CIPHER_SUITE_WEP40);
4342 else
4343 NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
4344 WLAN_CIPHER_SUITE_WEP104);
4345
4346 NLA_PUT_U8(msg, NL80211_KEY_IDX, i);
4347
4348 if (i == params->wep_tx_keyidx)
4349 NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
4350
4351 nla_nest_end(msg, nl_key);
4352 }
4353 nla_nest_end(msg, nl_keys);
4354
4355 return 0;
4356
4357nla_put_failure:
4358 return -ENOBUFS;
4359}
4360
4361
4362static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
4363 const u8 *addr, int cmd, u16 reason_code,
4364 int local_state_change)
4365{
4366 int ret = -1;
4367 struct nl_msg *msg;
4368
4369 msg = nlmsg_alloc();
4370 if (!msg)
4371 return -1;
4372
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004373 nl80211_cmd(drv, msg, 0, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004374
4375 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4376 NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);
4377 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
4378 if (local_state_change)
4379 NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);
4380
4381 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4382 msg = NULL;
4383 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004384 wpa_dbg(drv->ctx, MSG_DEBUG,
4385 "nl80211: MLME command failed: reason=%u ret=%d (%s)",
4386 reason_code, ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004387 goto nla_put_failure;
4388 }
4389 ret = 0;
4390
4391nla_put_failure:
4392 nlmsg_free(msg);
4393 return ret;
4394}
4395
4396
4397static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
4398 const u8 *addr, int reason_code)
4399{
4400 wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
4401 __func__, MAC2STR(addr), reason_code);
4402 drv->associated = 0;
4403 return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISCONNECT,
4404 reason_code, 0);
4405}
4406
4407
4408static int wpa_driver_nl80211_deauthenticate(void *priv, const u8 *addr,
4409 int reason_code)
4410{
4411 struct i802_bss *bss = priv;
4412 struct wpa_driver_nl80211_data *drv = bss->drv;
4413 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
4414 return wpa_driver_nl80211_disconnect(drv, addr, reason_code);
4415 wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
4416 __func__, MAC2STR(addr), reason_code);
4417 drv->associated = 0;
4418 if (drv->nlmode == NL80211_IFTYPE_ADHOC)
4419 return nl80211_leave_ibss(drv);
4420 return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
4421 reason_code, 0);
4422}
4423
4424
4425static int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr,
4426 int reason_code)
4427{
4428 struct i802_bss *bss = priv;
4429 struct wpa_driver_nl80211_data *drv = bss->drv;
4430 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
4431 return wpa_driver_nl80211_disconnect(drv, addr, reason_code);
4432 wpa_printf(MSG_DEBUG, "%s", __func__);
4433 drv->associated = 0;
4434 return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DISASSOCIATE,
4435 reason_code, 0);
4436}
4437
4438
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004439static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
4440 struct wpa_driver_auth_params *params)
4441{
4442 int i;
4443
4444 drv->auth_freq = params->freq;
4445 drv->auth_alg = params->auth_alg;
4446 drv->auth_wep_tx_keyidx = params->wep_tx_keyidx;
4447 drv->auth_local_state_change = params->local_state_change;
4448 drv->auth_p2p = params->p2p;
4449
4450 if (params->bssid)
4451 os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);
4452 else
4453 os_memset(drv->auth_bssid_, 0, ETH_ALEN);
4454
4455 if (params->ssid) {
4456 os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);
4457 drv->auth_ssid_len = params->ssid_len;
4458 } else
4459 drv->auth_ssid_len = 0;
4460
4461
4462 os_free(drv->auth_ie);
4463 drv->auth_ie = NULL;
4464 drv->auth_ie_len = 0;
4465 if (params->ie) {
4466 drv->auth_ie = os_malloc(params->ie_len);
4467 if (drv->auth_ie) {
4468 os_memcpy(drv->auth_ie, params->ie, params->ie_len);
4469 drv->auth_ie_len = params->ie_len;
4470 }
4471 }
4472
4473 for (i = 0; i < 4; i++) {
4474 if (params->wep_key[i] && params->wep_key_len[i] &&
4475 params->wep_key_len[i] <= 16) {
4476 os_memcpy(drv->auth_wep_key[i], params->wep_key[i],
4477 params->wep_key_len[i]);
4478 drv->auth_wep_key_len[i] = params->wep_key_len[i];
4479 } else
4480 drv->auth_wep_key_len[i] = 0;
4481 }
4482}
4483
4484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004485static int wpa_driver_nl80211_authenticate(
4486 void *priv, struct wpa_driver_auth_params *params)
4487{
4488 struct i802_bss *bss = priv;
4489 struct wpa_driver_nl80211_data *drv = bss->drv;
4490 int ret = -1, i;
4491 struct nl_msg *msg;
4492 enum nl80211_auth_type type;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004493 enum nl80211_iftype nlmode;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004494 int count = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004495 int is_retry;
4496
4497 is_retry = drv->retry_auth;
4498 drv->retry_auth = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004499
4500 drv->associated = 0;
4501 os_memset(drv->auth_bssid, 0, ETH_ALEN);
4502 /* FIX: IBSS mode */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004503 nlmode = params->p2p ?
4504 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
4505 if (drv->nlmode != nlmode &&
4506 wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004507 return -1;
4508
4509retry:
4510 msg = nlmsg_alloc();
4511 if (!msg)
4512 return -1;
4513
4514 wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
4515 drv->ifindex);
4516
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004517 nl80211_cmd(drv, msg, 0, NL80211_CMD_AUTHENTICATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004518
4519 for (i = 0; i < 4; i++) {
4520 if (!params->wep_key[i])
4521 continue;
4522 wpa_driver_nl80211_set_key(bss->ifname, priv, WPA_ALG_WEP,
4523 NULL, i,
4524 i == params->wep_tx_keyidx, NULL, 0,
4525 params->wep_key[i],
4526 params->wep_key_len[i]);
4527 if (params->wep_tx_keyidx != i)
4528 continue;
4529 if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
4530 params->wep_key[i], params->wep_key_len[i])) {
4531 nlmsg_free(msg);
4532 return -1;
4533 }
4534 }
4535
4536 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
4537 if (params->bssid) {
4538 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
4539 MAC2STR(params->bssid));
4540 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
4541 }
4542 if (params->freq) {
4543 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
4544 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
4545 }
4546 if (params->ssid) {
4547 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
4548 params->ssid, params->ssid_len);
4549 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
4550 params->ssid);
4551 }
4552 wpa_hexdump(MSG_DEBUG, " * IEs", params->ie, params->ie_len);
4553 if (params->ie)
4554 NLA_PUT(msg, NL80211_ATTR_IE, params->ie_len, params->ie);
4555 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
4556 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
4557 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
4558 type = NL80211_AUTHTYPE_SHARED_KEY;
4559 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
4560 type = NL80211_AUTHTYPE_NETWORK_EAP;
4561 else if (params->auth_alg & WPA_AUTH_ALG_FT)
4562 type = NL80211_AUTHTYPE_FT;
4563 else
4564 goto nla_put_failure;
4565 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
4566 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
4567 if (params->local_state_change) {
4568 wpa_printf(MSG_DEBUG, " * Local state change only");
4569 NLA_PUT_FLAG(msg, NL80211_ATTR_LOCAL_STATE_CHANGE);
4570 }
4571
4572 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
4573 msg = NULL;
4574 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004575 wpa_dbg(drv->ctx, MSG_DEBUG,
4576 "nl80211: MLME command failed (auth): ret=%d (%s)",
4577 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004578 count++;
4579 if (ret == -EALREADY && count == 1 && params->bssid &&
4580 !params->local_state_change) {
4581 /*
4582 * mac80211 does not currently accept new
4583 * authentication if we are already authenticated. As a
4584 * workaround, force deauthentication and try again.
4585 */
4586 wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
4587 "after forced deauthentication");
4588 wpa_driver_nl80211_deauthenticate(
4589 bss, params->bssid,
4590 WLAN_REASON_PREV_AUTH_NOT_VALID);
4591 nlmsg_free(msg);
4592 goto retry;
4593 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004594
4595 if (ret == -ENOENT && params->freq && !is_retry) {
4596 /*
4597 * cfg80211 has likely expired the BSS entry even
4598 * though it was previously available in our internal
4599 * BSS table. To recover quickly, start a single
4600 * channel scan on the specified channel.
4601 */
4602 struct wpa_driver_scan_params scan;
4603 int freqs[2];
4604
4605 os_memset(&scan, 0, sizeof(scan));
4606 scan.num_ssids = 1;
4607 if (params->ssid) {
4608 scan.ssids[0].ssid = params->ssid;
4609 scan.ssids[0].ssid_len = params->ssid_len;
4610 }
4611 freqs[0] = params->freq;
4612 freqs[1] = 0;
4613 scan.freqs = freqs;
4614 wpa_printf(MSG_DEBUG, "nl80211: Trigger single "
4615 "channel scan to refresh cfg80211 BSS "
4616 "entry");
4617 ret = wpa_driver_nl80211_scan(bss, &scan);
4618 if (ret == 0) {
4619 nl80211_copy_auth_params(drv, params);
4620 drv->scan_for_auth = 1;
4621 }
4622 } else if (is_retry) {
4623 /*
4624 * Need to indicate this with an event since the return
4625 * value from the retry is not delivered to core code.
4626 */
4627 union wpa_event_data event;
4628 wpa_printf(MSG_DEBUG, "nl80211: Authentication retry "
4629 "failed");
4630 os_memset(&event, 0, sizeof(event));
4631 os_memcpy(event.timeout_event.addr, drv->auth_bssid_,
4632 ETH_ALEN);
4633 wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,
4634 &event);
4635 }
4636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004637 goto nla_put_failure;
4638 }
4639 ret = 0;
4640 wpa_printf(MSG_DEBUG, "nl80211: Authentication request send "
4641 "successfully");
4642
4643nla_put_failure:
4644 nlmsg_free(msg);
4645 return ret;
4646}
4647
4648
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004649static int wpa_driver_nl80211_authenticate_retry(
4650 struct wpa_driver_nl80211_data *drv)
4651{
4652 struct wpa_driver_auth_params params;
4653 struct i802_bss *bss = &drv->first_bss;
4654 int i;
4655
4656 wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
4657
4658 os_memset(&params, 0, sizeof(params));
4659 params.freq = drv->auth_freq;
4660 params.auth_alg = drv->auth_alg;
4661 params.wep_tx_keyidx = drv->auth_wep_tx_keyidx;
4662 params.local_state_change = drv->auth_local_state_change;
4663 params.p2p = drv->auth_p2p;
4664
4665 if (!is_zero_ether_addr(drv->auth_bssid_))
4666 params.bssid = drv->auth_bssid_;
4667
4668 if (drv->auth_ssid_len) {
4669 params.ssid = drv->auth_ssid;
4670 params.ssid_len = drv->auth_ssid_len;
4671 }
4672
4673 params.ie = drv->auth_ie;
4674 params.ie_len = drv->auth_ie_len;
4675
4676 for (i = 0; i < 4; i++) {
4677 if (drv->auth_wep_key_len[i]) {
4678 params.wep_key[i] = drv->auth_wep_key[i];
4679 params.wep_key_len[i] = drv->auth_wep_key_len[i];
4680 }
4681 }
4682
4683 drv->retry_auth = 1;
4684 return wpa_driver_nl80211_authenticate(bss, &params);
4685}
4686
4687
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004688struct phy_info_arg {
4689 u16 *num_modes;
4690 struct hostapd_hw_modes *modes;
4691};
4692
4693static int phy_info_handler(struct nl_msg *msg, void *arg)
4694{
4695 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
4696 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4697 struct phy_info_arg *phy_info = arg;
4698
4699 struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
4700
4701 struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
4702 static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
4703 [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
4704 [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
4705 [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
4706 [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
4707 [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
4708 [NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
4709 };
4710
4711 struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
4712 static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {
4713 [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },
4714 [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG },
4715 };
4716
4717 struct nlattr *nl_band;
4718 struct nlattr *nl_freq;
4719 struct nlattr *nl_rate;
4720 int rem_band, rem_freq, rem_rate;
4721 struct hostapd_hw_modes *mode;
4722 int idx, mode_is_set;
4723
4724 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
4725 genlmsg_attrlen(gnlh, 0), NULL);
4726
4727 if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
4728 return NL_SKIP;
4729
4730 nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {
4731 mode = os_realloc(phy_info->modes, (*phy_info->num_modes + 1) * sizeof(*mode));
4732 if (!mode)
4733 return NL_SKIP;
4734 phy_info->modes = mode;
4735
4736 mode_is_set = 0;
4737
4738 mode = &phy_info->modes[*(phy_info->num_modes)];
4739 memset(mode, 0, sizeof(*mode));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004740 mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004741 *(phy_info->num_modes) += 1;
4742
4743 nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
4744 nla_len(nl_band), NULL);
4745
4746 if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) {
4747 mode->ht_capab = nla_get_u16(
4748 tb_band[NL80211_BAND_ATTR_HT_CAPA]);
4749 }
4750
4751 if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) {
4752 mode->a_mpdu_params |= nla_get_u8(
4753 tb_band[NL80211_BAND_ATTR_HT_AMPDU_FACTOR]) &
4754 0x03;
4755 }
4756
4757 if (tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) {
4758 mode->a_mpdu_params |= nla_get_u8(
4759 tb_band[NL80211_BAND_ATTR_HT_AMPDU_DENSITY]) <<
4760 2;
4761 }
4762
4763 if (tb_band[NL80211_BAND_ATTR_HT_MCS_SET] &&
4764 nla_len(tb_band[NL80211_BAND_ATTR_HT_MCS_SET])) {
4765 u8 *mcs;
4766 mcs = nla_data(tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);
4767 os_memcpy(mode->mcs_set, mcs, 16);
4768 }
4769
4770 nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
4771 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
4772 nla_len(nl_freq), freq_policy);
4773 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
4774 continue;
4775 mode->num_channels++;
4776 }
4777
4778 mode->channels = os_zalloc(mode->num_channels * sizeof(struct hostapd_channel_data));
4779 if (!mode->channels)
4780 return NL_SKIP;
4781
4782 idx = 0;
4783
4784 nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
4785 nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
4786 nla_len(nl_freq), freq_policy);
4787 if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
4788 continue;
4789
4790 mode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
4791 mode->channels[idx].flag = 0;
4792
4793 if (!mode_is_set) {
4794 /* crude heuristic */
4795 if (mode->channels[idx].freq < 4000)
4796 mode->mode = HOSTAPD_MODE_IEEE80211B;
4797 else
4798 mode->mode = HOSTAPD_MODE_IEEE80211A;
4799 mode_is_set = 1;
4800 }
4801
4802 /* crude heuristic */
4803 if (mode->channels[idx].freq < 4000)
4804 if (mode->channels[idx].freq == 2484)
4805 mode->channels[idx].chan = 14;
4806 else
4807 mode->channels[idx].chan = (mode->channels[idx].freq - 2407) / 5;
4808 else
4809 mode->channels[idx].chan = mode->channels[idx].freq/5 - 1000;
4810
4811 if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
4812 mode->channels[idx].flag |=
4813 HOSTAPD_CHAN_DISABLED;
4814 if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])
4815 mode->channels[idx].flag |=
4816 HOSTAPD_CHAN_PASSIVE_SCAN;
4817 if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])
4818 mode->channels[idx].flag |=
4819 HOSTAPD_CHAN_NO_IBSS;
4820 if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
4821 mode->channels[idx].flag |=
4822 HOSTAPD_CHAN_RADAR;
4823
4824 if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] &&
4825 !tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
4826 mode->channels[idx].max_tx_power =
4827 nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) / 100;
4828
4829 idx++;
4830 }
4831
4832 nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {
4833 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),
4834 nla_len(nl_rate), rate_policy);
4835 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
4836 continue;
4837 mode->num_rates++;
4838 }
4839
4840 mode->rates = os_zalloc(mode->num_rates * sizeof(int));
4841 if (!mode->rates)
4842 return NL_SKIP;
4843
4844 idx = 0;
4845
4846 nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {
4847 nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),
4848 nla_len(nl_rate), rate_policy);
4849 if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
4850 continue;
4851 mode->rates[idx] = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]);
4852
4853 /* crude heuristic */
4854 if (mode->mode == HOSTAPD_MODE_IEEE80211B &&
4855 mode->rates[idx] > 200)
4856 mode->mode = HOSTAPD_MODE_IEEE80211G;
4857
4858 idx++;
4859 }
4860 }
4861
4862 return NL_SKIP;
4863}
4864
4865static struct hostapd_hw_modes *
4866wpa_driver_nl80211_add_11b(struct hostapd_hw_modes *modes, u16 *num_modes)
4867{
4868 u16 m;
4869 struct hostapd_hw_modes *mode11g = NULL, *nmodes, *mode;
4870 int i, mode11g_idx = -1;
4871
4872 /* If only 802.11g mode is included, use it to construct matching
4873 * 802.11b mode data. */
4874
4875 for (m = 0; m < *num_modes; m++) {
4876 if (modes[m].mode == HOSTAPD_MODE_IEEE80211B)
4877 return modes; /* 802.11b already included */
4878 if (modes[m].mode == HOSTAPD_MODE_IEEE80211G)
4879 mode11g_idx = m;
4880 }
4881
4882 if (mode11g_idx < 0)
4883 return modes; /* 2.4 GHz band not supported at all */
4884
4885 nmodes = os_realloc(modes, (*num_modes + 1) * sizeof(*nmodes));
4886 if (nmodes == NULL)
4887 return modes; /* Could not add 802.11b mode */
4888
4889 mode = &nmodes[*num_modes];
4890 os_memset(mode, 0, sizeof(*mode));
4891 (*num_modes)++;
4892 modes = nmodes;
4893
4894 mode->mode = HOSTAPD_MODE_IEEE80211B;
4895
4896 mode11g = &modes[mode11g_idx];
4897 mode->num_channels = mode11g->num_channels;
4898 mode->channels = os_malloc(mode11g->num_channels *
4899 sizeof(struct hostapd_channel_data));
4900 if (mode->channels == NULL) {
4901 (*num_modes)--;
4902 return modes; /* Could not add 802.11b mode */
4903 }
4904 os_memcpy(mode->channels, mode11g->channels,
4905 mode11g->num_channels * sizeof(struct hostapd_channel_data));
4906
4907 mode->num_rates = 0;
4908 mode->rates = os_malloc(4 * sizeof(int));
4909 if (mode->rates == NULL) {
4910 os_free(mode->channels);
4911 (*num_modes)--;
4912 return modes; /* Could not add 802.11b mode */
4913 }
4914
4915 for (i = 0; i < mode11g->num_rates; i++) {
4916 if (mode11g->rates[i] != 10 && mode11g->rates[i] != 20 &&
4917 mode11g->rates[i] != 55 && mode11g->rates[i] != 110)
4918 continue;
4919 mode->rates[mode->num_rates] = mode11g->rates[i];
4920 mode->num_rates++;
4921 if (mode->num_rates == 4)
4922 break;
4923 }
4924
4925 if (mode->num_rates == 0) {
4926 os_free(mode->channels);
4927 os_free(mode->rates);
4928 (*num_modes)--;
4929 return modes; /* No 802.11b rates */
4930 }
4931
4932 wpa_printf(MSG_DEBUG, "nl80211: Added 802.11b mode based on 802.11g "
4933 "information");
4934
4935 return modes;
4936}
4937
4938
4939static void nl80211_set_ht40_mode(struct hostapd_hw_modes *mode, int start,
4940 int end)
4941{
4942 int c;
4943
4944 for (c = 0; c < mode->num_channels; c++) {
4945 struct hostapd_channel_data *chan = &mode->channels[c];
4946 if (chan->freq - 10 >= start && chan->freq + 10 <= end)
4947 chan->flag |= HOSTAPD_CHAN_HT40;
4948 }
4949}
4950
4951
4952static void nl80211_set_ht40_mode_sec(struct hostapd_hw_modes *mode, int start,
4953 int end)
4954{
4955 int c;
4956
4957 for (c = 0; c < mode->num_channels; c++) {
4958 struct hostapd_channel_data *chan = &mode->channels[c];
4959 if (!(chan->flag & HOSTAPD_CHAN_HT40))
4960 continue;
4961 if (chan->freq - 30 >= start && chan->freq - 10 <= end)
4962 chan->flag |= HOSTAPD_CHAN_HT40MINUS;
4963 if (chan->freq + 10 >= start && chan->freq + 30 <= end)
4964 chan->flag |= HOSTAPD_CHAN_HT40PLUS;
4965 }
4966}
4967
4968
4969static void nl80211_reg_rule_ht40(struct nlattr *tb[],
4970 struct phy_info_arg *results)
4971{
4972 u32 start, end, max_bw;
4973 u16 m;
4974
4975 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
4976 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
4977 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
4978 return;
4979
4980 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
4981 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
4982 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
4983
4984 wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz",
4985 start, end, max_bw);
4986 if (max_bw < 40)
4987 return;
4988
4989 for (m = 0; m < *results->num_modes; m++) {
4990 if (!(results->modes[m].ht_capab &
4991 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
4992 continue;
4993 nl80211_set_ht40_mode(&results->modes[m], start, end);
4994 }
4995}
4996
4997
4998static void nl80211_reg_rule_sec(struct nlattr *tb[],
4999 struct phy_info_arg *results)
5000{
5001 u32 start, end, max_bw;
5002 u16 m;
5003
5004 if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
5005 tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
5006 tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
5007 return;
5008
5009 start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
5010 end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
5011 max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
5012
5013 if (max_bw < 20)
5014 return;
5015
5016 for (m = 0; m < *results->num_modes; m++) {
5017 if (!(results->modes[m].ht_capab &
5018 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
5019 continue;
5020 nl80211_set_ht40_mode_sec(&results->modes[m], start, end);
5021 }
5022}
5023
5024
5025static int nl80211_get_reg(struct nl_msg *msg, void *arg)
5026{
5027 struct phy_info_arg *results = arg;
5028 struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
5029 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5030 struct nlattr *nl_rule;
5031 struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
5032 int rem_rule;
5033 static struct nla_policy reg_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
5034 [NL80211_ATTR_REG_RULE_FLAGS] = { .type = NLA_U32 },
5035 [NL80211_ATTR_FREQ_RANGE_START] = { .type = NLA_U32 },
5036 [NL80211_ATTR_FREQ_RANGE_END] = { .type = NLA_U32 },
5037 [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 },
5038 [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 },
5039 [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
5040 };
5041
5042 nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
5043 genlmsg_attrlen(gnlh, 0), NULL);
5044 if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
5045 !tb_msg[NL80211_ATTR_REG_RULES]) {
5046 wpa_printf(MSG_DEBUG, "nl80211: No regulatory information "
5047 "available");
5048 return NL_SKIP;
5049 }
5050
5051 wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s",
5052 (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));
5053
5054 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
5055 {
5056 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
5057 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
5058 nl80211_reg_rule_ht40(tb_rule, results);
5059 }
5060
5061 nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
5062 {
5063 nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
5064 nla_data(nl_rule), nla_len(nl_rule), reg_policy);
5065 nl80211_reg_rule_sec(tb_rule, results);
5066 }
5067
5068 return NL_SKIP;
5069}
5070
5071
5072static int nl80211_set_ht40_flags(struct wpa_driver_nl80211_data *drv,
5073 struct phy_info_arg *results)
5074{
5075 struct nl_msg *msg;
5076
5077 msg = nlmsg_alloc();
5078 if (!msg)
5079 return -ENOMEM;
5080
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005081 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005082 return send_and_recv_msgs(drv, msg, nl80211_get_reg, results);
5083}
5084
5085
5086static struct hostapd_hw_modes *
5087wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
5088{
5089 struct i802_bss *bss = priv;
5090 struct wpa_driver_nl80211_data *drv = bss->drv;
5091 struct nl_msg *msg;
5092 struct phy_info_arg result = {
5093 .num_modes = num_modes,
5094 .modes = NULL,
5095 };
5096
5097 *num_modes = 0;
5098 *flags = 0;
5099
5100 msg = nlmsg_alloc();
5101 if (!msg)
5102 return NULL;
5103
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005104 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005105
5106 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5107
5108 if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
5109 nl80211_set_ht40_flags(drv, &result);
5110 return wpa_driver_nl80211_add_11b(result.modes, num_modes);
5111 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005112 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005113 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005114 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005115 return NULL;
5116}
5117
5118
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005119static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv,
5120 const void *data, size_t len,
5121 int encrypt, int noack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005122{
5123 __u8 rtap_hdr[] = {
5124 0x00, 0x00, /* radiotap version */
5125 0x0e, 0x00, /* radiotap length */
5126 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
5127 IEEE80211_RADIOTAP_F_FRAG, /* F_FRAG (fragment if required) */
5128 0x00, /* padding */
5129 0x00, 0x00, /* RX and TX flags to indicate that */
5130 0x00, 0x00, /* this is the injected frame directly */
5131 };
5132 struct iovec iov[2] = {
5133 {
5134 .iov_base = &rtap_hdr,
5135 .iov_len = sizeof(rtap_hdr),
5136 },
5137 {
5138 .iov_base = (void *) data,
5139 .iov_len = len,
5140 }
5141 };
5142 struct msghdr msg = {
5143 .msg_name = NULL,
5144 .msg_namelen = 0,
5145 .msg_iov = iov,
5146 .msg_iovlen = 2,
5147 .msg_control = NULL,
5148 .msg_controllen = 0,
5149 .msg_flags = 0,
5150 };
5151 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005152 u16 txflags = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005153
5154 if (encrypt)
5155 rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
5156
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07005157 if (drv->monitor_sock < 0) {
5158 wpa_printf(MSG_DEBUG, "nl80211: No monitor socket available "
5159 "for %s", __func__);
5160 return -1;
5161 }
5162
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005163 if (noack)
5164 txflags |= IEEE80211_RADIOTAP_F_TX_NOACK;
5165 *(le16 *) &rtap_hdr[12] = host_to_le16(txflags);
5166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005167 res = sendmsg(drv->monitor_sock, &msg, 0);
5168 if (res < 0) {
5169 wpa_printf(MSG_INFO, "nl80211: sendmsg: %s", strerror(errno));
5170 return -1;
5171 }
5172 return 0;
5173}
5174
5175
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005176static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
5177 const void *data, size_t len,
5178 int encrypt, int noack)
5179{
5180 struct wpa_driver_nl80211_data *drv = bss->drv;
5181 u64 cookie;
5182
5183 if (drv->use_monitor)
5184 return wpa_driver_nl80211_send_mntr(drv, data, len,
5185 encrypt, noack);
5186
5187 return nl80211_send_frame_cmd(bss, bss->freq, 0, data, len,
5188 &cookie, 0, noack, 0);
5189}
5190
5191
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005192static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005193 size_t data_len, int noack)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005194{
5195 struct i802_bss *bss = priv;
5196 struct wpa_driver_nl80211_data *drv = bss->drv;
5197 struct ieee80211_mgmt *mgmt;
5198 int encrypt = 1;
5199 u16 fc;
5200
5201 mgmt = (struct ieee80211_mgmt *) data;
5202 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005203
5204 if (is_sta_interface(drv->nlmode) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005205 WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
5206 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
5207 /*
5208 * The use of last_mgmt_freq is a bit of a hack,
5209 * but it works due to the single-threaded nature
5210 * of wpa_supplicant.
5211 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005212 return nl80211_send_frame_cmd(bss, drv->last_mgmt_freq, 0,
5213 data, data_len, NULL, 1, noack,
5214 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005215 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005216#ifdef ANDROID_P2P
5217 if (is_ap_interface(drv->nlmode)) {
5218 return nl80211_send_frame_cmd(bss, bss->freq, 0,
5219 data, data_len, &drv->send_action_cookie, 0, noack, 1);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07005220 }
5221#else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005222
5223 if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
5224 return nl80211_send_frame_cmd(bss, bss->freq, 0,
5225 data, data_len, NULL,
5226 0, noack, 0);
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07005227 }
5228#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005229 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
5230 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) {
5231 /*
5232 * Only one of the authentication frame types is encrypted.
5233 * In order for static WEP encryption to work properly (i.e.,
5234 * to not encrypt the frame), we need to tell mac80211 about
5235 * the frames that must not be encrypted.
5236 */
5237 u16 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
5238 u16 auth_trans = le_to_host16(mgmt->u.auth.auth_transaction);
5239 if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)
5240 encrypt = 0;
5241 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005242
5243 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
5244 noack);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005245}
5246
5247
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005248static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
5249 int slot, int ht_opmode, int ap_isolate,
5250 int *basic_rates)
5251{
5252 struct wpa_driver_nl80211_data *drv = bss->drv;
5253 struct nl_msg *msg;
5254
5255 msg = nlmsg_alloc();
5256 if (!msg)
5257 return -ENOMEM;
5258
5259 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);
5260
5261 if (cts >= 0)
5262 NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);
5263 if (preamble >= 0)
5264 NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);
5265 if (slot >= 0)
5266 NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
5267 if (ht_opmode >= 0)
5268 NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);
5269 if (ap_isolate >= 0)
5270 NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate);
5271
5272 if (basic_rates) {
5273 u8 rates[NL80211_MAX_SUPP_RATES];
5274 u8 rates_len = 0;
5275 int i;
5276
5277 for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0;
5278 i++)
5279 rates[rates_len++] = basic_rates[i] / 5;
5280
5281 NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
5282 }
5283
5284 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
5285
5286 return send_and_recv_msgs(drv, msg, NULL, NULL);
5287 nla_put_failure:
5288 nlmsg_free(msg);
5289 return -ENOBUFS;
5290}
5291
5292
5293static int wpa_driver_nl80211_set_ap(void *priv,
5294 struct wpa_driver_ap_params *params)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005295{
5296 struct i802_bss *bss = priv;
5297 struct wpa_driver_nl80211_data *drv = bss->drv;
5298 struct nl_msg *msg;
5299 u8 cmd = NL80211_CMD_NEW_BEACON;
5300 int ret;
5301 int beacon_set;
5302 int ifindex = if_nametoindex(bss->ifname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005303 int num_suites;
5304 u32 suites[10];
5305 u32 ver;
5306
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07005307 beacon_set = bss->beacon_set;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005308
5309 msg = nlmsg_alloc();
5310 if (!msg)
5311 return -ENOMEM;
5312
5313 wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
5314 beacon_set);
5315 if (beacon_set)
5316 cmd = NL80211_CMD_SET_BEACON;
5317
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005318 nl80211_cmd(drv, msg, 0, cmd);
5319 NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);
5320 NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005321 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005322 NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);
5323 NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);
5324 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
5325 params->ssid);
5326 if (params->proberesp && params->proberesp_len)
5327 NLA_PUT(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
5328 params->proberesp);
5329 switch (params->hide_ssid) {
5330 case NO_SSID_HIDING:
5331 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
5332 NL80211_HIDDEN_SSID_NOT_IN_USE);
5333 break;
5334 case HIDDEN_SSID_ZERO_LEN:
5335 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
5336 NL80211_HIDDEN_SSID_ZERO_LEN);
5337 break;
5338 case HIDDEN_SSID_ZERO_CONTENTS:
5339 NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
5340 NL80211_HIDDEN_SSID_ZERO_CONTENTS);
5341 break;
5342 }
5343 if (params->privacy)
5344 NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
5345 if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
5346 (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
5347 /* Leave out the attribute */
5348 } else if (params->auth_algs & WPA_AUTH_ALG_SHARED)
5349 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
5350 NL80211_AUTHTYPE_SHARED_KEY);
5351 else
5352 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
5353 NL80211_AUTHTYPE_OPEN_SYSTEM);
5354
5355 ver = 0;
5356 if (params->wpa_version & WPA_PROTO_WPA)
5357 ver |= NL80211_WPA_VERSION_1;
5358 if (params->wpa_version & WPA_PROTO_RSN)
5359 ver |= NL80211_WPA_VERSION_2;
5360 if (ver)
5361 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
5362
5363 num_suites = 0;
5364 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
5365 suites[num_suites++] = WLAN_AKM_SUITE_8021X;
5366 if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
5367 suites[num_suites++] = WLAN_AKM_SUITE_PSK;
5368 if (num_suites) {
5369 NLA_PUT(msg, NL80211_ATTR_AKM_SUITES,
5370 num_suites * sizeof(u32), suites);
5371 }
5372
5373 if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X &&
5374 params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40))
5375 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
5376
5377 num_suites = 0;
5378 if (params->pairwise_ciphers & WPA_CIPHER_CCMP)
5379 suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
5380 if (params->pairwise_ciphers & WPA_CIPHER_TKIP)
5381 suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
5382 if (params->pairwise_ciphers & WPA_CIPHER_WEP104)
5383 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
5384 if (params->pairwise_ciphers & WPA_CIPHER_WEP40)
5385 suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
5386 if (num_suites) {
5387 NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
5388 num_suites * sizeof(u32), suites);
5389 }
5390
5391 switch (params->group_cipher) {
5392 case WPA_CIPHER_CCMP:
5393 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
5394 WLAN_CIPHER_SUITE_CCMP);
5395 break;
5396 case WPA_CIPHER_TKIP:
5397 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
5398 WLAN_CIPHER_SUITE_TKIP);
5399 break;
5400 case WPA_CIPHER_WEP104:
5401 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
5402 WLAN_CIPHER_SUITE_WEP104);
5403 break;
5404 case WPA_CIPHER_WEP40:
5405 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
5406 WLAN_CIPHER_SUITE_WEP40);
5407 break;
5408 }
5409
5410 if (params->beacon_ies) {
5411 NLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
5412 wpabuf_head(params->beacon_ies));
5413 }
5414 if (params->proberesp_ies) {
5415 NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
5416 wpabuf_len(params->proberesp_ies),
5417 wpabuf_head(params->proberesp_ies));
5418 }
5419 if (params->assocresp_ies) {
5420 NLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,
5421 wpabuf_len(params->assocresp_ies),
5422 wpabuf_head(params->assocresp_ies));
5423 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005424
5425 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5426 if (ret) {
5427 wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
5428 ret, strerror(-ret));
5429 } else {
5430 bss->beacon_set = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005431 nl80211_set_bss(bss, params->cts_protect, params->preamble,
5432 params->short_slot_time, params->ht_opmode,
5433 params->isolate, params->basic_rates);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005434 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005435#if defined(ANDROID_P2P) && defined(HOSTAPD)
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07005436 wpa_driver_nl80211_probe_req_report(priv, 1);
5437#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005438 return ret;
5439 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005440 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005441 return -ENOBUFS;
5442}
5443
5444
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005445static int wpa_driver_nl80211_set_freq(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005446 int freq, int ht_enabled,
5447 int sec_channel_offset)
5448{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005449 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005450 struct nl_msg *msg;
5451 int ret;
5452
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005453 wpa_printf(MSG_DEBUG, "nl80211: Set freq %d (ht_enabled=%d "
5454 "sec_channel_offset=%d)",
5455 freq, ht_enabled, sec_channel_offset);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005456 msg = nlmsg_alloc();
5457 if (!msg)
5458 return -1;
5459
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005460 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005461
5462 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5463 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
5464 if (ht_enabled) {
5465 switch (sec_channel_offset) {
5466 case -1:
5467 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
5468 NL80211_CHAN_HT40MINUS);
5469 break;
5470 case 1:
5471 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
5472 NL80211_CHAN_HT40PLUS);
5473 break;
5474 default:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005475#ifndef ANDROID_P2P
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07005476/* Should be change to HT20 as a default value because P2P firmware does not support 11n for BCM4329 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005477 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
5478 NL80211_CHAN_HT20);
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07005479#else
5480 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
5481 NL80211_CHAN_NO_HT);
5482#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005483 break;
5484 }
5485 }
5486
5487 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005488 msg = NULL;
5489 if (ret == 0) {
5490 bss->freq = freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005491 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005492 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005493 wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
5494 "%d (%s)", freq, ret, strerror(-ret));
5495nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005496 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005497 return -1;
5498}
5499
5500
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005501static u32 sta_flags_nl80211(int flags)
5502{
5503 u32 f = 0;
5504
5505 if (flags & WPA_STA_AUTHORIZED)
5506 f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
5507 if (flags & WPA_STA_WMM)
5508 f |= BIT(NL80211_STA_FLAG_WME);
5509 if (flags & WPA_STA_SHORT_PREAMBLE)
5510 f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
5511 if (flags & WPA_STA_MFP)
5512 f |= BIT(NL80211_STA_FLAG_MFP);
5513 if (flags & WPA_STA_TDLS_PEER)
5514 f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
5515
5516 return f;
5517}
5518
5519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005520static int wpa_driver_nl80211_sta_add(void *priv,
5521 struct hostapd_sta_add_params *params)
5522{
5523 struct i802_bss *bss = priv;
5524 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005525 struct nl_msg *msg, *wme = NULL;
5526 struct nl80211_sta_flag_update upd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005527 int ret = -ENOBUFS;
5528
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005529 if ((params->flags & WPA_STA_TDLS_PEER) &&
5530 !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
5531 return -EOPNOTSUPP;
5532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005533 msg = nlmsg_alloc();
5534 if (!msg)
5535 return -ENOMEM;
5536
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005537 nl80211_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION :
5538 NL80211_CMD_NEW_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005539
5540 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
5541 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005542 NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,
5543 params->supp_rates);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005544 if (!params->set) {
5545 NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
5546 NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
5547 params->listen_interval);
5548 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005549 if (params->ht_capabilities) {
5550 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,
5551 sizeof(*params->ht_capabilities),
5552 params->ht_capabilities);
5553 }
5554
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005555 os_memset(&upd, 0, sizeof(upd));
5556 upd.mask = sta_flags_nl80211(params->flags);
5557 upd.set = upd.mask;
5558 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
5559
5560 if (params->flags & WPA_STA_WMM) {
5561 wme = nlmsg_alloc();
5562 if (!wme)
5563 goto nla_put_failure;
5564
5565 NLA_PUT_U8(wme, NL80211_STA_WME_UAPSD_QUEUES,
5566 params->qosinfo & WMM_QOSINFO_STA_AC_MASK);
5567 NLA_PUT_U8(wme, NL80211_STA_WME_MAX_SP,
5568 (params->qosinfo > WMM_QOSINFO_STA_SP_SHIFT) &
5569 WMM_QOSINFO_STA_SP_MASK);
5570 nla_put_nested(msg, NL80211_ATTR_STA_WME, wme);
5571 }
5572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005573 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005574 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005575 if (ret)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005576 wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
5577 "result: %d (%s)", params->set ? "SET" : "NEW", ret,
5578 strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005579 if (ret == -EEXIST)
5580 ret = 0;
5581 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005582 nlmsg_free(wme);
5583 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005584 return ret;
5585}
5586
5587
5588static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr)
5589{
5590 struct i802_bss *bss = priv;
5591 struct wpa_driver_nl80211_data *drv = bss->drv;
5592 struct nl_msg *msg;
5593 int ret;
5594
5595 msg = nlmsg_alloc();
5596 if (!msg)
5597 return -ENOMEM;
5598
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005599 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005600
5601 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
5602 if_nametoindex(bss->ifname));
5603 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
5604
5605 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
5606 if (ret == -ENOENT)
5607 return 0;
5608 return ret;
5609 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005610 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005611 return -ENOBUFS;
5612}
5613
5614
5615static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
5616 int ifidx)
5617{
5618 struct nl_msg *msg;
5619
5620 wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx);
5621
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005622 /* stop listening for EAPOL on this interface */
5623 del_ifidx(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005624
5625 msg = nlmsg_alloc();
5626 if (!msg)
5627 goto nla_put_failure;
5628
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005629 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005630 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
5631
5632 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
5633 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005634 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005635 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005636 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005637 wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
5638}
5639
5640
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005641static const char * nl80211_iftype_str(enum nl80211_iftype mode)
5642{
5643 switch (mode) {
5644 case NL80211_IFTYPE_ADHOC:
5645 return "ADHOC";
5646 case NL80211_IFTYPE_STATION:
5647 return "STATION";
5648 case NL80211_IFTYPE_AP:
5649 return "AP";
5650 case NL80211_IFTYPE_MONITOR:
5651 return "MONITOR";
5652 case NL80211_IFTYPE_P2P_CLIENT:
5653 return "P2P_CLIENT";
5654 case NL80211_IFTYPE_P2P_GO:
5655 return "P2P_GO";
5656 default:
5657 return "unknown";
5658 }
5659}
5660
5661
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005662static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
5663 const char *ifname,
5664 enum nl80211_iftype iftype,
5665 const u8 *addr, int wds)
5666{
5667 struct nl_msg *msg, *flags = NULL;
5668 int ifidx;
5669 int ret = -ENOBUFS;
5670
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005671 wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)",
5672 iftype, nl80211_iftype_str(iftype));
5673
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005674 msg = nlmsg_alloc();
5675 if (!msg)
5676 return -1;
5677
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005678 nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005679 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
5680 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);
5681 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
5682
5683 if (iftype == NL80211_IFTYPE_MONITOR) {
5684 int err;
5685
5686 flags = nlmsg_alloc();
5687 if (!flags)
5688 goto nla_put_failure;
5689
5690 NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);
5691
5692 err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);
5693
5694 nlmsg_free(flags);
5695
5696 if (err)
5697 goto nla_put_failure;
5698 } else if (wds) {
5699 NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds);
5700 }
5701
5702 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005703 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005704 if (ret) {
5705 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005706 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005707 wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)",
5708 ifname, ret, strerror(-ret));
5709 return ret;
5710 }
5711
5712 ifidx = if_nametoindex(ifname);
5713 wpa_printf(MSG_DEBUG, "nl80211: New interface %s created: ifindex=%d",
5714 ifname, ifidx);
5715
5716 if (ifidx <= 0)
5717 return -1;
5718
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005719 /* start listening for EAPOL on this interface */
5720 add_ifidx(drv, ifidx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005721
5722 if (addr && iftype != NL80211_IFTYPE_MONITOR &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005723 linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005724 nl80211_remove_iface(drv, ifidx);
5725 return -1;
5726 }
5727
5728 return ifidx;
5729}
5730
5731
5732static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
5733 const char *ifname, enum nl80211_iftype iftype,
5734 const u8 *addr, int wds)
5735{
5736 int ret;
5737
5738 ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds);
5739
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005740 /* if error occurred and interface exists already */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005741 if (ret == -ENFILE && if_nametoindex(ifname)) {
5742 wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname);
5743
5744 /* Try to remove the interface that was already there. */
5745 nl80211_remove_iface(drv, if_nametoindex(ifname));
5746
5747 /* Try to create the interface again */
5748 ret = nl80211_create_iface_once(drv, ifname, iftype, addr,
5749 wds);
5750 }
5751
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005752 if (ret >= 0 && is_p2p_interface(iftype))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005753 nl80211_disable_11b_rates(drv, ret, 1);
5754
5755 return ret;
5756}
5757
5758
5759static void handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)
5760{
5761 struct ieee80211_hdr *hdr;
5762 u16 fc;
5763 union wpa_event_data event;
5764
5765 hdr = (struct ieee80211_hdr *) buf;
5766 fc = le_to_host16(hdr->frame_control);
5767
5768 os_memset(&event, 0, sizeof(event));
5769 event.tx_status.type = WLAN_FC_GET_TYPE(fc);
5770 event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
5771 event.tx_status.dst = hdr->addr1;
5772 event.tx_status.data = buf;
5773 event.tx_status.data_len = len;
5774 event.tx_status.ack = ok;
5775 wpa_supplicant_event(ctx, EVENT_TX_STATUS, &event);
5776}
5777
5778
5779static void from_unknown_sta(struct wpa_driver_nl80211_data *drv,
5780 u8 *buf, size_t len)
5781{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005782 struct ieee80211_hdr *hdr = (void *)buf;
5783 u16 fc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005784 union wpa_event_data event;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005785
5786 if (len < sizeof(*hdr))
5787 return;
5788
5789 fc = le_to_host16(hdr->frame_control);
5790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005791 os_memset(&event, 0, sizeof(event));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005792 event.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);
5793 event.rx_from_unknown.addr = hdr->addr2;
5794 event.rx_from_unknown.wds = (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) ==
5795 (WLAN_FC_FROMDS | WLAN_FC_TODS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005796 wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
5797}
5798
5799
5800static void handle_frame(struct wpa_driver_nl80211_data *drv,
5801 u8 *buf, size_t len, int datarate, int ssi_signal)
5802{
5803 struct ieee80211_hdr *hdr;
5804 u16 fc;
5805 union wpa_event_data event;
5806
5807 hdr = (struct ieee80211_hdr *) buf;
5808 fc = le_to_host16(hdr->frame_control);
5809
5810 switch (WLAN_FC_GET_TYPE(fc)) {
5811 case WLAN_FC_TYPE_MGMT:
5812 os_memset(&event, 0, sizeof(event));
5813 event.rx_mgmt.frame = buf;
5814 event.rx_mgmt.frame_len = len;
5815 event.rx_mgmt.datarate = datarate;
5816 event.rx_mgmt.ssi_signal = ssi_signal;
5817 wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
5818 break;
5819 case WLAN_FC_TYPE_CTRL:
5820 /* can only get here with PS-Poll frames */
5821 wpa_printf(MSG_DEBUG, "CTRL");
5822 from_unknown_sta(drv, buf, len);
5823 break;
5824 case WLAN_FC_TYPE_DATA:
5825 from_unknown_sta(drv, buf, len);
5826 break;
5827 }
5828}
5829
5830
5831static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
5832{
5833 struct wpa_driver_nl80211_data *drv = eloop_ctx;
5834 int len;
5835 unsigned char buf[3000];
5836 struct ieee80211_radiotap_iterator iter;
5837 int ret;
5838 int datarate = 0, ssi_signal = 0;
5839 int injected = 0, failed = 0, rxflags = 0;
5840
5841 len = recv(sock, buf, sizeof(buf), 0);
5842 if (len < 0) {
5843 perror("recv");
5844 return;
5845 }
5846
5847 if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {
5848 printf("received invalid radiotap frame\n");
5849 return;
5850 }
5851
5852 while (1) {
5853 ret = ieee80211_radiotap_iterator_next(&iter);
5854 if (ret == -ENOENT)
5855 break;
5856 if (ret) {
5857 printf("received invalid radiotap frame (%d)\n", ret);
5858 return;
5859 }
5860 switch (iter.this_arg_index) {
5861 case IEEE80211_RADIOTAP_FLAGS:
5862 if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
5863 len -= 4;
5864 break;
5865 case IEEE80211_RADIOTAP_RX_FLAGS:
5866 rxflags = 1;
5867 break;
5868 case IEEE80211_RADIOTAP_TX_FLAGS:
5869 injected = 1;
5870 failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
5871 IEEE80211_RADIOTAP_F_TX_FAIL;
5872 break;
5873 case IEEE80211_RADIOTAP_DATA_RETRIES:
5874 break;
5875 case IEEE80211_RADIOTAP_CHANNEL:
5876 /* TODO: convert from freq/flags to channel number */
5877 break;
5878 case IEEE80211_RADIOTAP_RATE:
5879 datarate = *iter.this_arg * 5;
5880 break;
5881 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
5882 ssi_signal = *iter.this_arg;
5883 break;
5884 }
5885 }
5886
5887 if (rxflags && injected)
5888 return;
5889
5890 if (!injected)
5891 handle_frame(drv, buf + iter.max_length,
5892 len - iter.max_length, datarate, ssi_signal);
5893 else
5894 handle_tx_callback(drv->ctx, buf + iter.max_length,
5895 len - iter.max_length, !failed);
5896}
5897
5898
5899/*
5900 * we post-process the filter code later and rewrite
5901 * this to the offset to the last instruction
5902 */
5903#define PASS 0xFF
5904#define FAIL 0xFE
5905
5906static struct sock_filter msock_filter_insns[] = {
5907 /*
5908 * do a little-endian load of the radiotap length field
5909 */
5910 /* load lower byte into A */
5911 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 2),
5912 /* put it into X (== index register) */
5913 BPF_STMT(BPF_MISC| BPF_TAX, 0),
5914 /* load upper byte into A */
5915 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 3),
5916 /* left-shift it by 8 */
5917 BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8),
5918 /* or with X */
5919 BPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0),
5920 /* put result into X */
5921 BPF_STMT(BPF_MISC| BPF_TAX, 0),
5922
5923 /*
5924 * Allow management frames through, this also gives us those
5925 * management frames that we sent ourselves with status
5926 */
5927 /* load the lower byte of the IEEE 802.11 frame control field */
5928 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
5929 /* mask off frame type and version */
5930 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF),
5931 /* accept frame if it's both 0, fall through otherwise */
5932 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0),
5933
5934 /*
5935 * TODO: add a bit to radiotap RX flags that indicates
5936 * that the sending station is not associated, then
5937 * add a filter here that filters on our DA and that flag
5938 * to allow us to deauth frames to that bad station.
5939 *
5940 * For now allow all To DS data frames through.
5941 */
5942 /* load the IEEE 802.11 frame control field */
5943 BPF_STMT(BPF_LD | BPF_H | BPF_IND, 0),
5944 /* mask off frame type, version and DS status */
5945 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03),
5946 /* accept frame if version 0, type 2 and To DS, fall through otherwise
5947 */
5948 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0801, PASS, 0),
5949
5950#if 0
5951 /*
5952 * drop non-data frames
5953 */
5954 /* load the lower byte of the frame control field */
5955 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
5956 /* mask off QoS bit */
5957 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c),
5958 /* drop non-data frames */
5959 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL),
5960#endif
5961 /* load the upper byte of the frame control field */
5962 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1),
5963 /* mask off toDS/fromDS */
5964 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03),
5965 /* accept WDS frames */
5966 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0),
5967
5968 /*
5969 * add header length to index
5970 */
5971 /* load the lower byte of the frame control field */
5972 BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0),
5973 /* mask off QoS bit */
5974 BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x80),
5975 /* right shift it by 6 to give 0 or 2 */
5976 BPF_STMT(BPF_ALU | BPF_RSH | BPF_K, 6),
5977 /* add data frame header length */
5978 BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 24),
5979 /* add index, was start of 802.11 header */
5980 BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0),
5981 /* move to index, now start of LL header */
5982 BPF_STMT(BPF_MISC | BPF_TAX, 0),
5983
5984 /*
5985 * Accept empty data frames, we use those for
5986 * polling activity.
5987 */
5988 BPF_STMT(BPF_LD | BPF_W | BPF_LEN, 0),
5989 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_X, 0, PASS, 0),
5990
5991 /*
5992 * Accept EAPOL frames
5993 */
5994 BPF_STMT(BPF_LD | BPF_W | BPF_IND, 0),
5995 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA0300, 0, FAIL),
5996 BPF_STMT(BPF_LD | BPF_W | BPF_IND, 4),
5997 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x0000888E, PASS, FAIL),
5998
5999 /* keep these last two statements or change the code below */
6000 /* return 0 == "DROP" */
6001 BPF_STMT(BPF_RET | BPF_K, 0),
6002 /* return ~0 == "keep all" */
6003 BPF_STMT(BPF_RET | BPF_K, ~0),
6004};
6005
6006static struct sock_fprog msock_filter = {
6007 .len = sizeof(msock_filter_insns)/sizeof(msock_filter_insns[0]),
6008 .filter = msock_filter_insns,
6009};
6010
6011
6012static int add_monitor_filter(int s)
6013{
6014 int idx;
6015
6016 /* rewrite all PASS/FAIL jump offsets */
6017 for (idx = 0; idx < msock_filter.len; idx++) {
6018 struct sock_filter *insn = &msock_filter_insns[idx];
6019
6020 if (BPF_CLASS(insn->code) == BPF_JMP) {
6021 if (insn->code == (BPF_JMP|BPF_JA)) {
6022 if (insn->k == PASS)
6023 insn->k = msock_filter.len - idx - 2;
6024 else if (insn->k == FAIL)
6025 insn->k = msock_filter.len - idx - 3;
6026 }
6027
6028 if (insn->jt == PASS)
6029 insn->jt = msock_filter.len - idx - 2;
6030 else if (insn->jt == FAIL)
6031 insn->jt = msock_filter.len - idx - 3;
6032
6033 if (insn->jf == PASS)
6034 insn->jf = msock_filter.len - idx - 2;
6035 else if (insn->jf == FAIL)
6036 insn->jf = msock_filter.len - idx - 3;
6037 }
6038 }
6039
6040 if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER,
6041 &msock_filter, sizeof(msock_filter))) {
6042 perror("SO_ATTACH_FILTER");
6043 return -1;
6044 }
6045
6046 return 0;
6047}
6048
6049
6050static void nl80211_remove_monitor_interface(
6051 struct wpa_driver_nl80211_data *drv)
6052{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006053 drv->monitor_refcount--;
6054 if (drv->monitor_refcount > 0)
6055 return;
6056
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006057 if (drv->monitor_ifidx >= 0) {
6058 nl80211_remove_iface(drv, drv->monitor_ifidx);
6059 drv->monitor_ifidx = -1;
6060 }
6061 if (drv->monitor_sock >= 0) {
6062 eloop_unregister_read_sock(drv->monitor_sock);
6063 close(drv->monitor_sock);
6064 drv->monitor_sock = -1;
6065 }
6066}
6067
6068
6069static int
6070nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
6071{
6072 char buf[IFNAMSIZ];
6073 struct sockaddr_ll ll;
6074 int optval;
6075 socklen_t optlen;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006076
6077 if (drv->monitor_ifidx >= 0) {
6078 drv->monitor_refcount++;
6079 return 0;
6080 }
6081
6082 if (os_strncmp(drv->first_bss.ifname, "p2p-", 4) == 0) {
6083 /*
6084 * P2P interface name is of the format p2p-%s-%d. For monitor
6085 * interface name corresponding to P2P GO, replace "p2p-" with
6086 * "mon-" to retain the same interface name length and to
6087 * indicate that it is a monitor interface.
6088 */
6089 snprintf(buf, IFNAMSIZ, "mon-%s", drv->first_bss.ifname + 4);
6090 } else {
6091 /* Non-P2P interface with AP functionality. */
6092 snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss.ifname);
6093 }
6094
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006095 buf[IFNAMSIZ - 1] = '\0';
6096
6097 drv->monitor_ifidx =
6098 nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,
6099 0);
6100
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07006101 if (drv->monitor_ifidx == -EOPNOTSUPP) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006102 /*
6103 * This is backward compatibility for a few versions of
6104 * the kernel only that didn't advertise the right
6105 * attributes for the only driver that then supported
6106 * AP mode w/o monitor -- ath6kl.
6107 */
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07006108 wpa_printf(MSG_DEBUG, "nl80211: Driver does not support "
6109 "monitor interface type - try to run without it");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006110 drv->device_ap_sme = 1;
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07006111 }
6112
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006113 if (drv->monitor_ifidx < 0)
6114 return -1;
6115
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006116 if (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006117 goto error;
6118
6119 memset(&ll, 0, sizeof(ll));
6120 ll.sll_family = AF_PACKET;
6121 ll.sll_ifindex = drv->monitor_ifidx;
6122 drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
6123 if (drv->monitor_sock < 0) {
6124 perror("socket[PF_PACKET,SOCK_RAW]");
6125 goto error;
6126 }
6127
6128 if (add_monitor_filter(drv->monitor_sock)) {
6129 wpa_printf(MSG_INFO, "Failed to set socket filter for monitor "
6130 "interface; do filtering in user space");
6131 /* This works, but will cost in performance. */
6132 }
6133
6134 if (bind(drv->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
6135 perror("monitor socket bind");
6136 goto error;
6137 }
6138
6139 optlen = sizeof(optval);
6140 optval = 20;
6141 if (setsockopt
6142 (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {
6143 perror("Failed to set socket priority");
6144 goto error;
6145 }
6146
6147 if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,
6148 drv, NULL)) {
6149 printf("Could not register monitor read socket\n");
6150 goto error;
6151 }
6152
6153 return 0;
6154 error:
6155 nl80211_remove_monitor_interface(drv);
6156 return -1;
6157}
6158
6159
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006160static int nl80211_setup_ap(struct i802_bss *bss)
6161{
6162 struct wpa_driver_nl80211_data *drv = bss->drv;
6163
6164 wpa_printf(MSG_DEBUG, "nl80211: Setup AP - device_ap_sme=%d "
6165 "use_monitor=%d", drv->device_ap_sme, drv->use_monitor);
6166
6167 /*
6168 * Disable Probe Request reporting unless we need it in this way for
6169 * devices that include the AP SME, in the other case (unless using
6170 * monitor iface) we'll get it through the nl_mgmt socket instead.
6171 */
6172 if (!drv->device_ap_sme)
6173 wpa_driver_nl80211_probe_req_report(bss, 0);
6174
6175 if (!drv->device_ap_sme && !drv->use_monitor)
6176 if (nl80211_mgmt_subscribe_ap(bss))
6177 return -1;
6178
6179 if (drv->device_ap_sme && !drv->use_monitor)
6180 if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
6181 return -1;
6182
6183 if (!drv->device_ap_sme && drv->use_monitor &&
6184 nl80211_create_monitor_interface(drv) &&
6185 !drv->device_ap_sme)
6186 return -1;
6187
6188 if (drv->device_ap_sme &&
6189 wpa_driver_nl80211_probe_req_report(bss, 1) < 0) {
6190 wpa_printf(MSG_DEBUG, "nl80211: Failed to enable "
6191 "Probe Request frame reporting in AP mode");
6192 /* Try to survive without this */
6193 }
6194
6195#ifdef ANDROID_P2P
6196 /* For AP mode, enable probe req report even if device_ap_sme
6197 * is not enabled
6198 */
6199 wpa_printf(MSG_DEBUG, "nl80211: Enabling probe req report");
6200 wpa_driver_nl80211_probe_req_report(bss, 1);
6201#endif
6202
6203 return 0;
6204}
6205
6206
6207static void nl80211_teardown_ap(struct i802_bss *bss)
6208{
6209 struct wpa_driver_nl80211_data *drv = bss->drv;
6210
6211 if (drv->device_ap_sme) {
6212 wpa_driver_nl80211_probe_req_report(bss, 0);
6213 if (!drv->use_monitor)
6214 nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)");
6215 } else if (drv->use_monitor)
6216 nl80211_remove_monitor_interface(drv);
6217 else
6218 nl80211_mgmt_unsubscribe(bss, "AP teardown");
6219
6220 bss->beacon_set = 0;
6221}
6222
6223
6224static int nl80211_send_eapol_data(struct i802_bss *bss,
6225 const u8 *addr, const u8 *data,
6226 size_t data_len)
6227{
6228 struct sockaddr_ll ll;
6229 int ret;
6230
6231 if (bss->drv->eapol_tx_sock < 0) {
6232 wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL");
6233 return -1;
6234 }
6235
6236 os_memset(&ll, 0, sizeof(ll));
6237 ll.sll_family = AF_PACKET;
6238 ll.sll_ifindex = bss->ifindex;
6239 ll.sll_protocol = htons(ETH_P_PAE);
6240 ll.sll_halen = ETH_ALEN;
6241 os_memcpy(ll.sll_addr, addr, ETH_ALEN);
6242 ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,
6243 (struct sockaddr *) &ll, sizeof(ll));
6244 if (ret < 0)
6245 wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s",
6246 strerror(errno));
6247
6248 return ret;
6249}
6250
6251
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006252static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
6253
6254static int wpa_driver_nl80211_hapd_send_eapol(
6255 void *priv, const u8 *addr, const u8 *data,
6256 size_t data_len, int encrypt, const u8 *own_addr, u32 flags)
6257{
6258 struct i802_bss *bss = priv;
6259 struct wpa_driver_nl80211_data *drv = bss->drv;
6260 struct ieee80211_hdr *hdr;
6261 size_t len;
6262 u8 *pos;
6263 int res;
6264 int qos = flags & WPA_STA_WMM;
6265
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006266 if (drv->device_ap_sme || !drv->use_monitor)
6267 return nl80211_send_eapol_data(bss, addr, data, data_len);
6268
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006269 len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
6270 data_len;
6271 hdr = os_zalloc(len);
6272 if (hdr == NULL) {
6273 printf("malloc() failed for i802_send_data(len=%lu)\n",
6274 (unsigned long) len);
6275 return -1;
6276 }
6277
6278 hdr->frame_control =
6279 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
6280 hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
6281 if (encrypt)
6282 hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
6283 if (qos) {
6284 hdr->frame_control |=
6285 host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
6286 }
6287
6288 memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
6289 memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
6290 memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
6291 pos = (u8 *) (hdr + 1);
6292
6293 if (qos) {
6294 /* add an empty QoS header if needed */
6295 pos[0] = 0;
6296 pos[1] = 0;
6297 pos += 2;
6298 }
6299
6300 memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
6301 pos += sizeof(rfc1042_header);
6302 WPA_PUT_BE16(pos, ETH_P_PAE);
6303 pos += 2;
6304 memcpy(pos, data, data_len);
6305
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006306 res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006307 if (res < 0) {
6308 wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
6309 "failed: %d (%s)",
6310 (unsigned long) len, errno, strerror(errno));
6311 }
6312 os_free(hdr);
6313
6314 return res;
6315}
6316
6317
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006318static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
6319 int total_flags,
6320 int flags_or, int flags_and)
6321{
6322 struct i802_bss *bss = priv;
6323 struct wpa_driver_nl80211_data *drv = bss->drv;
6324 struct nl_msg *msg, *flags = NULL;
6325 struct nl80211_sta_flag_update upd;
6326
6327 msg = nlmsg_alloc();
6328 if (!msg)
6329 return -ENOMEM;
6330
6331 flags = nlmsg_alloc();
6332 if (!flags) {
6333 nlmsg_free(msg);
6334 return -ENOMEM;
6335 }
6336
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006337 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006338
6339 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
6340 if_nametoindex(bss->ifname));
6341 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
6342
6343 /*
6344 * Backwards compatibility version using NL80211_ATTR_STA_FLAGS. This
6345 * can be removed eventually.
6346 */
6347 if (total_flags & WPA_STA_AUTHORIZED)
6348 NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);
6349
6350 if (total_flags & WPA_STA_WMM)
6351 NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);
6352
6353 if (total_flags & WPA_STA_SHORT_PREAMBLE)
6354 NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);
6355
6356 if (total_flags & WPA_STA_MFP)
6357 NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP);
6358
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006359 if (total_flags & WPA_STA_TDLS_PEER)
6360 NLA_PUT_FLAG(flags, NL80211_STA_FLAG_TDLS_PEER);
6361
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006362 if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
6363 goto nla_put_failure;
6364
6365 os_memset(&upd, 0, sizeof(upd));
6366 upd.mask = sta_flags_nl80211(flags_or | ~flags_and);
6367 upd.set = sta_flags_nl80211(flags_or);
6368 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
6369
6370 nlmsg_free(flags);
6371
6372 return send_and_recv_msgs(drv, msg, NULL, NULL);
6373 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006374 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006375 nlmsg_free(flags);
6376 return -ENOBUFS;
6377}
6378
6379
6380static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
6381 struct wpa_driver_associate_params *params)
6382{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006383 enum nl80211_iftype nlmode;
6384
6385 if (params->p2p) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006386 wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
6387 "group (GO)");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006388 nlmode = NL80211_IFTYPE_P2P_GO;
6389 } else
6390 nlmode = NL80211_IFTYPE_AP;
6391
6392 if (wpa_driver_nl80211_set_mode(&drv->first_bss, nlmode) ||
6393 wpa_driver_nl80211_set_freq(&drv->first_bss, params->freq, 0, 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006394 nl80211_remove_monitor_interface(drv);
6395 return -1;
6396 }
6397
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006398 return 0;
6399}
6400
6401
6402static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv)
6403{
6404 struct nl_msg *msg;
6405 int ret = -1;
6406
6407 msg = nlmsg_alloc();
6408 if (!msg)
6409 return -1;
6410
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006411 nl80211_cmd(drv, msg, 0, NL80211_CMD_LEAVE_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006412 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6413 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6414 msg = NULL;
6415 if (ret) {
6416 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d "
6417 "(%s)", ret, strerror(-ret));
6418 goto nla_put_failure;
6419 }
6420
6421 ret = 0;
6422 wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS request sent successfully");
6423
6424nla_put_failure:
6425 nlmsg_free(msg);
6426 return ret;
6427}
6428
6429
6430static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
6431 struct wpa_driver_associate_params *params)
6432{
6433 struct nl_msg *msg;
6434 int ret = -1;
6435 int count = 0;
6436
6437 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
6438
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006439 if (wpa_driver_nl80211_set_mode(&drv->first_bss,
6440 NL80211_IFTYPE_ADHOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006441 wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
6442 "IBSS mode");
6443 return -1;
6444 }
6445
6446retry:
6447 msg = nlmsg_alloc();
6448 if (!msg)
6449 return -1;
6450
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006451 nl80211_cmd(drv, msg, 0, NL80211_CMD_JOIN_IBSS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006452 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6453
6454 if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
6455 goto nla_put_failure;
6456
6457 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
6458 params->ssid, params->ssid_len);
6459 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
6460 params->ssid);
6461 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
6462 drv->ssid_len = params->ssid_len;
6463
6464 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
6465 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
6466
6467 ret = nl80211_set_conn_keys(params, msg);
6468 if (ret)
6469 goto nla_put_failure;
6470
6471 if (params->wpa_ie) {
6472 wpa_hexdump(MSG_DEBUG,
6473 " * Extra IEs for Beacon/Probe Response frames",
6474 params->wpa_ie, params->wpa_ie_len);
6475 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
6476 params->wpa_ie);
6477 }
6478
6479 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6480 msg = NULL;
6481 if (ret) {
6482 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)",
6483 ret, strerror(-ret));
6484 count++;
6485 if (ret == -EALREADY && count == 1) {
6486 wpa_printf(MSG_DEBUG, "nl80211: Retry IBSS join after "
6487 "forced leave");
6488 nl80211_leave_ibss(drv);
6489 nlmsg_free(msg);
6490 goto retry;
6491 }
6492
6493 goto nla_put_failure;
6494 }
6495 ret = 0;
6496 wpa_printf(MSG_DEBUG, "nl80211: Join IBSS request sent successfully");
6497
6498nla_put_failure:
6499 nlmsg_free(msg);
6500 return ret;
6501}
6502
6503
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006504static unsigned int nl80211_get_assoc_bssid(struct wpa_driver_nl80211_data *drv,
6505 u8 *bssid)
6506{
6507 struct nl_msg *msg;
6508 int ret;
6509 struct nl80211_bss_info_arg arg;
6510
6511 os_memset(&arg, 0, sizeof(arg));
6512 msg = nlmsg_alloc();
6513 if (!msg)
6514 goto nla_put_failure;
6515
6516 nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
6517 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6518
6519 arg.drv = drv;
6520 ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
6521 msg = NULL;
6522 if (ret == 0) {
6523 if (is_zero_ether_addr(arg.assoc_bssid))
6524 return -ENOTCONN;
6525 os_memcpy(bssid, arg.assoc_bssid, ETH_ALEN);
6526 return 0;
6527 }
6528 wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
6529 "(%s)", ret, strerror(-ret));
6530nla_put_failure:
6531 nlmsg_free(msg);
6532 return drv->assoc_freq;
6533}
6534
6535
6536static int nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
6537 const u8 *bssid)
6538{
6539 u8 addr[ETH_ALEN];
6540
6541 if (bssid == NULL) {
6542 int res = nl80211_get_assoc_bssid(drv, addr);
6543 if (res)
6544 return res;
6545 bssid = addr;
6546 }
6547
6548 return wpa_driver_nl80211_disconnect(drv, bssid,
6549 WLAN_REASON_PREV_AUTH_NOT_VALID);
6550}
6551
6552
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006553static int wpa_driver_nl80211_connect(
6554 struct wpa_driver_nl80211_data *drv,
6555 struct wpa_driver_associate_params *params)
6556{
6557 struct nl_msg *msg;
6558 enum nl80211_auth_type type;
6559 int ret = 0;
6560 int algs;
6561
6562 msg = nlmsg_alloc();
6563 if (!msg)
6564 return -1;
6565
6566 wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006567 nl80211_cmd(drv, msg, 0, NL80211_CMD_CONNECT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006568
6569 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6570 if (params->bssid) {
6571 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
6572 MAC2STR(params->bssid));
6573 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
6574 }
6575 if (params->freq) {
6576 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
6577 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
6578 }
6579 if (params->ssid) {
6580 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
6581 params->ssid, params->ssid_len);
6582 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
6583 params->ssid);
6584 if (params->ssid_len > sizeof(drv->ssid))
6585 goto nla_put_failure;
6586 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
6587 drv->ssid_len = params->ssid_len;
6588 }
6589 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
6590 if (params->wpa_ie)
6591 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
6592 params->wpa_ie);
6593
6594 algs = 0;
6595 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
6596 algs++;
6597 if (params->auth_alg & WPA_AUTH_ALG_SHARED)
6598 algs++;
6599 if (params->auth_alg & WPA_AUTH_ALG_LEAP)
6600 algs++;
6601 if (algs > 1) {
6602 wpa_printf(MSG_DEBUG, " * Leave out Auth Type for automatic "
6603 "selection");
6604 goto skip_auth_type;
6605 }
6606
6607 if (params->auth_alg & WPA_AUTH_ALG_OPEN)
6608 type = NL80211_AUTHTYPE_OPEN_SYSTEM;
6609 else if (params->auth_alg & WPA_AUTH_ALG_SHARED)
6610 type = NL80211_AUTHTYPE_SHARED_KEY;
6611 else if (params->auth_alg & WPA_AUTH_ALG_LEAP)
6612 type = NL80211_AUTHTYPE_NETWORK_EAP;
6613 else if (params->auth_alg & WPA_AUTH_ALG_FT)
6614 type = NL80211_AUTHTYPE_FT;
6615 else
6616 goto nla_put_failure;
6617
6618 wpa_printf(MSG_DEBUG, " * Auth Type %d", type);
6619 NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
6620
6621skip_auth_type:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006622 if (params->wpa_proto) {
6623 enum nl80211_wpa_versions ver = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006624
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006625 if (params->wpa_proto & WPA_PROTO_WPA)
6626 ver |= NL80211_WPA_VERSION_1;
6627 if (params->wpa_proto & WPA_PROTO_RSN)
6628 ver |= NL80211_WPA_VERSION_2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006629
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006630 wpa_printf(MSG_DEBUG, " * WPA Versions 0x%x", ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006631 NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
6632 }
6633
6634 if (params->pairwise_suite != CIPHER_NONE) {
6635 int cipher;
6636
6637 switch (params->pairwise_suite) {
6638 case CIPHER_WEP40:
6639 cipher = WLAN_CIPHER_SUITE_WEP40;
6640 break;
6641 case CIPHER_WEP104:
6642 cipher = WLAN_CIPHER_SUITE_WEP104;
6643 break;
6644 case CIPHER_CCMP:
6645 cipher = WLAN_CIPHER_SUITE_CCMP;
6646 break;
6647 case CIPHER_TKIP:
6648 default:
6649 cipher = WLAN_CIPHER_SUITE_TKIP;
6650 break;
6651 }
6652 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
6653 }
6654
6655 if (params->group_suite != CIPHER_NONE) {
6656 int cipher;
6657
6658 switch (params->group_suite) {
6659 case CIPHER_WEP40:
6660 cipher = WLAN_CIPHER_SUITE_WEP40;
6661 break;
6662 case CIPHER_WEP104:
6663 cipher = WLAN_CIPHER_SUITE_WEP104;
6664 break;
6665 case CIPHER_CCMP:
6666 cipher = WLAN_CIPHER_SUITE_CCMP;
6667 break;
6668 case CIPHER_TKIP:
6669 default:
6670 cipher = WLAN_CIPHER_SUITE_TKIP;
6671 break;
6672 }
6673 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
6674 }
6675
6676 if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
6677 params->key_mgmt_suite == KEY_MGMT_PSK) {
6678 int mgmt = WLAN_AKM_SUITE_PSK;
6679
6680 switch (params->key_mgmt_suite) {
6681 case KEY_MGMT_802_1X:
6682 mgmt = WLAN_AKM_SUITE_8021X;
6683 break;
6684 case KEY_MGMT_PSK:
6685 default:
6686 mgmt = WLAN_AKM_SUITE_PSK;
6687 break;
6688 }
6689 NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);
6690 }
6691
6692 ret = nl80211_set_conn_keys(params, msg);
6693 if (ret)
6694 goto nla_put_failure;
6695
6696 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6697 msg = NULL;
6698 if (ret) {
6699 wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
6700 "(%s)", ret, strerror(-ret));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006701 /*
6702 * cfg80211 does not currently accept new connection if we are
6703 * already connected. As a workaround, force disconnection and
6704 * try again once the driver indicates it completed
6705 * disconnection.
6706 */
6707 if (ret == -EALREADY)
6708 nl80211_disconnect(drv, params->bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006709 goto nla_put_failure;
6710 }
6711 ret = 0;
6712 wpa_printf(MSG_DEBUG, "nl80211: Connect request send successfully");
6713
6714nla_put_failure:
6715 nlmsg_free(msg);
6716 return ret;
6717
6718}
6719
6720
6721static int wpa_driver_nl80211_associate(
6722 void *priv, struct wpa_driver_associate_params *params)
6723{
6724 struct i802_bss *bss = priv;
6725 struct wpa_driver_nl80211_data *drv = bss->drv;
6726 int ret = -1;
6727 struct nl_msg *msg;
6728
6729 if (params->mode == IEEE80211_MODE_AP)
6730 return wpa_driver_nl80211_ap(drv, params);
6731
6732 if (params->mode == IEEE80211_MODE_IBSS)
6733 return wpa_driver_nl80211_ibss(drv, params);
6734
6735 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006736 enum nl80211_iftype nlmode = params->p2p ?
6737 NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
6738
6739 if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006740 return -1;
6741 return wpa_driver_nl80211_connect(drv, params);
6742 }
6743
6744 drv->associated = 0;
6745
6746 msg = nlmsg_alloc();
6747 if (!msg)
6748 return -1;
6749
6750 wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)",
6751 drv->ifindex);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006752 nl80211_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006753
6754 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
6755 if (params->bssid) {
6756 wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
6757 MAC2STR(params->bssid));
6758 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
6759 }
6760 if (params->freq) {
6761 wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
6762 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
6763 drv->assoc_freq = params->freq;
6764 } else
6765 drv->assoc_freq = 0;
6766 if (params->ssid) {
6767 wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
6768 params->ssid, params->ssid_len);
6769 NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
6770 params->ssid);
6771 if (params->ssid_len > sizeof(drv->ssid))
6772 goto nla_put_failure;
6773 os_memcpy(drv->ssid, params->ssid, params->ssid_len);
6774 drv->ssid_len = params->ssid_len;
6775 }
6776 wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
6777 if (params->wpa_ie)
6778 NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
6779 params->wpa_ie);
6780
6781 if (params->pairwise_suite != CIPHER_NONE) {
6782 int cipher;
6783
6784 switch (params->pairwise_suite) {
6785 case CIPHER_WEP40:
6786 cipher = WLAN_CIPHER_SUITE_WEP40;
6787 break;
6788 case CIPHER_WEP104:
6789 cipher = WLAN_CIPHER_SUITE_WEP104;
6790 break;
6791 case CIPHER_CCMP:
6792 cipher = WLAN_CIPHER_SUITE_CCMP;
6793 break;
6794 case CIPHER_TKIP:
6795 default:
6796 cipher = WLAN_CIPHER_SUITE_TKIP;
6797 break;
6798 }
6799 wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher);
6800 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
6801 }
6802
6803 if (params->group_suite != CIPHER_NONE) {
6804 int cipher;
6805
6806 switch (params->group_suite) {
6807 case CIPHER_WEP40:
6808 cipher = WLAN_CIPHER_SUITE_WEP40;
6809 break;
6810 case CIPHER_WEP104:
6811 cipher = WLAN_CIPHER_SUITE_WEP104;
6812 break;
6813 case CIPHER_CCMP:
6814 cipher = WLAN_CIPHER_SUITE_CCMP;
6815 break;
6816 case CIPHER_TKIP:
6817 default:
6818 cipher = WLAN_CIPHER_SUITE_TKIP;
6819 break;
6820 }
6821 wpa_printf(MSG_DEBUG, " * group=0x%x", cipher);
6822 NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
6823 }
6824
6825#ifdef CONFIG_IEEE80211W
6826 if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)
6827 NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);
6828#endif /* CONFIG_IEEE80211W */
6829
6830 NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
6831
6832 if (params->prev_bssid) {
6833 wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
6834 MAC2STR(params->prev_bssid));
6835 NLA_PUT(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
6836 params->prev_bssid);
6837 }
6838
6839 if (params->p2p)
6840 wpa_printf(MSG_DEBUG, " * P2P group");
6841
6842 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
6843 msg = NULL;
6844 if (ret) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006845 wpa_dbg(drv->ctx, MSG_DEBUG,
6846 "nl80211: MLME command failed (assoc): ret=%d (%s)",
6847 ret, strerror(-ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006848 nl80211_dump_scan(drv);
6849 goto nla_put_failure;
6850 }
6851 ret = 0;
6852 wpa_printf(MSG_DEBUG, "nl80211: Association request send "
6853 "successfully");
6854
6855nla_put_failure:
6856 nlmsg_free(msg);
6857 return ret;
6858}
6859
6860
6861static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006862 int ifindex, enum nl80211_iftype mode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006863{
6864 struct nl_msg *msg;
6865 int ret = -ENOBUFS;
6866
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006867 wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)",
6868 ifindex, mode, nl80211_iftype_str(mode));
6869
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006870 msg = nlmsg_alloc();
6871 if (!msg)
6872 return -ENOMEM;
6873
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006874 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006875 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
6876 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);
6877
6878 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006879 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006880 if (!ret)
6881 return 0;
6882nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006883 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006884 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
6885 " %d (%s)", ifindex, mode, ret, strerror(-ret));
6886 return ret;
6887}
6888
6889
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006890static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
6891 enum nl80211_iftype nlmode)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006892{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006893 struct wpa_driver_nl80211_data *drv = bss->drv;
6894 int ret = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006895 int i;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006896 int was_ap = is_ap_interface(drv->nlmode);
6897 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006898
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006899 res = nl80211_set_mode(drv, drv->ifindex, nlmode);
6900 if (res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006901 drv->nlmode = nlmode;
6902 ret = 0;
6903 goto done;
6904 }
6905
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006906 if (res == -ENODEV)
6907 return -1;
6908
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006909 if (nlmode == drv->nlmode) {
6910 wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
6911 "requested mode - ignore error");
6912 ret = 0;
6913 goto done; /* Already in the requested mode */
6914 }
6915
6916 /* mac80211 doesn't allow mode changes while the device is up, so
6917 * take the device down, try to set the mode again, and bring the
6918 * device back up.
6919 */
6920 wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
6921 "interface down");
6922 for (i = 0; i < 10; i++) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006923 res = linux_set_iface_flags(drv->global->ioctl_sock,
6924 bss->ifname, 0);
6925 if (res == -EACCES || res == -ENODEV)
6926 break;
6927 if (res == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006928 /* Try to set the mode again while the interface is
6929 * down */
6930 ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006931 if (ret == -EACCES)
6932 break;
6933 res = linux_set_iface_flags(drv->global->ioctl_sock,
6934 bss->ifname, 1);
6935 if (res && !ret)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006936 ret = -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006937 else if (ret != -EBUSY)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006938 break;
6939 } else
6940 wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
6941 "interface down");
6942 os_sleep(0, 100000);
6943 }
6944
6945 if (!ret) {
6946 wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
6947 "interface is down");
6948 drv->nlmode = nlmode;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006949 drv->ignore_if_down_event = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006950 }
6951
6952done:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006953 if (ret) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006954 wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
6955 "from %d failed", nlmode, drv->nlmode);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006956 return ret;
6957 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006958
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006959 if (is_ap_interface(nlmode)) {
6960 nl80211_mgmt_unsubscribe(bss, "start AP");
6961 /* Setup additional AP mode functionality if needed */
6962 if (nl80211_setup_ap(bss))
6963 return -1;
6964 } else if (was_ap) {
6965 /* Remove additional AP mode functionality */
6966 nl80211_teardown_ap(bss);
6967 } else {
6968 nl80211_mgmt_unsubscribe(bss, "mode change");
6969 }
6970
6971 if (!is_ap_interface(nlmode) &&
6972 nl80211_mgmt_subscribe_non_ap(bss) < 0)
6973 wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
6974 "frame processing - ignore for now");
6975
6976 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006977}
6978
6979
6980static int wpa_driver_nl80211_get_capa(void *priv,
6981 struct wpa_driver_capa *capa)
6982{
6983 struct i802_bss *bss = priv;
6984 struct wpa_driver_nl80211_data *drv = bss->drv;
6985 if (!drv->has_capability)
6986 return -1;
6987 os_memcpy(capa, &drv->capa, sizeof(*capa));
6988 return 0;
6989}
6990
6991
6992static int wpa_driver_nl80211_set_operstate(void *priv, int state)
6993{
6994 struct i802_bss *bss = priv;
6995 struct wpa_driver_nl80211_data *drv = bss->drv;
6996
6997 wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
6998 __func__, drv->operstate, state, state ? "UP" : "DORMANT");
6999 drv->operstate = state;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007000 return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007001 state ? IF_OPER_UP : IF_OPER_DORMANT);
7002}
7003
7004
7005static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
7006{
7007 struct i802_bss *bss = priv;
7008 struct wpa_driver_nl80211_data *drv = bss->drv;
7009 struct nl_msg *msg;
7010 struct nl80211_sta_flag_update upd;
7011
7012 msg = nlmsg_alloc();
7013 if (!msg)
7014 return -ENOMEM;
7015
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007016 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007017
7018 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
7019 if_nametoindex(bss->ifname));
7020 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
7021
7022 os_memset(&upd, 0, sizeof(upd));
7023 upd.mask = BIT(NL80211_STA_FLAG_AUTHORIZED);
7024 if (authorized)
7025 upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);
7026 NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
7027
7028 return send_and_recv_msgs(drv, msg, NULL, NULL);
7029 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007030 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007031 return -ENOBUFS;
7032}
7033
7034
Jouni Malinen75ecf522011-06-27 15:19:46 -07007035/* Set kernel driver on given frequency (MHz) */
7036static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007037{
Jouni Malinen75ecf522011-06-27 15:19:46 -07007038 struct i802_bss *bss = priv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007039 return wpa_driver_nl80211_set_freq(bss, freq->freq, freq->ht_enabled,
Jouni Malinen75ecf522011-06-27 15:19:46 -07007040 freq->sec_channel_offset);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007041}
7042
7043
Jouni Malinen75ecf522011-06-27 15:19:46 -07007044#if defined(HOSTAPD) || defined(CONFIG_AP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007045
7046static inline int min_int(int a, int b)
7047{
7048 if (a < b)
7049 return a;
7050 return b;
7051}
7052
7053
7054static int get_key_handler(struct nl_msg *msg, void *arg)
7055{
7056 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7057 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7058
7059 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7060 genlmsg_attrlen(gnlh, 0), NULL);
7061
7062 /*
7063 * TODO: validate the key index and mac address!
7064 * Otherwise, there's a race condition as soon as
7065 * the kernel starts sending key notifications.
7066 */
7067
7068 if (tb[NL80211_ATTR_KEY_SEQ])
7069 memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
7070 min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
7071 return NL_SKIP;
7072}
7073
7074
7075static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
7076 int idx, u8 *seq)
7077{
7078 struct i802_bss *bss = priv;
7079 struct wpa_driver_nl80211_data *drv = bss->drv;
7080 struct nl_msg *msg;
7081
7082 msg = nlmsg_alloc();
7083 if (!msg)
7084 return -ENOMEM;
7085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007086 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_KEY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007087
7088 if (addr)
7089 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
7090 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
7091 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
7092
7093 memset(seq, 0, 6);
7094
7095 return send_and_recv_msgs(drv, msg, get_key_handler, seq);
7096 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007097 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007098 return -ENOBUFS;
7099}
7100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007101
7102static int i802_set_rts(void *priv, int rts)
7103{
7104 struct i802_bss *bss = priv;
7105 struct wpa_driver_nl80211_data *drv = bss->drv;
7106 struct nl_msg *msg;
7107 int ret = -ENOBUFS;
7108 u32 val;
7109
7110 msg = nlmsg_alloc();
7111 if (!msg)
7112 return -ENOMEM;
7113
7114 if (rts >= 2347)
7115 val = (u32) -1;
7116 else
7117 val = rts;
7118
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007119 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007120 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7121 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val);
7122
7123 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007124 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007125 if (!ret)
7126 return 0;
7127nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007128 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007129 wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
7130 "%d (%s)", rts, ret, strerror(-ret));
7131 return ret;
7132}
7133
7134
7135static int i802_set_frag(void *priv, int frag)
7136{
7137 struct i802_bss *bss = priv;
7138 struct wpa_driver_nl80211_data *drv = bss->drv;
7139 struct nl_msg *msg;
7140 int ret = -ENOBUFS;
7141 u32 val;
7142
7143 msg = nlmsg_alloc();
7144 if (!msg)
7145 return -ENOMEM;
7146
7147 if (frag >= 2346)
7148 val = (u32) -1;
7149 else
7150 val = frag;
7151
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007152 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007153 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
7154 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val);
7155
7156 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007157 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007158 if (!ret)
7159 return 0;
7160nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007161 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007162 wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
7163 "%d: %d (%s)", frag, ret, strerror(-ret));
7164 return ret;
7165}
7166
7167
7168static int i802_flush(void *priv)
7169{
7170 struct i802_bss *bss = priv;
7171 struct wpa_driver_nl80211_data *drv = bss->drv;
7172 struct nl_msg *msg;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007173 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007174
7175 msg = nlmsg_alloc();
7176 if (!msg)
7177 return -1;
7178
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007179 nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007180
7181 /*
7182 * XXX: FIX! this needs to flush all VLANs too
7183 */
7184 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
7185 if_nametoindex(bss->ifname));
7186
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007187 res = send_and_recv_msgs(drv, msg, NULL, NULL);
7188 if (res) {
7189 wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
7190 "(%s)", res, strerror(-res));
7191 }
7192 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007193 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007194 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007195 return -ENOBUFS;
7196}
7197
7198
7199static int get_sta_handler(struct nl_msg *msg, void *arg)
7200{
7201 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7202 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7203 struct hostap_sta_driver_data *data = arg;
7204 struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
7205 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
7206 [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
7207 [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
7208 [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
7209 [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
7210 [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
7211 };
7212
7213 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7214 genlmsg_attrlen(gnlh, 0), NULL);
7215
7216 /*
7217 * TODO: validate the interface and mac address!
7218 * Otherwise, there's a race condition as soon as
7219 * the kernel starts sending station notifications.
7220 */
7221
7222 if (!tb[NL80211_ATTR_STA_INFO]) {
7223 wpa_printf(MSG_DEBUG, "sta stats missing!");
7224 return NL_SKIP;
7225 }
7226 if (nla_parse_nested(stats, NL80211_STA_INFO_MAX,
7227 tb[NL80211_ATTR_STA_INFO],
7228 stats_policy)) {
7229 wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
7230 return NL_SKIP;
7231 }
7232
7233 if (stats[NL80211_STA_INFO_INACTIVE_TIME])
7234 data->inactive_msec =
7235 nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);
7236 if (stats[NL80211_STA_INFO_RX_BYTES])
7237 data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
7238 if (stats[NL80211_STA_INFO_TX_BYTES])
7239 data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
7240 if (stats[NL80211_STA_INFO_RX_PACKETS])
7241 data->rx_packets =
7242 nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
7243 if (stats[NL80211_STA_INFO_TX_PACKETS])
7244 data->tx_packets =
7245 nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
7246
7247 return NL_SKIP;
7248}
7249
7250static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
7251 const u8 *addr)
7252{
7253 struct i802_bss *bss = priv;
7254 struct wpa_driver_nl80211_data *drv = bss->drv;
7255 struct nl_msg *msg;
7256
7257 os_memset(data, 0, sizeof(*data));
7258 msg = nlmsg_alloc();
7259 if (!msg)
7260 return -ENOMEM;
7261
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007262 nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007263
7264 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
7265 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
7266
7267 return send_and_recv_msgs(drv, msg, get_sta_handler, data);
7268 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007269 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007270 return -ENOBUFS;
7271}
7272
7273
7274static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
7275 int cw_min, int cw_max, int burst_time)
7276{
7277 struct i802_bss *bss = priv;
7278 struct wpa_driver_nl80211_data *drv = bss->drv;
7279 struct nl_msg *msg;
7280 struct nlattr *txq, *params;
7281
7282 msg = nlmsg_alloc();
7283 if (!msg)
7284 return -1;
7285
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007286 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007287
7288 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
7289
7290 txq = nla_nest_start(msg, NL80211_ATTR_WIPHY_TXQ_PARAMS);
7291 if (!txq)
7292 goto nla_put_failure;
7293
7294 /* We are only sending parameters for a single TXQ at a time */
7295 params = nla_nest_start(msg, 1);
7296 if (!params)
7297 goto nla_put_failure;
7298
7299 switch (queue) {
7300 case 0:
7301 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VO);
7302 break;
7303 case 1:
7304 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_VI);
7305 break;
7306 case 2:
7307 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BE);
7308 break;
7309 case 3:
7310 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_QUEUE, NL80211_TXQ_Q_BK);
7311 break;
7312 }
7313 /* Burst time is configured in units of 0.1 msec and TXOP parameter in
7314 * 32 usec, so need to convert the value here. */
7315 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_TXOP, (burst_time * 100 + 16) / 32);
7316 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMIN, cw_min);
7317 NLA_PUT_U16(msg, NL80211_TXQ_ATTR_CWMAX, cw_max);
7318 NLA_PUT_U8(msg, NL80211_TXQ_ATTR_AIFS, aifs);
7319
7320 nla_nest_end(msg, params);
7321
7322 nla_nest_end(msg, txq);
7323
7324 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
7325 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007326 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007327 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007328 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007329 return -1;
7330}
7331
7332
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007333static int i802_set_sta_vlan(void *priv, const u8 *addr,
7334 const char *ifname, int vlan_id)
7335{
7336 struct i802_bss *bss = priv;
7337 struct wpa_driver_nl80211_data *drv = bss->drv;
7338 struct nl_msg *msg;
7339 int ret = -ENOBUFS;
7340
7341 msg = nlmsg_alloc();
7342 if (!msg)
7343 return -ENOMEM;
7344
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007345 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007346
7347 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
7348 if_nametoindex(bss->ifname));
7349 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
7350 NLA_PUT_U32(msg, NL80211_ATTR_STA_VLAN,
7351 if_nametoindex(ifname));
7352
7353 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007354 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007355 if (ret < 0) {
7356 wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
7357 MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
7358 MAC2STR(addr), ifname, vlan_id, ret,
7359 strerror(-ret));
7360 }
7361 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007362 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007363 return ret;
7364}
7365
7366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007367static int i802_get_inact_sec(void *priv, const u8 *addr)
7368{
7369 struct hostap_sta_driver_data data;
7370 int ret;
7371
7372 data.inactive_msec = (unsigned long) -1;
7373 ret = i802_read_sta_data(priv, &data, addr);
7374 if (ret || data.inactive_msec == (unsigned long) -1)
7375 return -1;
7376 return data.inactive_msec / 1000;
7377}
7378
7379
7380static int i802_sta_clear_stats(void *priv, const u8 *addr)
7381{
7382#if 0
7383 /* TODO */
7384#endif
7385 return 0;
7386}
7387
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007388
7389static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
7390 int reason)
7391{
7392 struct i802_bss *bss = priv;
7393 struct ieee80211_mgmt mgmt;
7394
7395 memset(&mgmt, 0, sizeof(mgmt));
7396 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
7397 WLAN_FC_STYPE_DEAUTH);
7398 memcpy(mgmt.da, addr, ETH_ALEN);
7399 memcpy(mgmt.sa, own_addr, ETH_ALEN);
7400 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
7401 mgmt.u.deauth.reason_code = host_to_le16(reason);
7402 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
7403 IEEE80211_HDRLEN +
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007404 sizeof(mgmt.u.deauth), 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007405}
7406
7407
7408static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
7409 int reason)
7410{
7411 struct i802_bss *bss = priv;
7412 struct ieee80211_mgmt mgmt;
7413
7414 memset(&mgmt, 0, sizeof(mgmt));
7415 mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
7416 WLAN_FC_STYPE_DISASSOC);
7417 memcpy(mgmt.da, addr, ETH_ALEN);
7418 memcpy(mgmt.sa, own_addr, ETH_ALEN);
7419 memcpy(mgmt.bssid, own_addr, ETH_ALEN);
7420 mgmt.u.disassoc.reason_code = host_to_le16(reason);
7421 return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
7422 IEEE80211_HDRLEN +
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007423 sizeof(mgmt.u.disassoc), 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007424}
7425
7426#endif /* HOSTAPD || CONFIG_AP */
7427
7428#ifdef HOSTAPD
7429
Jouni Malinen75ecf522011-06-27 15:19:46 -07007430static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
7431{
7432 int i;
7433 int *old;
7434
7435 wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
7436 ifidx);
7437 for (i = 0; i < drv->num_if_indices; i++) {
7438 if (drv->if_indices[i] == 0) {
7439 drv->if_indices[i] = ifidx;
7440 return;
7441 }
7442 }
7443
7444 if (drv->if_indices != drv->default_if_indices)
7445 old = drv->if_indices;
7446 else
7447 old = NULL;
7448
7449 drv->if_indices = os_realloc(old,
7450 sizeof(int) * (drv->num_if_indices + 1));
7451 if (!drv->if_indices) {
7452 if (!old)
7453 drv->if_indices = drv->default_if_indices;
7454 else
7455 drv->if_indices = old;
7456 wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
7457 "interfaces");
7458 wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
7459 return;
7460 } else if (!old)
7461 os_memcpy(drv->if_indices, drv->default_if_indices,
7462 sizeof(drv->default_if_indices));
7463 drv->if_indices[drv->num_if_indices] = ifidx;
7464 drv->num_if_indices++;
7465}
7466
7467
7468static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
7469{
7470 int i;
7471
7472 for (i = 0; i < drv->num_if_indices; i++) {
7473 if (drv->if_indices[i] == ifidx) {
7474 drv->if_indices[i] = 0;
7475 break;
7476 }
7477 }
7478}
7479
7480
7481static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
7482{
7483 int i;
7484
7485 for (i = 0; i < drv->num_if_indices; i++)
7486 if (drv->if_indices[i] == ifidx)
7487 return 1;
7488
7489 return 0;
7490}
7491
7492
7493static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
7494 const char *bridge_ifname)
7495{
7496 struct i802_bss *bss = priv;
7497 struct wpa_driver_nl80211_data *drv = bss->drv;
7498 char name[IFNAMSIZ + 1];
7499
7500 os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
7501 wpa_printf(MSG_DEBUG, "nl80211: Set WDS STA addr=" MACSTR
7502 " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
7503 if (val) {
7504 if (!if_nametoindex(name)) {
7505 if (nl80211_create_iface(drv, name,
7506 NL80211_IFTYPE_AP_VLAN,
7507 NULL, 1) < 0)
7508 return -1;
7509 if (bridge_ifname &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007510 linux_br_add_if(drv->global->ioctl_sock,
7511 bridge_ifname, name) < 0)
Jouni Malinen75ecf522011-06-27 15:19:46 -07007512 return -1;
7513 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007514 linux_set_iface_flags(drv->global->ioctl_sock, name, 1);
Jouni Malinen75ecf522011-06-27 15:19:46 -07007515 return i802_set_sta_vlan(priv, addr, name, 0);
7516 } else {
7517 i802_set_sta_vlan(priv, addr, bss->ifname, 0);
7518 return wpa_driver_nl80211_if_remove(priv, WPA_IF_AP_VLAN,
7519 name);
7520 }
7521}
7522
7523
7524static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
7525{
7526 struct wpa_driver_nl80211_data *drv = eloop_ctx;
7527 struct sockaddr_ll lladdr;
7528 unsigned char buf[3000];
7529 int len;
7530 socklen_t fromlen = sizeof(lladdr);
7531
7532 len = recvfrom(sock, buf, sizeof(buf), 0,
7533 (struct sockaddr *)&lladdr, &fromlen);
7534 if (len < 0) {
7535 perror("recv");
7536 return;
7537 }
7538
7539 if (have_ifidx(drv, lladdr.sll_ifindex))
7540 drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
7541}
7542
7543
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007544static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
7545 struct i802_bss *bss,
7546 const char *brname, const char *ifname)
7547{
7548 int ifindex;
7549 char in_br[IFNAMSIZ];
7550
7551 os_strlcpy(bss->brname, brname, IFNAMSIZ);
7552 ifindex = if_nametoindex(brname);
7553 if (ifindex == 0) {
7554 /*
7555 * Bridge was configured, but the bridge device does
7556 * not exist. Try to add it now.
7557 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007558 if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007559 wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
7560 "bridge interface %s: %s",
7561 brname, strerror(errno));
7562 return -1;
7563 }
7564 bss->added_bridge = 1;
7565 add_ifidx(drv, if_nametoindex(brname));
7566 }
7567
7568 if (linux_br_get(in_br, ifname) == 0) {
7569 if (os_strcmp(in_br, brname) == 0)
7570 return 0; /* already in the bridge */
7571
7572 wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
7573 "bridge %s", ifname, in_br);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007574 if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
7575 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007576 wpa_printf(MSG_ERROR, "nl80211: Failed to "
7577 "remove interface %s from bridge "
7578 "%s: %s",
7579 ifname, brname, strerror(errno));
7580 return -1;
7581 }
7582 }
7583
7584 wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
7585 ifname, brname);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007586 if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007587 wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
7588 "into bridge %s: %s",
7589 ifname, brname, strerror(errno));
7590 return -1;
7591 }
7592 bss->added_if_into_bridge = 1;
7593
7594 return 0;
7595}
7596
7597
7598static void *i802_init(struct hostapd_data *hapd,
7599 struct wpa_init_params *params)
7600{
7601 struct wpa_driver_nl80211_data *drv;
7602 struct i802_bss *bss;
7603 size_t i;
7604 char brname[IFNAMSIZ];
7605 int ifindex, br_ifindex;
7606 int br_added = 0;
7607
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007608 bss = wpa_driver_nl80211_init(hapd, params->ifname,
7609 params->global_priv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007610 if (bss == NULL)
7611 return NULL;
7612
7613 drv = bss->drv;
7614 drv->nlmode = NL80211_IFTYPE_AP;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007615 drv->eapol_sock = -1;
7616
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007617 if (linux_br_get(brname, params->ifname) == 0) {
7618 wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
7619 params->ifname, brname);
7620 br_ifindex = if_nametoindex(brname);
7621 } else {
7622 brname[0] = '\0';
7623 br_ifindex = 0;
7624 }
7625
7626 drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
7627 drv->if_indices = drv->default_if_indices;
7628 for (i = 0; i < params->num_bridge; i++) {
7629 if (params->bridge[i]) {
7630 ifindex = if_nametoindex(params->bridge[i]);
7631 if (ifindex)
7632 add_ifidx(drv, ifindex);
7633 if (ifindex == br_ifindex)
7634 br_added = 1;
7635 }
7636 }
7637 if (!br_added && br_ifindex &&
7638 (params->num_bridge == 0 || !params->bridge[0]))
7639 add_ifidx(drv, br_ifindex);
7640
7641 /* start listening for EAPOL on the default AP interface */
7642 add_ifidx(drv, drv->ifindex);
7643
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007644 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007645 goto failed;
7646
7647 if (params->bssid) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007648 if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007649 params->bssid))
7650 goto failed;
7651 }
7652
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007653 if (wpa_driver_nl80211_set_mode(bss, drv->nlmode)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007654 wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s "
7655 "into AP mode", bss->ifname);
7656 goto failed;
7657 }
7658
7659 if (params->num_bridge && params->bridge[0] &&
7660 i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)
7661 goto failed;
7662
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007663 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007664 goto failed;
7665
7666 drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
7667 if (drv->eapol_sock < 0) {
7668 perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)");
7669 goto failed;
7670 }
7671
7672 if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
7673 {
7674 printf("Could not register read socket for eapol\n");
7675 goto failed;
7676 }
7677
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007678 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
7679 params->own_addr))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007680 goto failed;
7681
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007682 memcpy(bss->addr, params->own_addr, ETH_ALEN);
7683
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007684 return bss;
7685
7686failed:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007687 wpa_driver_nl80211_deinit(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007688 return NULL;
7689}
7690
7691
7692static void i802_deinit(void *priv)
7693{
7694 wpa_driver_nl80211_deinit(priv);
7695}
7696
7697#endif /* HOSTAPD */
7698
7699
7700static enum nl80211_iftype wpa_driver_nl80211_if_type(
7701 enum wpa_driver_if_type type)
7702{
7703 switch (type) {
7704 case WPA_IF_STATION:
7705 return NL80211_IFTYPE_STATION;
7706 case WPA_IF_P2P_CLIENT:
7707 case WPA_IF_P2P_GROUP:
7708 return NL80211_IFTYPE_P2P_CLIENT;
7709 case WPA_IF_AP_VLAN:
7710 return NL80211_IFTYPE_AP_VLAN;
7711 case WPA_IF_AP_BSS:
7712 return NL80211_IFTYPE_AP;
7713 case WPA_IF_P2P_GO:
7714 return NL80211_IFTYPE_P2P_GO;
7715 }
7716 return -1;
7717}
7718
7719
7720#ifdef CONFIG_P2P
7721
7722static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr)
7723{
7724 struct wpa_driver_nl80211_data *drv;
7725 dl_list_for_each(drv, &global->interfaces,
7726 struct wpa_driver_nl80211_data, list) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007727 if (os_memcmp(addr, drv->first_bss.addr, ETH_ALEN) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007728 return 1;
7729 }
7730 return 0;
7731}
7732
7733
7734static int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv,
7735 u8 *new_addr)
7736{
7737 unsigned int idx;
7738
7739 if (!drv->global)
7740 return -1;
7741
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007742 os_memcpy(new_addr, drv->first_bss.addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007743 for (idx = 0; idx < 64; idx++) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007744 new_addr[0] = drv->first_bss.addr[0] | 0x02;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007745 new_addr[0] ^= idx << 2;
7746 if (!nl80211_addr_in_use(drv->global, new_addr))
7747 break;
7748 }
7749 if (idx == 64)
7750 return -1;
7751
7752 wpa_printf(MSG_DEBUG, "nl80211: Assigned new P2P Interface Address "
7753 MACSTR, MAC2STR(new_addr));
7754
7755 return 0;
7756}
7757
7758#endif /* CONFIG_P2P */
7759
7760
7761static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
7762 const char *ifname, const u8 *addr,
7763 void *bss_ctx, void **drv_priv,
7764 char *force_ifname, u8 *if_addr,
7765 const char *bridge)
7766{
7767 struct i802_bss *bss = priv;
7768 struct wpa_driver_nl80211_data *drv = bss->drv;
7769 int ifidx;
7770#ifdef HOSTAPD
7771 struct i802_bss *new_bss = NULL;
7772
7773 if (type == WPA_IF_AP_BSS) {
7774 new_bss = os_zalloc(sizeof(*new_bss));
7775 if (new_bss == NULL)
7776 return -1;
7777 }
7778#endif /* HOSTAPD */
7779
7780 if (addr)
7781 os_memcpy(if_addr, addr, ETH_ALEN);
7782 ifidx = nl80211_create_iface(drv, ifname,
7783 wpa_driver_nl80211_if_type(type), addr,
7784 0);
7785 if (ifidx < 0) {
7786#ifdef HOSTAPD
7787 os_free(new_bss);
7788#endif /* HOSTAPD */
7789 return -1;
7790 }
7791
7792 if (!addr &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007793 linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
7794 if_addr) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007795 nl80211_remove_iface(drv, ifidx);
7796 return -1;
7797 }
7798
7799#ifdef CONFIG_P2P
7800 if (!addr &&
7801 (type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP ||
7802 type == WPA_IF_P2P_GO)) {
7803 /* Enforce unique P2P Interface Address */
7804 u8 new_addr[ETH_ALEN], own_addr[ETH_ALEN];
7805
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007806 if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
7807 own_addr) < 0 ||
7808 linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
7809 new_addr) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007810 nl80211_remove_iface(drv, ifidx);
7811 return -1;
7812 }
7813 if (os_memcmp(own_addr, new_addr, ETH_ALEN) == 0) {
7814 wpa_printf(MSG_DEBUG, "nl80211: Allocate new address "
7815 "for P2P group interface");
7816 if (nl80211_p2p_interface_addr(drv, new_addr) < 0) {
7817 nl80211_remove_iface(drv, ifidx);
7818 return -1;
7819 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007820 if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007821 new_addr) < 0) {
7822 nl80211_remove_iface(drv, ifidx);
7823 return -1;
7824 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007825 }
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07007826 os_memcpy(if_addr, new_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007827 }
7828#endif /* CONFIG_P2P */
7829
7830#ifdef HOSTAPD
7831 if (bridge &&
7832 i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
7833 wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
7834 "interface %s to a bridge %s", ifname, bridge);
7835 nl80211_remove_iface(drv, ifidx);
7836 os_free(new_bss);
7837 return -1;
7838 }
7839
7840 if (type == WPA_IF_AP_BSS) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007841 if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
7842 {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007843 nl80211_remove_iface(drv, ifidx);
7844 os_free(new_bss);
7845 return -1;
7846 }
7847 os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007848 os_memcpy(new_bss->addr, if_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007849 new_bss->ifindex = ifidx;
7850 new_bss->drv = drv;
7851 new_bss->next = drv->first_bss.next;
7852 drv->first_bss.next = new_bss;
7853 if (drv_priv)
7854 *drv_priv = new_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007855 nl80211_init_bss(new_bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007856 }
7857#endif /* HOSTAPD */
7858
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007859 if (drv->global)
7860 drv->global->if_add_ifindex = ifidx;
7861
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007862 return 0;
7863}
7864
7865
7866static int wpa_driver_nl80211_if_remove(void *priv,
7867 enum wpa_driver_if_type type,
7868 const char *ifname)
7869{
7870 struct i802_bss *bss = priv;
7871 struct wpa_driver_nl80211_data *drv = bss->drv;
7872 int ifindex = if_nametoindex(ifname);
7873
7874 wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d",
7875 __func__, type, ifname, ifindex);
7876 if (ifindex <= 0)
7877 return -1;
7878
7879#ifdef HOSTAPD
7880 if (bss->added_if_into_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007881 if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
7882 bss->ifname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007883 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
7884 "interface %s from bridge %s: %s",
7885 bss->ifname, bss->brname, strerror(errno));
7886 }
7887 if (bss->added_bridge) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007888 if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007889 wpa_printf(MSG_INFO, "nl80211: Failed to remove "
7890 "bridge %s: %s",
7891 bss->brname, strerror(errno));
7892 }
7893#endif /* HOSTAPD */
7894
7895 nl80211_remove_iface(drv, ifindex);
7896
7897#ifdef HOSTAPD
7898 if (type != WPA_IF_AP_BSS)
7899 return 0;
7900
7901 if (bss != &drv->first_bss) {
7902 struct i802_bss *tbss;
7903
7904 for (tbss = &drv->first_bss; tbss; tbss = tbss->next) {
7905 if (tbss->next == bss) {
7906 tbss->next = bss->next;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007907 nl80211_destroy_bss(bss);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007908 os_free(bss);
7909 bss = NULL;
7910 break;
7911 }
7912 }
7913 if (bss)
7914 wpa_printf(MSG_INFO, "nl80211: %s - could not find "
7915 "BSS %p in the list", __func__, bss);
7916 }
7917#endif /* HOSTAPD */
7918
7919 return 0;
7920}
7921
7922
7923static int cookie_handler(struct nl_msg *msg, void *arg)
7924{
7925 struct nlattr *tb[NL80211_ATTR_MAX + 1];
7926 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
7927 u64 *cookie = arg;
7928 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7929 genlmsg_attrlen(gnlh, 0), NULL);
7930 if (tb[NL80211_ATTR_COOKIE])
7931 *cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
7932 return NL_SKIP;
7933}
7934
7935
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007936static int nl80211_send_frame_cmd(struct i802_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007937 unsigned int freq, unsigned int wait,
7938 const u8 *buf, size_t buf_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007939 u64 *cookie_out, int no_cck, int no_ack,
7940 int offchanok)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007941{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007942 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007943 struct nl_msg *msg;
7944 u64 cookie;
7945 int ret = -1;
7946
7947 msg = nlmsg_alloc();
7948 if (!msg)
7949 return -1;
7950
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007951 nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007952
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007953 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007954 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007955#ifndef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07007956 if (wait)
7957 NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
7958#endif
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007959 if (offchanok)
7960 NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
7961 if (no_cck)
7962 NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
7963 if (no_ack)
7964 NLA_PUT_FLAG(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK);
7965
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007966 NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);
7967
7968 cookie = 0;
7969 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
7970 msg = NULL;
7971 if (ret) {
7972 wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d "
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07007973 "(%s) (freq=%u wait=%u)", ret, strerror(-ret),
7974 freq, wait);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007975 goto nla_put_failure;
7976 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007977 wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted%s; "
7978 "cookie 0x%llx", no_ack ? " (no ACK)" : "",
7979 (long long unsigned int) cookie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007980
7981 if (cookie_out)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007982 *cookie_out = no_ack ? (u64) -1 : cookie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007983
7984nla_put_failure:
7985 nlmsg_free(msg);
7986 return ret;
7987}
7988
7989
7990static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq,
7991 unsigned int wait_time,
7992 const u8 *dst, const u8 *src,
7993 const u8 *bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007994 const u8 *data, size_t data_len,
7995 int no_cck)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007996{
7997 struct i802_bss *bss = priv;
7998 struct wpa_driver_nl80211_data *drv = bss->drv;
7999 int ret = -1;
8000 u8 *buf;
8001 struct ieee80211_hdr *hdr;
8002
8003 wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008004 "wait=%d ms no_cck=%d)", drv->ifindex, wait_time, no_cck);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008005
8006 buf = os_zalloc(24 + data_len);
8007 if (buf == NULL)
8008 return ret;
8009 os_memcpy(buf + 24, data, data_len);
8010 hdr = (struct ieee80211_hdr *) buf;
8011 hdr->frame_control =
8012 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION);
8013 os_memcpy(hdr->addr1, dst, ETH_ALEN);
8014 os_memcpy(hdr->addr2, src, ETH_ALEN);
8015 os_memcpy(hdr->addr3, bssid, ETH_ALEN);
8016
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008017 if (is_ap_interface(drv->nlmode))
8018 ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len,
8019 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008020 else
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008021 ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008022 24 + data_len,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008023 &drv->send_action_cookie,
8024 no_cck, 0, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008025
8026 os_free(buf);
8027 return ret;
8028}
8029
8030
8031static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
8032{
8033 struct i802_bss *bss = priv;
8034 struct wpa_driver_nl80211_data *drv = bss->drv;
8035 struct nl_msg *msg;
8036 int ret;
8037
8038 msg = nlmsg_alloc();
8039 if (!msg)
8040 return;
8041
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008042 nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008043
8044 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8045 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);
8046
8047 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8048 msg = NULL;
8049 if (ret)
8050 wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d "
8051 "(%s)", ret, strerror(-ret));
8052
8053 nla_put_failure:
8054 nlmsg_free(msg);
8055}
8056
8057
8058static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
8059 unsigned int duration)
8060{
8061 struct i802_bss *bss = priv;
8062 struct wpa_driver_nl80211_data *drv = bss->drv;
8063 struct nl_msg *msg;
8064 int ret;
8065 u64 cookie;
8066
8067 msg = nlmsg_alloc();
8068 if (!msg)
8069 return -1;
8070
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008071 nl80211_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008072
8073 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8074 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
8075 NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);
8076
8077 cookie = 0;
8078 ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008079 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008080 if (ret == 0) {
8081 wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
8082 "0x%llx for freq=%u MHz duration=%u",
8083 (long long unsigned int) cookie, freq, duration);
8084 drv->remain_on_chan_cookie = cookie;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008085 drv->pending_remain_on_chan = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008086 return 0;
8087 }
8088 wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel "
8089 "(freq=%d duration=%u): %d (%s)",
8090 freq, duration, ret, strerror(-ret));
8091nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008092 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008093 return -1;
8094}
8095
8096
8097static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
8098{
8099 struct i802_bss *bss = priv;
8100 struct wpa_driver_nl80211_data *drv = bss->drv;
8101 struct nl_msg *msg;
8102 int ret;
8103
8104 if (!drv->pending_remain_on_chan) {
8105 wpa_printf(MSG_DEBUG, "nl80211: No pending remain-on-channel "
8106 "to cancel");
8107 return -1;
8108 }
8109
8110 wpa_printf(MSG_DEBUG, "nl80211: Cancel remain-on-channel with cookie "
8111 "0x%llx",
8112 (long long unsigned int) drv->remain_on_chan_cookie);
8113
8114 msg = nlmsg_alloc();
8115 if (!msg)
8116 return -1;
8117
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008118 nl80211_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008119
8120 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8121 NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);
8122
8123 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008124 msg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008125 if (ret == 0)
8126 return 0;
8127 wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
8128 "%d (%s)", ret, strerror(-ret));
8129nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008130 nlmsg_free(msg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008131 return -1;
8132}
8133
8134
8135static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
8136{
8137 struct i802_bss *bss = priv;
8138 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07008139
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008140 if (!report) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008141 if (bss->nl_preq && drv->device_ap_sme &&
8142 is_ap_interface(drv->nlmode)) {
8143 /*
8144 * Do not disable Probe Request reporting that was
8145 * enabled in nl80211_setup_ap().
8146 */
8147 wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of "
8148 "Probe Request reporting nl_preq=%p while "
8149 "in AP mode", bss->nl_preq);
8150 } else if (bss->nl_preq) {
8151 wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
8152 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008153 eloop_unregister_read_sock(
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008154 nl_socket_get_fd(bss->nl_preq));
8155 nl_destroy_handles(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008156 }
8157 return 0;
8158 }
8159
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008160 if (bss->nl_preq) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008161 wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008162 "already on! nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008163 return 0;
8164 }
8165
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008166 bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq");
8167 if (bss->nl_preq == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008168 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008169 wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request "
8170 "reporting nl_preq=%p", bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008171
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008172 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008173 (WLAN_FC_TYPE_MGMT << 2) |
8174 (WLAN_FC_STYPE_PROBE_REQ << 4),
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008175 NULL, 0) < 0)
8176 goto out_err;
8177#ifdef ANDROID_P2P
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008178 if (drv->nlmode != NL80211_IFTYPE_AP &&
8179 drv->nlmode != NL80211_IFTYPE_P2P_GO) {
8180 wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only "
8181 "allowed in AP or P2P GO mode (iftype=%d)",
8182 drv->nlmode);
8183 goto done;
8184 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008185 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008186 (WLAN_FC_TYPE_MGMT << 2) |
8187 (WLAN_FC_STYPE_ASSOC_REQ << 4),
8188 NULL, 0) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008189 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008190 }
8191
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008192 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008193 (WLAN_FC_TYPE_MGMT << 2) |
8194 (WLAN_FC_STYPE_REASSOC_REQ << 4),
8195 NULL, 0) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008196 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008197 }
8198
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008199 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008200 (WLAN_FC_TYPE_MGMT << 2) |
8201 (WLAN_FC_STYPE_DISASSOC << 4),
8202 NULL, 0) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008203 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008204 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008205
8206 if (nl80211_register_frame(bss, bss->nl_preq,
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008207 (WLAN_FC_TYPE_MGMT << 2) |
8208 (WLAN_FC_STYPE_DEAUTH << 4),
8209 NULL, 0) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008210 goto out_err;
8211 }
8212
8213 if (nl80211_register_frame(bss, bss->nl_preq,
8214 (WLAN_FC_TYPE_MGMT << 2) |
8215 (WLAN_FC_STYPE_ACTION << 4),
8216 NULL, 0) < 0) {
8217 goto out_err;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07008218 }
8219
8220done:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008221#endif /* ANDROID_P2P */
8222 eloop_register_read_sock(nl_socket_get_fd(bss->nl_preq),
8223 wpa_driver_nl80211_event_receive, bss->nl_cb,
8224 bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008225
8226 return 0;
8227
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008228 out_err:
8229 nl_destroy_handles(&bss->nl_preq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008230 return -1;
8231}
8232
8233
8234static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
8235 int ifindex, int disabled)
8236{
8237 struct nl_msg *msg;
8238 struct nlattr *bands, *band;
8239 int ret;
8240
8241 msg = nlmsg_alloc();
8242 if (!msg)
8243 return -1;
8244
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008245 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_TX_BITRATE_MASK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008246 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
8247
8248 bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
8249 if (!bands)
8250 goto nla_put_failure;
8251
8252 /*
8253 * Disable 2 GHz rates 1, 2, 5.5, 11 Mbps by masking out everything
8254 * else apart from 6, 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS
8255 * rates. All 5 GHz rates are left enabled.
8256 */
8257 band = nla_nest_start(msg, NL80211_BAND_2GHZ);
8258 if (!band)
8259 goto nla_put_failure;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008260 if (disabled) {
8261 NLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,
8262 "\x0c\x12\x18\x24\x30\x48\x60\x6c");
8263 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008264 nla_nest_end(msg, band);
8265
8266 nla_nest_end(msg, bands);
8267
8268 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
8269 msg = NULL;
8270 if (ret) {
8271 wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
8272 "(%s)", ret, strerror(-ret));
8273 }
8274
8275 return ret;
8276
8277nla_put_failure:
8278 nlmsg_free(msg);
8279 return -1;
8280}
8281
8282
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008283static int wpa_driver_nl80211_deinit_ap(void *priv)
8284{
8285 struct i802_bss *bss = priv;
8286 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008287 if (!is_ap_interface(drv->nlmode))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008288 return -1;
8289 wpa_driver_nl80211_del_beacon(drv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008290 return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008291}
8292
8293
8294static void wpa_driver_nl80211_resume(void *priv)
8295{
8296 struct i802_bss *bss = priv;
8297 struct wpa_driver_nl80211_data *drv = bss->drv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008298 if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008299 wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on "
8300 "resume event");
8301 }
8302}
8303
8304
8305static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
8306 const u8 *ies, size_t ies_len)
8307{
8308 struct i802_bss *bss = priv;
8309 struct wpa_driver_nl80211_data *drv = bss->drv;
8310 int ret;
8311 u8 *data, *pos;
8312 size_t data_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008313 const u8 *own_addr = bss->addr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008314
8315 if (action != 1) {
8316 wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action "
8317 "action %d", action);
8318 return -1;
8319 }
8320
8321 /*
8322 * Action frame payload:
8323 * Category[1] = 6 (Fast BSS Transition)
8324 * Action[1] = 1 (Fast BSS Transition Request)
8325 * STA Address
8326 * Target AP Address
8327 * FT IEs
8328 */
8329
8330 data_len = 2 + 2 * ETH_ALEN + ies_len;
8331 data = os_malloc(data_len);
8332 if (data == NULL)
8333 return -1;
8334 pos = data;
8335 *pos++ = 0x06; /* FT Action category */
8336 *pos++ = action;
8337 os_memcpy(pos, own_addr, ETH_ALEN);
8338 pos += ETH_ALEN;
8339 os_memcpy(pos, target_ap, ETH_ALEN);
8340 pos += ETH_ALEN;
8341 os_memcpy(pos, ies, ies_len);
8342
8343 ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0,
8344 drv->bssid, own_addr, drv->bssid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008345 data, data_len, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008346 os_free(data);
8347
8348 return ret;
8349}
8350
8351
8352static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
8353{
8354 struct i802_bss *bss = priv;
8355 struct wpa_driver_nl80211_data *drv = bss->drv;
8356 struct nl_msg *msg, *cqm = NULL;
8357
8358 wpa_printf(MSG_DEBUG, "nl80211: Signal monitor threshold=%d "
8359 "hysteresis=%d", threshold, hysteresis);
8360
8361 msg = nlmsg_alloc();
8362 if (!msg)
8363 return -1;
8364
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008365 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_CQM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008366
8367 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
8368
8369 cqm = nlmsg_alloc();
8370 if (cqm == NULL)
8371 return -1;
8372
8373 NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, threshold);
8374 NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hysteresis);
8375 nla_put_nested(msg, NL80211_ATTR_CQM, cqm);
8376
8377 if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
8378 return 0;
8379 msg = NULL;
8380
8381nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008382 nlmsg_free(cqm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008383 nlmsg_free(msg);
8384 return -1;
8385}
8386
8387
8388static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
8389{
8390 struct i802_bss *bss = priv;
8391 struct wpa_driver_nl80211_data *drv = bss->drv;
8392 int res;
8393
8394 os_memset(si, 0, sizeof(*si));
8395 res = nl80211_get_link_signal(drv, si);
8396 if (res != 0)
8397 return res;
8398
8399 return nl80211_get_link_noise(drv, si);
8400}
8401
8402
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008403static int wpa_driver_nl80211_shared_freq(void *priv)
8404{
8405 struct i802_bss *bss = priv;
8406 struct wpa_driver_nl80211_data *drv = bss->drv;
8407 struct wpa_driver_nl80211_data *driver;
8408 int freq = 0;
8409
8410 /*
8411 * If the same PHY is in connected state with some other interface,
8412 * then retrieve the assoc freq.
8413 */
8414 wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s",
8415 drv->phyname);
8416
8417 dl_list_for_each(driver, &drv->global->interfaces,
8418 struct wpa_driver_nl80211_data, list) {
8419 if (drv == driver ||
8420 os_strcmp(drv->phyname, driver->phyname) != 0 ||
8421#ifdef ANDROID_P2P
8422 (!driver->associated && !is_ap_interface(driver->nlmode)))
8423#else
8424 !driver->associated)
8425#endif
8426 continue;
8427
8428 wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
8429 MACSTR,
8430 driver->phyname, driver->first_bss.ifname,
8431 MAC2STR(driver->first_bss.addr));
8432#ifdef ANDROID_P2P
8433 if(is_ap_interface(driver->nlmode))
8434 freq = driver->first_bss.freq;
8435 else
8436#endif
8437 freq = nl80211_get_assoc_freq(driver);
8438 wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
8439 drv->phyname, freq);
8440 }
8441
8442 if (!freq)
8443 wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
8444 "PHY (%s) in associated state", drv->phyname);
8445
8446 return freq;
8447}
8448
8449
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008450static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
8451 int encrypt)
8452{
8453 struct i802_bss *bss = priv;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008454 return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008455}
8456
8457
8458static int nl80211_set_param(void *priv, const char *param)
8459{
8460 wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
8461 if (param == NULL)
8462 return 0;
8463
8464#ifdef CONFIG_P2P
8465 if (os_strstr(param, "use_p2p_group_interface=1")) {
8466 struct i802_bss *bss = priv;
8467 struct wpa_driver_nl80211_data *drv = bss->drv;
8468
8469 wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
8470 "interface");
8471 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
8472 drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
8473 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008474#ifdef ANDROID_P2P
8475 if(os_strstr(param, "use_multi_chan_concurrent=1")) {
8476 struct i802_bss *bss = priv;
8477 struct wpa_driver_nl80211_data *drv = bss->drv;
8478 wpa_printf(MSG_DEBUG, "nl80211: Use Multi channel "
8479 "concurrency");
8480 drv->capa.flags |= WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT;
8481 }
8482#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008483#endif /* CONFIG_P2P */
8484
8485 return 0;
8486}
8487
8488
8489static void * nl80211_global_init(void)
8490{
8491 struct nl80211_global *global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008492 struct netlink_config *cfg;
8493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008494 global = os_zalloc(sizeof(*global));
8495 if (global == NULL)
8496 return NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008497 global->ioctl_sock = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008498 dl_list_init(&global->interfaces);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008499 global->if_add_ifindex = -1;
8500
8501 cfg = os_zalloc(sizeof(*cfg));
8502 if (cfg == NULL)
8503 goto err;
8504
8505 cfg->ctx = global;
8506 cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
8507 cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
8508 global->netlink = netlink_init(cfg);
8509 if (global->netlink == NULL) {
8510 os_free(cfg);
8511 goto err;
8512 }
8513
8514 if (wpa_driver_nl80211_init_nl_global(global) < 0)
8515 goto err;
8516
8517 global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
8518 if (global->ioctl_sock < 0) {
8519 perror("socket(PF_INET,SOCK_DGRAM)");
8520 goto err;
8521 }
8522
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008523 return global;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008524
8525err:
8526 nl80211_global_deinit(global);
8527 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008528}
8529
8530
8531static void nl80211_global_deinit(void *priv)
8532{
8533 struct nl80211_global *global = priv;
8534 if (global == NULL)
8535 return;
8536 if (!dl_list_empty(&global->interfaces)) {
8537 wpa_printf(MSG_ERROR, "nl80211: %u interface(s) remain at "
8538 "nl80211_global_deinit",
8539 dl_list_len(&global->interfaces));
8540 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008541
8542 if (global->netlink)
8543 netlink_deinit(global->netlink);
8544
8545 nl_destroy_handles(&global->nl);
8546
8547 if (global->nl_event) {
8548 eloop_unregister_read_sock(
8549 nl_socket_get_fd(global->nl_event));
8550 nl_destroy_handles(&global->nl_event);
8551 }
8552
8553 nl_cb_put(global->nl_cb);
8554
8555 if (global->ioctl_sock >= 0)
8556 close(global->ioctl_sock);
8557
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008558 os_free(global);
8559}
8560
8561
8562static const char * nl80211_get_radio_name(void *priv)
8563{
8564 struct i802_bss *bss = priv;
8565 struct wpa_driver_nl80211_data *drv = bss->drv;
8566 return drv->phyname;
8567}
8568
8569
Jouni Malinen75ecf522011-06-27 15:19:46 -07008570static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,
8571 const u8 *pmkid)
8572{
8573 struct nl_msg *msg;
8574
8575 msg = nlmsg_alloc();
8576 if (!msg)
8577 return -ENOMEM;
8578
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008579 nl80211_cmd(bss->drv, msg, 0, cmd);
Jouni Malinen75ecf522011-06-27 15:19:46 -07008580
8581 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
8582 if (pmkid)
8583 NLA_PUT(msg, NL80211_ATTR_PMKID, 16, pmkid);
8584 if (bssid)
8585 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
8586
8587 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
8588 nla_put_failure:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008589 nlmsg_free(msg);
Jouni Malinen75ecf522011-06-27 15:19:46 -07008590 return -ENOBUFS;
8591}
8592
8593
8594static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
8595{
8596 struct i802_bss *bss = priv;
8597 wpa_printf(MSG_DEBUG, "nl80211: Add PMKID for " MACSTR, MAC2STR(bssid));
8598 return nl80211_pmkid(bss, NL80211_CMD_SET_PMKSA, bssid, pmkid);
8599}
8600
8601
8602static int nl80211_remove_pmkid(void *priv, const u8 *bssid, const u8 *pmkid)
8603{
8604 struct i802_bss *bss = priv;
8605 wpa_printf(MSG_DEBUG, "nl80211: Delete PMKID for " MACSTR,
8606 MAC2STR(bssid));
8607 return nl80211_pmkid(bss, NL80211_CMD_DEL_PMKSA, bssid, pmkid);
8608}
8609
8610
8611static int nl80211_flush_pmkid(void *priv)
8612{
8613 struct i802_bss *bss = priv;
8614 wpa_printf(MSG_DEBUG, "nl80211: Flush PMKIDs");
8615 return nl80211_pmkid(bss, NL80211_CMD_FLUSH_PMKSA, NULL, NULL);
8616}
8617
8618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008619static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
8620 const u8 *replay_ctr)
8621{
8622 struct i802_bss *bss = priv;
8623 struct wpa_driver_nl80211_data *drv = bss->drv;
8624 struct nlattr *replay_nested;
8625 struct nl_msg *msg;
8626
8627 msg = nlmsg_alloc();
8628 if (!msg)
8629 return;
8630
8631 nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
8632
8633 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
8634
8635 replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
8636 if (!replay_nested)
8637 goto nla_put_failure;
8638
8639 NLA_PUT(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek);
8640 NLA_PUT(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck);
8641 NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
8642 replay_ctr);
8643
8644 nla_nest_end(msg, replay_nested);
8645
8646 send_and_recv_msgs(drv, msg, NULL, NULL);
8647 return;
8648 nla_put_failure:
8649 nlmsg_free(msg);
8650}
8651
8652
8653static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
8654 const u8 *addr, int qos)
8655{
8656 /* send data frame to poll STA and check whether
8657 * this frame is ACKed */
8658 struct {
8659 struct ieee80211_hdr hdr;
8660 u16 qos_ctl;
8661 } STRUCT_PACKED nulldata;
8662 size_t size;
8663
8664 /* Send data frame to poll STA and check whether this frame is ACKed */
8665
8666 os_memset(&nulldata, 0, sizeof(nulldata));
8667
8668 if (qos) {
8669 nulldata.hdr.frame_control =
8670 IEEE80211_FC(WLAN_FC_TYPE_DATA,
8671 WLAN_FC_STYPE_QOS_NULL);
8672 size = sizeof(nulldata);
8673 } else {
8674 nulldata.hdr.frame_control =
8675 IEEE80211_FC(WLAN_FC_TYPE_DATA,
8676 WLAN_FC_STYPE_NULLFUNC);
8677 size = sizeof(struct ieee80211_hdr);
8678 }
8679
8680 nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
8681 os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
8682 os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
8683 os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
8684
8685 if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0) < 0)
8686 wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
8687 "send poll frame");
8688}
8689
8690static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
8691 int qos)
8692{
8693 struct i802_bss *bss = priv;
8694 struct wpa_driver_nl80211_data *drv = bss->drv;
8695 struct nl_msg *msg;
8696
8697 if (!drv->poll_command_supported) {
8698 nl80211_send_null_frame(bss, own_addr, addr, qos);
8699 return;
8700 }
8701
8702 msg = nlmsg_alloc();
8703 if (!msg)
8704 return;
8705
8706 nl80211_cmd(drv, msg, 0, NL80211_CMD_PROBE_CLIENT);
8707
8708 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
8709 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
8710
8711 send_and_recv_msgs(drv, msg, NULL, NULL);
8712 return;
8713 nla_put_failure:
8714 nlmsg_free(msg);
8715}
8716
8717
8718static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
8719{
8720 struct nl_msg *msg;
8721
8722 msg = nlmsg_alloc();
8723 if (!msg)
8724 return -ENOMEM;
8725
8726 nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_SET_POWER_SAVE);
8727 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
8728 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE,
8729 enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);
8730 return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
8731nla_put_failure:
8732 nlmsg_free(msg);
8733 return -ENOBUFS;
8734}
8735
8736
8737static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,
8738 int ctwindow)
8739{
8740 struct i802_bss *bss = priv;
8741
8742 wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d "
8743 "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow);
8744
8745 if (opp_ps != -1 || ctwindow != -1)
8746 return -1; /* Not yet supported */
8747
8748 if (legacy_ps == -1)
8749 return 0;
8750 if (legacy_ps != 0 && legacy_ps != 1)
8751 return -1; /* Not yet supported */
8752
8753 return nl80211_set_power_save(bss, legacy_ps);
8754}
8755
8756
8757#ifdef CONFIG_TDLS
8758
8759static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
8760 u8 dialog_token, u16 status_code,
8761 const u8 *buf, size_t len)
8762{
8763 struct i802_bss *bss = priv;
8764 struct wpa_driver_nl80211_data *drv = bss->drv;
8765 struct nl_msg *msg;
8766
8767 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
8768 return -EOPNOTSUPP;
8769
8770 if (!dst)
8771 return -EINVAL;
8772
8773 msg = nlmsg_alloc();
8774 if (!msg)
8775 return -ENOMEM;
8776
8777 nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_MGMT);
8778 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8779 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
8780 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code);
8781 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token);
8782 NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code);
8783 NLA_PUT(msg, NL80211_ATTR_IE, len, buf);
8784
8785 return send_and_recv_msgs(drv, msg, NULL, NULL);
8786
8787nla_put_failure:
8788 nlmsg_free(msg);
8789 return -ENOBUFS;
8790}
8791
8792
8793static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
8794{
8795 struct i802_bss *bss = priv;
8796 struct wpa_driver_nl80211_data *drv = bss->drv;
8797 struct nl_msg *msg;
8798 enum nl80211_tdls_operation nl80211_oper;
8799
8800 if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
8801 return -EOPNOTSUPP;
8802
8803 switch (oper) {
8804 case TDLS_DISCOVERY_REQ:
8805 nl80211_oper = NL80211_TDLS_DISCOVERY_REQ;
8806 break;
8807 case TDLS_SETUP:
8808 nl80211_oper = NL80211_TDLS_SETUP;
8809 break;
8810 case TDLS_TEARDOWN:
8811 nl80211_oper = NL80211_TDLS_TEARDOWN;
8812 break;
8813 case TDLS_ENABLE_LINK:
8814 nl80211_oper = NL80211_TDLS_ENABLE_LINK;
8815 break;
8816 case TDLS_DISABLE_LINK:
8817 nl80211_oper = NL80211_TDLS_DISABLE_LINK;
8818 break;
8819 case TDLS_ENABLE:
8820 return 0;
8821 case TDLS_DISABLE:
8822 return 0;
8823 default:
8824 return -EINVAL;
8825 }
8826
8827 msg = nlmsg_alloc();
8828 if (!msg)
8829 return -ENOMEM;
8830
8831 nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_OPER);
8832 NLA_PUT_U8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper);
8833 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
8834 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer);
8835
8836 return send_and_recv_msgs(drv, msg, NULL, NULL);
8837
8838nla_put_failure:
8839 nlmsg_free(msg);
8840 return -ENOBUFS;
8841}
8842
8843#endif /* CONFIG TDLS */
8844
8845
8846#ifdef ANDROID
8847
8848typedef struct android_wifi_priv_cmd {
8849 char *buf;
8850 int used_len;
8851 int total_len;
8852} android_wifi_priv_cmd;
8853
8854static int drv_errors = 0;
8855
8856static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
8857{
8858 drv_errors++;
8859 if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
8860 drv_errors = 0;
8861 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
8862 }
8863}
8864
8865
8866static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
8867{
8868 struct wpa_driver_nl80211_data *drv = bss->drv;
8869 struct ifreq ifr;
8870 android_wifi_priv_cmd priv_cmd;
8871 char buf[MAX_DRV_CMD_SIZE];
8872 int ret;
8873
8874 os_memset(&ifr, 0, sizeof(ifr));
8875 os_memset(&priv_cmd, 0, sizeof(priv_cmd));
8876 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
8877
8878 os_memset(buf, 0, sizeof(buf));
8879 os_strlcpy(buf, cmd, sizeof(buf));
8880
8881 priv_cmd.buf = buf;
8882 priv_cmd.used_len = sizeof(buf);
8883 priv_cmd.total_len = sizeof(buf);
8884 ifr.ifr_data = &priv_cmd;
8885
8886 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
8887 if (ret < 0) {
8888 wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
8889 __func__);
8890 wpa_driver_send_hang_msg(drv);
8891 return ret;
8892 }
8893
8894 drv_errors = 0;
8895 return 0;
8896}
8897
8898
8899static int android_pno_start(struct i802_bss *bss,
8900 struct wpa_driver_scan_params *params)
8901{
8902 struct wpa_driver_nl80211_data *drv = bss->drv;
8903 struct ifreq ifr;
8904 android_wifi_priv_cmd priv_cmd;
8905 int ret = 0, i = 0, bp;
8906 char buf[WEXT_PNO_MAX_COMMAND_SIZE];
8907
8908 bp = WEXT_PNOSETUP_HEADER_SIZE;
8909 os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
8910 buf[bp++] = WEXT_PNO_TLV_PREFIX;
8911 buf[bp++] = WEXT_PNO_TLV_VERSION;
8912 buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
8913 buf[bp++] = WEXT_PNO_TLV_RESERVED;
8914
8915 while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
8916 /* Check that there is enough space needed for 1 more SSID, the
8917 * other sections and null termination */
8918 if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
8919 WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
8920 break;
8921 wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
8922 params->ssids[i].ssid,
8923 params->ssids[i].ssid_len);
8924 buf[bp++] = WEXT_PNO_SSID_SECTION;
8925 buf[bp++] = params->ssids[i].ssid_len;
8926 os_memcpy(&buf[bp], params->ssids[i].ssid,
8927 params->ssids[i].ssid_len);
8928 bp += params->ssids[i].ssid_len;
8929 i++;
8930 }
8931
8932 buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
8933 os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
8934 WEXT_PNO_SCAN_INTERVAL);
8935 bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
8936
8937 buf[bp++] = WEXT_PNO_REPEAT_SECTION;
8938 os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
8939 WEXT_PNO_REPEAT);
8940 bp += WEXT_PNO_REPEAT_LENGTH;
8941
8942 buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
8943 os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
8944 WEXT_PNO_MAX_REPEAT);
8945 bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
8946
8947 memset(&ifr, 0, sizeof(ifr));
8948 memset(&priv_cmd, 0, sizeof(priv_cmd));
8949 os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
8950
8951 priv_cmd.buf = buf;
8952 priv_cmd.used_len = bp;
8953 priv_cmd.total_len = bp;
8954 ifr.ifr_data = &priv_cmd;
8955
8956 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
8957
8958 if (ret < 0) {
8959 wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
8960 ret);
8961 wpa_driver_send_hang_msg(drv);
8962 return ret;
8963 }
8964
8965 drv_errors = 0;
8966
8967 return android_priv_cmd(bss, "PNOFORCE 1");
8968}
8969
8970
8971static int android_pno_stop(struct i802_bss *bss)
8972{
8973 return android_priv_cmd(bss, "PNOFORCE 0");
8974}
8975
8976#endif /* ANDROID */
8977
8978
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008979const struct wpa_driver_ops wpa_driver_nl80211_ops = {
8980 .name = "nl80211",
8981 .desc = "Linux nl80211/cfg80211",
8982 .get_bssid = wpa_driver_nl80211_get_bssid,
8983 .get_ssid = wpa_driver_nl80211_get_ssid,
8984 .set_key = wpa_driver_nl80211_set_key,
8985 .scan2 = wpa_driver_nl80211_scan,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008986 .sched_scan = wpa_driver_nl80211_sched_scan,
8987 .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008988 .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
8989 .deauthenticate = wpa_driver_nl80211_deauthenticate,
8990 .disassociate = wpa_driver_nl80211_disassociate,
8991 .authenticate = wpa_driver_nl80211_authenticate,
8992 .associate = wpa_driver_nl80211_associate,
8993 .global_init = nl80211_global_init,
8994 .global_deinit = nl80211_global_deinit,
8995 .init2 = wpa_driver_nl80211_init,
8996 .deinit = wpa_driver_nl80211_deinit,
8997 .get_capa = wpa_driver_nl80211_get_capa,
8998 .set_operstate = wpa_driver_nl80211_set_operstate,
8999 .set_supp_port = wpa_driver_nl80211_set_supp_port,
9000 .set_country = wpa_driver_nl80211_set_country,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009001 .set_ap = wpa_driver_nl80211_set_ap,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009002 .if_add = wpa_driver_nl80211_if_add,
9003 .if_remove = wpa_driver_nl80211_if_remove,
9004 .send_mlme = wpa_driver_nl80211_send_mlme,
9005 .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data,
9006 .sta_add = wpa_driver_nl80211_sta_add,
9007 .sta_remove = wpa_driver_nl80211_sta_remove,
9008 .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
9009 .sta_set_flags = wpa_driver_nl80211_sta_set_flags,
9010#ifdef HOSTAPD
9011 .hapd_init = i802_init,
9012 .hapd_deinit = i802_deinit,
Jouni Malinen75ecf522011-06-27 15:19:46 -07009013 .set_wds_sta = i802_set_wds_sta,
9014#endif /* HOSTAPD */
9015#if defined(HOSTAPD) || defined(CONFIG_AP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009016 .get_seqnum = i802_get_seqnum,
9017 .flush = i802_flush,
9018 .read_sta_data = i802_read_sta_data,
9019 .get_inact_sec = i802_get_inact_sec,
9020 .sta_clear_stats = i802_sta_clear_stats,
9021 .set_rts = i802_set_rts,
9022 .set_frag = i802_set_frag,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009023 .set_tx_queue_params = i802_set_tx_queue_params,
9024 .set_sta_vlan = i802_set_sta_vlan,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009025 .sta_deauth = i802_sta_deauth,
9026 .sta_disassoc = i802_sta_disassoc,
9027#endif /* HOSTAPD || CONFIG_AP */
9028 .set_freq = i802_set_freq,
9029 .send_action = wpa_driver_nl80211_send_action,
9030 .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
9031 .remain_on_channel = wpa_driver_nl80211_remain_on_channel,
9032 .cancel_remain_on_channel =
9033 wpa_driver_nl80211_cancel_remain_on_channel,
9034 .probe_req_report = wpa_driver_nl80211_probe_req_report,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009035 .deinit_ap = wpa_driver_nl80211_deinit_ap,
9036 .resume = wpa_driver_nl80211_resume,
9037 .send_ft_action = nl80211_send_ft_action,
9038 .signal_monitor = nl80211_signal_monitor,
9039 .signal_poll = nl80211_signal_poll,
9040 .send_frame = nl80211_send_frame,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009041 .shared_freq = wpa_driver_nl80211_shared_freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009042 .set_param = nl80211_set_param,
9043 .get_radio_name = nl80211_get_radio_name,
Jouni Malinen75ecf522011-06-27 15:19:46 -07009044 .add_pmkid = nl80211_add_pmkid,
9045 .remove_pmkid = nl80211_remove_pmkid,
9046 .flush_pmkid = nl80211_flush_pmkid,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009047 .set_rekey_info = nl80211_set_rekey_info,
9048 .poll_client = nl80211_poll_client,
9049#ifndef ANDROID_P2P
9050 .set_p2p_powersave = nl80211_set_p2p_powersave,
9051#endif
9052#ifdef CONFIG_TDLS
9053 .send_tdls_mgmt = nl80211_send_tdls_mgmt,
9054 .tdls_oper = nl80211_tdls_oper,
9055#endif /* CONFIG_TDLS */
9056#ifdef ANDROID_P2P
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009057 .set_noa = wpa_driver_set_p2p_noa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08009058 .get_noa = wpa_driver_get_p2p_noa,
Dmitry Shmidt6e933c12011-09-27 12:29:26 -07009059 .set_p2p_powersave = wpa_driver_set_p2p_ps,
9060 .set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
9061#endif
Dmitry Shmidt738a26e2011-07-07 14:22:14 -07009062#ifdef ANDROID
9063 .driver_cmd = wpa_driver_nl80211_driver_cmd,
9064#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07009065};