aboutsummaryrefslogtreecommitdiffstats
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Apple80211.h156
-rw-r--r--src/drivers/MobileApple80211.c189
-rw-r--r--src/drivers/MobileApple80211.h43
-rw-r--r--src/drivers/android_drv.h62
-rw-r--r--src/drivers/driver.h691
-rw-r--r--src/drivers/driver_atheros.c56
-rw-r--r--src/drivers/driver_broadcom.c599
-rw-r--r--src/drivers/driver_common.c90
-rw-r--r--src/drivers/driver_hostap.c545
-rw-r--r--src/drivers/driver_iphone.m466
-rw-r--r--src/drivers/driver_madwifi.c581
-rw-r--r--src/drivers/driver_ndis.c146
-rw-r--r--src/drivers/driver_nl80211.c3893
-rw-r--r--src/drivers/driver_osx.m459
-rw-r--r--src/drivers/driver_ralink.c1498
-rw-r--r--src/drivers/driver_ralink.h383
-rw-r--r--src/drivers/driver_roboswitch.c2
-rw-r--r--src/drivers/driver_test.c105
-rw-r--r--src/drivers/driver_wext.c181
-rw-r--r--src/drivers/driver_wext.h8
-rw-r--r--src/drivers/drivers.c24
-rw-r--r--src/drivers/drivers.mak83
-rw-r--r--src/drivers/drivers.mk83
-rw-r--r--src/drivers/linux_ioctl.c29
-rw-r--r--src/drivers/linux_ioctl.h1
-rw-r--r--src/drivers/linux_wext.h51
-rw-r--r--src/drivers/netlink.c2
-rw-r--r--src/drivers/nl80211_copy.h885
-rw-r--r--src/drivers/wireless_copy.h1185
29 files changed, 5047 insertions, 7449 deletions
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 @@ struct hostapd_channel_data {
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 @@ struct hostapd_hw_modes {
* a_mpdu_params - A-MPDU (IEEE 802.11n) parameters
*/
u8 a_mpdu_params;
+
+ unsigned int flags; /* HOSTAPD_MODE_FLAG_* */
};
@@ -203,7 +199,7 @@ struct wpa_interface_info {
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 @@ struct wpa_driver_scan_params {
* 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 @@ struct wpa_driver_auth_params {
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 @@ struct wpa_driver_associate_params {
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 @@ struct wpa_driver_associate_params {
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 @@ struct wpa_driver_capa {
#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 @@ struct wpa_driver_capa {
#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 @@ struct wpa_driver_capa {
* 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 @@ struct hostapd_sta_add_params {
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 @@ enum wpa_driver_if_type {
};
struct wpa_init_params {
+ void *global_priv;
const u8 *bssid;
const char *ifname;
const u8 *ssid;
@@ -693,6 +919,7 @@ struct wpa_bss_params {
#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 @@ struct wpa_driver_ops {
* 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_ops {
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 @@ struct wpa_driver_ops {
* 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 @@ struct wpa_driver_ops {
* 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 @@ struct wpa_driver_ops {
*
* 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 @@ struct wpa_driver_ops {
* 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 @@ struct wpa_driver_ops {
* 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 @@ struct wpa_driver_ops {
* @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 @@ struct wpa_driver_ops {
* 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 @@ struct wpa_driver_ops {
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 @@ struct wpa_driver_ops {
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 @@ struct wpa_driver_ops {
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 @@ struct wpa_driver_ops {
*
* 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 @@ struct wpa_driver_ops {
* 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 @@ struct wpa_driver_ops {
* @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 @@ struct wpa_driver_ops {
*/
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 @@ struct wpa_driver_ops {
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 @@ struct wpa_driver_ops {
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_ops {
* 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 @@ struct wpa_driver_ops {
* @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 @@ struct wpa_driver_ops {
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 @@ struct wpa_driver_ops {
* 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 @@ struct wpa_driver_ops {
* 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 @@ enum wpa_event_type {
/**
* 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 @@ union wpa_event_data {
*/
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 @@ union wpa_event_data {
* 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 @@ union wpa_event_data {
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 @@ union wpa_event_data {
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 @@ static inline void drv_event_eapol_rx(void *ctx, const u8 *src, const u8 *data,
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 @@ atheros_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
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 @@ atheros_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
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 @@ atheros_set_opt_ie(void *priv, const u8 *ie, size_t ie_len)
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 @@ static void atheros_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
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 @@ atheros_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
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 @@ atheros_set_wps_ie(void *priv, const u8 *ie, size_t len, u32 frametype)
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 @@ atheros_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
{
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 @@ atheros_get_ssid(void *priv, u8 *buf, int len)
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 @@ static int atheros_set_authmode(void *priv, int auth_algs)
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 @@ const struct wpa_driver_ops wpa_driver_atheros_ops = {
.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 @@ static void handle_data(struct hostap_driver_data *drv, u8 *buf, size_t len,
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 @@ static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len)
{
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 @@ static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len)
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_init_sockets(struct hostap_driver_data *drv, u8 *own_addr)
}
-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 @@ static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
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 @@ static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
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 @@ static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
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 @@ static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
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)
-{
- struct iwreq iwr;
-
- 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;
-
- if (ioctl(drv->sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
- int ret = errno;
- if (show_err)
- perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
- return ret;
- }
-
- return 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)
+static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr,
+ const u8 *addr, int qos)
{
- struct wpa_driver_hostap_data *drv = priv;
- int ret = 0;
- int allow_unencrypted_eapol;
-
- wpa_printf(MSG_DEBUG, "%s", __FUNCTION__);
+ struct ieee80211_hdr hdr;
- 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;
+ os_memset(&hdr, 0, sizeof(hdr));
- /* 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;
-}
+ /*
+ * 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);
+ 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);
-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);
+ hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0);
}
-#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 @@ const struct wpa_driver_ops wpa_driver_hostap_ops = {
.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 @@ static void madwifi_raw_receive(void *ctx, const u8 *src_addr, const u8 *buf,
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 @@ madwifi_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
#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 @@ madwifi_commit(void *priv)
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 @@ const struct wpa_driver_ops wpa_driver_madwifi_ops = {
.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 @@ wpa_driver_ndis_get_interfaces(void *global_priv)
}
-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 @@ static void nl80211_handle_destroy(struct nl_handle *handle)
#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 @@ static void nl80211_handle_destroy(struct nl_handle *handle)
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 @@ struct i802_bss {
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 @@ struct wpa_driver_nl80211_data {
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 @@ struct wpa_driver_nl80211_data {
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 @@ static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
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 @@ static int wpa_driver_nl80211_if_remove(void *priv,
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 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
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 no_seq_check(struct nl_msg *msg, void *arg)
}
-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 @@ static int send_and_recv(struct wpa_driver_nl80211_data *drv,
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(struct wpa_driver_nl80211_data *drv,
}
+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 family_handler(struct nl_msg *msg, void *arg)
}
-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 @@ static int nl_get_multicast_id(struct wpa_driver_nl80211_data *drv,
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 @@ nla_put_failure:
}
+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 int wpa_driver_nl80211_own_ifindex(struct wpa_driver_nl80211_data *drv,
}
+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 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
(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 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
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 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
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 @@ static void wpa_driver_nl80211_event_rtm_dellink(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;
+ 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 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
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 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
"%s", brid, namebuf);
del_ifidx(drv, brid);
}
-#endif /* HOSTAPD */
}
@@ -629,8 +1050,7 @@ static unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv)
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 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
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 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
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 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
}
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_connect(struct wpa_driver_nl80211_data *drv,
}
+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 @@ static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
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_mgmt(struct wpa_driver_nl80211_data *drv,
}
-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 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
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 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
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 @@ static void mlme_event(struct wpa_driver_nl80211_data *drv,
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 @@ static void mlme_event_remain_on_channel(struct wpa_driver_nl80211_data *drv,
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 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
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 @@ static int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
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 @@ static int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
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 @@ static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
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 @@ static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
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 void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
}
-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;
+
+ 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);
+}
+
+
+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);
+}
- 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;
- }
- }
- if (drv->ap_scan_as_station &&
- (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
- gnlh->cmd == NL80211_CMD_SCAN_ABORTED)) {
+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 @@ static int process_event(struct nl_msg *msg, void *arg)
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 @@ static int process_event(struct nl_msg *msg, void *arg)
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 @@ static int process_event(struct nl_msg *msg, void *arg)
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 int process_event(struct nl_msg *msg, void *arg)
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 @@ static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg)
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 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
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 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
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 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
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 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv,
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 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
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 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
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;
+ drv->capa.flags |= WPA_DRIVER_FLAGS_SANE_ERROR_CODES;
+ drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
+ drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
+ drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
- 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;
- }
+ 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 (info.offchan_tx_supported) {
- wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
- "off-channel TX");
- drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
+ /*
+ * 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;
+ }
}
- 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;
+ /*
+ * 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)
{
- int ret;
-
- /* Initialize generic netlink and nl80211 */
+ /*
+ * 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;
- drv->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (drv->nl_cb == NULL) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
- "callbacks");
- goto err1;
+ if (genl_ctrl_alloc_cache(handle, &cache) < 0) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
+ "netlink cache");
+ goto fail;
}
- 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;
- }
+ nl80211 = genl_ctrl_search_by_name(cache, name);
+ if (nl80211 == NULL)
+ goto fail;
- 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;
- }
+ id = genl_family_get_id(nl80211);
- if (genl_connect(drv->nl_handle)) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
- "netlink");
- goto err3;
- }
+fail:
+ if (nl80211)
+ genl_family_put(nl80211);
+ if (cache)
+ nl_cache_free(cache);
- if (genl_connect(drv->nl_handle_event)) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to connect to generic "
- "netlink (event)");
- goto err3;
- }
+ return id;
+}
+#define genl_ctrl_resolve android_genl_ctrl_resolve
+#endif /* ANDROID */
-#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;
+
+static int wpa_driver_nl80211_init_nl_global(struct nl80211_global *global)
+{
+ int ret;
+
+ global->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (global->nl_cb == NULL) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to allocate netlink "
+ "callbacks");
+ return -1;
}
-#endif /* CONFIG_LIBNL20 */
- drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211");
- if (drv->nl80211 == NULL) {
+ global->nl = nl_create_handle(global->nl_cb, "nl");
+ if (global->nl == NULL)
+ goto err;
+
+ 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 @@ static int wpa_driver_nl80211_init_nl(struct wpa_driver_nl80211_data *drv)
/* 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 @@ static void wpa_driver_nl80211_rfkill_unblocked(void *ctx)
{
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 nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv)
}
+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 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
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,32 +2942,18 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
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;
}
- 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)");
+ if (nl80211_init_bss(bss))
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;
- }
+ nl80211_get_phy_name(drv);
rcfg = os_zalloc(sizeof(*rcfg));
if (rcfg == NULL)
@@ -2012,32 +2971,46 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
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 @@ static int nl80211_register_frame(struct wpa_driver_nl80211_data *drv,
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 @@ nla_put_failure:
}
-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 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
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 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv)
}
}
- 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 @@ static int wpa_driver_nl80211_del_beacon(struct wpa_driver_nl80211_data *drv)
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 @@ static void wpa_driver_nl80211_deinit(void *priv)
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 @@ static void wpa_driver_nl80211_deinit(void *priv)
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 @@ static void wpa_driver_nl80211_deinit(void *priv)
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);
-
- if (drv->ioctl_sock >= 0)
- close(drv->ioctl_sock);
+ (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");
- 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_deinit(void *priv)
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 @@ static int wpa_driver_nl80211_scan(void *priv,
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 @@ static int wpa_driver_nl80211_scan(void *priv,
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 @@ static int wpa_driver_nl80211_scan(void *priv,
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 @@ static int wpa_driver_nl80211_scan(void *priv,
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 @@ nla_put_failure:
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 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
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 @@ static int bss_info_handler(struct nl_msg *msg, void *arg)
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 @@ static void wpa_driver_nl80211_check_bss_status(
"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 @@ static void wpa_driver_nl80211_check_bss_status(
"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_driver_nl80211_check_bss_status(
}
-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 @@ nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
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 @@ nl80211_get_scan_results(struct wpa_driver_nl80211_data *drv)
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 @@ static int wpa_driver_nl80211_set_key(const char *ifname, void *priv,
"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 @@ static int wpa_driver_nl80211_set_key(const char *ifname, void *priv,
*/
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 @@ static int wpa_driver_nl80211_set_key(const char *ifname, void *priv,
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 @@ static int wpa_driver_nl80211_set_key(const char *ifname, void *priv,
return ret;
nla_put_failure:
+ nlmsg_free(msg);
return -ENOBUFS;
}
@@ -3069,7 +4370,7 @@ static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
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 @@ static int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
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 int wpa_driver_nl80211_disassociate(void *priv, const u8 *addr,
}
+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 @@ static int wpa_driver_nl80211_authenticate(
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 @@ retry:
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 @@ retry:
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 @@ retry:
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 @@ nla_put_failure:
}
+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 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
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 @@ static int nl80211_set_ht40_flags(struct wpa_driver_nl80211_data *drv,
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 @@ wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
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 @@ wpa_driver_nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
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 @@ static int wpa_driver_nl80211_send_frame(struct wpa_driver_nl80211_data *drv,
.msg_flags = 0,
};
int res;
+ u16 txflags = 0;
if (encrypt)
rtap_hdr[8] |= IEEE80211_RADIOTAP_F_WEP;
@@ -3721,6 +5160,10 @@ static int wpa_driver_nl80211_send_frame(struct wpa_driver_nl80211_data *drv,
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 wpa_driver_nl80211_data *drv,
}
+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 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data,
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 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data,
* 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 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data,
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 @@ static int wpa_driver_nl80211_set_beacon(void *priv,
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 @@ static int wpa_driver_nl80211_set_beacon(void *priv,
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 @@ static int wpa_driver_nl80211_set_beacon(void *priv,
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 @@ static int wpa_driver_nl80211_set_freq(struct wpa_driver_nl80211_data *drv,
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 @@ static int wpa_driver_nl80211_set_freq(struct wpa_driver_nl80211_data *drv,
}
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 @@ static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr)
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 @@ static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr)
return 0;
return ret;
nla_put_failure:
+ nlmsg_free(msg);
return -ENOBUFS;
}
@@ -3951,26 +5619,46 @@ static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
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 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
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 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
}
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 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
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 @@ static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
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 @@ static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
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 handle_tx_callback(void *ctx, u8 *buf, size_t len, int ok)
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 int add_monitor_filter(int s)
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 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
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 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
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 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
}
+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 @@ static int wpa_driver_nl80211_hapd_send_eapol(
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 @@ static int wpa_driver_nl80211_hapd_send_eapol(
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 int wpa_driver_nl80211_hapd_send_eapol(
}
-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 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
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 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
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 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
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_sta_set_flags(void *priv, const u8 *addr,
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 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv)
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 @@ static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
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 @@ retry:
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 @@ nla_put_failure:
}
+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 @@ static int wpa_driver_nl80211_connect(
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 @@ static int wpa_driver_nl80211_connect(
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 @@ skip_auth_type:
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 @@ static int wpa_driver_nl80211_associate(
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 @@ static int wpa_driver_nl80211_associate(
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 @@ static int wpa_driver_nl80211_associate(
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 @@ nla_put_failure:
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 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode)
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 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode)
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) {
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
+ "from %d failed", nlmode, drv->nlmode);
+ return ret;
+ }
+
+ if (is_ap_interface(nlmode)) {
+ nl80211_mgmt_unsubscribe(bss, "start 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)
+ if (nl80211_setup_ap(bss))
return -1;
- } else if (!ret && nlmode != NL80211_IFTYPE_AP) {
+ } else if (was_ap) {
/* Remove additional AP mode functionality */
- nl80211_remove_monitor_interface(drv);
- bss->beacon_set = 0;
+ nl80211_teardown_ap(bss);
+ } else {
+ nl80211_mgmt_unsubscribe(bss, "mode change");
}
- if (ret)
- wpa_printf(MSG_DEBUG, "nl80211: Interface mode change to %d "
- "from %d failed", nlmode, drv->nlmode);
+ 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 ret;
+ return 0;
}
@@ -5124,7 +6997,7 @@ static int wpa_driver_nl80211_set_operstate(void *priv, int state)
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 @@ static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
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 @@ static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
return send_and_recv_msgs(drv, msg, NULL, NULL);
nla_put_failure:
+ nlmsg_free(msg);
return -ENOBUFS;
}
@@ -5163,8 +7036,7 @@ static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
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 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
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 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
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 @@ static int i802_set_rts(void *priv, int rts)
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 @@ static int i802_set_frag(void *priv, int frag)
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 @@ static int i802_flush(void *priv)
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 @@ static int i802_flush(void *priv)
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 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
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 @@ static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
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 @@ static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
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 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
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 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
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 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
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 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
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 @@ static int i802_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
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 @@ static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
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 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
* 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 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
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 @@ static int i802_check_bridge(struct wpa_driver_nl80211_data *drv,
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 @@ static void *i802_init(struct hostapd_data *hapd,
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 @@ static void *i802_init(struct hostapd_data *hapd,
/* 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 @@ static void *i802_init(struct hostapd_data *hapd,
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 @@ static void *i802_init(struct hostapd_data *hapd,
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 @@ static int nl80211_addr_in_use(struct nl80211_global *global, const u8 *addr)
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 @@ static int nl80211_p2p_interface_addr(struct wpa_driver_nl80211_data *drv,
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 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
}
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 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
/* 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 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
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 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
}
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 @@ static int wpa_driver_nl80211_if_remove(void *priv,
#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 @@ static int wpa_driver_nl80211_if_remove(void *priv,
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 cookie_handler(struct nl_msg *msg, void *arg)
}
-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 @@ static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv,
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 @@ static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv,
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 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq,
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 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq,
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 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq,
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 @@ static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
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 @@ static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
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 @@ static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
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 @@ static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv)
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 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
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 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
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 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
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 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
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 @@ nla_put_failure:
}
-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 @@ static void wpa_driver_nl80211_resume(void *priv)
{
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 @@ static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
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 @@ static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
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 @@ static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
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 @@ static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis)
msg = NULL;
nla_put_failure:
- if (cqm)
- nlmsg_free(cqm);
+ nlmsg_free(cqm);
nlmsg_free(msg);
return -1;
}
@@ -6621,34 +8400,58 @@ static int nl80211_signal_poll(void *priv, struct wpa_signal_info *si)
}
-static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
- int encrypt)
+static int wpa_driver_nl80211_shared_freq(void *priv)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
- return wpa_driver_nl80211_send_frame(drv, data, data_len, encrypt);
-}
+ 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);
-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;
+ 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;
- msg = nlmsg_alloc();
- if (!msg)
- return -ENOMEM;
+ 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);
+ }
- genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
- NL80211_CMD_SET_BSS, 0);
+ if (!freq)
+ wpa_printf(MSG_DEBUG, "nl80211: No shared interface for "
+ "PHY (%s) in associated state", drv->phyname);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
- NLA_PUT_U8(msg, NL80211_ATTR_AP_ISOLATE, !enabled);
+ return freq;
+}
- return send_and_recv_msgs(drv, msg, NULL, NULL);
- nla_put_failure:
- return -ENOBUFS;
+
+static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
+ int encrypt)
+{
+ struct i802_bss *bss = priv;
+ return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0);
}
@@ -6668,6 +8471,15 @@ static int nl80211_set_param(void *priv, const char *param)
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 int nl80211_set_param(void *priv, const char *param)
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 @@ static void nl80211_global_deinit(void *priv)
"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 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,
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 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid,
return send_and_recv_msgs(bss->drv, msg, NULL, NULL);
nla_put_failure:
+ nlmsg_free(msg);
return -ENOBUFS;
}
@@ -6756,6 +8616,366 @@ static int nl80211_flush_pmkid(void *priv)
}
+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 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.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 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.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 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.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 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.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 @@ static void * wpa_driver_roboswitch_init(void *ctx, const char *ifname)
/* 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 @@ struct wpa_driver_test_data {
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 @@ struct wpa_driver_test_data {
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 test_driver_send_ether(void *priv, const u8 *dst, const u8 *src,
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 @@ static void test_driver_scan(struct wpa_driver_test_data *drv,
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_if_remove(void *priv, enum wpa_driver_if_type type,
}
-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 @@ static void * test_driver_init(struct hostapd_data *hapd,
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 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
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 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv,
#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 @@ static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv,
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 @@ static int wpa_driver_test_set_param(void *priv, const char *param)
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 @@ static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
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_mlme_setprotection(void *priv, const u8 *addr,
}
-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 @@ static int wpa_driver_test_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)
{
struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv;
@@ -2760,7 +2705,7 @@ static int wpa_driver_test_send_action(void *priv, unsigned int freq,
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 int wpa_driver_test_send_action(void *priv, unsigned int freq,
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 @@ static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx)
}
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 @@ static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
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 @@ static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
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 @@ static int test_send_action(void *ctx, unsigned int freq, const u8 *dst,
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_sd_response(void *ctx, const u8 *sa, u16 update_indic,
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 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
.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 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
.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 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
}
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 @@ static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
tmp[res->num++] = r;
res->res = tmp;
}
-
+
/**
* wpa_driver_wext_get_scan_results - Fetch the latest scan results
@@ -1426,7 +1430,7 @@ static void wpa_driver_wext_add_scan_entry(struct wpa_scan_results *res,
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 @@ struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv)
if (res_buf == NULL)
return NULL;
- ap_num = 0;
first = 1;
res = os_zalloc(sizeof(*res));
@@ -1868,8 +1871,10 @@ static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
{
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 @@ static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv)
}
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 @@ static const char * wext_get_radio_name(void *priv)
}
+#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 @@ const struct wpa_driver_ops wpa_driver_wext_ops = {
.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 @@ struct wpa_driver_wext_data {
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_set_auth_param(struct wpa_driver_wext_data *drv,
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 @@ extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
#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 @@ extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */
#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 @@ struct wpa_driver_ops *wpa_drivers[] =
#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 @@ struct wpa_driver_ops *wpa_drivers[] =
#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 @@ DRV_AP_LIBS =
##### 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_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
NEED_RFKILL=y
-ifdef CONFIG_LIBNL_TINY
-DRV_LIBS += -lnl-tiny
+
+ifdef CONFIG_LIBNL32
+ DRV_LIBS += -lnl-3
+ DRV_LIBS += -lnl-genl-3
+ DRV_CFLAGS += -DCONFIG_LIBNL20
else
-DRV_LIBS += -lnl
-endif
+ 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_LIBNL20
+ DRV_LIBS += -lnl-genl
+ DRV_CFLAGS += -DCONFIG_LIBNL20
+ endif
endif
endif
@@ -79,6 +68,24 @@ endif
##### 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_LINUX_IOCTL=y
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 @@ DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO
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 @@ DRV_AP_LIBS =
##### 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_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
NEED_RFKILL=y
-ifdef CONFIG_LIBNL_TINY
-DRV_LIBS += -lnl-tiny
+
+ifdef CONFIG_LIBNL32
+ DRV_LIBS += -lnl-3
+ DRV_LIBS += -lnl-genl-3
+ DRV_CFLAGS += -DCONFIG_LIBNL20
else
-DRV_LIBS += -lnl
-endif
+ 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_LIBNL20
+ DRV_LIBS += -lnl-genl
+ DRV_CFLAGS += -DCONFIG_LIBNL20
+ endif
endif
endif
@@ -79,6 +68,24 @@ endif
##### 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_LINUX_IOCTL=y
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 @@ DRV_WPA_CFLAGS += -DCONFIG_USE_NDISUIO
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 @@ int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
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 @@ int linux_set_iface_flags(int sock, const char *ifname, int dev_up)
}
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 @@ static void netlink_receive_link(struct netlink_data *netlink,
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 @@ enum nl80211_commands {
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 @@ enum nl80211_commands {
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 @@ enum nl80211_commands {
#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 @@ enum nl80211_commands {
* 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 @@ enum nl80211_commands {
*
* @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 @@ enum nl80211_commands {
* @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 @@ enum nl80211_commands {
* 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 @@ enum nl80211_commands {
* 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 @@ enum nl80211_attrs {
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 @@ enum nl80211_attrs {
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 @@ enum nl80211_attrs {
/* 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 @@ enum nl80211_attrs {
#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 @@ enum nl80211_attrs {
* @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 @@ enum nl80211_iftype {
* 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 @@ enum nl80211_sta_flags {
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_rate_info {
};
/**
+ * 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 @@ enum nl80211_rate_info {
* @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 @@ enum nl80211_sta_info {
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 @@ enum nl80211_bitrate_attr {
* 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_reg_rule_attr {
};
/**
+ * 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_mntr_flags {
/**
* 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 @@ enum nl80211_mntr_flags {
* @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 @@ enum nl80211_mntr_flags {
* @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 @@ enum nl80211_meshconf_params {
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_meshconf_params {
};
/**
+ * 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 @@ enum nl80211_tx_power_setting {
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 */