Update to new version 0.8.16 from BRCM

Sync with main tree commit b8349523e460493fa0b4de36c689595109e45e91
Author: Neeraj Kumar Garg <neerajkg@broadcom.com>
Date:   Tue Dec 27 23:21:45 2011 +0200
    P2P: Reject p2p_group_add if forced frequency is not acceptable

Change-Id: Icb4541a371b05c270e80440d7a7fdea7f33ff61e
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/drivers/Apple80211.h b/src/drivers/Apple80211.h
deleted file mode 100644
index 2a612e7..0000000
--- a/src/drivers/Apple80211.h
+++ /dev/null
@@ -1,156 +0,0 @@
-#ifndef APPLE80211_H
-#define APPLE80211_H
-
-/*
- * Apple80211 framework definitions
- * This is an undocumented interface and the definitions here are based on
- * information from MacStumbler (http://www.macstumbler.com/Apple80211.h) and
- * whatever related information can be found with google and experiments ;-).
- */
-
-typedef struct __WirelessRef *WirelessRef;
-typedef SInt32 WirelessError;
-#define errWirelessNoError 0
-
-typedef struct WirelessInfo {
-	UInt16 link_qual;
-	UInt16 comms_qual;
-	UInt16 signal;
-	UInt16 noise;
-	UInt16 port_stat;
-	UInt16 client_mode;
-	UInt16 res1;
-	UInt16 power;
-	UInt16 res2;
-	UInt8 bssID[6];
-	UInt8 ssid[34];
-} WirelessInfo;
-
-typedef struct WirelessInfo2 {
-	/* TODO - these are probably not in correct order or complete */
-	WirelessInfo info1;
-	UInt8 macAddress[6];
-} WirelessInfo2;
-
-typedef struct WirelessNetworkInfo {
-	UInt16 channel;
-	UInt16 noise;
-	UInt16 signal;
-	UInt8 bssid[6];
-	UInt16 beacon_int;
-	UInt16 capability;
-	UInt16 ssid_len;
-	UInt8 ssid[32];
-} WirelessNetworkInfo;
-
-typedef int wirelessKeyType; /* TODO */
-
-int WirelessIsAvailable(void);
-WirelessError WirelessAttach(WirelessRef *ref, UInt32 res);
-WirelessError WirelessDetach(WirelessRef ref);
-WirelessError WirelessPrivate(WirelessRef ref, void *in_ptr, int in_bytes,
-			      void *out_ptr, int out_bytes);
-WirelessError WirelessSetEnabled(WirelessRef ref, UInt8 enabled);
-WirelessError WirelessGetEnabled(WirelessRef ref, UInt8 *enabled);
-WirelessError WirelessSetPower(WirelessRef ref, UInt8 power);
-WirelessError WirelessGetPower(WirelessRef ref, UInt8 *power);
-WirelessError WirelessGetInfo(WirelessRef ref, WirelessInfo *info);
-WirelessError WirelessGetInfo2(WirelessRef ref, WirelessInfo2 *info);
-WirelessError WirelessScan(WirelessRef ref, CFArrayRef *results,
-			   UInt32 strip_dups);
-WirelessError WirelessScanSplit(WirelessRef ref, CFArrayRef *ap_results,
-				CFArrayRef *ibss_results, UInt32 strip_dups);
-WirelessError WirelessDirectedScan(WirelessRef ref, CFArrayRef *results,
-				   UInt32 strip_dups, CFStringRef ssid);
-WirelessError WirelessDirectedScan2(WirelessRef ref, CFDataRef ssid,
-				    UInt32 strip_dups, CFArrayRef *results);
-WirelessError WirelessJoin(WirelessRef ref, CFStringRef ssid);
-WirelessError WirelessJoinWEP(WirelessRef ref, CFStringRef ssid,
-			      CFStringRef passwd);
-WirelessError WirelessJoin8021x(WirelessRef ref, CFStringRef ssid);
-/*
- * Set WEP key
- * ref: wireless reference from WirelessAttach()
- * type: ?
- * key_idx: 0..3
- * key_len: 13 for WEP-104 or 0 for clearing the key
- * key: Pointer to the key or %NULL if key_len = 0
- */
-WirelessError WirelessSetKey(WirelessRef ref, wirelessKeyType type,
-			     int key_idx, int key_len,
-			     const unsigned char *key);
-/*
- * Set WPA key (e.g., PMK for 4-way handshake)
- * ref: wireless reference from WirelessAttach()
- * type: 0..4; 1 = PMK
- * key_len: 16, 32, or 0
- * key: Pointer to the key or %NULL if key_len = 0
- */
-WirelessError WirelessSetWPAKey(WirelessRef ref, wirelessKeyType type,
-				int key_len, const unsigned char *key);
-WirelessError WirelessAssociate(WirelessRef ref, int type, CFDataRef ssid,
-				CFStringRef key);
-WirelessError WirelessAssociate2(WirelessRef ref, CFDictionaryRef scan_res,
-				 CFStringRef key);
-WirelessError WirelessDisassociate(WirelessRef ref);
-
-/*
- * Get a copy of scan results for the given SSID
- * The returned dictionary includes following entries:
- * beaconInterval: CFNumber(kCFNumberSInt32Type)
- * SSID: CFData buffer of the SSID
- * isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 = WPA2
- * name: Name of the network (SSID string)
- * BSSID: CFData buffer of the BSSID
- * channel: CFNumber(kCFNumberSInt32Type)
- * signal: CFNumber(kCFNumberSInt32Type)
- * appleIE: CFData
- * WPSNOPINRequired: CFBoolean
- * noise: CFNumber(kCFNumberSInt32Type)
- * capability: CFNumber(kCFNumberSInt32Type)
- * uniCipher: CFArray of CFNumber(kCFNumberSInt32Type)
- * appleIE_Version: CFNumber(kCFNumberSInt32Type)
- * appleIE_Robust: CFBoolean
- * WPSConfigured: CFBoolean
- * scanWasDirected: CFBoolean
- * appleIE_Product: CFNumber(kCFNumberSInt32Type)
- * authModes: CFArray of CFNumber(kCFNumberSInt32Type)
- * multiCipher: CFNumber(kCFNumberSInt32Type)
- */
-CFDictionaryRef WirelessSafeDirectedScanCopy(WirelessRef ref, CFDataRef ssid);
-
-/*
- * Get information about the current association
- * The returned dictionary includes following entries:
- * keyData: CFData buffer of the key (e.g., 32-octet PSK)
- * multiCipher: CFNumber(kCFNumberSInt32Type); 0 = none, 5 = CCMP?
- * channel: CFNumber(kCFNumberSInt32Type)
- * isIBSS: CFBoolean
- * authMode: CFNumber(kCFNumberSInt32Type); 2 = WPA-Personal; 3 = open,
- *	129 = WPA2-Enterprise
- * isWPA: CFNumber(kCFNumberSInt32Type); 0 = not used, 1 = WPA, -128 == WPA2
- * SSID: CFData buffer of the SSID
- * cipherMode: CFNumber(kCFNumberSInt32Type); 0 = none, 4 = CCMP?
- */
-CFDictionaryRef WirelessGetAssociationInfo(WirelessRef ref);
-
-WirelessError WirelessConfigure(WirelessRef ref);
-
-/*
- * Get ASP information
- * The returned dictionary includes following entries:
- * Version: version number (e.g., 3.0)
- * Channel: channel (e.g., 1)
- * Vendor: vendor (e.g., 2)
- */
-CFDictionaryRef WirelessGetInfoASP(void);
-
-/*
- * Get a copy of the interface dictionary
- * The returned dictionary has a key,value pairs for wireless interfaces.
- * The key is the interface name and the value is the driver identifier, e.g.,
- * en1: com.apple.driver.AirPort.Atheros
- */
-CFDictionaryRef WirelessCopyInterfaceDict(void);
-
-#endif /* APPLE80211_H */
diff --git a/src/drivers/MobileApple80211.c b/src/drivers/MobileApple80211.c
deleted file mode 100644
index ce004fe..0000000
--- a/src/drivers/MobileApple80211.c
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "includes.h"
-#include <dlfcn.h>
-
-#include "common.h"
-
-#include <CoreFoundation/CoreFoundation.h>
-#include "MobileApple80211.h"
-
-/*
- * Code for dynamically loading Apple80211 functions from Aeropuerto to avoid
- * having to link with full Preferences.framework.
- */
-
-static void *aeropuerto = NULL;
-
-
-int _Apple80211Initialized(void)
-{
-	return aeropuerto ? 1 : 0;
-}
-
-
-static int (*__Apple80211Open)(Apple80211Ref *ctx) = NULL;
-
-int Apple80211Open(Apple80211Ref *ctx)
-{
-	return __Apple80211Open(ctx);
-}
-
-
-static int (*__Apple80211Close)(Apple80211Ref ctx) = NULL;
-
-int Apple80211Close(Apple80211Ref ctx)
-{
-	return __Apple80211Close(ctx);
-}
-
-
-static int (*__Apple80211GetIfListCopy)(Apple80211Ref handle, CFArrayRef *list)
-	= NULL;
-
-int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list)
-{
-	return __Apple80211GetIfListCopy(handle, list);
-}
-
-
-static int (*__Apple80211BindToInterface)(Apple80211Ref handle,
-					  CFStringRef interface) = NULL;
-
-int Apple80211BindToInterface(Apple80211Ref handle,
-			      CFStringRef interface)
-{
-	return __Apple80211BindToInterface(handle, interface);
-}
-
-
-static int (*__Apple80211GetInterfaceNameCopy)(Apple80211Ref handle,
-					       CFStringRef *name) = NULL;
-
-int Apple80211GetInterfaceNameCopy(Apple80211Ref handle,
-				   CFStringRef *name)
-{
-	return __Apple80211GetInterfaceNameCopy(handle, name);
-}
-
-
-static int (*__Apple80211GetInfoCopy)(Apple80211Ref handle,
-				      CFDictionaryRef *info) = NULL;
-
-int Apple80211GetInfoCopy(Apple80211Ref handle,
-			  CFDictionaryRef *info)
-{
-	return __Apple80211GetInfoCopy(handle, info);
-}
-
-
-static int (*__Apple80211GetPower)(Apple80211Ref handle, char *pwr) = NULL;
-
-int Apple80211GetPower(Apple80211Ref handle, char *pwr)
-{
-	return __Apple80211GetPower(handle, pwr);
-}
-
-
-static int (*__Apple80211SetPower)(Apple80211Ref handle, char pwr) = NULL;
-
-int Apple80211SetPower(Apple80211Ref handle, char pwr)
-{
-	return __Apple80211SetPower(handle, pwr);
-}
-
-
-static int (*__Apple80211Scan)(Apple80211Ref handle, CFArrayRef *list,
-			       CFDictionaryRef parameters) = NULL;
-
-int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list,
-		   CFDictionaryRef parameters)
-{
-	return __Apple80211Scan(handle, list, parameters);
-}
-
-
-static int (*__Apple80211Associate)(Apple80211Ref handle, CFDictionaryRef bss,
-				    CFStringRef password) = NULL;
-
-int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss,
-			CFStringRef password)
-{
-	return __Apple80211Associate(handle, bss, password);
-}
-
-
-static int (*__Apple80211AssociateAndCopyInfo)(Apple80211Ref handle,
-					       CFDictionaryRef bss,
-					       CFStringRef password,
-					       CFDictionaryRef *info) =
-	NULL;
-
-int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss,
-				   CFStringRef password, CFDictionaryRef *info)
-{
-	return __Apple80211AssociateAndCopyInfo(handle, bss, password, info);
-}
-
-
-static int (*__Apple80211CopyValue)(Apple80211Ref handle, int field,
-				    CFDictionaryRef arg2, void *value) = NULL;
-
-int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2,
-			void *value)
-{
-	return __Apple80211CopyValue(handle, field, arg2, value);
-}
-
-
-#define DLSYM(s) \
-do { \
-	__ ## s = dlsym(aeropuerto, #s); \
-	if (__ ## s == NULL) { \
-		wpa_printf(MSG_ERROR, "MobileApple80211: Could not resolve " \
-			   "symbol '" #s "' (%s)", dlerror()); \
-		err = 1; \
-	} \
-} while (0)
-
-
-__attribute__ ((constructor))
-void _Apple80211_constructor(void)
-{
-	const char *fname = "/System/Library/SystemConfiguration/"
-		"Aeropuerto.bundle/Aeropuerto";
-	int err = 0;
-
-	aeropuerto = dlopen(fname, RTLD_LAZY);
-	if (!aeropuerto) {
-		wpa_printf(MSG_ERROR, "MobileApple80211: Failed to open %s "
-			   "for symbols", fname);
-		return;
-	}
-
-	DLSYM(Apple80211Open);
-	DLSYM(Apple80211Close);
-	DLSYM(Apple80211GetIfListCopy);
-	DLSYM(Apple80211BindToInterface);
-	DLSYM(Apple80211GetInterfaceNameCopy);
-	DLSYM(Apple80211GetInfoCopy);
-	DLSYM(Apple80211GetPower);
-	DLSYM(Apple80211SetPower);
-	DLSYM(Apple80211Scan);
-	DLSYM(Apple80211Associate);
-	DLSYM(Apple80211AssociateAndCopyInfo);
-	DLSYM(Apple80211CopyValue);
-
-	if (err) {
-		dlclose(aeropuerto);
-		aeropuerto = NULL;
-	}
-}
-
-
-__attribute__ ((destructor))
-void _Apple80211_destructor(void)
-{
-	if (aeropuerto) {
-		dlclose(aeropuerto);
-		aeropuerto = NULL;
-	}
-}
diff --git a/src/drivers/MobileApple80211.h b/src/drivers/MobileApple80211.h
deleted file mode 100644
index 64d439d..0000000
--- a/src/drivers/MobileApple80211.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef MOBILEAPPLE80211_H
-#define MOBILEAPPLE80211_H
-
-/*
- * MobileApple80211 interface for iPhone/iPod touch
- * These functions are available from Aeropuerto.
- */
-
-struct Apple80211;
-typedef struct Apple80211 *Apple80211Ref;
-
-int Apple80211Open(Apple80211Ref *ctx);
-int Apple80211Close(Apple80211Ref ctx);
-int Apple80211GetIfListCopy(Apple80211Ref handle, CFArrayRef *list);
-int Apple80211BindToInterface(Apple80211Ref handle,
-			      CFStringRef interface);
-int Apple80211GetInterfaceNameCopy(Apple80211Ref handle,
-				   CFStringRef *name);
-int Apple80211GetInfoCopy(Apple80211Ref handle,
-			  CFDictionaryRef *info);
-int Apple80211GetPower(Apple80211Ref handle, char *pwr);
-int Apple80211SetPower(Apple80211Ref handle, char pwr);
-
-/* parameters can be NULL; returns scan results in CFArrayRef *list;
- * caller will need to free with CFRelease() */
-int Apple80211Scan(Apple80211Ref handle, CFArrayRef *list,
-		   CFDictionaryRef parameters);
-
-int Apple80211Associate(Apple80211Ref handle, CFDictionaryRef bss,
-			CFStringRef password);
-int Apple80211AssociateAndCopyInfo(Apple80211Ref handle, CFDictionaryRef bss,
-				   CFStringRef password,
-				   CFDictionaryRef *info);
-
-enum {
-	APPLE80211_VALUE_SSID = 1,
-	APPLE80211_VALUE_BSSID = 9
-};
-
-int Apple80211CopyValue(Apple80211Ref handle, int field, CFDictionaryRef arg2,
-			void *value);
-
-#endif /* MOBILEAPPLE80211_H */
diff --git a/src/drivers/android_drv.h b/src/drivers/android_drv.h
new file mode 100644
index 0000000..6df7160
--- /dev/null
+++ b/src/drivers/android_drv.h
@@ -0,0 +1,62 @@
+/*
+ * Android driver interface
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ */
+
+#ifndef ANDROID_DRV_H
+#define ANDROID_DRV_H
+
+#define WPA_EVENT_DRIVER_STATE "CTRL-EVENT-DRIVER-STATE "
+
+#define WEXT_CSCAN_AMOUNT		9
+
+#define MAX_SSID_LEN 32
+
+#define MAX_DRV_CMD_SIZE		248
+#define DRV_NUMBER_SEQUENTIAL_ERRORS	4
+
+#define WEXT_PNOSETUP_HEADER		"PNOSETUP "
+#define WEXT_PNOSETUP_HEADER_SIZE	9
+#define WEXT_PNO_TLV_PREFIX		'S'
+#define WEXT_PNO_TLV_VERSION		'1'
+#define WEXT_PNO_TLV_SUBVERSION		'2'
+#define WEXT_PNO_TLV_RESERVED		'0'
+#define WEXT_PNO_VERSION_SIZE		4
+#define WEXT_PNO_AMOUNT			16
+#define WEXT_PNO_SSID_SECTION		'S'
+/* SSID header size is SSID section type above + SSID length */
+#define WEXT_PNO_SSID_HEADER_SIZE	2
+#define WEXT_PNO_SCAN_INTERVAL_SECTION	'T'
+#define WEXT_PNO_SCAN_INTERVAL_LENGTH	2
+#define WEXT_PNO_SCAN_INTERVAL		30
+/* Scan interval size is scan interval section type + scan interval length
+ * above */
+#define WEXT_PNO_SCAN_INTERVAL_SIZE	(1 + WEXT_PNO_SCAN_INTERVAL_LENGTH)
+#define WEXT_PNO_REPEAT_SECTION		'R'
+#define WEXT_PNO_REPEAT_LENGTH		1
+#define WEXT_PNO_REPEAT			4
+/* Repeat section size is Repeat section type + Repeat value length above */
+#define WEXT_PNO_REPEAT_SIZE		(1 + WEXT_PNO_REPEAT_LENGTH)
+#define WEXT_PNO_MAX_REPEAT_SECTION	'M'
+#define WEXT_PNO_MAX_REPEAT_LENGTH	1
+#define WEXT_PNO_MAX_REPEAT		3
+/* Max Repeat section size is Max Repeat section type + Max Repeat value length
+ * above */
+#define WEXT_PNO_MAX_REPEAT_SIZE	(1 + WEXT_PNO_MAX_REPEAT_LENGTH)
+/* This corresponds to the size of all sections expect SSIDs */
+#define WEXT_PNO_NONSSID_SECTIONS_SIZE \
+(WEXT_PNO_SCAN_INTERVAL_SIZE + WEXT_PNO_REPEAT_SIZE + WEXT_PNO_MAX_REPEAT_SIZE)
+/* PNO Max command size is total of header, version, ssid and other sections +
+ * Null termination */
+#define WEXT_PNO_MAX_COMMAND_SIZE \
+	(WEXT_PNOSETUP_HEADER_SIZE + WEXT_PNO_VERSION_SIZE \
+	 + WEXT_PNO_AMOUNT * (WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN) \
+	 + WEXT_PNO_NONSSID_SECTIONS_SIZE + 1)
+
+#endif /* ANDROID_DRV_H */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 19f732d..ceed531 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -35,14 +35,6 @@
 #define HOSTAPD_CHAN_HT40MINUS 0x00000020
 #define HOSTAPD_CHAN_HT40 0x00000040
 
-#ifdef ANDROID_BRCM_P2P_PATCH
-/**
- * Monitor interface name is derived from p2p interface name
- * We need to reset p2p interface name early to take care of extra character in
- */
-#define WPA_MONITOR_IFNAME_PREFIX	"m."
-#endif
-
 /**
  * struct hostapd_channel_data - Channel information
  */
@@ -68,6 +60,8 @@
 	u8 max_tx_power;
 };
 
+#define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0)
+
 /**
  * struct hostapd_hw_modes - Supported hardware mode information
  */
@@ -111,6 +105,8 @@
 	 * a_mpdu_params - A-MPDU (IEEE 802.11n) parameters
 	 */
 	u8 a_mpdu_params;
+
+	unsigned int flags; /* HOSTAPD_MODE_FLAG_* */
 };
 
 
@@ -203,7 +199,7 @@
 	const char *drv_name;
 };
 
-#define WPAS_MAX_SCAN_SSIDS 10
+#define WPAS_MAX_SCAN_SSIDS 16
 
 /**
  * struct wpa_driver_scan_params - Scan parameters
@@ -272,6 +268,15 @@
 	 * num_filter_ssids - Number of entries in filter_ssids array
 	 */
 	size_t num_filter_ssids;
+
+	/**
+	 * p2p_probe - Used to disable CCK (802.11b) rates for P2P probes
+	 *
+	 * When set, the driver is expected to remove rates 1, 2, 5.5, and 11
+	 * Mbps from the support rates element(s) in the Probe Request frames
+	 * and not to transmit the frames at any of those rates.
+	 */
+	u8 p2p_probe;
 };
 
 /**
@@ -290,6 +295,12 @@
 	size_t wep_key_len[4];
 	int wep_tx_keyidx;
 	int local_state_change;
+
+	/**
+	 * p2p - Whether this connection is a P2P group
+	 */
+	int p2p;
+
 };
 
 enum wps_mode {
@@ -353,6 +364,11 @@
 	size_t wpa_ie_len;
 
 	/**
+	 * wpa_proto - Bitfield of WPA_PROTO_* values to indicate WPA/WPA2
+	 */
+	unsigned int wpa_proto;
+
+	/**
 	 * pairwise_suite - Selected pairwise cipher suite
 	 *
 	 * This is usually ignored if @wpa_ie is used.
@@ -502,6 +518,183 @@
 	int uapsd;
 };
 
+enum hide_ssid {
+	NO_SSID_HIDING,
+	HIDDEN_SSID_ZERO_LEN,
+	HIDDEN_SSID_ZERO_CONTENTS
+};
+
+struct wpa_driver_ap_params {
+	/**
+	 * head - Beacon head from IEEE 802.11 header to IEs before TIM IE
+	 */
+	const u8 *head;
+
+	/**
+	 * head_len - Length of the head buffer in octets
+	 */
+	size_t head_len;
+
+	/**
+	 * tail - Beacon tail following TIM IE
+	 */
+	const u8 *tail;
+
+	/**
+	 * tail_len - Length of the tail buffer in octets
+	 */
+	size_t tail_len;
+
+	/**
+	 * dtim_period - DTIM period
+	 */
+	int dtim_period;
+
+	/**
+	 * beacon_int - Beacon interval
+	 */
+	int beacon_int;
+
+	/**
+	 * basic_rates: -1 terminated array of basic rates in 100 kbps
+	 *
+	 * This parameter can be used to set a specific basic rate set for the
+	 * BSS. If %NULL, default basic rate set is used.
+	 */
+	int *basic_rates;
+
+	/**
+	 * proberesp - Probe Response template
+	 *
+	 * This is used by drivers that reply to Probe Requests internally in
+	 * AP mode and require the full Probe Response template.
+	 */
+	const u8 *proberesp;
+
+	/**
+	 * proberesp_len - Length of the proberesp buffer in octets
+	 */
+	size_t proberesp_len;
+
+	/**
+	 * ssid - The SSID to use in Beacon/Probe Response frames
+	 */
+	const u8 *ssid;
+
+	/**
+	 * ssid_len - Length of the SSID (1..32)
+	 */
+	size_t ssid_len;
+
+	/**
+	 * hide_ssid - Whether to hide the SSID
+	 */
+	enum hide_ssid hide_ssid;
+
+	/**
+	 * pairwise_ciphers - WPA_CIPHER_* bitfield
+	 */
+	unsigned int pairwise_ciphers;
+
+	/**
+	 * group_cipher - WPA_CIPHER_*
+	 */
+	unsigned int group_cipher;
+
+	/**
+	 * key_mgmt_suites - WPA_KEY_MGMT_* bitfield
+	 */
+	unsigned int key_mgmt_suites;
+
+	/**
+	 * auth_algs - WPA_AUTH_ALG_* bitfield
+	 */
+	unsigned int auth_algs;
+
+	/**
+	 * wpa_version - WPA_PROTO_* bitfield
+	 */
+	unsigned int wpa_version;
+
+	/**
+	 * privacy - Whether privacy is used in the BSS
+	 */
+	int privacy;
+
+	/**
+	 * beacon_ies - WPS/P2P IE(s) for Beacon frames
+	 *
+	 * This is used to add IEs like WPS IE and P2P IE by drivers that do
+	 * not use the full Beacon template.
+	 */
+	const struct wpabuf *beacon_ies;
+
+	/**
+	 * proberesp_ies - P2P/WPS IE(s) for Probe Response frames
+	 *
+	 * This is used to add IEs like WPS IE and P2P IE by drivers that
+	 * reply to Probe Request frames internally.
+	 */
+	const struct wpabuf *proberesp_ies;
+
+	/**
+	 * assocresp_ies - WPS IE(s) for (Re)Association Response frames
+	 *
+	 * This is used to add IEs like WPS IE by drivers that reply to
+	 * (Re)Association Request frames internally.
+	 */
+	const struct wpabuf *assocresp_ies;
+
+	/**
+	 * isolate - Whether to isolate frames between associated stations
+	 *
+	 * If this is non-zero, the AP is requested to disable forwarding of
+	 * frames between associated stations.
+	 */
+	int isolate;
+
+	/**
+	 * cts_protect - Whether CTS protection is enabled
+	 */
+	int cts_protect;
+
+	/**
+	 * preamble - Whether short preamble is enabled
+	 */
+	int preamble;
+
+	/**
+	 * short_slot_time - Whether short slot time is enabled
+	 *
+	 * 0 = short slot time disable, 1 = short slot time enabled, -1 = do
+	 * not set (e.g., when 802.11g mode is not in use)
+	 */
+	int short_slot_time;
+
+	/**
+	 * ht_opmode - HT operation mode or -1 if HT not in use
+	 */
+	int ht_opmode;
+
+	/**
+	 * interworking - Whether Interworking is enabled
+	 */
+	int interworking;
+
+	/**
+	 * hessid - Homogeneous ESS identifier or %NULL if not set
+	 */
+	const u8 *hessid;
+
+	/**
+	 * access_network_type - Access Network Type (0..15)
+	 *
+	 * This is used for filtering Probe Request frames when Interworking is
+	 * enabled.
+	 */
+	u8 access_network_type;
+};
+
 /**
  * struct wpa_driver_capa - Driver capability information
  */
@@ -530,7 +723,7 @@
 #define WPA_DRIVER_FLAGS_DRIVER_IE	0x00000001
 /* Driver needs static WEP key setup after association command */
 #define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002
-#define WPA_DRIVER_FLAGS_USER_SPACE_MLME 0x00000004
+/* unused: 0x00000004 */
 /* Driver takes care of RSN 4-way handshake internally; PMK is configured with
  * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */
 #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008
@@ -571,9 +764,24 @@
 #define WPA_DRIVER_FLAGS_OFFCHANNEL_TX			0x00008000
 /* Driver indicates TX status events for EAPOL Data frames */
 #define WPA_DRIVER_FLAGS_EAPOL_TX_STATUS		0x00010000
+/* Driver indicates TX status events for Deauth/Disassoc frames */
+#define WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS		0x00020000
+/* Driver supports roaming (BSS selection) in firmware */
+#define WPA_DRIVER_FLAGS_BSS_SELECTION			0x00040000
+/* Driver supports operating as a TDLS peer */
+#define WPA_DRIVER_FLAGS_TDLS_SUPPORT			0x00080000
+/* Driver requires external TDLS setup/teardown/discovery */
+#define WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP		0x00100000
+/* Driver indicates support for Probe Response offloading in AP mode */
+#define WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD		0x00200000
+/* Driver supports U-APSD in AP mode */
+#define WPA_DRIVER_FLAGS_AP_UAPSD			0x00400000
 	unsigned int flags;
 
 	int max_scan_ssids;
+	int max_sched_scan_ssids;
+	int sched_scan_supported;
+	int max_match_sets;
 
 	/**
 	 * max_remain_on_chan - Maximum remain-on-channel duration in msec
@@ -585,6 +793,20 @@
 	 * supports in AP mode
 	 */
 	unsigned int max_stations;
+
+	/**
+	 * probe_resp_offloads - Bitmap of supported protocols by the driver
+	 * for Probe Response offloading.
+	 */
+/* Driver Probe Response offloading support for WPS ver. 1 */
+#define WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS		0x00000001
+/* Driver Probe Response offloading support for WPS ver. 2 */
+#define WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2		0x00000002
+/* Driver Probe Response offloading support for P2P */
+#define WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P		0x00000004
+/* Driver Probe Response offloading support for IEEE 802.11u (Interworking) */
+#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING	0x00000008
+	unsigned int probe_resp_offloads;
 };
 
 
@@ -610,6 +832,9 @@
 	size_t supp_rates_len;
 	u16 listen_interval;
 	const struct ieee80211_ht_capabilities *ht_capabilities;
+	u32 flags; /* bitmask of WPA_STA_* flags */
+	int set; /* Set STA parameters instead of add */
+	u8 qosinfo;
 };
 
 struct hostapd_freq_params {
@@ -661,6 +886,7 @@
 };
 
 struct wpa_init_params {
+	void *global_priv;
 	const u8 *bssid;
 	const char *ifname;
 	const u8 *ssid;
@@ -693,6 +919,7 @@
 #define WPA_STA_WMM BIT(1)
 #define WPA_STA_SHORT_PREAMBLE BIT(2)
 #define WPA_STA_MFP BIT(3)
+#define WPA_STA_TDLS_PEER BIT(4)
 
 /**
  * struct p2p_params - P2P parameters for driver-based P2P management
@@ -1079,91 +1306,21 @@
 	 * flags: Variable for returning hardware feature flags
 	 * Returns: Pointer to allocated hardware data on success or %NULL on
 	 * failure. Caller is responsible for freeing this.
-	 *
-	 * This function is only needed for drivers that export MLME
-	 * (management frame processing) to %wpa_supplicant or hostapd.
 	 */
 	struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv,
 							 u16 *num_modes,
 							 u16 *flags);
 
 	/**
-	 * set_channel - Set channel
-	 * @priv: Private driver interface data
-	 * @phymode: HOSTAPD_MODE_IEEE80211B, ..
-	 * @chan: IEEE 802.11 channel number
-	 * @freq: Frequency of the channel in MHz
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * This function is only needed for drivers that export MLME
-	 * (management frame processing) to wpa_supplicant.
-	 */
-	int (*set_channel)(void *priv, enum hostapd_hw_mode phymode, int chan,
-			   int freq);
-
-	/**
-	 * set_ssid - Set SSID
-	 * @priv: Private driver interface data
-	 * @ssid: SSID
-	 * @ssid_len: SSID length
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * This function is only needed for drivers that export MLME
-	 * (management frame processing) to wpa_supplicant.
-	 */
-	int (*set_ssid)(void *priv, const u8 *ssid, size_t ssid_len);
-
-	/**
-	 * set_bssid - Set BSSID
-	 * @priv: Private driver interface data
-	 * @bssid: BSSID
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * This function is only needed for drivers that export MLME
-	 * (management frame processing) to wpa_supplicant.
-	 */
-	int (*set_bssid)(void *priv, const u8 *bssid);
-
-	/**
 	 * send_mlme - Send management frame from MLME
 	 * @priv: Private driver interface data
 	 * @data: IEEE 802.11 management frame with IEEE 802.11 header
 	 * @data_len: Size of the management frame
+	 * @noack: Do not wait for this frame to be acked (disable retries)
 	 * Returns: 0 on success, -1 on failure
-	 *
-	 * This function is only needed for drivers that export MLME
-	 * (management frame processing) to wpa_supplicant.
 	 */
-	int (*send_mlme)(void *priv, const u8 *data, size_t data_len);
-
-	/**
-	 * mlme_add_sta - Add a STA entry into the driver/netstack
-	 * @priv: Private driver interface data
-	 * @addr: MAC address of the STA (e.g., BSSID of the AP)
-	 * @supp_rates: Supported rate set (from (Re)AssocResp); in IEEE 802.11
-	 * format (one octet per rate, 1 = 0.5 Mbps)
-	 * @supp_rates_len: Number of entries in supp_rates
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * This function is only needed for drivers that export MLME
-	 * (management frame processing) to wpa_supplicant. When the MLME code
-	 * completes association with an AP, this function is called to
-	 * configure the driver/netstack with a STA entry for data frame
-	 * processing (TX rate control, encryption/decryption).
-	 */
-	int (*mlme_add_sta)(void *priv, const u8 *addr, const u8 *supp_rates,
-			    size_t supp_rates_len);
-
-	/**
-	 * mlme_remove_sta - Remove a STA entry from the driver/netstack
-	 * @priv: Private driver interface data
-	 * @addr: MAC address of the STA (e.g., BSSID of the AP)
-	 * Returns: 0 on success, -1 on failure
-	 *
-	 * This function is only needed for drivers that export MLME
-	 * (management frame processing) to wpa_supplicant.
-	 */
-	int (*mlme_remove_sta)(void *priv, const u8 *addr);
+	int (*send_mlme)(void *priv, const u8 *data, size_t data_len,
+			 int noack);
 
 	/**
 	 * update_ft_ies - Update FT (IEEE 802.11r) IEs
@@ -1292,24 +1449,25 @@
 			    struct wpa_driver_auth_params *params);
 
 	/**
-	 * set_beacon - Set Beacon frame template
+	 * set_ap - Set Beacon and Probe Response information for AP mode
 	 * @priv: Private driver interface data
-	 * @head: Beacon head from IEEE 802.11 header to IEs before TIM IE
-	 * @head_len: Length of the head buffer in octets
-	 * @tail: Beacon tail following TIM IE
-	 * @tail_len: Length of the tail buffer in octets
-	 * @dtim_period: DTIM period
-	 * @beacon_int: Beacon interval
-	 * Returns: 0 on success, -1 on failure
+	 * @params: Parameters to use in AP mode
 	 *
-	 * This function is used to configure Beacon template for the driver in
+	 * This function is used to configure Beacon template and/or extra IEs
+	 * to add for Beacon and Probe Response frames for the driver in
 	 * AP mode. The driver is responsible for building the full Beacon
 	 * frame by concatenating the head part with TIM IE generated by the
-	 * driver/firmware and finishing with the tail part.
+	 * driver/firmware and finishing with the tail part. Depending on the
+	 * driver architectue, this can be done either by using the full
+	 * template or the set of additional IEs (e.g., WPS and P2P IE).
+	 * Similarly, Probe Response processing depends on the driver design.
+	 * If the driver (or firmware) takes care of replying to Probe Request
+	 * frames, the extra IEs provided here needs to be added to the Probe
+	 * Response frames.
+	 *
+	 * Returns: 0 on success, -1 on failure
 	 */
-	int (*set_beacon)(void *priv, const u8 *head, size_t head_len,
-			  const u8 *tail, size_t tail_len, int dtim_period,
-			  int beacon_int);
+	int (*set_ap)(void *priv, struct wpa_driver_ap_params *params);
 
 	/**
 	 * hapd_init - Initialize driver interface (hostapd only)
@@ -1318,7 +1476,7 @@
 	 * Returns: Pointer to private data, %NULL on failure
 	 *
 	 * This function is used instead of init() or init2() when the driver
-	 * wrapper is used withh hostapd.
+	 * wrapper is used with hostapd.
 	 */
 	void * (*hapd_init)(struct hostapd_data *hapd,
 			    struct wpa_init_params *params);
@@ -1338,8 +1496,10 @@
 	 * This is an optional function to configure the kernel driver to
 	 * enable/disable IEEE 802.1X support and set WPA/WPA2 parameters. This
 	 * can be left undefined (set to %NULL) if IEEE 802.1X support is
-	 * always enabled and the driver uses set_beacon() to set WPA/RSN IE
+	 * always enabled and the driver uses set_ap() to set WPA/RSN IE
 	 * for Beacon frames.
+	 *
+	 * DEPRECATED - use set_ap() instead
 	 */
 	int (*set_ieee8021x)(void *priv, struct wpa_bss_params *params);
 
@@ -1351,7 +1511,9 @@
 	 *
 	 * This is an optional function to configure privacy field in the
 	 * kernel driver for Beacon frames. This can be left undefined (set to
-	 * %NULL) if the driver uses the Beacon template from set_beacon().
+	 * %NULL) if the driver uses the Beacon template from set_ap().
+	 *
+	 * DEPRECATED - use set_ap() instead
 	 */
 	int (*set_privacy)(void *priv, int enabled);
 
@@ -1393,7 +1555,9 @@
 	 * This is an optional function to add information elements in the
 	 * kernel driver for Beacon and Probe Response frames. This can be left
 	 * undefined (set to %NULL) if the driver uses the Beacon template from
-	 * set_beacon().
+	 * set_ap().
+	 *
+	 * DEPRECATED - use set_ap() instead
 	 */
 	int (*set_generic_elem)(void *priv, const u8 *elem, size_t elem_len);
 
@@ -1467,8 +1631,7 @@
 	 * Returns: Length of the SSID on success, -1 on failure
 	 *
 	 * This function need not be implemented if the driver uses Beacon
-	 * template from set_beacon() and does not reply to Probe Request
-	 * frames.
+	 * template from set_ap() and does not reply to Probe Request frames.
 	 */
 	int (*hapd_get_ssid)(void *priv, u8 *buf, int len);
 
@@ -1478,6 +1641,8 @@
 	 * @buf: SSID
 	 * @len: Length of the SSID in octets
 	 * Returns: 0 on success, -1 on failure
+	 *
+	 * DEPRECATED - use set_ap() instead
 	 */
 	int (*hapd_set_ssid)(void *priv, const u8 *buf, int len);
 
@@ -1501,6 +1666,9 @@
 	 * This function is used to add a station entry to the driver once the
 	 * station has completed association. This is only used if the driver
 	 * does not take care of association processing.
+	 *
+	 * With TDLS, this function is also used to add or set (params->set 1)
+	 * TDLS peer entries.
 	 */
 	int (*sta_add)(void *priv, struct hostapd_sta_add_params *params);
 
@@ -1557,41 +1725,6 @@
 			     int total_flags, int flags_or, int flags_and);
 
 	/**
-	 * set_rate_sets - Set supported and basic rate sets (AP only)
-	 * @priv: Private driver interface data
-	 * @supp_rates: -1 terminated array of supported rates in 100 kbps
-	 * @basic_rates: -1 terminated array of basic rates in 100 kbps
-	 * @mode: hardware mode (HOSTAPD_MODE_*)
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates,
-			     int mode);
-
-	/**
-	 * set_cts_protect - Set CTS protection mode (AP only)
-	 * @priv: Private driver interface data
-	 * @value: Whether CTS protection is enabled
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*set_cts_protect)(void *priv, int value);
-
-	/**
-	 * set_preamble - Set preamble mode (AP only)
-	 * @priv: Private driver interface data
-	 * @value: Whether short preamble is enabled
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*set_preamble)(void *priv, int value);
-
-	/**
-	 * set_short_slot_time - Set short slot time (AP only)
-	 * @priv: Private driver interface data
-	 * @value: Whether short slot time is enabled
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*set_short_slot_time)(void *priv, int value);
-
-	/**
 	 * set_tx_queue_params - Set TX queue parameters
 	 * @priv: Private driver interface data
 	 * @queue: Queue number (0 = VO, 1 = VI, 2 = BE, 3 = BK)
@@ -1604,17 +1737,6 @@
 				   int cw_max, int burst_time);
 
 	/**
-	 * valid_bss_mask - Validate BSSID mask
-	 * @priv: Private driver interface data
-	 * @addr: Address
-	 * @mask: Mask
-	 * Returns: 0 if mask is valid, -1 if mask is not valid, 1 if mask can
-	 * be used, but the main interface address must be the first address in
-	 * the block if mask is applied
-	 */
-	int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask);
-
-	/**
 	 * if_add - Add a virtual interface
 	 * @priv: Private driver interface data
 	 * @type: Interface type
@@ -1709,19 +1831,6 @@
 	int (*set_radius_acl_expire)(void *priv, const u8 *mac);
 
 	/**
-	 * set_ht_params - Set HT parameters (AP only)
-	 * @priv: Private driver interface data
-	 * @ht_capab: HT Capabilities IE
-	 * @ht_capab_len: Length of ht_capab in octets
-	 * @ht_oper: HT Operation IE
-	 * @ht_oper_len: Length of ht_oper in octets
-	 * Returns: 0 on success, -1 on failure
-	 */
-	int (*set_ht_params)(void *priv,
-			     const u8 *ht_capab, size_t ht_capab_len,
-			     const u8 *ht_oper, size_t ht_oper_len);
-
-	/**
 	 * set_ap_wps_ie - Add WPS IE(s) into Beacon/Probe Response frames (AP)
 	 * @priv: Private driver interface data
 	 * @beacon: WPS IE(s) for Beacon frames or %NULL to remove extra IE(s)
@@ -1733,7 +1842,7 @@
 	 *
 	 * This is an optional function to add WPS IE in the kernel driver for
 	 * Beacon and Probe Response frames. This can be left undefined (set
-	 * to %NULL) if the driver uses the Beacon template from set_beacon()
+	 * to %NULL) if the driver uses the Beacon template from set_ap()
 	 * and does not process Probe Request frames. If the driver takes care
 	 * of (Re)Association frame processing, the assocresp buffer includes
 	 * WPS IE(s) that need to be added to (Re)Association Response frames
@@ -1746,6 +1855,8 @@
 	 * also used to provide Probe Response IEs for P2P Listen state
 	 * operations for drivers that generate the Probe Response frames
 	 * internally.
+	 *
+	 * DEPRECATED - use set_ap() instead
 	 */
 	int (*set_ap_wps_ie)(void *priv, const struct wpabuf *beacon,
 			     const struct wpabuf *proberesp,
@@ -1782,6 +1893,7 @@
 	 * @bssid: BSSID (Address 3)
 	 * @data: Frame body
 	 * @data_len: data length in octets
+	 @ @no_cck: Whether CCK rates must not be used to transmit this frame
 	 * Returns: 0 on success, -1 on failure
 	 *
 	 * This command can be used to request the driver to transmit an action
@@ -1799,7 +1911,7 @@
 	 */
 	int (*send_action)(void *priv, unsigned int freq, unsigned int wait,
 			   const u8 *dst, const u8 *src, const u8 *bssid,
-			   const u8 *data, size_t data_len);
+			   const u8 *data, size_t data_len, int no_cck);
 
 	/**
 	 * send_action_cancel_wait - Cancel action frame TX wait
@@ -1866,19 +1978,6 @@
 	int (*probe_req_report)(void *priv, int report);
 
 	/**
-	 * disable_11b_rates - Set whether IEEE 802.11b rates are used for TX
-	 * @priv: Private driver interface data
-	 * @disabled: Whether IEEE 802.11b rates are disabled
-	 * Returns: 0 on success, -1 on failure (or if not supported)
-	 *
-	 * This command is used to disable IEEE 802.11b rates (1, 2, 5.5, and
-	 * 11 Mbps) as TX rates for data and management frames. This can be
-	 * used to optimize channel use when there is no need to support IEEE
-	 * 802.11b-only devices.
-	 */
-	int (*disable_11b_rates)(void *priv, int disabled);
-
-	/**
 	 * deinit_ap - Deinitialize AP mode
 	 * @priv: Private driver interface data
 	 * Returns: 0 on success, -1 on failure (or if not supported)
@@ -1990,11 +2089,6 @@
 	int (*ampdu)(void *priv, int ampdu);
 
 	/**
-	 * set_intra_bss - Enables/Disables intra BSS bridging
-	 */
-	int (*set_intra_bss)(void *priv, int enabled);
-
-	/**
 	 * get_radio_name - Get physical radio name for the device
 	 * @priv: Private driver interface data
 	 * Returns: Radio name or %NULL if not known
@@ -2132,7 +2226,7 @@
 	 * struct wpa_driver_capa.
 	 */
 	int (*p2p_prov_disc_req)(void *priv, const u8 *peer_addr,
-				 u16 config_methods);
+				 u16 config_methods, int join);
 
 	/**
 	 * p2p_sd_request - Schedule a service discovery query
@@ -2232,7 +2326,7 @@
 	 * @status_code: Status Code or Reason Code to use (if needed)
 	 * @buf: TDLS IEs to add to the message
 	 * @len: Length of buf in octets
-	 * Returns: 0 on success, -1 on failure
+	 * Returns: 0 on success, negative (<0) on failure
 	 *
 	 * This optional function can be used to send packet to driver which is
 	 * responsible for receiving and sending all TDLS packets.
@@ -2241,6 +2335,16 @@
 			      u8 dialog_token, u16 status_code,
 			      const u8 *buf, size_t len);
 
+	/**
+	 * tdls_oper - Ask the driver to perform high-level TDLS operations
+	 * @priv: Private driver interface data
+	 * @oper: TDLS high-level operation. See %enum tdls_oper
+	 * @peer: Destination (peer) MAC address
+	 * Returns: 0 on success, negative (<0) on failure
+	 *
+	 * This optional function can be used to send high-level TDLS commands
+	 * to the driver.
+	 */
 	int (*tdls_oper)(void *priv, enum tdls_oper oper, const u8 *peer);
 
 	/**
@@ -2259,9 +2363,11 @@
 	 * This function can be used to set authentication algorithms for AP
 	 * mode when static WEP is used. If the driver uses user space MLME/SME
 	 * implementation, there is no need to implement this function.
+	 *
+	 * DEPRECATED - use set_ap() instead
 	 */
 	int (*set_authmode)(void *priv, int authmode);
-
+#ifdef ANDROID
 	/**
 	 * driver_cmd - execute driver-specific command
 	 * @priv: private driver interface data
@@ -2272,6 +2378,135 @@
 	 * Returns: 0 on success, -1 on failure
 	 */
 	 int (*driver_cmd)(void *priv, char *cmd, char *buf, size_t buf_len);
+#endif
+	/**
+	 * set_rekey_info - Set rekey information
+	 * @priv: Private driver interface data
+	 * @kek: Current KEK
+	 * @kck: Current KCK
+	 * @replay_ctr: Current EAPOL-Key Replay Counter
+	 *
+	 * This optional function can be used to provide information for the
+	 * driver/firmware to process EAPOL-Key frames in Group Key Handshake
+	 * while the host (including wpa_supplicant) is sleeping.
+	 */
+	void (*set_rekey_info)(void *priv, const u8 *kek, const u8 *kck,
+			       const u8 *replay_ctr);
+
+	/**
+	 * sta_assoc - Station association indication
+	 * @priv: Private driver interface data
+	 * @own_addr: Source address and BSSID for association frame
+	 * @addr: MAC address of the station to associate
+	 * @reassoc: flag to indicate re-association
+	 * @status: association response status code
+	 * @ie: assoc response ie buffer
+	 * @len: ie buffer length
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function indicates the driver to send (Re)Association
+	 * Response frame to the station.
+	 */
+	 int (*sta_assoc)(void *priv, const u8 *own_addr, const u8 *addr,
+			  int reassoc, u16 status, const u8 *ie, size_t len);
+
+	/**
+	 * sta_auth - Station authentication indication
+	 * @priv: Private driver interface data
+	 * @own_addr: Source address and BSSID for authentication frame
+	 * @addr: MAC address of the station to associate
+	 * @seq: authentication sequence number
+	 * @status: authentication response status code
+	 * @ie: authentication frame ie buffer
+	 * @len: ie buffer length
+	 *
+	 * This function indicates the driver to send Authentication frame
+	 * to the station.
+	 */
+	 int (*sta_auth)(void *priv, const u8 *own_addr, const u8 *addr,
+			 u16 seq, u16 status, const u8 *ie, size_t len);
+
+	/**
+	 * add_tspec - Add traffic stream
+	 * @priv: Private driver interface data
+	 * @addr: MAC address of the station to associate
+	 * @tspec_ie: tspec ie buffer
+	 * @tspec_ielen: tspec ie length
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function adds the traffic steam for the station
+	 * and fills the medium_time in tspec_ie.
+	 */
+	 int (*add_tspec)(void *priv, const u8 *addr, u8 *tspec_ie,
+			  size_t tspec_ielen);
+
+	/**
+	 * add_sta_node - Add a station node in the driver
+	 * @priv: Private driver interface data
+	 * @addr: MAC address of the station to add
+	 * @auth_alg: authentication algorithm used by the station
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function adds the station node in the driver, when
+	 * the station gets added by FT-over-DS.
+	 */
+	int (*add_sta_node)(void *priv, const u8 *addr, u16 auth_alg);
+
+	/**
+	 * sched_scan - Request the driver to initiate scheduled scan
+	 * @priv: Private driver interface data
+	 * @params: Scan parameters
+	 * @interval: Interval between scan cycles in milliseconds
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This operation should be used for scheduled scan offload to
+	 * the hardware. Every time scan results are available, the
+	 * driver should report scan results event for wpa_supplicant
+	 * which will eventually request the results with
+	 * wpa_driver_get_scan_results2(). This operation is optional
+	 * and if not provided or if it returns -1, we fall back to
+	 * normal host-scheduled scans.
+	 */
+	int (*sched_scan)(void *priv, struct wpa_driver_scan_params *params,
+			  u32 interval);
+
+	/**
+	 * stop_sched_scan - Request the driver to stop a scheduled scan
+	 * @priv: Private driver interface data
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This should cause the scheduled scan to be stopped and
+	 * results should stop being sent. Must be supported if
+	 * sched_scan is supported.
+	 */
+	int (*stop_sched_scan)(void *priv);
+
+	/**
+	 * poll_client - Probe (null data or such) the given station
+	 * @priv: Private driver interface data
+	 * @own_addr: MAC address of sending interface
+	 * @addr: MAC address of the station to probe
+	 * @qos: Indicates whether station is QoS station
+	 *
+	 * This function is used to verify whether an associated station is
+	 * still present. This function does not need to be implemented if the
+	 * driver provides such inactivity polling mechanism.
+	 */
+	void (*poll_client)(void *priv, const u8 *own_addr,
+			    const u8 *addr, int qos);
+#ifdef ANDROID_P2P
+	/**
+	 * go_switch_channel - Announce channel switch and migrate the GO to a
+	 * given frequency.
+	 * @priv: Private driver interface data
+	 * @freq: frequency in MHz
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is used to move the GO to the legacy STA channel to avoid
+	 * frequency conflict in single channel concurrency.
+	 */
+	int (*go_switch_channel)(void *priv, unsigned int freq);
+#endif
 };
 
 
@@ -2674,7 +2909,35 @@
 	/**
 	 * EVENT_IBSS_PEER_LOST - IBSS peer not reachable anymore
 	 */
-	EVENT_IBSS_PEER_LOST
+	EVENT_IBSS_PEER_LOST,
+
+	/**
+	 * EVENT_DRIVER_GTK_REKEY - Device/driver did GTK rekey
+	 *
+	 * This event carries the new replay counter to notify wpa_supplicant
+	 * of the current EAPOL-Key Replay Counter in case the driver/firmware
+	 * completed Group Key Handshake while the host (including
+	 * wpa_supplicant was sleeping).
+	 */
+	EVENT_DRIVER_GTK_REKEY,
+
+	/**
+	 * EVENT_SCHED_SCAN_STOPPED - Scheduled scan was stopped
+	 */
+	EVENT_SCHED_SCAN_STOPPED,
+
+	/**
+	 * EVENT_DRIVER_CLIENT_POLL_OK - Station responded to poll
+	 *
+	 * This event indicates that the station responded to the poll
+	 * initiated with @poll_client.
+	 */
+	EVENT_DRIVER_CLIENT_POLL_OK,
+
+	/**
+	 * EVENT_EAPOL_TX_STATUS - notify of EAPOL TX status
+	 */
+	EVENT_EAPOL_TX_STATUS
 };
 
 
@@ -2898,7 +3161,9 @@
 	 */
 	struct auth_info {
 		u8 peer[ETH_ALEN];
+		u8 bssid[ETH_ALEN];
 		u16 auth_type;
+		u16 auth_transaction;
 		u16 status_code;
 		const u8 *ies;
 		size_t ies_len;
@@ -2966,8 +3231,9 @@
 	 * struct rx_from_unknown - Data for EVENT_RX_FROM_UNKNOWN events
 	 */
 	struct rx_from_unknown {
-		const u8 *frame;
-		size_t len;
+		const u8 *bssid;
+		const u8 *addr;
+		int wds;
 	} rx_from_unknown;
 
 	/**
@@ -3075,6 +3341,18 @@
 		const u8 *sa;
 
 		/**
+		 * da - Destination address of the received Probe Request frame
+		 *	or %NULL if not available
+		 */
+		const u8 *da;
+
+		/**
+		 * bssid - BSSID of the received Probe Request frame or %NULL
+		 *	if not available
+		 */
+		const u8 *bssid;
+
+		/**
 		 * ie - IEs from the Probe Request body
 		 */
 		const u8 *ie;
@@ -3206,6 +3484,39 @@
 	struct ibss_peer_lost {
 		u8 peer[ETH_ALEN];
 	} ibss_peer_lost;
+
+	/**
+	 * struct driver_gtk_rekey - Data for EVENT_DRIVER_GTK_REKEY
+	 */
+	struct driver_gtk_rekey {
+		const u8 *bssid;
+		const u8 *replay_ctr;
+	} driver_gtk_rekey;
+
+	/**
+	 * struct client_poll - Data for EVENT_DRIVER_CLIENT_POLL_OK events
+	 * @addr: station address
+	 */
+	struct client_poll {
+		u8 addr[ETH_ALEN];
+	} client_poll;
+
+	/**
+	 * struct eapol_tx_status
+	 * @dst: Original destination
+	 * @data: Data starting with IEEE 802.1X header (!)
+	 * @data_len: Length of data
+	 * @ack: Indicates ack or lost frame
+	 *
+	 * This corresponds to hapd_send_eapol if the frame sent
+	 * there isn't just reported as EVENT_TX_STATUS.
+	 */
+	struct eapol_tx_status {
+		const u8 *dst;
+		const u8 *data;
+		int data_len;
+		int ack;
+	} eapol_tx_status;
 };
 
 /**
@@ -3258,4 +3569,10 @@
 	wpa_supplicant_event(ctx, EVENT_EAPOL_RX, &event);
 }
 
+/* driver_common.c */
+void wpa_scan_results_free(struct wpa_scan_results *res);
+
+/* Convert wpa_event_type to a string for logging */
+const char * event_to_string(enum wpa_event_type event);
+
 #endif /* DRIVER_H */
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index 1e78f6e..b17d1a6 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -34,7 +34,7 @@
  */
 #define ATH_WPS_IE
 
-#include "os/linux/include/ieee80211_external.h"
+#include "ieee80211_external.h"
 
 
 #ifdef CONFIG_WPS
@@ -45,7 +45,7 @@
 #endif
 #endif /* CONFIG_WPS */
 
-#include "wireless_copy.h"
+#include "linux_wext.h"
 
 #include "driver.h"
 #include "eloop.h"
@@ -641,6 +641,7 @@
 
 	wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__,
 		   (unsigned long) ie_len);
+	wpa_hexdump(MSG_DEBUG, "atheros: set_generic_elem", ie, ie_len);
 
 	wpabuf_free(drv->wpa_ie);
 	drv->wpa_ie = wpabuf_alloc_copy(ie, ie_len);
@@ -658,6 +659,8 @@
 			  wpabuf_len(drv->wps_beacon_ie));
 		app_ie->app_buflen = ie_len + wpabuf_len(drv->wps_beacon_ie);
 	}
+	wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF(Beacon)",
+		    app_ie->app_buf, app_ie->app_buflen);
 	set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, app_ie,
 		     sizeof(struct ieee80211req_getset_appiebuf) +
 		     app_ie->app_buflen);
@@ -672,6 +675,8 @@
 			wpabuf_len(drv->wps_probe_resp_ie);
 	} else
 		app_ie->app_buflen = ie_len;
+	wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF(ProbeResp)",
+		    app_ie->app_buf, app_ie->app_buflen);
 	set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, app_ie,
 		     sizeof(struct ieee80211req_getset_appiebuf) +
 		     app_ie->app_buflen);
@@ -748,6 +753,8 @@
 
 	os_memset(&event, 0, sizeof(event));
 	event.rx_probe_req.sa = mgmt->sa;
+	event.rx_probe_req.da = mgmt->da;
+	event.rx_probe_req.bssid = mgmt->bssid;
 	event.rx_probe_req.ie = mgmt->u.probe_req.variable;
 	event.rx_probe_req.ie_len =
 		len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
@@ -785,8 +792,9 @@
 	u8 buf[512];
 	struct ieee80211req_getset_appiebuf *beac_ie;
 
-	wpa_printf(MSG_DEBUG, "%s buflen = %lu", __func__,
-		   (unsigned long) len);
+	wpa_printf(MSG_DEBUG, "%s buflen = %lu frametype=%u", __func__,
+		   (unsigned long) len, frametype);
+	wpa_hexdump(MSG_DEBUG, "atheros: IE", ie, len);
 
 	beac_ie = (struct ieee80211req_getset_appiebuf *) buf;
 	beac_ie->app_frmtype = frametype;
@@ -797,11 +805,15 @@
 	if (((frametype == IEEE80211_APPIE_FRAME_BEACON) ||
 	     (frametype == IEEE80211_APPIE_FRAME_PROBE_RESP)) &&
 	    (drv->wpa_ie != NULL)) {
+		wpa_hexdump_buf(MSG_DEBUG, "atheros: Append WPA/RSN IE",
+				drv->wpa_ie);
 		os_memcpy(&(beac_ie->app_buf[len]), wpabuf_head(drv->wpa_ie),
 			  wpabuf_len(drv->wpa_ie));
 		beac_ie->app_buflen += wpabuf_len(drv->wpa_ie);
 	}
 
+	wpa_hexdump(MSG_DEBUG, "atheros: SET_APPIEBUF",
+		    beac_ie->app_buf, beac_ie->app_buflen);
 	return set80211priv(drv, IEEE80211_IOCTL_SET_APPIEBUF, beac_ie,
 			    sizeof(struct ieee80211req_getset_appiebuf) +
 			    beac_ie->app_buflen);
@@ -814,6 +826,11 @@
 {
 	struct atheros_driver_data *drv = priv;
 
+	wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - beacon", beacon);
+	wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - proberesp",
+			proberesp);
+	wpa_hexdump_buf(MSG_DEBUG, "atheros: set_ap_wps_ie - assocresp",
+			assocresp);
 	wpabuf_free(drv->wps_beacon_ie);
 	drv->wps_beacon_ie = beacon ? wpabuf_dup(beacon) : NULL;
 	wpabuf_free(drv->wps_probe_resp_ie);
@@ -1332,6 +1349,8 @@
 	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
 	iwr.u.essid.pointer = (caddr_t) buf;
 	iwr.u.essid.length = len;
+	iwr.u.essid.length = (len > IW_ESSID_MAX_SIZE) ?
+		IW_ESSID_MAX_SIZE : len;
 
 	if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
 		perror("ioctl[SIOCGIWESSID]");
@@ -1374,6 +1393,34 @@
 	return set80211param(priv, IEEE80211_PARAM_AUTHMODE, authmode);
 }
 
+static int atheros_set_ap(void *priv, struct wpa_driver_ap_params *params)
+{
+	/*
+	 * TODO: Use this to replace set_authmode, set_privacy, set_ieee8021x,
+	 * set_generic_elem, and hapd_set_ssid.
+	 */
+
+	wpa_printf(MSG_DEBUG, "atheros: set_ap - pairwise_ciphers=0x%x "
+		   "group_cipher=0x%x key_mgmt_suites=0x%x auth_algs=0x%x "
+		   "wpa_version=0x%x privacy=%d interworking=%d",
+		   params->pairwise_ciphers, params->group_cipher,
+		   params->key_mgmt_suites, params->auth_algs,
+		   params->wpa_version, params->privacy, params->interworking);
+	wpa_hexdump_ascii(MSG_DEBUG, "atheros: SSID",
+			  params->ssid, params->ssid_len);
+	if (params->hessid)
+		wpa_printf(MSG_DEBUG, "atheros: HESSID " MACSTR,
+			   MAC2STR(params->hessid));
+	wpa_hexdump_buf(MSG_DEBUG, "atheros: beacon_ies",
+			params->beacon_ies);
+	wpa_hexdump_buf(MSG_DEBUG, "atheros: proberesp_ies",
+			params->proberesp_ies);
+	wpa_hexdump_buf(MSG_DEBUG, "atheros: assocresp_ies",
+			params->assocresp_ies);
+
+	return 0;
+}
+
 const struct wpa_driver_ops wpa_driver_atheros_ops = {
 	.name			= "atheros",
 	.hapd_init		= atheros_init,
@@ -1396,4 +1443,5 @@
 	.commit			= atheros_commit,
 	.set_ap_wps_ie		= atheros_set_ap_wps_ie,
 	.set_authmode		= atheros_set_authmode,
+	.set_ap			= atheros_set_ap,
 };
diff --git a/src/drivers/driver_broadcom.c b/src/drivers/driver_broadcom.c
deleted file mode 100644
index cb88543..0000000
--- a/src/drivers/driver_broadcom.c
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * WPA Supplicant - driver interaction with old Broadcom wl.o driver
- * Copyright (c) 2004, Nikki Chumkov <nikki@gattaca.ru>
- * Copyright (c) 2004, Jouni Malinen <j@w1.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
- *
- * Please note that the newer Broadcom driver ("hybrid Linux driver") supports
- * Linux wireless extensions and does not need (or even work) with this old
- * driver wrapper. Use driver_wext.c with that driver.
- */
-
-#include "includes.h"
-
-#include <sys/ioctl.h>
-
-#include "common.h"
-
-#if 0
-#include <netpacket/packet.h>
-#include <net/ethernet.h>     /* the L2 protocols */
-#else
-#include <linux/if_packet.h>
-#include <linux/if_ether.h>   /* The L2 protocols */
-#endif
-#include <net/if.h>
-#include <typedefs.h>
-
-/* wlioctl.h is a Broadcom header file and it is available, e.g., from Linksys
- * WRT54G GPL tarball. */
-#include <wlioctl.h>
-
-#include "driver.h"
-#include "eloop.h"
-
-struct wpa_driver_broadcom_data {
-	void *ctx;
-	int ioctl_sock;
-	int event_sock;
-	char ifname[IFNAMSIZ + 1];
-};
-
-
-#ifndef WLC_DEAUTHENTICATE
-#define WLC_DEAUTHENTICATE 143
-#endif
-#ifndef WLC_DEAUTHENTICATE_WITH_REASON
-#define WLC_DEAUTHENTICATE_WITH_REASON 201
-#endif
-#ifndef WLC_SET_TKIP_COUNTERMEASURES
-#define WLC_SET_TKIP_COUNTERMEASURES 202
-#endif
-
-#if !defined(PSK_ENABLED) /* NEW driver interface */
-#define WL_VERSION 360130
-/* wireless authentication bit vector */
-#define WPA_ENABLED 1
-#define PSK_ENABLED 2
-                                                                                
-#define WAUTH_WPA_ENABLED(wauth)  ((wauth) & WPA_ENABLED)
-#define WAUTH_PSK_ENABLED(wauth)  ((wauth) & PSK_ENABLED)
-#define WAUTH_ENABLED(wauth)    ((wauth) & (WPA_ENABLED | PSK_ENABLED))
-
-#define WSEC_PRIMARY_KEY WL_PRIMARY_KEY
-
-typedef wl_wsec_key_t wsec_key_t;
-#endif
-
-typedef struct {
-	uint32 val;
-	struct ether_addr ea;
-	uint16 res;
-} wlc_deauth_t;
-
-
-static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx,
-					     void *timeout_ctx);
-
-static int broadcom_ioctl(struct wpa_driver_broadcom_data *drv, int cmd,
-			  void *buf, int len)
-{
-	struct ifreq ifr;
-	wl_ioctl_t ioc;
-	int ret = 0;
-
-	wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl(%s,%d,len=%d,val=%p)",
-		   drv->ifname, cmd, len, buf);
-	/* wpa_hexdump(MSG_MSGDUMP, "BROADCOM: wlioctl buf", buf, len); */
-
-	ioc.cmd = cmd;
-	ioc.buf = buf;
-	ioc.len = len;
-	os_strlcpy(ifr.ifr_name, drv->ifname, IFNAMSIZ);
-	ifr.ifr_data = (caddr_t) &ioc;
-	if ((ret = ioctl(drv->ioctl_sock, SIOCDEVPRIVATE, &ifr)) < 0) {
-		if (cmd != WLC_GET_MAGIC)
-			perror(ifr.ifr_name);
-		wpa_printf(MSG_MSGDUMP, "BROADCOM: wlioctl cmd=%d res=%d",
-			   cmd, ret);
-	}
-
-	return ret;
-}
-
-static int wpa_driver_broadcom_get_bssid(void *priv, u8 *bssid)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	if (broadcom_ioctl(drv, WLC_GET_BSSID, bssid, ETH_ALEN) == 0)
-		return 0;
-	
-	os_memset(bssid, 0, ETH_ALEN);
-	return -1;
-}
-
-static int wpa_driver_broadcom_get_ssid(void *priv, u8 *ssid)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	wlc_ssid_t s;
-	
-	if (broadcom_ioctl(drv, WLC_GET_SSID, &s, sizeof(s)) == -1)
-		return -1;
-
-	os_memcpy(ssid, s.SSID, s.SSID_len);
-	return s.SSID_len;
-}
-
-static int wpa_driver_broadcom_set_wpa(void *priv, int enable)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	unsigned int wauth, wsec;
-	struct ether_addr ea;
-
-	os_memset(&ea, enable ? 0xff : 0, sizeof(ea));
-	if (broadcom_ioctl(drv, WLC_GET_WPA_AUTH, &wauth, sizeof(wauth)) ==
-	    -1 ||
-	    broadcom_ioctl(drv, WLC_GET_WSEC, &wsec, sizeof(wsec)) == -1)
-		return -1;
-
-	if (enable) {
-		wauth = PSK_ENABLED;
-		wsec = TKIP_ENABLED;
-	} else {
-		wauth = 255;
-		wsec &= ~(TKIP_ENABLED | AES_ENABLED);
-	}
-
-	if (broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wauth, sizeof(wauth)) ==
-	    -1 ||
-	    broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) == -1)
-		return -1;
-
-	/* FIX: magic number / error handling? */
-	broadcom_ioctl(drv, 122, &ea, sizeof(ea));
-
-	return 0;
-}
-
-static int wpa_driver_broadcom_set_key(const char *ifname, void *priv,
-				       enum wpa_alg alg,
-				       const u8 *addr, int key_idx, int set_tx,
-				       const u8 *seq, size_t seq_len,
-				       const u8 *key, size_t key_len)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	int ret;
-	wsec_key_t wkt;
-
-	os_memset(&wkt, 0, sizeof wkt);
-	wpa_printf(MSG_MSGDUMP, "BROADCOM: SET %sKEY[%d] alg=%d",
-		   set_tx ? "PRIMARY " : "", key_idx, alg);
-	if (key && key_len > 0)
-		wpa_hexdump_key(MSG_MSGDUMP, "BROADCOM: key", key, key_len);
-
-	switch (alg) {
-	case WPA_ALG_NONE:
-		wkt.algo = CRYPTO_ALGO_OFF;
-		break;
-	case WPA_ALG_WEP:
-		wkt.algo = CRYPTO_ALGO_WEP128; /* CRYPTO_ALGO_WEP1? */
-		break;
-	case WPA_ALG_TKIP:
-		wkt.algo = 0; /* CRYPTO_ALGO_TKIP? */
-		break;
-	case WPA_ALG_CCMP:
-		wkt.algo = 0; /* CRYPTO_ALGO_AES_CCM;
-			       * AES_OCB_MSDU, AES_OCB_MPDU? */
-		break;
-	default:
-		wkt.algo = CRYPTO_ALGO_NALG;
-		break;
-	}
-
-	if (seq && seq_len > 0)
-		wpa_hexdump(MSG_MSGDUMP, "BROADCOM: SEQ", seq, seq_len);
-
-	if (addr)
-		wpa_hexdump(MSG_MSGDUMP, "BROADCOM: addr", addr, ETH_ALEN);
-
-	wkt.index = key_idx;
-	wkt.len = key_len;
-	if (key && key_len > 0) {
-		os_memcpy(wkt.data, key, key_len);
-		if (key_len == 32) {
-			/* hack hack hack XXX */
-			os_memcpy(&wkt.data[16], &key[24], 8);
-			os_memcpy(&wkt.data[24], &key[16], 8);
-		}
-	}
-	/* wkt.algo = CRYPTO_ALGO_...; */
-	wkt.flags = set_tx ? 0 : WSEC_PRIMARY_KEY;
-	if (addr && set_tx)
-		os_memcpy(&wkt.ea, addr, sizeof(wkt.ea));
-	ret = broadcom_ioctl(drv, WLC_SET_KEY, &wkt, sizeof(wkt));
-	if (addr && set_tx) {
-		/* FIX: magic number / error handling? */
-		broadcom_ioctl(drv, 121, &wkt.ea, sizeof(wkt.ea));
-	}
-	return ret;
-}
-
-
-static void wpa_driver_broadcom_event_receive(int sock, void *ctx,
-					      void *sock_ctx)
-{
-	char buf[8192];
-	int left;
-	wl_wpa_header_t *wwh;
-	union wpa_event_data data;
-	u8 *resp_ies = NULL;
-
-	if ((left = recv(sock, buf, sizeof buf, 0)) < 0)
-		return;
-
-	wpa_hexdump(MSG_DEBUG, "RECEIVE EVENT", (u8 *) buf, left);
-
-	if ((size_t) left < sizeof(wl_wpa_header_t))
-		return;
-
-	wwh = (wl_wpa_header_t *) buf;
-
-	if (wwh->snap.type != WL_WPA_ETHER_TYPE)
-		return;
-	if (os_memcmp(&wwh->snap, wl_wpa_snap_template, 6) != 0)
-		return;
-
-	os_memset(&data, 0, sizeof(data));
-
-	switch (wwh->type) {
-	case WLC_ASSOC_MSG:
-		left -= WL_WPA_HEADER_LEN;
-		wpa_printf(MSG_DEBUG, "BROADCOM: ASSOC MESSAGE (left: %d)",
-			   left);
-		if (left > 0) {
-			resp_ies = os_malloc(left);
-			if (resp_ies == NULL)
-				return;
-			os_memcpy(resp_ies, buf + WL_WPA_HEADER_LEN, left);
-			data.assoc_info.resp_ies = resp_ies;
-			data.assoc_info.resp_ies_len = left;
-		}
-
-		wpa_supplicant_event(ctx, EVENT_ASSOC, &data);
-		os_free(resp_ies);
-		break;
-	case WLC_DISASSOC_MSG:
-		wpa_printf(MSG_DEBUG, "BROADCOM: DISASSOC MESSAGE");
-		wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
-		break;
-	case WLC_PTK_MIC_MSG:
-		wpa_printf(MSG_DEBUG, "BROADCOM: PTK MIC MSG MESSAGE");
-		data.michael_mic_failure.unicast = 1;
-		wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
-		break;
-	case WLC_GTK_MIC_MSG:
-		wpa_printf(MSG_DEBUG, "BROADCOM: GTK MIC MSG MESSAGE");
-		data.michael_mic_failure.unicast = 0;
-		wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "BROADCOM: UNKNOWN MESSAGE (%d)",
-			   wwh->type);
-		break;
-	}
-}	
-
-static void * wpa_driver_broadcom_init(void *ctx, const char *ifname)
-{
-	int s;
-	struct sockaddr_ll ll;
-	struct wpa_driver_broadcom_data *drv;
-	struct ifreq ifr;
-
-	/* open socket to kernel */
-	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		perror("socket");
-		return NULL;
-	}
-	/* do it */
-	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
-	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
-		perror(ifr.ifr_name);
-		return NULL;
-	}
-
-
-	drv = os_zalloc(sizeof(*drv));
-	if (drv == NULL)
-		return NULL;
-	drv->ctx = ctx;
-	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
-	drv->ioctl_sock = s;
-
-	s = socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2));
-	if (s < 0) {
-		perror("socket(PF_PACKET, SOCK_RAW, ntohs(ETH_P_802_2))");
-		close(drv->ioctl_sock);
-		os_free(drv);
-		return NULL;
-	}
-
-	os_memset(&ll, 0, sizeof(ll));
-	ll.sll_family = AF_PACKET;
-	ll.sll_protocol = ntohs(ETH_P_802_2);
-	ll.sll_ifindex = ifr.ifr_ifindex;
-	ll.sll_hatype = 0;
-	ll.sll_pkttype = PACKET_HOST;
-	ll.sll_halen = 0;
-
-	if (bind(s, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
-		perror("bind(netlink)");
-		close(s);
-		close(drv->ioctl_sock);
-		os_free(drv);
-		return NULL;
-	}
-
-	eloop_register_read_sock(s, wpa_driver_broadcom_event_receive, ctx,
-				 NULL);
-	drv->event_sock = s;
-	wpa_driver_broadcom_set_wpa(drv, 1);
-
-	return drv;
-}
-
-static void wpa_driver_broadcom_deinit(void *priv)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	wpa_driver_broadcom_set_wpa(drv, 0);
-	eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx);
-	eloop_unregister_read_sock(drv->event_sock);
-	close(drv->event_sock);
-	close(drv->ioctl_sock);
-	os_free(drv);
-}
-
-static int wpa_driver_broadcom_set_countermeasures(void *priv,
-						   int enabled)
-{
-#if 0
-	struct wpa_driver_broadcom_data *drv = priv;
-	/* FIX: ? */
-	return broadcom_ioctl(drv, WLC_SET_TKIP_COUNTERMEASURES, &enabled,
-			      sizeof(enabled));
-#else
-	return 0;
-#endif
-}
-
-static int wpa_driver_broadcom_set_drop_unencrypted(void *priv, int enabled)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	/* SET_EAP_RESTRICT, SET_WEP_RESTRICT */
-	int _restrict = (enabled ? 1 : 0);
-	
-	if (broadcom_ioctl(drv, WLC_SET_WEP_RESTRICT, 
-			   &_restrict, sizeof(_restrict)) < 0 ||
-	    broadcom_ioctl(drv, WLC_SET_EAP_RESTRICT,
-			   &_restrict, sizeof(_restrict)) < 0)
-		return -1;
-
-	return 0;
-}
-
-static void wpa_driver_broadcom_scan_timeout(void *eloop_ctx,
-					     void *timeout_ctx)
-{
-	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
-	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
-}
-
-static int wpa_driver_broadcom_scan(void *priv,
-				    struct wpa_driver_scan_params *params)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	wlc_ssid_t wst = { 0, "" };
-	const u8 *ssid = params->ssids[0].ssid;
-	size_t ssid_len = params->ssids[0].ssid_len;
-
-	if (ssid && ssid_len > 0 && ssid_len <= sizeof(wst.SSID)) {
-		wst.SSID_len = ssid_len;
-		os_memcpy(wst.SSID, ssid, ssid_len);
-	}
-	
-	if (broadcom_ioctl(drv, WLC_SCAN, &wst, sizeof(wst)) < 0)
-		return -1;
-
-	eloop_cancel_timeout(wpa_driver_broadcom_scan_timeout, drv, drv->ctx);
-	eloop_register_timeout(3, 0, wpa_driver_broadcom_scan_timeout, drv,
-			       drv->ctx);
-	return 0;
-}
-
-
-static const int frequency_list[] = { 
-	2412, 2417, 2422, 2427, 2432, 2437, 2442,
-	2447, 2452, 2457, 2462, 2467, 2472, 2484 
-};
-
-struct bss_ie_hdr {
-	u8 elem_id;
-	u8 len;
-	u8 oui[3];
-	/* u8 oui_type; */
-	/* u16 version; */
-} __attribute__ ((packed));
-
-static struct wpa_scan_results *
-wpa_driver_broadcom_get_scan_results(void *priv)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	char *buf;
-	wl_scan_results_t *wsr;
-	wl_bss_info_t *wbi;
-	size_t ap_num;
-	struct wpa_scan_results *res;
-
-	buf = os_malloc(WLC_IOCTL_MAXLEN);
-	if (buf == NULL)
-		return NULL;
-
-	wsr = (wl_scan_results_t *) buf;
-
-	wsr->buflen = WLC_IOCTL_MAXLEN - sizeof(wsr);
-	wsr->version = 107;
-	wsr->count = 0;
-
-	if (broadcom_ioctl(drv, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0) {
-		os_free(buf);
-		return NULL;
-	}
-
-	res = os_zalloc(sizeof(*res));
-	if (res == NULL) {
-		os_free(buf);
-		return NULL;
-	}
-
-	res->res = os_zalloc(wsr->count * sizeof(struct wpa_scan_res *));
-	if (res->res == NULL) {
-		os_free(res);
-		os_free(buf);
-		return NULL;
-	}
-
-	for (ap_num = 0, wbi = wsr->bss_info; ap_num < wsr->count; ++ap_num) {
-		struct wpa_scan_res *r;
-		r = os_malloc(sizeof(*r) + wbi->ie_length);
-		if (r == NULL)
-			break;
-		res->res[res->num++] = r;
-
-		os_memcpy(r->bssid, &wbi->BSSID, ETH_ALEN);
-		r->freq = frequency_list[wbi->channel - 1];
-		/* get ie's */
-		os_memcpy(r + 1, wbi + 1, wbi->ie_length);
-		r->ie_len = wbi->ie_length;
-
-		wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length);
-	}
-
-	wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%lu "
-		   "BSSes)",
-		   wsr->buflen, (unsigned long) ap_num);
-	
-	os_free(buf);
-	return res;
-	}
-
-static int wpa_driver_broadcom_deauthenticate(void *priv, const u8 *addr,
-					      int reason_code)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	wlc_deauth_t wdt;
-	wdt.val = reason_code;
-	os_memcpy(&wdt.ea, addr, sizeof wdt.ea);
-	wdt.res = 0x7fff;
-	return broadcom_ioctl(drv, WLC_DEAUTHENTICATE_WITH_REASON, &wdt,
-			      sizeof(wdt));
-}
-
-static int wpa_driver_broadcom_disassociate(void *priv, const u8 *addr,
-					    int reason_code)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	return broadcom_ioctl(drv, WLC_DISASSOC, NULL, 0);
-}
-
-static int
-wpa_driver_broadcom_associate(void *priv,
-			      struct wpa_driver_associate_params *params)
-{
-	struct wpa_driver_broadcom_data *drv = priv;
-	wlc_ssid_t s;
-	int infra = 1;
-	int auth = 0;
-	int wsec = 4;
-	int dummy;
-	int wpa_auth;
-	int ret;
-
-	ret = wpa_driver_broadcom_set_drop_unencrypted(
-		drv, params->drop_unencrypted);
-
-	s.SSID_len = params->ssid_len;
-	os_memcpy(s.SSID, params->ssid, params->ssid_len);
-
-	switch (params->pairwise_suite) {
-	case CIPHER_WEP40:
-	case CIPHER_WEP104:
-		wsec = 1;
-		break;
-
-	case CIPHER_TKIP:
-		wsec = 2;
-		break;
-
-	case CIPHER_CCMP:
-		wsec = 4;
-		break;
-
-	default:
-		wsec = 0;
-		break;
-	}
-
-	switch (params->key_mgmt_suite) {
-	case KEY_MGMT_802_1X:
-		wpa_auth = 1;
-		break;
-
-	case KEY_MGMT_PSK:
-		wpa_auth = 2;
-		break;
-
-	default:
-		wpa_auth = 255;
-		break;
-	}
-
-	/* printf("broadcom_associate: %u %u %u\n", pairwise_suite,
-	 * group_suite, key_mgmt_suite);
-	 * broadcom_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(wsec));
-	 * wl join uses wlc_sec_wep here, not wlc_set_wsec */
-
-	if (broadcom_ioctl(drv, WLC_SET_WSEC, &wsec, sizeof(wsec)) < 0 ||
-	    broadcom_ioctl(drv, WLC_SET_WPA_AUTH, &wpa_auth,
-			   sizeof(wpa_auth)) < 0 ||
-	    broadcom_ioctl(drv, WLC_GET_WEP, &dummy, sizeof(dummy)) < 0 ||
-	    broadcom_ioctl(drv, WLC_SET_INFRA, &infra, sizeof(infra)) < 0 ||
-	    broadcom_ioctl(drv, WLC_SET_AUTH, &auth, sizeof(auth)) < 0 ||
-	    broadcom_ioctl(drv, WLC_SET_WEP, &wsec, sizeof(wsec)) < 0 ||
-	    broadcom_ioctl(drv, WLC_SET_SSID, &s, sizeof(s)) < 0)
-		return -1;
-
-	return ret;
-}
-
-const struct wpa_driver_ops wpa_driver_broadcom_ops = {
-	.name = "broadcom",
-	.desc = "Broadcom wl.o driver",
-	.get_bssid = wpa_driver_broadcom_get_bssid,
-	.get_ssid = wpa_driver_broadcom_get_ssid,
-	.set_key = wpa_driver_broadcom_set_key,
-	.init = wpa_driver_broadcom_init,
-	.deinit = wpa_driver_broadcom_deinit,
-	.set_countermeasures = wpa_driver_broadcom_set_countermeasures,
-	.scan2 = wpa_driver_broadcom_scan,
-	.get_scan_results2 = wpa_driver_broadcom_get_scan_results,
-	.deauthenticate = wpa_driver_broadcom_deauthenticate,
-	.disassociate = wpa_driver_broadcom_disassociate,
-	.associate = wpa_driver_broadcom_associate,
-};
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
new file mode 100644
index 0000000..26ca8d6
--- /dev/null
+++ b/src/drivers/driver_common.c
@@ -0,0 +1,90 @@
+/*
+ * Common driver-related functions
+ * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+#include "utils/common.h"
+#include "driver.h"
+
+void wpa_scan_results_free(struct wpa_scan_results *res)
+{
+	size_t i;
+
+	if (res == NULL)
+		return;
+
+	for (i = 0; i < res->num; i++)
+		os_free(res->res[i]);
+	os_free(res->res);
+	os_free(res);
+}
+
+
+const char * event_to_string(enum wpa_event_type event)
+{
+#define E2S(n) case EVENT_ ## n: return #n
+	switch (event) {
+	E2S(ASSOC);
+	E2S(DISASSOC);
+	E2S(MICHAEL_MIC_FAILURE);
+	E2S(SCAN_RESULTS);
+	E2S(ASSOCINFO);
+	E2S(INTERFACE_STATUS);
+	E2S(PMKID_CANDIDATE);
+	E2S(STKSTART);
+	E2S(TDLS);
+	E2S(FT_RESPONSE);
+	E2S(IBSS_RSN_START);
+	E2S(AUTH);
+	E2S(DEAUTH);
+	E2S(ASSOC_REJECT);
+	E2S(AUTH_TIMED_OUT);
+	E2S(ASSOC_TIMED_OUT);
+	E2S(FT_RRB_RX);
+	E2S(WPS_BUTTON_PUSHED);
+	E2S(TX_STATUS);
+	E2S(RX_FROM_UNKNOWN);
+	E2S(RX_MGMT);
+	E2S(RX_ACTION);
+	E2S(REMAIN_ON_CHANNEL);
+	E2S(CANCEL_REMAIN_ON_CHANNEL);
+	E2S(MLME_RX);
+	E2S(RX_PROBE_REQ);
+	E2S(NEW_STA);
+	E2S(EAPOL_RX);
+	E2S(SIGNAL_CHANGE);
+	E2S(INTERFACE_ENABLED);
+	E2S(INTERFACE_DISABLED);
+	E2S(CHANNEL_LIST_CHANGED);
+	E2S(INTERFACE_UNAVAILABLE);
+	E2S(BEST_CHANNEL);
+	E2S(UNPROT_DEAUTH);
+	E2S(UNPROT_DISASSOC);
+	E2S(STATION_LOW_ACK);
+	E2S(P2P_DEV_FOUND);
+	E2S(P2P_GO_NEG_REQ_RX);
+	E2S(P2P_GO_NEG_COMPLETED);
+	E2S(P2P_PROV_DISC_REQUEST);
+	E2S(P2P_PROV_DISC_RESPONSE);
+	E2S(P2P_SD_REQUEST);
+	E2S(P2P_SD_RESPONSE);
+	E2S(IBSS_PEER_LOST);
+	E2S(DRIVER_GTK_REKEY);
+	E2S(SCHED_SCAN_STOPPED);
+	E2S(DRIVER_CLIENT_POLL_OK);
+	E2S(EAPOL_TX_STATUS);
+	}
+
+	return "UNKNOWN";
+#undef E2S
+}
diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c
index e855c1b..8fc0efd 100644
--- a/src/drivers/driver_hostap.c
+++ b/src/drivers/driver_hostap.c
@@ -15,7 +15,7 @@
 #include "includes.h"
 #include <sys/ioctl.h>
 
-#include "wireless_copy.h"
+#include "linux_wext.h"
 #include "common.h"
 #include "driver.h"
 #include "driver_wext.h"
@@ -23,8 +23,6 @@
 #include "driver_hostap.h"
 
 
-#ifdef HOSTAPD
-
 #include <net/if_arp.h>
 #include <netpacket/packet.h>
 
@@ -32,6 +30,7 @@
 #include "netlink.h"
 #include "linux_ioctl.h"
 #include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
 
 
 /* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X
@@ -84,8 +83,8 @@
 
 	sa = hdr->addr2;
 	os_memset(&event, 0, sizeof(event));
-	event.rx_from_unknown.frame = buf;
-	event.rx_from_unknown.len = len;
+	event.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);
+	event.rx_from_unknown.addr = sa;
 	wpa_supplicant_event(drv->hapd, EVENT_RX_FROM_UNKNOWN, &event);
 
 	pos = (u8 *) (hdr + 1);
@@ -148,7 +147,6 @@
 {
 	struct ieee80211_hdr *hdr;
 	u16 fc, extra_len, type, stype;
-	unsigned char *extra = NULL;
 	size_t data_len = len;
 	int ver;
 	union wpa_event_data event;
@@ -185,7 +183,6 @@
 			return;
 		}
 		len -= extra_len + 2;
-		extra = buf + len;
 	} else if (ver == 1 || ver == 2) {
 		handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0);
 		return;
@@ -273,7 +270,7 @@
 }
 
 
-static int hostap_send_mlme(void *priv, const u8 *msg, size_t len)
+static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack)
 {
 	struct hostap_driver_data *drv = priv;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg;
@@ -322,7 +319,7 @@
 	pos += 2;
 	memcpy(pos, data, data_len);
 
-	res = hostap_send_mlme(drv, (u8 *) hdr, len);
+	res = hostap_send_mlme(drv, (u8 *) hdr, len, 0);
 	if (res < 0) {
 		wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - "
 			   "failed: %d (%s)",
@@ -1054,7 +1051,26 @@
 	memcpy(mgmt.bssid, own_addr, ETH_ALEN);
 	mgmt.u.deauth.reason_code = host_to_le16(reason);
 	return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
-				sizeof(mgmt.u.deauth));
+				sizeof(mgmt.u.deauth), 0);
+}
+
+
+static int hostap_set_freq(void *priv, struct hostapd_freq_params *freq)
+{
+	struct hostap_driver_data *drv = priv;
+	struct iwreq iwr;
+
+	os_memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+	iwr.u.freq.m = freq->channel;
+	iwr.u.freq.e = 0;
+
+	if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
+		perror("ioctl[SIOCSIWFREQ]");
+		return -1;
+	}
+
+	return 0;
 }
 
 
@@ -1072,7 +1088,7 @@
 	memcpy(mgmt.bssid, own_addr, ETH_ALEN);
 	mgmt.u.disassoc.reason_code = host_to_le16(reason);
 	return  hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
-				 sizeof(mgmt.u.disassoc));
+				 sizeof(mgmt.u.disassoc), 0);
 }
 
 
@@ -1126,492 +1142,38 @@
 	return mode;
 }
 
-#else /* HOSTAPD */
 
-struct wpa_driver_hostap_data {
-	void *wext; /* private data for driver_wext */
-	void *ctx;
-	char ifname[IFNAMSIZ + 1];
-	int sock;
-	int current_mode; /* infra/adhoc */
-};
-
-
-static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg);
-
-
-static int hostapd_ioctl(struct wpa_driver_hostap_data *drv,
-			 struct prism2_hostapd_param *param,
-			 int len, int show_err)
+static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr,
+					  const u8 *addr, int qos)
 {
-	struct iwreq iwr;
+	struct ieee80211_hdr hdr;
 
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.data.pointer = (caddr_t) param;
-	iwr.u.data.length = len;
+	os_memset(&hdr, 0, sizeof(hdr));
 
-	if (ioctl(drv->sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
-		int ret = errno;
-		if (show_err)
-			perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
-		return ret;
-	}
+	/*
+	 * WLAN_FC_STYPE_NULLFUNC would be more appropriate,
+	 * but it is apparently not retried so TX Exc events
+	 * are not received for it.
+	 * This is the reason the driver overrides the default
+	 * handling.
+	 */
+	hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA,
+					 WLAN_FC_STYPE_DATA);
 
-	return 0;
+	hdr.frame_control |=
+		host_to_le16(WLAN_FC_FROMDS);
+	os_memcpy(hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
+	os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
+	os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
+
+	hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0);
 }
 
 
-static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data *drv,
-					const u8 *wpa_ie, size_t wpa_ie_len)
-{
-	struct prism2_hostapd_param *param;
-	int res;
-	size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len;
-	if (blen < sizeof(*param))
-		blen = sizeof(*param);
-
-	param = os_zalloc(blen);
-	if (param == NULL)
-		return -1;
-
-	param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
-	param->u.generic_elem.len = wpa_ie_len;
-	os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len);
-	res = hostapd_ioctl(drv, param, blen, 1);
-
-	os_free(param);
-
-	return res;
-}
-
-
-static int prism2param(struct wpa_driver_hostap_data *drv, int param,
-		       int value)
-{
-	struct iwreq iwr;
-	int *i, ret = 0;
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	i = (int *) iwr.u.name;
-	*i++ = param;
-	*i++ = value;
-
-	if (ioctl(drv->sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
-		perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
-		ret = -1;
-	}
-	return ret;
-}
-
-
-static int wpa_driver_hostap_set_wpa(void *priv, int enabled)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	int ret = 0;
-
-	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
-
-	if (!enabled && wpa_driver_hostap_set_wpa_ie(drv, NULL, 0) < 0)
-		ret = -1;
-	if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING, enabled ? 2 : 0) < 0)
-		ret = -1;
-	if (prism2param(drv, PRISM2_PARAM_WPA, enabled) < 0)
-		ret = -1;
-
-	return ret;
-}
-
-
-static void show_set_key_error(struct prism2_hostapd_param *param)
-{
-	switch (param->u.crypt.err) {
-	case HOSTAP_CRYPT_ERR_UNKNOWN_ALG:
-		wpa_printf(MSG_INFO, "Unknown algorithm '%s'.",
-			   param->u.crypt.alg);
-		wpa_printf(MSG_INFO, "You may need to load kernel module to "
-			   "register that algorithm.");
-		wpa_printf(MSG_INFO, "E.g., 'modprobe hostap_crypt_wep' for "
-			   "WEP.");
-		break;
-	case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR:
-		wpa_printf(MSG_INFO, "Unknown address " MACSTR ".",
-			   MAC2STR(param->sta_addr));
-		break;
-	case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED:
-		wpa_printf(MSG_INFO, "Crypt algorithm initialization failed.");
-		break;
-	case HOSTAP_CRYPT_ERR_KEY_SET_FAILED:
-		wpa_printf(MSG_INFO, "Key setting failed.");
-		break;
-	case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED:
-		wpa_printf(MSG_INFO, "TX key index setting failed.");
-		break;
-	case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED:
-		wpa_printf(MSG_INFO, "Card configuration failed.");
-		break;
-	}
-}
-
-
-static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
-				     enum wpa_alg alg, const u8 *addr,
-				     int key_idx, int set_tx,
-				     const u8 *seq, size_t seq_len,
-				     const u8 *key, size_t key_len)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	struct prism2_hostapd_param *param;
-	u8 *buf;
-	size_t blen;
-	int ret = 0;
-	char *alg_name;
-
-	switch (alg) {
-	case WPA_ALG_NONE:
-		alg_name = "none";
-		break;
-	case WPA_ALG_WEP:
-		alg_name = "WEP";
-		break;
-	case WPA_ALG_TKIP:
-		alg_name = "TKIP";
-		break;
-	case WPA_ALG_CCMP:
-		alg_name = "CCMP";
-		break;
-	default:
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
-		   "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
-		   (unsigned long) seq_len, (unsigned long) key_len);
-
-	if (seq_len > 8)
-		return -2;
-
-	blen = sizeof(*param) + key_len;
-	buf = os_zalloc(blen);
-	if (buf == NULL)
-		return -1;
-
-	param = (struct prism2_hostapd_param *) buf;
-	param->cmd = PRISM2_SET_ENCRYPTION;
-	/* TODO: In theory, STA in client mode can use five keys; four default
-	 * keys for receiving (with keyidx 0..3) and one individual key for
-	 * both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
-	 * keyidx 0 is reserved for this unicast use and default keys can only
-	 * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
-	 * This should be fine for more or less all cases, but for completeness
-	 * sake, the driver could be enhanced to support the missing key. */
-#if 0
-	if (addr == NULL)
-		os_memset(param->sta_addr, 0xff, ETH_ALEN);
-	else
-		os_memcpy(param->sta_addr, addr, ETH_ALEN);
-#else
-	os_memset(param->sta_addr, 0xff, ETH_ALEN);
-#endif
-	os_strlcpy((char *) param->u.crypt.alg, alg_name,
-		   HOSTAP_CRYPT_ALG_NAME_LEN);
-	param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
-	param->u.crypt.idx = key_idx;
-	if (seq)
-		os_memcpy(param->u.crypt.seq, seq, seq_len);
-	param->u.crypt.key_len = key_len;
-	os_memcpy((u8 *) (param + 1), key, key_len);
-
-	if (hostapd_ioctl(drv, param, blen, 1)) {
-		wpa_printf(MSG_WARNING, "Failed to set encryption.");
-		show_set_key_error(param);
-		ret = -1;
-	}
-	os_free(buf);
-
-	return ret;
-}
-
-
-static int wpa_driver_hostap_set_countermeasures(void *priv, int enabled)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
-	return prism2param(drv, PRISM2_PARAM_TKIP_COUNTERMEASURES, enabled);
-}
-
-
-static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data *drv,
-				   int type)
-{
-	struct iwreq iwr;
-	int *i, ret = 0;
-
-	wpa_printf(MSG_DEBUG, "%s: type=%d", __FUNCTION__, type);
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	i = (int *) iwr.u.name;
-	*i++ = type;
-
-	if (ioctl(drv->sock, PRISM2_IOCTL_RESET, &iwr) < 0) {
-	        perror("ioctl[PRISM2_IOCTL_RESET]");
-	        ret = -1;
-	}
-	return ret;
-}
-
-
-static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data *drv,
-				  const u8 *addr, int cmd, int reason_code)
-{
-	struct prism2_hostapd_param param;
-	int ret;
-
-	/* There does not seem to be a better way of deauthenticating or
-	 * disassociating with Prism2/2.5/3 than sending the management frame
-	 * and then resetting the Port0 to make sure both the AP and the STA
-	 * end up in disconnected state. */
-	os_memset(&param, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_MLME;
-	os_memcpy(param.sta_addr, addr, ETH_ALEN);
-	param.u.mlme.cmd = cmd;
-	param.u.mlme.reason_code = reason_code;
-	ret = hostapd_ioctl(drv, &param, sizeof(param), 1);
-	if (ret == 0) {
-		os_sleep(0, 100000);
-		ret = wpa_driver_hostap_reset(drv, 2);
-	}
-	return ret;
-}
-
-
-static int wpa_driver_hostap_deauthenticate(void *priv, const u8 *addr,
-					    int reason_code)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-	return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DEAUTH,
-				      reason_code);
-}
-
-
-static int wpa_driver_hostap_disassociate(void *priv, const u8 *addr,
-					  int reason_code)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-	return wpa_driver_hostap_mlme(drv, addr, MLME_STA_DISASSOC,
-				      reason_code);
-}
-
-
-static int
-wpa_driver_hostap_associate(void *priv,
-			    struct wpa_driver_associate_params *params)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	int ret = 0;
-	int allow_unencrypted_eapol;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (prism2param(drv, PRISM2_PARAM_DROP_UNENCRYPTED,
-			params->drop_unencrypted) < 0)
-		ret = -1;
-	if (wpa_driver_hostap_set_auth_alg(drv, params->auth_alg) < 0)
-		ret = -1;
-	if (params->mode != drv->current_mode) {
-		/* At the moment, Host AP driver requires host_roaming=2 for
-		 * infrastructure mode and host_roaming=0 for adhoc. */
-		if (prism2param(drv, PRISM2_PARAM_HOST_ROAMING,
-				params->mode == IEEE80211_MODE_IBSS ? 0 : 2) <
-		    0) {
-			wpa_printf(MSG_DEBUG, "%s: failed to set host_roaming",
-				   __func__);
-		}
-		drv->current_mode = params->mode;
-	}
-
-	if (prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED,
-			params->key_mgmt_suite != KEY_MGMT_NONE) < 0)
-		ret = -1;
-	if (wpa_driver_hostap_set_wpa_ie(drv, params->wpa_ie,
-					 params->wpa_ie_len) < 0)
-		ret = -1;
-	if (wpa_driver_wext_set_mode(drv->wext, params->mode) < 0)
-		ret = -1;
-	if (params->freq &&
-	    wpa_driver_wext_set_freq(drv->wext, params->freq) < 0)
-		ret = -1;
-	if (wpa_driver_wext_set_ssid(drv->wext, params->ssid, params->ssid_len)
-	    < 0)
-		ret = -1;
-	if (wpa_driver_wext_set_bssid(drv->wext, params->bssid) < 0)
-		ret = -1;
-
-	/* Allow unencrypted EAPOL messages even if pairwise keys are set when
-	 * not using WPA. IEEE 802.1X specifies that these frames are not
-	 * encrypted, but WPA encrypts them when pairwise keys are in use. */
-	if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
-	    params->key_mgmt_suite == KEY_MGMT_PSK)
-		allow_unencrypted_eapol = 0;
-	else
-		allow_unencrypted_eapol = 1;
-	
-	if (prism2param(drv, PRISM2_PARAM_IEEE_802_1X,
-			allow_unencrypted_eapol) < 0) {
-		wpa_printf(MSG_DEBUG, "hostap: Failed to configure "
-			   "ieee_802_1x param");
-		/* Ignore this error.. driver_hostap.c can also be used with
-		 * other drivers that do not support this prism2_param. */
-	}
-
-	return ret;
-}
-
-
-static int wpa_driver_hostap_scan(void *priv,
-				  struct wpa_driver_scan_params *params)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	struct prism2_hostapd_param param;
-	int ret;
-	const u8 *ssid = params->ssids[0].ssid;
-	size_t ssid_len = params->ssids[0].ssid_len;
-
-	if (ssid == NULL) {
-		/* Use standard Linux Wireless Extensions ioctl if possible
-		 * because some drivers using hostap code in wpa_supplicant
-		 * might not support Host AP specific scan request (with SSID
-		 * info). */
-		return wpa_driver_wext_scan(drv->wext, params);
-	}
-
-	if (ssid_len > 32)
-		ssid_len = 32;
-
-	os_memset(&param, 0, sizeof(param));
-	param.cmd = PRISM2_HOSTAPD_SCAN_REQ;
-	param.u.scan_req.ssid_len = ssid_len;
-	os_memcpy(param.u.scan_req.ssid, ssid, ssid_len);
-	ret = hostapd_ioctl(drv, &param, sizeof(param), 1);
-
-	/* Not all drivers generate "scan completed" wireless event, so try to
-	 * read results after a timeout. */
-	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
-			     drv->ctx);
-	eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv->wext,
-			       drv->ctx);
-
-	return ret;
-}
-
-
-static int wpa_driver_hostap_set_auth_alg(void *priv, int auth_alg)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	int algs = 0;
-
-	if (auth_alg & WPA_AUTH_ALG_OPEN)
-		algs |= 1;
-	if (auth_alg & WPA_AUTH_ALG_SHARED)
-		algs |= 2;
-	if (auth_alg & WPA_AUTH_ALG_LEAP)
-		algs |= 4;
-	if (algs == 0)
-		algs = 1; /* at least one algorithm should be set */
-
-	return prism2param(drv, PRISM2_PARAM_AP_AUTH_ALGS, algs);
-}
-
-
-static int wpa_driver_hostap_get_bssid(void *priv, u8 *bssid)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	return wpa_driver_wext_get_bssid(drv->wext, bssid);
-}
-
-
-static int wpa_driver_hostap_get_ssid(void *priv, u8 *ssid)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	return wpa_driver_wext_get_ssid(drv->wext, ssid);
-}
-
-
-static struct wpa_scan_results * wpa_driver_hostap_get_scan_results(void *priv)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	return wpa_driver_wext_get_scan_results(drv->wext);
-}
-
-
-static int wpa_driver_hostap_set_operstate(void *priv, int state)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	return wpa_driver_wext_set_operstate(drv->wext, state);
-}
-
-
-static void * wpa_driver_hostap_init(void *ctx, const char *ifname)
-{
-	struct wpa_driver_hostap_data *drv;
-
-	drv = os_zalloc(sizeof(*drv));
-	if (drv == NULL)
-		return NULL;
-	drv->wext = wpa_driver_wext_init(ctx, ifname);
-	if (drv->wext == NULL) {
-		os_free(drv);
-		return NULL;
-	}
-
-	drv->ctx = ctx;
-	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
-	drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
-	if (drv->sock < 0) {
-		perror("socket");
-		wpa_driver_wext_deinit(drv->wext);
-		os_free(drv);
-		return NULL;
-	}
-
-	if (os_strncmp(ifname, "wlan", 4) == 0) {
-		/*
-		 * Host AP driver may use both wlan# and wifi# interface in
-		 * wireless events.
-		 */
-		char ifname2[IFNAMSIZ + 1];
-		os_strlcpy(ifname2, ifname, sizeof(ifname2));
-		os_memcpy(ifname2, "wifi", 4);
-		wpa_driver_wext_alternative_ifindex(drv->wext, ifname2);
-	}
-
-	wpa_driver_hostap_set_wpa(drv, 1);
-
-	return drv;
-}
-
-
-static void wpa_driver_hostap_deinit(void *priv)
-{
-	struct wpa_driver_hostap_data *drv = priv;
-	wpa_driver_hostap_set_wpa(drv, 0);
-	wpa_driver_wext_deinit(drv->wext);
-	close(drv->sock);
-	os_free(drv);
-}
-
-#endif /* HOSTAPD */
-
-
 const struct wpa_driver_ops wpa_driver_hostap_ops = {
 	.name = "hostap",
 	.desc = "Host AP driver (Intersil Prism2/2.5/3)",
 	.set_key = wpa_driver_hostap_set_key,
-#ifdef HOSTAPD
 	.hapd_init = hostap_init,
 	.hapd_deinit = hostap_driver_deinit,
 	.set_ieee8021x = hostap_set_ieee8021x,
@@ -1632,17 +1194,6 @@
 	.sta_clear_stats = hostap_sta_clear_stats,
 	.get_hw_feature_data = hostap_get_hw_feature_data,
 	.set_ap_wps_ie = hostap_set_ap_wps_ie,
-#else /* HOSTAPD */
-	.get_bssid = wpa_driver_hostap_get_bssid,
-	.get_ssid = wpa_driver_hostap_get_ssid,
-	.set_countermeasures = wpa_driver_hostap_set_countermeasures,
-	.scan2 = wpa_driver_hostap_scan,
-	.get_scan_results2 = wpa_driver_hostap_get_scan_results,
-	.deauthenticate = wpa_driver_hostap_deauthenticate,
-	.disassociate = wpa_driver_hostap_disassociate,
-	.associate = wpa_driver_hostap_associate,
-	.init = wpa_driver_hostap_init,
-	.deinit = wpa_driver_hostap_deinit,
-	.set_operstate = wpa_driver_hostap_set_operstate,
-#endif /* HOSTAPD */
+	.set_freq = hostap_set_freq,
+	.poll_client = wpa_driver_hostap_poll_client,
 };
diff --git a/src/drivers/driver_iphone.m b/src/drivers/driver_iphone.m
deleted file mode 100644
index 8213fda..0000000
--- a/src/drivers/driver_iphone.m
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * WPA Supplicant - iPhone/iPod touch Apple80211 driver interface
- * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
- */
-
-#include "includes.h"
-#define Boolean __DummyBoolean
-#include <CoreFoundation/CoreFoundation.h>
-#undef Boolean
-
-#include "common.h"
-#include "driver.h"
-#include "eloop.h"
-#include "common/ieee802_11_defs.h"
-
-#include "MobileApple80211.h"
-
-struct wpa_driver_iphone_data {
-	void *ctx;
-	Apple80211Ref wireless_ctx;
-	CFArrayRef scan_results;
-	int ctrl_power;
-};
-
-
-static const void * cfdict_get_key_str(CFDictionaryRef dict, const char *key)
-{
-	const void *res;
-	CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, key,
-						    kCFStringEncodingMacRoman);
-	if (str == NULL)
-		return NULL;
-
-	res = CFDictionaryGetValue(dict, str);
-	CFRelease(str);
-	return res;
-}
-
-
-static int wpa_driver_iphone_get_ssid(void *priv, u8 *ssid)
-{
-	struct wpa_driver_iphone_data *drv = priv;
-	CFDataRef data;
-	int err, len;
-
-	err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_SSID, 0,
-				  &data);
-	if (err != 0) {
-		wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(SSID) "
-			   "failed: %d", err);
-		return -1;
-	}
-
-	len = CFDataGetLength(data);
-	if (len > 32) {
-		CFRelease(data);
-		return -1;
-	}
-	os_memcpy(ssid, CFDataGetBytePtr(data), len);
-	CFRelease(data);
-
-	return len;
-}
-
-
-static int wpa_driver_iphone_get_bssid(void *priv, u8 *bssid)
-{
-	struct wpa_driver_iphone_data *drv = priv;
-	CFStringRef data;
-	int err;
-	int a1, a2, a3, a4, a5, a6;
-
-	err = Apple80211CopyValue(drv->wireless_ctx, APPLE80211_VALUE_BSSID, 0,
-				  &data);
-	if (err != 0) {
-		wpa_printf(MSG_DEBUG, "iPhone: Apple80211CopyValue(BSSID) "
-			   "failed: %d", err);
-		return -1;
-	}
-
-	sscanf(CFStringGetCStringPtr(data, kCFStringEncodingMacRoman),
-	       "%x:%x:%x:%x:%x:%x", &a1, &a2, &a3, &a4, &a5, &a6);
-	bssid[0] = a1;
-	bssid[1] = a2;
-	bssid[2] = a3;
-	bssid[3] = a4;
-	bssid[4] = a5;
-	bssid[5] = a6;
-
-	CFRelease(data);
-
-	return 0;
-}
-
-
-static void wpa_driver_iphone_scan_timeout(void *eloop_ctx, void *timeout_ctx)
-{
-	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
-}
-
-
-static int wpa_driver_iphone_scan(void *priv, const u8 *ssid, size_t ssid_len)
-{
-	struct wpa_driver_iphone_data *drv = priv;
-	int err;
-
-	if (drv->scan_results) {
-		CFRelease(drv->scan_results);
-		drv->scan_results = NULL;
-	}
-
-	err = Apple80211Scan(drv->wireless_ctx, &drv->scan_results, NULL);
-	if (err) {
-		wpa_printf(MSG_DEBUG, "iPhone: Apple80211Scan failed: %d",
-			   err);
-		return -1;
-	}
-
-	eloop_register_timeout(0, 0, wpa_driver_iphone_scan_timeout, drv,
-			       drv->ctx);
-	return 0;
-}
-
-
-static int wpa_driver_iphone_get_scan_results(void *priv,
-					      struct wpa_scan_result *results,
-					      size_t max_size)
-{
-	struct wpa_driver_iphone_data *drv = priv;
-	size_t i, num;
-
-	if (drv->scan_results == NULL)
-		return 0;
-
-	num = CFArrayGetCount(drv->scan_results);
-	if (num > max_size)
-		num = max_size;
-	os_memset(results, 0, num * sizeof(struct wpa_scan_result));
-
-	for (i = 0; i < num; i++) {
-		struct wpa_scan_result *res = &results[i];
-		CFDictionaryRef dict =
-			CFArrayGetValueAtIndex(drv->scan_results, i);
-		CFDataRef data;
-		CFStringRef str;
-		CFNumberRef num;
-		int val;
-
-		data = cfdict_get_key_str(dict, "SSID");
-		if (data) {
-			res->ssid_len = CFDataGetLength(data);
-			if (res->ssid_len > 32)
-				res->ssid_len = 32;
-			os_memcpy(res->ssid, CFDataGetBytePtr(data),
-				  res->ssid_len);
-		}
-
-		str = cfdict_get_key_str(dict, "BSSID");
-		if (str) {
-			int a1, a2, a3, a4, a5, a6;
-			sscanf(CFStringGetCStringPtr(
-				       str, kCFStringEncodingMacRoman),
-			       "%x:%x:%x:%x:%x:%x",
-			       &a1, &a2, &a3, &a4, &a5, &a6);
-			res->bssid[0] = a1;
-			res->bssid[1] = a2;
-			res->bssid[2] = a3;
-			res->bssid[3] = a4;
-			res->bssid[4] = a5;
-			res->bssid[5] = a6;
-		}
-
-		num = cfdict_get_key_str(dict, "CAPABILITIES");
-		if (num) {
-			if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
-				res->caps = val;
-		}
-
-		num = cfdict_get_key_str(dict, "CHANNEL");
-		if (num) {
-			if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
-				res->freq = 2407 + val * 5;
-		}
-
-		num = cfdict_get_key_str(dict, "RSSI");
-		if (num) {
-			if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
-				res->level = val;
-		}
-
-		num = cfdict_get_key_str(dict, "NOISE");
-		if (num) {
-			if (CFNumberGetValue(num, kCFNumberSInt32Type, &val))
-				res->noise = val;
-		}
-
-		data = cfdict_get_key_str(dict, "IE");
-		if (data) {
-			u8 *ptr = (u8 *) CFDataGetBytePtr(data);
-			int len = CFDataGetLength(data);
-			u8 *pos = ptr, *end = ptr + len;
-
-			while (pos + 2 < end) {
-				if (pos + 2 + pos[1] > end)
-					break;
-				if (pos[0] == WLAN_EID_RSN &&
-				    pos[1] <= SSID_MAX_WPA_IE_LEN) {
-					os_memcpy(res->rsn_ie, pos,
-						  2 + pos[1]);
-					res->rsn_ie_len = 2 + pos[1];
-				}
-				if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
-				    pos[1] > 4 && pos[2] == 0x00 &&
-				    pos[3] == 0x50 && pos[4] == 0xf2 &&
-				    pos[5] == 0x01) {
-					os_memcpy(res->wpa_ie, pos,
-						  2 + pos[1]);
-					res->wpa_ie_len = 2 + pos[1];
-				}
-
-				pos = pos + 2 + pos[1];
-			}
-		}
-	}
-
-	return num;
-}
-
-
-static void wpa_driver_iphone_assoc_timeout(void *eloop_ctx, void *timeout_ctx)
-{
-	struct wpa_driver_iphone_data *drv = eloop_ctx;
-	u8 bssid[ETH_ALEN];
-
-	if (wpa_driver_iphone_get_bssid(drv, bssid) != 0) {
-		eloop_register_timeout(1, 0, wpa_driver_iphone_assoc_timeout,
-				       drv, drv->ctx);
-		return;
-	}
-
-	wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL);
-}
-
-
-static int wpa_driver_iphone_associate(
-	void *priv, struct wpa_driver_associate_params *params)
-{
-	struct wpa_driver_iphone_data *drv = priv;
-	int i, num, err;
-	size_t ssid_len;
-	CFDictionaryRef bss = NULL;
-
-	/*
-	 * TODO: Consider generating parameters instead of just using an entry
-	 * from scan results in order to support ap_scan=2.
-	 */
-
-	if (drv->scan_results == NULL) {
-		wpa_printf(MSG_DEBUG, "iPhone: No scan results - cannot "
-			   "associate");
-		return -1;
-	}
-
-	num = CFArrayGetCount(drv->scan_results);
-
-	for (i = 0; i < num; i++) {
-		CFDictionaryRef dict =
-			CFArrayGetValueAtIndex(drv->scan_results, i);
-		CFDataRef data;
-
-		data = cfdict_get_key_str(dict, "SSID");
-		if (data == NULL)
-			continue;
-
-		ssid_len = CFDataGetLength(data);
-		if (ssid_len != params->ssid_len ||
-		    os_memcmp(CFDataGetBytePtr(data), params->ssid, ssid_len)
-		    != 0)
-			continue;
-
-		bss = dict;
-		break;
-	}
-
-	if (bss == NULL) {
-		wpa_printf(MSG_DEBUG, "iPhone: Could not find SSID from scan "
-			   "results - cannot associate");
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "iPhone: Trying to associate with a BSS found "
-		   "from scan results");
-
-	err = Apple80211Associate(drv->wireless_ctx, bss, NULL);
-	if (err) {
-		wpa_printf(MSG_DEBUG, "iPhone: Apple80211Associate() failed: "
-			   "%d", err);
-		return -1;
-	}
-
-	/*
-	 * Driver is actually already associated; report association from an
-	 * eloop callback.
-	 */
-	eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx);
-	eloop_register_timeout(0, 0, wpa_driver_iphone_assoc_timeout, drv,
-			       drv->ctx);
-
-	return 0;
-}
-
-
-static int wpa_driver_iphone_set_key(void *priv, wpa_alg alg, const u8 *addr,
-				     int key_idx, int set_tx, const u8 *seq,
-				     size_t seq_len, const u8 *key,
-				     size_t key_len)
-{
-	/*
-	 * TODO: Need to either support configuring PMK for 4-way handshake or
-	 * PTK for TKIP/CCMP.
-	 */
-	return -1;
-}
-
-
-static int wpa_driver_iphone_get_capa(void *priv, struct wpa_driver_capa *capa)
-{
-	os_memset(capa, 0, sizeof(*capa));
-
-	capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
-	capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 |
-		WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP;
-	capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED |
-		WPA_DRIVER_AUTH_LEAP;
-	capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
-
-	return 0;
-}
-
-
-static void * wpa_driver_iphone_init(void *ctx, const char *ifname)
-{
-	struct wpa_driver_iphone_data *drv;
-	int err;
-	char power;
-	CFStringRef name;
-	CFDictionaryRef dict;
-
-	drv = os_zalloc(sizeof(*drv));
-	if (drv == NULL)
-		return NULL;
-	drv->ctx = ctx;
-	err = Apple80211Open(&drv->wireless_ctx);
-	if (err) {
-		wpa_printf(MSG_ERROR, "iPhone: Apple80211Open failed: %d",
-			   err);
-		os_free(drv);
-		return NULL;
-	}
-
-	name = CFStringCreateWithCString(kCFAllocatorDefault, ifname,
-					 kCFStringEncodingISOLatin1);
-	if (name == NULL) {
-		wpa_printf(MSG_ERROR, "iPhone: ifname -> CFString failed");
-		Apple80211Close(drv->wireless_ctx);
-		os_free(drv);
-		return NULL;
-	}
-
-	err = Apple80211BindToInterface(drv->wireless_ctx, name);
-	CFRelease(name);
-
-	if (err) {
-		wpa_printf(MSG_ERROR, "iPhone: Apple80211BindToInterface "
-			   "failed: %d", err);
-		Apple80211Close(drv->wireless_ctx);
-		os_free(drv);
-		return NULL;
-	}
-
-	err = Apple80211GetPower(drv->wireless_ctx, &power);
-	if (err)
-		wpa_printf(MSG_DEBUG, "iPhone: Apple80211GetPower failed: %d",
-			   err);
-
-	wpa_printf(MSG_DEBUG, "iPhone: Power=%d", power);
-
-	if (!power) {
-		drv->ctrl_power = 1;
-		err = Apple80211SetPower(drv->wireless_ctx, 1);
-		if (err) {
-			wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower "
-				   "failed: %d", err);
-			Apple80211Close(drv->wireless_ctx);
-			os_free(drv);
-			return NULL;
-		}
-	}
-
-	err = Apple80211GetInfoCopy(drv->wireless_ctx, &dict);
-	if (err == 0) {
-		CFShow(dict);
-		CFRelease(dict);
-	} else {
-		printf("Apple80211GetInfoCopy: %d\n", err);
-	}
-
-	return drv;
-}
-
-
-static void wpa_driver_iphone_deinit(void *priv)
-{
-	struct wpa_driver_iphone_data *drv = priv;
-	int err;
-
-	eloop_cancel_timeout(wpa_driver_iphone_scan_timeout, drv, drv->ctx);
-	eloop_cancel_timeout(wpa_driver_iphone_assoc_timeout, drv, drv->ctx);
-
-	if (drv->ctrl_power) {
-		wpa_printf(MSG_DEBUG, "iPhone: Power down the interface");
-		err = Apple80211SetPower(drv->wireless_ctx, 0);
-		if (err) {
-			wpa_printf(MSG_DEBUG, "iPhone: Apple80211SetPower(0) "
-				   "failed: %d", err);
-		}
-	}
-
-	err = Apple80211Close(drv->wireless_ctx);
-	if (err) {
-		wpa_printf(MSG_DEBUG, "iPhone: Apple80211Close failed: %d",
-			   err);
-	}
-
-	if (drv->scan_results)
-		CFRelease(drv->scan_results);
-
-	os_free(drv);
-}
-
-
-const struct wpa_driver_ops wpa_driver_iphone_ops = {
-	.name = "iphone",
-	.desc = "iPhone/iPod touch Apple80211 driver",
-	.get_ssid = wpa_driver_iphone_get_ssid,
-	.get_bssid = wpa_driver_iphone_get_bssid,
-	.init = wpa_driver_iphone_init,
-	.deinit = wpa_driver_iphone_deinit,
-	.scan = wpa_driver_iphone_scan,
-	.get_scan_results = wpa_driver_iphone_get_scan_results,
-	.associate = wpa_driver_iphone_associate,
-	.set_key = wpa_driver_iphone_set_key,
-	.get_capa = wpa_driver_iphone_get_capa,
-};
diff --git a/src/drivers/driver_madwifi.c b/src/drivers/driver_madwifi.c
index 630fbf4..edb086f 100644
--- a/src/drivers/driver_madwifi.c
+++ b/src/drivers/driver_madwifi.c
@@ -27,7 +27,7 @@
 #include "driver_wext.h"
 #include "eloop.h"
 #include "common/ieee802_11_defs.h"
-#include "wireless_copy.h"
+#include "linux_wext.h"
 
 /*
  * Avoid conflicts with wpa_supplicant definitions by undefining a definition.
@@ -71,8 +71,6 @@
 
 #define WPA_KEY_RSC_LEN 8
 
-#ifdef HOSTAPD
-
 #include "priv_netlink.h"
 #include "netlink.h"
 #include "linux_ioctl.h"
@@ -734,6 +732,8 @@
 
 	os_memset(&event, 0, sizeof(event));
 	event.rx_probe_req.sa = mgmt->sa;
+	event.rx_probe_req.da = mgmt->da;
+	event.rx_probe_req.bssid = mgmt->bssid;
 	event.rx_probe_req.ie = mgmt->u.probe_req.variable;
 	event.rx_probe_req.ie_len =
 		len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
@@ -804,6 +804,24 @@
 #define madwifi_set_ap_wps_ie NULL
 #endif /* CONFIG_WPS */
 
+static int madwifi_set_freq(void *priv, struct hostapd_freq_params *freq)
+{
+	struct madwifi_driver_data *drv = priv;
+	struct iwreq iwr;
+
+	os_memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
+	iwr.u.freq.m = freq->channel;
+	iwr.u.freq.e = 0;
+
+	if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
+		perror("ioctl[SIOCSIWFREQ]");
+		return -1;
+	}
+
+	return 0;
+}
+
 static void
 madwifi_new_sta(struct madwifi_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN])
 {
@@ -1274,554 +1292,11 @@
 	return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);
 }
 
-#else /* HOSTAPD */
-
-struct wpa_driver_madwifi_data {
-	void *wext; /* private data for driver_wext */
-	void *ctx;
-	char ifname[IFNAMSIZ + 1];
-	int sock;
-};
-
-static int wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg);
-static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies,
-					       size_t ies_len);
-
-
-static int
-set80211priv(struct wpa_driver_madwifi_data *drv, int op, void *data, int len,
-	     int show_err)
-{
-	struct iwreq iwr;
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	if (len < IFNAMSIZ &&
-	    op != IEEE80211_IOCTL_SET_APPIEBUF) {
-		/*
-		 * Argument data fits inline; put it there.
-		 */
-		os_memcpy(iwr.u.name, data, len);
-	} else {
-		/*
-		 * Argument data too big for inline transfer; setup a
-		 * parameter block instead; the kernel will transfer
-		 * the data for the driver.
-		 */
-		iwr.u.data.pointer = data;
-		iwr.u.data.length = len;
-	}
-
-	if (ioctl(drv->sock, op, &iwr) < 0) {
-		if (show_err) {
-#ifdef MADWIFI_NG
-			int first = IEEE80211_IOCTL_SETPARAM;
-			int last = IEEE80211_IOCTL_KICKMAC;
-			static const char *opnames[] = {
-				"ioctl[IEEE80211_IOCTL_SETPARAM]",
-				"ioctl[IEEE80211_IOCTL_GETPARAM]",
-				"ioctl[IEEE80211_IOCTL_SETMODE]",
-				"ioctl[IEEE80211_IOCTL_GETMODE]",
-				"ioctl[IEEE80211_IOCTL_SETWMMPARAMS]",
-				"ioctl[IEEE80211_IOCTL_GETWMMPARAMS]",
-				"ioctl[IEEE80211_IOCTL_SETCHANLIST]",
-				"ioctl[IEEE80211_IOCTL_GETCHANLIST]",
-				"ioctl[IEEE80211_IOCTL_CHANSWITCH]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_SET_APPIEBUF]",
-				"ioctl[IEEE80211_IOCTL_GETSCANRESULTS]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_GETCHANINFO]",
-				"ioctl[IEEE80211_IOCTL_SETOPTIE]",
-				"ioctl[IEEE80211_IOCTL_GETOPTIE]",
-				"ioctl[IEEE80211_IOCTL_SETMLME]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_SETKEY]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_DELKEY]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_ADDMAC]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_DELMAC]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_WDSMAC]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_WDSDELMAC]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_KICKMAC]",
-			};
-#else /* MADWIFI_NG */
-			int first = IEEE80211_IOCTL_SETPARAM;
-			int last = IEEE80211_IOCTL_CHANLIST;
-			static const char *opnames[] = {
-				"ioctl[IEEE80211_IOCTL_SETPARAM]",
-				"ioctl[IEEE80211_IOCTL_GETPARAM]",
-				"ioctl[IEEE80211_IOCTL_SETKEY]",
-				"ioctl[IEEE80211_IOCTL_GETKEY]",
-				"ioctl[IEEE80211_IOCTL_DELKEY]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_SETMLME]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_SETOPTIE]",
-				"ioctl[IEEE80211_IOCTL_GETOPTIE]",
-				"ioctl[IEEE80211_IOCTL_ADDMAC]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_DELMAC]",
-				NULL,
-				"ioctl[IEEE80211_IOCTL_CHANLIST]",
-			};
-#endif /* MADWIFI_NG */
-			int idx = op - first;
-			if (first <= op && op <= last &&
-			    idx < (int) (sizeof(opnames) / sizeof(opnames[0]))
-			    && opnames[idx])
-				perror(opnames[idx]);
-			else
-				perror("ioctl[unknown???]");
-		}
-		return -1;
-	}
-	return 0;
-}
-
-static int
-set80211param(struct wpa_driver_madwifi_data *drv, int op, int arg,
-	      int show_err)
-{
-	struct iwreq iwr;
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.mode = op;
-	os_memcpy(iwr.u.name+sizeof(u32), &arg, sizeof(arg));
-
-	if (ioctl(drv->sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
-		if (show_err) 
-			perror("ioctl[IEEE80211_IOCTL_SETPARAM]");
-		return -1;
-	}
-	return 0;
-}
-
-static int
-wpa_driver_madwifi_set_wpa_ie(struct wpa_driver_madwifi_data *drv,
-			      const u8 *wpa_ie, size_t wpa_ie_len)
-{
-	struct iwreq iwr;
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	/* NB: SETOPTIE is not fixed-size so must not be inlined */
-	iwr.u.data.pointer = (void *) wpa_ie;
-	iwr.u.data.length = wpa_ie_len;
-
-	if (ioctl(drv->sock, IEEE80211_IOCTL_SETOPTIE, &iwr) < 0) {
-		perror("ioctl[IEEE80211_IOCTL_SETOPTIE]");
-		return -1;
-	}
-	return 0;
-}
-
-static int
-wpa_driver_madwifi_del_key(struct wpa_driver_madwifi_data *drv, int key_idx,
-			   const u8 *addr)
-{
-	struct ieee80211req_del_key wk;
-
-	wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __FUNCTION__, key_idx);
-	os_memset(&wk, 0, sizeof(wk));
-	wk.idk_keyix = key_idx;
-	if (addr != NULL)
-		os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
-
-	return set80211priv(drv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk), 1);
-}
-
-static int
-wpa_driver_madwifi_set_key(const char *ifname, void *priv, enum wpa_alg alg,
-			   const u8 *addr, int key_idx, int set_tx,
-			   const u8 *seq, size_t seq_len,
-			   const u8 *key, size_t key_len)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	struct ieee80211req_key wk;
-	char *alg_name;
-	u_int8_t cipher;
-
-	if (alg == WPA_ALG_NONE)
-		return wpa_driver_madwifi_del_key(drv, key_idx, addr);
-
-	switch (alg) {
-	case WPA_ALG_WEP:
-		if (addr == NULL || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff",
-					      ETH_ALEN) == 0) {
-			/*
-			 * madwifi did not seem to like static WEP key
-			 * configuration with IEEE80211_IOCTL_SETKEY, so use
-			 * Linux wireless extensions ioctl for this.
-			 */
-			return wpa_driver_wext_set_key(ifname, drv->wext, alg,
-						       addr, key_idx, set_tx,
-						       seq, seq_len,
-						       key, key_len);
-		}
-		alg_name = "WEP";
-		cipher = IEEE80211_CIPHER_WEP;
-		break;
-	case WPA_ALG_TKIP:
-		alg_name = "TKIP";
-		cipher = IEEE80211_CIPHER_TKIP;
-		break;
-	case WPA_ALG_CCMP:
-		alg_name = "CCMP";
-		cipher = IEEE80211_CIPHER_AES_CCM;
-		break;
-	default:
-		wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d",
-			__FUNCTION__, alg);
-		return -1;
-	}
-
-	wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
-		   "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx,
-		   (unsigned long) seq_len, (unsigned long) key_len);
-
-	if (seq_len > sizeof(u_int64_t)) {
-		wpa_printf(MSG_DEBUG, "%s: seq_len %lu too big",
-			   __FUNCTION__, (unsigned long) seq_len);
-		return -2;
-	}
-	if (key_len > sizeof(wk.ik_keydata)) {
-		wpa_printf(MSG_DEBUG, "%s: key length %lu too big",
-			   __FUNCTION__, (unsigned long) key_len);
-		return -3;
-	}
-
-	os_memset(&wk, 0, sizeof(wk));
-	wk.ik_type = cipher;
-	wk.ik_flags = IEEE80211_KEY_RECV;
-	if (addr == NULL ||
-	    os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
-		wk.ik_flags |= IEEE80211_KEY_GROUP;
-	if (set_tx) {
-		wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
-		os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
-	} else
-		os_memset(wk.ik_macaddr, 0, IEEE80211_ADDR_LEN);
-	wk.ik_keyix = key_idx;
-	wk.ik_keylen = key_len;
-#ifdef WORDS_BIGENDIAN
-	if (seq) {
-		size_t i;
-		u8 tmp[WPA_KEY_RSC_LEN];
-		os_memset(tmp, 0, sizeof(tmp));
-		for (i = 0; i < seq_len; i++)
-			tmp[WPA_KEY_RSC_LEN - i - 1] = seq[i];
-		os_memcpy(&wk.ik_keyrsc, tmp, WPA_KEY_RSC_LEN);
-	}
-#else /* WORDS_BIGENDIAN */
-	if (seq)
-		os_memcpy(&wk.ik_keyrsc, seq, seq_len);
-#endif /* WORDS_BIGENDIAN */
-	os_memcpy(wk.ik_keydata, key, key_len);
-
-	return set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk), 1);
-}
-
-static int
-wpa_driver_madwifi_set_countermeasures(void *priv, int enabled)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
-	return set80211param(drv, IEEE80211_PARAM_COUNTERMEASURES, enabled, 1);
-}
-
-static int
-wpa_driver_madwifi_deauthenticate(void *priv, const u8 *addr, int reason_code)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	struct ieee80211req_mlme mlme;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-	mlme.im_op = IEEE80211_MLME_DEAUTH;
-	mlme.im_reason = reason_code;
-	os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
-	return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
-}
-
-static int
-wpa_driver_madwifi_disassociate(void *priv, const u8 *addr, int reason_code)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	struct ieee80211req_mlme mlme;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-	mlme.im_op = IEEE80211_MLME_DISASSOC;
-	mlme.im_reason = reason_code;
-	os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
-	return set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme), 1);
-}
-
-static int
-wpa_driver_madwifi_associate(void *priv,
-			     struct wpa_driver_associate_params *params)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	struct ieee80211req_mlme mlme;
-	int ret = 0, privacy = 1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (set80211param(drv, IEEE80211_PARAM_DROPUNENCRYPTED,
-			  params->drop_unencrypted, 1) < 0)
-		ret = -1;
-	if (wpa_driver_madwifi_set_auth_alg(drv, params->auth_alg) < 0)
-		ret = -1;
-
-	/*
-	 * NB: Don't need to set the freq or cipher-related state as
-	 *     this is implied by the bssid which is used to locate
-	 *     the scanned node state which holds it.  The ssid is
-	 *     needed to disambiguate an AP that broadcasts multiple
-	 *     ssid's but uses the same bssid.
-	 */
-	/* XXX error handling is wrong but unclear what to do... */
-	if (wpa_driver_madwifi_set_wpa_ie(drv, params->wpa_ie,
-					  params->wpa_ie_len) < 0)
-		ret = -1;
-
-	if (params->pairwise_suite == CIPHER_NONE &&
-	    params->group_suite == CIPHER_NONE &&
-	    params->key_mgmt_suite == KEY_MGMT_NONE &&
-	    params->wpa_ie_len == 0)
-		privacy = 0;
-
-	if (set80211param(drv, IEEE80211_PARAM_PRIVACY, privacy, 1) < 0)
-		ret = -1;
-
-	if (params->wpa_ie_len &&
-	    set80211param(drv, IEEE80211_PARAM_WPA,
-			  params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1, 1) < 0)
-		ret = -1;
-
-	if (params->bssid == NULL) {
-		/* ap_scan=2 mode - driver takes care of AP selection and
-		 * roaming */
-		/* FIX: this does not seem to work; would probably need to
-		 * change something in the driver */
-		if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0)
-			ret = -1;
-
-		if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
-					     params->ssid_len) < 0)
-			ret = -1;
-	} else {
-		if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0)
-			ret = -1;
-		if (wpa_driver_wext_set_ssid(drv->wext, params->ssid,
-					     params->ssid_len) < 0)
-			ret = -1;
-		os_memset(&mlme, 0, sizeof(mlme));
-		mlme.im_op = IEEE80211_MLME_ASSOC;
-		os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN);
-		if (set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme,
-				 sizeof(mlme), 1) < 0) {
-			wpa_printf(MSG_DEBUG, "%s: SETMLME[ASSOC] failed",
-				   __func__);
-			ret = -1;
-		}
-	}
-
-	return ret;
-}
-
-static int
-wpa_driver_madwifi_set_auth_alg(void *priv, int auth_alg)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	int authmode;
-
-	if ((auth_alg & WPA_AUTH_ALG_OPEN) &&
-	    (auth_alg & WPA_AUTH_ALG_SHARED))
-		authmode = IEEE80211_AUTH_AUTO;
-	else if (auth_alg & WPA_AUTH_ALG_SHARED)
-		authmode = IEEE80211_AUTH_SHARED;
-	else
-		authmode = IEEE80211_AUTH_OPEN;
-
-	return set80211param(drv, IEEE80211_PARAM_AUTHMODE, authmode, 1);
-}
-
-static int
-wpa_driver_madwifi_scan(void *priv, struct wpa_driver_scan_params *params)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	struct iwreq iwr;
-	int ret = 0;
-	const u8 *ssid = params->ssids[0].ssid;
-	size_t ssid_len = params->ssids[0].ssid_len;
-
-	wpa_driver_madwifi_set_probe_req_ie(drv, params->extra_ies,
-					    params->extra_ies_len);
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-
-	/* set desired ssid before scan */
-	/* FIX: scan should not break the current association, so using
-	 * set_ssid may not be the best way of doing this.. */
-	if (wpa_driver_wext_set_ssid(drv->wext, ssid, ssid_len) < 0)
-		ret = -1;
-
-	if (ioctl(drv->sock, SIOCSIWSCAN, &iwr) < 0) {
-		perror("ioctl[SIOCSIWSCAN]");
-		ret = -1;
-	}
-
-	/*
-	 * madwifi delivers a scan complete event so no need to poll, but
-	 * register a backup timeout anyway to make sure that we recover even
-	 * if the driver does not send this event for any reason. This timeout
-	 * will only be used if the event is not delivered (event handler will
-	 * cancel the timeout).
-	 */
-	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv->wext,
-			     drv->ctx);
-	eloop_register_timeout(30, 0, wpa_driver_wext_scan_timeout, drv->wext,
-			       drv->ctx);
-
-	return ret;
-}
-
-static int wpa_driver_madwifi_get_bssid(void *priv, u8 *bssid)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	return wpa_driver_wext_get_bssid(drv->wext, bssid);
-}
-
-
-static int wpa_driver_madwifi_get_ssid(void *priv, u8 *ssid)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	return wpa_driver_wext_get_ssid(drv->wext, ssid);
-}
-
-
-static struct wpa_scan_results *
-wpa_driver_madwifi_get_scan_results(void *priv)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	return wpa_driver_wext_get_scan_results(drv->wext);
-}
-
-
-static int wpa_driver_madwifi_set_operstate(void *priv, int state)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-	return wpa_driver_wext_set_operstate(drv->wext, state);
-}
-
-
-static int wpa_driver_madwifi_set_probe_req_ie(void *priv, const u8 *ies,
-					       size_t ies_len)
-{
-	struct ieee80211req_getset_appiebuf *probe_req_ie;
-	int ret;
-
-	probe_req_ie = os_malloc(sizeof(*probe_req_ie) + ies_len);
-	if (probe_req_ie == NULL)
-		return -1;
-
-	probe_req_ie->app_frmtype = IEEE80211_APPIE_FRAME_PROBE_REQ;
-	probe_req_ie->app_buflen = ies_len;
-	os_memcpy(probe_req_ie->app_buf, ies, ies_len);
-
-	ret = set80211priv(priv, IEEE80211_IOCTL_SET_APPIEBUF, probe_req_ie,
-			   sizeof(struct ieee80211req_getset_appiebuf) +
-			   ies_len, 1);
-
-	os_free(probe_req_ie);
-
-	return ret;
-}
-
-
-static void * wpa_driver_madwifi_init(void *ctx, const char *ifname)
-{
-	struct wpa_driver_madwifi_data *drv;
-
-	drv = os_zalloc(sizeof(*drv));
-	if (drv == NULL)
-		return NULL;
-	drv->wext = wpa_driver_wext_init(ctx, ifname);
-	if (drv->wext == NULL)
-		goto fail;
-
-	drv->ctx = ctx;
-	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
-	drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
-	if (drv->sock < 0)
-		goto fail2;
-
-	if (set80211param(drv, IEEE80211_PARAM_ROAMING, 2, 1) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: failed to set wpa_supplicant-based "
-			   "roaming", __FUNCTION__);
-		goto fail3;
-	}
-
-	if (set80211param(drv, IEEE80211_PARAM_WPA, 3, 1) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: failed to enable WPA support",
-			   __FUNCTION__);
-		goto fail3;
-	}
-
-	return drv;
-
-fail3:
-	close(drv->sock);
-fail2:
-	wpa_driver_wext_deinit(drv->wext);
-fail:
-	os_free(drv);
-	return NULL;
-}
-
-
-static void wpa_driver_madwifi_deinit(void *priv)
-{
-	struct wpa_driver_madwifi_data *drv = priv;
-
-	if (wpa_driver_madwifi_set_wpa_ie(drv, NULL, 0) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: failed to clear WPA IE",
-			   __FUNCTION__);
-	}
-	if (set80211param(drv, IEEE80211_PARAM_ROAMING, 0, 1) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: failed to enable driver-based "
-			   "roaming", __FUNCTION__);
-	}
-	if (set80211param(drv, IEEE80211_PARAM_PRIVACY, 0, 1) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: failed to disable forced Privacy "
-			   "flag", __FUNCTION__);
-	}
-	if (set80211param(drv, IEEE80211_PARAM_WPA, 0, 1) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: failed to disable WPA",
-			   __FUNCTION__);
-	}
-
-	wpa_driver_wext_deinit(drv->wext);
-
-	close(drv->sock);
-	os_free(drv);
-}
-
-#endif /* HOSTAPD */
-
 
 const struct wpa_driver_ops wpa_driver_madwifi_ops = {
 	.name			= "madwifi",
 	.desc			= "MADWIFI 802.11 support (Atheros, etc.)",
 	.set_key		= wpa_driver_madwifi_set_key,
-#ifdef HOSTAPD
 	.hapd_init		= madwifi_init,
 	.hapd_deinit		= madwifi_deinit,
 	.set_ieee8021x		= madwifi_set_ieee8021x,
@@ -1840,17 +1315,5 @@
 	.sta_clear_stats        = madwifi_sta_clear_stats,
 	.commit			= madwifi_commit,
 	.set_ap_wps_ie		= madwifi_set_ap_wps_ie,
-#else /* HOSTAPD */
-	.get_bssid		= wpa_driver_madwifi_get_bssid,
-	.get_ssid		= wpa_driver_madwifi_get_ssid,
-	.init			= wpa_driver_madwifi_init,
-	.deinit			= wpa_driver_madwifi_deinit,
-	.set_countermeasures	= wpa_driver_madwifi_set_countermeasures,
-	.scan2			= wpa_driver_madwifi_scan,
-	.get_scan_results2	= wpa_driver_madwifi_get_scan_results,
-	.deauthenticate		= wpa_driver_madwifi_deauthenticate,
-	.disassociate		= wpa_driver_madwifi_disassociate,
-	.associate		= wpa_driver_madwifi_associate,
-	.set_operstate		= wpa_driver_madwifi_set_operstate,
-#endif /* HOSTAPD */
+	.set_freq		= madwifi_set_freq,
 };
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index aeb7304..dbe9a28 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -3213,119 +3213,33 @@
 }
 
 
-const struct wpa_driver_ops wpa_driver_ndis_ops = {
-	"ndis",
-	"Windows NDIS driver",
-	wpa_driver_ndis_get_bssid,
-	wpa_driver_ndis_get_ssid,
-	wpa_driver_ndis_set_key,
-	wpa_driver_ndis_init,
-	wpa_driver_ndis_deinit,
-	NULL /* set_param */,
-	NULL /* set_countermeasures */,
-	wpa_driver_ndis_deauthenticate,
-	wpa_driver_ndis_disassociate,
-	wpa_driver_ndis_associate,
-	wpa_driver_ndis_add_pmkid,
-	wpa_driver_ndis_remove_pmkid,
-	wpa_driver_ndis_flush_pmkid,
-	wpa_driver_ndis_get_capa,
-	wpa_driver_ndis_poll,
-	wpa_driver_ndis_get_ifname,
-	wpa_driver_ndis_get_mac_addr,
-	NULL /* send_eapol */,
-	NULL /* set_operstate */,
-	NULL /* mlme_setprotection */,
-	NULL /* get_hw_feature_data */,
-	NULL /* set_channel */,
-	NULL /* set_ssid */,
-	NULL /* set_bssid */,
-	NULL /* send_mlme */,
-	NULL /* mlme_add_sta */,
-	NULL /* mlme_remove_sta */,
-	NULL /* update_ft_ies */,
-	NULL /* send_ft_action */,
-	wpa_driver_ndis_get_scan_results,
-	NULL /* set_country */,
-	NULL /* global_init */,
-	NULL /* global_deinit */,
-	NULL /* init2 */,
-	wpa_driver_ndis_get_interfaces,
-	wpa_driver_ndis_scan,
-	NULL /* authenticate */,
-	NULL /* set_beacon */,
-	NULL /* hapd_init */,
-	NULL /* hapd_deinit */,
-	NULL /* set_ieee8021x */,
-	NULL /* set_privacy */,
-	NULL /* get_seqnum */,
-	NULL /* flush */,
-	NULL /* set_generic_elem */,
-	NULL /* read_sta_data */,
-	NULL /* hapd_send_eapol */,
-	NULL /* sta_deauth */,
-	NULL /* sta_disassoc */,
-	NULL /* sta_remove */,
-	NULL /* hapd_get_ssid */,
-	NULL /* hapd_set_ssid */,
-	NULL /* hapd_set_countermeasures */,
-	NULL /* sta_add */,
-	NULL /* get_inact_sec */,
-	NULL /* sta_clear_stats */,
-	NULL /* set_freq */,
-	NULL /* set_rts */,
-	NULL /* set_frag */,
-	NULL /* sta_set_flags */,
-	NULL /* set_rate_sets */,
-	NULL /* set_cts_protect */,
-	NULL /* set_preamble */,
-	NULL /* set_short_slot_time */,
-	NULL /* set_tx_queue_params */,
-	NULL /* valid_bss_mask */,
-	NULL /* if_add */,
-	NULL /* if_remove */,
-	NULL /* set_sta_vlan */,
-	NULL /* commit */,
-	NULL /* send_ether */,
-	NULL /* set_radius_acl_auth */,
-	NULL /* set_radius_acl_expire */,
-	NULL /* set_ht_params */,
-	NULL /* set_ap_wps_ie */,
-	NULL /* set_supp_port */,
-	NULL /* set_wds_sta */,
-	NULL /* send_action */,
-	NULL /* send_action_cancel_wait */,
-	NULL /* remain_on_channel */,
-	NULL /* cancel_remain_on_channel */,
-	NULL /* probe_req_report */,
-	NULL /* disable_11b_rates */,
-	NULL /* deinit_ap */,
-	NULL /* suspend */,
-	NULL /* resume */,
-	NULL /* signal_monitor */,
-	NULL /* send_frame */,
-	NULL /* shared_freq */,
-	NULL /* get_noa */,
-	NULL /* set_noa */,
-	NULL /* set_p2p_powersave */,
-	NULL /* ampdu */,
-	NULL /* set_intra_bss */,
-	NULL /* get_radio_name */,
-	NULL /* p2p_find */,
-	NULL /* p2p_stop_find */,
-	NULL /* p2p_listen */,
-	NULL /* p2p_connect */,
-	NULL /* wps_success_cb */,
-	NULL /* p2p_group_formation_failed */,
-	NULL /* p2p_set_params */,
-	NULL /* p2p_prov_disc_req */,
-	NULL /* p2p_sd_request */,
-	NULL /* p2p_sd_cancel_request */,
-	NULL /* p2p_sd_response */,
-	NULL /* p2p_service_update */,
-	NULL /* p2p_reject */,
-	NULL /* p2p_invite */,
-	NULL /* send_tdls_mgmt */,
-	NULL /* tdls_oper */,
-	NULL /* signal_poll */
-};
+static const char *ndis_drv_name = "ndis";
+static const char *ndis_drv_desc = "Windows NDIS driver";
+
+struct wpa_driver_ops wpa_driver_ndis_ops;
+
+void driver_ndis_init_ops(void)
+{
+	os_memset(&wpa_driver_ndis_ops, 0, sizeof(wpa_driver_ndis_ops));
+	wpa_driver_ndis_ops.name = ndis_drv_name;
+	wpa_driver_ndis_ops.desc = ndis_drv_desc;
+	wpa_driver_ndis_ops.get_bssid = wpa_driver_ndis_get_bssid;
+	wpa_driver_ndis_ops.get_ssid = wpa_driver_ndis_get_ssid;
+	wpa_driver_ndis_ops.set_key = wpa_driver_ndis_set_key;
+	wpa_driver_ndis_ops.init = wpa_driver_ndis_init;
+	wpa_driver_ndis_ops.deinit = wpa_driver_ndis_deinit;
+	wpa_driver_ndis_ops.deauthenticate = wpa_driver_ndis_deauthenticate;
+	wpa_driver_ndis_ops.disassociate = wpa_driver_ndis_disassociate;
+	wpa_driver_ndis_ops.associate = wpa_driver_ndis_associate;
+	wpa_driver_ndis_ops.add_pmkid = wpa_driver_ndis_add_pmkid;
+	wpa_driver_ndis_ops.remove_pmkid = wpa_driver_ndis_remove_pmkid;
+	wpa_driver_ndis_ops.flush_pmkid = wpa_driver_ndis_flush_pmkid;
+	wpa_driver_ndis_ops.get_capa = wpa_driver_ndis_get_capa;
+	wpa_driver_ndis_ops.poll = wpa_driver_ndis_poll;
+	wpa_driver_ndis_ops.get_ifname = wpa_driver_ndis_get_ifname;
+	wpa_driver_ndis_ops.get_mac_addr = wpa_driver_ndis_get_mac_addr;
+	wpa_driver_ndis_ops.get_scan_results2 =
+		wpa_driver_ndis_get_scan_results;
+	wpa_driver_ndis_ops.get_interfaces = wpa_driver_ndis_get_interfaces;
+	wpa_driver_ndis_ops.scan2 = wpa_driver_ndis_scan;
+}
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index df309c5..a00f703 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -28,21 +28,47 @@
 #include <linux/rtnetlink.h>
 #include <netpacket/packet.h>
 #include <linux/filter.h>
+#include <linux/errqueue.h>
 #include "nl80211_copy.h"
 
 #include "common.h"
 #include "eloop.h"
 #include "utils/list.h"
 #include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "l2_packet/l2_packet.h"
 #include "netlink.h"
 #include "linux_ioctl.h"
 #include "radiotap.h"
 #include "radiotap_iter.h"
 #include "rfkill.h"
 #include "driver.h"
-#if defined(ANDROID_BRCM_P2P_PATCH) && !defined(HOSTAPD)
+#if defined(ANDROID_P2P) && !defined(HOSTAPD)
 #include "wpa_supplicant_i.h"
 #endif
+#ifndef SO_WIFI_STATUS
+# if defined(__sparc__)
+#  define SO_WIFI_STATUS	0x0025
+# elif defined(__parisc__)
+#  define SO_WIFI_STATUS	0x4022
+# else
+#  define SO_WIFI_STATUS	41
+# endif
+
+# define SCM_WIFI_STATUS	SO_WIFI_STATUS
+#endif
+
+#ifndef SO_EE_ORIGIN_TXSTATUS
+#define SO_EE_ORIGIN_TXSTATUS	4
+#endif
+
+#ifndef PACKET_TX_TIMESTAMP
+#define PACKET_TX_TIMESTAMP	16
+#endif
+
+#ifdef ANDROID
+#include "android_drv.h"
+#endif /* ANDROID */
 #ifdef CONFIG_LIBNL20
 /* libnl 2.0 compatibility code */
 #define nl_handle nl_sock
@@ -91,6 +117,37 @@
 #endif /* CONFIG_LIBNL20 */
 
 
+static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
+{
+	struct nl_handle *handle;
+
+	handle = nl80211_handle_alloc(cb);
+	if (handle == NULL) {
+		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
+			   "callbacks (%s)", dbg);
+		return NULL;
+	}
+
+	if (genl_connect(handle)) {
+		wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
+			   "netlink (%s)", dbg);
+		nl80211_handle_destroy(handle);
+		return NULL;
+	}
+
+	return handle;
+}
+
+
+static void nl_destroy_handles(struct nl_handle **handle)
+{
+	if (*handle == NULL)
+		return;
+	nl80211_handle_destroy(*handle);
+	*handle = NULL;
+}
+
+
 #ifndef IFF_LOWER_UP
 #define IFF_LOWER_UP   0x10000         /* driver signals L1 up         */
 #endif
@@ -107,8 +164,30 @@
 
 struct nl80211_global {
 	struct dl_list interfaces;
+	int if_add_ifindex;
+	struct netlink_data *netlink;
+	struct nl_cb *nl_cb;
+	struct nl_handle *nl;
+	int nl80211_id;
+	int ioctl_sock; /* socket for ioctl() use */
+
+	struct nl_handle *nl_event;
 };
 
+struct nl80211_wiphy_data {
+	struct dl_list list;
+	struct dl_list bsss;
+	struct dl_list drvs;
+
+	struct nl_handle *nl_beacons;
+	struct nl_cb *nl_cb;
+
+	int wiphy_idx;
+};
+
+static void nl80211_global_deinit(void *priv);
+static void wpa_driver_nl80211_deinit(void *priv);
+
 struct i802_bss {
 	struct wpa_driver_nl80211_data *drv;
 	struct i802_bss *next;
@@ -118,19 +197,28 @@
 	unsigned int beacon_set:1;
 	unsigned int added_if_into_bridge:1;
 	unsigned int added_bridge:1;
+
+	u8 addr[ETH_ALEN];
+
+	int freq;
+
+	struct nl_handle *nl_preq, *nl_mgmt;
+	struct nl_cb *nl_cb;
+
+	struct nl80211_wiphy_data *wiphy_data;
+	struct dl_list wiphy_list;
 };
 
 struct wpa_driver_nl80211_data {
 	struct nl80211_global *global;
 	struct dl_list list;
-	u8 addr[ETH_ALEN];
+	struct dl_list wiphy_list;
 	char phyname[32];
 	void *ctx;
-	struct netlink_data *netlink;
-	int ioctl_sock; /* socket for ioctl() use */
 	int ifindex;
 	int if_removed;
 	int if_disabled;
+	int ignore_if_down_event;
 	struct rfkill_data *rfkill;
 	struct wpa_driver_capa capa;
 	int has_capability;
@@ -139,42 +227,43 @@
 
 	int scan_complete_events;
 
-	struct nl_handle *nl_handle;
-	struct nl_handle *nl_handle_event;
-	struct nl_handle *nl_handle_preq;
-	struct nl_cache *nl_cache;
-	struct nl_cache *nl_cache_event;
-	struct nl_cache *nl_cache_preq;
 	struct nl_cb *nl_cb;
-	struct genl_family *nl80211;
 
 	u8 auth_bssid[ETH_ALEN];
 	u8 bssid[ETH_ALEN];
 	int associated;
 	u8 ssid[32];
 	size_t ssid_len;
-	int nlmode;
-	int ap_scan_as_station;
+	enum nl80211_iftype nlmode;
+	enum nl80211_iftype ap_scan_as_station;
 	unsigned int assoc_freq;
 
 	int monitor_sock;
 	int monitor_ifidx;
-	int no_monitor_iface_capab;
-	int disable_11b_rates;
+	int monitor_refcount;
 
+	unsigned int disabled_11b_rates:1;
 	unsigned int pending_remain_on_chan:1;
+	unsigned int in_interface_list:1;
+	unsigned int device_ap_sme:1;
+	unsigned int poll_command_supported:1;
+	unsigned int data_tx_status:1;
+	unsigned int scan_for_auth:1;
+	unsigned int retry_auth:1;
+	unsigned int use_monitor:1;
 
 	u64 remain_on_chan_cookie;
 	u64 send_action_cookie;
 
 	unsigned int last_mgmt_freq;
-	unsigned int ap_oper_freq;
 
 	struct wpa_driver_scan_filter *filter_ssids;
 	size_t num_filter_ssids;
 
 	struct i802_bss first_bss;
 
+	int eapol_tx_sock;
+
 #ifdef HOSTAPD
 	int eapol_sock; /* socket for EAPOL frames */
 
@@ -185,12 +274,27 @@
 	int last_freq;
 	int last_freq_ht;
 #endif /* HOSTAPD */
+
+	/* From failed authentication command */
+	int auth_freq;
+	u8 auth_bssid_[ETH_ALEN];
+	u8 auth_ssid[32];
+	size_t auth_ssid_len;
+	int auth_alg;
+	u8 *auth_ie;
+	size_t auth_ie_len;
+	u8 auth_wep_key[4][16];
+	size_t auth_wep_key_len[4];
+	int auth_wep_tx_keyidx;
+	int auth_local_state_change;
+	int auth_p2p;
 };
 
 
 static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
 					    void *timeout_ctx);
-static int wpa_driver_nl80211_set_mode(void *priv, int mode);
+static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
+				       enum nl80211_iftype nlmode);
 static int
 wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv);
 static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
@@ -198,22 +302,28 @@
 				   int local_state_change);
 static void nl80211_remove_monitor_interface(
 	struct wpa_driver_nl80211_data *drv);
-static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv,
+static int nl80211_send_frame_cmd(struct i802_bss *bss,
 				  unsigned int freq, unsigned int wait,
-				  const u8 *buf, size_t buf_len, u64 *cookie);
+				  const u8 *buf, size_t buf_len, u64 *cookie,
+				  int no_cck, int no_ack, int offchanok);
 static int wpa_driver_nl80211_probe_req_report(void *priv, int report);
-#ifdef ANDROID_BRCM_P2P_PATCH
+#ifdef ANDROID
+static int android_pno_start(struct i802_bss *bss,
+			     struct wpa_driver_scan_params *params);
+static int android_pno_stop(struct i802_bss *bss);
+#endif /* ANDROID */
+#ifdef ANDROID_P2P
 static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
 				  enum wpa_event_type type,
 				  const u8 *frame, size_t len);
-int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len);
 int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration);
+int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len);
 int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow);
 int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
 				  const struct wpabuf *proberesp,
 				  const struct wpabuf *assocresp);
-#endif
 
+#endif
 #ifdef HOSTAPD
 static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
 static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
@@ -222,12 +332,19 @@
 					enum wpa_driver_if_type type,
 					const char *ifname);
 #else /* HOSTAPD */
-static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static inline void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+{
+}
+
+static inline void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+{
+}
+
+static inline int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
 {
 	return 0;
 }
 #endif /* HOSTAPD */
-
 #ifdef ANDROID
 extern int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
 					 size_t buf_len);
@@ -238,12 +355,36 @@
 				     int ifindex, int disabled);
 
 static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv);
+static int wpa_driver_nl80211_authenticate_retry(
+	struct wpa_driver_nl80211_data *drv);
+
+
+static int is_ap_interface(enum nl80211_iftype nlmode)
+{
+	return (nlmode == NL80211_IFTYPE_AP ||
+		nlmode == NL80211_IFTYPE_P2P_GO);
+}
+
+
+static int is_sta_interface(enum nl80211_iftype nlmode)
+{
+	return (nlmode == NL80211_IFTYPE_STATION ||
+		nlmode == NL80211_IFTYPE_P2P_CLIENT);
+}
+
+
+static int is_p2p_interface(enum nl80211_iftype nlmode)
+{
+	return (nlmode == NL80211_IFTYPE_P2P_CLIENT ||
+		nlmode == NL80211_IFTYPE_P2P_GO);
+}
 
 
 struct nl80211_bss_info_arg {
 	struct wpa_driver_nl80211_data *drv;
 	struct wpa_scan_results *res;
 	unsigned int assoc_freq;
+	u8 assoc_bssid[ETH_ALEN];
 };
 
 static int bss_info_handler(struct nl_msg *msg, void *arg);
@@ -279,7 +420,7 @@
 }
 
 
-static int send_and_recv(struct wpa_driver_nl80211_data *drv,
+static int send_and_recv(struct nl80211_global *global,
 			 struct nl_handle *nl_handle, struct nl_msg *msg,
 			 int (*valid_handler)(struct nl_msg *, void *),
 			 void *valid_data)
@@ -287,7 +428,7 @@
 	struct nl_cb *cb;
 	int err = -ENOMEM;
 
-	cb = nl_cb_clone(drv->nl_cb);
+	cb = nl_cb_clone(global->nl_cb);
 	if (!cb)
 		goto out;
 
@@ -314,13 +455,22 @@
 }
 
 
+static int send_and_recv_msgs_global(struct nl80211_global *global,
+				     struct nl_msg *msg,
+				     int (*valid_handler)(struct nl_msg *, void *),
+				     void *valid_data)
+{
+	return send_and_recv(global, global->nl, msg, valid_handler,
+			     valid_data);
+}
+
 int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
 			      struct nl_msg *msg,
 			      int (*valid_handler)(struct nl_msg *, void *),
 			      void *valid_data)
 {
-	return send_and_recv(drv, drv->nl_handle, msg, valid_handler,
-			     valid_data);
+	return send_and_recv(drv->global, drv->global->nl, msg,
+			     valid_handler, valid_data);
 }
 
 
@@ -361,7 +511,7 @@
 }
 
 
-static int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv,
+static int nl_get_multicast_id(struct nl80211_global *global,
 			       const char *family, const char *group)
 {
 	struct nl_msg *msg;
@@ -371,11 +521,11 @@
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -ENOMEM;
-	genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"),
+	genlmsg_put(msg, 0, 0, genl_ctrl_resolve(global->nl, "nlctrl"),
 		    0, 0, CTRL_CMD_GETFAMILY, 0);
 	NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
 
-	ret = send_and_recv_msgs(drv, msg, family_handler, &res);
+	ret = send_and_recv_msgs_global(global, msg, family_handler, &res);
 	msg = NULL;
 	if (ret == 0)
 		ret = res.id;
@@ -386,6 +536,235 @@
 }
 
 
+static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
+			  struct nl_msg *msg, int flags, uint8_t cmd)
+{
+	return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
+			   0, flags, cmd, 0);
+}
+
+
+struct wiphy_idx_data {
+	int wiphy_idx;
+};
+
+
+static int netdev_info_handler(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct wiphy_idx_data *info = arg;
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (tb[NL80211_ATTR_WIPHY])
+		info->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
+
+	return NL_SKIP;
+}
+
+
+static int nl80211_get_wiphy_index(struct i802_bss *bss)
+{
+	struct nl_msg *msg;
+	struct wiphy_idx_data data = {
+		.wiphy_idx = -1,
+	};
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_GET_INTERFACE);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+
+	if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0)
+		return data.wiphy_idx;
+	msg = NULL;
+nla_put_failure:
+	nlmsg_free(msg);
+	return -1;
+}
+
+
+static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv,
+				    struct nl80211_wiphy_data *w)
+{
+	struct nl_msg *msg;
+	int ret = -1;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_BEACONS);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, w->wiphy_idx);
+
+	ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL);
+	msg = NULL;
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "nl80211: Register beacons command "
+			   "failed: ret=%d (%s)",
+			   ret, strerror(-ret));
+		goto nla_put_failure;
+	}
+	ret = 0;
+nla_put_failure:
+	nlmsg_free(msg);
+	return ret;
+}
+
+
+static void nl80211_recv_beacons(int sock, void *eloop_ctx, void *handle)
+{
+	struct nl80211_wiphy_data *w = eloop_ctx;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Beacon event message available");
+
+	nl_recvmsgs(handle, w->nl_cb);
+}
+
+
+static int process_beacon_event(struct nl_msg *msg, void *arg)
+{
+	struct nl80211_wiphy_data *w = arg;
+	struct wpa_driver_nl80211_data *drv;
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	union wpa_event_data event;
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (gnlh->cmd != NL80211_CMD_FRAME) {
+		wpa_printf(MSG_DEBUG, "nl80211: Unexpected beacon event? (%d)",
+			   gnlh->cmd);
+		return NL_SKIP;
+	}
+
+	if (!tb[NL80211_ATTR_FRAME])
+		return NL_SKIP;
+
+	dl_list_for_each(drv, &w->drvs, struct wpa_driver_nl80211_data,
+			 wiphy_list) {
+		os_memset(&event, 0, sizeof(event));
+		event.rx_mgmt.frame = nla_data(tb[NL80211_ATTR_FRAME]);
+		event.rx_mgmt.frame_len = nla_len(tb[NL80211_ATTR_FRAME]);
+		wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
+	}
+
+	return NL_SKIP;
+}
+
+
+static struct nl80211_wiphy_data *
+nl80211_get_wiphy_data_ap(struct i802_bss *bss)
+{
+	static DEFINE_DL_LIST(nl80211_wiphys);
+	struct nl80211_wiphy_data *w;
+	int wiphy_idx, found = 0;
+	struct i802_bss *tmp_bss;
+
+	if (bss->wiphy_data != NULL)
+		return bss->wiphy_data;
+
+	wiphy_idx = nl80211_get_wiphy_index(bss);
+
+	dl_list_for_each(w, &nl80211_wiphys, struct nl80211_wiphy_data, list) {
+		if (w->wiphy_idx == wiphy_idx)
+			goto add;
+	}
+
+	/* alloc new one */
+	w = os_zalloc(sizeof(*w));
+	if (w == NULL)
+		return NULL;
+	w->wiphy_idx = wiphy_idx;
+	dl_list_init(&w->bsss);
+	dl_list_init(&w->drvs);
+
+	w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (!w->nl_cb) {
+		os_free(w);
+		return NULL;
+	}
+	nl_cb_set(w->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+	nl_cb_set(w->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_beacon_event,
+		  w);
+
+	w->nl_beacons = nl_create_handle(bss->drv->global->nl_cb,
+					 "wiphy beacons");
+	if (w->nl_beacons == NULL) {
+		os_free(w);
+		return NULL;
+	}
+
+	if (nl80211_register_beacons(bss->drv, w)) {
+		nl_destroy_handles(&w->nl_beacons);
+		os_free(w);
+		return NULL;
+	}
+
+	eloop_register_read_sock(nl_socket_get_fd(w->nl_beacons),
+				 nl80211_recv_beacons, w, w->nl_beacons);
+
+	dl_list_add(&nl80211_wiphys, &w->list);
+
+add:
+	/* drv entry for this bss already there? */
+	dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
+		if (tmp_bss->drv == bss->drv) {
+			found = 1;
+			break;
+		}
+	}
+	/* if not add it */
+	if (!found)
+		dl_list_add(&w->drvs, &bss->drv->wiphy_list);
+
+	dl_list_add(&w->bsss, &bss->wiphy_list);
+	bss->wiphy_data = w;
+	return w;
+}
+
+
+static void nl80211_put_wiphy_data_ap(struct i802_bss *bss)
+{
+	struct nl80211_wiphy_data *w = bss->wiphy_data;
+	struct i802_bss *tmp_bss;
+	int found = 0;
+
+	if (w == NULL)
+		return;
+	bss->wiphy_data = NULL;
+	dl_list_del(&bss->wiphy_list);
+
+	/* still any for this drv present? */
+	dl_list_for_each(tmp_bss, &w->bsss, struct i802_bss, wiphy_list) {
+		if (tmp_bss->drv == bss->drv) {
+			found = 1;
+			break;
+		}
+	}
+	/* if not remove it */
+	if (!found)
+		dl_list_del(&bss->drv->wiphy_list);
+
+	if (!dl_list_empty(&w->bsss))
+		return;
+
+	eloop_unregister_read_sock(nl_socket_get_fd(w->nl_beacons));
+
+	nl_cb_put(w->nl_cb);
+	nl_destroy_handles(&w->nl_beacons);
+	dl_list_del(&w->list);
+	os_free(w);
+}
+
+
 static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
 {
 	struct i802_bss *bss = priv;
@@ -479,17 +858,33 @@
 }
 
 
+static struct wpa_driver_nl80211_data *
+nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len)
+{
+	struct wpa_driver_nl80211_data *drv;
+	dl_list_for_each(drv, &global->interfaces,
+			 struct wpa_driver_nl80211_data, list) {
+		if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
+		    have_ifidx(drv, idx))
+			return drv;
+	}
+	return NULL;
+}
+
+
 static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 						 struct ifinfomsg *ifi,
 						 u8 *buf, size_t len)
 {
-	struct wpa_driver_nl80211_data *drv = ctx;
+	struct nl80211_global *global = ctx;
+	struct wpa_driver_nl80211_data *drv;
 	int attrlen, rta_len;
 	struct rtattr *attr;
 	u32 brid = 0;
+	char namebuf[IFNAMSIZ];
 
-	if (!wpa_driver_nl80211_own_ifindex(drv, ifi->ifi_index, buf, len) &&
-	    !have_ifidx(drv, ifi->ifi_index)) {
+	drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
+	if (!drv) {
 		wpa_printf(MSG_DEBUG, "nl80211: Ignore event for foreign "
 			   "ifindex %d", ifi->ifi_index);
 		return;
@@ -504,15 +899,38 @@
 		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
 
 	if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
+		if (if_indextoname(ifi->ifi_index, namebuf) &&
+		    linux_iface_up(drv->global->ioctl_sock,
+				   drv->first_bss.ifname) > 0) {
+			wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
+				   "event since interface %s is up", namebuf);
+			return;
+		}
 		wpa_printf(MSG_DEBUG, "nl80211: Interface down");
-		drv->if_disabled = 1;
-		wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
+		if (drv->ignore_if_down_event) {
+			wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
+				   "event generated by mode change");
+			drv->ignore_if_down_event = 0;
+		} else {
+			drv->if_disabled = 1;
+			wpa_supplicant_event(drv->ctx,
+					     EVENT_INTERFACE_DISABLED, NULL);
+		}
 	}
 
 	if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
-		wpa_printf(MSG_DEBUG, "nl80211: Interface up");
-		drv->if_disabled = 0;
-		wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
+		if (if_indextoname(ifi->ifi_index, namebuf) &&
+		    linux_iface_up(drv->global->ioctl_sock,
+				   drv->first_bss.ifname) == 0) {
+			wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
+				   "event since interface %s is down",
+				   namebuf);
+		} else {
+			wpa_printf(MSG_DEBUG, "nl80211: Interface up");
+			drv->if_disabled = 0;
+			wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
+					     NULL);
+		}
 	}
 
 	/*
@@ -524,7 +942,7 @@
 	if (drv->operstate == 1 &&
 	    (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
 	    !(ifi->ifi_flags & IFF_RUNNING))
-		netlink_send_oper_ifla(drv->netlink, drv->ifindex,
+		netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
 				       -1, IF_OPER_UP);
 
 	attrlen = len;
@@ -541,16 +959,13 @@
 		attr = RTA_NEXT(attr, attrlen);
 	}
 
-#ifdef HOSTAPD
 	if (ifi->ifi_family == AF_BRIDGE && brid) {
 		/* device has been added to bridge */
-		char namebuf[IFNAMSIZ];
 		if_indextoname(brid, namebuf);
 		wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
 			   brid, namebuf);
 		add_ifidx(drv, brid);
 	}
-#endif /* HOSTAPD */
 }
 
 
@@ -558,11 +973,19 @@
 						 struct ifinfomsg *ifi,
 						 u8 *buf, size_t len)
 {
-	struct wpa_driver_nl80211_data *drv = ctx;
+	struct nl80211_global *global = ctx;
+	struct wpa_driver_nl80211_data *drv;
 	int attrlen, rta_len;
 	struct rtattr *attr;
 	u32 brid = 0;
 
+	drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
+	if (!drv) {
+		wpa_printf(MSG_DEBUG, "nl80211: Ignore dellink event for "
+			   "foreign ifindex %d", ifi->ifi_index);
+		return;
+	}
+
 	attrlen = len;
 	attr = (struct rtattr *) buf;
 
@@ -578,7 +1001,6 @@
 		attr = RTA_NEXT(attr, attrlen);
 	}
 
-#ifdef HOSTAPD
 	if (ifi->ifi_family == AF_BRIDGE && brid) {
 		/* device has been removed from bridge */
 		char namebuf[IFNAMSIZ];
@@ -587,7 +1009,6 @@
 			   "%s", brid, namebuf);
 		del_ifidx(drv, brid);
 	}
-#endif /* HOSTAPD */
 }
 
 
@@ -629,8 +1050,7 @@
 	if (!msg)
 		goto nla_put_failure;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, NLM_F_DUMP,
-		    NL80211_CMD_GET_SCAN, 0);
+	nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 
 	arg.drv = drv;
@@ -656,12 +1076,12 @@
 	const struct ieee80211_mgmt *mgmt;
 	union wpa_event_data event;
 	u16 status;
-#ifdef ANDROID_BRCM_P2P_PATCH
+#ifdef ANDROID_P2P
 	struct wpa_supplicant *wpa_s = drv->ctx;
 #endif
 
 	mgmt = (const struct ieee80211_mgmt *) frame;
-#if (defined (CONFIG_AP) || defined (HOSTAPD) ) && defined (ANDROID_BRCM_P2P_PATCH)
+#if (defined (CONFIG_AP) || defined (HOSTAPD) ) && defined (ANDROID_P2P)
 	if (drv->nlmode == NL80211_IFTYPE_AP || drv->nlmode == NL80211_IFTYPE_P2P_GO) {
 		if (len < 24 + sizeof(mgmt->u.assoc_req)) {
 			wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
@@ -674,7 +1094,7 @@
 		event.assoc_info.req_ies_len = len - 24 - sizeof(mgmt->u.assoc_req);
 		event.assoc_info.addr = mgmt->sa;
 	} else {
-#endif	
+#endif
 	if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
 		wpa_printf(MSG_DEBUG, "nl80211: Too short association event "
 			   "frame");
@@ -708,7 +1128,7 @@
 	}
 
 	event.assoc_info.freq = drv->assoc_freq;
-#if (defined (CONFIG_AP) || defined(HOSTAPD)) && defined (ANDROID_BRCM_P2P_PATCH)
+#if (defined (CONFIG_AP) || defined(HOSTAPD)) && defined (ANDROID_P2P)
 	}
 #endif
 	wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
@@ -765,6 +1185,29 @@
 }
 
 
+static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
+				  struct nlattr *reason, struct nlattr *addr)
+{
+	union wpa_event_data data;
+
+	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
+		/*
+		 * Avoid reporting two disassociation events that could
+		 * confuse the core code.
+		 */
+		wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
+			   "event when using userspace SME");
+		return;
+	}
+
+	drv->associated = 0;
+	os_memset(&data, 0, sizeof(data));
+	if (reason)
+		data.disassoc_info.reason_code = nla_get_u16(reason);
+	wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data);
+}
+
+
 static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
 			       enum nl80211_commands cmd, struct nlattr *addr)
 {
@@ -819,7 +1262,7 @@
 		event.rx_action.data = &mgmt->u.action.category + 1;
 		event.rx_action.len = frame + len - event.rx_action.data;
 		wpa_supplicant_event(drv->ctx, EVENT_RX_ACTION, &event);
-#ifdef ANDROID_BRCM_P2P_PATCH
+#ifdef ANDROID_P2P
 	} else if (stype == WLAN_FC_STYPE_ASSOC_REQ) {
 		mlme_event_assoc(drv, frame, len);
 	} else if (stype == WLAN_FC_STYPE_DISASSOC) {
@@ -835,26 +1278,29 @@
 }
 
 
-static void mlme_event_action_tx_status(struct wpa_driver_nl80211_data *drv,
-					struct nlattr *cookie, const u8 *frame,
-					size_t len, struct nlattr *ack)
+static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv,
+				      struct nlattr *cookie, const u8 *frame,
+				      size_t len, struct nlattr *ack)
 {
 	union wpa_event_data event;
 	const struct ieee80211_hdr *hdr;
 	u16 fc;
-	u64 cookie_val;
 
-	if (!cookie)
-		return;
+	if (!is_ap_interface(drv->nlmode)) {
+		u64 cookie_val;
 
-	cookie_val = nla_get_u64(cookie);
-	wpa_printf(MSG_DEBUG, "nl80211: Action TX status: cookie=0%llx%s "
-		   "(ack=%d)",
-		   (long long unsigned int) cookie_val,
-		   cookie_val == drv->send_action_cookie ?
-		   " (match)" : " (unknown)", ack != NULL);
-	if (cookie_val != drv->send_action_cookie)
-		return;
+		if (!cookie)
+			return;
+
+		cookie_val = nla_get_u64(cookie);
+		wpa_printf(MSG_DEBUG, "nl80211: Action TX status:"
+			   " cookie=0%llx%s (ack=%d)",
+			   (long long unsigned int) cookie_val,
+			   cookie_val == drv->send_action_cookie ?
+			   " (match)" : " (unknown)", ack != NULL);
+		if (cookie_val != drv->send_action_cookie)
+			return;
+	}
 
 	hdr = (const struct ieee80211_hdr *) frame;
 	fc = le_to_host16(hdr->frame_control);
@@ -906,7 +1352,7 @@
 		reason_code = le_to_host16(mgmt->u.deauth.reason_code);
 
 	if (type == EVENT_DISASSOC) {
-#ifdef ANDROID_BRCM_P2P_PATCH
+#ifdef ANDROID_P2P
 		if (drv->nlmode == NL80211_IFTYPE_AP ||
 			drv->nlmode == NL80211_IFTYPE_P2P_GO) {
 			event.disassoc_info.addr = mgmt->sa;
@@ -920,7 +1366,7 @@
 				mgmt->u.disassoc.variable;
 		}
 	} else {
-#ifdef ANDROID_BRCM_P2P_PATCH
+#ifdef ANDROID_P2P
 		if (drv->nlmode == NL80211_IFTYPE_AP ||
 			drv->nlmode == NL80211_IFTYPE_P2P_GO) {
 		event.deauth_info.addr = mgmt->sa;
@@ -1011,8 +1457,8 @@
 		mlme_event_mgmt(drv, freq, nla_data(frame), nla_len(frame));
 		break;
 	case NL80211_CMD_FRAME_TX_STATUS:
-		mlme_event_action_tx_status(drv, cookie, nla_data(frame),
-					    nla_len(frame), ack);
+		mlme_event_mgmt_tx_status(drv, cookie, nla_data(frame),
+					  nla_len(frame), ack);
 		break;
 	case NL80211_CMD_UNPROT_DEAUTHENTICATE:
 		mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DEAUTH,
@@ -1117,7 +1563,8 @@
 	if (cookie != drv->remain_on_chan_cookie)
 		return; /* not for us */
 
-	drv->pending_remain_on_chan = !cancel_event;
+	if (cancel_event)
+		drv->pending_remain_on_chan = 0;
 
 	os_memset(&data, 0, sizeof(data));
 	data.remain_on_channel.freq = freq;
@@ -1139,6 +1586,14 @@
 	int freqs[MAX_REPORT_FREQS];
 	int num_freqs = 0;
 
+	if (drv->scan_for_auth) {
+		drv->scan_for_auth = 0;
+		wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
+			   "cfg80211 BSS entry");
+		wpa_driver_nl80211_authenticate_retry(drv);
+		return;
+	}
+
 	os_memset(&event, 0, sizeof(event));
 	info = &event.scan_info;
 	info->aborted = aborted;
@@ -1228,14 +1683,14 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_GET_STATION, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, drv->bssid);
 
 	return send_and_recv_msgs(drv, msg, get_link_signal, sig);
  nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -1296,13 +1751,88 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    NLM_F_DUMP, NL80211_CMD_GET_SURVEY, 0);
+	nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 
 	return send_and_recv_msgs(drv, msg, get_link_noise, sig_change);
  nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+
+static int get_noise_for_scan_results(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
+	static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
+		[NL80211_SURVEY_INFO_FREQUENCY] = { .type = NLA_U32 },
+		[NL80211_SURVEY_INFO_NOISE] = { .type = NLA_U8 },
+	};
+	struct wpa_scan_results *scan_results = arg;
+	struct wpa_scan_res *scan_res;
+	size_t i;
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (!tb[NL80211_ATTR_SURVEY_INFO]) {
+		wpa_printf(MSG_DEBUG, "nl80211: Survey data missing");
+		return NL_SKIP;
+	}
+
+	if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,
+			     tb[NL80211_ATTR_SURVEY_INFO],
+			     survey_policy)) {
+		wpa_printf(MSG_DEBUG, "nl80211: Failed to parse nested "
+			   "attributes");
+		return NL_SKIP;
+	}
+
+	if (!sinfo[NL80211_SURVEY_INFO_NOISE])
+		return NL_SKIP;
+
+	if (!sinfo[NL80211_SURVEY_INFO_FREQUENCY])
+		return NL_SKIP;
+
+	for (i = 0; i < scan_results->num; ++i) {
+		scan_res = scan_results->res[i];
+		if (!scan_res)
+			continue;
+		if ((int) nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]) !=
+		    scan_res->freq)
+			continue;
+		if (!(scan_res->flags & WPA_SCAN_NOISE_INVALID))
+			continue;
+		scan_res->noise = (s8)
+			nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
+		scan_res->flags &= ~WPA_SCAN_NOISE_INVALID;
+	}
+
+	return NL_SKIP;
+}
+
+
+static int nl80211_get_noise_for_scan_results(
+	struct wpa_driver_nl80211_data *drv,
+	struct wpa_scan_results *scan_res)
+{
+	struct nl_msg *msg;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+	return send_and_recv_msgs(drv, msg, get_noise_for_scan_results,
+				  scan_res);
+ nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -1385,8 +1915,7 @@
 	addr = nla_data(tb[NL80211_ATTR_MAC]);
 	wpa_printf(MSG_DEBUG, "nl80211: New station " MACSTR, MAC2STR(addr));
 
-	if (drv->nlmode == NL80211_IFTYPE_AP &&
-	    drv->no_monitor_iface_capab) {
+	if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
 		u8 *ies = NULL;
 		size_t ies_len = 0;
 		if (tb[NL80211_ATTR_IE]) {
@@ -1419,8 +1948,7 @@
 	wpa_printf(MSG_DEBUG, "nl80211: Delete station " MACSTR,
 		   MAC2STR(addr));
 
-	if (drv->nlmode == NL80211_IFTYPE_AP &&
-	    drv->no_monitor_iface_capab) {
+	if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
 		drv_event_disassoc(drv->ctx, addr);
 		return;
 	}
@@ -1434,38 +1962,138 @@
 }
 
 
-static int process_event(struct nl_msg *msg, void *arg)
+static void nl80211_rekey_offload_event(struct wpa_driver_nl80211_data *drv,
+					struct nlattr **tb)
 {
-	struct wpa_driver_nl80211_data *drv = arg;
-	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	struct nlattr *rekey_info[NUM_NL80211_REKEY_DATA];
+	static struct nla_policy rekey_policy[NUM_NL80211_REKEY_DATA] = {
+		[NL80211_REKEY_DATA_KEK] = {
+			.minlen = NL80211_KEK_LEN,
+			.maxlen = NL80211_KEK_LEN,
+		},
+		[NL80211_REKEY_DATA_KCK] = {
+			.minlen = NL80211_KCK_LEN,
+			.maxlen = NL80211_KCK_LEN,
+		},
+		[NL80211_REKEY_DATA_REPLAY_CTR] = {
+			.minlen = NL80211_REPLAY_CTR_LEN,
+			.maxlen = NL80211_REPLAY_CTR_LEN,
+		},
+	};
 	union wpa_event_data data;
 
-	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
-		  genlmsg_attrlen(gnlh, 0), NULL);
+	if (!tb[NL80211_ATTR_MAC])
+		return;
+	if (!tb[NL80211_ATTR_REKEY_DATA])
+		return;
+	if (nla_parse_nested(rekey_info, MAX_NL80211_REKEY_DATA,
+			     tb[NL80211_ATTR_REKEY_DATA], rekey_policy))
+		return;
+	if (!rekey_info[NL80211_REKEY_DATA_REPLAY_CTR])
+		return;
 
-	if (tb[NL80211_ATTR_IFINDEX]) {
-		int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
-		if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) {
-			wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)"
-				   " for foreign interface (ifindex %d)",
-				   gnlh->cmd, ifindex);
-			return NL_SKIP;
-		}
-	}
+	os_memset(&data, 0, sizeof(data));
+	data.driver_gtk_rekey.bssid = nla_data(tb[NL80211_ATTR_MAC]);
+	wpa_printf(MSG_DEBUG, "nl80211: Rekey offload event for BSSID " MACSTR,
+		   MAC2STR(data.driver_gtk_rekey.bssid));
+	data.driver_gtk_rekey.replay_ctr =
+		nla_data(rekey_info[NL80211_REKEY_DATA_REPLAY_CTR]);
+	wpa_hexdump(MSG_DEBUG, "nl80211: Rekey offload - Replay Counter",
+		    data.driver_gtk_rekey.replay_ctr, NL80211_REPLAY_CTR_LEN);
+	wpa_supplicant_event(drv->ctx, EVENT_DRIVER_GTK_REKEY, &data);
+}
 
-	if (drv->ap_scan_as_station &&
-	    (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
-	     gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) {
+
+static void nl80211_pmksa_candidate_event(struct wpa_driver_nl80211_data *drv,
+					  struct nlattr **tb)
+{
+	struct nlattr *cand[NUM_NL80211_PMKSA_CANDIDATE];
+	static struct nla_policy cand_policy[NUM_NL80211_PMKSA_CANDIDATE] = {
+		[NL80211_PMKSA_CANDIDATE_INDEX] = { .type = NLA_U32 },
+		[NL80211_PMKSA_CANDIDATE_BSSID] = {
+			.minlen = ETH_ALEN,
+			.maxlen = ETH_ALEN,
+		},
+		[NL80211_PMKSA_CANDIDATE_PREAUTH] = { .type = NLA_FLAG },
+	};
+	union wpa_event_data data;
+
+	if (!tb[NL80211_ATTR_PMKSA_CANDIDATE])
+		return;
+	if (nla_parse_nested(cand, MAX_NL80211_PMKSA_CANDIDATE,
+			     tb[NL80211_ATTR_PMKSA_CANDIDATE], cand_policy))
+		return;
+	if (!cand[NL80211_PMKSA_CANDIDATE_INDEX] ||
+	    !cand[NL80211_PMKSA_CANDIDATE_BSSID])
+		return;
+
+	os_memset(&data, 0, sizeof(data));
+	os_memcpy(data.pmkid_candidate.bssid,
+		  nla_data(cand[NL80211_PMKSA_CANDIDATE_BSSID]), ETH_ALEN);
+	data.pmkid_candidate.index =
+		nla_get_u32(cand[NL80211_PMKSA_CANDIDATE_INDEX]);
+	data.pmkid_candidate.preauth =
+		cand[NL80211_PMKSA_CANDIDATE_PREAUTH] != NULL;
+	wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE, &data);
+}
+
+
+static void nl80211_client_probe_event(struct wpa_driver_nl80211_data *drv,
+				       struct nlattr **tb)
+{
+	union wpa_event_data data;
+
+	if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_ACK])
+		return;
+
+	os_memset(&data, 0, sizeof(data));
+	os_memcpy(data.client_poll.addr,
+		  nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN);
+
+	wpa_supplicant_event(drv->ctx, EVENT_DRIVER_CLIENT_POLL_OK, &data);
+}
+
+
+static void nl80211_spurious_frame(struct i802_bss *bss, struct nlattr **tb,
+				   int wds)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	union wpa_event_data event;
+
+	if (!tb[NL80211_ATTR_MAC])
+		return;
+
+	os_memset(&event, 0, sizeof(event));
+	event.rx_from_unknown.bssid = bss->addr;
+	event.rx_from_unknown.addr = nla_data(tb[NL80211_ATTR_MAC]);
+	event.rx_from_unknown.wds = wds;
+
+	wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
+}
+
+
+static void do_process_drv_event(struct wpa_driver_nl80211_data *drv,
+				 int cmd, struct nlattr **tb)
+{
+	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
+	    (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
+	     cmd == NL80211_CMD_SCAN_ABORTED)) {
 		wpa_driver_nl80211_set_mode(&drv->first_bss,
-					    IEEE80211_MODE_AP);
-		drv->ap_scan_as_station = 0;
+					    drv->ap_scan_as_station);
+		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 	}
 
-	switch (gnlh->cmd) {
+	switch (cmd) {
 	case NL80211_CMD_TRIGGER_SCAN:
 		wpa_printf(MSG_DEBUG, "nl80211: Scan trigger");
 		break;
+	case NL80211_CMD_START_SCHED_SCAN:
+		wpa_printf(MSG_DEBUG, "nl80211: Sched scan started");
+		break;
+	case NL80211_CMD_SCHED_SCAN_STOPPED:
+		wpa_printf(MSG_DEBUG, "nl80211: Sched scan stopped");
+		wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
+		break;
 	case NL80211_CMD_NEW_SCAN_RESULTS:
 		wpa_printf(MSG_DEBUG, "nl80211: New scan results available");
 		drv->scan_complete_events = 1;
@@ -1473,6 +2101,11 @@
 				     drv->ctx);
 		send_scan_event(drv, 0, tb);
 		break;
+	case NL80211_CMD_SCHED_SCAN_RESULTS:
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: New sched scan results available");
+		send_scan_event(drv, 0, tb);
+		break;
 	case NL80211_CMD_SCAN_ABORTED:
 		wpa_printf(MSG_DEBUG, "nl80211: Scan aborted");
 		/*
@@ -1487,39 +2120,25 @@
 	case NL80211_CMD_ASSOCIATE:
 	case NL80211_CMD_DEAUTHENTICATE:
 	case NL80211_CMD_DISASSOCIATE:
-	case NL80211_CMD_FRAME:
 	case NL80211_CMD_FRAME_TX_STATUS:
 	case NL80211_CMD_UNPROT_DEAUTHENTICATE:
 	case NL80211_CMD_UNPROT_DISASSOCIATE:
-		mlme_event(drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],
+		mlme_event(drv, cmd, tb[NL80211_ATTR_FRAME],
 			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
 			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
 			   tb[NL80211_ATTR_COOKIE]);
 		break;
 	case NL80211_CMD_CONNECT:
 	case NL80211_CMD_ROAM:
-		mlme_event_connect(drv, gnlh->cmd,
+		mlme_event_connect(drv, cmd,
 				   tb[NL80211_ATTR_STATUS_CODE],
 				   tb[NL80211_ATTR_MAC],
 				   tb[NL80211_ATTR_REQ_IE],
 				   tb[NL80211_ATTR_RESP_IE]);
 		break;
 	case NL80211_CMD_DISCONNECT:
-		if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) {
-			/*
-			 * Avoid reporting two disassociation events that could
-			 * confuse the core code.
-			 */
-			wpa_printf(MSG_DEBUG, "nl80211: Ignore disconnect "
-				   "event when using userspace SME");
-			break;
-		}
-		drv->associated = 0;
-		os_memset(&data, 0, sizeof(data));
-		if (tb[NL80211_ATTR_REASON_CODE])
-			data.disassoc_info.reason_code =
-				nla_get_u16(tb[NL80211_ATTR_REASON_CODE]);
-		wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, &data);
+		mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
+				      tb[NL80211_ATTR_MAC]);
 		break;
 	case NL80211_CMD_MICHAEL_MIC_FAILURE:
 		mlme_event_michael_mic_failure(drv, tb);
@@ -1552,6 +2171,95 @@
 	case NL80211_CMD_DEL_STATION:
 		nl80211_del_station_event(drv, tb);
 		break;
+	case NL80211_CMD_SET_REKEY_OFFLOAD:
+		nl80211_rekey_offload_event(drv, tb);
+		break;
+	case NL80211_CMD_PMKSA_CANDIDATE:
+		nl80211_pmksa_candidate_event(drv, tb);
+		break;
+	case NL80211_CMD_PROBE_CLIENT:
+		nl80211_client_probe_event(drv, tb);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
+			   "(cmd=%d)", cmd);
+		break;
+	}
+}
+
+
+static int process_drv_event(struct nl_msg *msg, void *arg)
+{
+	struct wpa_driver_nl80211_data *drv = arg;
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (tb[NL80211_ATTR_IFINDEX]) {
+		int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
+		if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) {
+			wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)"
+				   " for foreign interface (ifindex %d)",
+				   gnlh->cmd, ifindex);
+			return NL_SKIP;
+		}
+	}
+
+	do_process_drv_event(drv, gnlh->cmd, tb);
+	return NL_SKIP;
+}
+
+
+static int process_global_event(struct nl_msg *msg, void *arg)
+{
+	struct nl80211_global *global = arg;
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	struct wpa_driver_nl80211_data *drv;
+	int ifidx = -1;
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (tb[NL80211_ATTR_IFINDEX])
+		ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
+
+	dl_list_for_each(drv, &global->interfaces,
+			 struct wpa_driver_nl80211_data, list) {
+		if (ifidx == -1 || ifidx == drv->ifindex ||
+		    have_ifidx(drv, ifidx))
+			do_process_drv_event(drv, gnlh->cmd, tb);
+	}
+
+	return NL_SKIP;
+}
+
+
+static int process_bss_event(struct nl_msg *msg, void *arg)
+{
+	struct i802_bss *bss = arg;
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	switch (gnlh->cmd) {
+	case NL80211_CMD_FRAME:
+	case NL80211_CMD_FRAME_TX_STATUS:
+		mlme_event(bss->drv, gnlh->cmd, tb[NL80211_ATTR_FRAME],
+			   tb[NL80211_ATTR_MAC], tb[NL80211_ATTR_TIMED_OUT],
+			   tb[NL80211_ATTR_WIPHY_FREQ], tb[NL80211_ATTR_ACK],
+			   tb[NL80211_ATTR_COOKIE]);
+		break;
+	case NL80211_CMD_UNEXPECTED_FRAME:
+		nl80211_spurious_frame(bss, tb, 0);
+		break;
+	case NL80211_CMD_UNEXPECTED_4ADDR_FRAME:
+		nl80211_spurious_frame(bss, tb, 1);
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
 			   "(cmd=%d)", gnlh->cmd);
@@ -1565,18 +2273,11 @@
 static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
 					     void *handle)
 {
-	struct nl_cb *cb;
-	struct wpa_driver_nl80211_data *drv = eloop_ctx;
+	struct nl_cb *cb = eloop_ctx;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Event message available");
 
-	cb = nl_cb_clone(drv->nl_cb);
-	if (!cb)
-		return;
-	nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
-	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, process_event, drv);
 	nl_recvmsgs(handle, cb);
-	nl_cb_put(cb);
 }
 
 
@@ -1604,43 +2305,82 @@
 	alpha2[1] = alpha2_arg[1];
 	alpha2[2] = '\0';
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_REQ_SET_REG, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_REQ_SET_REG);
 
 	NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
 	if (send_and_recv_msgs(drv, msg, NULL, NULL))
 		return -EINVAL;
 	return 0;
 nla_put_failure:
+	nlmsg_free(msg);
 	return -EINVAL;
 }
 
 
 struct wiphy_info_data {
-	int max_scan_ssids;
-	int ap_supported;
-	int p2p_supported;
-	int auth_supported;
-	int connect_supported;
-	int offchan_tx_supported;
-	int max_remain_on_chan;
+	struct wpa_driver_capa *capa;
+
+	unsigned int error:1;
+	unsigned int device_ap_sme:1;
+	unsigned int poll_command_supported:1;
+	unsigned int data_tx_status:1;
+	unsigned int monitor_supported:1;
 };
 
 
+static unsigned int probe_resp_offload_support(int supp_protocols)
+{
+	unsigned int prot = 0;
+
+	if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS)
+		prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS;
+	if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)
+		prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2;
+	if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P)
+		prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P;
+	if (supp_protocols & NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U)
+		prot |= WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING;
+
+	return prot;
+}
+
+
 static int wiphy_info_handler(struct nl_msg *msg, void *arg)
 {
 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
 	struct wiphy_info_data *info = arg;
 	int p2p_go_supported = 0, p2p_client_supported = 0;
+	int p2p_concurrent = 0;
+	int auth_supported = 0, connect_supported = 0;
+	struct wpa_driver_capa *capa = info->capa;
+	static struct nla_policy
+	iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
+		[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
+		[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
+		[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
+		[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
+	},
+	iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
+		[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
+		[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
+	};
 
 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
 		  genlmsg_attrlen(gnlh, 0), NULL);
 
 	if (tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS])
-		info->max_scan_ssids =
+		capa->max_scan_ssids =
 			nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
 
+	if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])
+		capa->max_sched_scan_ssids =
+			nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
+
+	if (tb[NL80211_ATTR_MAX_MATCH_SETS])
+		capa->max_match_sets =
+			nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
+
 	if (tb[NL80211_ATTR_SUPPORTED_IFTYPES]) {
 		struct nlattr *nl_mode;
 		int i;
@@ -1648,7 +2388,7 @@
 				    tb[NL80211_ATTR_SUPPORTED_IFTYPES], i) {
 			switch (nla_type(nl_mode)) {
 			case NL80211_IFTYPE_AP:
-				info->ap_supported = 1;
+				capa->flags |= WPA_DRIVER_FLAGS_AP;
 				break;
 			case NL80211_IFTYPE_P2P_GO:
 				p2p_go_supported = 1;
@@ -1656,11 +2396,69 @@
 			case NL80211_IFTYPE_P2P_CLIENT:
 				p2p_client_supported = 1;
 				break;
+			case NL80211_IFTYPE_MONITOR:
+				info->monitor_supported = 1;
+				break;
 			}
 		}
 	}
 
-	info->p2p_supported = p2p_go_supported && p2p_client_supported;
+	if (tb[NL80211_ATTR_INTERFACE_COMBINATIONS]) {
+		struct nlattr *nl_combi;
+		int rem_combi;
+
+		nla_for_each_nested(nl_combi,
+				    tb[NL80211_ATTR_INTERFACE_COMBINATIONS],
+				    rem_combi) {
+			struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+			struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+			struct nlattr *nl_limit, *nl_mode;
+			int err, rem_limit, rem_mode;
+			int combination_has_p2p = 0, combination_has_mgd = 0;
+
+			err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
+					       nl_combi,
+					       iface_combination_policy);
+			if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
+			    !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
+			    !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
+				goto broken_combination;
+
+			nla_for_each_nested(nl_limit,
+					    tb_comb[NL80211_IFACE_COMB_LIMITS],
+					    rem_limit) {
+				err = nla_parse_nested(tb_limit,
+						       MAX_NL80211_IFACE_LIMIT,
+						       nl_limit,
+						       iface_limit_policy);
+				if (err ||
+				    !tb_limit[NL80211_IFACE_LIMIT_TYPES])
+					goto broken_combination;
+
+				nla_for_each_nested(
+					nl_mode,
+					tb_limit[NL80211_IFACE_LIMIT_TYPES],
+					rem_mode) {
+					int ift = nla_type(nl_mode);
+					if (ift == NL80211_IFTYPE_P2P_GO ||
+					    ift == NL80211_IFTYPE_P2P_CLIENT)
+						combination_has_p2p = 1;
+					if (ift == NL80211_IFTYPE_STATION)
+						combination_has_mgd = 1;
+				}
+				if (combination_has_p2p && combination_has_mgd)
+					break;
+			}
+
+			if (combination_has_p2p && combination_has_mgd) {
+				p2p_concurrent = 1;
+				break;
+			}
+
+broken_combination:
+			;
+		}
+	}
 
 	if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {
 		struct nlattr *nl_cmd;
@@ -1668,21 +2466,92 @@
 
 		nla_for_each_nested(nl_cmd,
 				    tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) {
-			u32 cmd = nla_get_u32(nl_cmd);
-			if (cmd == NL80211_CMD_AUTHENTICATE)
-				info->auth_supported = 1;
-			else if (cmd == NL80211_CMD_CONNECT)
-				info->connect_supported = 1;
+			switch (nla_get_u32(nl_cmd)) {
+			case NL80211_CMD_AUTHENTICATE:
+				auth_supported = 1;
+				break;
+			case NL80211_CMD_CONNECT:
+				connect_supported = 1;
+				break;
+			case NL80211_CMD_START_SCHED_SCAN:
+				capa->sched_scan_supported = 1;
+				break;
+			case NL80211_CMD_PROBE_CLIENT:
+				info->poll_command_supported = 1;
+				break;
+			}
 		}
 	}
 
-	if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK])
-		info->offchan_tx_supported = 1;
+	if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
+		wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
+			   "off-channel TX");
+		capa->flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
+	}
+
+	if (tb[NL80211_ATTR_ROAM_SUPPORT]) {
+		wpa_printf(MSG_DEBUG, "nl80211: Using driver-based roaming");
+		capa->flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
+	}
+
+	/* default to 5000 since early versions of mac80211 don't set it */
+	capa->max_remain_on_chan = 5000;
+
+	if (tb[NL80211_ATTR_SUPPORT_AP_UAPSD])
+		capa->flags |= WPA_DRIVER_FLAGS_AP_UAPSD;
 
 	if (tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION])
-		info->max_remain_on_chan =
+		capa->max_remain_on_chan =
 			nla_get_u32(tb[NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION]);
 
+	if (auth_supported)
+		capa->flags |= WPA_DRIVER_FLAGS_SME;
+	else if (!connect_supported) {
+		wpa_printf(MSG_INFO, "nl80211: Driver does not support "
+			   "authentication/association or connect commands");
+		info->error = 1;
+	}
+
+	if (p2p_go_supported && p2p_client_supported)
+		capa->flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
+	if (p2p_concurrent) {
+		wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
+			   "interface (driver advertised support)");
+		capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
+		capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
+	}
+
+	if (tb[NL80211_ATTR_TDLS_SUPPORT]) {
+		wpa_printf(MSG_DEBUG, "nl80211: TDLS supported");
+		capa->flags |= WPA_DRIVER_FLAGS_TDLS_SUPPORT;
+
+		if (tb[NL80211_ATTR_TDLS_EXTERNAL_SETUP]) {
+			wpa_printf(MSG_DEBUG, "nl80211: TDLS external setup");
+			capa->flags |=
+				WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP;
+		}
+	}
+
+	if (tb[NL80211_ATTR_DEVICE_AP_SME])
+		info->device_ap_sme = 1;
+
+	if (tb[NL80211_ATTR_FEATURE_FLAGS]) {
+		u32 flags = nla_get_u32(tb[NL80211_ATTR_FEATURE_FLAGS]);
+
+		if (flags & NL80211_FEATURE_SK_TX_STATUS)
+			info->data_tx_status = 1;
+	}
+
+	if (tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]) {
+		int protocols =
+			nla_get_u32(tb[NL80211_ATTR_PROBE_RESP_OFFLOAD]);
+		wpa_printf(MSG_DEBUG, "nl80211: Supports Probe Response "
+			   "offload in AP mode");
+		capa->flags |= WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD;
+		capa->probe_resp_offloads =
+			probe_resp_offload_support(protocols);
+	}
+
 	return NL_SKIP;
 }
 
@@ -1693,16 +2562,13 @@
 	struct nl_msg *msg;
 
 	os_memset(info, 0, sizeof(*info));
-
-	/* default to 5000 since early versions of mac80211 don't set it */
-	info->max_remain_on_chan = 5000;
+	info->capa = &drv->capa;
 
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_GET_WIPHY, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->first_bss.ifindex);
 
@@ -1720,6 +2586,10 @@
 	struct wiphy_info_data info;
 	if (wpa_driver_nl80211_get_info(drv, &info))
 		return -1;
+
+	if (info.error)
+		return -1;
+
 	drv->has_capability = 1;
 	/* For now, assume TKIP, CCMP, WPA, WPA2 are supported */
 	drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
@@ -1734,131 +2604,132 @@
 		WPA_DRIVER_AUTH_SHARED |
 		WPA_DRIVER_AUTH_LEAP;
 
-	drv->capa.max_scan_ssids = info.max_scan_ssids;
-	if (info.ap_supported)
-		drv->capa.flags |= WPA_DRIVER_FLAGS_AP;
-
-	if (info.auth_supported)
-		drv->capa.flags |= WPA_DRIVER_FLAGS_SME;
-	else if (!info.connect_supported) {
-		wpa_printf(MSG_INFO, "nl80211: Driver does not support "
-			   "authentication/association or connect commands");
-		return -1;
-	}
-
-	if (info.offchan_tx_supported) {
-		wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
-			   "off-channel TX");
-		drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
-	}
-
 	drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
 	drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
-	if (info.p2p_supported)
-		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
 	drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
-	drv->capa.max_remain_on_chan = info.max_remain_on_chan;
+	drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
+
+	drv->device_ap_sme = info.device_ap_sme;
+	drv->poll_command_supported = info.poll_command_supported;
+	drv->data_tx_status = info.data_tx_status;
+
+	/*
+	 * If poll command is supported mac80211 is new enough to
+	 * have everything we need to not need monitor interfaces.
+	 */
+	drv->use_monitor = !info.poll_command_supported;
+
+	if (drv->device_ap_sme && drv->use_monitor) {
+		/*
+		 * Non-mac80211 drivers may not support monitor interface.
+		 * Make sure we do not get stuck with incorrect capability here
+		 * by explicitly testing this.
+		 */
+		if (!info.monitor_supported) {
+			wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor "
+				   "with device_ap_sme since no monitor mode "
+				   "support detected");
+			drv->use_monitor = 0;
+		}
+	}
+
+	/*
+	 * If we aren't going to use monitor interfaces, but the
+	 * driver doesn't support data TX status, we won't get TX
+	 * status for EAPOL frames.
+	 */
+	if (!drv->use_monitor && !info.data_tx_status)
+		drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
 
 	return 0;
 }
 
 
-static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
+#ifdef ANDROID
+static int android_genl_ctrl_resolve(struct nl_handle *handle,
+				     const char *name)
+{
+	/*
+	 * Android ICS has very minimal genl_ctrl_resolve() implementation, so
+	 * need to work around that.
+	 */
+	struct nl_cache *cache = NULL;
+	struct genl_family *nl80211 = NULL;
+	int id = -1;
+
+	if (genl_ctrl_alloc_cache(handle, &cache) < 0) {
+		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
+			   "netlink cache");
+		goto fail;
+	}
+
+	nl80211 = genl_ctrl_search_by_name(cache, name);
+	if (nl80211 == NULL)
+		goto fail;
+
+	id = genl_family_get_id(nl80211);
+
+fail:
+	if (nl80211)
+		genl_family_put(nl80211);
+	if (cache)
+		nl_cache_free(cache);
+
+	return id;
+}
+#define genl_ctrl_resolve android_genl_ctrl_resolve
+#endif /* ANDROID */
+
+
+static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
 {
 	int ret;
 
-	/* Initialize generic netlink and nl80211 */
-
-	drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
-	if (drv->nl_cb == NULL) {
+	global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (global->nl_cb == NULL) {
 		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
 			   "callbacks");
-		goto err1;
+		return -1;
 	}
 
-	drv->nl_handle = nl80211_handle_alloc(drv->nl_cb);
-	if (drv->nl_handle == NULL) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
-			   "callbacks");
-		goto err2;
-	}
+	global->nl = nl_create_handle(global->nl_cb, "nl");
+	if (global->nl == NULL)
+		goto err;
 
-	drv->nl_handle_event = nl80211_handle_alloc(drv->nl_cb);
-	if (drv->nl_handle_event == NULL) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
-			   "callbacks (event)");
-		goto err2b;
-	}
-
-	if (genl_connect(drv->nl_handle)) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
-			   "netlink");
-		goto err3;
-	}
-
-	if (genl_connect(drv->nl_handle_event)) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
-			   "netlink (event)");
-		goto err3;
-	}
-
-#ifdef CONFIG_LIBNL20
-	if (genl_ctrl_alloc_cache(drv->nl_handle, &drv->nl_cache) < 0) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
-			   "netlink cache");
-		goto err3;
-	}
-	if (genl_ctrl_alloc_cache(drv->nl_handle_event, &drv->nl_cache_event) <
-	    0) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
-			   "netlink cache (event)");
-		goto err3b;
-	}
-#else /* CONFIG_LIBNL20 */
-	drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle);
-	if (drv->nl_cache == NULL) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
-			   "netlink cache");
-		goto err3;
-	}
-	drv->nl_cache_event = genl_ctrl_alloc_cache(drv->nl_handle_event);
-	if (drv->nl_cache_event == NULL) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
-			   "netlink cache (event)");
-		goto err3b;
-	}
-#endif /* CONFIG_LIBNL20 */
-
-	drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211");
-	if (drv->nl80211 == NULL) {
+	global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
+	if (global->nl80211_id < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: 'nl80211' generic netlink not "
 			   "found");
-		goto err4;
+		goto err;
 	}
 
-	ret = nl_get_multicast_id(drv, "nl80211", "scan");
+	global->nl_event = nl_create_handle(global->nl_cb, "event");
+	if (global->nl_event == NULL)
+		goto err;
+
+	ret = nl_get_multicast_id(global, "nl80211", "scan");
 	if (ret >= 0)
-		ret = nl_socket_add_membership(drv->nl_handle_event, ret);
+		ret = nl_socket_add_membership(global->nl_event, ret);
 	if (ret < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
 			   "membership for scan events: %d (%s)",
 			   ret, strerror(-ret));
-		goto err4;
+		goto err;
 	}
 
-	ret = nl_get_multicast_id(drv, "nl80211", "mlme");
+	ret = nl_get_multicast_id(global, "nl80211", "mlme");
 	if (ret >= 0)
-		ret = nl_socket_add_membership(drv->nl_handle_event, ret);
+		ret = nl_socket_add_membership(global->nl_event, ret);
 	if (ret < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: Could not add multicast "
 			   "membership for mlme events: %d (%s)",
 			   ret, strerror(-ret));
-		goto err4;
+		goto err;
 	}
 
-	ret = nl_get_multicast_id(drv, "nl80211", "regulatory");
+	ret = nl_get_multicast_id(global, "nl80211", "regulatory");
 	if (ret >= 0)
-		ret = nl_socket_add_membership(drv->nl_handle_event, ret);
+		ret = nl_socket_add_membership(global->nl_event, ret);
 	if (ret < 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
 			   "membership for regulatory events: %d (%s)",
@@ -1866,27 +2737,43 @@
 		/* Continue without regulatory events */
 	}
 
-	eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event),
-				 wpa_driver_nl80211_event_receive, drv,
-				 drv->nl_handle_event);
+	nl_cb_set(global->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+		  no_seq_check, NULL);
+	nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
+		  process_global_event, global);
+
+	eloop_register_read_sock(nl_socket_get_fd(global->nl_event),
+				 wpa_driver_nl80211_event_receive,
+				 global->nl_cb, global->nl_event);
 
 	return 0;
 
-err4:
-	nl_cache_free(drv->nl_cache_event);
-err3b:
-	nl_cache_free(drv->nl_cache);
-err3:
-	nl80211_handle_destroy(drv->nl_handle_event);
-err2b:
-	nl80211_handle_destroy(drv->nl_handle);
-err2:
-	nl_cb_put(drv->nl_cb);
-err1:
+err:
+	nl_destroy_handles(&global->nl_event);
+	nl_destroy_handles(&global->nl);
+	nl_cb_put(global->nl_cb);
+	global->nl_cb = NULL;
 	return -1;
 }
 
 
+static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
+{
+	drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (!drv->nl_cb) {
+		wpa_printf(MSG_ERROR, "nl80211: Failed to alloc cb struct");
+		return -1;
+	}
+
+	nl_cb_set(drv->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+		  no_seq_check, NULL);
+	nl_cb_set(drv->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
+		  process_drv_event, drv);
+
+	return 0;
+}
+
+
 static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
 {
 	wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
@@ -1901,7 +2788,8 @@
 {
 	struct wpa_driver_nl80211_data *drv = ctx;
 	wpa_printf(MSG_DEBUG, "nl80211: RFKILL unblocked");
-	if (linux_set_iface_flags(drv->ioctl_sock, drv->first_bss.ifname, 1)) {
+	if (linux_set_iface_flags(drv->global->ioctl_sock,
+				  drv->first_bss.ifname, 1)) {
 		wpa_printf(MSG_DEBUG, "nl80211: Could not set interface UP "
 			   "after rfkill unblock");
 		return;
@@ -1943,6 +2831,90 @@
 }
 
 
+static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
+						      void *eloop_ctx,
+						      void *handle)
+{
+	struct wpa_driver_nl80211_data *drv = eloop_ctx;
+	u8 data[2048];
+	struct msghdr msg;
+	struct iovec entry;
+	struct {
+		struct cmsghdr cm;
+		char control[512];
+	} control;
+	struct cmsghdr *cmsg;
+	int res, found_ee = 0, found_wifi = 0, acked = 0;
+	union wpa_event_data event;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = &entry;
+	msg.msg_iovlen = 1;
+	entry.iov_base = data;
+	entry.iov_len = sizeof(data);
+	msg.msg_control = &control;
+	msg.msg_controllen = sizeof(control);
+
+	res = recvmsg(sock, &msg, MSG_ERRQUEUE);
+	/* if error or not fitting 802.3 header, return */
+	if (res < 14)
+		return;
+
+	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
+	{
+		if (cmsg->cmsg_level == SOL_SOCKET &&
+		    cmsg->cmsg_type == SCM_WIFI_STATUS) {
+			int *ack;
+
+			found_wifi = 1;
+			ack = (void *)CMSG_DATA(cmsg);
+			acked = *ack;
+		}
+
+		if (cmsg->cmsg_level == SOL_PACKET &&
+		    cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
+			struct sock_extended_err *err =
+				(struct sock_extended_err *)CMSG_DATA(cmsg);
+
+			if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
+				found_ee = 1;
+		}
+	}
+
+	if (!found_ee || !found_wifi)
+		return;
+
+	memset(&event, 0, sizeof(event));
+	event.eapol_tx_status.dst = data;
+	event.eapol_tx_status.data = data + 14;
+	event.eapol_tx_status.data_len = res - 14;
+	event.eapol_tx_status.ack = acked;
+	wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
+}
+
+
+static int nl80211_init_bss(struct i802_bss *bss)
+{
+	bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (!bss->nl_cb)
+		return -1;
+
+	nl_cb_set(bss->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+		  no_seq_check, NULL);
+	nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,
+		  process_bss_event, bss);
+
+	return 0;
+}
+
+
+static void nl80211_destroy_bss(struct i802_bss *bss)
+{
+	nl_cb_put(bss->nl_cb);
+	bss->nl_cb = NULL;
+}
+
+
 /**
  * wpa_driver_nl80211_init - Initialize nl80211 driver interface
  * @ctx: context to be used when calling wpa_supplicant functions,
@@ -1955,10 +2927,11 @@
 				      void *global_priv)
 {
 	struct wpa_driver_nl80211_data *drv;
-	struct netlink_config *cfg;
 	struct rfkill_config *rcfg;
 	struct i802_bss *bss;
 
+	if (global_priv == NULL)
+		return NULL;
 	drv = os_zalloc(sizeof(*drv));
 	if (drv == NULL)
 		return NULL;
@@ -1969,33 +2942,19 @@
 	os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
 	drv->monitor_ifidx = -1;
 	drv->monitor_sock = -1;
-	drv->ioctl_sock = -1;
+	drv->eapol_tx_sock = -1;
+	drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 
 	if (wpa_driver_nl80211_init_nl(drv)) {
 		os_free(drv);
 		return NULL;
 	}
 
+	if (nl80211_init_bss(bss))
+		goto failed;
+
 	nl80211_get_phy_name(drv);
 
-	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
-	if (drv->ioctl_sock < 0) {
-		perror("socket(PF_INET,SOCK_DGRAM)");
-		goto failed;
-	}
-
-	cfg = os_zalloc(sizeof(*cfg));
-	if (cfg == NULL)
-		goto failed;
-	cfg->ctx = drv;
-	cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
-	cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
-	drv->netlink = netlink_init(cfg);
-	if (drv->netlink == NULL) {
-		os_free(cfg);
-		goto failed;
-	}
-
 	rcfg = os_zalloc(sizeof(*rcfg));
 	if (rcfg == NULL)
 		goto failed;
@@ -2012,32 +2971,46 @@
 	if (wpa_driver_nl80211_finish_drv_init(drv))
 		goto failed;
 
-	if (drv->global)
+	drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
+	if (drv->eapol_tx_sock < 0)
+		goto failed;
+
+	if (drv->data_tx_status) {
+		int enabled = 1;
+
+		if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
+			       &enabled, sizeof(enabled)) < 0) {
+			wpa_printf(MSG_DEBUG,
+				"nl80211: wifi status sockopt failed\n");
+			drv->data_tx_status = 0;
+			if (!drv->use_monitor)
+				drv->capa.flags &=
+					~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
+		} else {
+			eloop_register_read_sock(drv->eapol_tx_sock,
+				wpa_driver_nl80211_handle_eapol_tx_status,
+				drv, NULL);
+		}
+	}
+
+	if (drv->global) {
 		dl_list_add(&drv->global->interfaces, &drv->list);
+		drv->in_interface_list = 1;
+	}
 
 	return bss;
 
 failed:
-	rfkill_deinit(drv->rfkill);
-	netlink_deinit(drv->netlink);
-	if (drv->ioctl_sock >= 0)
-		close(drv->ioctl_sock);
-
-	genl_family_put(drv->nl80211);
-	nl_cache_free(drv->nl_cache);
-	nl80211_handle_destroy(drv->nl_handle);
-	nl_cb_put(drv->nl_cb);
-	eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event));
-
-	os_free(drv);
+	wpa_driver_nl80211_deinit(bss);
 	return NULL;
 }
 
 
-static int nl80211_register_frame(struct wpa_driver_nl80211_data *drv,
+static int nl80211_register_frame(struct i802_bss *bss,
 				  struct nl_handle *nl_handle,
 				  u16 type, const u8 *match, size_t match_len)
 {
+	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
 	int ret = -1;
 
@@ -2045,14 +3018,18 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_REGISTER_ACTION, 0);
+	wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x nl_handle=%p",
+		   type, nl_handle);
+	wpa_hexdump(MSG_DEBUG, "nl80211: Register frame match",
+		    match, match_len);
 
-	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
 	NLA_PUT_U16(msg, NL80211_ATTR_FRAME_TYPE, type);
 	NLA_PUT(msg, NL80211_ATTR_FRAME_MATCH, match_len, match);
 
-	ret = send_and_recv(drv, nl_handle, msg, NULL, NULL);
+	ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Register frame command "
@@ -2069,58 +3046,213 @@
 }
 
 
-static int nl80211_register_action_frame(struct wpa_driver_nl80211_data *drv,
+static int nl80211_alloc_mgmt_handle(struct i802_bss *bss)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+
+	if (bss->nl_mgmt) {
+		wpa_printf(MSG_DEBUG, "nl80211: Mgmt reporting "
+			   "already on! (nl_mgmt=%p)", bss->nl_mgmt);
+		return -1;
+	}
+
+	bss->nl_mgmt = nl_create_handle(drv->nl_cb, "mgmt");
+	if (bss->nl_mgmt == NULL)
+		return -1;
+
+	eloop_register_read_sock(nl_socket_get_fd(bss->nl_mgmt),
+				 wpa_driver_nl80211_event_receive, bss->nl_cb,
+				 bss->nl_mgmt);
+
+	return 0;
+}
+
+
+static int nl80211_register_action_frame(struct i802_bss *bss,
 					 const u8 *match, size_t match_len)
 {
 	u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4);
-	return nl80211_register_frame(drv, drv->nl_handle_event,
+	return nl80211_register_frame(bss, bss->nl_mgmt,
 				      type, match, match_len);
 }
 
 
-static int nl80211_register_action_frames(struct wpa_driver_nl80211_data *drv)
+static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
 {
-#ifdef CONFIG_P2P
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+
+	if (nl80211_alloc_mgmt_handle(bss))
+		return -1;
+	wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP "
+		   "handle %p", bss->nl_mgmt);
+
+#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
 	/* GAS Initial Request */
-	if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0a", 2) < 0)
+	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
 		return -1;
 	/* GAS Initial Response */
-	if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0b", 2) < 0)
+	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
 		return -1;
 	/* GAS Comeback Request */
-	if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0c", 2) < 0)
+	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
 		return -1;
 	/* GAS Comeback Response */
-	if (nl80211_register_action_frame(drv, (u8 *) "\x04\x0d", 2) < 0)
+	if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
 		return -1;
+#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
+#ifdef CONFIG_P2P
 	/* P2P Public Action */
-	if (nl80211_register_action_frame(drv,
+	if (nl80211_register_action_frame(bss,
 					  (u8 *) "\x04\x09\x50\x6f\x9a\x09",
 					  6) < 0)
 		return -1;
 	/* P2P Action */
-	if (nl80211_register_action_frame(drv,
+	if (nl80211_register_action_frame(bss,
 					  (u8 *) "\x7f\x50\x6f\x9a\x09",
 					  5) < 0)
 		return -1;
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_IEEE80211W
 	/* SA Query Response */
-	if (nl80211_register_action_frame(drv, (u8 *) "\x08\x01", 2) < 0)
+	if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
 		return -1;
 #endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_TDLS
+	if ((drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) {
+		/* TDLS Discovery Response */
+		if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0e", 2) <
+		    0)
+			return -1;
+	}
+#endif /* CONFIG_TDLS */
 
 	/* FT Action frames */
-	if (nl80211_register_action_frame(drv, (u8 *) "\x06", 1) < 0)
+	if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
 		return -1;
 	else
 		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
 			WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
 
+	/* WNM - BSS Transition Management Request */
+	if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
+		return -1;
+
 	return 0;
 }
 
 
+static int nl80211_register_spurious_class3(struct i802_bss *bss)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+	int ret = -1;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_UNEXPECTED_FRAME);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+
+	ret = send_and_recv(drv->global, bss->nl_mgmt, msg, NULL, NULL);
+	msg = NULL;
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 "
+			   "failed: ret=%d (%s)",
+			   ret, strerror(-ret));
+		goto nla_put_failure;
+	}
+	ret = 0;
+nla_put_failure:
+	nlmsg_free(msg);
+	return ret;
+}
+
+
+static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
+{
+	static const int stypes[] = {
+		WLAN_FC_STYPE_AUTH,
+		WLAN_FC_STYPE_ASSOC_REQ,
+		WLAN_FC_STYPE_REASSOC_REQ,
+		WLAN_FC_STYPE_DISASSOC,
+		WLAN_FC_STYPE_DEAUTH,
+		WLAN_FC_STYPE_ACTION,
+		WLAN_FC_STYPE_PROBE_REQ,
+/* Beacon doesn't work as mac80211 doesn't currently allow
+ * it, but it wouldn't really be the right thing anyway as
+ * it isn't per interface ... maybe just dump the scan
+ * results periodically for OLBC?
+ */
+//		WLAN_FC_STYPE_BEACON,
+	};
+	unsigned int i;
+
+	if (nl80211_alloc_mgmt_handle(bss))
+		return -1;
+	wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
+		   "handle %p", bss->nl_mgmt);
+
+	for (i = 0; i < sizeof(stypes) / sizeof(stypes[0]); i++) {
+		if (nl80211_register_frame(bss, bss->nl_mgmt,
+					   (WLAN_FC_TYPE_MGMT << 2) |
+					   (stypes[i] << 4),
+					   NULL, 0) < 0) {
+			goto out_err;
+		}
+	}
+
+	if (nl80211_register_spurious_class3(bss))
+		goto out_err;
+
+	if (nl80211_get_wiphy_data_ap(bss) == NULL)
+		goto out_err;
+
+	return 0;
+
+out_err:
+	eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));
+	nl_destroy_handles(&bss->nl_mgmt);
+	return -1;
+}
+
+
+static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss)
+{
+	if (nl80211_alloc_mgmt_handle(bss))
+		return -1;
+	wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
+		   "handle %p (device SME)", bss->nl_mgmt);
+
+	if (nl80211_register_frame(bss, bss->nl_mgmt,
+				   (WLAN_FC_TYPE_MGMT << 2) |
+				   (WLAN_FC_STYPE_ACTION << 4),
+				   NULL, 0) < 0)
+		goto out_err;
+
+	return 0;
+
+out_err:
+	eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));
+	nl_destroy_handles(&bss->nl_mgmt);
+	return -1;
+}
+
+
+static void nl80211_mgmt_unsubscribe(struct i802_bss *bss, const char *reason)
+{
+	if (bss->nl_mgmt == NULL)
+		return;
+	wpa_printf(MSG_DEBUG, "nl80211: Unsubscribe mgmt frames handle %p "
+		   "(%s)", bss->nl_mgmt, reason);
+	eloop_unregister_read_sock(nl_socket_get_fd(bss->nl_mgmt));
+	nl_destroy_handles(&bss->nl_mgmt);
+
+	nl80211_put_wiphy_data_ap(bss);
+}
+
+
 static void wpa_driver_nl80211_send_rfkill(void *eloop_ctx, void *timeout_ctx)
 {
 	wpa_supplicant_event(timeout_ctx, EVENT_INTERFACE_DISABLED, NULL);
@@ -2137,12 +3269,19 @@
 	drv->first_bss.ifindex = drv->ifindex;
 
 #ifndef HOSTAPD
-	if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA) < 0) {
-		wpa_printf(MSG_DEBUG, "nl80211: Could not configure driver to "
+	/*
+	 * Make sure the interface starts up in station mode unless this is a
+	 * dynamically added interface (e.g., P2P) that was already configured
+	 * with proper iftype.
+	 */
+	if (drv->ifindex != drv->global->if_add_ifindex &&
+	    wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION) < 0) {
+		wpa_printf(MSG_ERROR, "nl80211: Could not configure driver to "
 			   "use managed mode");
+		return -1;
 	}
 
-	if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
+	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
 		if (rfkill_is_blocked(drv->rfkill)) {
 			wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
 				   "interface '%s' due to rfkill",
@@ -2156,26 +3295,17 @@
 		}
 	}
 
-	netlink_send_oper_ifla(drv->netlink, drv->ifindex,
+	netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
 			       1, IF_OPER_DORMANT);
 #endif /* HOSTAPD */
 
 	if (wpa_driver_nl80211_capa(drv))
 		return -1;
 
-	if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, drv->addr))
+	if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+			       bss->addr))
 		return -1;
 
-	if (nl80211_register_action_frames(drv) < 0) {
-		wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
-			   "frame processing - ignore for now");
-		/*
-		 * Older kernel versions did not support this, so ignore the
-		 * error for now. Some functionality may not be available
-		 * because of this.
-		 */
-	}
-
 	if (send_rfkill_event) {
 		eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
 				       drv, drv->ctx);
@@ -2193,12 +3323,12 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_DEL_BEACON, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_BEACON);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 
 	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -2215,17 +3345,22 @@
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 
-	if (drv->nl_handle_preq)
+	if (drv->data_tx_status)
+		eloop_unregister_read_sock(drv->eapol_tx_sock);
+	if (drv->eapol_tx_sock >= 0)
+		close(drv->eapol_tx_sock);
+
+	if (bss->nl_preq)
 		wpa_driver_nl80211_probe_req_report(bss, 0);
 	if (bss->added_if_into_bridge) {
-		if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname)
-		    < 0)
+		if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
+				    bss->ifname) < 0)
 			wpa_printf(MSG_INFO, "nl80211: Failed to remove "
 				   "interface %s from bridge %s: %s",
 				   bss->ifname, bss->brname, strerror(errno));
 	}
 	if (bss->added_bridge) {
-		if (linux_br_del(drv->ioctl_sock, bss->brname) < 0)
+		if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
 			wpa_printf(MSG_INFO, "nl80211: Failed to remove "
 				   "bridge %s: %s",
 				   bss->brname, strerror(errno));
@@ -2233,7 +3368,7 @@
 
 	nl80211_remove_monitor_interface(drv);
 
-	if (drv->nlmode == NL80211_IFTYPE_AP)
+	if (is_ap_interface(drv->nlmode))
 		wpa_driver_nl80211_del_beacon(drv);
 
 #ifdef HOSTAPD
@@ -2254,32 +3389,28 @@
 		os_free(drv->if_indices);
 #endif /* HOSTAPD */
 
-	if (drv->disable_11b_rates)
+	if (drv->disabled_11b_rates)
 		nl80211_disable_11b_rates(drv, drv->ifindex, 0);
 
-	netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
-	netlink_deinit(drv->netlink);
+	netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
+			       IF_OPER_UP);
 	rfkill_deinit(drv->rfkill);
 
 	eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
 
-	(void) linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0);
-	wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_INFRA);
+	(void) linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
+	wpa_driver_nl80211_set_mode(bss, NL80211_IFTYPE_STATION);
+	nl80211_mgmt_unsubscribe(bss, "deinit");
 
-	if (drv->ioctl_sock >= 0)
-		close(drv->ioctl_sock);
-
-	eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event));
-	genl_family_put(drv->nl80211);
-	nl_cache_free(drv->nl_cache);
-	nl_cache_free(drv->nl_cache_event);
-	nl80211_handle_destroy(drv->nl_handle);
-	nl80211_handle_destroy(drv->nl_handle_event);
 	nl_cb_put(drv->nl_cb);
 
+	nl80211_destroy_bss(&drv->first_bss);
+
 	os_free(drv->filter_ssids);
 
-	if (drv->global)
+	os_free(drv->auth_ie);
+
+	if (drv->in_interface_list)
 		dl_list_del(&drv->list);
 
 	os_free(drv);
@@ -2297,10 +3428,10 @@
 static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_driver_nl80211_data *drv = eloop_ctx;
-	if (drv->ap_scan_as_station) {
+	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
 		wpa_driver_nl80211_set_mode(&drv->first_bss,
-					    IEEE80211_MODE_AP);
-		drv->ap_scan_as_station = 0;
+					    drv->ap_scan_as_station);
+		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 	}
 	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
@@ -2319,16 +3450,20 @@
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ret = 0, timeout;
-	struct nl_msg *msg, *ssids, *freqs;
+	struct nl_msg *msg, *ssids, *freqs, *rates;
 	size_t i;
 
+	drv->scan_for_auth = 0;
+
 	msg = nlmsg_alloc();
 	ssids = nlmsg_alloc();
 	freqs = nlmsg_alloc();
-	if (!msg || !ssids || !freqs) {
+	rates = nlmsg_alloc();
+	if (!msg || !ssids || !freqs || !rates) {
 		nlmsg_free(msg);
 		nlmsg_free(ssids);
 		nlmsg_free(freqs);
+		nlmsg_free(rates);
 		return -1;
 	}
 
@@ -2337,8 +3472,7 @@
 	params->filter_ssids = NULL;
 	drv->num_filter_ssids = params->num_filter_ssids;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_TRIGGER_SCAN, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_TRIGGER_SCAN);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 
@@ -2353,8 +3487,8 @@
 		nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
 
 	if (params->extra_ies) {
-		wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan extra IEs",
-				  params->extra_ies, params->extra_ies_len);
+		wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
+			    params->extra_ies, params->extra_ies_len);
 		NLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len,
 			params->extra_ies);
 	}
@@ -2368,29 +3502,42 @@
 		nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
 	}
 
+	if (params->p2p_probe) {
+		/*
+		 * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
+		 * by masking out everything else apart from the OFDM rates 6,
+		 * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
+		 * rates are left enabled.
+		 */
+		NLA_PUT(rates, NL80211_BAND_2GHZ, 8,
+			"\x0c\x12\x18\x24\x30\x48\x60\x6c");
+		nla_put_nested(msg, NL80211_ATTR_SCAN_SUPP_RATES, rates);
+
+		NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
+	}
+
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	msg = NULL;
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d "
 			   "(%s)", ret, strerror(-ret));
 #ifdef HOSTAPD
-		if (drv->nlmode == NL80211_IFTYPE_AP) {
+		if (is_ap_interface(drv->nlmode)) {
 			/*
 			 * mac80211 does not allow scan requests in AP mode, so
 			 * try to do this in station mode.
 			 */
-			if (wpa_driver_nl80211_set_mode(bss,
-							IEEE80211_MODE_INFRA))
+			if (wpa_driver_nl80211_set_mode(
+				    bss, NL80211_IFTYPE_STATION))
 				goto nla_put_failure;
 
 			if (wpa_driver_nl80211_scan(drv, params)) {
-				wpa_driver_nl80211_set_mode(bss,
-							    IEEE80211_MODE_AP);
+				wpa_driver_nl80211_set_mode(bss, drv->nlmode);
 				goto nla_put_failure;
 			}
 
 			/* Restore AP mode when processing scan results */
-			drv->ap_scan_as_station = 1;
+			drv->ap_scan_as_station = drv->nlmode;
 			ret = 0;
 		} else
 			goto nla_put_failure;
@@ -2420,6 +3567,165 @@
 	nlmsg_free(ssids);
 	nlmsg_free(msg);
 	nlmsg_free(freqs);
+	nlmsg_free(rates);
+	return ret;
+}
+
+
+/**
+ * wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
+ * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
+ * @params: Scan parameters
+ * @interval: Interval between scan cycles in milliseconds
+ * Returns: 0 on success, -1 on failure or if not supported
+ */
+static int wpa_driver_nl80211_sched_scan(void *priv,
+					 struct wpa_driver_scan_params *params,
+					 u32 interval)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	int ret = 0;
+	struct nl_msg *msg, *ssids, *freqs, *match_set_ssid, *match_sets;
+	size_t i;
+
+#ifdef ANDROID
+	if (!drv->capa.sched_scan_supported)
+		return android_pno_start(bss, params);
+#endif /* ANDROID */
+
+	msg = nlmsg_alloc();
+	ssids = nlmsg_alloc();
+	freqs = nlmsg_alloc();
+	if (!msg || !ssids || !freqs) {
+		nlmsg_free(msg);
+		nlmsg_free(ssids);
+		nlmsg_free(freqs);
+		return -1;
+	}
+
+	os_free(drv->filter_ssids);
+	drv->filter_ssids = params->filter_ssids;
+	params->filter_ssids = NULL;
+	drv->num_filter_ssids = params->num_filter_ssids;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_START_SCHED_SCAN);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval);
+
+	if (drv->num_filter_ssids &&
+	    (int) drv->num_filter_ssids <= drv->capa.max_match_sets) {
+		match_sets = nlmsg_alloc();
+
+		for (i = 0; i < drv->num_filter_ssids; i++) {
+			wpa_hexdump_ascii(MSG_MSGDUMP,
+					  "nl80211: Sched scan filter SSID",
+					  drv->filter_ssids[i].ssid,
+					  drv->filter_ssids[i].ssid_len);
+
+			match_set_ssid = nlmsg_alloc();
+			nla_put(match_set_ssid,
+				NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
+				drv->filter_ssids[i].ssid_len,
+				drv->filter_ssids[i].ssid);
+
+			nla_put_nested(match_sets, i + 1, match_set_ssid);
+
+			nlmsg_free(match_set_ssid);
+		}
+
+		nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH,
+			       match_sets);
+		nlmsg_free(match_sets);
+	}
+
+	for (i = 0; i < params->num_ssids; i++) {
+		wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Sched scan SSID",
+				  params->ssids[i].ssid,
+				  params->ssids[i].ssid_len);
+		NLA_PUT(ssids, i + 1, params->ssids[i].ssid_len,
+			params->ssids[i].ssid);
+	}
+	if (params->num_ssids)
+		nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
+
+	if (params->extra_ies) {
+		wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Sched scan extra IEs",
+				  params->extra_ies, params->extra_ies_len);
+		NLA_PUT(msg, NL80211_ATTR_IE, params->extra_ies_len,
+			params->extra_ies);
+	}
+
+	if (params->freqs) {
+		for (i = 0; params->freqs[i]; i++) {
+			wpa_printf(MSG_MSGDUMP, "nl80211: Scan frequency %u "
+				   "MHz", params->freqs[i]);
+			NLA_PUT_U32(freqs, i + 1, params->freqs[i]);
+		}
+		nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
+	}
+
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+
+	/* TODO: if we get an error here, we should fall back to normal scan */
+
+	msg = NULL;
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "nl80211: Sched scan start failed: "
+			   "ret=%d (%s)", ret, strerror(-ret));
+		goto nla_put_failure;
+	}
+
+	wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) - "
+		   "scan interval %d msec", ret, interval);
+
+nla_put_failure:
+	nlmsg_free(ssids);
+	nlmsg_free(msg);
+	nlmsg_free(freqs);
+	return ret;
+}
+
+
+/**
+ * wpa_driver_nl80211_stop_sched_scan - Stop a scheduled scan
+ * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
+ * Returns: 0 on success, -1 on failure or if not supported
+ */
+static int wpa_driver_nl80211_stop_sched_scan(void *priv)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	int ret = 0;
+	struct nl_msg *msg;
+
+#ifdef ANDROID
+	if (!drv->capa.sched_scan_supported)
+		return android_pno_stop(bss);
+#endif /* ANDROID */
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_STOP_SCHED_SCAN);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
+	if (ret) {
+		wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop failed: "
+			   "ret=%d (%s)", ret, strerror(-ret));
+		goto nla_put_failure;
+	}
+
+	wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop sent (ret=%d)", ret);
+
+nla_put_failure:
+	nlmsg_free(msg);
 	return ret;
 }
 
@@ -2514,6 +3820,13 @@
 			wpa_printf(MSG_DEBUG, "nl80211: Associated on %u MHz",
 				   _arg->assoc_freq);
 		}
+		if (status == NL80211_BSS_STATUS_ASSOCIATED &&
+		    bss[NL80211_BSS_BSSID]) {
+			os_memcpy(_arg->assoc_bssid,
+				  nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN);
+			wpa_printf(MSG_DEBUG, "nl80211: Associated with "
+				   MACSTR, MAC2STR(_arg->assoc_bssid));
+		}
 	}
 	if (!res)
 		return NL_SKIP;
@@ -2555,7 +3868,7 @@
 		r->flags |= WPA_SCAN_LEVEL_DBM | WPA_SCAN_QUAL_INVALID;
 	} else if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
 		r->level = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
-		r->flags |= WPA_SCAN_LEVEL_INVALID;
+		r->flags |= WPA_SCAN_QUAL_INVALID;
 	} else
 		r->flags |= WPA_SCAN_LEVEL_INVALID | WPA_SCAN_QUAL_INVALID;
 	if (bss[NL80211_BSS_TSF])
@@ -2657,7 +3970,7 @@
 				   "indicates BSS status with " MACSTR
 				   " as authenticated",
 				   MAC2STR(r->bssid));
-			if (drv->nlmode == NL80211_IFTYPE_STATION &&
+			if (is_sta_interface(drv->nlmode) &&
 			    os_memcmp(r->bssid, drv->bssid, ETH_ALEN) != 0 &&
 			    os_memcmp(r->bssid, drv->auth_bssid, ETH_ALEN) !=
 			    0) {
@@ -2675,13 +3988,13 @@
 				   "indicate BSS status with " MACSTR
 				   " as associated",
 				   MAC2STR(r->bssid));
-			if (drv->nlmode == NL80211_IFTYPE_STATION &&
+			if (is_sta_interface(drv->nlmode) &&
 			    !drv->associated) {
 				wpa_printf(MSG_DEBUG, "nl80211: Local state "
 					   "(not associated) does not match "
 					   "with BSS state");
 				clear_state_mismatch(drv, r->bssid);
-			} else if (drv->nlmode == NL80211_IFTYPE_STATION &&
+			} else if (is_sta_interface(drv->nlmode) &&
 				   os_memcmp(drv->bssid, r->bssid, ETH_ALEN) !=
 				   0) {
 				wpa_printf(MSG_DEBUG, "nl80211: Local state "
@@ -2696,20 +4009,6 @@
 }
 
 
-static void wpa_scan_results_free(struct wpa_scan_results *res)
-{
-	size_t i;
-
-	if (res == NULL)
-		return;
-
-	for (i = 0; i < res->num; i++)
-		os_free(res->res[i]);
-	os_free(res->res);
-	os_free(res);
-}
-
-
 static struct wpa_scan_results *
 nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
 {
@@ -2725,8 +4024,7 @@
 	if (!msg)
 		goto nla_put_failure;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, NLM_F_DUMP,
-		    NL80211_CMD_GET_SCAN, 0);
+	nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 
 	arg.drv = drv;
@@ -2734,8 +4032,9 @@
 	ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
 	msg = NULL;
 	if (ret == 0) {
-		wpa_printf(MSG_DEBUG, "Received scan results (%lu BSSes)",
-			   (unsigned long) res->num);
+		wpa_printf(MSG_DEBUG, "nl80211: Received scan results (%lu "
+			   "BSSes)", (unsigned long) res->num);
+		nl80211_get_noise_for_scan_results(drv, res);
 		return res;
 	}
 	wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
@@ -2806,17 +4105,19 @@
 		   "set_tx=%d seq_len=%lu key_len=%lu",
 		   __func__, ifindex, alg, addr, key_idx, set_tx,
 		   (unsigned long) seq_len, (unsigned long) key_len);
+#ifdef CONFIG_TDLS
+	if (key_idx == -1)
+		key_idx = 0;
+#endif /* CONFIG_TDLS */
 
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -ENOMEM;
 
 	if (alg == WPA_ALG_NONE) {
-		genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-			    0, NL80211_CMD_DEL_KEY, 0);
+		nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_KEY);
 	} else {
-		genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-			    0, NL80211_CMD_NEW_KEY, 0);
+		nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);
 		NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);
 		switch (alg) {
 		case WPA_ALG_WEP:
@@ -2889,7 +4190,7 @@
 	 */
 	if (ret || !set_tx || alg == WPA_ALG_NONE)
 		return ret;
-	if (drv->nlmode == NL80211_IFTYPE_AP && addr &&
+	if (is_ap_interface(drv->nlmode) && addr &&
 	    !is_broadcast_ether_addr(addr))
 		return ret;
 
@@ -2897,8 +4198,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_KEY, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_KEY);
 	NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
 	if (alg == WPA_ALG_IGTK)
@@ -2940,6 +4240,7 @@
 	return ret;
 
 nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -3069,7 +4370,7 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, cmd, 0);
+	nl80211_cmd(drv, msg, 0, cmd);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_U16(msg, NL80211_ATTR_REASON_CODE, reason_code);
@@ -3080,8 +4381,9 @@
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	msg = NULL;
 	if (ret) {
-		wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d "
-			   "(%s)", ret, strerror(-ret));
+		wpa_dbg(drv->ctx, MSG_DEBUG,
+			"nl80211: MLME command failed: reason=%u ret=%d (%s)",
+			reason_code, ret, strerror(-ret));
 		goto nla_put_failure;
 	}
 	ret = 0;
@@ -3134,6 +4436,52 @@
 }
 
 
+static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
+				     struct wpa_driver_auth_params *params)
+{
+	int i;
+
+	drv->auth_freq = params->freq;
+	drv->auth_alg = params->auth_alg;
+	drv->auth_wep_tx_keyidx = params->wep_tx_keyidx;
+	drv->auth_local_state_change = params->local_state_change;
+	drv->auth_p2p = params->p2p;
+
+	if (params->bssid)
+		os_memcpy(drv->auth_bssid_, params->bssid, ETH_ALEN);
+	else
+		os_memset(drv->auth_bssid_, 0, ETH_ALEN);
+
+	if (params->ssid) {
+		os_memcpy(drv->auth_ssid, params->ssid, params->ssid_len);
+		drv->auth_ssid_len = params->ssid_len;
+	} else
+		drv->auth_ssid_len = 0;
+
+
+	os_free(drv->auth_ie);
+	drv->auth_ie = NULL;
+	drv->auth_ie_len = 0;
+	if (params->ie) {
+		drv->auth_ie = os_malloc(params->ie_len);
+		if (drv->auth_ie) {
+			os_memcpy(drv->auth_ie, params->ie, params->ie_len);
+			drv->auth_ie_len = params->ie_len;
+		}
+	}
+
+	for (i = 0; i < 4; i++) {
+		if (params->wep_key[i] && params->wep_key_len[i] &&
+		    params->wep_key_len[i] <= 16) {
+			os_memcpy(drv->auth_wep_key[i], params->wep_key[i],
+				  params->wep_key_len[i]);
+			drv->auth_wep_key_len[i] = params->wep_key_len[i];
+		} else
+			drv->auth_wep_key_len[i] = 0;
+	}
+}
+
+
 static int wpa_driver_nl80211_authenticate(
 	void *priv, struct wpa_driver_auth_params *params)
 {
@@ -3142,13 +4490,20 @@
 	int ret = -1, i;
 	struct nl_msg *msg;
 	enum nl80211_auth_type type;
+	enum nl80211_iftype nlmode;
 	int count = 0;
+	int is_retry;
+
+	is_retry = drv->retry_auth;
+	drv->retry_auth = 0;
 
 	drv->associated = 0;
 	os_memset(drv->auth_bssid, 0, ETH_ALEN);
 	/* FIX: IBSS mode */
-	if (drv->nlmode != NL80211_IFTYPE_STATION &&
-	    wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA) < 0)
+	nlmode = params->p2p ?
+		NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
+	if (drv->nlmode != nlmode &&
+	    wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
 		return -1;
 
 retry:
@@ -3159,8 +4514,7 @@
 	wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
 		   drv->ifindex);
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_AUTHENTICATE, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_AUTHENTICATE);
 
 	for (i = 0; i < 4; i++) {
 		if (!params->wep_key[i])
@@ -3218,8 +4572,9 @@
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	msg = NULL;
 	if (ret) {
-		wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d "
-			   "(%s)", ret, strerror(-ret));
+		wpa_dbg(drv->ctx, MSG_DEBUG,
+			"nl80211: MLME command failed (auth): ret=%d (%s)",
+			ret, strerror(-ret));
 		count++;
 		if (ret == -EALREADY && count == 1 && params->bssid &&
 		    !params->local_state_change) {
@@ -3236,6 +4591,49 @@
 			nlmsg_free(msg);
 			goto retry;
 		}
+
+		if (ret == -ENOENT && params->freq && !is_retry) {
+			/*
+			 * cfg80211 has likely expired the BSS entry even
+			 * though it was previously available in our internal
+			 * BSS table. To recover quickly, start a single
+			 * channel scan on the specified channel.
+			 */
+			struct wpa_driver_scan_params scan;
+			int freqs[2];
+
+			os_memset(&scan, 0, sizeof(scan));
+			scan.num_ssids = 1;
+			if (params->ssid) {
+				scan.ssids[0].ssid = params->ssid;
+				scan.ssids[0].ssid_len = params->ssid_len;
+			}
+			freqs[0] = params->freq;
+			freqs[1] = 0;
+			scan.freqs = freqs;
+			wpa_printf(MSG_DEBUG, "nl80211: Trigger single "
+				   "channel scan to refresh cfg80211 BSS "
+				   "entry");
+			ret = wpa_driver_nl80211_scan(bss, &scan);
+			if (ret == 0) {
+				nl80211_copy_auth_params(drv, params);
+				drv->scan_for_auth = 1;
+			}
+		} else if (is_retry) {
+			/*
+			 * Need to indicate this with an event since the return
+			 * value from the retry is not delivered to core code.
+			 */
+			union wpa_event_data event;
+			wpa_printf(MSG_DEBUG, "nl80211: Authentication retry "
+				   "failed");
+			os_memset(&event, 0, sizeof(event));
+			os_memcpy(event.timeout_event.addr, drv->auth_bssid_,
+				  ETH_ALEN);
+			wpa_supplicant_event(drv->ctx, EVENT_AUTH_TIMED_OUT,
+					     &event);
+		}
+
 		goto nla_put_failure;
 	}
 	ret = 0;
@@ -3248,6 +4646,45 @@
 }
 
 
+static int wpa_driver_nl80211_authenticate_retry(
+	struct wpa_driver_nl80211_data *drv)
+{
+	struct wpa_driver_auth_params params;
+	struct i802_bss *bss = &drv->first_bss;
+	int i;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Try to authenticate again");
+
+	os_memset(&params, 0, sizeof(params));
+	params.freq = drv->auth_freq;
+	params.auth_alg = drv->auth_alg;
+	params.wep_tx_keyidx = drv->auth_wep_tx_keyidx;
+	params.local_state_change = drv->auth_local_state_change;
+	params.p2p = drv->auth_p2p;
+
+	if (!is_zero_ether_addr(drv->auth_bssid_))
+		params.bssid = drv->auth_bssid_;
+
+	if (drv->auth_ssid_len) {
+		params.ssid = drv->auth_ssid;
+		params.ssid_len = drv->auth_ssid_len;
+	}
+
+	params.ie = drv->auth_ie;
+	params.ie_len = drv->auth_ie_len;
+
+	for (i = 0; i < 4; i++) {
+		if (drv->auth_wep_key_len[i]) {
+			params.wep_key[i] = drv->auth_wep_key[i];
+			params.wep_key_len[i] = drv->auth_wep_key_len[i];
+		}
+	}
+
+	drv->retry_auth = 1;
+	return wpa_driver_nl80211_authenticate(bss, &params);
+}
+
+
 struct phy_info_arg {
 	u16 *num_modes;
 	struct hostapd_hw_modes *modes;
@@ -3300,6 +4737,7 @@
 
 		mode = &phy_info->modes[*(phy_info->num_modes)];
 		memset(mode, 0, sizeof(*mode));
+		mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN;
 		*(phy_info->num_modes) += 1;
 
 		nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
@@ -3640,8 +5078,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_GET_REG, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
 	return send_and_recv_msgs(drv, msg, nl80211_get_reg, results);
 }
 
@@ -3664,8 +5101,7 @@
 	if (!msg)
 		return NULL;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_GET_WIPHY, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_WIPHY);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 
@@ -3673,14 +5109,16 @@
 		nl80211_set_ht40_flags(drv, &result);
 		return wpa_driver_nl80211_add_11b(result.modes, num_modes);
 	}
+	msg = NULL;
  nla_put_failure:
+	nlmsg_free(msg);
 	return NULL;
 }
 
 
-static int wpa_driver_nl80211_send_frame(struct wpa_driver_nl80211_data *drv,
-					 const void *data, size_t len,
-					 int encrypt)
+static int wpa_driver_nl80211_send_mntr(struct wpa_driver_nl80211_data *drv,
+					const void *data, size_t len,
+					int encrypt, int noack)
 {
 	__u8 rtap_hdr[] = {
 		0x00, 0x00, /* radiotap version */
@@ -3711,6 +5149,7 @@
 		.msg_flags = 0,
 	};
 	int res;
+	u16 txflags = 0;
 
 	if (encrypt)
 		rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
@@ -3721,6 +5160,10 @@
 		return -1;
 	}
 
+	if (noack)
+		txflags |= IEEE80211_RADIOTAP_F_TX_NOACK;
+	*(le16 *) &rtap_hdr[12] = host_to_le16(txflags);
+
 	res = sendmsg(drv->monitor_sock, &msg, 0);
 	if (res < 0) {
 		wpa_printf(MSG_INFO, "nl80211: sendmsg: %s", strerror(errno));
@@ -3730,8 +5173,24 @@
 }
 
 
+static int wpa_driver_nl80211_send_frame(struct i802_bss *bss,
+					 const void *data, size_t len,
+					 int encrypt, int noack)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	u64 cookie;
+
+	if (drv->use_monitor)
+		return wpa_driver_nl80211_send_mntr(drv, data, len,
+						    encrypt, noack);
+
+	return nl80211_send_frame_cmd(bss, bss->freq, 0, data, len,
+				      &cookie, 0, noack, 0);
+}
+
+
 static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data,
-					size_t data_len)
+					size_t data_len, int noack)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -3741,7 +5200,8 @@
 
 	mgmt = (struct ieee80211_mgmt *) data;
 	fc = le_to_host16(mgmt->frame_control);
-	if (drv->nlmode == NL80211_IFTYPE_STATION &&
+
+	if (is_sta_interface(drv->nlmode) &&
 	    WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
 	    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) {
 		/*
@@ -3749,19 +5209,21 @@
 		 * but it works due to the single-threaded nature
 		 * of wpa_supplicant.
 		 */
-		return nl80211_send_frame_cmd(drv, drv->last_mgmt_freq, 0,
-					      data, data_len, NULL);
+		return nl80211_send_frame_cmd(bss, drv->last_mgmt_freq, 0,
+					      data, data_len, NULL, 1, noack,
+					      1);
 	}
-#ifdef ANDROID_BRCM_P2P_PATCH
-	if (drv->nlmode == NL80211_IFTYPE_AP) {
-		wpa_printf(MSG_DEBUG, "%s: Sending frame on ap_oper_freq %d using nl80211_send_frame_cmd", __func__, drv->ap_oper_freq);
-		return nl80211_send_frame_cmd(drv, drv->ap_oper_freq, 0,
-					  data, data_len, &drv->send_action_cookie);
+#ifdef ANDROID_P2P
+	if (is_ap_interface(drv->nlmode)) {
+		return nl80211_send_frame_cmd(bss, bss->freq, 0,
+					  data, data_len, &drv->send_action_cookie, 0, noack, 1);
 	}
 #else
-	if (drv->no_monitor_iface_capab && drv->nlmode == NL80211_IFTYPE_AP ) {
-		return nl80211_send_frame_cmd(drv, drv->ap_oper_freq, 0,
-					      data, data_len, NULL);
+
+	if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
+		return nl80211_send_frame_cmd(bss, bss->freq, 0,
+					      data, data_len, NULL,
+					      0, noack, 0);
 	}
 #endif
 	if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
@@ -3777,15 +5239,59 @@
 		if (auth_alg != WLAN_AUTH_SHARED_KEY || auth_trans != 3)
 			encrypt = 0;
 	}
-	wpa_printf(MSG_DEBUG, "%s: Sending frame using monitor interface/l2 socket", __func__);
-	return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt);
+
+	return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
+					     noack);
 }
 
 
-static int wpa_driver_nl80211_set_beacon(void *priv,
-					 const u8 *head, size_t head_len,
-					 const u8 *tail, size_t tail_len,
-					 int dtim_period, int beacon_int)
+static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
+			   int slot, int ht_opmode, int ap_isolate,
+			   int *basic_rates)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_BSS);
+
+	if (cts >= 0)
+		NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);
+	if (preamble >= 0)
+		NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);
+	if (slot >= 0)
+		NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
+	if (ht_opmode >= 0)
+		NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);
+	if (ap_isolate >= 0)
+		NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, ap_isolate);
+
+	if (basic_rates) {
+		u8 rates[NL80211_MAX_SUPP_RATES];
+		u8 rates_len = 0;
+		int i;
+
+		for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0;
+		     i++)
+			rates[rates_len++] = basic_rates[i] / 5;
+
+		NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
+	}
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
+
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
+ nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+
+static int wpa_driver_nl80211_set_ap(void *priv,
+				     struct wpa_driver_ap_params *params)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -3794,6 +5300,10 @@
 	int ret;
 	int beacon_set;
 	int ifindex = if_nametoindex(bss->ifname);
+	int num_suites;
+	u32 suites[10];
+	u32 ver;
+
 	beacon_set = bss->beacon_set;
 
 	msg = nlmsg_alloc();
@@ -3805,13 +5315,112 @@
 	if (beacon_set)
 		cmd = NL80211_CMD_SET_BEACON;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, cmd, 0);
-	NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, head_len, head);
-	NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, tail_len, tail);
+	nl80211_cmd(drv, msg, 0, cmd);
+	NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, params->head_len, params->head);
+	NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len, params->tail);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
-	NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, beacon_int);
-	NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period);
+	NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, params->beacon_int);
+	NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period);
+	NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
+		params->ssid);
+	if (params->proberesp && params->proberesp_len)
+		NLA_PUT(msg, NL80211_ATTR_PROBE_RESP, params->proberesp_len,
+			params->proberesp);
+	switch (params->hide_ssid) {
+	case NO_SSID_HIDING:
+		NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
+			    NL80211_HIDDEN_SSID_NOT_IN_USE);
+		break;
+	case HIDDEN_SSID_ZERO_LEN:
+		NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
+			    NL80211_HIDDEN_SSID_ZERO_LEN);
+		break;
+	case HIDDEN_SSID_ZERO_CONTENTS:
+		NLA_PUT_U32(msg, NL80211_ATTR_HIDDEN_SSID,
+			    NL80211_HIDDEN_SSID_ZERO_CONTENTS);
+		break;
+	}
+	if (params->privacy)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_PRIVACY);
+	if ((params->auth_algs & (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) ==
+	    (WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED)) {
+		/* Leave out the attribute */
+	} else if (params->auth_algs & WPA_AUTH_ALG_SHARED)
+		NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
+			    NL80211_AUTHTYPE_SHARED_KEY);
+	else
+		NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE,
+			    NL80211_AUTHTYPE_OPEN_SYSTEM);
+
+	ver = 0;
+	if (params->wpa_version & WPA_PROTO_WPA)
+		ver |= NL80211_WPA_VERSION_1;
+	if (params->wpa_version & WPA_PROTO_RSN)
+		ver |= NL80211_WPA_VERSION_2;
+	if (ver)
+		NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
+
+	num_suites = 0;
+	if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X)
+		suites[num_suites++] = WLAN_AKM_SUITE_8021X;
+	if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK)
+		suites[num_suites++] = WLAN_AKM_SUITE_PSK;
+	if (num_suites) {
+		NLA_PUT(msg, NL80211_ATTR_AKM_SUITES,
+			num_suites * sizeof(u32), suites);
+	}
+
+	if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X &&
+	    params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40))
+		NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT);
+
+	num_suites = 0;
+	if (params->pairwise_ciphers & WPA_CIPHER_CCMP)
+		suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
+	if (params->pairwise_ciphers & WPA_CIPHER_TKIP)
+		suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
+	if (params->pairwise_ciphers & WPA_CIPHER_WEP104)
+		suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
+	if (params->pairwise_ciphers & WPA_CIPHER_WEP40)
+		suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
+	if (num_suites) {
+		NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
+			num_suites * sizeof(u32), suites);
+	}
+
+	switch (params->group_cipher) {
+	case WPA_CIPHER_CCMP:
+		NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
+			    WLAN_CIPHER_SUITE_CCMP);
+		break;
+	case WPA_CIPHER_TKIP:
+		NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
+			    WLAN_CIPHER_SUITE_TKIP);
+		break;
+	case WPA_CIPHER_WEP104:
+		NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
+			    WLAN_CIPHER_SUITE_WEP104);
+		break;
+	case WPA_CIPHER_WEP40:
+		NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
+			    WLAN_CIPHER_SUITE_WEP40);
+		break;
+	}
+
+	if (params->beacon_ies) {
+		NLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
+			wpabuf_head(params->beacon_ies));
+	}
+	if (params->proberesp_ies) {
+		NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
+			wpabuf_len(params->proberesp_ies),
+			wpabuf_head(params->proberesp_ies));
+	}
+	if (params->assocresp_ies) {
+		NLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,
+			wpabuf_len(params->assocresp_ies),
+			wpabuf_head(params->assocresp_ies));
+	}
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	if (ret) {
@@ -3819,29 +5428,36 @@
 			   ret, strerror(-ret));
 	} else {
 		bss->beacon_set = 1;
+		nl80211_set_bss(bss, params->cts_protect, params->preamble,
+				params->short_slot_time, params->ht_opmode,
+				params->isolate, params->basic_rates);
 	}
-#if defined(ANDROID_BRCM_P2P_PATCH) && defined(HOSTAPD)
+#if defined(ANDROID_P2P) && defined(HOSTAPD)
 	wpa_driver_nl80211_probe_req_report(priv, 1);
 #endif
 	return ret;
  nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
 
-static int wpa_driver_nl80211_set_freq(struct wpa_driver_nl80211_data *drv,
+static int wpa_driver_nl80211_set_freq(struct i802_bss *bss,
 				       int freq, int ht_enabled,
 				       int sec_channel_offset)
 {
+	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
 	int ret;
 
+	wpa_printf(MSG_DEBUG, "nl80211: Set freq %d (ht_enabled=%d "
+		   "sec_channel_offset=%d)",
+		   freq, ht_enabled, sec_channel_offset);
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_SET_WIPHY, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
@@ -3856,7 +5472,7 @@
 				    NL80211_CHAN_HT40PLUS);
 			break;
 		default:
-#ifndef ANDROID_BRCM_P2P_PATCH
+#ifndef ANDROID_P2P
 /* Should be change to HT20 as a default value because P2P firmware does not support 11n for BCM4329 */
 			NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
 				    NL80211_CHAN_HT20);
@@ -3869,50 +5485,102 @@
 	}
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
-	if (ret == 0)
+	msg = NULL;
+	if (ret == 0) {
+		bss->freq = freq;
 		return 0;
+	}
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
 		   "%d (%s)", freq, ret, strerror(-ret));
 nla_put_failure:
+	nlmsg_free(msg);
 	return -1;
 }
 
 
+static u32 sta_flags_nl80211(int flags)
+{
+	u32 f = 0;
+
+	if (flags & WPA_STA_AUTHORIZED)
+		f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+	if (flags & WPA_STA_WMM)
+		f |= BIT(NL80211_STA_FLAG_WME);
+	if (flags & WPA_STA_SHORT_PREAMBLE)
+		f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
+	if (flags & WPA_STA_MFP)
+		f |= BIT(NL80211_STA_FLAG_MFP);
+	if (flags & WPA_STA_TDLS_PEER)
+		f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+
+	return f;
+}
+
+
 static int wpa_driver_nl80211_sta_add(void *priv,
 				      struct hostapd_sta_add_params *params)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl_msg *msg;
+	struct nl_msg *msg, *wme = NULL;
+	struct nl80211_sta_flag_update upd;
 	int ret = -ENOBUFS;
 
+	if ((params->flags & WPA_STA_TDLS_PEER) &&
+	    !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
+		return -EOPNOTSUPP;
+
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_NEW_STATION, 0);
+	nl80211_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION :
+		    NL80211_CMD_NEW_STATION);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
 	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);
-	NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
 	NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,
 		params->supp_rates);
-	NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
-		    params->listen_interval);
+	if (!params->set) {
+		NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
+		NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
+			    params->listen_interval);
+	}
 	if (params->ht_capabilities) {
 		NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,
 			sizeof(*params->ht_capabilities),
 			params->ht_capabilities);
 	}
 
+	os_memset(&upd, 0, sizeof(upd));
+	upd.mask = sta_flags_nl80211(params->flags);
+	upd.set = upd.mask;
+	NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
+
+	if (params->flags & WPA_STA_WMM) {
+		wme = nlmsg_alloc();
+		if (!wme)
+			goto nla_put_failure;
+
+		NLA_PUT_U8(wme, NL80211_STA_WME_UAPSD_QUEUES,
+				params->qosinfo & WMM_QOSINFO_STA_AC_MASK);
+		NLA_PUT_U8(wme, NL80211_STA_WME_MAX_SP,
+				(params->qosinfo > WMM_QOSINFO_STA_SP_SHIFT) &
+				WMM_QOSINFO_STA_SP_MASK);
+		nla_put_nested(msg, NL80211_ATTR_STA_WME, wme);
+	}
+
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
 	if (ret)
-		wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_NEW_STATION "
-			   "result: %d (%s)", ret, strerror(-ret));
+		wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
+			   "result: %d (%s)", params->set ? "SET" : "NEW", ret,
+			   strerror(-ret));
 	if (ret == -EEXIST)
 		ret = 0;
  nla_put_failure:
+	nlmsg_free(wme);
+	nlmsg_free(msg);
 	return ret;
 }
 
@@ -3928,8 +5596,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_DEL_STATION, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 		    if_nametoindex(bss->ifname));
@@ -3940,6 +5607,7 @@
 		return 0;
 	return ret;
  nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -3951,26 +5619,46 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: Remove interface ifindex=%d", ifidx);
 
-#ifdef HOSTAPD
 	/* stop listening for EAPOL on this interface */
 	del_ifidx(drv, ifidx);
-#endif /* HOSTAPD */
 
 	msg = nlmsg_alloc();
 	if (!msg)
 		goto nla_put_failure;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_DEL_INTERFACE, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_INTERFACE);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
 
 	if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
 		return;
+	msg = NULL;
  nla_put_failure:
+	nlmsg_free(msg);
 	wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx);
 }
 
 
+static const char * nl80211_iftype_str(enum nl80211_iftype mode)
+{
+	switch (mode) {
+	case NL80211_IFTYPE_ADHOC:
+		return "ADHOC";
+	case NL80211_IFTYPE_STATION:
+		return "STATION";
+	case NL80211_IFTYPE_AP:
+		return "AP";
+	case NL80211_IFTYPE_MONITOR:
+		return "MONITOR";
+	case NL80211_IFTYPE_P2P_CLIENT:
+		return "P2P_CLIENT";
+	case NL80211_IFTYPE_P2P_GO:
+		return "P2P_GO";
+	default:
+		return "unknown";
+	}
+}
+
+
 static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
 				     const char *ifname,
 				     enum nl80211_iftype iftype,
@@ -3980,12 +5668,14 @@
 	int ifidx;
 	int ret = -ENOBUFS;
 
+	wpa_printf(MSG_DEBUG, "nl80211: Create interface iftype %d (%s)",
+		   iftype, nl80211_iftype_str(iftype));
+
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_NEW_INTERFACE, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_INTERFACE);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
@@ -4010,8 +5700,10 @@
 	}
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
 	if (ret) {
  nla_put_failure:
+		nlmsg_free(msg);
 		wpa_printf(MSG_ERROR, "Failed to create interface %s: %d (%s)",
 			   ifname, ret, strerror(-ret));
 		return ret;
@@ -4024,13 +5716,11 @@
 	if (ifidx <= 0)
 		return -1;
 
-#ifdef HOSTAPD
 	/* start listening for EAPOL on this interface */
 	add_ifidx(drv, ifidx);
-#endif /* HOSTAPD */
 
 	if (addr && iftype != NL80211_IFTYPE_MONITOR &&
-	    linux_set_ifhwaddr(drv->ioctl_sock, ifname, addr)) {
+	    linux_set_ifhwaddr(drv->global->ioctl_sock, ifname, addr)) {
 		nl80211_remove_iface(drv, ifidx);
 		return -1;
 	}
@@ -4047,7 +5737,7 @@
 
 	ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds);
 
-	/* if error occured and interface exists already */
+	/* if error occurred and interface exists already */
 	if (ret == -ENFILE && if_nametoindex(ifname)) {
 		wpa_printf(MSG_INFO, "Try to remove and re-create %s", ifname);
 
@@ -4059,7 +5749,7 @@
 						wds);
 	}
 
-	if (ret >= 0 && drv->disable_11b_rates)
+	if (ret >= 0 && is_p2p_interface(iftype))
 		nl80211_disable_11b_rates(drv, ret, 1);
 
 	return ret;
@@ -4089,10 +5779,20 @@
 static void from_unknown_sta(struct wpa_driver_nl80211_data *drv,
 			     u8 *buf, size_t len)
 {
+	struct ieee80211_hdr *hdr = (void *)buf;
+	u16 fc;
 	union wpa_event_data event;
+
+	if (len < sizeof(*hdr))
+		return;
+
+	fc = le_to_host16(hdr->frame_control);
+
 	os_memset(&event, 0, sizeof(event));
-	event.rx_from_unknown.frame = buf;
-	event.rx_from_unknown.len = len;
+	event.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);
+	event.rx_from_unknown.addr = hdr->addr2;
+	event.rx_from_unknown.wds = (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) ==
+		(WLAN_FC_FROMDS | WLAN_FC_TODS);
 	wpa_supplicant_event(drv->ctx, EVENT_RX_FROM_UNKNOWN, &event);
 }
 
@@ -4350,6 +6050,10 @@
 static void nl80211_remove_monitor_interface(
 	struct wpa_driver_nl80211_data *drv)
 {
+	drv->monitor_refcount--;
+	if (drv->monitor_refcount > 0)
+		return;
+
 	if (drv->monitor_ifidx >= 0) {
 		nl80211_remove_iface(drv, drv->monitor_ifidx);
 		drv->monitor_ifidx = -1;
@@ -4369,11 +6073,25 @@
 	struct sockaddr_ll ll;
 	int optval;
 	socklen_t optlen;
-#ifdef ANDROID_BRCM_P2P_PATCH
-	snprintf(buf, IFNAMSIZ, "%s%s", WPA_MONITOR_IFNAME_PREFIX, drv->first_bss.ifname);
-#else
-	snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss.ifname);
-#endif
+
+	if (drv->monitor_ifidx >= 0) {
+		drv->monitor_refcount++;
+		return 0;
+	}
+
+	if (os_strncmp(drv->first_bss.ifname, "p2p-", 4) == 0) {
+		/*
+		 * P2P interface name is of the format p2p-%s-%d. For monitor
+		 * interface name corresponding to P2P GO, replace "p2p-" with
+		 * "mon-" to retain the same interface name length and to
+		 * indicate that it is a monitor interface.
+		 */
+		snprintf(buf, IFNAMSIZ, "mon-%s", drv->first_bss.ifname + 4);
+	} else {
+		/* Non-P2P interface with AP functionality. */
+		snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss.ifname);
+	}
+
 	buf[IFNAMSIZ - 1] = '\0';
 
 	drv->monitor_ifidx =
@@ -4381,15 +6099,21 @@
 				     0);
 
 	if (drv->monitor_ifidx == -EOPNOTSUPP) {
+		/*
+		 * This is backward compatibility for a few versions of
+		 * the kernel only that didn't advertise the right
+		 * attributes for the only driver that then supported
+		 * AP mode w/o monitor -- ath6kl.
+		 */
 		wpa_printf(MSG_DEBUG, "nl80211: Driver does not support "
 			   "monitor interface type - try to run without it");
-		drv->no_monitor_iface_capab = 1;
+		drv->device_ap_sme = 1;
 	}
 
 	if (drv->monitor_ifidx < 0)
 		return -1;
 
-	if (linux_set_iface_flags(drv->ioctl_sock, buf, 1))
+	if (linux_set_iface_flags(drv->global->ioctl_sock, buf, 1))
 		goto error;
 
 	memset(&ll, 0, sizeof(ll));
@@ -4433,6 +6157,98 @@
 }
 
 
+static int nl80211_setup_ap(struct i802_bss *bss)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Setup AP - device_ap_sme=%d "
+		   "use_monitor=%d", drv->device_ap_sme, drv->use_monitor);
+
+	/*
+	 * Disable Probe Request reporting unless we need it in this way for
+	 * devices that include the AP SME, in the other case (unless using
+	 * monitor iface) we'll get it through the nl_mgmt socket instead.
+	 */
+	if (!drv->device_ap_sme)
+		wpa_driver_nl80211_probe_req_report(bss, 0);
+
+	if (!drv->device_ap_sme && !drv->use_monitor)
+		if (nl80211_mgmt_subscribe_ap(bss))
+			return -1;
+
+	if (drv->device_ap_sme && !drv->use_monitor)
+		if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
+			return -1;
+
+	if (!drv->device_ap_sme && drv->use_monitor &&
+	    nl80211_create_monitor_interface(drv) &&
+	    !drv->device_ap_sme)
+		return -1;
+
+	if (drv->device_ap_sme &&
+	    wpa_driver_nl80211_probe_req_report(bss, 1) < 0) {
+		wpa_printf(MSG_DEBUG, "nl80211: Failed to enable "
+			   "Probe Request frame reporting in AP mode");
+		/* Try to survive without this */
+	}
+
+#ifdef ANDROID_P2P
+	/* For AP mode, enable probe req report even if device_ap_sme
+	 * is not enabled
+	 */
+	wpa_printf(MSG_DEBUG, "nl80211: Enabling probe req report");
+	wpa_driver_nl80211_probe_req_report(bss, 1);
+#endif
+
+	return 0;
+}
+
+
+static void nl80211_teardown_ap(struct i802_bss *bss)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+
+	if (drv->device_ap_sme) {
+		wpa_driver_nl80211_probe_req_report(bss, 0);
+		if (!drv->use_monitor)
+			nl80211_mgmt_unsubscribe(bss, "AP teardown (dev SME)");
+	} else if (drv->use_monitor)
+		nl80211_remove_monitor_interface(drv);
+	else
+		nl80211_mgmt_unsubscribe(bss, "AP teardown");
+
+	bss->beacon_set = 0;
+}
+
+
+static int nl80211_send_eapol_data(struct i802_bss *bss,
+				   const u8 *addr, const u8 *data,
+				   size_t data_len)
+{
+	struct sockaddr_ll ll;
+	int ret;
+
+	if (bss->drv->eapol_tx_sock < 0) {
+		wpa_printf(MSG_DEBUG, "nl80211: No socket to send EAPOL");
+		return -1;
+	}
+
+	os_memset(&ll, 0, sizeof(ll));
+	ll.sll_family = AF_PACKET;
+	ll.sll_ifindex = bss->ifindex;
+	ll.sll_protocol = htons(ETH_P_PAE);
+	ll.sll_halen = ETH_ALEN;
+	os_memcpy(ll.sll_addr, addr, ETH_ALEN);
+	ret = sendto(bss->drv->eapol_tx_sock, data, data_len, 0,
+		     (struct sockaddr *) &ll, sizeof(ll));
+	if (ret < 0)
+		wpa_printf(MSG_ERROR, "nl80211: EAPOL TX: %s",
+			   strerror(errno));
+
+	return ret;
+}
+
+
 static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 
 static int wpa_driver_nl80211_hapd_send_eapol(
@@ -4447,6 +6263,9 @@
 	int res;
 	int qos = flags & WPA_STA_WMM;
 
+	if (drv->device_ap_sme || !drv->use_monitor)
+		return nl80211_send_eapol_data(bss, addr, data, data_len);
+
 	len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
 		data_len;
 	hdr = os_zalloc(len);
@@ -4484,7 +6303,7 @@
 	pos += 2;
 	memcpy(pos, data, data_len);
 
-	res = wpa_driver_nl80211_send_frame(drv, (u8 *) hdr, len, encrypt);
+	res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0);
 	if (res < 0) {
 		wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
 			   "failed: %d (%s)",
@@ -4496,23 +6315,6 @@
 }
 
 
-static u32 sta_flags_nl80211(int flags)
-{
-	u32 f = 0;
-
-	if (flags & WPA_STA_AUTHORIZED)
-		f |= BIT(NL80211_STA_FLAG_AUTHORIZED);
-	if (flags & WPA_STA_WMM)
-		f |= BIT(NL80211_STA_FLAG_WME);
-	if (flags & WPA_STA_SHORT_PREAMBLE)
-		f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
-	if (flags & WPA_STA_MFP)
-		f |= BIT(NL80211_STA_FLAG_MFP);
-
-	return f;
-}
-
-
 static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
 					    int total_flags,
 					    int flags_or, int flags_and)
@@ -4532,8 +6334,7 @@
 		return -ENOMEM;
 	}
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_STATION, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 		    if_nametoindex(bss->ifname));
@@ -4555,6 +6356,9 @@
 	if (total_flags & WPA_STA_MFP)
 		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP);
 
+	if (total_flags & WPA_STA_TDLS_PEER)
+		NLA_PUT_FLAG(flags, NL80211_STA_FLAG_TDLS_PEER);
+
 	if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
 		goto nla_put_failure;
 
@@ -4567,6 +6371,7 @@
 
 	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
+	nlmsg_free(msg);
 	nlmsg_free(flags);
 	return -ENOBUFS;
 }
@@ -4575,20 +6380,21 @@
 static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
 				 struct wpa_driver_associate_params *params)
 {
-	if (params->p2p)
+	enum nl80211_iftype nlmode;
+
+	if (params->p2p) {
 		wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
 			   "group (GO)");
-	if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode) ||
-	    wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) {
+		nlmode = NL80211_IFTYPE_P2P_GO;
+	} else
+		nlmode = NL80211_IFTYPE_AP;
+
+	if (wpa_driver_nl80211_set_mode(&drv->first_bss, nlmode) ||
+	    wpa_driver_nl80211_set_freq(&drv->first_bss, params->freq, 0, 0)) {
 		nl80211_remove_monitor_interface(drv);
 		return -1;
 	}
 
-	/* TODO: setup monitor interface (and add code somewhere to remove this
-	 * when AP mode is stopped; associate with mode != 2 or drv_deinit) */
-	wpa_printf(MSG_DEBUG, "nl80211: Update ap_oper_freq with params->freq %d", params->freq);
-	drv->ap_oper_freq = params->freq;
-
 	return 0;
 }
 
@@ -4602,8 +6408,7 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_LEAVE_IBSS, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_LEAVE_IBSS);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	msg = NULL;
@@ -4631,7 +6436,8 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
 
-	if (wpa_driver_nl80211_set_mode(&drv->first_bss, params->mode)) {
+	if (wpa_driver_nl80211_set_mode(&drv->first_bss,
+					NL80211_IFTYPE_ADHOC)) {
 		wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
 			   "IBSS mode");
 		return -1;
@@ -4642,8 +6448,7 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_JOIN_IBSS, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_JOIN_IBSS);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 
 	if (params->ssid == NULL || params->ssid_len > sizeof(drv->ssid))
@@ -4696,6 +6501,55 @@
 }
 
 
+static unsigned int nl80211_get_assoc_bssid(struct wpa_driver_nl80211_data *drv,
+					    u8 *bssid)
+{
+	struct nl_msg *msg;
+	int ret;
+	struct nl80211_bss_info_arg arg;
+
+	os_memset(&arg, 0, sizeof(arg));
+	msg = nlmsg_alloc();
+	if (!msg)
+		goto nla_put_failure;
+
+	nl80211_cmd(drv, msg, NLM_F_DUMP, NL80211_CMD_GET_SCAN);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+	arg.drv = drv;
+	ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg);
+	msg = NULL;
+	if (ret == 0) {
+		if (is_zero_ether_addr(arg.assoc_bssid))
+			return -ENOTCONN;
+		os_memcpy(bssid, arg.assoc_bssid, ETH_ALEN);
+		return 0;
+	}
+	wpa_printf(MSG_DEBUG, "nl80211: Scan result fetch failed: ret=%d "
+		   "(%s)", ret, strerror(-ret));
+nla_put_failure:
+	nlmsg_free(msg);
+	return drv->assoc_freq;
+}
+
+
+static int nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
+			      const u8 *bssid)
+{
+	u8 addr[ETH_ALEN];
+
+	if (bssid == NULL) {
+		int res = nl80211_get_assoc_bssid(drv, addr);
+		if (res)
+			return res;
+		bssid = addr;
+	}
+
+	return wpa_driver_nl80211_disconnect(drv, bssid,
+					     WLAN_REASON_PREV_AUTH_NOT_VALID);
+}
+
+
 static int wpa_driver_nl80211_connect(
 	struct wpa_driver_nl80211_data *drv,
 	struct wpa_driver_associate_params *params)
@@ -4710,8 +6564,7 @@
 		return -1;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_CONNECT, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_CONNECT);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	if (params->bssid) {
@@ -4766,15 +6619,15 @@
 	NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
 
 skip_auth_type:
-	if (params->wpa_ie && params->wpa_ie_len) {
-		enum nl80211_wpa_versions ver;
+	if (params->wpa_proto) {
+		enum nl80211_wpa_versions ver = 0;
 
-		if (params->wpa_ie[0] == WLAN_EID_RSN)
-			ver = NL80211_WPA_VERSION_2;
-		else
-			ver = NL80211_WPA_VERSION_1;
+		if (params->wpa_proto & WPA_PROTO_WPA)
+			ver |= NL80211_WPA_VERSION_1;
+		if (params->wpa_proto & WPA_PROTO_RSN)
+			ver |= NL80211_WPA_VERSION_2;
 
-		wpa_printf(MSG_DEBUG, "  * WPA Version %d", ver);
+		wpa_printf(MSG_DEBUG, "  * WPA Versions 0x%x", ver);
 		NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
 	}
 
@@ -4845,6 +6698,14 @@
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d "
 			   "(%s)", ret, strerror(-ret));
+		/*
+		 * cfg80211 does not currently accept new connection if we are
+		 * already connected. As a workaround, force disconnection and
+		 * try again once the driver indicates it completed
+		 * disconnection.
+		 */
+		if (ret == -EALREADY)
+			nl80211_disconnect(drv, params->bssid);
 		goto nla_put_failure;
 	}
 	ret = 0;
@@ -4872,7 +6733,10 @@
 		return wpa_driver_nl80211_ibss(drv, params);
 
 	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
-		if (wpa_driver_nl80211_set_mode(priv, params->mode) < 0)
+		enum nl80211_iftype nlmode = params->p2p ?
+			NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
+
+		if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
 			return -1;
 		return wpa_driver_nl80211_connect(drv, params);
 	}
@@ -4885,8 +6749,7 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: Associate (ifindex=%d)",
 		   drv->ifindex);
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_ASSOCIATE, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	if (params->bssid) {
@@ -4979,8 +6842,9 @@
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	msg = NULL;
 	if (ret) {
-		wpa_printf(MSG_DEBUG, "nl80211: MLME command failed: ret=%d "
-			   "(%s)", ret, strerror(-ret));
+		wpa_dbg(drv->ctx, MSG_DEBUG,
+			"nl80211: MLME command failed (assoc): ret=%d (%s)",
+			ret, strerror(-ret));
 		nl80211_dump_scan(drv);
 		goto nla_put_failure;
 	}
@@ -4995,58 +6859,53 @@
 
 
 static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv,
-			    int ifindex, int mode)
+			    int ifindex, enum nl80211_iftype mode)
 {
 	struct nl_msg *msg;
 	int ret = -ENOBUFS;
 
+	wpa_printf(MSG_DEBUG, "nl80211: Set mode ifindex %d iftype %d (%s)",
+		   ifindex, mode, nl80211_iftype_str(mode));
+
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_INTERFACE, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_INTERFACE);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, mode);
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
 	if (!ret)
 		return 0;
 nla_put_failure:
+	nlmsg_free(msg);
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface %d to mode %d:"
 		   " %d (%s)", ifindex, mode, ret, strerror(-ret));
 	return ret;
 }
 
 
-static int wpa_driver_nl80211_set_mode(void *priv, int mode)
+static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
+				       enum nl80211_iftype nlmode)
 {
-	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ret = -1;
-	int nlmode;
 	int i;
+	int was_ap = is_ap_interface(drv->nlmode);
+	int res;
 
-	switch (mode) {
-	case 0:
-		nlmode = NL80211_IFTYPE_STATION;
-		break;
-	case 1:
-		nlmode = NL80211_IFTYPE_ADHOC;
-		break;
-	case 2:
-		nlmode = NL80211_IFTYPE_AP;
-		break;
-	default:
-		return -1;
-	}
-
-	if (nl80211_set_mode(drv, drv->ifindex, nlmode) == 0) {
+	res = nl80211_set_mode(drv, drv->ifindex, nlmode);
+	if (res == 0) {
 		drv->nlmode = nlmode;
 		ret = 0;
 		goto done;
 	}
 
+	if (res == -ENODEV)
+		return -1;
+
 	if (nlmode == drv->nlmode) {
 		wpa_printf(MSG_DEBUG, "nl80211: Interface already in "
 			   "requested mode - ignore error");
@@ -5061,15 +6920,21 @@
 	wpa_printf(MSG_DEBUG, "nl80211: Try mode change after setting "
 		   "interface down");
 	for (i = 0; i < 10; i++) {
-		if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0) ==
-		    0) {
+		res = linux_set_iface_flags(drv->global->ioctl_sock,
+					    bss->ifname, 0);
+		if (res == -EACCES || res == -ENODEV)
+			break;
+		if (res == 0) {
 			/* Try to set the mode again while the interface is
 			 * down */
 			ret = nl80211_set_mode(drv, drv->ifindex, nlmode);
-			if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname,
-						  1))
+			if (ret == -EACCES)
+				break;
+			res = linux_set_iface_flags(drv->global->ioctl_sock,
+						    bss->ifname, 1);
+			if (res && !ret)
 				ret = -1;
-			if (!ret)
+			else if (ret != -EBUSY)
 				break;
 		} else
 			wpa_printf(MSG_DEBUG, "nl80211: Failed to set "
@@ -5081,26 +6946,34 @@
 		wpa_printf(MSG_DEBUG, "nl80211: Mode change succeeded while "
 			   "interface is down");
 		drv->nlmode = nlmode;
+		drv->ignore_if_down_event = 1;
 	}
 
 done:
-	if (!ret && nlmode == NL80211_IFTYPE_AP) {
-		/* Setup additional AP mode functionality if needed */
-		if (!drv->no_monitor_iface_capab && drv->monitor_ifidx < 0 &&
-		    nl80211_create_monitor_interface(drv) &&
-		    !drv->no_monitor_iface_capab)
-			return -1;
-	} else if (!ret && nlmode != NL80211_IFTYPE_AP) {
-		/* Remove additional AP mode functionality */
-		nl80211_remove_monitor_interface(drv);
-		bss->beacon_set = 0;
-	}
-
-	if (ret)
+	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
 			   "from %d failed", nlmode, drv->nlmode);
+		return ret;
+	}
 
-	return ret;
+	if (is_ap_interface(nlmode)) {
+		nl80211_mgmt_unsubscribe(bss, "start AP");
+		/* Setup additional AP mode functionality if needed */
+		if (nl80211_setup_ap(bss))
+			return -1;
+	} else if (was_ap) {
+		/* Remove additional AP mode functionality */
+		nl80211_teardown_ap(bss);
+	} else {
+		nl80211_mgmt_unsubscribe(bss, "mode change");
+	}
+
+	if (!is_ap_interface(nlmode) &&
+	    nl80211_mgmt_subscribe_non_ap(bss) < 0)
+		wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "
+			   "frame processing - ignore for now");
+
+	return 0;
 }
 
 
@@ -5124,7 +6997,7 @@
 	wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
 		   __func__, drv->operstate, state, state ? "UP" : "DORMANT");
 	drv->operstate = state;
-	return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
+	return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
 				      state ? IF_OPER_UP : IF_OPER_DORMANT);
 }
 
@@ -5140,8 +7013,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_STATION, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 		    if_nametoindex(bss->ifname));
@@ -5155,6 +7027,7 @@
 
 	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -5163,8 +7036,7 @@
 static int i802_set_freq(void *priv, struct hostapd_freq_params *freq)
 {
 	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	return wpa_driver_nl80211_set_freq(drv, freq->freq, freq->ht_enabled,
+	return wpa_driver_nl80211_set_freq(bss, freq->freq, freq->ht_enabled,
 					   freq->sec_channel_offset);
 }
 
@@ -5211,8 +7083,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_GET_KEY, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_KEY);
 
 	if (addr)
 		NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
@@ -5223,36 +7094,7 @@
 
 	return send_and_recv_msgs(drv, msg, get_key_handler, seq);
  nla_put_failure:
-	return -ENOBUFS;
-}
-
-
-static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates,
-			      int mode)
-{
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl_msg *msg;
-	u8 rates[NL80211_MAX_SUPP_RATES];
-	u8 rates_len = 0;
-	int i;
-
-	msg = nlmsg_alloc();
-	if (!msg)
-		return -ENOMEM;
-
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_SET_BSS, 0);
-
-	for (i = 0; i < NL80211_MAX_SUPP_RATES && basic_rates[i] >= 0; i++)
-		rates[rates_len++] = basic_rates[i] / 5;
-
-	NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, rates_len, rates);
-
-	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
-
-	return send_and_recv_msgs(drv, msg, NULL, NULL);
- nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -5274,15 +7116,16 @@
 	else
 		val = rts;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_WIPHY, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, val);
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
 	if (!ret)
 		return 0;
 nla_put_failure:
+	nlmsg_free(msg);
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: "
 		   "%d (%s)", rts, ret, strerror(-ret));
 	return ret;
@@ -5306,15 +7149,16 @@
 	else
 		val = frag;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_WIPHY, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, val);
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
 	if (!ret)
 		return 0;
 nla_put_failure:
+	nlmsg_free(msg);
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold "
 		   "%d: %d (%s)", frag, ret, strerror(-ret));
 	return ret;
@@ -5326,13 +7170,13 @@
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
+	int res;
 
 	msg = nlmsg_alloc();
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_DEL_STATION, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_DEL_STATION);
 
 	/*
 	 * XXX: FIX! this needs to flush all VLANs too
@@ -5340,8 +7184,14 @@
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 		    if_nametoindex(bss->ifname));
 
-	return send_and_recv_msgs(drv, msg, NULL, NULL);
+	res = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (res) {
+		wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d "
+			   "(%s)", res, strerror(-res));
+	}
+	return res;
  nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -5409,14 +7259,14 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_GET_STATION, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_STATION);
 
 	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
 
 	return send_and_recv_msgs(drv, msg, get_sta_handler, data);
  nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -5433,8 +7283,7 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_WIPHY, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_WIPHY);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
 
@@ -5474,59 +7323,13 @@
 
 	if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
 		return 0;
+	msg = NULL;
  nla_put_failure:
+	nlmsg_free(msg);
 	return -1;
 }
 
 
-static int i802_set_bss(void *priv, int cts, int preamble, int slot,
-			int ht_opmode)
-{
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl_msg *msg;
-
-	msg = nlmsg_alloc();
-	if (!msg)
-		return -ENOMEM;
-
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_SET_BSS, 0);
-
-	if (cts >= 0)
-		NLA_PUT_U8(msg, NL80211_ATTR_BSS_CTS_PROT, cts);
-	if (preamble >= 0)
-		NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_PREAMBLE, preamble);
-	if (slot >= 0)
-		NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
-	if (ht_opmode >= 0)
-		NLA_PUT_U16(msg, NL80211_ATTR_BSS_HT_OPMODE, ht_opmode);
-	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
-
-	return send_and_recv_msgs(drv, msg, NULL, NULL);
- nla_put_failure:
-	return -ENOBUFS;
-}
-
-
-static int i802_set_cts_protect(void *priv, int value)
-{
-	return i802_set_bss(priv, value, -1, -1, -1);
-}
-
-
-static int i802_set_preamble(void *priv, int value)
-{
-	return i802_set_bss(priv, -1, value, -1, -1);
-}
-
-
-static int i802_set_short_slot_time(void *priv, int value)
-{
-	return i802_set_bss(priv, -1, -1, value, -1);
-}
-
-
 static int i802_set_sta_vlan(void *priv, const u8 *addr,
 			     const char *ifname, int vlan_id)
 {
@@ -5539,8 +7342,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_STATION, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_STATION);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 		    if_nametoindex(bss->ifname));
@@ -5549,6 +7351,7 @@
 		    if_nametoindex(ifname));
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
 	if (ret < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr="
 			   MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)",
@@ -5556,23 +7359,11 @@
 			   strerror(-ret));
 	}
  nla_put_failure:
+	nlmsg_free(msg);
 	return ret;
 }
 
 
-static int i802_set_ht_params(void *priv, const u8 *ht_capab,
-			      size_t ht_capab_len, const u8 *ht_oper,
-			      size_t ht_oper_len)
-{
-	if (ht_oper_len >= 6) {
-		/* ht opmode uses 16bit in octet 5 & 6 */
-		u16 ht_opmode = le_to_host16(((u16 *) ht_oper)[2]);
-		return i802_set_bss(priv, -1, -1, -1, ht_opmode);
-	} else
-		return -1;
-}
-
-
 static int i802_get_inact_sec(void *priv, const u8 *addr)
 {
 	struct hostap_sta_driver_data data;
@@ -5610,7 +7401,7 @@
 	mgmt.u.deauth.reason_code = host_to_le16(reason);
 	return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
 					    IEEE80211_HDRLEN +
-					    sizeof(mgmt.u.deauth));
+					    sizeof(mgmt.u.deauth), 0);
 }
 
 
@@ -5629,7 +7420,7 @@
 	mgmt.u.disassoc.reason_code = host_to_le16(reason);
 	return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
 					    IEEE80211_HDRLEN +
-					    sizeof(mgmt.u.disassoc));
+					    sizeof(mgmt.u.disassoc), 0);
 }
 
 #endif /* HOSTAPD || CONFIG_AP */
@@ -5716,11 +7507,11 @@
 						 NULL, 1) < 0)
 				return -1;
 			if (bridge_ifname &&
-			    linux_br_add_if(drv->ioctl_sock, bridge_ifname,
-					    name) < 0)
+			    linux_br_add_if(drv->global->ioctl_sock,
+					    bridge_ifname, name) < 0)
 				return -1;
 		}
-		linux_set_iface_flags(drv->ioctl_sock, name, 1);
+		linux_set_iface_flags(drv->global->ioctl_sock, name, 1);
 		return i802_set_sta_vlan(priv, addr, name, 0);
 	} else {
 		i802_set_sta_vlan(priv, addr, bss->ifname, 0);
@@ -5764,7 +7555,7 @@
 		 * Bridge was configured, but the bridge device does
 		 * not exist. Try to add it now.
 		 */
-		if (linux_br_add(drv->ioctl_sock, brname) < 0) {
+		if (linux_br_add(drv->global->ioctl_sock, brname) < 0) {
 			wpa_printf(MSG_ERROR, "nl80211: Failed to add the "
 				   "bridge interface %s: %s",
 				   brname, strerror(errno));
@@ -5780,7 +7571,8 @@
 
 		wpa_printf(MSG_DEBUG, "nl80211: Removing interface %s from "
 			   "bridge %s", ifname, in_br);
-		if (linux_br_del_if(drv->ioctl_sock, in_br, ifname) < 0) {
+		if (linux_br_del_if(drv->global->ioctl_sock, in_br, ifname) <
+		    0) {
 			wpa_printf(MSG_ERROR, "nl80211: Failed to "
 				   "remove interface %s from bridge "
 				   "%s: %s",
@@ -5791,7 +7583,7 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: Adding interface %s into bridge %s",
 		   ifname, brname);
-	if (linux_br_add_if(drv->ioctl_sock, brname, ifname) < 0) {
+	if (linux_br_add_if(drv->global->ioctl_sock, brname, ifname) < 0) {
 		wpa_printf(MSG_ERROR, "nl80211: Failed to add interface %s "
 			   "into bridge %s: %s",
 			   ifname, brname, strerror(errno));
@@ -5813,12 +7605,15 @@
 	int ifindex, br_ifindex;
 	int br_added = 0;
 
-	bss = wpa_driver_nl80211_init(hapd, params->ifname, NULL);
+	bss = wpa_driver_nl80211_init(hapd, params->ifname,
+				      params->global_priv);
 	if (bss == NULL)
 		return NULL;
 
 	drv = bss->drv;
 	drv->nlmode = NL80211_IFTYPE_AP;
+	drv->eapol_sock = -1;
+
 	if (linux_br_get(brname, params->ifname) == 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in bridge %s",
 			   params->ifname, brname);
@@ -5846,16 +7641,16 @@
 	/* start listening for EAPOL on the default AP interface */
 	add_ifidx(drv, drv->ifindex);
 
-	if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 0))
+	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0))
 		goto failed;
 
 	if (params->bssid) {
-		if (linux_set_ifhwaddr(drv->ioctl_sock, bss->ifname,
+		if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
 				       params->bssid))
 			goto failed;
 	}
 
-	if (wpa_driver_nl80211_set_mode(bss, IEEE80211_MODE_AP)) {
+	if (wpa_driver_nl80211_set_mode(bss, drv->nlmode)) {
 		wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s "
 			   "into AP mode", bss->ifname);
 		goto failed;
@@ -5865,7 +7660,7 @@
 	    i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)
 		goto failed;
 
-	if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1))
+	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1))
 		goto failed;
 
 	drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
@@ -5880,25 +7675,16 @@
 		goto failed;
 	}
 
-	if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, params->own_addr))
+	if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+			       params->own_addr))
 		goto failed;
 
+	memcpy(bss->addr, params->own_addr, ETH_ALEN);
+
 	return bss;
 
 failed:
-	nl80211_remove_monitor_interface(drv);
-	rfkill_deinit(drv->rfkill);
-	netlink_deinit(drv->netlink);
-	if (drv->ioctl_sock >= 0)
-		close(drv->ioctl_sock);
-
-	genl_family_put(drv->nl80211);
-	nl_cache_free(drv->nl_cache);
-	nl80211_handle_destroy(drv->nl_handle);
-	nl_cb_put(drv->nl_cb);
-	eloop_unregister_read_sock(nl_socket_get_fd(drv->nl_handle_event));
-
-	os_free(drv);
+	wpa_driver_nl80211_deinit(bss);
 	return NULL;
 }
 
@@ -5938,7 +7724,7 @@
 	struct wpa_driver_nl80211_data *drv;
 	dl_list_for_each(drv, &global->interfaces,
 			 struct wpa_driver_nl80211_data, list) {
-		if (os_memcmp(addr, drv->addr, ETH_ALEN) == 0)
+		if (os_memcmp(addr, drv->first_bss.addr, ETH_ALEN) == 0)
 			return 1;
 	}
 	return 0;
@@ -5953,9 +7739,9 @@
 	if (!drv->global)
 		return -1;
 
-	os_memcpy(new_addr, drv->addr, ETH_ALEN);
+	os_memcpy(new_addr, drv->first_bss.addr, ETH_ALEN);
 	for (idx = 0; idx < 64; idx++) {
-		new_addr[0] = drv->addr[0] | 0x02;
+		new_addr[0] = drv->first_bss.addr[0] | 0x02;
 		new_addr[0] ^= idx << 2;
 		if (!nl80211_addr_in_use(drv->global, new_addr))
 			break;
@@ -6004,7 +7790,8 @@
 	}
 
 	if (!addr &&
-	    linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, if_addr) < 0) {
+	    linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+			       if_addr) < 0) {
 		nl80211_remove_iface(drv, ifidx);
 		return -1;
 	}
@@ -6016,10 +7803,10 @@
 		/* Enforce unique P2P Interface Address */
 		u8 new_addr[ETH_ALEN], own_addr[ETH_ALEN];
 
-		if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr)
-		    < 0 ||
-		    linux_get_ifhwaddr(drv->ioctl_sock, ifname, new_addr) < 0)
-		{
+		if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+				       own_addr) < 0 ||
+		    linux_get_ifhwaddr(drv->global->ioctl_sock, ifname,
+				       new_addr) < 0) {
 			nl80211_remove_iface(drv, ifidx);
 			return -1;
 		}
@@ -6030,7 +7817,7 @@
 				nl80211_remove_iface(drv, ifidx);
 				return -1;
 			}
-			if (linux_set_ifhwaddr(drv->ioctl_sock, ifname,
+			if (linux_set_ifhwaddr(drv->global->ioctl_sock, ifname,
 					       new_addr) < 0) {
 				nl80211_remove_iface(drv, ifidx);
 				return -1;
@@ -6051,21 +7838,27 @@
 	}
 
 	if (type == WPA_IF_AP_BSS) {
-		if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) {
+		if (linux_set_iface_flags(drv->global->ioctl_sock, ifname, 1))
+		{
 			nl80211_remove_iface(drv, ifidx);
 			os_free(new_bss);
 			return -1;
 		}
 		os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ);
+		os_memcpy(new_bss->addr, if_addr, ETH_ALEN);
 		new_bss->ifindex = ifidx;
 		new_bss->drv = drv;
 		new_bss->next = drv->first_bss.next;
 		drv->first_bss.next = new_bss;
 		if (drv_priv)
 			*drv_priv = new_bss;
+		nl80211_init_bss(new_bss);
 	}
 #endif /* HOSTAPD */
 
+	if (drv->global)
+		drv->global->if_add_ifindex = ifidx;
+
 	return 0;
 }
 
@@ -6085,14 +7878,14 @@
 
 #ifdef HOSTAPD
 	if (bss->added_if_into_bridge) {
-		if (linux_br_del_if(drv->ioctl_sock, bss->brname, bss->ifname)
-		    < 0)
+		if (linux_br_del_if(drv->global->ioctl_sock, bss->brname,
+				    bss->ifname) < 0)
 			wpa_printf(MSG_INFO, "nl80211: Failed to remove "
 				   "interface %s from bridge %s: %s",
 				   bss->ifname, bss->brname, strerror(errno));
 	}
 	if (bss->added_bridge) {
-		if (linux_br_del(drv->ioctl_sock, bss->brname) < 0)
+		if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
 			wpa_printf(MSG_INFO, "nl80211: Failed to remove "
 				   "bridge %s: %s",
 				   bss->brname, strerror(errno));
@@ -6111,6 +7904,7 @@
 		for (tbss = &drv->first_bss; tbss; tbss = tbss->next) {
 			if (tbss->next == bss) {
 				tbss->next = bss->next;
+				nl80211_destroy_bss(bss);
 				os_free(bss);
 				bss = NULL;
 				break;
@@ -6139,11 +7933,13 @@
 }
 
 
-static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv,
+static int nl80211_send_frame_cmd(struct i802_bss *bss,
 				  unsigned int freq, unsigned int wait,
 				  const u8 *buf, size_t buf_len,
-				  u64 *cookie_out)
+				  u64 *cookie_out, int no_cck, int no_ack,
+				  int offchanok)
 {
+	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
 	u64 cookie;
 	int ret = -1;
@@ -6152,16 +7948,21 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_FRAME, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME);
 
-	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
-#ifndef ANDROID_BRCM_P2P_PATCH
+#ifndef ANDROID_P2P
 	if (wait)
 		NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
 #endif
-	NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
+	if (offchanok)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
+	if (no_cck)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
+	if (no_ack)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK);
+
 	NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);
 
 	cookie = 0;
@@ -6173,11 +7974,12 @@
 			   freq, wait);
 		goto nla_put_failure;
 	}
-	wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted; "
-		   "cookie 0x%llx", (long long unsigned int) cookie);
+	wpa_printf(MSG_DEBUG, "nl80211: Frame TX command accepted%s; "
+		   "cookie 0x%llx", no_ack ? " (no ACK)" : "",
+		   (long long unsigned int) cookie);
 
 	if (cookie_out)
-		*cookie_out = cookie;
+		*cookie_out = no_ack ? (u64) -1 : cookie;
 
 nla_put_failure:
 	nlmsg_free(msg);
@@ -6189,7 +7991,8 @@
 					  unsigned int wait_time,
 					  const u8 *dst, const u8 *src,
 					  const u8 *bssid,
-					  const u8 *data, size_t data_len)
+					  const u8 *data, size_t data_len,
+					  int no_cck)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -6198,7 +8001,7 @@
 	struct ieee80211_hdr *hdr;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
-		   "wait=%d ms)", drv->ifindex, wait_time);
+		   "wait=%d ms no_cck=%d)", drv->ifindex, wait_time, no_cck);
 
 	buf = os_zalloc(24 + data_len);
 	if (buf == NULL)
@@ -6211,12 +8014,14 @@
 	os_memcpy(hdr->addr2, src, ETH_ALEN);
 	os_memcpy(hdr->addr3, bssid, ETH_ALEN);
 
-	if (drv->nlmode == NL80211_IFTYPE_AP)
-		ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len);
+	if (is_ap_interface(drv->nlmode))
+		ret = wpa_driver_nl80211_send_mlme(priv, buf, 24 + data_len,
+						   0);
 	else
-		ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf,
+		ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
 					     24 + data_len,
-					     &drv->send_action_cookie);
+					     &drv->send_action_cookie,
+					     no_cck, 0, 1);
 
 	os_free(buf);
 	return ret;
@@ -6234,8 +8039,7 @@
 	if (!msg)
 		return;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_FRAME_WAIT_CANCEL, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_FRAME_WAIT_CANCEL);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie);
@@ -6264,8 +8068,7 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_REMAIN_ON_CHANNEL, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_REMAIN_ON_CHANNEL);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
@@ -6273,17 +8076,20 @@
 
 	cookie = 0;
 	ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie);
+	msg = NULL;
 	if (ret == 0) {
 		wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie "
 			   "0x%llx for freq=%u MHz duration=%u",
 			   (long long unsigned int) cookie, freq, duration);
 		drv->remain_on_chan_cookie = cookie;
+		drv->pending_remain_on_chan = 1;
 		return 0;
 	}
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to request remain-on-channel "
 		   "(freq=%d duration=%u): %d (%s)",
 		   freq, duration, ret, strerror(-ret));
 nla_put_failure:
+	nlmsg_free(msg);
 	return -1;
 }
 
@@ -6309,18 +8115,19 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
 	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, drv->remain_on_chan_cookie);
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
 	if (ret == 0)
 		return 0;
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: "
 		   "%d (%s)", ret, strerror(-ret));
 nla_put_failure:
+	nlmsg_free(msg);
 	return -1;
 }
 
@@ -6331,60 +8138,43 @@
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 
 	if (!report) {
-		if (drv->nl_handle_preq) {
+		if (bss->nl_preq && drv->device_ap_sme &&
+		    is_ap_interface(drv->nlmode)) {
+			/*
+			 * Do not disable Probe Request reporting that was
+			 * enabled in nl80211_setup_ap().
+			 */
+			wpa_printf(MSG_DEBUG, "nl80211: Skip disabling of "
+				   "Probe Request reporting nl_preq=%p while "
+				   "in AP mode", bss->nl_preq);
+		} else if (bss->nl_preq) {
+			wpa_printf(MSG_DEBUG, "nl80211: Disable Probe Request "
+				   "reporting nl_preq=%p", bss->nl_preq);
 			eloop_unregister_read_sock(
-				nl_socket_get_fd(drv->nl_handle_preq));
-			nl_cache_free(drv->nl_cache_preq);
-			nl80211_handle_destroy(drv->nl_handle_preq);
-			drv->nl_handle_preq = NULL;
+				nl_socket_get_fd(bss->nl_preq));
+			nl_destroy_handles(&bss->nl_preq);
 		}
 		return 0;
 	}
 
-	if (drv->nl_handle_preq) {
+	if (bss->nl_preq) {
 		wpa_printf(MSG_DEBUG, "nl80211: Probe Request reporting "
-			   "already on!");
+			   "already on! nl_preq=%p", bss->nl_preq);
 		return 0;
 	}
 
-	drv->nl_handle_preq = nl80211_handle_alloc(drv->nl_cb);
-	if (drv->nl_handle_preq == NULL) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate "
-			   "netlink callbacks (preq)");
-		goto out_err1;
-	}
-
-	if (genl_connect(drv->nl_handle_preq)) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to connect to "
-			   "generic netlink (preq)");
-		goto out_err2;
+	bss->nl_preq = nl_create_handle(drv->global->nl_cb, "preq");
+	if (bss->nl_preq == NULL)
 		return -1;
-	}
+	wpa_printf(MSG_DEBUG, "nl80211: Enable Probe Request "
+		   "reporting nl_preq=%p", bss->nl_preq);
 
-#ifdef CONFIG_LIBNL20
-	if (genl_ctrl_alloc_cache(drv->nl_handle_preq,
-				  &drv->nl_cache_preq) < 0) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
-			   "netlink cache (preq)");
-		goto out_err2;
-	}
-#else /* CONFIG_LIBNL20 */
-	drv->nl_cache_preq = genl_ctrl_alloc_cache(drv->nl_handle_preq);
-	if (drv->nl_cache_preq == NULL) {
-		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
-			   "netlink cache (preq)");
-		goto out_err2;
-	}
-#endif /* CONFIG_LIBNL20 */
-
-	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+	if (nl80211_register_frame(bss, bss->nl_preq,
 				   (WLAN_FC_TYPE_MGMT << 2) |
 				   (WLAN_FC_STYPE_PROBE_REQ << 4),
-				   NULL, 0) < 0) {
-		goto out_err3;
-	}
-
-#ifdef ANDROID_BRCM_P2P_PATCH
+				   NULL, 0) < 0)
+		goto out_err;
+#ifdef ANDROID_P2P
 	if (drv->nlmode != NL80211_IFTYPE_AP &&
 		drv->nlmode != NL80211_IFTYPE_P2P_GO) {
 		wpa_printf(MSG_DEBUG, "nl80211: probe_req_report control only "
@@ -6392,49 +8182,51 @@
 			   drv->nlmode);
 		goto done;
 	}
-	
-	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+	if (nl80211_register_frame(bss, bss->nl_preq,
 			   (WLAN_FC_TYPE_MGMT << 2) |
 			   (WLAN_FC_STYPE_ASSOC_REQ << 4),
 			   NULL, 0) < 0) {
-		goto out_err3;
+		goto out_err;
 	}
 
-	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+	if (nl80211_register_frame(bss, bss->nl_preq,
 			   (WLAN_FC_TYPE_MGMT << 2) |
 			   (WLAN_FC_STYPE_REASSOC_REQ << 4),
 			   NULL, 0) < 0) {
-		goto out_err3;
+		goto out_err;
 	}
 
-	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+	if (nl80211_register_frame(bss, bss->nl_preq,
 			   (WLAN_FC_TYPE_MGMT << 2) |
 			   (WLAN_FC_STYPE_DISASSOC << 4),
 			   NULL, 0) < 0) {
-		goto out_err3;
+		goto out_err;
 	}
-	
-	if (nl80211_register_frame(drv, drv->nl_handle_preq,
+
+	if (nl80211_register_frame(bss, bss->nl_preq,
 					   (WLAN_FC_TYPE_MGMT << 2) |
 					   (WLAN_FC_STYPE_DEAUTH << 4),
 					   NULL, 0) < 0) {
-		goto out_err3;
+		goto out_err;
+	}
+
+	if (nl80211_register_frame(bss, bss->nl_preq,
+			   (WLAN_FC_TYPE_MGMT << 2) |
+			   (WLAN_FC_STYPE_ACTION << 4),
+			   NULL, 0) < 0) {
+		goto out_err;
 	}
 
 done:
-#endif
-	eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_preq),
-				 wpa_driver_nl80211_event_receive, drv,
-				 drv->nl_handle_preq);
+#endif /* ANDROID_P2P */
+	eloop_register_read_sock(nl_socket_get_fd(bss->nl_preq),
+				 wpa_driver_nl80211_event_receive, bss->nl_cb,
+				 bss->nl_preq);
 
 	return 0;
 
- out_err3:
-	nl_cache_free(drv->nl_cache_preq);
- out_err2:
-	nl80211_handle_destroy(drv->nl_handle_preq);
-	drv->nl_handle_preq = NULL;
- out_err1:
+ out_err:
+	nl_destroy_handles(&bss->nl_preq);
 	return -1;
 }
 
@@ -6450,8 +8242,7 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_SET_TX_BITRATE_MASK, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_TX_BITRATE_MASK);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
 
 	bands = nla_nest_start(msg, NL80211_ATTR_TX_RATES);
@@ -6466,8 +8257,10 @@
 	band = nla_nest_start(msg, NL80211_BAND_2GHZ);
 	if (!band)
 		goto nla_put_failure;
-	NLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,
-		"\x0c\x12\x18\x24\x30\x48\x60\x6c");
+	if (disabled) {
+		NLA_PUT(msg, NL80211_TXRATE_LEGACY, 8,
+			"\x0c\x12\x18\x24\x30\x48\x60\x6c");
+	}
 	nla_nest_end(msg, band);
 
 	nla_nest_end(msg, bands);
@@ -6487,23 +8280,14 @@
 }
 
 
-static int wpa_driver_nl80211_disable_11b_rates(void *priv, int disabled)
-{
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	drv->disable_11b_rates = disabled;
-	return nl80211_disable_11b_rates(drv, drv->ifindex, disabled);
-}
-
-
 static int wpa_driver_nl80211_deinit_ap(void *priv)
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	if (drv->nlmode != NL80211_IFTYPE_AP)
+	if (!is_ap_interface(drv->nlmode))
 		return -1;
 	wpa_driver_nl80211_del_beacon(drv);
-	return wpa_driver_nl80211_set_mode(priv, IEEE80211_MODE_INFRA);
+	return wpa_driver_nl80211_set_mode(priv, NL80211_IFTYPE_STATION);
 }
 
 
@@ -6511,7 +8295,7 @@
 {
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
-	if (linux_set_iface_flags(drv->ioctl_sock, bss->ifname, 1)) {
+	if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
 		wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on "
 			   "resume event");
 	}
@@ -6526,10 +8310,7 @@
 	int ret;
 	u8 *data, *pos;
 	size_t data_len;
-	u8 own_addr[ETH_ALEN];
-
-	if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, own_addr) < 0)
-		return -1;
+	const u8 *own_addr = bss->addr;
 
 	if (action != 1) {
 		wpa_printf(MSG_ERROR, "nl80211: Unsupported send_ft_action "
@@ -6561,7 +8342,7 @@
 
 	ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0,
 					     drv->bssid, own_addr, drv->bssid,
-					     data, data_len);
+					     data, data_len, 0);
 	os_free(data);
 
 	return ret;
@@ -6581,8 +8362,7 @@
 	if (!msg)
 		return -1;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
-		    0, NL80211_CMD_SET_CQM, 0);
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_CQM);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
 
@@ -6599,8 +8379,7 @@
 	msg = NULL;
 
 nla_put_failure:
-	if (cqm)
-		nlmsg_free(cqm);
+	nlmsg_free(cqm);
 	nlmsg_free(msg);
 	return -1;
 }
@@ -6621,34 +8400,58 @@
 }
 
 
+static int wpa_driver_nl80211_shared_freq(void *priv)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct wpa_driver_nl80211_data *driver;
+	int freq = 0;
+
+	/*
+	 * If the same PHY is in connected state with some other interface,
+	 * then retrieve the assoc freq.
+	 */
+	wpa_printf(MSG_DEBUG, "nl80211: Get shared freq for PHY %s",
+		   drv->phyname);
+
+	dl_list_for_each(driver, &drv->global->interfaces,
+			 struct wpa_driver_nl80211_data, list) {
+		if (drv == driver ||
+		    os_strcmp(drv->phyname, driver->phyname) != 0 ||
+#ifdef ANDROID_P2P
+		    (!driver->associated && !is_ap_interface(driver->nlmode)))
+#else
+		    !driver->associated)
+#endif
+			continue;
+
+		wpa_printf(MSG_DEBUG, "nl80211: Found a match for PHY %s - %s "
+			   MACSTR,
+			   driver->phyname, driver->first_bss.ifname,
+			   MAC2STR(driver->first_bss.addr));
+#ifdef ANDROID_P2P
+		if(is_ap_interface(driver->nlmode))
+			freq = driver->first_bss.freq;
+		else
+#endif
+			freq = nl80211_get_assoc_freq(driver);
+		wpa_printf(MSG_DEBUG, "nl80211: Shared freq for PHY %s: %d",
+			   drv->phyname, freq);
+	}
+
+	if (!freq)
+		wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
+			   "PHY (%s) in associated state", drv->phyname);
+
+	return freq;
+}
+
+
 static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
 			      int encrypt)
 {
 	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt);
-}
-
-
-static int nl80211_set_intra_bss(void *priv, int enabled)
-{
-	struct i802_bss *bss = priv;
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-	struct nl_msg *msg;
-
-	msg = nlmsg_alloc();
-	if (!msg)
-		return -ENOMEM;
-
-	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-		    NL80211_CMD_SET_BSS, 0);
-
-	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
-	NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, !enabled);
-
-	return send_and_recv_msgs(drv, msg, NULL, NULL);
- nla_put_failure:
-	return -ENOBUFS;
+	return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0);
 }
 
 
@@ -6668,6 +8471,15 @@
 		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
 		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
 	}
+#ifdef ANDROID_P2P
+	if(os_strstr(param, "use_multi_chan_concurrent=1")) {
+		struct i802_bss *bss = priv;
+		struct wpa_driver_nl80211_data *drv = bss->drv;
+		wpa_printf(MSG_DEBUG, "nl80211: Use Multi channel "
+			   "concurrency");
+		drv->capa.flags |= WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT;
+	}
+#endif
 #endif /* CONFIG_P2P */
 
 	return 0;
@@ -6677,11 +8489,42 @@
 static void * nl80211_global_init(void)
 {
 	struct nl80211_global *global;
+	struct netlink_config *cfg;
+
 	global = os_zalloc(sizeof(*global));
 	if (global == NULL)
 		return NULL;
+	global->ioctl_sock = -1;
 	dl_list_init(&global->interfaces);
+	global->if_add_ifindex = -1;
+
+	cfg = os_zalloc(sizeof(*cfg));
+	if (cfg == NULL)
+		goto err;
+
+	cfg->ctx = global;
+	cfg->newlink_cb = wpa_driver_nl80211_event_rtm_newlink;
+	cfg->dellink_cb = wpa_driver_nl80211_event_rtm_dellink;
+	global->netlink = netlink_init(cfg);
+	if (global->netlink == NULL) {
+		os_free(cfg);
+		goto err;
+	}
+
+	if (wpa_driver_nl80211_init_nl_global(global) < 0)
+		goto err;
+
+	global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
+	if (global->ioctl_sock < 0) {
+		perror("socket(PF_INET,SOCK_DGRAM)");
+		goto err;
+	}
+
 	return global;
+
+err:
+	nl80211_global_deinit(global);
+	return NULL;
 }
 
 
@@ -6695,6 +8538,23 @@
 			   "nl80211_global_deinit",
 			   dl_list_len(&global->interfaces));
 	}
+
+	if (global->netlink)
+		netlink_deinit(global->netlink);
+
+	nl_destroy_handles(&global->nl);
+
+	if (global->nl_event) {
+		eloop_unregister_read_sock(
+			nl_socket_get_fd(global->nl_event));
+		nl_destroy_handles(&global->nl_event);
+	}
+
+	nl_cb_put(global->nl_cb);
+
+	if (global->ioctl_sock >= 0)
+		close(global->ioctl_sock);
+
 	os_free(global);
 }
 
@@ -6716,8 +8576,7 @@
 	if (!msg)
 		return -ENOMEM;
 
-	genlmsg_put(msg, 0, 0, genl_family_get_id(bss->drv->nl80211), 0, 0,
-		    cmd, 0);
+	nl80211_cmd(bss->drv, msg, 0, cmd);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
 	if (pmkid)
@@ -6727,6 +8586,7 @@
 
 	return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
  nla_put_failure:
+	nlmsg_free(msg);
 	return -ENOBUFS;
 }
 
@@ -6756,6 +8616,366 @@
 }
 
 
+static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
+				   const u8 *replay_ctr)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nlattr *replay_nested;
+	struct nl_msg *msg;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+
+	replay_nested = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
+	if (!replay_nested)
+		goto nla_put_failure;
+
+	NLA_PUT(msg, NL80211_REKEY_DATA_KEK, NL80211_KEK_LEN, kek);
+	NLA_PUT(msg, NL80211_REKEY_DATA_KCK, NL80211_KCK_LEN, kck);
+	NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR, NL80211_REPLAY_CTR_LEN,
+		replay_ctr);
+
+	nla_nest_end(msg, replay_nested);
+
+	send_and_recv_msgs(drv, msg, NULL, NULL);
+	return;
+ nla_put_failure:
+	nlmsg_free(msg);
+}
+
+
+static void nl80211_send_null_frame(struct i802_bss *bss, const u8 *own_addr,
+				    const u8 *addr, int qos)
+{
+	/* send data frame to poll STA and check whether
+	 * this frame is ACKed */
+	struct {
+		struct ieee80211_hdr hdr;
+		u16 qos_ctl;
+	} STRUCT_PACKED nulldata;
+	size_t size;
+
+	/* Send data frame to poll STA and check whether this frame is ACKed */
+
+	os_memset(&nulldata, 0, sizeof(nulldata));
+
+	if (qos) {
+		nulldata.hdr.frame_control =
+			IEEE80211_FC(WLAN_FC_TYPE_DATA,
+				     WLAN_FC_STYPE_QOS_NULL);
+		size = sizeof(nulldata);
+	} else {
+		nulldata.hdr.frame_control =
+			IEEE80211_FC(WLAN_FC_TYPE_DATA,
+				     WLAN_FC_STYPE_NULLFUNC);
+		size = sizeof(struct ieee80211_hdr);
+	}
+
+	nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
+	os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
+	os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
+	os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
+
+	if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0) < 0)
+		wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
+			   "send poll frame");
+}
+
+static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr,
+				int qos)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+
+	if (!drv->poll_command_supported) {
+		nl80211_send_null_frame(bss, own_addr, addr, qos);
+		return;
+	}
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_PROBE_CLIENT);
+
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
+
+	send_and_recv_msgs(drv, msg, NULL, NULL);
+	return;
+ nla_put_failure:
+	nlmsg_free(msg);
+}
+
+
+static int nl80211_set_power_save(struct i802_bss *bss, int enabled)
+{
+	struct nl_msg *msg;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_SET_POWER_SAVE);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, bss->ifindex);
+	NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE,
+		    enabled ? NL80211_PS_ENABLED : NL80211_PS_DISABLED);
+	return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+
+static int nl80211_set_p2p_powersave(void *priv, int legacy_ps, int opp_ps,
+				     int ctwindow)
+{
+	struct i802_bss *bss = priv;
+
+	wpa_printf(MSG_DEBUG, "nl80211: set_p2p_powersave (legacy_ps=%d "
+		   "opp_ps=%d ctwindow=%d)", legacy_ps, opp_ps, ctwindow);
+
+	if (opp_ps != -1 || ctwindow != -1)
+		return -1; /* Not yet supported */
+
+	if (legacy_ps == -1)
+		return 0;
+	if (legacy_ps != 0 && legacy_ps != 1)
+		return -1; /* Not yet supported */
+
+	return nl80211_set_power_save(bss, legacy_ps);
+}
+
+
+#ifdef CONFIG_TDLS
+
+static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
+				  u8 dialog_token, u16 status_code,
+				  const u8 *buf, size_t len)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
+		return -EOPNOTSUPP;
+
+	if (!dst)
+		return -EINVAL;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_MGMT);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
+	NLA_PUT_U8(msg, NL80211_ATTR_TDLS_ACTION, action_code);
+	NLA_PUT_U8(msg, NL80211_ATTR_TDLS_DIALOG_TOKEN, dialog_token);
+	NLA_PUT_U16(msg, NL80211_ATTR_STATUS_CODE, status_code);
+	NLA_PUT(msg, NL80211_ATTR_IE, len, buf);
+
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+
+static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+	enum nl80211_tdls_operation nl80211_oper;
+
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
+		return -EOPNOTSUPP;
+
+	switch (oper) {
+	case TDLS_DISCOVERY_REQ:
+		nl80211_oper = NL80211_TDLS_DISCOVERY_REQ;
+		break;
+	case TDLS_SETUP:
+		nl80211_oper = NL80211_TDLS_SETUP;
+		break;
+	case TDLS_TEARDOWN:
+		nl80211_oper = NL80211_TDLS_TEARDOWN;
+		break;
+	case TDLS_ENABLE_LINK:
+		nl80211_oper = NL80211_TDLS_ENABLE_LINK;
+		break;
+	case TDLS_DISABLE_LINK:
+		nl80211_oper = NL80211_TDLS_DISABLE_LINK;
+		break;
+	case TDLS_ENABLE:
+		return 0;
+	case TDLS_DISABLE:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	nl80211_cmd(drv, msg, 0, NL80211_CMD_TDLS_OPER);
+	NLA_PUT_U8(msg, NL80211_ATTR_TDLS_OPERATION, nl80211_oper);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, peer);
+
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+#endif /* CONFIG TDLS */
+
+
+#ifdef ANDROID
+
+typedef struct android_wifi_priv_cmd {
+	char *buf;
+	int used_len;
+	int total_len;
+} android_wifi_priv_cmd;
+
+static int drv_errors = 0;
+
+static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
+{
+	drv_errors++;
+	if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
+		drv_errors = 0;
+		wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+	}
+}
+
+
+static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct ifreq ifr;
+	android_wifi_priv_cmd priv_cmd;
+	char buf[MAX_DRV_CMD_SIZE];
+	int ret;
+
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_memset(&priv_cmd, 0, sizeof(priv_cmd));
+	os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
+
+	os_memset(buf, 0, sizeof(buf));
+	os_strlcpy(buf, cmd, sizeof(buf));
+
+	priv_cmd.buf = buf;
+	priv_cmd.used_len = sizeof(buf);
+	priv_cmd.total_len = sizeof(buf);
+	ifr.ifr_data = &priv_cmd;
+
+	ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
+	if (ret < 0) {
+		wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
+			   __func__);
+		wpa_driver_send_hang_msg(drv);
+		return ret;
+	}
+
+	drv_errors = 0;
+	return 0;
+}
+
+
+static int android_pno_start(struct i802_bss *bss,
+			     struct wpa_driver_scan_params *params)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct ifreq ifr;
+	android_wifi_priv_cmd priv_cmd;
+	int ret = 0, i = 0, bp;
+	char buf[WEXT_PNO_MAX_COMMAND_SIZE];
+
+	bp = WEXT_PNOSETUP_HEADER_SIZE;
+	os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
+	buf[bp++] = WEXT_PNO_TLV_PREFIX;
+	buf[bp++] = WEXT_PNO_TLV_VERSION;
+	buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
+	buf[bp++] = WEXT_PNO_TLV_RESERVED;
+
+	while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
+		/* Check that there is enough space needed for 1 more SSID, the
+		 * other sections and null termination */
+		if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
+		     WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
+			break;
+		wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
+				  params->ssids[i].ssid,
+				  params->ssids[i].ssid_len);
+		buf[bp++] = WEXT_PNO_SSID_SECTION;
+		buf[bp++] = params->ssids[i].ssid_len;
+		os_memcpy(&buf[bp], params->ssids[i].ssid,
+			  params->ssids[i].ssid_len);
+		bp += params->ssids[i].ssid_len;
+		i++;
+	}
+
+	buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
+	os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
+		    WEXT_PNO_SCAN_INTERVAL);
+	bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
+
+	buf[bp++] = WEXT_PNO_REPEAT_SECTION;
+	os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
+		    WEXT_PNO_REPEAT);
+	bp += WEXT_PNO_REPEAT_LENGTH;
+
+	buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
+	os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
+		    WEXT_PNO_MAX_REPEAT);
+	bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
+
+	memset(&ifr, 0, sizeof(ifr));
+	memset(&priv_cmd, 0, sizeof(priv_cmd));
+	os_strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
+
+	priv_cmd.buf = buf;
+	priv_cmd.used_len = bp;
+	priv_cmd.total_len = bp;
+	ifr.ifr_data = &priv_cmd;
+
+	ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
+
+	if (ret < 0) {
+		wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
+			   ret);
+		wpa_driver_send_hang_msg(drv);
+		return ret;
+	}
+
+	drv_errors = 0;
+
+	return android_priv_cmd(bss, "PNOFORCE 1");
+}
+
+
+static int android_pno_stop(struct i802_bss *bss)
+{
+	return android_priv_cmd(bss, "PNOFORCE 0");
+}
+
+#endif /* ANDROID */
+
+
 const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.name = "nl80211",
 	.desc = "Linux nl80211/cfg80211",
@@ -6763,6 +8983,8 @@
 	.get_ssid = wpa_driver_nl80211_get_ssid,
 	.set_key = wpa_driver_nl80211_set_key,
 	.scan2 = wpa_driver_nl80211_scan,
+	.sched_scan = wpa_driver_nl80211_sched_scan,
+	.stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
 	.get_scan_results2 = wpa_driver_nl80211_get_scan_results,
 	.deauthenticate = wpa_driver_nl80211_deauthenticate,
 	.disassociate = wpa_driver_nl80211_disassociate,
@@ -6776,7 +8998,7 @@
 	.set_operstate = wpa_driver_nl80211_set_operstate,
 	.set_supp_port = wpa_driver_nl80211_set_supp_port,
 	.set_country = wpa_driver_nl80211_set_country,
-	.set_beacon = wpa_driver_nl80211_set_beacon,
+	.set_ap = wpa_driver_nl80211_set_ap,
 	.if_add = wpa_driver_nl80211_if_add,
 	.if_remove = wpa_driver_nl80211_if_remove,
 	.send_mlme = wpa_driver_nl80211_send_mlme,
@@ -6798,13 +9020,8 @@
 	.sta_clear_stats = i802_sta_clear_stats,
 	.set_rts = i802_set_rts,
 	.set_frag = i802_set_frag,
-	.set_cts_protect = i802_set_cts_protect,
-	.set_preamble = i802_set_preamble,
-	.set_short_slot_time = i802_set_short_slot_time,
 	.set_tx_queue_params = i802_set_tx_queue_params,
 	.set_sta_vlan = i802_set_sta_vlan,
-	.set_ht_params = i802_set_ht_params,
-	.set_rate_sets = i802_set_rate_sets,
 	.sta_deauth = i802_sta_deauth,
 	.sta_disassoc = i802_sta_disassoc,
 #endif /* HOSTAPD || CONFIG_AP */
@@ -6815,22 +9032,30 @@
 	.cancel_remain_on_channel =
 	wpa_driver_nl80211_cancel_remain_on_channel,
 	.probe_req_report = wpa_driver_nl80211_probe_req_report,
-	.disable_11b_rates = wpa_driver_nl80211_disable_11b_rates,
 	.deinit_ap = wpa_driver_nl80211_deinit_ap,
 	.resume = wpa_driver_nl80211_resume,
 	.send_ft_action = nl80211_send_ft_action,
 	.signal_monitor = nl80211_signal_monitor,
 	.signal_poll = nl80211_signal_poll,
 	.send_frame = nl80211_send_frame,
-	.set_intra_bss = nl80211_set_intra_bss,
+	.shared_freq = wpa_driver_nl80211_shared_freq,
 	.set_param = nl80211_set_param,
 	.get_radio_name = nl80211_get_radio_name,
 	.add_pmkid = nl80211_add_pmkid,
 	.remove_pmkid = nl80211_remove_pmkid,
 	.flush_pmkid = nl80211_flush_pmkid,
-#ifdef ANDROID_BRCM_P2P_PATCH
-	.get_noa = wpa_driver_get_p2p_noa,
+	.set_rekey_info = nl80211_set_rekey_info,
+	.poll_client = nl80211_poll_client,
+#ifndef ANDROID_P2P
+	.set_p2p_powersave = nl80211_set_p2p_powersave,
+#endif
+#ifdef CONFIG_TDLS
+	.send_tdls_mgmt = nl80211_send_tdls_mgmt,
+	.tdls_oper = nl80211_tdls_oper,
+#endif /* CONFIG_TDLS */
+#ifdef ANDROID_P2P
 	.set_noa = wpa_driver_set_p2p_noa,
+	.get_noa = wpa_driver_get_p2p_noa,
 	.set_p2p_powersave = wpa_driver_set_p2p_ps,
 	.set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
 #endif
diff --git a/src/drivers/driver_osx.m b/src/drivers/driver_osx.m
deleted file mode 100644
index 69ca4b5..0000000
--- a/src/drivers/driver_osx.m
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * WPA Supplicant - Mac OS X Apple80211 driver interface
- * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
- */
-
-#include "includes.h"
-#define Boolean __DummyBoolean
-#include <CoreFoundation/CoreFoundation.h>
-#undef Boolean
-
-#include "common.h"
-#include "driver.h"
-#include "eloop.h"
-#include "common/ieee802_11_defs.h"
-
-#include "Apple80211.h"
-
-struct wpa_driver_osx_data {
-	void *ctx;
-	WirelessRef wireless_ctx;
-	CFArrayRef scan_results;
-};
-
-
-#ifndef CONFIG_NO_STDOUT_DEBUG
-extern int wpa_debug_level;
-
-static void dump_dict_cb(const void *key, const void *value, void *context)
-{
-        if (MSG_DEBUG < wpa_debug_level)
-                return;
-
-	wpa_printf(MSG_DEBUG, "Key:");
-	CFShow(key);
-	wpa_printf(MSG_DEBUG, "Value:");
-	CFShow(value);
-}
-#endif /* CONFIG_NO_STDOUT_DEBUG */
-
-
-static void wpa_driver_osx_dump_dict(CFDictionaryRef dict, const char *title)
-{
-#ifndef CONFIG_NO_STDOUT_DEBUG
-	wpa_printf(MSG_DEBUG, "OSX: Dump dictionary %s - %u entries",
-		   title, (unsigned int) CFDictionaryGetCount(dict));
-	CFDictionaryApplyFunction(dict, dump_dict_cb, NULL);
-#endif /* CONFIG_NO_STDOUT_DEBUG */
-}
-
-
-static int wpa_driver_osx_get_ssid(void *priv, u8 *ssid)
-{
-	struct wpa_driver_osx_data *drv = priv;
-	WirelessError err;
-	WirelessInfo info;
-	int len;
-
-	err = WirelessGetInfo(drv->wireless_ctx, &info);
-	if (err) {
-		wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d",
-			   (int) err);
-		return -1;
-	}
-	if (!info.power) {
-		wpa_printf(MSG_DEBUG, "OSX: Wireless device power off");
-		return -1;
-	}
-
-	for (len = 0; len < 32; len++)
-		if (info.ssid[len] == 0)
-			break;
-
-	os_memcpy(ssid, info.ssid, len);
-	return len;
-}
-
-
-static int wpa_driver_osx_get_bssid(void *priv, u8 *bssid)
-{
-	struct wpa_driver_osx_data *drv = priv;
-	WirelessError err;
-	WirelessInfo info;
-
-	err = WirelessGetInfo(drv->wireless_ctx, &info);
-	if (err) {
-		wpa_printf(MSG_DEBUG, "OSX: WirelessGetInfo failed: %d",
-			   (int) err);
-		return -1;
-	}
-	if (!info.power) {
-		wpa_printf(MSG_DEBUG, "OSX: Wireless device power off");
-		return -1;
-	}
-
-	os_memcpy(bssid, info.bssID, ETH_ALEN);
-	return 0;
-}
-
-
-static void wpa_driver_osx_scan_timeout(void *eloop_ctx, void *timeout_ctx)
-{
-	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
-}
-
-
-static int wpa_driver_osx_scan(void *priv, struct wpa_driver_scan_params *params)
-{
-	struct wpa_driver_osx_data *drv = priv;
-	WirelessError err;
-	const u8 *ssid = params->ssids[0].ssid;
-	size_t ssid_len = params->ssids[0].ssid_len;
-
-	if (drv->scan_results) {
-		CFRelease(drv->scan_results);
-		drv->scan_results = NULL;
-	}
-
-	if (ssid) {
-		CFStringRef data;
-		data = CFStringCreateWithBytes(kCFAllocatorDefault,
-					       ssid, ssid_len,
-					       kCFStringEncodingISOLatin1,
-					       FALSE);
-		if (data == NULL) {
-			wpa_printf(MSG_DEBUG, "CFStringCreateWithBytes "
-				   "failed");
-			return -1;
-		}
-
-		err = WirelessDirectedScan(drv->wireless_ctx,
-					   &drv->scan_results, 0, data);
-		CFRelease(data);
-		if (err) {
-			wpa_printf(MSG_DEBUG, "OSX: WirelessDirectedScan "
-				   "failed: 0x%08x", (unsigned int) err);
-			return -1;
-		}
-	} else {
-		err = WirelessScan(drv->wireless_ctx, &drv->scan_results, 0);
-		if (err) {
-			wpa_printf(MSG_DEBUG, "OSX: WirelessScan failed: "
-				   "0x%08x", (unsigned int) err);
-			return -1;
-		}
-	}
-
-	eloop_register_timeout(0, 0, wpa_driver_osx_scan_timeout, drv,
-			       drv->ctx);
-	return 0;
-}
-
-
-static void wpa_driver_osx_add_scan_entry(struct wpa_scan_results *res,
-					  WirelessNetworkInfo *info)
-{
-	struct wpa_scan_res *result, **tmp;
-	size_t extra_len;
-	u8 *pos;
-
-	extra_len = 2 + info->ssid_len;
-
-	result = os_zalloc(sizeof(*result) + extra_len);
-	if (result == NULL)
-		return;
-	os_memcpy(result->bssid, info->bssid, ETH_ALEN);
-	result->freq = 2407 + info->channel * 5;
-	//result->beacon_int =;
-	result->caps = info->capability;
-	//result->qual = info->signal;
-	result->noise = info->noise;
-
-	pos = (u8 *)(result + 1);
-
-	*pos++ = WLAN_EID_SSID;
-	*pos++ = info->ssid_len;
-	os_memcpy(pos, info->ssid, info->ssid_len);
-	pos += info->ssid_len;
-
-	result->ie_len = pos - (u8 *)(result + 1);
-
-	tmp = os_realloc(res->res,
-			 (res->num + 1) * sizeof(struct wpa_scan_res *));
-	if (tmp == NULL) {
-		os_free(result);
-		return;
-	}
-	tmp[res->num++] = result;
-	res->res = tmp;
-}
-
-
-static struct wpa_scan_results * wpa_driver_osx_get_scan_results(void *priv)
-{
-	struct wpa_driver_osx_data *drv = priv;
-	struct wpa_scan_results *res;
-	size_t i, num;
-
-	if (drv->scan_results == NULL)
-		return 0;
-
-	num = CFArrayGetCount(drv->scan_results);
-
-	res = os_zalloc(sizeof(*res));
-	if (res == NULL)
-		return NULL;
-
-	for (i = 0; i < num; i++)
-		wpa_driver_osx_add_scan_entry(res, (WirelessNetworkInfo *)
-			CFDataGetBytePtr(CFArrayGetValueAtIndex(
-				drv->scan_results, i)));
-
-	return res;
-}
-
-
-static void wpa_driver_osx_assoc_timeout(void *eloop_ctx, void *timeout_ctx)
-{
-	struct wpa_driver_osx_data *drv = eloop_ctx;
-	u8 bssid[ETH_ALEN];
-	CFDictionaryRef ai;
-
-	if (wpa_driver_osx_get_bssid(drv, bssid) != 0) {
-		eloop_register_timeout(1, 0, wpa_driver_osx_assoc_timeout,
-				       drv, drv->ctx);
-		return;
-	}
-
-	ai = WirelessGetAssociationInfo(drv->wireless_ctx);
-	if (ai) {
-		wpa_driver_osx_dump_dict(ai, "WirelessGetAssociationInfo");
-		CFRelease(ai);
-	} else {
-		wpa_printf(MSG_DEBUG, "OSX: Failed to get association info");
-	}
-
-	wpa_supplicant_event(timeout_ctx, EVENT_ASSOC, NULL);
-}
-
-
-static int wpa_driver_osx_associate(void *priv,
-				    struct wpa_driver_associate_params *params)
-{
-	struct wpa_driver_osx_data *drv = priv;
-	WirelessError err;
-	CFDataRef ssid;
-	CFStringRef key;
-	int assoc_type;
-
-	ssid = CFDataCreate(kCFAllocatorDefault, params->ssid,
-			    params->ssid_len);
-	if (ssid == NULL)
-		return -1;
-
-	/* TODO: support for WEP */
-	if (params->key_mgmt_suite == KEY_MGMT_PSK) {
-		if (params->passphrase == NULL)
-			return -1;
-		key = CFStringCreateWithCString(kCFAllocatorDefault,
-						params->passphrase,
-						kCFStringEncodingISOLatin1);
-		if (key == NULL) {
-			CFRelease(ssid);
-			return -1;
-		}
-	} else
-		key = NULL;
-
-	if (params->key_mgmt_suite == KEY_MGMT_NONE)
-		assoc_type = 0;
-	else
-		assoc_type = 4;
-
-	wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate(type=%d key=%p)",
-		   assoc_type, key);
-	err = WirelessAssociate(drv->wireless_ctx, assoc_type, ssid, key);
-	CFRelease(ssid);
-	if (key)
-		CFRelease(key);
-	if (err) {
-		wpa_printf(MSG_DEBUG, "OSX: WirelessAssociate failed: 0x%08x",
-			   (unsigned int) err);
-		return -1;
-	}
-
-	/*
-	 * Driver is actually already associated; report association from an
-	 * eloop callback.
-	 */
-	eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx);
-	eloop_register_timeout(0, 0, wpa_driver_osx_assoc_timeout, drv,
-			       drv->ctx);
-
-	return 0;
-}
-
-
-static int wpa_driver_osx_set_key(const char *ifname, void *priv,
-				  enum wpa_alg alg, const u8 *addr,
-				  int key_idx, int set_tx, const u8 *seq,
-				  size_t seq_len, const u8 *key,
-				  size_t key_len)
-{
-	struct wpa_driver_osx_data *drv = priv;
-	WirelessError err;
-
-	if (alg == WPA_ALG_WEP) {
-		err = WirelessSetKey(drv->wireless_ctx, 1, key_idx, key_len,
-				     key);
-		if (err != 0) {
-			wpa_printf(MSG_DEBUG, "OSX: WirelessSetKey failed: "
-				   "0x%08x", (unsigned int) err);
-			return -1;
-		}
-
-		return 0;
-	}
-
-	if (alg == WPA_ALG_PMK) {
-		err = WirelessSetWPAKey(drv->wireless_ctx, 1, key_len, key);
-		if (err != 0) {
-			wpa_printf(MSG_DEBUG, "OSX: WirelessSetWPAKey failed: "
-				   "0x%08x", (unsigned int) err);
-			return -1;
-		}
-		return 0;
-	}
-
-	wpa_printf(MSG_DEBUG, "OSX: Unsupported set_key alg %d", alg);
-	return -1;
-}
-
-
-static int wpa_driver_osx_get_capa(void *priv, struct wpa_driver_capa *capa)
-{
-	os_memset(capa, 0, sizeof(*capa));
-
-	capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
-	capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 | WPA_DRIVER_CAPA_ENC_WEP104 |
-		WPA_DRIVER_CAPA_ENC_TKIP | WPA_DRIVER_CAPA_ENC_CCMP;
-	capa->auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED |
-		WPA_DRIVER_AUTH_LEAP;
-	capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
-
-	return 0;
-}
-
-
-static void * wpa_driver_osx_init(void *ctx, const char *ifname)
-{
-	struct wpa_driver_osx_data *drv;
-	WirelessError err;
-	u8 enabled, power;
-
-	if (!WirelessIsAvailable()) {
-		wpa_printf(MSG_ERROR, "OSX: No wireless interface available");
-		return NULL;
-	}
-
-	drv = os_zalloc(sizeof(*drv));
-	if (drv == NULL)
-		return NULL;
-	drv->ctx = ctx;
-	err = WirelessAttach(&drv->wireless_ctx, 0);
-	if (err) {
-		wpa_printf(MSG_ERROR, "OSX: WirelessAttach failed: %d",
-			   (int) err);
-		os_free(drv);
-		return NULL;
-	}
-
-	err = WirelessGetEnabled(drv->wireless_ctx, &enabled);
-	if (err)
-		wpa_printf(MSG_DEBUG, "OSX: WirelessGetEnabled failed: 0x%08x",
-			   (unsigned int) err);
-	err = WirelessGetPower(drv->wireless_ctx, &power);
-	if (err)
-		wpa_printf(MSG_DEBUG, "OSX: WirelessGetPower failed: 0x%08x",
-			   (unsigned int) err);
-
-	wpa_printf(MSG_DEBUG, "OSX: Enabled=%d Power=%d", enabled, power);
-
-	if (!enabled) {
-		err = WirelessSetEnabled(drv->wireless_ctx, 1);
-		if (err) {
-			wpa_printf(MSG_DEBUG, "OSX: WirelessSetEnabled failed:"
-				   " 0x%08x", (unsigned int) err);
-			WirelessDetach(drv->wireless_ctx);
-			os_free(drv);
-			return NULL;
-		}
-	}
-
-	if (!power) {
-		err = WirelessSetPower(drv->wireless_ctx, 1);
-		if (err) {
-			wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower failed: "
-				   "0x%08x", (unsigned int) err);
-			WirelessDetach(drv->wireless_ctx);
-			os_free(drv);
-			return NULL;
-		}
-	}
-
-	return drv;
-}
-
-
-static void wpa_driver_osx_deinit(void *priv)
-{
-	struct wpa_driver_osx_data *drv = priv;
-	WirelessError err;
-
-	eloop_cancel_timeout(wpa_driver_osx_scan_timeout, drv, drv->ctx);
-	eloop_cancel_timeout(wpa_driver_osx_assoc_timeout, drv, drv->ctx);
-
-	err = WirelessSetPower(drv->wireless_ctx, 0);
-	if (err) {
-		wpa_printf(MSG_DEBUG, "OSX: WirelessSetPower(0) failed: "
-			   "0x%08x", (unsigned int) err);
-	}
-
-	err = WirelessDetach(drv->wireless_ctx);
-	if (err) {
-		wpa_printf(MSG_DEBUG, "OSX: WirelessDetach failed: 0x%08x",
-			   (unsigned int) err);
-	}
-
-	if (drv->scan_results)
-		CFRelease(drv->scan_results);
-
-	os_free(drv);
-}
-
-
-const struct wpa_driver_ops wpa_driver_osx_ops = {
-	.name = "osx",
-	.desc = "Mac OS X Apple80211 driver",
-	.get_ssid = wpa_driver_osx_get_ssid,
-	.get_bssid = wpa_driver_osx_get_bssid,
-	.init = wpa_driver_osx_init,
-	.deinit = wpa_driver_osx_deinit,
-	.scan2 = wpa_driver_osx_scan,
-	.get_scan_results2 = wpa_driver_osx_get_scan_results,
-	.associate = wpa_driver_osx_associate,
-	.set_key = wpa_driver_osx_set_key,
-	.get_capa = wpa_driver_osx_get_capa,
-};
diff --git a/src/drivers/driver_ralink.c b/src/drivers/driver_ralink.c
deleted file mode 100644
index a1e27be..0000000
--- a/src/drivers/driver_ralink.c
+++ /dev/null
@@ -1,1498 +0,0 @@
-/*
- * WPA Supplicant - driver interaction with Ralink Wireless Client
- * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2007, Snowpin Lee <snowpin_lee@ralinktech.com.tw>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
- *
- */
-
-#include "includes.h"
-#include <sys/ioctl.h>
-
-#include "wireless_copy.h"
-#include "common.h"
-#include "driver.h"
-#include "l2_packet/l2_packet.h"
-#include "eloop.h"
-#include "common/ieee802_11_defs.h"
-#include "priv_netlink.h"
-#include "netlink.h"
-#include "linux_ioctl.h"
-#include "driver_ralink.h"
-
-static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx);
-
-#define MAX_SSID_LEN 32
-
-struct wpa_driver_ralink_data {
-	void *ctx;
-	int ioctl_sock;
-	struct netlink_data *netlink;
-	char ifname[IFNAMSIZ + 1];
-	u8 *assoc_req_ies;
-	size_t assoc_req_ies_len;
-	u8 *assoc_resp_ies;
-	size_t assoc_resp_ies_len;
-	int no_of_pmkid;
-	struct ndis_pmkid_entry *pmkid;
-	int we_version_compiled;
-	int ap_scan;
-	int scanning_done;
-	u8 g_driver_down;
-	BOOLEAN	bAddWepKey;
-};
-
-static int ralink_set_oid(struct wpa_driver_ralink_data *drv,
-			  unsigned short oid, char *data, int len)
-{
-	char *buf;
-	struct iwreq iwr;
-
-	buf = os_zalloc(len);
-	if (buf == NULL)
-		return -1;
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.data.flags = oid;
-	iwr.u.data.flags |= OID_GET_SET_TOGGLE;
-
-	if (data)
-		os_memcpy(buf, data, len);
-
-	iwr.u.data.pointer = (caddr_t) buf;
-	iwr.u.data.length = len;
-
-	if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: oid=0x%x len (%d) failed",
-			   __func__, oid, len);
-		os_free(buf);
-		return -1;
-	}
-	os_free(buf);
-	return 0;
-}
-
-static int
-ralink_get_new_driver_flag(struct wpa_driver_ralink_data *drv)
-{
-	struct iwreq iwr;
-	UCHAR enabled = 0;
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.data.pointer = (UCHAR*) &enabled;
-	iwr.u.data.flags = RT_OID_NEW_DRIVER;
-
-	if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: failed", __func__);
-		return 0;
-	}
-
-	return (enabled == 1) ? 1 : 0;
-}
-
-static int wpa_driver_ralink_get_bssid(void *priv, u8 *bssid)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	struct iwreq iwr;
-	int ret = 0;
-
-	if (drv->g_driver_down == 1)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-
-	if (ioctl(drv->ioctl_sock, SIOCGIWAP, &iwr) < 0) {
-		perror("ioctl[SIOCGIWAP]");
-		ret = -1;
-	}
-	os_memcpy(bssid, iwr.u.ap_addr.sa_data, ETH_ALEN);
-
-	return ret;
-}
-
-static int wpa_driver_ralink_get_ssid(void *priv, u8 *ssid)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-#if 0
-	struct wpa_supplicant *wpa_s = drv->ctx;
-	struct wpa_ssid *entry;
-#endif
-	int ssid_len;
-	u8 bssid[ETH_ALEN];
-	u8 ssid_str[MAX_SSID_LEN];
-	struct iwreq iwr;
-#if 0
-	int result = 0;
-#endif
-	int ret = 0;
-#if 0
-	BOOLEAN	ieee8021x_mode = FALSE;
-	BOOLEAN ieee8021x_required_key = FALSE;
-#endif
-
-	if (drv->g_driver_down == 1)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.essid.pointer = (caddr_t) ssid;
-	iwr.u.essid.length = 32;
-
-	if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) {
-		perror("ioctl[SIOCGIWESSID]");
-		ret = -1;
-	} else
-		ret = iwr.u.essid.length;
-
-	if (ret <= 0)
-		return ret;
-
-	ssid_len = ret;
-	os_memset(ssid_str, 0, MAX_SSID_LEN);
-	os_memcpy(ssid_str, ssid, ssid_len);
-
-	if (drv->ap_scan == 0) {
-		/* Read BSSID form driver */
-		if (wpa_driver_ralink_get_bssid(priv, bssid) < 0) {
-			wpa_printf(MSG_WARNING, "Could not read BSSID from "
-				   "driver.");
-			return ret;
-		}
-
-#if 0
-		entry = wpa_s->conf->ssid;
-		while (entry) {
-			if (!entry->disabled && ssid_len == entry->ssid_len &&
-			    os_memcmp(ssid_str, entry->ssid, ssid_len) == 0 &&
-			    (!entry->bssid_set ||
-			     os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) {
-				/* match the config of driver */
-				result = 1;
-				break;
-			}
-			entry = entry->next;
-		}
-
-		if (result) {
-			wpa_printf(MSG_DEBUG, "Ready to set 802.1x mode and "
-				   "ieee_required_keys parameters to driver");
-
-			/* set 802.1x mode and ieee_required_keys parameter */
-			if (entry->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
-				if ((entry->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | EAPOL_FLAG_REQUIRE_KEY_BROADCAST)))
-						ieee8021x_required_key = TRUE;
-				ieee8021x_mode = TRUE;
-			}
-
-			if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X, (char *) &ieee8021x_mode, sizeof(BOOLEAN)) < 0)
-			{
-				wpa_printf(MSG_DEBUG, "RALINK: Failed to set OID_802_11_SET_IEEE8021X(%d)", (int) ieee8021x_mode);
-			}
-			else
-			{
-				wpa_printf(MSG_DEBUG, "ieee8021x_mode is %s", ieee8021x_mode ? "TRUE" : "FALSE");
-			}
-
-			if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY, (char *) &ieee8021x_required_key, sizeof(BOOLEAN)) < 0)
-			{
-				wpa_printf(MSG_DEBUG, "ERROR: Failed to set OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)", (int) ieee8021x_required_key);
-			}
-			else
-			{
-				wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s and eapol_flag(%d)", ieee8021x_required_key ? "TRUE" : "FALSE",
-																								entry->eapol_flags);
-			}
-		}
-#endif
-	}
-
-	return ret;
-}
-
-static int wpa_driver_ralink_set_ssid(struct wpa_driver_ralink_data *drv,
-				      const u8 *ssid, size_t ssid_len)
-{
-	NDIS_802_11_SSID *buf;
-	int ret = 0;
-	struct iwreq iwr;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	buf = os_zalloc(sizeof(NDIS_802_11_SSID));
-	if (buf == NULL)
-		return -1;
-	os_memset(buf, 0, sizeof(buf));
-	buf->SsidLength = ssid_len;
-	os_memcpy(buf->Ssid, ssid, ssid_len);
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-
-	iwr.u.data.flags = OID_802_11_SSID;
-	iwr.u.data.flags |= OID_GET_SET_TOGGLE;
-	iwr.u.data.pointer = (caddr_t) buf;
-	iwr.u.data.length = sizeof(NDIS_802_11_SSID);
-
-	if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
-		perror("ioctl[RT_PRIV_IOCTL] -- OID_802_11_SSID");
-		ret = -1;
-	}
-	os_free(buf);
-	return ret;
-}
-
-static void wpa_driver_ralink_event_pmkid(struct wpa_driver_ralink_data *drv,
-					  const u8 *data, size_t data_len)
-{
-	NDIS_802_11_PMKID_CANDIDATE_LIST *pmkid;
-	size_t i;
-	union wpa_event_data event;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (data_len < 8) {
-		wpa_printf(MSG_DEBUG, "RALINK: Too short PMKID Candidate List "
-			   "Event (len=%lu)", (unsigned long) data_len);
-		return;
-	}
-	pmkid = (NDIS_802_11_PMKID_CANDIDATE_LIST *) data;
-	wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List Event - Version %d"
-		   " NumCandidates %d",
-		   (int) pmkid->Version, (int) pmkid->NumCandidates);
-
-	if (pmkid->Version != 1) {
-		wpa_printf(MSG_DEBUG, "RALINK: Unsupported PMKID Candidate "
-			   "List Version %d", (int) pmkid->Version);
-		return;
-	}
-
-	if (data_len < 8 + pmkid->NumCandidates * sizeof(PMKID_CANDIDATE)) {
-		wpa_printf(MSG_DEBUG, "RALINK: PMKID Candidate List "
-			   "underflow");
-
-		return;
-	}
-
-
-
-	os_memset(&event, 0, sizeof(event));
-	for (i = 0; i < pmkid->NumCandidates; i++) {
-		PMKID_CANDIDATE *p = &pmkid->CandidateList[i];
-		wpa_printf(MSG_DEBUG, "RALINK: %lu: " MACSTR " Flags 0x%x",
-			   (unsigned long) i, MAC2STR(p->BSSID),
-			   (int) p->Flags);
-		os_memcpy(event.pmkid_candidate.bssid, p->BSSID, ETH_ALEN);
-		event.pmkid_candidate.index = i;
-		event.pmkid_candidate.preauth =
-			p->Flags & NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED;
-		wpa_supplicant_event(drv->ctx, EVENT_PMKID_CANDIDATE,
-				     &event);
-	}
-}
-
-static int wpa_driver_ralink_set_pmkid(struct wpa_driver_ralink_data *drv)
-{
-	int len, count, i, ret;
-	struct ndis_pmkid_entry *entry;
-	NDIS_802_11_PMKID *p;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	count = 0;
-	entry = drv->pmkid;
-	while (entry) {
-		count++;
-		if (count >= drv->no_of_pmkid)
-			break;
-		entry = entry->next;
-	}
-	len = 8 + count * sizeof(BSSID_INFO);
-	p = os_zalloc(len);
-	if (p == NULL)
-		return -1;
-	p->Length = len;
-	p->BSSIDInfoCount = count;
-	entry = drv->pmkid;
-	for (i = 0; i < count; i++) {
-		os_memcpy(&p->BSSIDInfo[i].BSSID, entry->bssid, ETH_ALEN);
-		os_memcpy(&p->BSSIDInfo[i].PMKID, entry->pmkid, 16);
-		entry = entry->next;
-	}
-	wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID",
-		    (const u8 *) p, len);
-	ret = ralink_set_oid(drv, OID_802_11_PMKID, (char *) p, len);
-	os_free(p);
-	return ret;
-}
-
-static int wpa_driver_ralink_add_pmkid(void *priv, const u8 *bssid,
-				       const u8 *pmkid)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	struct ndis_pmkid_entry *entry, *prev;
-
-	if (drv->g_driver_down == 1)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (drv->no_of_pmkid == 0)
-		return 0;
-
-	prev = NULL;
-	entry = drv->pmkid;
-	while (entry) {
-		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0)
-			break;
-		prev = entry;
-		entry = entry->next;
-	}
-
-	if (entry) {
-		/* Replace existing entry for this BSSID and move it into the
-		 * beginning of the list. */
-		os_memcpy(entry->pmkid, pmkid, 16);
-		if (prev) {
-			prev->next = entry->next;
-			entry->next = drv->pmkid;
-			drv->pmkid = entry;
-		}
-	} else {
-		entry = os_malloc(sizeof(*entry));
-		if (entry) {
-			os_memcpy(entry->bssid, bssid, ETH_ALEN);
-			os_memcpy(entry->pmkid, pmkid, 16);
-			entry->next = drv->pmkid;
-			drv->pmkid = entry;
-		}
-	}
-
-	return wpa_driver_ralink_set_pmkid(drv);
-}
-
-
-static int wpa_driver_ralink_remove_pmkid(void *priv, const u8 *bssid,
-					  const u8 *pmkid)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	struct ndis_pmkid_entry *entry, *prev;
-
-	if (drv->g_driver_down == 1)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (drv->no_of_pmkid == 0)
-		return 0;
-
-	entry = drv->pmkid;
-	prev = NULL;
-	drv->pmkid = NULL;
-	while (entry) {
-		if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 &&
-		    os_memcmp(entry->pmkid, pmkid, 16) == 0) {
-			if (prev)
-				prev->next = entry->next;
-			else
-				drv->pmkid = entry->next;
-			os_free(entry);
-			break;
-		}
-		prev = entry;
-		entry = entry->next;
-	}
-	return wpa_driver_ralink_set_pmkid(drv);
-}
-
-
-static int wpa_driver_ralink_flush_pmkid(void *priv)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	NDIS_802_11_PMKID p;
-	struct ndis_pmkid_entry *pmkid, *prev;
-
-	if (drv->g_driver_down == 1)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (drv->no_of_pmkid == 0)
-		return 0;
-
-	pmkid = drv->pmkid;
-	drv->pmkid = NULL;
-	while (pmkid) {
-		prev = pmkid;
-		pmkid = pmkid->next;
-		os_free(prev);
-	}
-
-	os_memset(&p, 0, sizeof(p));
-	p.Length = 8;
-	p.BSSIDInfoCount = 0;
-	wpa_hexdump(MSG_MSGDUMP, "NDIS: OID_802_11_PMKID (flush)",
-		    (const u8 *) &p, 8);
-	return ralink_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8);
-}
-
-static void
-wpa_driver_ralink_event_wireless_custom(struct wpa_driver_ralink_data *drv,
-					void *ctx, char *custom)
-{
-	union wpa_event_data data;
-	u8 *req_ies = NULL, *resp_ies = NULL;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
-
-	os_memset(&data, 0, sizeof(data));
-	/* Host AP driver */
-	if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
-		/* receive a MICFAILURE report */
-		data.michael_mic_failure.unicast =
-			os_strstr(custom, " unicast") != NULL;
-		/* TODO: parse parameters(?) */
-		wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE, &data);
-	} else if (os_strncmp(custom, "ASSOCINFO_ReqIEs=", 17) == 0) {
-		/* receive assoc. req. IEs */
-		char *spos;
-		int bytes;
-
-		spos = custom + 17;
-		/*get IE's length */
-		/*
-		 * bytes = strlen(spos); ==> bug, bytes may less than original
-		 * size by using this way to get size. snowpin 20070312
-		 * if (!bytes)
-		 *	return;
-		 */
-		bytes = drv->assoc_req_ies_len;
-
-		req_ies = os_malloc(bytes);
-		if (req_ies == NULL)
-			return;
-		os_memcpy(req_ies, spos, bytes);
-		data.assoc_info.req_ies = req_ies;
-		data.assoc_info.req_ies_len = bytes;
-
-		/* skip the '\0' byte */
-		spos += bytes + 1;
-
-		data.assoc_info.resp_ies = NULL;
-		data.assoc_info.resp_ies_len = 0;
-
-		if (os_strncmp(spos, " RespIEs=", 9) == 0) {
-			/* receive assoc. resp. IEs */
-			spos += 9;
-			/* get IE's length */
-			bytes = os_strlen(spos);
-			if (!bytes)
-				goto done;
-
-			resp_ies = os_malloc(bytes);
-			if (resp_ies == NULL)
-				goto done;
-			os_memcpy(resp_ies, spos, bytes);
-			data.assoc_info.resp_ies = resp_ies;
-			data.assoc_info.resp_ies_len = bytes;
-		}
-
-		wpa_supplicant_event(ctx, EVENT_ASSOCINFO, &data);
-
-	done:
-		/* free allocated memory */
-		os_free(resp_ies);
-		os_free(req_ies);
-	}
-}
-
-static void ralink_interface_up(struct wpa_driver_ralink_data *drv)
-{
-	union wpa_event_data event;
-	int enable_wpa_supplicant = 0;
-	drv->g_driver_down = 0;
-	os_memset(&event, 0, sizeof(event));
-	os_snprintf(event.interface_status.ifname,
-		    sizeof(event.interface_status.ifname), "%s", drv->ifname);
-
-	event.interface_status.ievent = EVENT_INTERFACE_ADDED;
-	wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
-
-	if (drv->ap_scan == 1)
-		enable_wpa_supplicant = 1;
-	else
-		enable_wpa_supplicant = 2;
-	/* trigger driver support wpa_supplicant */
-	if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT,
-			   (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0)
-	{
-		wpa_printf(MSG_INFO, "RALINK: Failed to set "
-			   "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)",
-			   (int) enable_wpa_supplicant);
-		wpa_printf(MSG_ERROR, "ralink. Driver does not support "
-			   "wpa_supplicant");
-	}
-}
-
-static void
-wpa_driver_ralink_event_wireless(struct wpa_driver_ralink_data *drv,
-				 void *ctx, char *data, int len)
-{
-	struct iw_event iwe_buf, *iwe = &iwe_buf;
-	char *pos, *end, *custom, *buf, *assoc_info_buf, *info_pos;
-#if 0
-	BOOLEAN ieee8021x_required_key = FALSE;
-#endif
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	assoc_info_buf = info_pos = NULL;
-	pos = data;
-	end = data + len;
-
-	while (pos + IW_EV_LCP_LEN <= end) {
-		/* Event data may be unaligned, so make a local, aligned copy
-		 * before processing. */
-		os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
-		wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
-			   iwe->cmd, iwe->len);
-		if (iwe->len <= IW_EV_LCP_LEN)
-			return;
-
-		custom = pos + IW_EV_POINT_LEN;
-
-		if (drv->we_version_compiled > 18 && iwe->cmd == IWEVCUSTOM) {
-			/* WE-19 removed the pointer from struct iw_point */
-			char *dpos = (char *) &iwe_buf.u.data.length;
-			int dlen = dpos - (char *) &iwe_buf;
-			os_memcpy(dpos, pos + IW_EV_LCP_LEN,
-				  sizeof(struct iw_event) - dlen);
-		} else {
-			os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
-			custom += IW_EV_POINT_OFF;
-		}
-
-		switch (iwe->cmd) {
-		case IWEVCUSTOM:
-			if (custom + iwe->u.data.length > end)
-				return;
-			buf = os_malloc(iwe->u.data.length + 1);
-			if (buf == NULL)
-				return;
-			os_memcpy(buf, custom, iwe->u.data.length);
-			buf[iwe->u.data.length] = '\0';
-
-			if (drv->ap_scan == 1) {
-				if ((iwe->u.data.flags == RT_ASSOC_EVENT_FLAG)
-				    || (iwe->u.data.flags ==
-					RT_REQIE_EVENT_FLAG) ||
-				    (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG)
-				    || (iwe->u.data.flags ==
-					RT_ASSOCINFO_EVENT_FLAG)) {
-					if (drv->scanning_done == 0) {
-						os_free(buf);
-						return;
-					}
-				}
-			}
-
-			if (iwe->u.data.flags == RT_ASSOC_EVENT_FLAG) {
-				wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
-				wpa_printf(MSG_DEBUG, "Custom wireless event: "
-					   "receive ASSOCIATED_EVENT !!!");
-			} else if (iwe->u.data.flags == RT_REQIE_EVENT_FLAG) {
-				wpa_printf(MSG_DEBUG, "Custom wireless event: "
-					   "receive ReqIEs !!!");
-				drv->assoc_req_ies =
-					os_malloc(iwe->u.data.length);
-				if (drv->assoc_req_ies == NULL) {
-					os_free(buf);
-					return;
-				}
-
-				drv->assoc_req_ies_len = iwe->u.data.length;
-				os_memcpy(drv->assoc_req_ies, custom,
-					  iwe->u.data.length);
-			} else if (iwe->u.data.flags == RT_RESPIE_EVENT_FLAG) {
-				wpa_printf(MSG_DEBUG, "Custom wireless event: "
-					   "receive RespIEs !!!");
-				drv->assoc_resp_ies =
-					os_malloc(iwe->u.data.length);
-				if (drv->assoc_resp_ies == NULL) {
-					os_free(drv->assoc_req_ies);
-					drv->assoc_req_ies = NULL;
-					os_free(buf);
-					return;
-				}
-
-				drv->assoc_resp_ies_len = iwe->u.data.length;
-				os_memcpy(drv->assoc_resp_ies, custom,
-					  iwe->u.data.length);
-			} else if (iwe->u.data.flags ==
-				   RT_ASSOCINFO_EVENT_FLAG) {
-				wpa_printf(MSG_DEBUG, "Custom wireless event: "
-					   "receive ASSOCINFO_EVENT !!!");
-
-				assoc_info_buf =
-					os_zalloc(drv->assoc_req_ies_len +
-						  drv->assoc_resp_ies_len + 1);
-
-				if (assoc_info_buf == NULL) {
-					os_free(drv->assoc_req_ies);
-					drv->assoc_req_ies = NULL;
-					os_free(drv->assoc_resp_ies);
-					drv->assoc_resp_ies = NULL;
-					os_free(buf);
-					return;
-				}
-
-				if (drv->assoc_req_ies) {
-					os_memcpy(assoc_info_buf,
-						  drv->assoc_req_ies,
-						  drv->assoc_req_ies_len);
-				}
-				info_pos = assoc_info_buf +
-					drv->assoc_req_ies_len;
-				if (drv->assoc_resp_ies) {
-					os_memcpy(info_pos,
-						  drv->assoc_resp_ies,
-						  drv->assoc_resp_ies_len);
-				}
-				assoc_info_buf[drv->assoc_req_ies_len +
-					       drv->assoc_resp_ies_len] = '\0';
-				wpa_driver_ralink_event_wireless_custom(
-					drv, ctx, assoc_info_buf);
-				os_free(drv->assoc_req_ies);
-				drv->assoc_req_ies = NULL;
-				os_free(drv->assoc_resp_ies);
-				drv->assoc_resp_ies = NULL;
-				os_free(assoc_info_buf);
-			} else if (iwe->u.data.flags == RT_DISASSOC_EVENT_FLAG)
-			{
-				wpa_printf(MSG_DEBUG, "Custom wireless event: "
-					   "receive DISASSOCIATED_EVENT !!!");
-				wpa_supplicant_event(ctx, EVENT_DISASSOC,
-						     NULL);
-			} else if (iwe->u.data.flags == RT_PMKIDCAND_FLAG) {
-				wpa_printf(MSG_DEBUG, "Custom wireless event: "
-					   "receive PMKIDCAND_EVENT !!!");
-				wpa_driver_ralink_event_pmkid(
-					drv, (const u8 *) custom,
-					iwe->u.data.length);
-			} else if (iwe->u.data.flags == RT_INTERFACE_DOWN) {
-				drv->g_driver_down = 1;
-				eloop_terminate();
-			} else if (iwe->u.data.flags == RT_INTERFACE_UP) {
-				ralink_interface_up(drv);
-			} else {
-				wpa_driver_ralink_event_wireless_custom(
-					drv, ctx, buf);
-			}
-			os_free(buf);
-			break;
-		}
-
-		pos += iwe->len;
-	}
-}
-
-static void
-wpa_driver_ralink_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, 
-				    u8 *buf, size_t len)
-{
-	struct wpa_driver_ralink_data *drv = ctx;
-	int attrlen, rta_len;
-	struct rtattr *attr;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	wpa_hexdump(MSG_DEBUG, "ifi: ", (u8 *) ifi, sizeof(struct ifinfomsg));
-
-	attrlen = len;
-	wpa_printf(MSG_DEBUG, "attrlen=%d", attrlen);
-	attr = (struct rtattr *) buf;
-	wpa_hexdump(MSG_DEBUG, "attr1: ", (u8 *) attr, sizeof(struct rtattr));
-	rta_len = RTA_ALIGN(sizeof(struct rtattr));
-	wpa_hexdump(MSG_DEBUG, "attr2: ", (u8 *)attr,rta_len);
-	while (RTA_OK(attr, attrlen)) {
-		wpa_printf(MSG_DEBUG, "rta_type=%02x\n", attr->rta_type);
-		if (attr->rta_type == IFLA_WIRELESS) {
-			wpa_driver_ralink_event_wireless(
-				drv, ctx,
-				((char *) attr) + rta_len,
-				attr->rta_len - rta_len);
-		}
-		attr = RTA_NEXT(attr, attrlen);
-		wpa_hexdump(MSG_DEBUG, "attr3: ",
-			    (u8 *) attr, sizeof(struct rtattr));
-	}
-}
-
-static int
-ralink_get_we_version_compiled(struct wpa_driver_ralink_data *drv)
-{
-	struct iwreq iwr;
-	UINT we_version_compiled = 0;
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.data.pointer = (caddr_t) &we_version_compiled;
-	iwr.u.data.flags = RT_OID_WE_VERSION_COMPILED;
-
-	if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) < 0) {
-		wpa_printf(MSG_DEBUG, "%s: failed", __func__);
-		return -1;
-	}
-
-	drv->we_version_compiled = we_version_compiled;
-
-	return 0;
-}
-
-static void * wpa_driver_ralink_init(void *ctx, const char *ifname)
-{
-	int s;
-	struct wpa_driver_ralink_data *drv;
-	struct ifreq ifr;
-	UCHAR enable_wpa_supplicant = 0;
-	struct netlink_config *cfg;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	/* open socket to kernel */
-	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		perror("socket");
-		return NULL;
-	}
-	/* do it */
-	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
-
-	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
-		perror(ifr.ifr_name);
-		return NULL;
-	}
-
-	drv = os_zalloc(sizeof(*drv));
-	if (drv == NULL)
-		return NULL;
-
-	drv->scanning_done = 1;
-	drv->ap_scan = 1; /* for now - let's assume ap_scan=1 is used */
-	drv->ctx = ctx;
-	os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
-	drv->ioctl_sock = s;
-	drv->g_driver_down = 0;
-
-	cfg = os_zalloc(sizeof(*cfg));
-	if (cfg == NULL) {
-		close(drv->ioctl_sock);
-		os_free(drv);
-		return NULL;
-	}
-	cfg->ctx = drv;
-	cfg->newlink_cb = wpa_driver_ralink_event_rtm_newlink;
-	drv->netlink = netlink_init(cfg);
-	if (drv->netlink == NULL) {
-		os_free(cfg);
-		close(drv->ioctl_sock);
-		os_free(drv);
-		return NULL;
-	}
-
-	drv->no_of_pmkid = 4; /* Number of PMKID saved supported */
-
-	linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1);
-	ralink_get_we_version_compiled(drv);
-	wpa_driver_ralink_flush_pmkid(drv);
-
-	if (drv->ap_scan == 1)
-		enable_wpa_supplicant = 1;
-	else
-		enable_wpa_supplicant = 2;
-	/* trigger driver support wpa_supplicant */
-	if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT,
-			   (PCHAR) &enable_wpa_supplicant, sizeof(UCHAR)) < 0)
-	{
-		wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-			   "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)",
-			   (int) enable_wpa_supplicant);
-		wpa_printf(MSG_ERROR, "RALINK: Driver does not support "
-			   "wpa_supplicant");
-		close(s);
-		close(drv->ioctl_sock);
-		os_free(drv);
-		return NULL;
-	}
-
-	if (drv->ap_scan == 1)
-		drv->scanning_done = 0;
-
-	return drv;
-}
-
-static void wpa_driver_ralink_deinit(void *priv)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	UCHAR enable_wpa_supplicant;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	enable_wpa_supplicant = 0;
-
-	if (drv->g_driver_down == 0) {
-		/* trigger driver disable wpa_supplicant support */
-		if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT,
-				   (char *) &enable_wpa_supplicant,
-				   sizeof(BOOLEAN)) < 0) {
-			wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-				   "RT_OID_WPA_SUPPLICANT_SUPPORT(%d)",
-				   (int) enable_wpa_supplicant);
-		}
-
-		wpa_driver_ralink_flush_pmkid(drv);
-
-		sleep(1);
-		/* linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 0); */
-	}
-
-	eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx);
-	netlink_deinit(drv->netlink);
-	close(drv->ioctl_sock);
-	os_free(drv);
-}
-
-static void wpa_driver_ralink_scan_timeout(void *eloop_ctx, void *timeout_ctx)
-{
-	struct wpa_driver_ralink_data *drv = eloop_ctx;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
-	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
-
-	drv->scanning_done = 1;
-
-}
-
-static int wpa_driver_ralink_scan(void *priv,
-				  struct wpa_driver_scan_params *params)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	struct iwreq iwr;
-	int ret = 0;
-
-	if (drv->g_driver_down == 1)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-#if 0
-	if (ssid_len > IW_ESSID_MAX_SIZE) {
-		wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
-			   __FUNCTION__, (unsigned long) ssid_len);
-		return -1;
-	}
-
-	/* wpa_driver_ralink_set_ssid(drv, ssid, ssid_len); */
-#endif
-
-	if (ralink_set_oid(drv, RT_OID_WPS_PROBE_REQ_IE,
-			   (char *) params->extra_ies, params->extra_ies_len) <
-	    0) {
-		wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-			   "RT_OID_WPS_PROBE_REQ_IE");
-	}
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-
-	if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
-		perror("ioctl[SIOCSIWSCAN]");
-		ret = -1;
-	}
-
-	/* Not all drivers generate "scan completed" wireless event, so try to
-	 * read results after a timeout. */
-	eloop_cancel_timeout(wpa_driver_ralink_scan_timeout, drv, drv->ctx);
-	eloop_register_timeout(4, 0, wpa_driver_ralink_scan_timeout, drv,
-			       drv->ctx);
-
-	drv->scanning_done = 0;
-
-	return ret;
-}
-
-static struct wpa_scan_results *
-wpa_driver_ralink_get_scan_results(void *priv)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	UCHAR *buf = NULL;
-	size_t buf_len;
-	NDIS_802_11_BSSID_LIST_EX *wsr;
-	NDIS_WLAN_BSSID_EX *wbi;
-	struct iwreq iwr;
-	size_t ap_num;
-	u8 *pos;
-	struct wpa_scan_results *res;
-
-	if (drv->g_driver_down == 1)
-		return NULL;
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (drv->we_version_compiled >= 17)
-		buf_len = 8192;
-	else
-		buf_len = 4096;
-
-	for (;;) {
-		buf = os_zalloc(buf_len);
-		iwr.u.data.length = buf_len;
-		if (buf == NULL)
-			return NULL;
-
-		wsr = (NDIS_802_11_BSSID_LIST_EX *) buf;
-
-		wsr->NumberOfItems = 0;
-		os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-		iwr.u.data.pointer = (void *) buf;
-		iwr.u.data.flags = OID_802_11_BSSID_LIST;
-
-		if (ioctl(drv->ioctl_sock, RT_PRIV_IOCTL, &iwr) == 0)
-			break;
-
-		if (errno == E2BIG && buf_len < 65535) {
-			os_free(buf);
-			buf = NULL;
-			buf_len *= 2;
-			if (buf_len > 65535)
-				buf_len = 65535; /* 16-bit length field */
-			wpa_printf(MSG_DEBUG, "Scan results did not fit - "
-				   "trying larger buffer (%lu bytes)",
-				   (unsigned long) buf_len);
-		} else {
-			perror("ioctl[RT_PRIV_IOCTL]");
-			os_free(buf);
-			return NULL;
-		}
-	}
-
-	res = os_zalloc(sizeof(*res));
-	if (res == NULL) {
-		os_free(buf);
-		return NULL;
-	}
-
-	res->res = os_zalloc(wsr->NumberOfItems *
-			     sizeof(struct wpa_scan_res *));
-	if (res->res == NULL) {
-		os_free(res);
-		os_free(buf);
-		return NULL;
-	}
-
-	for (ap_num = 0, wbi = wsr->Bssid; ap_num < wsr->NumberOfItems;
-	     ++ap_num) {
-		struct wpa_scan_res *r = NULL;
-		size_t extra_len = 0, var_ie_len = 0;
-		u8 *pos2;
-
-		/* SSID data element */
-		extra_len += 2 + wbi->Ssid.SsidLength;
-		var_ie_len = wbi->IELength - sizeof(NDIS_802_11_FIXED_IEs);
-		r = os_zalloc(sizeof(*r) + extra_len + var_ie_len);
-		if (r == NULL)
-			break;
-		res->res[res->num++] = r;
-
-		wpa_printf(MSG_DEBUG, "SSID - %s", wbi->Ssid.Ssid);
-		/* get ie's */
-		wpa_hexdump(MSG_DEBUG, "RALINK: AP IEs",
-			    (u8 *) &wbi->IEs[0], wbi->IELength);
-
-		os_memcpy(r->bssid, wbi->MacAddress, ETH_ALEN);
-
-		extra_len += (2 + wbi->Ssid.SsidLength);
-		r->ie_len = extra_len + var_ie_len;
-		pos2 = (u8 *) (r + 1);
-
-		/*
-		 * Generate a fake SSID IE since the driver did not report
-		 * a full IE list.
-		 */
-		*pos2++ = WLAN_EID_SSID;
-		*pos2++ = wbi->Ssid.SsidLength;
-		os_memcpy(pos2, wbi->Ssid.Ssid, wbi->Ssid.SsidLength);
-		pos2 += wbi->Ssid.SsidLength;
-
-		r->freq = (wbi->Configuration.DSConfig / 1000);
-
-		pos = (u8 *) wbi + sizeof(*wbi) - 1;
-
-		pos += sizeof(NDIS_802_11_FIXED_IEs) - 2;
-		os_memcpy(&(r->caps), pos, 2);
-		pos += 2;
-
-		if (wbi->IELength > sizeof(NDIS_802_11_FIXED_IEs))
-			os_memcpy(pos2, pos, var_ie_len);
-
-		wbi = (NDIS_WLAN_BSSID_EX *) ((u8 *) wbi + wbi->Length);
-	}
-
-	os_free(buf);
-	return res;
-}
-
-static int ralink_set_auth_mode(struct wpa_driver_ralink_data *drv,
-				NDIS_802_11_AUTHENTICATION_MODE mode)
-{
-	NDIS_802_11_AUTHENTICATION_MODE auth_mode = mode;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (ralink_set_oid(drv, OID_802_11_AUTHENTICATION_MODE,
-			   (char *) &auth_mode, sizeof(auth_mode)) < 0) {
-		wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-			   "OID_802_11_AUTHENTICATION_MODE (%d)",
-			   (int) auth_mode);
-		return -1;
-	}
-	return 0;
-}
-
-static int ralink_set_encr_type(struct wpa_driver_ralink_data *drv,
-				NDIS_802_11_WEP_STATUS encr_type)
-{
-	NDIS_802_11_WEP_STATUS wep_status = encr_type;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (ralink_set_oid(drv, OID_802_11_WEP_STATUS,
-			   (char *) &wep_status, sizeof(wep_status)) < 0) {
-		wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-			   "OID_802_11_WEP_STATUS (%d)",
-			   (int) wep_status);
-		return -1;
-	}
-	return 0;
-}
-
-
-static int wpa_driver_ralink_remove_key(struct wpa_driver_ralink_data *drv,
-					int key_idx, const u8 *addr,
-					const u8 *bssid, int pairwise)
-{
-	NDIS_802_11_REMOVE_KEY rkey;
-	NDIS_802_11_KEY_INDEX _index;
-	int res, res2;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	os_memset(&rkey, 0, sizeof(rkey));
-
-	rkey.Length = sizeof(rkey);
-	rkey.KeyIndex = key_idx;
-
-	if (pairwise)
-		rkey.KeyIndex |= 1 << 30;
-
-	os_memcpy(rkey.BSSID, bssid, ETH_ALEN);
-
-	res = ralink_set_oid(drv, OID_802_11_REMOVE_KEY, (char *) &rkey,
-			     sizeof(rkey));
-
-	/* AlbertY@20060210 removed it */
-	if (0 /* !pairwise */) {
-		res2 = ralink_set_oid(drv, OID_802_11_REMOVE_WEP,
-				      (char *) &_index, sizeof(_index));
-	} else
-		res2 = 0;
-
-	if (res < 0 && res2 < 0)
-		return res;
-	return 0;
-}
-
-static int wpa_driver_ralink_add_wep(struct wpa_driver_ralink_data *drv,
-				     int pairwise, int key_idx, int set_tx,
-				     const u8 *key, size_t key_len)
-{
-	NDIS_802_11_WEP *wep;
-	size_t len;
-	int res;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	len = 12 + key_len;
-	wep = os_zalloc(len);
-	if (wep == NULL)
-		return -1;
-
-	wep->Length = len;
-	wep->KeyIndex = key_idx;
-
-	if (set_tx)
-		wep->KeyIndex |= 0x80000000;
-
-	wep->KeyLength = key_len;
-	os_memcpy(wep->KeyMaterial, key, key_len);
-
-	wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_WEP",
-			(const u8 *) wep, len);
-	res = ralink_set_oid(drv, OID_802_11_ADD_WEP, (char *) wep, len);
-
-	os_free(wep);
-
-	return res;
-}
-
-static int wpa_driver_ralink_set_key(const char *ifname, void *priv,
-				     enum wpa_alg alg, const u8 *addr,
-				     int key_idx, int set_tx,
-				     const u8 *seq, size_t seq_len,
-				     const u8 *key, size_t key_len)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	size_t len, i;
-	NDIS_802_11_KEY *nkey;
-	int res, pairwise;
-	u8 bssid[ETH_ALEN];
-
-	if (drv->g_driver_down == 1)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	drv->bAddWepKey = FALSE;
-
-	if (addr == NULL || is_broadcast_ether_addr(addr)) {
-		/* Group Key */
-		pairwise = 0;
-		wpa_driver_ralink_get_bssid(drv, bssid);
-	} else {
-		/* Pairwise Key */
-		pairwise = 1;
-		os_memcpy(bssid, addr, ETH_ALEN);
-	}
-
-	if (alg == WPA_ALG_NONE || key_len == 0) {
-		return wpa_driver_ralink_remove_key(drv, key_idx, addr, bssid,
-						    pairwise);
-	}
-
-	if (alg == WPA_ALG_WEP) {
-		drv->bAddWepKey = TRUE;
-		return wpa_driver_ralink_add_wep(drv, pairwise, key_idx,
-						 set_tx, key, key_len);
-	}
-
-	len = 12 + 6 + 6 + 8 + key_len;
-
-	nkey = os_zalloc(len);
-	if (nkey == NULL)
-		return -1;
-
-	nkey->Length = len;
-	nkey->KeyIndex = key_idx;
-
-	if (set_tx)
-		nkey->KeyIndex |= 1 << 31;
-
-	if (pairwise)
-		nkey->KeyIndex |= 1 << 30;
-
-	if (seq && seq_len)
-		nkey->KeyIndex |= 1 << 29;
-
-	nkey->KeyLength = key_len;
-	os_memcpy(nkey->BSSID, bssid, ETH_ALEN);
-
-	if (seq && seq_len) {
-		for (i = 0; i < seq_len; i++)
-			nkey->KeyRSC |= seq[i] << (i * 8);
-	}
-	if (alg == WPA_ALG_TKIP && key_len == 32) {
-		os_memcpy(nkey->KeyMaterial, key, 16);
-		os_memcpy(nkey->KeyMaterial + 16, key + 24, 8);
-		os_memcpy(nkey->KeyMaterial + 24, key + 16, 8);
-	} else {
-		os_memcpy(nkey->KeyMaterial, key, key_len);
-	}
-
-	wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
-		   "key_len=%lu", __FUNCTION__, alg, key_idx, set_tx,
-		   (unsigned long) seq_len, (unsigned long) key_len);
-
-	wpa_hexdump_key(MSG_MSGDUMP, "RALINK: OID_802_11_ADD_KEY",
-			(const u8 *) nkey, len);
-	res = ralink_set_oid(drv, OID_802_11_ADD_KEY, (char *) nkey, len);
-	os_free(nkey);
-
-	return res;
-}
-
-static int wpa_driver_ralink_disassociate(void *priv, const u8 *addr,
-					int reason_code)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-
-	if (drv->g_driver_down == 1)
-		return -1;
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-	if (ralink_set_oid(drv, OID_802_11_DISASSOCIATE, "    ", 4) < 0) {
-		wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-			   "OID_802_11_DISASSOCIATE");
-	}
-
-	return 0;
-}
-
-static int wpa_driver_ralink_deauthenticate(void *priv, const u8 *addr,
-					  int reason_code)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-
-	wpa_printf(MSG_DEBUG, "g_driver_down = %d", drv->g_driver_down);
-
-	if (drv->g_driver_down == 1)
-		return -1;
-
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-	if (ralink_get_new_driver_flag(drv) == 0) {
-		return wpa_driver_ralink_disassociate(priv, addr, reason_code);
-	} else {
-		MLME_DEAUTH_REQ_STRUCT mlme;
-		os_memset(&mlme, 0, sizeof(MLME_DEAUTH_REQ_STRUCT));
-		mlme.Reason = reason_code;
-		os_memcpy(mlme.Addr, addr, MAC_ADDR_LEN);
-		return ralink_set_oid(drv, OID_802_11_DEAUTHENTICATION,
-				      (char *) &mlme,
-				      sizeof(MLME_DEAUTH_REQ_STRUCT));
-	}
-}
-
-static int wpa_driver_ralink_set_gen_ie(void *priv, const u8 *ie,
-					size_t ie_len)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	struct iwreq iwr;
-	int ret = 0;
-
-	os_memset(&iwr, 0, sizeof(iwr));
-	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.data.pointer = (caddr_t) ie;
-	iwr.u.data.length = ie_len;
-
-	wpa_hexdump(MSG_DEBUG, "wpa_driver_ralink_set_gen_ie: ",
-		    (u8 *) ie, ie_len);
-
-	if (ioctl(drv->ioctl_sock, SIOCSIWGENIE, &iwr) < 0) {
-		perror("ioctl[SIOCSIWGENIE]");
-		ret = -1;
-	}
-
-	return ret;
-}
-
-static int
-wpa_driver_ralink_associate(void *priv,
-			    struct wpa_driver_associate_params *params)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-
-	NDIS_802_11_NETWORK_INFRASTRUCTURE mode;
-	NDIS_802_11_AUTHENTICATION_MODE auth_mode;
-	NDIS_802_11_WEP_STATUS encr;
-	BOOLEAN		ieee8021xMode;
-	BOOLEAN 	ieee8021x_required_key = TRUE;
-
-	if (drv->g_driver_down == 1)
-		return -1;
-	wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
-
-	if (params->mode == IEEE80211_MODE_IBSS)
-		mode = Ndis802_11IBSS;
-	else
-		mode = Ndis802_11Infrastructure;
-
-	if (ralink_set_oid(drv, OID_802_11_INFRASTRUCTURE_MODE,
-			 (char *) &mode, sizeof(mode)) < 0) {
-		wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-			   "OID_802_11_INFRASTRUCTURE_MODE (%d)",
-			   (int) mode);
-		/* Try to continue anyway */
-	}
-
-	if (params->key_mgmt_suite == KEY_MGMT_WPS) {
-		UCHAR enable_wps = 0x80;
-		/* trigger driver support wpa_supplicant */
-		if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT,
-				   (PCHAR) &enable_wps, sizeof(UCHAR)) < 0) {
-			wpa_printf(MSG_INFO, "RALINK: Failed to set "
-				   "RT_OID_WPA_SUPPLICANT_SUPPORT (%d)",
-				   (int) enable_wps);
-		}
-
-		wpa_driver_ralink_set_gen_ie(priv, params->wpa_ie,
-					     params->wpa_ie_len);
-
-		ralink_set_auth_mode(drv, Ndis802_11AuthModeOpen);
-
-		ralink_set_encr_type(drv, Ndis802_11EncryptionDisabled);
-	} else {
-#ifdef CONFIG_WPS
-		UCHAR enable_wpa_supplicant;
-
-		if (drv->ap_scan == 1)
-			enable_wpa_supplicant = 0x01;
-		else
-			enable_wpa_supplicant = 0x02;
-
-		/* trigger driver support wpa_supplicant */
-		if (ralink_set_oid(drv, RT_OID_WPA_SUPPLICANT_SUPPORT,
-				   (PCHAR) &enable_wpa_supplicant,
-				   sizeof(UCHAR)) < 0) {
-			wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-				   "RT_OID_WPA_SUPPLICANT_SUPPORT (%d)",
-				   (int) enable_wpa_supplicant);
-		}
-
-		wpa_driver_ralink_set_gen_ie(priv, (u8 *) "", 0);
-#endif /* CONFIG_WPS */
-
-		if (params->wpa_ie == NULL || params->wpa_ie_len == 0) {
-			if (params->auth_alg & WPA_AUTH_ALG_SHARED) {
-				if (params->auth_alg & WPA_AUTH_ALG_OPEN)
-					auth_mode = Ndis802_11AuthModeAutoSwitch;
-				else
-					auth_mode = Ndis802_11AuthModeShared;
-			} else
-				auth_mode = Ndis802_11AuthModeOpen;
-		} else if (params->wpa_ie[0] == WLAN_EID_RSN) {
-			if (params->key_mgmt_suite == KEY_MGMT_PSK)
-				auth_mode = Ndis802_11AuthModeWPA2PSK;
-			else
-				auth_mode = Ndis802_11AuthModeWPA2;
-		} else {
-			if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE)
-				auth_mode = Ndis802_11AuthModeWPANone;
-			else if (params->key_mgmt_suite == KEY_MGMT_PSK)
-				auth_mode = Ndis802_11AuthModeWPAPSK;
-			else
-				auth_mode = Ndis802_11AuthModeWPA;
-		}
-
-		switch (params->pairwise_suite) {
-		case CIPHER_CCMP:
-			encr = Ndis802_11Encryption3Enabled;
-			break;
-		case CIPHER_TKIP:
-			encr = Ndis802_11Encryption2Enabled;
-			break;
-		case CIPHER_WEP40:
-		case CIPHER_WEP104:
-			encr = Ndis802_11Encryption1Enabled;
-			break;
-		case CIPHER_NONE:
-			if (params->group_suite == CIPHER_CCMP)
-				encr = Ndis802_11Encryption3Enabled;
-			else if (params->group_suite == CIPHER_TKIP)
-				encr = Ndis802_11Encryption2Enabled;
-			else
-				encr = Ndis802_11EncryptionDisabled;
-			break;
-		default:
-			encr = Ndis802_11EncryptionDisabled;
-			break;
-		}
-
-		ralink_set_auth_mode(drv, auth_mode);
-
-		/* notify driver that IEEE8021x mode is enabled */
-		if (params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) {
-			ieee8021xMode = TRUE;
-			if (drv->bAddWepKey)
-				ieee8021x_required_key = FALSE;
-		} else
-			ieee8021xMode = FALSE;
-
-		if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X_REQUIRE_KEY,
-				   (char *) &ieee8021x_required_key,
-				   sizeof(BOOLEAN)) < 0) {
-			wpa_printf(MSG_DEBUG, "ERROR: Failed to set "
-				   "OID_802_11_SET_IEEE8021X_REQUIRE_KEY(%d)",
-				   (int) ieee8021x_required_key);
-		} else {
-			wpa_printf(MSG_DEBUG, "ieee8021x_required_key is %s",
-				   ieee8021x_required_key ? "TRUE" : "FALSE");
-		}
-
-		if (ralink_set_oid(drv, OID_802_11_SET_IEEE8021X,
-				   (char *) &ieee8021xMode, sizeof(BOOLEAN)) <
-		    0) {
-			wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-				   "OID_802_11_SET_IEEE8021X(%d)",
-				   (int) ieee8021xMode);
-		}
-
-		ralink_set_encr_type(drv, encr);
-
-		if ((ieee8021xMode == FALSE) &&
-		    (encr == Ndis802_11Encryption1Enabled)) {
-			/* static WEP */
-			int enabled = 0;
-			if (ralink_set_oid(drv, OID_802_11_DROP_UNENCRYPTED,
-					   (char *) &enabled, sizeof(enabled))
-			    < 0) {
-				wpa_printf(MSG_DEBUG, "RALINK: Failed to set "
-					   "OID_802_11_DROP_UNENCRYPTED(%d)",
-					   (int) encr);
-			}
-		}
-	}
-
-	return wpa_driver_ralink_set_ssid(drv, params->ssid, params->ssid_len);
-}
-
-static int
-wpa_driver_ralink_set_countermeasures(void *priv, int enabled)
-{
-	struct wpa_driver_ralink_data *drv = priv;
-	if (drv->g_driver_down == 1)
-		return -1;
-	wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
-	return ralink_set_oid(drv, OID_SET_COUNTERMEASURES, (char *) &enabled,
-			      sizeof(int));
-}
-
-const struct wpa_driver_ops wpa_driver_ralink_ops = {
-	.name = "ralink",
-	.desc = "Ralink Wireless Client driver",
-	.get_bssid = wpa_driver_ralink_get_bssid,
-	.get_ssid = wpa_driver_ralink_get_ssid,
-	.set_key = wpa_driver_ralink_set_key,
-	.init = wpa_driver_ralink_init,
-	.deinit = wpa_driver_ralink_deinit,
-	.set_countermeasures	= wpa_driver_ralink_set_countermeasures,
-	.scan2 = wpa_driver_ralink_scan,
-	.get_scan_results2 = wpa_driver_ralink_get_scan_results,
-	.deauthenticate = wpa_driver_ralink_deauthenticate,
-	.disassociate = wpa_driver_ralink_disassociate,
-	.associate = wpa_driver_ralink_associate,
-	.add_pmkid = wpa_driver_ralink_add_pmkid,
-	.remove_pmkid = wpa_driver_ralink_remove_pmkid,
-	.flush_pmkid = wpa_driver_ralink_flush_pmkid,
-};
diff --git a/src/drivers/driver_ralink.h b/src/drivers/driver_ralink.h
deleted file mode 100644
index d13df28..0000000
--- a/src/drivers/driver_ralink.h
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * WPA Supplicant - driver_ralink exported functions
- * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2007, Snowpin Lee <snowpin_lee@ralinktech.com.tw>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
- */
-
-// Ralink defined OIDs
-#if WIRELESS_EXT <= 11
-#ifndef SIOCDEVPRIVATE
-#define SIOCDEVPRIVATE                              0x8BE0
-#endif
-#define SIOCIWFIRSTPRIV								SIOCDEVPRIVATE
-#endif
-
-#define RT_PRIV_IOCTL								(SIOCIWFIRSTPRIV + 0x0E)  
-#define RTPRIV_IOCTL_SET							(SIOCIWFIRSTPRIV + 0x02)
-
-// IEEE 802.11 OIDs  &  Ralink defined OIDs  ******
-
-// (RaConfig Set/QueryInform) ==>
-#define OID_GET_SET_TOGGLE							0x8000
-
-#define OID_802_11_ADD_WEP                          0x0112
-#define OID_802_11_REMOVE_WEP                       0x0113
-#define OID_802_11_DISASSOCIATE                     0x0114
-#define OID_802_11_PRIVACY_FILTER                   0x0118
-#define OID_802_11_ASSOCIATION_INFORMATION          0x011E
-#define OID_802_11_BSSID_LIST_SCAN                  0x0508
-#define OID_802_11_SSID                             0x0509
-#define OID_802_11_BSSID                            0x050A
-#define OID_802_11_WEP_STATUS                       0x0510
-#define OID_802_11_AUTHENTICATION_MODE              0x0511
-#define OID_802_11_INFRASTRUCTURE_MODE              0x0512
-#define OID_802_11_TX_POWER_LEVEL                   0x0517
-#define OID_802_11_REMOVE_KEY                       0x0519
-#define OID_802_11_ADD_KEY                          0x0520
-#define OID_802_11_DEAUTHENTICATION                 0x0526
-#define OID_802_11_DROP_UNENCRYPTED                 0x0527
-#define OID_802_11_BSSID_LIST                       0x0609
-#define OID_802_3_CURRENT_ADDRESS                   0x060A
-#define OID_SET_COUNTERMEASURES                     0x0616
-#define OID_802_11_SET_IEEE8021X                    0x0617	// For IEEE8021x mode 
-#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY        0x0618  // For DynamicWEP in IEEE802.1x mode
-#define OID_802_11_PMKID                            0x0620
-#define RT_OID_WPA_SUPPLICANT_SUPPORT               0x0621  // for trigger driver enable/disable wpa_supplicant support 
-#define RT_OID_WE_VERSION_COMPILED                  0x0622
-#define RT_OID_NEW_DRIVER                           0x0623
-#define RT_OID_WPS_PROBE_REQ_IE						0x0625
-
-#define PACKED  __attribute__ ((packed))
-
-//wpa_supplicant event flags
-#define	RT_ASSOC_EVENT_FLAG                         0x0101
-#define	RT_DISASSOC_EVENT_FLAG                      0x0102
-#define	RT_REQIE_EVENT_FLAG                         0x0103
-#define	RT_RESPIE_EVENT_FLAG                        0x0104
-#define	RT_ASSOCINFO_EVENT_FLAG                     0x0105
-#define RT_PMKIDCAND_FLAG                           0x0106
-#define RT_INTERFACE_DOWN                           0x0107
-#define RT_INTERFACE_UP                           	0x0108
-
-//
-// IEEE 802.11 Structures and definitions
-//
-// new types for Media Specific Indications
-
-#ifndef ULONG
-#define CHAR            char
-#define INT             int
-#define SHORT           int
-#define UINT            u32
-#undef  ULONG           
-//#define ULONG           u32
-#define ULONG           unsigned long /* 32-bit in 32-bit CPU or 64-bit in 64-bit CPU */
-#define USHORT          unsigned short
-#define UCHAR           unsigned char
-
-#define uint32		u32
-#define uint8		u8
-
-
-#define BOOLEAN         u8
-//#define LARGE_INTEGER s64
-#define VOID            void
-#define LONG            long
-#define LONGLONG        s64
-#define ULONGLONG       u64
-typedef VOID            *PVOID;
-typedef CHAR            *PCHAR;
-typedef UCHAR           *PUCHAR;
-typedef USHORT          *PUSHORT;
-typedef LONG            *PLONG;
-typedef ULONG           *PULONG;
-
-typedef union _LARGE_INTEGER {
-    struct {
-        ULONG LowPart;
-        LONG HighPart;
-    }vv;
-    struct {
-        ULONG LowPart;
-        LONG HighPart;
-    } u;
-    s64 QuadPart;
-} LARGE_INTEGER;
-
-#endif
-
-#define NDIS_802_11_LENGTH_SSID         32
-#define NDIS_802_11_LENGTH_RATES        8
-#define NDIS_802_11_LENGTH_RATES_EX     16
-#define MAX_LEN_OF_SSID                 32
-#define MAC_ADDR_LEN                    6
-
-typedef UCHAR   NDIS_802_11_MAC_ADDRESS[6];
-
-// mask for authentication/integrity fields
-#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS        0x0f
-
-#define NDIS_802_11_AUTH_REQUEST_REAUTH             0x01
-#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE          0x02
-#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR     0x06
-#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR        0x0E
-
-// Added new types for OFDM 5G and 2.4G
-typedef enum _NDIS_802_11_NETWORK_TYPE
-{
-    Ndis802_11FH, 
-    Ndis802_11DS, 
-    Ndis802_11OFDM5,
-    Ndis802_11OFDM24,
-    Ndis802_11Automode,
-    Ndis802_11NetworkTypeMax    // not a real type, defined as an upper bound
-} NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE;
-
-//
-// Received Signal Strength Indication
-//
-typedef LONG    NDIS_802_11_RSSI;           // in dBm
-
-typedef struct _NDIS_802_11_CONFIGURATION_FH
-{
-   ULONG           Length;            // Length of structure
-   ULONG           HopPattern;        // As defined by 802.11, MSB set 
-   ULONG           HopSet;            // to one if non-802.11
-   ULONG           DwellTime;         // units are Kusec
-} NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH;
-
-typedef struct _NDIS_802_11_CONFIGURATION
-{
-   ULONG                           Length;             // Length of structure
-   ULONG                           BeaconPeriod;       // units are Kusec
-   ULONG                           ATIMWindow;         // units are Kusec
-   ULONG                           DSConfig;           // Frequency, units are kHz
-   NDIS_802_11_CONFIGURATION_FH    FHConfig;
-} NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION;
-
-typedef  ULONG  NDIS_802_11_KEY_INDEX;
-typedef ULONGLONG   NDIS_802_11_KEY_RSC;
-
-// Key mapping keys require a BSSID
-typedef struct _NDIS_802_11_KEY
-{
-    UINT           Length;             // Length of this structure
-    UINT           KeyIndex;           
-    UINT           KeyLength;          // length of key in bytes
-    NDIS_802_11_MAC_ADDRESS BSSID;
-    NDIS_802_11_KEY_RSC KeyRSC;
-    UCHAR           KeyMaterial[1];     // variable length depending on above field
-} NDIS_802_11_KEY, *PNDIS_802_11_KEY;
-
-typedef struct _NDIS_802_11_REMOVE_KEY
-{
-    UINT                   Length;        // Length of this structure
-    UINT                   KeyIndex;           
-    NDIS_802_11_MAC_ADDRESS BSSID;      
-} NDIS_802_11_REMOVE_KEY, *PNDIS_802_11_REMOVE_KEY;
-
-typedef struct PACKED _NDIS_802_11_WEP
-{
-   UINT     Length;        // Length of this structure
-   UINT           KeyIndex;           // 0 is the per-client key, 1-N are the
-                                        // global keys
-   UINT     KeyLength;     // length of key in bytes
-   UCHAR     KeyMaterial[1];// variable length depending on above field
-} NDIS_802_11_WEP, *PNDIS_802_11_WEP;
-
-
-typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE
-{
-   Ndis802_11IBSS,
-   Ndis802_11Infrastructure,
-   Ndis802_11AutoUnknown,
-   Ndis802_11InfrastructureMax     // Not a real value, defined as upper bound
-} NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE;
-
-// PMKID Structures
-typedef UCHAR   NDIS_802_11_PMKID_VALUE[16];
-
-typedef struct _BSSID_INFO
-{
-	NDIS_802_11_MAC_ADDRESS BSSID;
-	NDIS_802_11_PMKID_VALUE PMKID;
-} BSSID_INFO, *PBSSID_INFO;
-
-typedef struct _NDIS_802_11_PMKID
-{
-	ULONG Length;
-	ULONG BSSIDInfoCount;
-	BSSID_INFO BSSIDInfo[1];
-} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID;
-
-//Added new types for PMKID Candidate lists.
-typedef struct _PMKID_CANDIDATE {
-	NDIS_802_11_MAC_ADDRESS BSSID;
-	ULONG Flags;
-} PMKID_CANDIDATE, *PPMKID_CANDIDATE;
-
-typedef struct _NDIS_802_11_PMKID_CANDIDATE_LIST
-{
-	ULONG Version;       // Version of the structure
-	ULONG NumCandidates; // No. of pmkid candidates
-	PMKID_CANDIDATE CandidateList[1];
-} NDIS_802_11_PMKID_CANDIDATE_LIST, *PNDIS_802_11_PMKID_CANDIDATE_LIST;
-
-//Flags for PMKID Candidate list structure
-#define NDIS_802_11_PMKID_CANDIDATE_PREAUTH_ENABLED	0x01
-
-// Add new authentication modes
-typedef enum _NDIS_802_11_AUTHENTICATION_MODE
-{
-   Ndis802_11AuthModeOpen,
-   Ndis802_11AuthModeShared,
-   Ndis802_11AuthModeAutoSwitch,
-   Ndis802_11AuthModeWPA,
-   Ndis802_11AuthModeWPAPSK,
-   Ndis802_11AuthModeWPANone,
-   Ndis802_11AuthModeWPA2,
-   Ndis802_11AuthModeWPA2PSK,    
-   Ndis802_11AuthModeMax           // Not a real mode, defined as upper bound
-} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE;
-
-typedef UCHAR  NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES];        // Set of 8 data rates
-typedef UCHAR  NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];  // Set of 16 data rates
-
-typedef struct PACKED _NDIS_802_11_SSID 
-{
-    INT   SsidLength;         // length of SSID field below, in bytes;
-                                // this can be zero.
-    UCHAR   Ssid[NDIS_802_11_LENGTH_SSID];           // SSID information field
-} NDIS_802_11_SSID, *PNDIS_802_11_SSID;
-
-
-typedef struct PACKED _NDIS_WLAN_BSSID
-{
-   ULONG                               Length;     // Length of this structure
-   NDIS_802_11_MAC_ADDRESS             MacAddress; // BSSID
-   UCHAR                               Reserved[2];
-   NDIS_802_11_SSID                    Ssid;       // SSID
-   ULONG                               Privacy;    // WEP encryption requirement
-    NDIS_802_11_RSSI                    Rssi;               // receive signal
-                                                            // strength in dBm
-   NDIS_802_11_NETWORK_TYPE            NetworkTypeInUse;
-   NDIS_802_11_CONFIGURATION           Configuration;
-   NDIS_802_11_NETWORK_INFRASTRUCTURE  InfrastructureMode;
-   NDIS_802_11_RATES                   SupportedRates;
-} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID;
-
-typedef struct PACKED _NDIS_802_11_BSSID_LIST
-{
-   UINT             NumberOfItems;      // in list below, at least 1
-   NDIS_WLAN_BSSID Bssid[1];
-} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST;
-
-// Added Capabilities, IELength and IEs for each BSSID
-typedef struct PACKED _NDIS_WLAN_BSSID_EX
-{
-    ULONG                               Length;             // Length of this structure
-    NDIS_802_11_MAC_ADDRESS             MacAddress;         // BSSID
-    UCHAR                               Reserved[2];
-    NDIS_802_11_SSID                    Ssid;               // SSID
-    UINT                                Privacy;            // WEP encryption requirement
-    NDIS_802_11_RSSI                    Rssi;               // receive signal
-                                                            // strength in dBm
-    NDIS_802_11_NETWORK_TYPE            NetworkTypeInUse;
-    NDIS_802_11_CONFIGURATION           Configuration;
-    NDIS_802_11_NETWORK_INFRASTRUCTURE  InfrastructureMode;
-    NDIS_802_11_RATES_EX                SupportedRates;
-    ULONG                               IELength;
-    UCHAR                               IEs[1];
-} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX;
-
-typedef struct PACKED _NDIS_802_11_BSSID_LIST_EX
-{
-    UINT                   NumberOfItems;      // in list below, at least 1
-    NDIS_WLAN_BSSID_EX      Bssid[1];
-} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX;
-
-typedef struct PACKED _NDIS_802_11_FIXED_IEs 
-{
-    UCHAR Timestamp[8];
-    USHORT BeaconInterval;
-    USHORT Capabilities;
-} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs;
-
-// Added new encryption types
-// Also aliased typedef to new name
-typedef enum _NDIS_802_11_WEP_STATUS
-{
-   Ndis802_11WEPEnabled,
-   Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
-   Ndis802_11WEPDisabled,
-   Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
-   Ndis802_11WEPKeyAbsent,
-   Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
-   Ndis802_11WEPNotSupported,
-   Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
-   Ndis802_11Encryption2Enabled,
-   Ndis802_11Encryption2KeyAbsent,
-   Ndis802_11Encryption3Enabled,
-   Ndis802_11Encryption3KeyAbsent
-} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS,
-  NDIS_802_11_ENCRYPTION_STATUS, *PNDIS_802_11_ENCRYPTION_STATUS;
-
-typedef enum _NDIS_802_11_RELOAD_DEFAULTS
-{
-   Ndis802_11ReloadWEPKeys
-} NDIS_802_11_RELOAD_DEFAULTS, *PNDIS_802_11_RELOAD_DEFAULTS;
-
-#define NDIS_802_11_AI_REQFI_CAPABILITIES      1
-#define NDIS_802_11_AI_REQFI_LISTENINTERVAL    2
-#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS  4
-
-#define NDIS_802_11_AI_RESFI_CAPABILITIES      1
-#define NDIS_802_11_AI_RESFI_STATUSCODE        2
-#define NDIS_802_11_AI_RESFI_ASSOCIATIONID     4
-
-typedef struct _NDIS_802_11_AI_REQFI
-{
-    USHORT Capabilities;
-    USHORT ListenInterval;
-    NDIS_802_11_MAC_ADDRESS  CurrentAPAddress;
-} NDIS_802_11_AI_REQFI, *PNDIS_802_11_AI_REQFI;
-
-typedef struct _NDIS_802_11_AI_RESFI
-{
-    USHORT Capabilities;
-    USHORT StatusCode;
-    USHORT AssociationId;
-} NDIS_802_11_AI_RESFI, *PNDIS_802_11_AI_RESFI;
-
-typedef struct _NDIS_802_11_ASSOCIATION_INFORMATION
-{
-    ULONG                   Length;
-    USHORT                  AvailableRequestFixedIEs;
-    NDIS_802_11_AI_REQFI    RequestFixedIEs;
-    ULONG                   RequestIELength;
-    ULONG                   OffsetRequestIEs;
-    USHORT                  AvailableResponseFixedIEs;
-    NDIS_802_11_AI_RESFI    ResponseFixedIEs;
-    ULONG                   ResponseIELength;
-    ULONG                   OffsetResponseIEs;
-} NDIS_802_11_ASSOCIATION_INFORMATION, *PNDIS_802_11_ASSOCIATION_INFORMATION;
-
-struct ndis_pmkid_entry {
-	struct ndis_pmkid_entry *next;
-	u8 bssid[ETH_ALEN];
-	u8 pmkid[16];
-};
-
-typedef struct _MLME_DEAUTH_REQ_STRUCT {
-    UCHAR        Addr[MAC_ADDR_LEN];
-    USHORT       Reason;
-} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT;
diff --git a/src/drivers/driver_roboswitch.c b/src/drivers/driver_roboswitch.c
index c014b96..61b75b1 100644
--- a/src/drivers/driver_roboswitch.c
+++ b/src/drivers/driver_roboswitch.c
@@ -364,7 +364,7 @@
 	/* copy ifname and take a pointer to the second to last character */
 	sep = drv->ifname +
 	      os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)) - 2;
-	/* find the '.' seperating <interface> and <vlan> */
+	/* find the '.' separating <interface> and <vlan> */
 	while (sep > drv->ifname && *sep != '.') sep--;
 	if (sep <= drv->ifname) {
 		wpa_printf(MSG_INFO, "%s: No <interface>.<vlan> pair in "
diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c
index 6bfa46d..f8e314b 100644
--- a/src/drivers/driver_test.c
+++ b/src/drivers/driver_test.c
@@ -89,7 +89,6 @@
 	int use_associnfo;
 	u8 assoc_wpa_ie[80];
 	size_t assoc_wpa_ie_len;
-	int use_mlme;
 	int associated;
 	u8 *probe_req_ie;
 	size_t probe_req_ie_len;
@@ -117,6 +116,7 @@
 	u8 pending_action_dst[ETH_ALEN];
 	u8 pending_action_bssid[ETH_ALEN];
 	unsigned int pending_action_freq;
+	unsigned int pending_action_no_cck;
 	unsigned int pending_listen_freq;
 	unsigned int pending_listen_duration;
 	int pending_p2p_scan;
@@ -309,7 +309,7 @@
 
 
 static int wpa_driver_test_send_mlme(void *priv, const u8 *data,
-				     size_t data_len)
+				     size_t data_len, int noack)
 {
 	struct test_driver_bss *dbss = priv;
 	struct wpa_driver_test_data *drv = dbss->drv;
@@ -561,7 +561,7 @@
 		wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event);
 #ifdef CONFIG_P2P
 		if (drv->p2p)
-			p2p_probe_req_rx(drv->p2p, sa, ie, ielen);
+			p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
 #endif /* CONFIG_P2P */
 	}
 
@@ -1102,13 +1102,6 @@
 }
 
 
-static int test_driver_valid_bss_mask(void *priv, const u8 *addr,
-				      const u8 *mask)
-{
-	return 0;
-}
-
-
 static int test_driver_set_ssid(void *priv, const u8 *buf, int len)
 {
 	struct test_driver_bss *bss = priv;
@@ -1232,6 +1225,7 @@
 		return NULL;
 	drv->ap = 1;
 	bss = dl_list_first(&drv->bss, struct test_driver_bss, list);
+	drv->global = params->global_priv;
 
 	bss->bss_ctx = hapd;
 	os_memcpy(bss->bssid, drv->own_addr, ETH_ALEN);
@@ -1966,6 +1960,8 @@
 		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) {
 			os_memset(&event, 0, sizeof(event));
 			event.rx_probe_req.sa = mgmt->sa;
+			event.rx_probe_req.da = mgmt->da;
+			event.rx_probe_req.bssid = mgmt->bssid;
 			event.rx_probe_req.ie = mgmt->u.probe_req.variable;
 			event.rx_probe_req.ie_len =
 				data_len - (mgmt->u.probe_req.variable - data);
@@ -1974,6 +1970,7 @@
 #ifdef CONFIG_P2P
 			if (drv->p2p)
 				p2p_probe_req_rx(drv->p2p, mgmt->sa,
+						 mgmt->da, mgmt->bssid,
 						 event.rx_probe_req.ie,
 						 event.rx_probe_req.ie_len);
 #endif /* CONFIG_P2P */
@@ -2028,7 +2025,7 @@
 			ielen = 0;
 		drv->probe_from = from;
 		drv->probe_from_len = fromlen;
-		p2p_probe_req_rx(drv->p2p, sa, ie, ielen);
+		p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
 		drv->probe_from = NULL;
 	}
 #endif /* CONFIG_P2P */
@@ -2390,13 +2387,6 @@
 		drv->use_associnfo = 1;
 	}
 
-#ifdef CONFIG_CLIENT_MLME
-	if (os_strstr(param, "use_mlme=1")) {
-		wpa_printf(MSG_DEBUG, "test_driver: Use internal MLME");
-		drv->use_mlme = 1;
-	}
-#endif /* CONFIG_CLIENT_MLME */
-
 	if (os_strstr(param, "p2p_mgmt=1")) {
 		wpa_printf(MSG_DEBUG, "test_driver: Use internal P2P "
 			   "management");
@@ -2510,8 +2500,6 @@
 	capa->auth = WPA_DRIVER_AUTH_OPEN |
 		WPA_DRIVER_AUTH_SHARED |
 		WPA_DRIVER_AUTH_LEAP;
-	if (drv->use_mlme)
-		capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME;
 	if (drv->p2p)
 		capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT;
 	capa->flags |= WPA_DRIVER_FLAGS_AP;
@@ -2541,50 +2529,6 @@
 }
 
 
-static int wpa_driver_test_set_channel(void *priv,
-				       enum hostapd_hw_mode phymode,
-				       int chan, int freq)
-{
-	struct test_driver_bss *dbss = priv;
-	struct wpa_driver_test_data *drv = dbss->drv;
-	wpa_printf(MSG_DEBUG, "%s: phymode=%d chan=%d freq=%d",
-		   __func__, phymode, chan, freq);
-	drv->current_freq = freq;
-	return 0;
-}
-
-
-static int wpa_driver_test_mlme_add_sta(void *priv, const u8 *addr,
-					const u8 *supp_rates,
-					size_t supp_rates_len)
-{
-	wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr));
-	return 0;
-}
-
-
-static int wpa_driver_test_mlme_remove_sta(void *priv, const u8 *addr)
-{
-	wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr));
-	return 0;
-}
-
-
-static int wpa_driver_test_set_ssid(void *priv, const u8 *ssid,
-				    size_t ssid_len)
-{
-	wpa_printf(MSG_DEBUG, "%s", __func__);
-	return 0;
-}
-
-
-static int wpa_driver_test_set_bssid(void *priv, const u8 *bssid)
-{
-	wpa_printf(MSG_DEBUG, "%s: bssid=" MACSTR, __func__, MAC2STR(bssid));
-	return 0;
-}
-
-
 static void * wpa_driver_test_global_init(void)
 {
 	struct wpa_driver_test_global *global;
@@ -2727,7 +2671,8 @@
 				       unsigned int wait,
 				       const u8 *dst, const u8 *src,
 				       const u8 *bssid,
-				       const u8 *data, size_t data_len)
+				       const u8 *data, size_t data_len,
+				       int no_cck)
 {
 	struct test_driver_bss *dbss = priv;
 	struct wpa_driver_test_data *drv = dbss->drv;
@@ -2760,7 +2705,7 @@
 	os_memcpy(hdr->addr2, src, ETH_ALEN);
 	os_memcpy(hdr->addr3, bssid, ETH_ALEN);
 
-	ret = wpa_driver_test_send_mlme(priv, buf, 24 + data_len);
+	ret = wpa_driver_test_send_mlme(priv, buf, 24 + data_len, 0);
 	os_free(buf);
 	return ret;
 }
@@ -2770,7 +2715,6 @@
 static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_driver_test_data *drv = eloop_ctx;
-	int res;
 
 	if (drv->pending_action_tx == NULL)
 		return;
@@ -2783,12 +2727,13 @@
 	}
 	wpa_printf(MSG_DEBUG, "P2P: Sending pending Action frame to "
 		   MACSTR, MAC2STR(drv->pending_action_dst));
-	res = wpa_driver_test_send_action(drv, drv->pending_action_freq, 0,
-					  drv->pending_action_dst,
-					  drv->pending_action_src,
-					  drv->pending_action_bssid,
-					  wpabuf_head(drv->pending_action_tx),
-					  wpabuf_len(drv->pending_action_tx));
+	wpa_driver_test_send_action(drv, drv->pending_action_freq, 0,
+				    drv->pending_action_dst,
+				    drv->pending_action_src,
+				    drv->pending_action_bssid,
+				    wpabuf_head(drv->pending_action_tx),
+				    wpabuf_len(drv->pending_action_tx),
+				    drv->pending_action_no_cck);
 }
 #endif /* CONFIG_P2P */
 
@@ -2980,6 +2925,7 @@
 	int ret;
 	struct wpabuf *wps_ie, *ies;
 	int social_channels[] = { 2412, 2437, 2462, 0, 0 };
+	size_t ielen;
 
 	wpa_printf(MSG_DEBUG, "%s(type=%d freq=%d)",
 		   __func__, type, freq);
@@ -3001,7 +2947,8 @@
 	if (wps_ie == NULL)
 		return -1;
 
-	ies = wpabuf_alloc(wpabuf_len(wps_ie) + 100);
+	ielen = p2p_scan_ie_buf_len(drv->p2p);
+	ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
 	if (ies == NULL) {
 		wpabuf_free(wps_ie);
 		return -1;
@@ -3069,6 +3016,7 @@
 	os_memcpy(drv->pending_action_dst, dst, ETH_ALEN);
 	os_memcpy(drv->pending_action_bssid, bssid, ETH_ALEN);
 	drv->pending_action_freq = freq;
+	drv->pending_action_no_cck = 1;
 
 	if (drv->off_channel_freq == freq) {
 		/* Already on requested channel; send immediately */
@@ -3248,7 +3196,8 @@
 static void test_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
 			       const u8 *dev_addr, const u8 *pri_dev_type,
 			       const char *dev_name, u16 supp_config_methods,
-			       u8 dev_capab, u8 group_capab)
+			       u8 dev_capab, u8 group_capab,
+			       const u8 *group_id, size_t group_id_len)
 {
 	wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)",
 		   __func__, MAC2STR(peer), config_methods);
@@ -3343,7 +3292,6 @@
 	.get_hw_feature_data = wpa_driver_test_get_hw_feature_data,
 	.if_add = test_driver_if_add,
 	.if_remove = test_driver_if_remove,
-	.valid_bss_mask = test_driver_valid_bss_mask,
 	.hapd_set_ssid = test_driver_set_ssid,
 	.set_privacy = test_driver_set_privacy,
 	.set_sta_vlan = test_driver_set_sta_vlan,
@@ -3362,11 +3310,6 @@
 	.get_mac_addr = wpa_driver_test_get_mac_addr,
 	.send_eapol = wpa_driver_test_send_eapol,
 	.mlme_setprotection = wpa_driver_test_mlme_setprotection,
-	.set_channel = wpa_driver_test_set_channel,
-	.set_ssid = wpa_driver_test_set_ssid,
-	.set_bssid = wpa_driver_test_set_bssid,
-	.mlme_add_sta = wpa_driver_test_mlme_add_sta,
-	.mlme_remove_sta = wpa_driver_test_mlme_remove_sta,
 	.get_scan_results2 = wpa_driver_test_get_scan_results2,
 	.global_init = wpa_driver_test_global_init,
 	.global_deinit = wpa_driver_test_global_deinit,
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 001716e..381cb3e 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -25,7 +25,7 @@
 #include <fcntl.h>
 #include <net/if_arp.h>
 
-#include "wireless_copy.h"
+#include "linux_wext.h"
 #include "common.h"
 #include "eloop.h"
 #include "common/ieee802_11_defs.h"
@@ -37,6 +37,9 @@
 #include "driver.h"
 #include "driver_wext.h"
 
+#ifdef ANDROID
+#include "android_drv.h"
+#endif /* ANDROID */
 
 static int wpa_driver_wext_flush_pmkid(void *priv);
 static int wpa_driver_wext_get_range(void *priv);
@@ -842,12 +845,13 @@
 	}
 
 	drv->mlme_sock = -1;
+
 #ifdef ANDROID
 	drv->errors = 0;
 	drv->driver_is_started = TRUE;
 	drv->skip_disconnect = 0;
 	drv->bgscan_enabled = 0;
-#endif
+#endif /* ANDROID */
 
 	if (wpa_driver_wext_finish_drv_init(drv) < 0)
 		goto err3;
@@ -1416,7 +1420,7 @@
 	tmp[res->num++] = r;
 	res->res = tmp;
 }
-				      
+
 
 /**
  * wpa_driver_wext_get_scan_results - Fetch the latest scan results
@@ -1426,7 +1430,7 @@
 struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
 {
 	struct wpa_driver_wext_data *drv = priv;
-	size_t ap_num = 0, len;
+	size_t len;
 	int first;
 	u8 *res_buf;
 	struct iw_event iwe_buf, *iwe = &iwe_buf;
@@ -1438,7 +1442,6 @@
 	if (res_buf == NULL)
 		return NULL;
 
-	ap_num = 0;
 	first = 1;
 
 	res = os_zalloc(sizeof(*res));
@@ -1868,8 +1871,10 @@
 {
 	struct iwreq iwr;
 	const u8 null_bssid[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
+#ifndef ANDROID
 	u8 ssid[32];
 	int i;
+#endif /* ANDROID */
 
 	/*
 	 * Only force-disconnect when the card is in infrastructure mode,
@@ -1884,40 +1889,39 @@
 	}
 
 	if (iwr.u.mode == IW_MODE_INFRA) {
+		/* Clear the BSSID selection */
+		if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0) {
+			wpa_printf(MSG_DEBUG, "WEXT: Failed to clear BSSID "
+				   "selection on disconnect");
+		}
+
+#ifndef ANDROID
 		if (drv->cfg80211) {
 			/*
 			 * cfg80211 supports SIOCSIWMLME commands, so there is
 			 * no need for the random SSID hack, but clear the
-			 * BSSID and SSID.
+			 * SSID.
 			 */
-			if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 ||
-#ifdef ANDROID
-			    0) {
-#else
-			    wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
-#endif
+			if (wpa_driver_wext_set_ssid(drv, (u8 *) "", 0) < 0) {
 				wpa_printf(MSG_DEBUG, "WEXT: Failed to clear "
-					   "to disconnect");
+					   "SSID on disconnect");
 			}
 			return;
 		}
+
 		/*
-		 * Clear the BSSID selection and set a random SSID to make sure
-		 * the driver will not be trying to associate with something
-		 * even if it does not understand SIOCSIWMLME commands (or
-		 * tries to associate automatically after deauth/disassoc).
+		 * Set a random SSID to make sure the driver will not be trying
+		 * to associate with something even if it does not understand
+		 * SIOCSIWMLME commands (or tries to associate automatically
+		 * after deauth/disassoc).
 		 */
 		for (i = 0; i < 32; i++)
 			ssid[i] = rand() & 0xFF;
-		if (wpa_driver_wext_set_bssid(drv, null_bssid) < 0 ||
-#ifdef ANDROID
-		    0) {
-#else
-		    wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) {
-#endif
+		if (wpa_driver_wext_set_ssid(drv, ssid, 32) < 0) {
 			wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus "
-				   "BSSID/SSID to disconnect");
+				   "SSID to disconnect");
 		}
+#endif /* ANDROID */
 	}
 }
 
@@ -2350,6 +2354,129 @@
 }
 
 
+#ifdef ANDROID
+
+static int android_wext_cmd(struct wpa_driver_wext_data *drv, const char *cmd)
+{
+	struct iwreq iwr;
+	char buf[MAX_DRV_CMD_SIZE];
+	int ret;
+
+	os_memset(&iwr, 0, sizeof(iwr));
+	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+
+	os_memset(buf, 0, sizeof(buf));
+	os_strlcpy(buf, cmd, sizeof(buf));
+
+	iwr.u.data.pointer = buf;
+	iwr.u.data.length = sizeof(buf);
+
+	ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
+
+	if (ret < 0) {
+		wpa_printf(MSG_ERROR, "%s failed (%d): %s", __func__, ret,
+			   cmd);
+		drv->errors++;
+		if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
+			drv->errors = 0;
+			wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE
+				"HANGED");
+		}
+		return ret;
+	}
+
+	drv->errors = 0;
+	return 0;
+}
+
+
+static int wext_sched_scan(void *priv, struct wpa_driver_scan_params *params,
+			   u32 interval)
+{
+	struct wpa_driver_wext_data *drv = priv;
+	struct iwreq iwr;
+	int ret = 0, i = 0, bp;
+	char buf[WEXT_PNO_MAX_COMMAND_SIZE];
+
+	bp = WEXT_PNOSETUP_HEADER_SIZE;
+	os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
+	buf[bp++] = WEXT_PNO_TLV_PREFIX;
+	buf[bp++] = WEXT_PNO_TLV_VERSION;
+	buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
+	buf[bp++] = WEXT_PNO_TLV_RESERVED;
+
+	while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
+		/*
+		 * Check that there is enough space needed for 1 more SSID, the
+		 * other sections and null termination.
+		 */
+		if ((bp + WEXT_PNO_SSID_HEADER_SIZE + IW_ESSID_MAX_SIZE +
+		     WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
+			break;
+
+		wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
+				  params->ssids[i].ssid,
+				  params->ssids[i].ssid_len);
+		buf[bp++] = WEXT_PNO_SSID_SECTION;
+		buf[bp++] = params->ssids[i].ssid_len;
+		os_memcpy(&buf[bp], params->ssids[i].ssid,
+			  params->ssids[i].ssid_len);
+		bp += params->ssids[i].ssid_len;
+		i++;
+	}
+
+	buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
+	/* TODO: consider using interval parameter (interval in msec) instead
+	 * of hardcoded value here */
+	os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
+		    WEXT_PNO_SCAN_INTERVAL);
+	bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
+
+	buf[bp++] = WEXT_PNO_REPEAT_SECTION;
+	os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
+		    WEXT_PNO_REPEAT);
+	bp += WEXT_PNO_REPEAT_LENGTH;
+
+	buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
+	os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
+		    WEXT_PNO_MAX_REPEAT);
+	bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
+
+	os_memset(&iwr, 0, sizeof(iwr));
+	os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+	iwr.u.data.pointer = buf;
+	iwr.u.data.length = bp;
+
+	ret = ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr);
+	if (ret < 0) {
+		wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
+			   ret);
+		drv->errors++;
+		if (drv->errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
+			drv->errors = 0;
+			wpa_msg(drv->ctx, MSG_INFO,
+				WPA_EVENT_DRIVER_STATE "HANGED");
+		}
+		return ret;
+	}
+
+	drv->errors = 0;
+	drv->bgscan_enabled = 1;
+
+	return android_wext_cmd(drv, "PNOFORCE 1");
+}
+
+
+static int wext_stop_sched_scan(void *priv)
+{
+	struct wpa_driver_wext_data *drv = priv;
+	drv->bgscan_enabled = 0;
+	return android_wext_cmd(drv, "PNOFORCE 0");
+}
+
+#endif /* ANDROID */
+
+
 const struct wpa_driver_ops wpa_driver_wext_ops = {
 	.name = "wext",
 	.desc = "Linux wireless extensions (generic)",
@@ -2371,7 +2498,7 @@
 	.set_operstate = wpa_driver_wext_set_operstate,
 	.get_radio_name = wext_get_radio_name,
 #ifdef ANDROID
-	.signal_poll = wpa_driver_signal_poll,
-	.driver_cmd = wpa_driver_wext_driver_cmd,
-#endif
+	.sched_scan = wext_sched_scan,
+	.stop_sched_scan = wext_stop_sched_scan,
+#endif /* ANDROID */
 };
diff --git a/src/drivers/driver_wext.h b/src/drivers/driver_wext.h
index 51e4d98..03df8e4 100644
--- a/src/drivers/driver_wext.h
+++ b/src/drivers/driver_wext.h
@@ -50,12 +50,13 @@
 	int cfg80211; /* whether driver is using cfg80211 */
 
 	u8 max_level;
+
 #ifdef ANDROID
 	int errors;
 	int driver_is_started;
 	int skip_disconnect;
 	int bgscan_enabled;
-#endif
+#endif /* ANDROID */
 };
 
 int wpa_driver_wext_get_bssid(void *priv, u8 *bssid);
@@ -90,9 +91,4 @@
 int wpa_driver_wext_cipher2wext(int cipher);
 int wpa_driver_wext_keymgmt2wext(int keymgmt);
 
-#ifdef ANDROID
-#define WPA_EVENT_DRIVER_STATE		"CTRL-EVENT-DRIVER-STATE "
-#define WEXT_CSCAN_AMOUNT		9
-#endif
-
 #endif /* DRIVER_WEXT_H */
diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
index b710778..667ea22 100644
--- a/src/drivers/drivers.c
+++ b/src/drivers/drivers.c
@@ -27,9 +27,6 @@
 #ifdef CONFIG_DRIVER_MADWIFI
 extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */
 #endif /* CONFIG_DRIVER_MADWIFI */
-#ifdef CONFIG_DRIVER_BROADCOM
-extern struct wpa_driver_ops wpa_driver_broadcom_ops; /* driver_broadcom.c */
-#endif /* CONFIG_DRIVER_BROADCOM */
 #ifdef CONFIG_DRIVER_BSD
 extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
 #endif /* CONFIG_DRIVER_BSD */
@@ -42,15 +39,6 @@
 #ifdef CONFIG_DRIVER_TEST
 extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */
 #endif /* CONFIG_DRIVER_TEST */
-#ifdef CONFIG_DRIVER_RALINK
-extern struct wpa_driver_ops wpa_driver_ralink_ops; /* driver_ralink.c */
-#endif /* CONFIG_DRIVER_RALINK */
-#ifdef CONFIG_DRIVER_OSX
-extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */
-#endif /* CONFIG_DRIVER_OSX */
-#ifdef CONFIG_DRIVER_IPHONE
-extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */
-#endif /* CONFIG_DRIVER_IPHONE */
 #ifdef CONFIG_DRIVER_ROBOSWITCH
 /* driver_roboswitch.c */
 extern struct wpa_driver_ops wpa_driver_roboswitch_ops;
@@ -77,9 +65,6 @@
 #ifdef CONFIG_DRIVER_MADWIFI
 	&wpa_driver_madwifi_ops,
 #endif /* CONFIG_DRIVER_MADWIFI */
-#ifdef CONFIG_DRIVER_BROADCOM
-	&wpa_driver_broadcom_ops,
-#endif /* CONFIG_DRIVER_BROADCOM */
 #ifdef CONFIG_DRIVER_BSD
 	&wpa_driver_bsd_ops,
 #endif /* CONFIG_DRIVER_BSD */
@@ -92,15 +77,6 @@
 #ifdef CONFIG_DRIVER_TEST
 	&wpa_driver_test_ops,
 #endif /* CONFIG_DRIVER_TEST */
-#ifdef CONFIG_DRIVER_RALINK
-	&wpa_driver_ralink_ops,
-#endif /* CONFIG_DRIVER_RALINK */
-#ifdef CONFIG_DRIVER_OSX
-	&wpa_driver_osx_ops,
-#endif /* CONFIG_DRIVER_OSX */
-#ifdef CONFIG_DRIVER_IPHONE
-	&wpa_driver_iphone_ops,
-#endif /* CONFIG_DRIVER_IPHONE */
 #ifdef CONFIG_DRIVER_ROBOSWITCH
 	&wpa_driver_roboswitch_ops,
 #endif /* CONFIG_DRIVER_ROBOSWITCH */
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index ebf39c8..0cc81f9 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -12,29 +12,11 @@
 
 ##### COMMON DRIVERS
 
-ifdef CONFIG_DRIVER_HOSTAP
-DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP
-DRV_OBJS += ../src/drivers/driver_hostap.o
-CONFIG_WIRELESS_EXTENSION=y
-NEED_AP_MLME=y
-NEED_NETLINK=y
-NEED_LINUX_IOCTL=y
-endif
-
 ifdef CONFIG_DRIVER_WIRED
 DRV_CFLAGS += -DCONFIG_DRIVER_WIRED
 DRV_OBJS += ../src/drivers/driver_wired.o
 endif
 
-ifdef CONFIG_DRIVER_MADWIFI
-DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI
-DRV_OBJS += ../src/drivers/driver_madwifi.o
-CONFIG_WIRELESS_EXTENSION=y
-CONFIG_L2_PACKET=linux
-NEED_NETLINK=y
-NEED_LINUX_IOCTL=y
-endif
-
 ifdef CONFIG_DRIVER_NL80211
 DRV_CFLAGS += -DCONFIG_DRIVER_NL80211
 DRV_OBJS += ../src/drivers/driver_nl80211.o
@@ -44,15 +26,22 @@
 NEED_NETLINK=y
 NEED_LINUX_IOCTL=y
 NEED_RFKILL=y
-ifdef CONFIG_LIBNL_TINY
-DRV_LIBS += -lnl-tiny
-else
-DRV_LIBS += -lnl
-endif
 
-ifdef CONFIG_LIBNL20
-DRV_LIBS += -lnl-genl
-DRV_CFLAGS += -DCONFIG_LIBNL20
+ifdef CONFIG_LIBNL32
+  DRV_LIBS += -lnl-3
+  DRV_LIBS += -lnl-genl-3
+  DRV_CFLAGS += -DCONFIG_LIBNL20
+else
+  ifdef CONFIG_LIBNL_TINY
+    DRV_LIBS += -lnl-tiny
+  else
+    DRV_LIBS += -lnl
+  endif
+
+  ifdef CONFIG_LIBNL20
+    DRV_LIBS += -lnl-genl
+    DRV_CFLAGS += -DCONFIG_LIBNL20
+  endif
 endif
 endif
 
@@ -79,6 +68,24 @@
 
 ##### PURE AP DRIVERS
 
+ifdef CONFIG_DRIVER_HOSTAP
+DRV_AP_CFLAGS += -DCONFIG_DRIVER_HOSTAP
+DRV_AP_OBJS += ../src/drivers/driver_hostap.o
+CONFIG_WIRELESS_EXTENSION=y
+NEED_AP_MLME=y
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
+ifdef CONFIG_DRIVER_MADWIFI
+DRV_AP_CFLAGS += -DCONFIG_DRIVER_MADWIFI
+DRV_AP_OBJS += ../src/drivers/driver_madwifi.o
+CONFIG_WIRELESS_EXTENSION=y
+CONFIG_L2_PACKET=linux
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
 ifdef CONFIG_DRIVER_ATHEROS
 DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS
 DRV_AP_OBJS += ../src/drivers/driver_atheros.o
@@ -97,18 +104,6 @@
 NEED_RFKILL=y
 endif
 
-ifdef CONFIG_DRIVER_RALINK
-DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK
-DRV_WPA_OBJS += ../src/drivers/driver_ralink.o
-NEED_NETLINK=y
-NEED_LINUX_IOCTL=y
-endif
-
-ifdef CONFIG_DRIVER_BROADCOM
-DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM
-DRV_WPA_OBJS += ../src/drivers/driver_broadcom.o
-endif
-
 ifdef CONFIG_DRIVER_NDIS
 DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS
 DRV_WPA_OBJS += ../src/drivers/driver_ndis.o
@@ -124,20 +119,6 @@
 endif
 endif
 
-ifdef CONFIG_DRIVER_OSX
-DRV_WPA_CFLAGS += -DCONFIG_DRIVER_OSX
-DRV_WPA_OBJS += ../src/drivers/driver_osx.o
-DRV_WPA_LDFLAGS += -framework CoreFoundation
-DRV_WPA_LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211
-endif
-
-ifdef CONFIG_DRIVER_IPHONE
-DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPHONE
-DRV_WPA_OBJS += ../src/drivers/driver_iphone.o
-DRV_WPA_OBJS += ../src/drivers/MobileApple80211.o
-DRV_WPA_LDFLAGS += -framework CoreFoundation
-endif
-
 ifdef CONFIG_DRIVER_ROBOSWITCH
 DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH
 DRV_WPA_OBJS += ../src/drivers/driver_roboswitch.o
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index c690e1c..1d7129c 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -12,29 +12,11 @@
 
 ##### COMMON DRIVERS
 
-ifdef CONFIG_DRIVER_HOSTAP
-DRV_CFLAGS += -DCONFIG_DRIVER_HOSTAP
-DRV_OBJS += src/drivers/driver_hostap.c
-CONFIG_WIRELESS_EXTENSION=y
-NEED_AP_MLME=y
-NEED_NETLINK=y
-NEED_LINUX_IOCTL=y
-endif
-
 ifdef CONFIG_DRIVER_WIRED
 DRV_CFLAGS += -DCONFIG_DRIVER_WIRED
 DRV_OBJS += src/drivers/driver_wired.c
 endif
 
-ifdef CONFIG_DRIVER_MADWIFI
-DRV_CFLAGS += -DCONFIG_DRIVER_MADWIFI
-DRV_OBJS += src/drivers/driver_madwifi.c
-CONFIG_WIRELESS_EXTENSION=y
-CONFIG_L2_PACKET=linux
-NEED_NETLINK=y
-NEED_LINUX_IOCTL=y
-endif
-
 ifdef CONFIG_DRIVER_NL80211
 DRV_CFLAGS += -DCONFIG_DRIVER_NL80211
 DRV_OBJS += src/drivers/driver_nl80211.c
@@ -44,15 +26,22 @@
 NEED_NETLINK=y
 NEED_LINUX_IOCTL=y
 NEED_RFKILL=y
-ifdef CONFIG_LIBNL_TINY
-DRV_LIBS += -lnl-tiny
-else
-DRV_LIBS += -lnl
-endif
 
-ifdef CONFIG_LIBNL20
-DRV_LIBS += -lnl-genl
-DRV_CFLAGS += -DCONFIG_LIBNL20
+ifdef CONFIG_LIBNL32
+  DRV_LIBS += -lnl-3
+  DRV_LIBS += -lnl-genl-3
+  DRV_CFLAGS += -DCONFIG_LIBNL20
+else
+  ifdef CONFIG_LIBNL_TINY
+    DRV_LIBS += -lnl-tiny
+  else
+    DRV_LIBS += -lnl
+  endif
+
+  ifdef CONFIG_LIBNL20
+    DRV_LIBS += -lnl-genl
+    DRV_CFLAGS += -DCONFIG_LIBNL20
+  endif
 endif
 endif
 
@@ -79,6 +68,24 @@
 
 ##### PURE AP DRIVERS
 
+ifdef CONFIG_DRIVER_HOSTAP
+DRV_AP_CFLAGS += -DCONFIG_DRIVER_HOSTAP
+DRV_AP_OBJS += src/drivers/driver_hostap.c
+CONFIG_WIRELESS_EXTENSION=y
+NEED_AP_MLME=y
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
+ifdef CONFIG_DRIVER_MADWIFI
+DRV_AP_CFLAGS += -DCONFIG_DRIVER_MADWIFI
+DRV_AP_OBJS += src/drivers/driver_madwifi.c
+CONFIG_WIRELESS_EXTENSION=y
+CONFIG_L2_PACKET=linux
+NEED_NETLINK=y
+NEED_LINUX_IOCTL=y
+endif
+
 ifdef CONFIG_DRIVER_ATHEROS
 DRV_AP_CFLAGS += -DCONFIG_DRIVER_ATHEROS
 DRV_AP_OBJS += src/drivers/driver_atheros.c
@@ -97,18 +104,6 @@
 NEED_RFKILL=y
 endif
 
-ifdef CONFIG_DRIVER_RALINK
-DRV_WPA_CFLAGS += -DCONFIG_DRIVER_RALINK
-DRV_WPA_OBJS += src/drivers/driver_ralink.c
-NEED_NETLINK=y
-NEED_LINUX_IOCTL=y
-endif
-
-ifdef CONFIG_DRIVER_BROADCOM
-DRV_WPA_CFLAGS += -DCONFIG_DRIVER_BROADCOM
-DRV_WPA_OBJS += src/drivers/driver_broadcom.c
-endif
-
 ifdef CONFIG_DRIVER_NDIS
 DRV_WPA_CFLAGS += -DCONFIG_DRIVER_NDIS
 DRV_WPA_OBJS += src/drivers/driver_ndis.c
@@ -124,20 +119,6 @@
 endif
 endif
 
-ifdef CONFIG_DRIVER_OSX
-DRV_WPA_CFLAGS += -DCONFIG_DRIVER_OSX
-DRV_WPA_OBJS += src/drivers/driver_osx.c
-DRV_WPA_LDFLAGS += -framework CoreFoundation
-DRV_WPA_LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211
-endif
-
-ifdef CONFIG_DRIVER_IPHONE
-DRV_WPA_CFLAGS += -DCONFIG_DRIVER_IPHONE
-DRV_WPA_OBJS += src/drivers/driver_iphone.c
-DRV_WPA_OBJS += src/drivers/MobileApple80211.c
-DRV_WPA_LDFLAGS += -framework CoreFoundation
-endif
-
 ifdef CONFIG_DRIVER_ROBOSWITCH
 DRV_WPA_CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH
 DRV_WPA_OBJS += src/drivers/driver_roboswitch.c
diff --git a/src/drivers/linux_ioctl.c b/src/drivers/linux_ioctl.c
index 0d6cf54..d7501cf 100644
--- a/src/drivers/linux_ioctl.c
+++ b/src/drivers/linux_ioctl.c
@@ -24,6 +24,7 @@
 int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
 {
 	struct ifreq ifr;
+	int ret;
 
 	if (sock < 0)
 		return -1;
@@ -32,9 +33,10 @@
 	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
 
 	if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
+		ret = errno ? -errno : -999;
 		wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
 			   ifname, strerror(errno));
-		return -1;
+		return ret;
 	}
 
 	if (dev_up) {
@@ -48,15 +50,38 @@
 	}
 
 	if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
+		ret = errno ? -errno : -999;
 		wpa_printf(MSG_ERROR, "Could not set interface %s flags: %s",
 			   ifname, strerror(errno));
-		return -1;
+		return ret;
 	}
 
 	return 0;
 }
 
 
+int linux_iface_up(int sock, const char *ifname)
+{
+	struct ifreq ifr;
+	int ret;
+
+	if (sock < 0)
+		return -1;
+
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
+
+	if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
+		ret = errno ? -errno : -999;
+		wpa_printf(MSG_ERROR, "Could not read interface %s flags: %s",
+			   ifname, strerror(errno));
+		return ret;
+	}
+
+	return !!(ifr.ifr_flags & IFF_UP);
+}
+
+
 int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr)
 {
 	struct ifreq ifr;
diff --git a/src/drivers/linux_ioctl.h b/src/drivers/linux_ioctl.h
index a555738..e0bf673 100644
--- a/src/drivers/linux_ioctl.h
+++ b/src/drivers/linux_ioctl.h
@@ -16,6 +16,7 @@
 #define LINUX_IOCTL_H
 
 int linux_set_iface_flags(int sock, const char *ifname, int dev_up);
+int linux_iface_up(int sock, const char *ifname);
 int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr);
 int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr);
 int linux_br_add(int sock, const char *brname);
diff --git a/src/drivers/linux_wext.h b/src/drivers/linux_wext.h
new file mode 100644
index 0000000..b6eea68
--- /dev/null
+++ b/src/drivers/linux_wext.h
@@ -0,0 +1,51 @@
+/*
+ * Driver interaction with generic Linux Wireless Extensions
+ * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef LINUX_WEXT_H
+#define LINUX_WEXT_H
+
+#ifndef ANDROID
+
+/*
+ * Avoid including other kernel header to avoid conflicts with C library
+ * headers.
+ */
+#define _LINUX_TYPES_H
+#define _LINUX_SOCKET_H
+#define _LINUX_IF_H
+
+#include <sys/types.h>
+#include <net/if.h>
+typedef __uint32_t __u32;
+typedef __int32_t __s32;
+typedef __uint16_t __u16;
+typedef __int16_t __s16;
+typedef __uint8_t __u8;
+#ifndef __user
+#define __user
+#endif /* __user */
+
+#endif /* ANDROID */
+
+#include <linux/wireless.h>
+
+#ifndef IW_ENCODE_ALG_PMK
+#define IW_ENCODE_ALG_PMK 4
+#endif
+
+#ifndef IW_ENC_CAPA_4WAY_HANDSHAKE
+#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010
+#endif
+
+#endif /* LINUX_WEXT_H */
diff --git a/src/drivers/netlink.c b/src/drivers/netlink.c
index ad15b1d..6778907 100644
--- a/src/drivers/netlink.c
+++ b/src/drivers/netlink.c
@@ -34,7 +34,7 @@
 	if (cb == NULL || NLMSG_PAYLOAD(h, 0) < sizeof(struct ifinfomsg))
 		return;
 	cb(netlink->cfg->ctx, NLMSG_DATA(h),
-	   NLMSG_DATA(h) + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
+	   (u8 *) NLMSG_DATA(h) + NLMSG_ALIGN(sizeof(struct ifinfomsg)),
 	   NLMSG_PAYLOAD(h, sizeof(struct ifinfomsg)));
 }
 
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 7483a89..f9261c2 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -6,7 +6,7 @@
  * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2008 Michael Wu <flamingice@sourmilk.net>
  * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
- * Copyright 2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright 2008 Michael Buesch <m@bues.ch>
  * Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
  * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
  * Copyright 2008 Colin McCabe <colin@cozybit.com>
@@ -77,6 +77,39 @@
  */
 
 /**
+ * DOC: Virtual interface / concurrency capabilities
+ *
+ * Some devices are able to operate with virtual MACs, they can have
+ * more than one virtual interface. The capability handling for this
+ * is a bit complex though, as there may be a number of restrictions
+ * on the types of concurrency that are supported.
+ *
+ * To start with, each device supports the interface types listed in
+ * the %NL80211_ATTR_SUPPORTED_IFTYPES attribute, but by listing the
+ * types there no concurrency is implied.
+ *
+ * Once concurrency is desired, more attributes must be observed:
+ * To start with, since some interface types are purely managed in
+ * software, like the AP-VLAN type in mac80211 for example, there's
+ * an additional list of these, they can be added at any time and
+ * are only restricted by some semantic restrictions (e.g. AP-VLAN
+ * cannot be added without a corresponding AP interface). This list
+ * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute.
+ *
+ * Further, the list of supported combinations is exported. This is
+ * in the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute. Basically,
+ * it exports a list of "groups", and at any point in time the
+ * interfaces that are currently active must fall into any one of
+ * the advertised groups. Within each group, there are restrictions
+ * on the number of interfaces of different types that are supported
+ * and also the number of different channels, along with potentially
+ * some other restrictions. See &enum nl80211_if_combination_attrs.
+ *
+ * All together, these attributes define the concurrency of virtual
+ * interfaces that a given device supports.
+ */
+
+/**
  * enum nl80211_commands - supported nl80211 commands
  *
  * @NL80211_CMD_UNSPEC: unspecified command to catch errors
@@ -128,6 +161,13 @@
  * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface
  *	using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD,
  *	%NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes.
+ *	Following attributes are provided for drivers that generate full Beacon
+ *	and Probe Response frames internally: %NL80211_ATTR_SSID,
+ *	%NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE,
+ *	%NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS,
+ *	%NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
+ *	%NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_IE, %NL80211_ATTR_IE_PROBE_RESP,
+ *	%NL80211_ATTR_IE_ASSOC_RESP.
  * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface,
  *	parameters are like for %NL80211_CMD_SET_BEACON.
  * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it
@@ -148,6 +188,10 @@
  * @NL80211_CMD_SET_MPATH:  Set mesh path attributes for mesh path to
  * 	destination %NL80211_ATTR_MAC on the interface identified by
  * 	%NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_NEW_MPATH: Create a new mesh path for the destination given by
+ *	%NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP.
+ * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by
+ *	%NL80211_ATTR_MAC.
  * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
  *	the interface identified by %NL80211_ATTR_IFINDEX.
  * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
@@ -172,10 +216,10 @@
  * 	to the specified ISO/IEC 3166-1 alpha2 country code. The core will
  * 	store this as a valid request and then query userspace for it.
  *
- * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the
+ * @NL80211_CMD_GET_MESH_CONFIG: Get mesh networking properties for the
  *	interface identified by %NL80211_ATTR_IFINDEX
  *
- * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the
+ * @NL80211_CMD_SET_MESH_CONFIG: Set mesh networking properties for the
  *      interface identified by %NL80211_ATTR_IFINDEX
  *
  * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The
@@ -194,11 +238,36 @@
  *
  * @NL80211_CMD_GET_SCAN: get scan results
  * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
+ *	%NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
+ *	probe requests at CCK rate or not.
  * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to
  *	NL80211_CMD_GET_SCAN and on the "scan" multicast group)
  * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
  *	partial scan results may be available
  *
+ * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain
+ *	intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL.
+ *	Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS)
+ *	are passed, they are used in the probe requests.  For
+ *	broadcast, a broadcast SSID must be passed (ie. an empty
+ *	string).  If no SSID is passed, no probe requests are sent and
+ *	a passive scan is performed.  %NL80211_ATTR_SCAN_FREQUENCIES,
+ *	if passed, define which channels should be scanned; if not
+ *	passed, all channels allowed for the current regulatory domain
+ *	are used.  Extra IEs can also be passed from the userspace by
+ *	using the %NL80211_ATTR_IE attribute.
+ * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan.  Returns -ENOENT
+ *	if scheduled scan is not running.
+ * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan
+ *	results available.
+ * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has
+ *	stopped.  The driver may issue this event at any time during a
+ *	scheduled scan.  One reason for stopping the scan is if the hardware
+ *	does not support starting an association or a normal scan while running
+ *	a scheduled scan.  This event is also sent when the
+ *	%NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface
+ *	is brought down while a scheduled scan was running.
+ *
  * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
  *      or noise level
  * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
@@ -365,6 +434,8 @@
  *	specified using %NL80211_ATTR_DURATION. When called, this operation
  *	returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the
  *	TX status event pertaining to the TX request.
+ *	%NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
+ *	management frames at CCK rate or not in 2GHz band.
  * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
  *	command may be used with the corresponding cookie to cancel the wait
  *	time if it is known that it is no longer necessary.
@@ -406,11 +477,72 @@
  *	notification. This event is used to indicate that an unprotected
  *	disassociation frame was dropped when MFP is in use.
  *
+ * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a
+ *      beacon or probe response from a compatible mesh peer.  This is only
+ *      sent while no station information (sta_info) exists for the new peer
+ *      candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set.  On
+ *      reception of this notification, userspace may decide to create a new
+ *      station (@NL80211_CMD_NEW_STATION).  To stop this notification from
+ *      reoccurring, the userspace authentication daemon may want to create the
+ *      new station with the AUTHENTICATED flag unset and maybe change it later
+ *      depending on the authentication result.
+ *
+ * @NL80211_CMD_GET_WOWLAN: get Wake-on-Wireless-LAN (WoWLAN) settings.
+ * @NL80211_CMD_SET_WOWLAN: set Wake-on-Wireless-LAN (WoWLAN) settings.
+ *	Since wireless is more complex than wired ethernet, it supports
+ *	various triggers. These triggers can be configured through this
+ *	command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For
+ *	more background information, see
+ *	http://wireless.kernel.org/en/users/Documentation/WoWLAN.
+ *
+ * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver
+ *	the necessary information for supporting GTK rekey offload. This
+ *	feature is typically used during WoWLAN. The configuration data
+ *	is contained in %NL80211_ATTR_REKEY_DATA (which is nested and
+ *	contains the data in sub-attributes). After rekeying happened,
+ *	this command may also be sent by the driver as an MLME event to
+ *	inform userspace of the new replay counter.
+ *
+ * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace
+ *	of PMKSA caching dandidates.
+ *
+ * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
+ *
+ * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
+ *	(or GO) interface (i.e. hostapd) to ask for unexpected frames to
+ *	implement sending deauth to stations that send unexpected class 3
+ *	frames. Also used as the event sent by the kernel when such a frame
+ *	is received.
+ *	For the event, the %NL80211_ATTR_MAC attribute carries the TA and
+ *	other attributes like the interface index are present.
+ *	If used as the command it must have an interface index and you can
+ *	only unsubscribe from the event by closing the socket. Subscription
+ *	is also for %NL80211_CMD_UNEXPECTED_4ADDR_FRAME events.
+ *
+ * @NL80211_CMD_UNEXPECTED_4ADDR_FRAME: Sent as an event indicating that the
+ *	associated station identified by %NL80211_ATTR_MAC sent a 4addr frame
+ *	and wasn't already in a 4-addr VLAN. The event will be sent similarly
+ *	to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener.
+ *
+ * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface
+ *	by sending a null data frame to it and reporting when the frame is
+ *	acknowleged. This is used to allow timing out inactive clients. Uses
+ *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a
+ *	direct reply with an %NL80211_ATTR_COOKIE that is later used to match
+ *	up the event with the request. The event includes the same data and
+ *	has %NL80211_ATTR_ACK set if the frame was ACKed.
+ *
+ * @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from
+ *	other BSSes when any interfaces are in AP mode. This helps implement
+ *	OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME
+ *	messages. Note that per PHY only one application may register.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
 enum nl80211_commands {
-/* don't change the order or add anything inbetween, this is ABI! */
+/* don't change the order or add anything between, this is ABI! */
 	NL80211_CMD_UNSPEC,
 
 	NL80211_CMD_GET_WIPHY,		/* can dump */
@@ -448,8 +580,8 @@
 	NL80211_CMD_SET_REG,
 	NL80211_CMD_REQ_SET_REG,
 
-	NL80211_CMD_GET_MESH_PARAMS,
-	NL80211_CMD_SET_MESH_PARAMS,
+	NL80211_CMD_GET_MESH_CONFIG,
+	NL80211_CMD_SET_MESH_CONFIG,
 
 	NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */,
 
@@ -518,6 +650,31 @@
 	NL80211_CMD_UNPROT_DEAUTHENTICATE,
 	NL80211_CMD_UNPROT_DISASSOCIATE,
 
+	NL80211_CMD_NEW_PEER_CANDIDATE,
+
+	NL80211_CMD_GET_WOWLAN,
+	NL80211_CMD_SET_WOWLAN,
+
+	NL80211_CMD_START_SCHED_SCAN,
+	NL80211_CMD_STOP_SCHED_SCAN,
+	NL80211_CMD_SCHED_SCAN_RESULTS,
+	NL80211_CMD_SCHED_SCAN_STOPPED,
+
+	NL80211_CMD_SET_REKEY_OFFLOAD,
+
+	NL80211_CMD_PMKSA_CANDIDATE,
+
+	NL80211_CMD_TDLS_OPER,
+	NL80211_CMD_TDLS_MGMT,
+
+	NL80211_CMD_UNEXPECTED_FRAME,
+
+	NL80211_CMD_PROBE_CLIENT,
+
+	NL80211_CMD_REGISTER_BEACONS,
+
+	NL80211_CMD_UNEXPECTED_4ADDR_FRAME,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -538,6 +695,13 @@
 #define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE
 #define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT
 
+#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS
+
+/* source-level API compatibility */
+#define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG
+#define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG
+#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE
+
 /**
  * enum nl80211_attrs - nl80211 netlink attributes
  *
@@ -608,7 +772,7 @@
  *	consisting of a nested array.
  *
  * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
- * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link.
+ * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link.
  * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
  * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
  * 	info given for %NL80211_CMD_GET_MPATH, nested attribute described at
@@ -653,8 +817,14 @@
  *
  * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with
  *	a single scan request, a wiphy attribute.
+ * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: number of SSIDs you can
+ *	scan with a single scheduled scan request, a wiphy attribute.
  * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements
  *	that can be added to a scan request
+ * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information
+ *	elements that can be added to a scheduled scan request
+ * @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be
+ *	used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute.
  *
  * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
  * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
@@ -735,18 +905,20 @@
  * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT
  *	event (u16)
  * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating
- *	that protected APs should be used.
+ *	that protected APs should be used. This is also used with NEW_BEACON to
+ *	indicate that the BSS is to use protection.
  *
- * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to
- *	indicate which unicast key ciphers will be used with the connection
+ * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON
+ *	to indicate which unicast key ciphers will be used with the connection
  *	(an array of u32).
- * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate
- *	which group key cipher will be used with the connection (a u32).
- * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate
- *	which WPA version(s) the AP we want to associate with is using
+ * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+ *	indicate which group key cipher will be used with the connection (a
+ *	u32).
+ * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+ *	indicate which WPA version(s) the AP we want to associate with is using
  *	(a u32 with flags from &enum nl80211_wpa_versions).
- * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate
- *	which key management algorithm(s) to use (an array of u32).
+ * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+ *	indicate which key management algorithm(s) to use (an array of u32).
  *
  * @NL80211_ATTR_REQ_IE: (Re)association request information elements as
  *	sent out by the card, for ROAM and successful CONNECT events.
@@ -852,7 +1024,13 @@
  *	This can be used to mask out antennas which are not attached or should
  *	not be used for receiving. If an antenna is not selected in this bitmap
  *	the hardware should not be configured to receive on this antenna.
- *	For a more detailed descripton see @NL80211_ATTR_WIPHY_ANTENNA_TX.
+ *	For a more detailed description see @NL80211_ATTR_WIPHY_ANTENNA_TX.
+ *
+ * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: Bitmap of antennas which are available
+ *	for configuration as TX antennas via the above parameters.
+ *
+ * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: Bitmap of antennas which are available
+ *	for configuration as RX antennas via the above parameters.
  *
  * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS
  *
@@ -868,11 +1046,135 @@
  *	attributes, specifying what a key should be set as default as.
  *	See &enum nl80211_key_default_types.
  *
+ * @NL80211_ATTR_MESH_SETUP: Optional mesh setup parameters.  These cannot be
+ *	changed once the mesh is active.
+ * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute
+ *	containing attributes from &enum nl80211_meshconf_params.
+ * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver
+ *	allows auth frames in a mesh to be passed to userspace for processing via
+ *	the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
+ * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as
+ *	defined in &enum nl80211_plink_state. Used when userspace is
+ *	driving the peer link management state machine.
+ *	@NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled.
+ *
+ * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy
+ *	capabilities, the supported WoWLAN triggers
+ * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to
+ *	indicate which WoW triggers should be enabled. This is also
+ *	used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN
+ *	triggers.
+
+ * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan
+ *	cycles, in msecs.
+
+ * @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more
+ *	sets of attributes to match during scheduled scans.  Only BSSs
+ *	that match any of the sets will be reported.  These are
+ *	pass-thru filter rules.
+ *	For a match to succeed, the BSS must match all attributes of a
+ *	set.  Since not every hardware supports matching all types of
+ *	attributes, there is no guarantee that the reported BSSs are
+ *	fully complying with the match sets and userspace needs to be
+ *	able to ignore them by itself.
+ *	Thus, the implementation is somewhat hardware-dependent, but
+ *	this is only an optimization and the userspace application
+ *	needs to handle all the non-filtered results anyway.
+ *	If the match attributes don't make sense when combined with
+ *	the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID
+ *	is included in the probe request, but the match attributes
+ *	will never let it go through), -EINVAL may be returned.
+ *	If ommited, no filtering is done.
+ *
+ * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
+ *	interface combinations. In each nested item, it contains attributes
+ *	defined in &enum nl80211_if_combination_attrs.
+ * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like
+ *	%NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that
+ *	are managed in software: interfaces of these types aren't subject to
+ *	any restrictions in their number or combinations.
+ *
+ * @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information
+ *	necessary for GTK rekeying in the device, see &enum nl80211_rekey_data.
+ *
+ * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan,
+ *	nested array attribute containing an entry for each band, with the entry
+ *	being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but
+ *	without the length restriction (at most %NL80211_MAX_SUPP_RATES).
+ *
+ * @NL80211_ATTR_HIDDEN_SSID: indicates whether SSID is to be hidden from Beacon
+ *	and Probe Response (when response to wildcard Probe Request); see
+ *	&enum nl80211_hidden_ssid, represented as a u32
+ *
+ * @NL80211_ATTR_IE_PROBE_RESP: Information element(s) for Probe Response frame.
+ *	This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to
+ *	provide extra IEs (e.g., WPS/P2P IE) into Probe Response frames when the
+ *	driver (or firmware) replies to Probe Request frames.
+ * @NL80211_ATTR_IE_ASSOC_RESP: Information element(s) for (Re)Association
+ *	Response frames. This is used with %NL80211_CMD_NEW_BEACON and
+ *	%NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into
+ *	(Re)Association Response frames when the driver (or firmware) replies to
+ *	(Re)Association Request frames.
+ *
+ * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration
+ *	of the station, see &enum nl80211_sta_wme_attr.
+ * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working
+ *	as AP.
+ *
+ * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of
+ *	roaming to another AP in the same ESS if the signal lever is low.
+ *
+ * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching
+ *	candidate information, see &enum nl80211_pmksa_candidate_attr.
+ *
+ * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not
+ *	for management frames transmission. In order to avoid p2p probe/action
+ *	frames are being transmitted at CCK rate in 2GHz band, the user space
+ *	applications use this attribute.
+ *	This attribute is used with %NL80211_CMD_TRIGGER_SCAN and
+ *	%NL80211_CMD_FRAME commands.
+ *
+ * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
+ *	request, link setup confirm, link teardown, etc.). Values are
+ *	described in the TDLS (802.11z) specification.
+ * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
+ *	TDLS conversation between two devices.
+ * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
+ *	&enum nl80211_tdls_operation, represented as a u8.
+ * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
+ *	as a TDLS peer sta.
+ * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
+ *	procedures should be performed by sending TDLS packets via
+ *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
+ *	used for asking the driver to perform a TDLS operation.
+ *
+ * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
+ *	that have AP support to indicate that they have the AP SME integrated
+ *	with support for the features listed in this attribute, see
+ *	&enum nl80211_ap_sme_features.
+ *
+ * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
+ *	the driver to not wait for an acknowledgement. Note that due to this,
+ *	it will also not give a status callback nor return a cookie. This is
+ *	mostly useful for probe responses to save airtime.
+ *
+ * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
+ *	&enum nl80211_feature_flags and is advertised in wiphy information.
+ * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe
+ *
+ *	requests while operating in AP-mode.
+ *	This attribute holds a bitmap of the supported protocols for
+ *	offloading (see &enum nl80211_probe_resp_offload_support_attr).
+ *
+ * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire
+ *	probe-response frame. The DA field in the 802.11 header is zero-ed out,
+ *	to be filled by the FW.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
 enum nl80211_attrs {
-/* don't change the order or add anything inbetween, this is ABI! */
+/* don't change the order or add anything between, this is ABI! */
 	NL80211_ATTR_UNSPEC,
 
 	NL80211_ATTR_WIPHY,
@@ -922,7 +1224,7 @@
 	NL80211_ATTR_REG_ALPHA2,
 	NL80211_ATTR_REG_RULES,
 
-	NL80211_ATTR_MESH_PARAMS,
+	NL80211_ATTR_MESH_CONFIG,
 
 	NL80211_ATTR_BSS_BASIC_RATES,
 
@@ -1050,6 +1352,62 @@
 
 	NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
 
+	NL80211_ATTR_MESH_SETUP,
+
+	NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX,
+	NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,
+
+	NL80211_ATTR_SUPPORT_MESH_AUTH,
+	NL80211_ATTR_STA_PLINK_STATE,
+
+	NL80211_ATTR_WOWLAN_TRIGGERS,
+	NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED,
+
+	NL80211_ATTR_SCHED_SCAN_INTERVAL,
+
+	NL80211_ATTR_INTERFACE_COMBINATIONS,
+	NL80211_ATTR_SOFTWARE_IFTYPES,
+
+	NL80211_ATTR_REKEY_DATA,
+
+	NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS,
+	NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN,
+
+	NL80211_ATTR_SCAN_SUPP_RATES,
+
+	NL80211_ATTR_HIDDEN_SSID,
+
+	NL80211_ATTR_IE_PROBE_RESP,
+	NL80211_ATTR_IE_ASSOC_RESP,
+
+	NL80211_ATTR_STA_WME,
+	NL80211_ATTR_SUPPORT_AP_UAPSD,
+
+	NL80211_ATTR_ROAM_SUPPORT,
+
+	NL80211_ATTR_SCHED_SCAN_MATCH,
+	NL80211_ATTR_MAX_MATCH_SETS,
+
+	NL80211_ATTR_PMKSA_CANDIDATE,
+
+	NL80211_ATTR_TX_NO_CCK_RATE,
+
+	NL80211_ATTR_TDLS_ACTION,
+	NL80211_ATTR_TDLS_DIALOG_TOKEN,
+	NL80211_ATTR_TDLS_OPERATION,
+	NL80211_ATTR_TDLS_SUPPORT,
+	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+
+	NL80211_ATTR_DEVICE_AP_SME,
+
+	NL80211_ATTR_DONT_WAIT_FOR_ACK,
+
+	NL80211_ATTR_FEATURE_FLAGS,
+
+	NL80211_ATTR_PROBE_RESP_OFFLOAD,
+
+	NL80211_ATTR_PROBE_RESP,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -1058,6 +1416,7 @@
 
 /* source-level API compatibility */
 #define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
+#define	NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
 
 /*
  * Allow user space programs to use #ifdef on new attributes by defining them
@@ -1083,6 +1442,7 @@
 #define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES
 #define NL80211_ATTR_KEY NL80211_ATTR_KEY
 #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
+#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS
 
 #define NL80211_MAX_SUPP_RATES			32
 #define NL80211_MAX_SUPP_REG_RULES		32
@@ -1101,7 +1461,9 @@
  * @NL80211_IFTYPE_ADHOC: independent BSS member
  * @NL80211_IFTYPE_STATION: managed BSS member
  * @NL80211_IFTYPE_AP: access point
- * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
+ * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces
+ *	are a bit special in that they must always be tied to a pre-existing
+ *	AP type interface.
  * @NL80211_IFTYPE_WDS: wireless distribution interface
  * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
  * @NL80211_IFTYPE_MESH_POINT: mesh point
@@ -1143,6 +1505,8 @@
  *	with short barker preamble
  * @NL80211_STA_FLAG_WME: station is WME/QoS capable
  * @NL80211_STA_FLAG_MFP: station uses management frame protection
+ * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
+ * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer
  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
@@ -1152,6 +1516,8 @@
 	NL80211_STA_FLAG_SHORT_PREAMBLE,
 	NL80211_STA_FLAG_WME,
 	NL80211_STA_FLAG_MFP,
+	NL80211_STA_FLAG_AUTHENTICATED,
+	NL80211_STA_FLAG_TDLS_PEER,
 
 	/* keep last */
 	__NL80211_STA_FLAG_AFTER_LAST,
@@ -1197,6 +1563,36 @@
 };
 
 /**
+ * enum nl80211_sta_bss_param - BSS information collected by STA
+ *
+ * These attribute types are used with %NL80211_STA_INFO_BSS_PARAM
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_STA_BSS_PARAM_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_BSS_PARAM_CTS_PROT: whether CTS protection is enabled (flag)
+ * @NL80211_STA_BSS_PARAM_SHORT_PREAMBLE:  whether short preamble is enabled
+ *	(flag)
+ * @NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME:  whether short slot time is enabled
+ *	(flag)
+ * @NL80211_STA_BSS_PARAM_DTIM_PERIOD: DTIM period for beaconing (u8)
+ * @NL80211_STA_BSS_PARAM_BEACON_INTERVAL: Beacon interval (u16)
+ * @NL80211_STA_BSS_PARAM_MAX: highest sta_bss_param number currently defined
+ * @__NL80211_STA_BSS_PARAM_AFTER_LAST: internal use
+ */
+enum nl80211_sta_bss_param {
+	__NL80211_STA_BSS_PARAM_INVALID,
+	NL80211_STA_BSS_PARAM_CTS_PROT,
+	NL80211_STA_BSS_PARAM_SHORT_PREAMBLE,
+	NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME,
+	NL80211_STA_BSS_PARAM_DTIM_PERIOD,
+	NL80211_STA_BSS_PARAM_BEACON_INTERVAL,
+
+	/* keep last */
+	__NL80211_STA_BSS_PARAM_AFTER_LAST,
+	NL80211_STA_BSS_PARAM_MAX = __NL80211_STA_BSS_PARAM_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -1206,17 +1602,27 @@
  * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
  * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
- * @__NL80211_STA_INFO_AFTER_LAST: internal
- * @NL80211_STA_INFO_MAX: highest possible station info attribute
  * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
  * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
- * 	containing info as possible, see &enum nl80211_sta_info_txrate.
+ * 	containing info as possible, see &enum nl80211_rate_info
  * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station)
  * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this
  *	station)
  * @NL80211_STA_INFO_TX_RETRIES: total retries (u32, to this station)
  * @NL80211_STA_INFO_TX_FAILED: total failed packets (u32, to this station)
  * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm)
+ * @NL80211_STA_INFO_LLID: the station's mesh LLID
+ * @NL80211_STA_INFO_PLID: the station's mesh PLID
+ * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station
+ *	(see %enum nl80211_plink_state)
+ * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested
+ *	attribute, like NL80211_STA_INFO_TX_BITRATE.
+ * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute
+ *     containing info as possible, see &enum nl80211_sta_bss_param
+ * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected
+ * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
+ * @__NL80211_STA_INFO_AFTER_LAST: internal
+ * @NL80211_STA_INFO_MAX: highest possible station info attribute
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -1233,6 +1639,10 @@
 	NL80211_STA_INFO_TX_RETRIES,
 	NL80211_STA_INFO_TX_FAILED,
 	NL80211_STA_INFO_SIGNAL_AVG,
+	NL80211_STA_INFO_RX_BITRATE,
+	NL80211_STA_INFO_BSS_PARAM,
+	NL80211_STA_INFO_CONNECTED_TIME,
+	NL80211_STA_INFO_STA_FLAGS,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
@@ -1388,7 +1798,7 @@
  * 	802.11 country information element with regulatory information it
  * 	thinks we should consider. cfg80211 only processes the country
  *	code from the IE, and relies on the regulatory domain information
- *	structure pased by userspace (CRDA) from our wireless-regdb.
+ *	structure passed by userspace (CRDA) from our wireless-regdb.
  *	If a channel is enabled but the country code indicates it should
  *	be disabled we disable the channel and re-enable it upon disassociation.
  */
@@ -1462,6 +1872,26 @@
 };
 
 /**
+ * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
+ * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
+ * only report BSS with matching SSID.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
+ *	attribute number currently defined
+ * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
+ */
+enum nl80211_sched_scan_match_attr {
+	__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID,
+
+	NL80211_ATTR_SCHED_SCAN_MATCH_SSID,
+
+	/* keep last */
+	__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
+	NL80211_SCHED_SCAN_MATCH_ATTR_MAX =
+		__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_reg_rule_flags - regulatory rule flags
  *
  * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed
@@ -1559,14 +1989,15 @@
 /**
  * enum nl80211_meshconf_params - mesh configuration parameters
  *
- * Mesh configuration parameters
+ * Mesh configuration parameters. These can be changed while the mesh is
+ * active.
  *
  * @__NL80211_MESHCONF_INVALID: internal use
  *
  * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in
  * millisecond units, used by the Peer Link Open message
  *
- * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in
+ * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the initial confirm timeout, in
  * millisecond units, used by the peer link management to close a peer link
  *
  * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in
@@ -1582,9 +2013,6 @@
  * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
  * point.
  *
- * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a
- * source mesh point for path selection elements.
- *
  * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
  * open peer links when we detect compatible mesh peers.
  *
@@ -1609,7 +2037,17 @@
  * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs)
  * that it takes for an HWMP information element to propagate across the mesh
  *
- * @NL80211_MESHCONF_ROOTMODE: whether root mode is enabled or not
+ * @NL80211_MESHCONF_HWMP_ROOTMODE: whether root mode is enabled or not
+ *
+ * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a
+ * source mesh point for path selection elements.
+ *
+ * @NL80211_MESHCONF_HWMP_RANN_INTERVAL:  The interval of time (in TUs) between
+ * root announcements are transmitted.
+ *
+ * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has
+ * access to a broader network beyond the MBSS.  This is done via Root
+ * Announcement frames.
  *
  * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
  *
@@ -1632,6 +2070,8 @@
 	NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
 	NL80211_MESHCONF_HWMP_ROOTMODE,
 	NL80211_MESHCONF_ELEMENT_TTL,
+	NL80211_MESHCONF_HWMP_RANN_INTERVAL,
+	NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
 
 	/* keep last */
 	__NL80211_MESHCONF_ATTR_AFTER_LAST,
@@ -1639,6 +2079,54 @@
 };
 
 /**
+ * enum nl80211_mesh_setup_params - mesh setup parameters
+ *
+ * Mesh setup parameters.  These are used to start/join a mesh and cannot be
+ * changed while the mesh is active.
+ *
+ * @__NL80211_MESH_SETUP_INVALID: Internal use
+ *
+ * @NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: Enable this option to use a
+ * vendor specific path selection algorithm or disable it to use the default
+ * HWMP.
+ *
+ * @NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: Enable this option to use a
+ * vendor specific path metric or disable it to use the default Airtime
+ * metric.
+ *
+ * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a
+ * robust security network ie, or a vendor specific information element that
+ * vendors will use to identify the path selection methods and metrics in use.
+ *
+ * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication
+ * daemon will be authenticating mesh candidates.
+ *
+ * @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication
+ * daemon will be securing peer link frames.  AMPE is a secured version of Mesh
+ * Peering Management (MPM) and is implemented with the assistance of a
+ * userspace daemon.  When this flag is set, the kernel will send peer
+ * management frames to a userspace daemon that will implement AMPE
+ * functionality (security capabilities selection, key confirmation, and key
+ * management).  When the flag is unset (default), the kernel can autonomously
+ * complete (unsecured) mesh peering without the need of a userspace daemon.
+ *
+ * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
+ * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
+ */
+enum nl80211_mesh_setup_params {
+	__NL80211_MESH_SETUP_INVALID,
+	NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL,
+	NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC,
+	NL80211_MESH_SETUP_IE,
+	NL80211_MESH_SETUP_USERSPACE_AUTH,
+	NL80211_MESH_SETUP_USERSPACE_AMPE,
+
+	/* keep last */
+	__NL80211_MESH_SETUP_ATTR_AFTER_LAST,
+	NL80211_MESH_SETUP_ATTR_MAX = __NL80211_MESH_SETUP_ATTR_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_txq_attr - TX queue parameter attributes
  * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved
  * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*)
@@ -1936,4 +2424,341 @@
 	NL80211_TX_POWER_FIXED,
 };
 
+/**
+ * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute
+ * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute
+ * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has
+ *	a zero bit are ignored
+ * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have
+ *	a bit for each byte in the pattern. The lowest-order bit corresponds
+ *	to the first byte of the pattern, but the bytes of the pattern are
+ *	in a little-endian-like format, i.e. the 9th byte of the pattern
+ *	corresponds to the lowest-order bit in the second byte of the mask.
+ *	For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where
+ *	xx indicates "don't care") would be represented by a pattern of
+ *	twelve zero bytes, and a mask of "0xed,0x07".
+ *	Note that the pattern matching is done as though frames were not
+ *	802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
+ *	first (including SNAP header unpacking) and then matched.
+ * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
+ * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
+ */
+enum nl80211_wowlan_packet_pattern_attr {
+	__NL80211_WOWLAN_PKTPAT_INVALID,
+	NL80211_WOWLAN_PKTPAT_MASK,
+	NL80211_WOWLAN_PKTPAT_PATTERN,
+
+	NUM_NL80211_WOWLAN_PKTPAT,
+	MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
+};
+
+/**
+ * struct nl80211_wowlan_pattern_support - pattern support information
+ * @max_patterns: maximum number of patterns supported
+ * @min_pattern_len: minimum length of each pattern
+ * @max_pattern_len: maximum length of each pattern
+ *
+ * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when
+ * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
+ * capability information given by the kernel to userspace.
+ */
+struct nl80211_wowlan_pattern_support {
+	__u32 max_patterns;
+	__u32 min_pattern_len;
+	__u32 max_pattern_len;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_wowlan_triggers - WoWLAN trigger definitions
+ * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes
+ * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put
+ *	the chip into a special state -- works best with chips that have
+ *	support for low-power operation already (flag)
+ * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect
+ *	is detected is implementation-specific (flag)
+ * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed
+ *	by 16 repetitions of MAC addr, anywhere in payload) (flag)
+ * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns
+ *	which are passed in an array of nested attributes, each nested attribute
+ *	defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern.
+ *	Each pattern defines a wakeup packet. The matching is done on the MSDU,
+ *	i.e. as though the packet was an 802.3 packet, so the pattern matching
+ *	is done after the packet is converted to the MSDU.
+ *
+ *	In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
+ *	carrying a &struct nl80211_wowlan_pattern_support.
+ * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be
+ *	used when setting, used only to indicate that GTK rekeying is supported
+ *	by the device (flag)
+ * @NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: wake up on GTK rekey failure (if
+ *	done by the device) (flag)
+ * @NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: wake up on EAP Identity Request
+ *	packet (flag)
+ * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag)
+ * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released
+ *	(on devices that have rfkill in the device) (flag)
+ * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
+ * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
+ */
+enum nl80211_wowlan_triggers {
+	__NL80211_WOWLAN_TRIG_INVALID,
+	NL80211_WOWLAN_TRIG_ANY,
+	NL80211_WOWLAN_TRIG_DISCONNECT,
+	NL80211_WOWLAN_TRIG_MAGIC_PKT,
+	NL80211_WOWLAN_TRIG_PKT_PATTERN,
+	NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED,
+	NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE,
+	NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST,
+	NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE,
+	NL80211_WOWLAN_TRIG_RFKILL_RELEASE,
+
+	/* keep last */
+	NUM_NL80211_WOWLAN_TRIG,
+	MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1
+};
+
+/**
+ * enum nl80211_iface_limit_attrs - limit attributes
+ * @NL80211_IFACE_LIMIT_UNSPEC: (reserved)
+ * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that
+ *	can be chosen from this set of interface types (u32)
+ * @NL80211_IFACE_LIMIT_TYPES: nested attribute containing a
+ *	flag attribute for each interface type in this set
+ * @NUM_NL80211_IFACE_LIMIT: number of attributes
+ * @MAX_NL80211_IFACE_LIMIT: highest attribute number
+ */
+enum nl80211_iface_limit_attrs {
+	NL80211_IFACE_LIMIT_UNSPEC,
+	NL80211_IFACE_LIMIT_MAX,
+	NL80211_IFACE_LIMIT_TYPES,
+
+	/* keep last */
+	NUM_NL80211_IFACE_LIMIT,
+	MAX_NL80211_IFACE_LIMIT = NUM_NL80211_IFACE_LIMIT - 1
+};
+
+/**
+ * enum nl80211_if_combination_attrs -- interface combination attributes
+ *
+ * @NL80211_IFACE_COMB_UNSPEC: (reserved)
+ * @NL80211_IFACE_COMB_LIMITS: Nested attributes containing the limits
+ *	for given interface types, see &enum nl80211_iface_limit_attrs.
+ * @NL80211_IFACE_COMB_MAXNUM: u32 attribute giving the total number of
+ *	interfaces that can be created in this group. This number doesn't
+ *	apply to interfaces purely managed in software, which are listed
+ *	in a separate attribute %NL80211_ATTR_INTERFACES_SOFTWARE.
+ * @NL80211_IFACE_COMB_STA_AP_BI_MATCH: flag attribute specifying that
+ *	beacon intervals within this group must be all the same even for
+ *	infrastructure and AP/GO combinations, i.e. the GO(s) must adopt
+ *	the infrastructure network's beacon interval.
+ * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many
+ *	different channels may be used within this group.
+ * @NUM_NL80211_IFACE_COMB: number of attributes
+ * @MAX_NL80211_IFACE_COMB: highest attribute number
+ *
+ * Examples:
+ *	limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
+ *	=> allows an AP and a STA that must match BIs
+ *
+ *	numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
+ *	=> allows 8 of AP/GO
+ *
+ *	numbers = [ #{STA} <= 2 ], channels = 2, max = 2
+ *	=> allows two STAs on different channels
+ *
+ *	numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4
+ *	=> allows a STA plus three P2P interfaces
+ *
+ * The list of these four possiblities could completely be contained
+ * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate
+ * that any of these groups must match.
+ *
+ * "Combinations" of just a single interface will not be listed here,
+ * a single interface of any valid interface type is assumed to always
+ * be possible by itself. This means that implicitly, for each valid
+ * interface type, the following group always exists:
+ *	numbers = [ #{<type>} <= 1 ], channels = 1, max = 1
+ */
+enum nl80211_if_combination_attrs {
+	NL80211_IFACE_COMB_UNSPEC,
+	NL80211_IFACE_COMB_LIMITS,
+	NL80211_IFACE_COMB_MAXNUM,
+	NL80211_IFACE_COMB_STA_AP_BI_MATCH,
+	NL80211_IFACE_COMB_NUM_CHANNELS,
+
+	/* keep last */
+	NUM_NL80211_IFACE_COMB,
+	MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1
+};
+
+
+/**
+ * enum nl80211_plink_state - state of a mesh peer link finite state machine
+ *
+ * @NL80211_PLINK_LISTEN: initial state, considered the implicit
+ *	state of non existant mesh peer links
+ * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to
+ *	this mesh peer
+ * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received
+ *	from this mesh peer
+ * @NL80211_PLINK_CNF_RCVD: mesh plink confirm frame has been
+ *	received from this mesh peer
+ * @NL80211_PLINK_ESTAB: mesh peer link is established
+ * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled
+ * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh
+ *	plink are discarded
+ * @NUM_NL80211_PLINK_STATES: number of peer link states
+ * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states
+ */
+enum nl80211_plink_state {
+	NL80211_PLINK_LISTEN,
+	NL80211_PLINK_OPN_SNT,
+	NL80211_PLINK_OPN_RCVD,
+	NL80211_PLINK_CNF_RCVD,
+	NL80211_PLINK_ESTAB,
+	NL80211_PLINK_HOLDING,
+	NL80211_PLINK_BLOCKED,
+
+	/* keep last */
+	NUM_NL80211_PLINK_STATES,
+	MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1
+};
+
+#define NL80211_KCK_LEN			16
+#define NL80211_KEK_LEN			16
+#define NL80211_REPLAY_CTR_LEN		8
+
+/**
+ * enum nl80211_rekey_data - attributes for GTK rekey offload
+ * @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes
+ * @NL80211_REKEY_DATA_KEK: key encryption key (binary)
+ * @NL80211_REKEY_DATA_KCK: key confirmation key (binary)
+ * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary)
+ * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal)
+ * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal)
+ */
+enum nl80211_rekey_data {
+	__NL80211_REKEY_DATA_INVALID,
+	NL80211_REKEY_DATA_KEK,
+	NL80211_REKEY_DATA_KCK,
+	NL80211_REKEY_DATA_REPLAY_CTR,
+
+	/* keep last */
+	NUM_NL80211_REKEY_DATA,
+	MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1
+};
+
+/**
+ * enum nl80211_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID
+ * @NL80211_HIDDEN_SSID_NOT_IN_USE: do not hide SSID (i.e., broadcast it in
+ *	Beacon frames)
+ * @NL80211_HIDDEN_SSID_ZERO_LEN: hide SSID by using zero-length SSID element
+ *	in Beacon frames
+ * @NL80211_HIDDEN_SSID_ZERO_CONTENTS: hide SSID by using correct length of SSID
+ *	element in Beacon frames but zero out each byte in the SSID
+ */
+enum nl80211_hidden_ssid {
+	NL80211_HIDDEN_SSID_NOT_IN_USE,
+	NL80211_HIDDEN_SSID_ZERO_LEN,
+	NL80211_HIDDEN_SSID_ZERO_CONTENTS
+};
+
+/**
+ * enum nl80211_sta_wme_attr - station WME attributes
+ * @__NL80211_STA_WME_INVALID: invalid number for nested attribute
+ * @NL80211_STA_WME_UAPSD_QUEUES: bitmap of uapsd queues. the format
+ *	is the same as the AC bitmap in the QoS info field.
+ * @NL80211_STA_WME_MAX_SP: max service period. the format is the same
+ *	as the MAX_SP field in the QoS info field (but already shifted down).
+ * @__NL80211_STA_WME_AFTER_LAST: internal
+ * @NL80211_STA_WME_MAX: highest station WME attribute
+ */
+enum nl80211_sta_wme_attr {
+	__NL80211_STA_WME_INVALID,
+	NL80211_STA_WME_UAPSD_QUEUES,
+	NL80211_STA_WME_MAX_SP,
+
+	/* keep last */
+	__NL80211_STA_WME_AFTER_LAST,
+	NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1
+};
+
+/**
+ * enum nl80211_pmksa_candidate_attr - attributes for PMKSA caching candidates
+ * @__NL80211_PMKSA_CANDIDATE_INVALID: invalid number for nested attributes
+ * @NL80211_PMKSA_CANDIDATE_INDEX: candidate index (u32; the smaller, the higher
+ *	priority)
+ * @NL80211_PMKSA_CANDIDATE_BSSID: candidate BSSID (6 octets)
+ * @NL80211_PMKSA_CANDIDATE_PREAUTH: RSN pre-authentication supported (flag)
+ * @NUM_NL80211_PMKSA_CANDIDATE: number of PMKSA caching candidate attributes
+ *	(internal)
+ * @MAX_NL80211_PMKSA_CANDIDATE: highest PMKSA caching candidate attribute
+ *	(internal)
+ */
+enum nl80211_pmksa_candidate_attr {
+	__NL80211_PMKSA_CANDIDATE_INVALID,
+	NL80211_PMKSA_CANDIDATE_INDEX,
+	NL80211_PMKSA_CANDIDATE_BSSID,
+	NL80211_PMKSA_CANDIDATE_PREAUTH,
+
+	/* keep last */
+	NUM_NL80211_PMKSA_CANDIDATE,
+	MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1
+};
+
+/**
+ * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION
+ * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request
+ * @NL80211_TDLS_SETUP: Setup TDLS link
+ * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established
+ * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link
+ * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link
+ */
+enum nl80211_tdls_operation {
+	NL80211_TDLS_DISCOVERY_REQ,
+	NL80211_TDLS_SETUP,
+	NL80211_TDLS_TEARDOWN,
+	NL80211_TDLS_ENABLE_LINK,
+	NL80211_TDLS_DISABLE_LINK,
+};
+
+/*
+ * enum nl80211_ap_sme_features - device-integrated AP features
+ * Reserved for future use, no bits are defined in
+ * NL80211_ATTR_DEVICE_AP_SME yet.
+enum nl80211_ap_sme_features {
+};
+ */
+
+/**
+ * enum nl80211_feature_flags - device/driver features
+ * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back
+ *	TX status to the socket error queue when requested with the
+ *	socket option.
+ */
+enum nl80211_feature_flags {
+	NL80211_FEATURE_SK_TX_STATUS	= 1 << 0,
+};
+
+/**
+ * enum nl80211_probe_resp_offload_support_attr - optional supported
+ *	protocols for probe-response offloading by the driver/FW.
+ *	To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute.
+ *	Each enum value represents a bit in the bitmap of supported
+ *	protocols. Typically a subset of probe-requests belonging to a
+ *	supported protocol will be excluded from offload and uploaded
+ *	to the host.
+ *
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P
+ * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u
+ */
+enum nl80211_probe_resp_offload_support_attr {
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS =	1<<0,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 =	1<<1,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P =	1<<2,
+	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U =	1<<3,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/src/drivers/wireless_copy.h b/src/drivers/wireless_copy.h
deleted file mode 100644
index 201719b..0000000
--- a/src/drivers/wireless_copy.h
+++ /dev/null
@@ -1,1185 +0,0 @@
-/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 22.
- * I have just removed kernel related headers and added some typedefs etc. to
- * make this easier to include into user space programs.
- * Jouni Malinen, 2005-03-12.
- */
-
-
-/*
- * This file define a set of standard wireless extensions
- *
- * Version :	22	16.3.07
- *
- * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
- */
-
-#ifndef _LINUX_WIRELESS_H
-#define _LINUX_WIRELESS_H
-
-/************************** DOCUMENTATION **************************/
-/*
- * Initial APIs (1996 -> onward) :
- * -----------------------------
- * Basically, the wireless extensions are for now a set of standard ioctl
- * call + /proc/net/wireless
- *
- * The entry /proc/net/wireless give statistics and information on the
- * driver.
- * This is better than having each driver having its entry because
- * its centralised and we may remove the driver module safely.
- *
- * Ioctl are used to configure the driver and issue commands.  This is
- * better than command line options of insmod because we may want to
- * change dynamically (while the driver is running) some parameters.
- *
- * The ioctl mechanimsm are copied from standard devices ioctl.
- * We have the list of command plus a structure descibing the
- * data exchanged...
- * Note that to add these ioctl, I was obliged to modify :
- *	# net/core/dev.c (two place + add include)
- *	# net/ipv4/af_inet.c (one place + add include)
- *
- * /proc/net/wireless is a copy of /proc/net/dev.
- * We have a structure for data passed from the driver to /proc/net/wireless
- * Too add this, I've modified :
- *	# net/core/dev.c (two other places)
- *	# include/linux/netdevice.h (one place)
- *	# include/linux/proc_fs.h (one place)
- *
- * New driver API (2002 -> onward) :
- * -------------------------------
- * This file is only concerned with the user space API and common definitions.
- * The new driver API is defined and documented in :
- *	# include/net/iw_handler.h
- *
- * Note as well that /proc/net/wireless implementation has now moved in :
- *	# net/core/wireless.c
- *
- * Wireless Events (2002 -> onward) :
- * --------------------------------
- * Events are defined at the end of this file, and implemented in :
- *	# net/core/wireless.c
- *
- * Other comments :
- * --------------
- * Do not add here things that are redundant with other mechanisms
- * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
- * wireless specific.
- *
- * These wireless extensions are not magic : each driver has to provide
- * support for them...
- *
- * IMPORTANT NOTE : As everything in the kernel, this is very much a
- * work in progress. Contact me if you have ideas of improvements...
- */
-
-/***************************** INCLUDES *****************************/
-
- /* jkm - replaced linux headers with C library headers, added typedefs */
-#if 0
-#include <linux/types.h>		/* for __u* and __s* typedefs */
-#include <linux/socket.h>		/* for "struct sockaddr" et al	*/
-#include <linux/if.h>			/* for IFNAMSIZ and co... */
-#else
-#include <sys/types.h>
-#include <net/if.h>
-#ifndef ANDROID
-typedef __uint32_t __u32;
-typedef __int32_t __s32;
-typedef __uint16_t __u16;
-typedef __int16_t __s16;
-typedef __uint8_t __u8;
-#endif /* ANDROID */
-#ifndef __user
-#define __user
-#endif /* __user */
-#endif
-
-/***************************** VERSION *****************************/
-/*
- * This constant is used to know the availability of the wireless
- * extensions and to know which version of wireless extensions it is
- * (there is some stuff that will be added in the future...)
- * I just plan to increment with each new version.
- */
-#define WIRELESS_EXT	22
-
-/*
- * Changes :
- *
- * V2 to V3
- * --------
- *	Alan Cox start some incompatibles changes. I've integrated a bit more.
- *	- Encryption renamed to Encode to avoid US regulation problems
- *	- Frequency changed from float to struct to avoid problems on old 386
- *
- * V3 to V4
- * --------
- *	- Add sensitivity
- *
- * V4 to V5
- * --------
- *	- Missing encoding definitions in range
- *	- Access points stuff
- *
- * V5 to V6
- * --------
- *	- 802.11 support (ESSID ioctls)
- *
- * V6 to V7
- * --------
- *	- define IW_ESSID_MAX_SIZE and IW_MAX_AP
- *
- * V7 to V8
- * --------
- *	- Changed my e-mail address
- *	- More 802.11 support (nickname, rate, rts, frag)
- *	- List index in frequencies
- *
- * V8 to V9
- * --------
- *	- Support for 'mode of operation' (ad-hoc, managed...)
- *	- Support for unicast and multicast power saving
- *	- Change encoding to support larger tokens (>64 bits)
- *	- Updated iw_params (disable, flags) and use it for NWID
- *	- Extracted iw_point from iwreq for clarity
- *
- * V9 to V10
- * ---------
- *	- Add PM capability to range structure
- *	- Add PM modifier : MAX/MIN/RELATIVE
- *	- Add encoding option : IW_ENCODE_NOKEY
- *	- Add TxPower ioctls (work like TxRate)
- *
- * V10 to V11
- * ----------
- *	- Add WE version in range (help backward/forward compatibility)
- *	- Add retry ioctls (work like PM)
- *
- * V11 to V12
- * ----------
- *	- Add SIOCSIWSTATS to get /proc/net/wireless programatically
- *	- Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
- *	- Add new statistics (frag, retry, beacon)
- *	- Add average quality (for user space calibration)
- *
- * V12 to V13
- * ----------
- *	- Document creation of new driver API.
- *	- Extract union iwreq_data from struct iwreq (for new driver API).
- *	- Rename SIOCSIWNAME as SIOCSIWCOMMIT
- *
- * V13 to V14
- * ----------
- *	- Wireless Events support : define struct iw_event
- *	- Define additional specific event numbers
- *	- Add "addr" and "param" fields in union iwreq_data
- *	- AP scanning stuff (SIOCSIWSCAN and friends)
- *
- * V14 to V15
- * ----------
- *	- Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
- *	- Make struct iw_freq signed (both m & e), add explicit padding
- *	- Add IWEVCUSTOM for driver specific event/scanning token
- *	- Add IW_MAX_GET_SPY for driver returning a lot of addresses
- *	- Add IW_TXPOW_RANGE for range of Tx Powers
- *	- Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
- *	- Add IW_MODE_MONITOR for passive monitor
- *
- * V15 to V16
- * ----------
- *	- Increase the number of bitrates in iw_range to 32 (for 802.11g)
- *	- Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
- *	- Reshuffle struct iw_range for increases, add filler
- *	- Increase IW_MAX_AP to 64 for driver returning a lot of addresses
- *	- Remove IW_MAX_GET_SPY because conflict with enhanced spy support
- *	- Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
- *	- Add IW_ENCODE_TEMP and iw_range->encoding_login_index
- *
- * V16 to V17
- * ----------
- *	- Add flags to frequency -> auto/fixed
- *	- Document (struct iw_quality *)->updated, add new flags (INVALID)
- *	- Wireless Event capability in struct iw_range
- *	- Add support for relative TxPower (yick !)
- *
- * V17 to V18 (From Jouni Malinen <j@w1.fi>)
- * ----------
- *	- Add support for WPA/WPA2
- *	- Add extended encoding configuration (SIOCSIWENCODEEXT and
- *	  SIOCGIWENCODEEXT)
- *	- Add SIOCSIWGENIE/SIOCGIWGENIE
- *	- Add SIOCSIWMLME
- *	- Add SIOCSIWPMKSA
- *	- Add struct iw_range bit field for supported encoding capabilities
- *	- Add optional scan request parameters for SIOCSIWSCAN
- *	- Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
- *	  related parameters (extensible up to 4096 parameter values)
- *	- Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
- *	  IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
- *
- * V18 to V19
- * ----------
- *	- Remove (struct iw_point *)->pointer from events and streams
- *	- Remove header includes to help user space
- *	- Increase IW_ENCODING_TOKEN_MAX from 32 to 64
- *	- Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros
- *	- Add explicit flag to tell stats are in dBm : IW_QUAL_DBM
- *	- Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros
- *
- * V19 to V20
- * ----------
- *	- RtNetlink requests support (SET/GET)
- *
- * V20 to V21
- * ----------
- *	- Remove (struct net_device *)->get_wireless_stats()
- *	- Change length in ESSID and NICK to strlen() instead of strlen()+1
- *	- Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
- *	- Power/Retry relative values no longer * 100000
- *	- Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
- *
- * V21 to V22
- * ----------
- *	- Prevent leaking of kernel space in stream on 64 bits.
- */
-
-/**************************** CONSTANTS ****************************/
-
-/* -------------------------- IOCTL LIST -------------------------- */
-
-/* Wireless Identification */
-#define SIOCSIWCOMMIT	0x8B00		/* Commit pending changes to driver */
-#define SIOCGIWNAME	0x8B01		/* get name == wireless protocol */
-/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
- * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
- * Don't put the name of your driver there, it's useless. */
-
-/* Basic operations */
-#define SIOCSIWNWID	0x8B02		/* set network id (pre-802.11) */
-#define SIOCGIWNWID	0x8B03		/* get network id (the cell) */
-#define SIOCSIWFREQ	0x8B04		/* set channel/frequency (Hz) */
-#define SIOCGIWFREQ	0x8B05		/* get channel/frequency (Hz) */
-#define SIOCSIWMODE	0x8B06		/* set operation mode */
-#define SIOCGIWMODE	0x8B07		/* get operation mode */
-#define SIOCSIWSENS	0x8B08		/* set sensitivity (dBm) */
-#define SIOCGIWSENS	0x8B09		/* get sensitivity (dBm) */
-
-/* Informative stuff */
-#define SIOCSIWRANGE	0x8B0A		/* Unused */
-#define SIOCGIWRANGE	0x8B0B		/* Get range of parameters */
-#define SIOCSIWPRIV	0x8B0C		/* Unused */
-#define SIOCGIWPRIV	0x8B0D		/* get private ioctl interface info */
-#define SIOCSIWSTATS	0x8B0E		/* Unused */
-#define SIOCGIWSTATS	0x8B0F		/* Get /proc/net/wireless stats */
-/* SIOCGIWSTATS is strictly used between user space and the kernel, and
- * is never passed to the driver (i.e. the driver will never see it). */
-
-/* Spy support (statistics per MAC address - used for Mobile IP support) */
-#define SIOCSIWSPY	0x8B10		/* set spy addresses */
-#define SIOCGIWSPY	0x8B11		/* get spy info (quality of link) */
-#define SIOCSIWTHRSPY	0x8B12		/* set spy threshold (spy event) */
-#define SIOCGIWTHRSPY	0x8B13		/* get spy threshold */
-
-/* Access Point manipulation */
-#define SIOCSIWAP	0x8B14		/* set access point MAC addresses */
-#define SIOCGIWAP	0x8B15		/* get access point MAC addresses */
-#define SIOCGIWAPLIST	0x8B17		/* Deprecated in favor of scanning */
-#define SIOCSIWSCAN	0x8B18		/* trigger scanning (list cells) */
-#define SIOCGIWSCAN	0x8B19		/* get scanning results */
-
-/* 802.11 specific support */
-#define SIOCSIWESSID	0x8B1A		/* set ESSID (network name) */
-#define SIOCGIWESSID	0x8B1B		/* get ESSID */
-#define SIOCSIWNICKN	0x8B1C		/* set node name/nickname */
-#define SIOCGIWNICKN	0x8B1D		/* get node name/nickname */
-/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
- * within the 'iwreq' structure, so we need to use the 'data' member to
- * point to a string in user space, like it is done for RANGE... */
-
-/* Other parameters useful in 802.11 and some other devices */
-#define SIOCSIWRATE	0x8B20		/* set default bit rate (bps) */
-#define SIOCGIWRATE	0x8B21		/* get default bit rate (bps) */
-#define SIOCSIWRTS	0x8B22		/* set RTS/CTS threshold (bytes) */
-#define SIOCGIWRTS	0x8B23		/* get RTS/CTS threshold (bytes) */
-#define SIOCSIWFRAG	0x8B24		/* set fragmentation thr (bytes) */
-#define SIOCGIWFRAG	0x8B25		/* get fragmentation thr (bytes) */
-#define SIOCSIWTXPOW	0x8B26		/* set transmit power (dBm) */
-#define SIOCGIWTXPOW	0x8B27		/* get transmit power (dBm) */
-#define SIOCSIWRETRY	0x8B28		/* set retry limits and lifetime */
-#define SIOCGIWRETRY	0x8B29		/* get retry limits and lifetime */
-
-/* Encoding stuff (scrambling, hardware security, WEP...) */
-#define SIOCSIWENCODE	0x8B2A		/* set encoding token & mode */
-#define SIOCGIWENCODE	0x8B2B		/* get encoding token & mode */
-/* Power saving stuff (power management, unicast and multicast) */
-#define SIOCSIWPOWER	0x8B2C		/* set Power Management settings */
-#define SIOCGIWPOWER	0x8B2D		/* get Power Management settings */
-
-/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
- * This ioctl uses struct iw_point and data buffer that includes IE id and len
- * fields. More than one IE may be included in the request. Setting the generic
- * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
- * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
- * are required to report the used IE as a wireless event, e.g., when
- * associating with an AP. */
-#define SIOCSIWGENIE	0x8B30		/* set generic IE */
-#define SIOCGIWGENIE	0x8B31		/* get generic IE */
-
-/* WPA : IEEE 802.11 MLME requests */
-#define SIOCSIWMLME	0x8B16		/* request MLME operation; uses
-					 * struct iw_mlme */
-/* WPA : Authentication mode parameters */
-#define SIOCSIWAUTH	0x8B32		/* set authentication mode params */
-#define SIOCGIWAUTH	0x8B33		/* get authentication mode params */
-
-/* WPA : Extended version of encoding configuration */
-#define SIOCSIWENCODEEXT 0x8B34		/* set encoding token & mode */
-#define SIOCGIWENCODEEXT 0x8B35		/* get encoding token & mode */
-
-/* WPA2 : PMKSA cache management */
-#define SIOCSIWPMKSA	0x8B36		/* PMKSA cache operation */
-
-/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
-
-/* These 32 ioctl are wireless device private, for 16 commands.
- * Each driver is free to use them for whatever purpose it chooses,
- * however the driver *must* export the description of those ioctls
- * with SIOCGIWPRIV and *must* use arguments as defined below.
- * If you don't follow those rules, DaveM is going to hate you (reason :
- * it make mixed 32/64bit operation impossible).
- */
-#define SIOCIWFIRSTPRIV	0x8BE0
-#define SIOCIWLASTPRIV	0x8BFF
-/* Previously, we were using SIOCDEVPRIVATE, but we now have our
- * separate range because of collisions with other tools such as
- * 'mii-tool'.
- * We now have 32 commands, so a bit more space ;-).
- * Also, all 'even' commands are only usable by root and don't return the
- * content of ifr/iwr to user (but you are not obliged to use the set/get
- * convention, just use every other two command). More details in iwpriv.c.
- * And I repeat : you are not forced to use them with iwpriv, but you
- * must be compliant with it.
- */
-
-/* ------------------------- IOCTL STUFF ------------------------- */
-
-/* The first and the last (range) */
-#define SIOCIWFIRST	0x8B00
-#define SIOCIWLAST	SIOCIWLASTPRIV		/* 0x8BFF */
-#define IW_IOCTL_IDX(cmd)	((cmd) - SIOCIWFIRST)
-#define IW_HANDLER(id, func)			\
-	[IW_IOCTL_IDX(id)] = func
-
-/* Odd : get (world access), even : set (root access) */
-#define IW_IS_SET(cmd)	(!((cmd) & 0x1))
-#define IW_IS_GET(cmd)	((cmd) & 0x1)
-
-/* ----------------------- WIRELESS EVENTS ----------------------- */
-/* Those are *NOT* ioctls, do not issue request on them !!! */
-/* Most events use the same identifier as ioctl requests */
-
-#define IWEVTXDROP	0x8C00		/* Packet dropped to excessive retry */
-#define IWEVQUAL	0x8C01		/* Quality part of statistics (scan) */
-#define IWEVCUSTOM	0x8C02		/* Driver specific ascii string */
-#define IWEVREGISTERED	0x8C03		/* Discovered a new node (AP mode) */
-#define IWEVEXPIRED	0x8C04		/* Expired a node (AP mode) */
-#define IWEVGENIE	0x8C05		/* Generic IE (WPA, RSN, WMM, ..)
-					 * (scan results); This includes id and
-					 * length fields. One IWEVGENIE may
-					 * contain more than one IE. Scan
-					 * results may contain one or more
-					 * IWEVGENIE events. */
-#define IWEVMICHAELMICFAILURE 0x8C06	/* Michael MIC failure
-					 * (struct iw_michaelmicfailure)
-					 */
-#define IWEVASSOCREQIE	0x8C07		/* IEs used in (Re)Association Request.
-					 * The data includes id and length
-					 * fields and may contain more than one
-					 * IE. This event is required in
-					 * Managed mode if the driver
-					 * generates its own WPA/RSN IE. This
-					 * should be sent just before
-					 * IWEVREGISTERED event for the
-					 * association. */
-#define IWEVASSOCRESPIE	0x8C08		/* IEs used in (Re)Association
-					 * Response. The data includes id and
-					 * length fields and may contain more
-					 * than one IE. This may be sent
-					 * between IWEVASSOCREQIE and
-					 * IWEVREGISTERED events for the
-					 * association. */
-#define IWEVPMKIDCAND	0x8C09		/* PMKID candidate for RSN
-					 * pre-authentication
-					 * (struct iw_pmkid_cand) */
-
-#define IWEVFIRST	0x8C00
-#define IW_EVENT_IDX(cmd)	((cmd) - IWEVFIRST)
-
-/* ------------------------- PRIVATE INFO ------------------------- */
-/*
- * The following is used with SIOCGIWPRIV. It allow a driver to define
- * the interface (name, type of data) for its private ioctl.
- * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV
- */
-
-#define IW_PRIV_TYPE_MASK	0x7000	/* Type of arguments */
-#define IW_PRIV_TYPE_NONE	0x0000
-#define IW_PRIV_TYPE_BYTE	0x1000	/* Char as number */
-#define IW_PRIV_TYPE_CHAR	0x2000	/* Char as character */
-#define IW_PRIV_TYPE_INT	0x4000	/* 32 bits int */
-#define IW_PRIV_TYPE_FLOAT	0x5000	/* struct iw_freq */
-#define IW_PRIV_TYPE_ADDR	0x6000	/* struct sockaddr */
-
-#define IW_PRIV_SIZE_FIXED	0x0800	/* Variable or fixed number of args */
-
-#define IW_PRIV_SIZE_MASK	0x07FF	/* Max number of those args */
-
-/*
- * Note : if the number of args is fixed and the size < 16 octets,
- * instead of passing a pointer we will put args in the iwreq struct...
- */
-
-/* ----------------------- OTHER CONSTANTS ----------------------- */
-
-/* Maximum frequencies in the range struct */
-#define IW_MAX_FREQUENCIES	32
-/* Note : if you have something like 80 frequencies,
- * don't increase this constant and don't fill the frequency list.
- * The user will be able to set by channel anyway... */
-
-/* Maximum bit rates in the range struct */
-#define IW_MAX_BITRATES		32
-
-/* Maximum tx powers in the range struct */
-#define IW_MAX_TXPOWER		8
-/* Note : if you more than 8 TXPowers, just set the max and min or
- * a few of them in the struct iw_range. */
-
-/* Maximum of address that you may set with SPY */
-#define IW_MAX_SPY		8
-
-/* Maximum of address that you may get in the
-   list of access points in range */
-#define IW_MAX_AP		64
-
-/* Maximum size of the ESSID and NICKN strings */
-#define IW_ESSID_MAX_SIZE	32
-
-/* Modes of operation */
-#define IW_MODE_AUTO	0	/* Let the driver decides */
-#define IW_MODE_ADHOC	1	/* Single cell network */
-#define IW_MODE_INFRA	2	/* Multi cell network, roaming, ... */
-#define IW_MODE_MASTER	3	/* Synchronisation master or Access Point */
-#define IW_MODE_REPEAT	4	/* Wireless Repeater (forwarder) */
-#define IW_MODE_SECOND	5	/* Secondary master/repeater (backup) */
-#define IW_MODE_MONITOR	6	/* Passive monitor (listen only) */
-#define IW_MODE_MESH	7	/* Mesh (IEEE 802.11s) network */
-
-/* Statistics flags (bitmask in updated) */
-#define IW_QUAL_QUAL_UPDATED	0x01	/* Value was updated since last read */
-#define IW_QUAL_LEVEL_UPDATED	0x02
-#define IW_QUAL_NOISE_UPDATED	0x04
-#define IW_QUAL_ALL_UPDATED	0x07
-#define IW_QUAL_DBM		0x08	/* Level + Noise are dBm */
-#define IW_QUAL_QUAL_INVALID	0x10	/* Driver doesn't provide value */
-#define IW_QUAL_LEVEL_INVALID	0x20
-#define IW_QUAL_NOISE_INVALID	0x40
-#define IW_QUAL_RCPI		0x80	/* Level + Noise are 802.11k RCPI */
-#define IW_QUAL_ALL_INVALID	0x70
-
-/* Frequency flags */
-#define IW_FREQ_AUTO		0x00	/* Let the driver decides */
-#define IW_FREQ_FIXED		0x01	/* Force a specific value */
-
-/* Maximum number of size of encoding token available
- * they are listed in the range structure */
-#define IW_MAX_ENCODING_SIZES	8
-
-/* Maximum size of the encoding token in bytes */
-#define IW_ENCODING_TOKEN_MAX	64	/* 512 bits (for now) */
-
-/* Flags for encoding (along with the token) */
-#define IW_ENCODE_INDEX		0x00FF	/* Token index (if needed) */
-#define IW_ENCODE_FLAGS		0xFF00	/* Flags defined below */
-#define IW_ENCODE_MODE		0xF000	/* Modes defined below */
-#define IW_ENCODE_DISABLED	0x8000	/* Encoding disabled */
-#define IW_ENCODE_ENABLED	0x0000	/* Encoding enabled */
-#define IW_ENCODE_RESTRICTED	0x4000	/* Refuse non-encoded packets */
-#define IW_ENCODE_OPEN		0x2000	/* Accept non-encoded packets */
-#define IW_ENCODE_NOKEY		0x0800  /* Key is write only, so not present */
-#define IW_ENCODE_TEMP		0x0400  /* Temporary key */
-
-/* Power management flags available (along with the value, if any) */
-#define IW_POWER_ON		0x0000	/* No details... */
-#define IW_POWER_TYPE		0xF000	/* Type of parameter */
-#define IW_POWER_PERIOD		0x1000	/* Value is a period/duration of  */
-#define IW_POWER_TIMEOUT	0x2000	/* Value is a timeout (to go asleep) */
-#define IW_POWER_MODE		0x0F00	/* Power Management mode */
-#define IW_POWER_UNICAST_R	0x0100	/* Receive only unicast messages */
-#define IW_POWER_MULTICAST_R	0x0200	/* Receive only multicast messages */
-#define IW_POWER_ALL_R		0x0300	/* Receive all messages though PM */
-#define IW_POWER_FORCE_S	0x0400	/* Force PM procedure for sending unicast */
-#define IW_POWER_REPEATER	0x0800	/* Repeat broadcast messages in PM period */
-#define IW_POWER_MODIFIER	0x000F	/* Modify a parameter */
-#define IW_POWER_MIN		0x0001	/* Value is a minimum  */
-#define IW_POWER_MAX		0x0002	/* Value is a maximum */
-#define IW_POWER_RELATIVE	0x0004	/* Value is not in seconds/ms/us */
-
-/* Transmit Power flags available */
-#define IW_TXPOW_TYPE		0x00FF	/* Type of value */
-#define IW_TXPOW_DBM		0x0000	/* Value is in dBm */
-#define IW_TXPOW_MWATT		0x0001	/* Value is in mW */
-#define IW_TXPOW_RELATIVE	0x0002	/* Value is in arbitrary units */
-#define IW_TXPOW_RANGE		0x1000	/* Range of value between min/max */
-
-/* Retry limits and lifetime flags available */
-#define IW_RETRY_ON		0x0000	/* No details... */
-#define IW_RETRY_TYPE		0xF000	/* Type of parameter */
-#define IW_RETRY_LIMIT		0x1000	/* Maximum number of retries*/
-#define IW_RETRY_LIFETIME	0x2000	/* Maximum duration of retries in us */
-#define IW_RETRY_MODIFIER	0x00FF	/* Modify a parameter */
-#define IW_RETRY_MIN		0x0001	/* Value is a minimum  */
-#define IW_RETRY_MAX		0x0002	/* Value is a maximum */
-#define IW_RETRY_RELATIVE	0x0004	/* Value is not in seconds/ms/us */
-#define IW_RETRY_SHORT		0x0010	/* Value is for short packets  */
-#define IW_RETRY_LONG		0x0020	/* Value is for long packets */
-
-/* Scanning request flags */
-#define IW_SCAN_DEFAULT		0x0000	/* Default scan of the driver */
-#define IW_SCAN_ALL_ESSID	0x0001	/* Scan all ESSIDs */
-#define IW_SCAN_THIS_ESSID	0x0002	/* Scan only this ESSID */
-#define IW_SCAN_ALL_FREQ	0x0004	/* Scan all Frequencies */
-#define IW_SCAN_THIS_FREQ	0x0008	/* Scan only this Frequency */
-#define IW_SCAN_ALL_MODE	0x0010	/* Scan all Modes */
-#define IW_SCAN_THIS_MODE	0x0020	/* Scan only this Mode */
-#define IW_SCAN_ALL_RATE	0x0040	/* Scan all Bit-Rates */
-#define IW_SCAN_THIS_RATE	0x0080	/* Scan only this Bit-Rate */
-/* struct iw_scan_req scan_type */
-#define IW_SCAN_TYPE_ACTIVE 0
-#define IW_SCAN_TYPE_PASSIVE 1
-/* Maximum size of returned data */
-#define IW_SCAN_MAX_DATA	4096	/* In bytes */
-
-/* Scan capability flags - in (struct iw_range *)->scan_capa */
-#define IW_SCAN_CAPA_NONE		0x00
-#define IW_SCAN_CAPA_ESSID		0x01
-#define IW_SCAN_CAPA_BSSID		0x02
-#define IW_SCAN_CAPA_CHANNEL	0x04
-#define IW_SCAN_CAPA_MODE		0x08
-#define IW_SCAN_CAPA_RATE		0x10
-#define IW_SCAN_CAPA_TYPE		0x20
-#define IW_SCAN_CAPA_TIME		0x40
-
-/* Max number of char in custom event - use multiple of them if needed */
-#define IW_CUSTOM_MAX		256	/* In bytes */
-
-/* Generic information element */
-#define IW_GENERIC_IE_MAX	1024
-
-/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
-#define IW_MLME_DEAUTH		0
-#define IW_MLME_DISASSOC	1
-#define IW_MLME_AUTH		2
-#define IW_MLME_ASSOC		3
-
-/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
-#define IW_AUTH_INDEX		0x0FFF
-#define IW_AUTH_FLAGS		0xF000
-/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
- * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
- * parameter that is being set/get to; value will be read/written to
- * struct iw_param value field) */
-#define IW_AUTH_WPA_VERSION		0
-#define IW_AUTH_CIPHER_PAIRWISE		1
-#define IW_AUTH_CIPHER_GROUP		2
-#define IW_AUTH_KEY_MGMT		3
-#define IW_AUTH_TKIP_COUNTERMEASURES	4
-#define IW_AUTH_DROP_UNENCRYPTED	5
-#define IW_AUTH_80211_AUTH_ALG		6
-#define IW_AUTH_WPA_ENABLED		7
-#define IW_AUTH_RX_UNENCRYPTED_EAPOL	8
-#define IW_AUTH_ROAMING_CONTROL		9
-#define IW_AUTH_PRIVACY_INVOKED		10
-#define IW_AUTH_CIPHER_GROUP_MGMT	11
-#define IW_AUTH_MFP			12
-
-/* IW_AUTH_WPA_VERSION values (bit field) */
-#define IW_AUTH_WPA_VERSION_DISABLED	0x00000001
-#define IW_AUTH_WPA_VERSION_WPA		0x00000002
-#define IW_AUTH_WPA_VERSION_WPA2	0x00000004
-
-/* IW_AUTH_PAIRWISE_CIPHER, IW_AUTH_GROUP_CIPHER, and IW_AUTH_CIPHER_GROUP_MGMT
- * values (bit field) */
-#define IW_AUTH_CIPHER_NONE	0x00000001
-#define IW_AUTH_CIPHER_WEP40	0x00000002
-#define IW_AUTH_CIPHER_TKIP	0x00000004
-#define IW_AUTH_CIPHER_CCMP	0x00000008
-#define IW_AUTH_CIPHER_WEP104	0x00000010
-#define IW_AUTH_CIPHER_AES_CMAC	0x00000020
-
-/* IW_AUTH_KEY_MGMT values (bit field) */
-#define IW_AUTH_KEY_MGMT_802_1X	1
-#define IW_AUTH_KEY_MGMT_PSK	2
-
-/* IW_AUTH_80211_AUTH_ALG values (bit field) */
-#define IW_AUTH_ALG_OPEN_SYSTEM	0x00000001
-#define IW_AUTH_ALG_SHARED_KEY	0x00000002
-#define IW_AUTH_ALG_LEAP	0x00000004
-
-/* IW_AUTH_ROAMING_CONTROL values */
-#define IW_AUTH_ROAMING_ENABLE	0	/* driver/firmware based roaming */
-#define IW_AUTH_ROAMING_DISABLE	1	/* user space program used for roaming
-					 * control */
-
-/* IW_AUTH_MFP (management frame protection) values */
-#define IW_AUTH_MFP_DISABLED	0	/* MFP disabled */
-#define IW_AUTH_MFP_OPTIONAL	1	/* MFP optional */
-#define IW_AUTH_MFP_REQUIRED	2	/* MFP required */
-
-/* SIOCSIWENCODEEXT definitions */
-#define IW_ENCODE_SEQ_MAX_SIZE	8
-/* struct iw_encode_ext ->alg */
-#define IW_ENCODE_ALG_NONE	0
-#define IW_ENCODE_ALG_WEP	1
-#define IW_ENCODE_ALG_TKIP	2
-#define IW_ENCODE_ALG_CCMP	3
-#define IW_ENCODE_ALG_PMK	4
-#define IW_ENCODE_ALG_AES_CMAC	5
-/* struct iw_encode_ext ->ext_flags */
-#define IW_ENCODE_EXT_TX_SEQ_VALID	0x00000001
-#define IW_ENCODE_EXT_RX_SEQ_VALID	0x00000002
-#define IW_ENCODE_EXT_GROUP_KEY		0x00000004
-#define IW_ENCODE_EXT_SET_TX_KEY	0x00000008
-
-/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
-#define IW_MICFAILURE_KEY_ID	0x00000003 /* Key ID 0..3 */
-#define IW_MICFAILURE_GROUP	0x00000004
-#define IW_MICFAILURE_PAIRWISE	0x00000008
-#define IW_MICFAILURE_STAKEY	0x00000010
-#define IW_MICFAILURE_COUNT	0x00000060 /* 1 or 2 (0 = count not supported)
-					    */
-
-/* Bit field values for enc_capa in struct iw_range */
-#define IW_ENC_CAPA_WPA		0x00000001
-#define IW_ENC_CAPA_WPA2	0x00000002
-#define IW_ENC_CAPA_CIPHER_TKIP	0x00000004
-#define IW_ENC_CAPA_CIPHER_CCMP	0x00000008
-#define IW_ENC_CAPA_4WAY_HANDSHAKE	0x00000010
-
-/* Event capability macros - in (struct iw_range *)->event_capa
- * Because we have more than 32 possible events, we use an array of
- * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
-#define IW_EVENT_CAPA_BASE(cmd)		((cmd >= SIOCIWFIRSTPRIV) ? \
-					 (cmd - SIOCIWFIRSTPRIV + 0x60) : \
-					 (cmd - SIOCIWFIRST))
-#define IW_EVENT_CAPA_INDEX(cmd)	(IW_EVENT_CAPA_BASE(cmd) >> 5)
-#define IW_EVENT_CAPA_MASK(cmd)		(1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F))
-/* Event capability constants - event autogenerated by the kernel
- * This list is valid for most 802.11 devices, customise as needed... */
-#define IW_EVENT_CAPA_K_0	(IW_EVENT_CAPA_MASK(0x8B04) | \
-				 IW_EVENT_CAPA_MASK(0x8B06) | \
-				 IW_EVENT_CAPA_MASK(0x8B1A))
-#define IW_EVENT_CAPA_K_1	(IW_EVENT_CAPA_MASK(0x8B2A))
-/* "Easy" macro to set events in iw_range (less efficient) */
-#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd))
-#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; }
-
-
-/****************************** TYPES ******************************/
-
-/* --------------------------- SUBTYPES --------------------------- */
-/*
- *	Generic format for most parameters that fit in an int
- */
-struct	iw_param
-{
-  __s32		value;		/* The value of the parameter itself */
-  __u8		fixed;		/* Hardware should not use auto select */
-  __u8		disabled;	/* Disable the feature */
-  __u16		flags;		/* Various specifc flags (if any) */
-};
-
-/*
- *	For all data larger than 16 octets, we need to use a
- *	pointer to memory allocated in user space.
- */
-struct	iw_point
-{
-  void __user	*pointer;	/* Pointer to the data  (in user space) */
-  __u16		length;		/* number of fields or size in bytes */
-  __u16		flags;		/* Optional params */
-};
-
-#ifdef __KERNEL__
-#ifdef CONFIG_COMPAT
-
-#include <linux/compat.h>
-
-struct compat_iw_point {
-	compat_caddr_t pointer;
-	__u16 length;
-	__u16 flags;
-};
-#endif
-#endif
-
-/*
- *	A frequency
- *	For numbers lower than 10^9, we encode the number in 'm' and
- *	set 'e' to 0
- *	For number greater than 10^9, we divide it by the lowest power
- *	of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
- *	The power of 10 is in 'e', the result of the division is in 'm'.
- */
-struct	iw_freq
-{
-	__s32		m;		/* Mantissa */
-	__s16		e;		/* Exponent */
-	__u8		i;		/* List index (when in range struct) */
-	__u8		flags;		/* Flags (fixed/auto) */
-};
-
-/*
- *	Quality of the link
- */
-struct	iw_quality
-{
-	__u8		qual;		/* link quality (%retries, SNR,
-					   %missed beacons or better...) */
-	__u8		level;		/* signal level (dBm) */
-	__u8		noise;		/* noise level (dBm) */
-	__u8		updated;	/* Flags to know if updated */
-};
-
-/*
- *	Packet discarded in the wireless adapter due to
- *	"wireless" specific problems...
- *	Note : the list of counter and statistics in net_device_stats
- *	is already pretty exhaustive, and you should use that first.
- *	This is only additional stats...
- */
-struct	iw_discarded
-{
-	__u32		nwid;		/* Rx : Wrong nwid/essid */
-	__u32		code;		/* Rx : Unable to code/decode (WEP) */
-	__u32		fragment;	/* Rx : Can't perform MAC reassembly */
-	__u32		retries;	/* Tx : Max MAC retries num reached */
-	__u32		misc;		/* Others cases */
-};
-
-/*
- *	Packet/Time period missed in the wireless adapter due to
- *	"wireless" specific problems...
- */
-struct	iw_missed
-{
-	__u32		beacon;		/* Missed beacons/superframe */
-};
-
-/*
- *	Quality range (for spy threshold)
- */
-struct	iw_thrspy
-{
-	struct sockaddr		addr;		/* Source address (hw/mac) */
-	struct iw_quality	qual;		/* Quality of the link */
-	struct iw_quality	low;		/* Low threshold */
-	struct iw_quality	high;		/* High threshold */
-};
-
-/*
- *	Optional data for scan request
- *
- *	Note: these optional parameters are controlling parameters for the
- *	scanning behavior, these do not apply to getting scan results
- *	(SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
- *	provide a merged results with all BSSes even if the previous scan
- *	request limited scanning to a subset, e.g., by specifying an SSID.
- *	Especially, scan results are required to include an entry for the
- *	current BSS if the driver is in Managed mode and associated with an AP.
- */
-struct	iw_scan_req
-{
-	__u8		scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
-	__u8		essid_len;
-	__u8		num_channels; /* num entries in channel_list;
-				       * 0 = scan all allowed channels */
-	__u8		flags; /* reserved as padding; use zero, this may
-				* be used in the future for adding flags
-				* to request different scan behavior */
-	struct sockaddr	bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
-				* individual address of a specific BSS */
-
-	/*
-	 * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
-	 * the current ESSID. This allows scan requests for specific ESSID
-	 * without having to change the current ESSID and potentially breaking
-	 * the current association.
-	 */
-	__u8		essid[IW_ESSID_MAX_SIZE];
-
-	/*
-	 * Optional parameters for changing the default scanning behavior.
-	 * These are based on the MLME-SCAN.request from IEEE Std 802.11.
-	 * TU is 1.024 ms. If these are set to 0, driver is expected to use
-	 * reasonable default values. min_channel_time defines the time that
-	 * will be used to wait for the first reply on each channel. If no
-	 * replies are received, next channel will be scanned after this. If
-	 * replies are received, total time waited on the channel is defined by
-	 * max_channel_time.
-	 */
-	__u32		min_channel_time; /* in TU */
-	__u32		max_channel_time; /* in TU */
-
-	struct iw_freq	channel_list[IW_MAX_FREQUENCIES];
-};
-
-/* ------------------------- WPA SUPPORT ------------------------- */
-
-/*
- *	Extended data structure for get/set encoding (this is used with
- *	SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
- *	flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
- *	only the data contents changes (key data -> this structure, including
- *	key data).
- *
- *	If the new key is the first group key, it will be set as the default
- *	TX key. Otherwise, default TX key index is only changed if
- *	IW_ENCODE_EXT_SET_TX_KEY flag is set.
- *
- *	Key will be changed with SIOCSIWENCODEEXT in all cases except for
- *	special "change TX key index" operation which is indicated by setting
- *	key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
- *
- *	tx_seq/rx_seq are only used when respective
- *	IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
- *	TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
- *	TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
- *	used only by an Authenticator (AP or an IBSS station) to get the
- *	current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
- *	RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
- *	debugging/testing.
- */
-struct	iw_encode_ext
-{
-	__u32		ext_flags; /* IW_ENCODE_EXT_* */
-	__u8		tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-	__u8		rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-	struct sockaddr	addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
-			       * (group) keys or unicast address for
-			       * individual keys */
-	__u16		alg; /* IW_ENCODE_ALG_* */
-	__u16		key_len;
-	__u8		key[0];
-};
-
-/* SIOCSIWMLME data */
-struct	iw_mlme
-{
-	__u16		cmd; /* IW_MLME_* */
-	__u16		reason_code;
-	struct sockaddr	addr;
-};
-
-/* SIOCSIWPMKSA data */
-#define IW_PMKSA_ADD		1
-#define IW_PMKSA_REMOVE		2
-#define IW_PMKSA_FLUSH		3
-
-#define IW_PMKID_LEN	16
-
-struct	iw_pmksa
-{
-	__u32		cmd; /* IW_PMKSA_* */
-	struct sockaddr	bssid;
-	__u8		pmkid[IW_PMKID_LEN];
-};
-
-/* IWEVMICHAELMICFAILURE data */
-struct	iw_michaelmicfailure
-{
-	__u32		flags;
-	struct sockaddr	src_addr;
-	__u8		tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
-};
-
-/* IWEVPMKIDCAND data */
-#define IW_PMKID_CAND_PREAUTH	0x00000001 /* RNS pre-authentication enabled */
-struct	iw_pmkid_cand
-{
-	__u32		flags; /* IW_PMKID_CAND_* */
-	__u32		index; /* the smaller the index, the higher the
-				* priority */
-	struct sockaddr	bssid;
-};
-
-/* ------------------------ WIRELESS STATS ------------------------ */
-/*
- * Wireless statistics (used for /proc/net/wireless)
- */
-struct	iw_statistics
-{
-	__u16		status;		/* Status
-					 * - device dependent for now */
-
-	struct iw_quality	qual;		/* Quality of the link
-						 * (instant/mean/max) */
-	struct iw_discarded	discard;	/* Packet discarded counts */
-	struct iw_missed	miss;		/* Packet missed counts */
-};
-
-/* ------------------------ IOCTL REQUEST ------------------------ */
-/*
- * This structure defines the payload of an ioctl, and is used 
- * below.
- *
- * Note that this structure should fit on the memory footprint
- * of iwreq (which is the same as ifreq), which mean a max size of
- * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
- * You should check this when increasing the structures defined
- * above in this file...
- */
-union	iwreq_data
-{
-	/* Config - generic */
-	char		name[IFNAMSIZ];
-	/* Name : used to verify the presence of  wireless extensions.
-	 * Name of the protocol/provider... */
-
-	struct iw_point	essid;		/* Extended network name */
-	struct iw_param	nwid;		/* network id (or domain - the cell) */
-	struct iw_freq	freq;		/* frequency or channel :
-					 * 0-1000 = channel
-					 * > 1000 = frequency in Hz */
-
-	struct iw_param	sens;		/* signal level threshold */
-	struct iw_param	bitrate;	/* default bit rate */
-	struct iw_param	txpower;	/* default transmit power */
-	struct iw_param	rts;		/* RTS threshold threshold */
-	struct iw_param	frag;		/* Fragmentation threshold */
-	__u32		mode;		/* Operation mode */
-	struct iw_param	retry;		/* Retry limits & lifetime */
-
-	struct iw_point	encoding;	/* Encoding stuff : tokens */
-	struct iw_param	power;		/* PM duration/timeout */
-	struct iw_quality qual;		/* Quality part of statistics */
-
-	struct sockaddr	ap_addr;	/* Access point address */
-	struct sockaddr	addr;		/* Destination address (hw/mac) */
-
-	struct iw_param	param;		/* Other small parameters */
-	struct iw_point	data;		/* Other large parameters */
-};
-
-/*
- * The structure to exchange data for ioctl.
- * This structure is the same as 'struct ifreq', but (re)defined for
- * convenience...
- * Do I need to remind you about structure size (32 octets) ?
- */
-struct	iwreq 
-{
-	union
-	{
-		char	ifrn_name[IFNAMSIZ];	/* if name, e.g. "eth0" */
-	} ifr_ifrn;
-
-	/* Data part (defined just above) */
-	union	iwreq_data	u;
-};
-
-/* -------------------------- IOCTL DATA -------------------------- */
-/*
- *	For those ioctl which want to exchange mode data that what could
- *	fit in the above structure...
- */
-
-/*
- *	Range of parameters
- */
-
-struct	iw_range
-{
-	/* Informative stuff (to choose between different interface) */
-	__u32		throughput;	/* To give an idea... */
-	/* In theory this value should be the maximum benchmarked
-	 * TCP/IP throughput, because with most of these devices the
-	 * bit rate is meaningless (overhead an co) to estimate how
-	 * fast the connection will go and pick the fastest one.
-	 * I suggest people to play with Netperf or any benchmark...
-	 */
-
-	/* NWID (or domain id) */
-	__u32		min_nwid;	/* Minimal NWID we are able to set */
-	__u32		max_nwid;	/* Maximal NWID we are able to set */
-
-	/* Old Frequency (backward compat - moved lower ) */
-	__u16		old_num_channels;
-	__u8		old_num_frequency;
-
-	/* Scan capabilities */
-	__u8		scan_capa; 	/* IW_SCAN_CAPA_* bit field */
-
-	/* Wireless event capability bitmasks */
-	__u32		event_capa[6];
-
-	/* signal level threshold range */
-	__s32		sensitivity;
-
-	/* Quality of link & SNR stuff */
-	/* Quality range (link, level, noise)
-	 * If the quality is absolute, it will be in the range [0 ; max_qual],
-	 * if the quality is dBm, it will be in the range [max_qual ; 0].
-	 * Don't forget that we use 8 bit arithmetics... */
-	struct iw_quality	max_qual;	/* Quality of the link */
-	/* This should contain the average/typical values of the quality
-	 * indicator. This should be the threshold between a "good" and
-	 * a "bad" link (example : monitor going from green to orange).
-	 * Currently, user space apps like quality monitors don't have any
-	 * way to calibrate the measurement. With this, they can split
-	 * the range between 0 and max_qual in different quality level
-	 * (using a geometric subdivision centered on the average).
-	 * I expect that people doing the user space apps will feedback
-	 * us on which value we need to put in each driver... */
-	struct iw_quality	avg_qual;	/* Quality of the link */
-
-	/* Rates */
-	__u8		num_bitrates;	/* Number of entries in the list */
-	__s32		bitrate[IW_MAX_BITRATES];	/* list, in bps */
-
-	/* RTS threshold */
-	__s32		min_rts;	/* Minimal RTS threshold */
-	__s32		max_rts;	/* Maximal RTS threshold */
-
-	/* Frag threshold */
-	__s32		min_frag;	/* Minimal frag threshold */
-	__s32		max_frag;	/* Maximal frag threshold */
-
-	/* Power Management duration & timeout */
-	__s32		min_pmp;	/* Minimal PM period */
-	__s32		max_pmp;	/* Maximal PM period */
-	__s32		min_pmt;	/* Minimal PM timeout */
-	__s32		max_pmt;	/* Maximal PM timeout */
-	__u16		pmp_flags;	/* How to decode max/min PM period */
-	__u16		pmt_flags;	/* How to decode max/min PM timeout */
-	__u16		pm_capa;	/* What PM options are supported */
-
-	/* Encoder stuff */
-	__u16	encoding_size[IW_MAX_ENCODING_SIZES];	/* Different token sizes */
-	__u8	num_encoding_sizes;	/* Number of entry in the list */
-	__u8	max_encoding_tokens;	/* Max number of tokens */
-	/* For drivers that need a "login/passwd" form */
-	__u8	encoding_login_index;	/* token index for login token */
-
-	/* Transmit power */
-	__u16		txpower_capa;	/* What options are supported */
-	__u8		num_txpower;	/* Number of entries in the list */
-	__s32		txpower[IW_MAX_TXPOWER];	/* list, in bps */
-
-	/* Wireless Extension version info */
-	__u8		we_version_compiled;	/* Must be WIRELESS_EXT */
-	__u8		we_version_source;	/* Last update of source */
-
-	/* Retry limits and lifetime */
-	__u16		retry_capa;	/* What retry options are supported */
-	__u16		retry_flags;	/* How to decode max/min retry limit */
-	__u16		r_time_flags;	/* How to decode max/min retry life */
-	__s32		min_retry;	/* Minimal number of retries */
-	__s32		max_retry;	/* Maximal number of retries */
-	__s32		min_r_time;	/* Minimal retry lifetime */
-	__s32		max_r_time;	/* Maximal retry lifetime */
-
-	/* Frequency */
-	__u16		num_channels;	/* Number of channels [0; num - 1] */
-	__u8		num_frequency;	/* Number of entry in the list */
-	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
-	/* Note : this frequency list doesn't need to fit channel numbers,
-	 * because each entry contain its channel index */
-
-	__u32		enc_capa;	/* IW_ENC_CAPA_* bit field */
-};
-
-/*
- * Private ioctl interface information
- */
- 
-struct	iw_priv_args
-{
-	__u32		cmd;		/* Number of the ioctl to issue */
-	__u16		set_args;	/* Type and number of args */
-	__u16		get_args;	/* Type and number of args */
-	char		name[IFNAMSIZ];	/* Name of the extension */
-};
-
-/* ----------------------- WIRELESS EVENTS ----------------------- */
-/*
- * Wireless events are carried through the rtnetlink socket to user
- * space. They are encapsulated in the IFLA_WIRELESS field of
- * a RTM_NEWLINK message.
- */
-
-/*
- * A Wireless Event. Contains basically the same data as the ioctl...
- */
-struct iw_event
-{
-	__u16		len;			/* Real length of this stuff */
-	__u16		cmd;			/* Wireless IOCTL */
-	union iwreq_data	u;		/* IOCTL fixed payload */
-};
-
-/* Size of the Event prefix (including padding and alignement junk) */
-#define IW_EV_LCP_LEN	(sizeof(struct iw_event) - sizeof(union iwreq_data))
-/* Size of the various events */
-#define IW_EV_CHAR_LEN	(IW_EV_LCP_LEN + IFNAMSIZ)
-#define IW_EV_UINT_LEN	(IW_EV_LCP_LEN + sizeof(__u32))
-#define IW_EV_FREQ_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_freq))
-#define IW_EV_PARAM_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_param))
-#define IW_EV_ADDR_LEN	(IW_EV_LCP_LEN + sizeof(struct sockaddr))
-#define IW_EV_QUAL_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_quality))
-
-/* iw_point events are special. First, the payload (extra data) come at
- * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second,
- * we omit the pointer, so start at an offset. */
-#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
-			  (char *) NULL)
-#define IW_EV_POINT_LEN	(IW_EV_LCP_LEN + sizeof(struct iw_point) - \
-			 IW_EV_POINT_OFF)
-
-#ifdef __KERNEL__
-#ifdef CONFIG_COMPAT
-struct __compat_iw_event {
-	__u16		len;			/* Real length of this stuff */
-	__u16		cmd;			/* Wireless IOCTL */
-	compat_caddr_t	pointer;
-};
-#define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer)
-#define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length)
-
-/* Size of the various events for compat */
-#define IW_EV_COMPAT_CHAR_LEN	(IW_EV_COMPAT_LCP_LEN + IFNAMSIZ)
-#define IW_EV_COMPAT_UINT_LEN	(IW_EV_COMPAT_LCP_LEN + sizeof(__u32))
-#define IW_EV_COMPAT_FREQ_LEN	(IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_freq))
-#define IW_EV_COMPAT_PARAM_LEN	(IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_param))
-#define IW_EV_COMPAT_ADDR_LEN	(IW_EV_COMPAT_LCP_LEN + sizeof(struct sockaddr))
-#define IW_EV_COMPAT_QUAL_LEN	(IW_EV_COMPAT_LCP_LEN + sizeof(struct iw_quality))
-#define IW_EV_COMPAT_POINT_LEN	\
-	(IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \
-	 IW_EV_COMPAT_POINT_OFF)
-#endif
-#endif
-
-/* Size of the Event prefix when packed in stream */
-#define IW_EV_LCP_PK_LEN	(4)
-/* Size of the various events when packed in stream */
-#define IW_EV_CHAR_PK_LEN	(IW_EV_LCP_PK_LEN + IFNAMSIZ)
-#define IW_EV_UINT_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(__u32))
-#define IW_EV_FREQ_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
-#define IW_EV_PARAM_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
-#define IW_EV_ADDR_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
-#define IW_EV_QUAL_PK_LEN	(IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
-#define IW_EV_POINT_PK_LEN	(IW_EV_LCP_PK_LEN + 4)
-
-#endif	/* _LINUX_WIRELESS_H */