18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Driver interaction with Linux nl80211/cfg80211
3fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2004, Instant802 Networks, Inc.
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2006, Devicescape Software, Inc.
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
9c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
10c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/ioctl.h>
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/types.h>
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/stat.h>
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <fcntl.h>
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <net/if.h>
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netlink/genl/genl.h>
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netlink/genl/family.h>
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netlink/genl/ctrl.h>
22661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#ifdef CONFIG_LIBNL3_ROUTE
23661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#include <netlink/route/neighbour.h>
24661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt#endif /* CONFIG_LIBNL3_ROUTE */
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <linux/rtnetlink.h>
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netpacket/packet.h>
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <linux/filter.h>
281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include <linux/errqueue.h>
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "nl80211_copy.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/list.h"
34cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#include "common/qca-vendor.h"
357832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#include "common/qca-vendor-attr.h"
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common/ieee802_11_common.h"
381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "l2_packet/l2_packet.h"
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "netlink.h"
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "linux_ioctl.h"
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radiotap.h"
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radiotap_iter.h"
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rfkill.h"
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver.h"
45c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef SO_WIFI_STATUS
471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt# if defined(__sparc__)
481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#  define SO_WIFI_STATUS	0x0025
491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt# elif defined(__parisc__)
501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#  define SO_WIFI_STATUS	0x4022
511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt# else
521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#  define SO_WIFI_STATUS	41
531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt# endif
541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt# define SCM_WIFI_STATUS	SO_WIFI_STATUS
561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef SO_EE_ORIGIN_TXSTATUS
591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define SO_EE_ORIGIN_TXSTATUS	4
601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef PACKET_TX_TIMESTAMP
631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#define PACKET_TX_TIMESTAMP	16
641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif
651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef ANDROID
671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "android_drv.h"
681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* ANDROID */
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_LIBNL20
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* libnl 2.0 compatibility code */
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define nl_handle nl_sock
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define nl80211_handle_alloc nl_socket_alloc_cb
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define nl80211_handle_destroy nl_socket_free
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * libnl 1.1 has a bug, it tries to allocate socket numbers densely
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * but when you free a socket again it will mess up its bitmap and
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and use the wrong number the next time it needs a socket ID.
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Therefore, we wrap the handle alloc/destroy and add our own pid
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * accounting.
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic uint32_t port_bitmap[32] = { 0 };
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct nl_handle *nl80211_handle_alloc(void *cb)
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct nl_handle *handle;
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	uint32_t pid = getpid() & 0x3FFFFF;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	handle = nl_handle_alloc_cb(cb);
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 1024; i++) {
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (port_bitmap[i / 32] & (1 << (i % 32)))
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		port_bitmap[i / 32] |= 1 << (i % 32);
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pid += i << 22;
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nl_socket_set_local_port(handle, pid);
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return handle;
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_handle_destroy(struct nl_handle *handle)
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	uint32_t port = nl_socket_get_local_port(handle);
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	port >>= 22;
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	port_bitmap[port / 32] &= ~(1 << (port % 32));
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	nl_handle_destroy(handle);
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_LIBNL20 */
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1175460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#ifdef ANDROID
1185460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt/* system/core/libnl_2 does not include nl_socket_set_nonblocking() */
1195460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidtstatic int android_nl_socket_set_nonblocking(struct nl_handle *handle)
1205460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt{
1215460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt	return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
1225460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt}
1235460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#undef nl_socket_set_nonblocking
1245460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h)
1255460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt#endif /* ANDROID */
1265460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
1275460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl_handle *handle;
1311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	handle = nl80211_handle_alloc(cb);
1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (handle == NULL) {
1341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "callbacks (%s)", dbg);
1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
1371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
1381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (genl_connect(handle)) {
1401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "netlink (%s)", dbg);
1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		nl80211_handle_destroy(handle);
1431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return NULL;
1441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return handle;
1471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nl_destroy_handles(struct nl_handle **handle)
1511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
1521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (*handle == NULL)
1531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
1541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	nl80211_handle_destroy(*handle);
1551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	*handle = NULL;
1561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
1571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
1581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
15968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#if __WORDSIZE == 64
16068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define ELOOP_SOCKET_INVALID	(intptr_t) 0x8888888888888889ULL
16168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#else
16268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define ELOOP_SOCKET_INVALID	(intptr_t) 0x88888889ULL
16368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#endif
16468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
16568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic void nl80211_register_eloop_read(struct nl_handle **handle,
16668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt					eloop_sock_handler handler,
16768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt					void *eloop_data)
16868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{
16968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	nl_socket_set_nonblocking(*handle);
17068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	eloop_register_read_sock(nl_socket_get_fd(*handle), handler,
17168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt				 eloop_data, *handle);
17268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	*handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
17368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt}
17468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
17568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
17668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic void nl80211_destroy_eloop_handle(struct nl_handle **handle)
17768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{
17868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	*handle = (void *) (((intptr_t) *handle) ^ ELOOP_SOCKET_INVALID);
17968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	eloop_unregister_read_sock(nl_socket_get_fd(*handle));
18068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt	nl_destroy_handles(handle);
18168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt}
18268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
18368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef IFF_LOWER_UP
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IFF_LOWER_UP   0x10000         /* driver signals L1 up         */
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef IFF_DORMANT
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IFF_DORMANT    0x20000         /* driver signals dormant       */
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef IF_OPER_DORMANT
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IF_OPER_DORMANT 5
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef IF_OPER_UP
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IF_OPER_UP 6
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct nl80211_global {
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dl_list interfaces;
2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int if_add_ifindex;
20134af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u64 if_add_wdevid;
20234af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	int if_add_wdevid_set;
2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct netlink_data *netlink;
2041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl_cb *nl_cb;
2051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl_handle *nl;
2061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int nl80211_id;
2071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int ioctl_sock; /* socket for ioctl() use */
2081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl_handle *nl_event;
2101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt};
2111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct nl80211_wiphy_data {
2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct dl_list list;
2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct dl_list bsss;
2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct dl_list drvs;
2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl_handle *nl_beacons;
2181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl_cb *nl_cb;
2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int wiphy_idx;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void nl80211_global_deinit(void *priv);
2241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct i802_bss {
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_nl80211_data *drv;
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct i802_bss *next;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ifindex;
22934af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	u64 wdev_id;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char ifname[IFNAMSIZ + 1];
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char brname[IFNAMSIZ];
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int beacon_set:1;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int added_if_into_bridge:1;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int added_bridge:1;
23504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	unsigned int in_deinit:1;
23634af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	unsigned int wdev_id_set:1;
237cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	unsigned int added_if:1;
23803658834c33748b9ad86f3d4cdf0c7be9c6887d1Dmitry Shmidt	unsigned int static_ap:1;
2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 addr[ETH_ALEN];
2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int freq;
2437832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt	int bandwidth;
244b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	int if_dynamic;
2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
246a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	void *ctx;
2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl_handle *nl_preq, *nl_mgmt;
2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl_cb *nl_cb;
2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct nl80211_wiphy_data *wiphy_data;
2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct dl_list wiphy_list;
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_driver_nl80211_data {
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct nl80211_global *global;
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct dl_list list;
2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct dl_list wiphy_list;
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char phyname[32];
259661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	u8 perm_addr[ETH_ALEN];
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ifindex;
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int if_removed;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int if_disabled;
2641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int ignore_if_down_event;
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct rfkill_data *rfkill;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_capa capa;
267444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	u8 *extended_capa, *extended_capa_mask;
268444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	unsigned int extended_capa_len;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int has_capability;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int operstate;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int scan_complete_events;
2745605286c30e1701491bd3af974ae423727750eddDmitry Shmidt	enum scan_states {
2755605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		NO_SCAN, SCAN_REQUESTED, SCAN_STARTED, SCAN_COMPLETED,
2765605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		SCAN_ABORTED, SCHED_SCAN_STARTED, SCHED_SCAN_STOPPED,
2775605286c30e1701491bd3af974ae423727750eddDmitry Shmidt		SCHED_SCAN_RESULTS
2785605286c30e1701491bd3af974ae423727750eddDmitry Shmidt	} scan_state;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct nl_cb *nl_cb;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 auth_bssid[ETH_ALEN];
2838bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	u8 auth_attempt_bssid[ETH_ALEN];
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bssid[ETH_ALEN];
2858bae4138a0356709720a96f3e50b4d734e532c12Dmitry Shmidt	u8 prev_bssid[ETH_ALEN];
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int associated;
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 ssid[32];
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t ssid_len;
2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	enum nl80211_iftype nlmode;
2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	enum nl80211_iftype ap_scan_as_station;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int assoc_freq;
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int monitor_sock;
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int monitor_ifidx;
2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int monitor_refcount;
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int disabled_11b_rates:1;
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int pending_remain_on_chan:1;
2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int in_interface_list:1;
3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int device_ap_sme:1;
3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int poll_command_supported:1;
3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int data_tx_status:1;
3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int scan_for_auth:1;
3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int retry_auth:1;
3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	unsigned int use_monitor:1;
306d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	unsigned int ignore_next_local_disconnect:1;
3077dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	unsigned int ignore_next_local_deauth:1;
30834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt	unsigned int allow_p2p_device:1;
309e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	unsigned int hostapd:1;
310e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	unsigned int start_mode_ap:1;
311e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	unsigned int start_iface_up:1;
3127d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt	unsigned int test_use_roc_tx:1;
3139866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt	unsigned int ignore_deauth_event:1;
314661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	unsigned int roaming_vendor_cmd_avail:1;
315d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt	unsigned int dfs_vendor_cmd_avail:1;
3162271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	unsigned int have_low_prio_scan:1;
317661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	unsigned int force_connect_cmd:1;
318661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	unsigned int addr_changed:1;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u64 remain_on_chan_cookie;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u64 send_action_cookie;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int last_mgmt_freq;
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_scan_filter *filter_ssids;
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t num_filter_ssids;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
328cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	struct i802_bss *first_bss;
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int eapol_tx_sock;
3311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int eapol_sock; /* socket for EAPOL frames */
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3349ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt	struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
335661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int default_if_indices[16];
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int *if_indices;
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int num_if_indices;
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* From failed authentication command */
3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int auth_freq;
3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 auth_bssid_[ETH_ALEN];
3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 auth_ssid[32];
3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t auth_ssid_len;
3451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int auth_alg;
3461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 *auth_ie;
3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t auth_ie_len;
3481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u8 auth_wep_key[4][16];
3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t auth_wep_key_len[4];
3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int auth_wep_tx_keyidx;
3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int auth_local_state_change;
3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int auth_p2p;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3564b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtstatic void wpa_driver_nl80211_deinit(struct i802_bss *bss);
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    void *timeout_ctx);
3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				       enum nl80211_iftype nlmode);
3619ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidtstatic int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
3629ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt					    struct hostapd_freq_params *freq);
363d30ac604c9f6da71a0dd7f46d25be05a2a62cfbbDmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int
365e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidtwpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
366e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt				   const u8 *set_addr, int first);
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   const u8 *addr, int cmd, u16 reason_code,
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   int local_state_change);
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void nl80211_remove_monitor_interface(
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_driver_nl80211_data *drv);
3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int nl80211_send_frame_cmd(struct i802_bss *bss,
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  unsigned int freq, unsigned int wait,
3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				  const u8 *buf, size_t buf_len, u64 *cookie,
3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				  int no_cck, int no_ack, int offchanok);
376c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic int nl80211_register_frame(struct i802_bss *bss,
377c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				  struct