Cumulative patch from commit 95fb2db2420d8fa291fd6423cc6dbcd042f4eb46
95fb2db P2P: Reject group formation on WPS provisioning failure
6fc61e1 Fix TX status processing during AP mode shutdown in wpa_supplicant
90a545c nl80211: Clean up netlink parsing and debug prints
b6a9590 Interworking: Keep up to two pending GAS_REQUEST responses
090b8e3 Update copyright notices for the new year 2014
991aa9c nl80211: Move CS supported flag to wpa_driver_capa
f0cbb98 Add DRIVER-STATUS command for hostapd
188ebcd EAP-IKEv2 peer: Fix a memory leak in notify round
a190189 Remove PEAPv2 support
16a19dd EAP-pwd peer: Allow fragmentation limit to be configured
60bf585 EAP-IKEv2 peer: Allow fragmentation limit to be configured
ea6fc58 WPS: Convert printf() debug print to use wpa_printf()
c4b8c71 EAP-GPSK: Report CSuite negotiation failure properly
5a0f596 EAP-GPSK: Allow forced algorithm selection to be configured
5f01c3c EAP peer: Improve failure reporting from METHOD with no eapRespData
7271ee8 Fix EAP-GPSK server compilation for SHA256 cipher suite
356d148 Interworking: Add optional freq argument to INTERWORKING_SELECT
a09ffd5 Fix req_scan-deplete-timeout and update eloop API for this
083916c P2P: Clear p2p_disabled and p2p_per_sta_psk on FLUSH command
3f45fc4 P2P: Clear services on FLUSH command
1f965e6 Allow external programs to request wpa_radio work items
6428d0a Do not start wpa_radio work during externally triggered scan
6470f47 Remove unneeded scan delay on connection-in-progress
4bb2321 Remove unneeded GAS query delay on connection-in-progress
6ac4b15 Use wpa_radio work for connection
b9e6d70 Use radio work for GAS requests
e05e130 P2P: Use radio work to protect offchannel Action frame exchanges
e1d1c8e Use radio work for P2P Listen requests
1b5d471 Use radio work for P2P scan requests
d12a51b Use radio work for scan requests
b1ae396 Add framework for exclusive radio operations
dd43aaa Add helper functions for cloning and freeing scan parameters
06f9acc Ignore externally triggered scan results with scan_res_handler
c9b5559 Clean up ctrl_iface debug prints for monitor events
d31b5ac Use cleaner debug print for ctrl_iface commands with private info
9595151 Remove duplicated RX ctrl_iface hexdump
9b85079 Fix scan-cache-clearing operation to avoid unnecessary cases
2f30cac Avoid unnecessary key clearing operations
466bcf9 Remove some unnecessary EAPOL port (un)authorized callbacks
949938a Ask driver to report only new scan results if requested
a1a31b6 Remove hostapd dump_file functionality
ea23df6 Make EAPOL dump data available through ctrl_iface STA command
96ea74b Convert EAPOL authenticator dump into easier to parse format
ca3b71c Remove hostapd dump_file data that is available through ctrl_iface
4c03a2b Make RADIUS server MIB available through control interface
f538be3 Add more STA information into the ctrl_iface STA command
101bdc2 Remove forgotten notes about already removed driver wrappers
7006753 Update EAP-FAST note regarding OpenSSL support
17b79e6 nl80211: Initial support for vendor commands and events
5890fa8 WPS: Fix clear-from-timeout handling to avoid race condition
c64e3a0 P2P: Send received Presence Response information to ctrl_iface monitors
f7fb676 ACS: Mark acs_fail() static
3cf06c9 OpenSSL: Include sha1/sha256 header files to verify declarations
5ace51a WNM: Clean up le16 variable use to avoid sparse warnings
c583868 Mark wpas_wps_er_nfc_handover_sel() static
8cf1e68 Move declaration of hostapd_acs_completed() into correct header file
0187c41 Declare wpa_debug_* variables in src/utils/wpa_debug.h
fcc6123 Declare wpa_drivers in src/drivers/driver.h
0d79b50 Clear EAPOL Logoff state on FLUSH command
327b01d nl80211: Add driver param for forcing monitor and connect APIs
6f06766 nl80211: Fix nl_mgmt handling in partial error case
4ea6a47 nl80211: Prefer newer scan result over older during duplicate removal
2eef517 nl80211: Report set_supp_port failures in debug log
a0bdd19 nl80211: Share a helper function for connect and associate commands
e00d546 Remove unnecessary build #ifdef from definitions
4848a38 Get rid of duplicated cipher suite and AKM definitions
de4ed4a nl80211: Use helper functions for cipher suite mapping
a565084 nl80211: Set control port for NL80211_CMD_COMMAND
ef93abd WPS: Clean up UUID debug print
35f3d3e nl80211: Clean up regulatory rule debug prints
880de88 nl80211: Print frame registration match on same debug line
03ed332 Interworking: Allow cred blocks not to be saved to a file
04f7ecc Reset WPA parameters to default values on FLUSH command
152cff6 P2P: Remove WPA_DRIVER_FLAGS_P2P_MGMT option
538d6f4 WPS: Use shorter scan interval during pre-provisioning search
3187fd9 WPS: Replace wpas_wps_in_progress with identical wpas_wps_searching
4414d9e SAE: Fix ECC element y coordinate validation step
069fb47 EAP-EKE: Allow forced algorithm selection to be configured
3a88914 Remove unused information element parsing data
dbfb8e8 Remove unnecessary EVENT_RX_ACTION
1450e1e Define __maybe_unused
912b34f Do not process Action frames twice in hostapd SME/MLME
006309b Fix whitespace style
6780713 WPS: Remove unused send_wpabuf()
e912986 tests: Verify concurrent WPS protocol run with assigned PIN
8aaafce Make local UUID available through ctrl_iface STATUS command
0e22b8d WPS: Make sure reconfiguration timeout is not left behind on deinit
75d1d0f WPS: Allow testing mode to disable 2.0 functionality
f7e2542 Remove unused wps_device_data_dup()
c89d9db Remove unnecessary extra tracking of eloop registration
c86bf16 Replace unnecessary hex_value() with hex2byte()
7b02375 Clear wps_fragment_size on FLUSH command
aa189ac Enable FT with SAE
2d2ecf5 nl80211: Fix protected Action frame reporting for AP mode
db76aa6 Fix PeerKey 4-way handshake
7732729 Fix PeerKey deinit behavior
8d321a7 WNM: Move disassociation imminent sending to wnm_ap.c
b76f4c2 hostapd: Make STA flags available through ctrl_iface STA command
aa03dbd Remove IEEE80211_REQUIRE_AUTH_ACK
121f2ab Remove unused STA flags
3578e66 WNM: Add STA flag to indicate the current WNM-Sleep-Mode state
4776897 WNM: Fix AP processing without wnm_oper driver callback
2025cad WNM: Move ESS Disassoc Imminent sending to a helper function
28ab64a WNM: Minimal processing of BSS Transition Management Query/Response
2cd0f6a WNM: Add Target BSSID into BSS Transition Management Response
a8a6a35 WNM: Use nonzero dialog token in BSS Transition Management Query
629edfe WNM: Fix Sleep Mode AP processing in open network
3c1060f WNM: Add debug logs to get the RSSI from the scan results
dff1e28 Initial handling of GTK-not-used cipher suite
51e3eaf OpenSSL: Do not accept SSL Client certificate for server
6bf61fb OpenSSL: Use certificates from TLS authentication in OCSP stapling
c962947 WPS ER: Fix deinit timeout handling with delayed/failing unsubscribe
7b75c30 WPS: Reschedule AP configuration reload on EAP completion
c511b32 WPS: Remove old duplicate network even if key is different
9d2cb3e Make CONFIG_TESTING_OPTIONS=y enable all testing options
662b40b WPS: Reduce scan wait time during WPS processing
015af91 Do not use results from externally requested scan for network selection
1cd93ff Reschedule own scan request if an externally started one is in progress
dc3906c Show timing information about scan requests in debug log
d81c73b Optional scan id for ctrl_iface SCAN requests
a5f40ef Track whether scan was started by us or an external program
18ae237 Fix comment format
88c2d48 Allow passive scan to be requested with SCAN passive=1
3ae3ec2 nl80211: Add scanned frequencies/SSIDs into debug log
69278f7 Remove unused last_scan_full
1f5d2dd Interworking: Allow EAP-FAST to be used
6ffa168 Add GAS-QUERY-START and GAS-QUERY-DONE event messages
93827f4 hostapd: Allow external management frame processing or testing
fee5234 Allow channel list to be specified for SCAN command
98eda9c Move int_array helpfer functions to utils/common.c
a4cfb48 Add make lcov-html to generate code coverage report
bee25cc nl80211: Fetch cipher capabilities from the driver
4daa011 Clean up cipher capability prints
35c2006 Convert wpa_hexdump functions to use void pointer instead of u8 *
5f9c134 Remove obsolete license notifications
bd1e328 Android: Remove old WEXT extensions
bad5cdf Verify that beacon setup succeeds before proceeding
7d7f7be Verify group key configuration for WPA group
30675c3 Add definitions for new cipher suites from IEEE Std 802.11ac-2013
13b24a7 VHT: Use status code 104 to indicate VHT required
ab41595 wpa_supplicant: Fix crash when terminating all interfaces
76aab03 Add secondary channel IE for CSA
8f4713c Store entire CS freq_params and not only freq
13daed5 Include driver.h in hostapd.h
a12d345 wpa_supplicant: Use monotonic time for last_scan check
51bffab WPS: Use monotonic time for AP connection attempt
6473e5c wpa_supplicant: Use relative time for TKIP Michael MIC failures
4e1eae1 wpa_supplicant: Use monotonic time for temp-disabled networks
151ab80 P2P: Use monotonic time for GO client waiting
3326f19 IBSS RSN: Use monotonic time for reinit detection
196a217 WPS_UPNP: Use monotonic time for event debouncing
864c9af wps_registrar: Use monotonic time for PBC workaround
61e98e9 wps_registrar: Use monotonic time for PBC session timeout
3647e5a wps_registrar: Use monotonic time for PIN timeout
3618618 rsn_supp: Use monotonic time for PMKSA cache expiry
c2be937 wpa_supplicant: Use monotonic time for EAPOL RX workaround
e72a001 bgscan: Use monotonic time
e05f060 rsn_supp: Do not track expiration time
5870717 RADIUS server: Use monotonic time
4012804 RADIUS client: Use monotonic time
acb69ce wpa_supplicant: Use monotonic time for RX/BSS times
46b8d4c wpa_supplicant: Use monotonic time for SA query timeout
f073fde EAP server: Remove SIM-DB pending timestamp
636e19a wpa_ctrl: Use monotonic time for request retry loop
7ffe7d2 AP: Use monotonic time for MMIC failure/TKIP countermeasures
dd4e32b AP: Use monotonic time for PMKSA cache
0fc545a AP: Use monotonic time for STA accounting
3e06180 bgscan_learn: Start scanning from the first freq
f4c73ae bgscan_learn: Fix initial interval
7dab119 bgscan_learn: Avoid redundant frequencies
3727123 bgscan: Stop bgscan only on disassociation
b2838ba Update IBSS documentation to include RSN option
429dd9a Advertise QoS Map support based on driver capability
049105b nl80211: Add support for QoS Map configuration
74ddd64 nl80211: Sync with mac80211-next.git
9fcd300 nl80211: Sync with wireless-testing.git
Change-Id: Iabdd88d9cabd478a41c3cb0a8d061b425cc1beca
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/README b/README
index bf0bd83..f531698 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
wpa_supplicant and hostapd
--------------------------
-Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
These programs are licensed under the BSD license (the one with
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index bc0273e..6e37beb 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -137,10 +137,10 @@
ifndef CONFIG_NO_DUMP_STATE
-# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
-# a file (undefine it, if you want to save in binary size)
+# define HOSTAPD_DUMP_STATE to include support for dumping internal state
+# through control interface commands (undefine it, if you want to save in
+# binary size)
L_CFLAGS += -DHOSTAPD_DUMP_STATE
-OBJS += dump_state.c
OBJS += src/eapol_auth/eapol_auth_dump.c
endif
@@ -351,7 +351,7 @@
L_CFLAGS += -DEAP_SERVER_GPSK
OBJS += src/eap_server/eap_server_gpsk.c src/eap_common/eap_gpsk_common.c
ifdef CONFIG_EAP_GPSK_SHA256
-L_CFLAGS += -DEAP_SERVER_GPSK_SHA256
+L_CFLAGS += -DEAP_GPSK_SHA256
endif
NEED_SHA256=y
NEED_AES_OMAC1=y
diff --git a/hostapd/Makefile b/hostapd/Makefile
index ae96d35..5fd6481 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -6,8 +6,8 @@
CFLAGS = -MMD -O2 -Wall -g
endif
-CFLAGS += -I../src
-CFLAGS += -I../src/utils
+CFLAGS += -I$(abspath ../src)
+CFLAGS += -I$(abspath ../src/utils)
# Uncomment following line and set the path to your kernel tree include
# directory if your C library does not include all header files.
@@ -15,6 +15,11 @@
-include .config
+ifdef CONFIG_TESTING_OPTIONS
+CFLAGS += -DCONFIG_TESTING_OPTIONS
+CONFIG_WPS_TESTING=y
+endif
+
ifndef CONFIG_OS
ifdef CONFIG_NATIVE_WINDOWS
CONFIG_OS=win32
@@ -114,10 +119,10 @@
endif
ifndef CONFIG_NO_DUMP_STATE
-# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
-# a file (undefine it, if you want to save in binary size)
+# define HOSTAPD_DUMP_STATE to include support for dumping internal state
+# through control interface commands (undefine it, if you want to save in
+# binary size)
CFLAGS += -DHOSTAPD_DUMP_STATE
-OBJS += dump_state.o
OBJS += ../src/eapol_auth/eapol_auth_dump.o
endif
@@ -327,7 +332,7 @@
CFLAGS += -DEAP_SERVER_GPSK
OBJS += ../src/eap_server/eap_server_gpsk.o ../src/eap_common/eap_gpsk_common.o
ifdef CONFIG_EAP_GPSK_SHA256
-CFLAGS += -DEAP_SERVER_GPSK_SHA256
+CFLAGS += -DEAP_GPSK_SHA256
endif
NEED_SHA256=y
NEED_AES_OMAC1=y
@@ -858,10 +863,6 @@
LIBS_h += -lsqlite3
endif
-ifdef CONFIG_TESTING_OPTIONS
-CFLAGS += -DCONFIG_TESTING_OPTIONS
-endif
-
ALL=hostapd hostapd_cli
all: verify_config $(ALL)
@@ -873,9 +874,15 @@
E=true
endif
+ifdef CONFIG_CODE_COVERAGE
+%.o: %.c
+ @$(E) " CC " $<
+ $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
+else
%.o: %.c
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
+endif
verify_config:
@if [ ! -r .config ]; then \
@@ -944,9 +951,15 @@
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
@$(E) " LD " $@
+lcov-html:
+ lcov -c -d .. > lcov.info
+ genhtml lcov.info --output-directory lcov-html
+
clean:
$(MAKE) -C ../src clean
rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
rm -f *.d *.gcno *.gcda *.gcov
+ rm -f lcov.info
+ rm -rf lcov-html
-include $(OBJS:%.o=%.d)
diff --git a/hostapd/README b/hostapd/README
index 39b70ca..50868ee 100644
--- a/hostapd/README
+++ b/hostapd/README
@@ -2,7 +2,7 @@
Authenticator and RADIUS authentication server
================================================================
-Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
diff --git a/hostapd/android.config b/hostapd/android.config
index f51a5bf..33e96c4 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -157,7 +157,7 @@
# Remove support for VLANs
#CONFIG_NO_VLAN=y
-# Remove support for dumping state into a file on SIGUSR1 signal
+# Remove support for dumping internal state through control interface commands
# This can be used to reduce binary size at the cost of disabling a debugging
# option.
#CONFIG_NO_DUMP_STATE=y
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index ae05917..4198834 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -22,9 +22,6 @@
#include "config_file.h"
-extern struct wpa_driver_ops *wpa_drivers[];
-
-
#ifndef CONFIG_NO_VLAN
static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
const char *fname)
@@ -1634,7 +1631,8 @@
} else if (os_strcmp(buf, "logger_stdout") == 0) {
bss->logger_stdout = atoi(pos);
} else if (os_strcmp(buf, "dump_file") == 0) {
- bss->dump_log_name = os_strdup(pos);
+ wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
+ line);
} else if (os_strcmp(buf, "ssid") == 0) {
bss->ssid.ssid_len = os_strlen(pos);
if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 2d0379f..72faeae 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1,6 +1,6 @@
/*
* hostapd / UNIX domain socket -based control interface
- * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -20,6 +20,7 @@
#include "common/ieee802_11_defs.h"
#include "drivers/driver.h"
#include "radius/radius_client.h"
+#include "radius/radius_server.h"
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/ieee802_1x.h"
@@ -29,6 +30,7 @@
#include "ap/wps_hostapd.h"
#include "ap/ctrl_iface_ap.h"
#include "ap/ap_drv_ops.h"
+#include "ap/wnm_ap.h"
#include "ap/wpa_auth.h"
#include "wps/wps_defs.h"
#include "wps/wps.h"
@@ -665,9 +667,8 @@
const char *cmd)
{
u8 addr[ETH_ALEN];
- u8 buf[1000], *pos;
- struct ieee80211_mgmt *mgmt;
int disassoc_timer;
+ struct sta_info *sta;
if (hwaddr_aton(cmd, addr))
return -1;
@@ -675,31 +676,15 @@
return -1;
disassoc_timer = atoi(cmd + 17);
- os_memset(buf, 0, sizeof(buf));
- mgmt = (struct ieee80211_mgmt *) buf;
- mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- os_memcpy(mgmt->da, addr, ETH_ALEN);
- os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
- mgmt->u.action.category = WLAN_ACTION_WNM;
- mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
- mgmt->u.action.u.bss_tm_req.dialog_token = 1;
- mgmt->u.action.u.bss_tm_req.req_mode =
- WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
- mgmt->u.action.u.bss_tm_req.disassoc_timer =
- host_to_le16(disassoc_timer);
- mgmt->u.action.u.bss_tm_req.validity_interval = 0;
-
- pos = mgmt->u.action.u.bss_tm_req.variable;
-
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
- wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
- "Management Request frame");
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for disassociation imminent message",
+ MAC2STR(addr));
return -1;
}
- return 0;
+ return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
}
@@ -708,14 +693,20 @@
{
u8 addr[ETH_ALEN];
const char *url, *timerstr;
- u8 buf[1000], *pos;
- struct ieee80211_mgmt *mgmt;
- size_t url_len;
int disassoc_timer;
+ struct sta_info *sta;
if (hwaddr_aton(cmd, addr))
return -1;
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for ESS disassociation imminent message",
+ MAC2STR(addr));
+ return -1;
+ }
+
timerstr = cmd + 17;
if (*timerstr != ' ')
return -1;
@@ -728,76 +719,8 @@
if (url == NULL)
return -1;
url++;
- url_len = os_strlen(url);
- if (url_len > 255)
- return -1;
- os_memset(buf, 0, sizeof(buf));
- mgmt = (struct ieee80211_mgmt *) buf;
- mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- os_memcpy(mgmt->da, addr, ETH_ALEN);
- os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
- os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
- mgmt->u.action.category = WLAN_ACTION_WNM;
- mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
- mgmt->u.action.u.bss_tm_req.dialog_token = 1;
- mgmt->u.action.u.bss_tm_req.req_mode =
- WNM_BSS_TM_REQ_DISASSOC_IMMINENT |
- WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
- mgmt->u.action.u.bss_tm_req.disassoc_timer =
- host_to_le16(disassoc_timer);
- mgmt->u.action.u.bss_tm_req.validity_interval = 0x01;
-
- pos = mgmt->u.action.u.bss_tm_req.variable;
-
- /* Session Information URL */
- *pos++ = url_len;
- os_memcpy(pos, url, url_len);
- pos += url_len;
-
- if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
- wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
- "Management Request frame");
- return -1;
- }
-
- /* send disassociation frame after time-out */
- if (disassoc_timer) {
- struct sta_info *sta;
- int timeout, beacon_int;
-
- /*
- * Prevent STA from reconnecting using cached PMKSA to force
- * full authentication with the authentication server (which may
- * decide to reject the connection),
- */
- wpa_auth_pmksa_remove(hapd->wpa_auth, addr);
-
- sta = ap_get_sta(hapd, addr);
- if (sta == NULL) {
- wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
- "for ESS disassociation imminent message",
- MAC2STR(addr));
- return -1;
- }
-
- beacon_int = hapd->iconf->beacon_int;
- if (beacon_int < 1)
- beacon_int = 100; /* best guess */
- /* Calculate timeout in ms based on beacon_int in TU */
- timeout = disassoc_timer * beacon_int * 128 / 125;
- wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR
- " set to %d ms", MAC2STR(addr), timeout);
-
- sta->timeout_next = STA_DISASSOC_FROM_CLI;
- eloop_cancel_timeout(ap_handle_timer, hapd, sta);
- eloop_register_timeout(timeout / 1000,
- timeout % 1000 * 1000,
- ap_handle_timer, hapd, sta);
- }
-
- return 0;
+ return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
}
#endif /* CONFIG_WNM */
@@ -994,6 +917,10 @@
else
hapd->gas_frag_limit = val;
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_TESTING_OPTIONS
+ } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
+ hapd->ext_mgmt_frame_handling = atoi(value);
+#endif /* CONFIG_TESTING_OPTIONS */
} else {
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
}
@@ -1051,6 +978,7 @@
#ifdef CONFIG_TESTING_OPTIONS
+
static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
{
union wpa_event_data data;
@@ -1108,6 +1036,35 @@
return 0;
}
+
+
+static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
+{
+ size_t len;
+ u8 *buf;
+ int res;
+
+ wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
+
+ len = os_strlen(cmd);
+ if (len & 1)
+ return -1;
+ len /= 2;
+
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return -1;
+
+ if (hexstr2bin(cmd, buf, len) < 0) {
+ os_free(buf);
+ return -1;
+ }
+
+ res = hostapd_drv_send_mlme(hapd, buf, len, 0);
+ os_free(buf);
+ return res;
+}
+
#endif /* CONFIG_TESTING_OPTIONS */
@@ -1127,6 +1084,19 @@
}
+static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
+ int reply_size, const char *param)
+{
+#ifdef RADIUS_SERVER
+ if (os_strcmp(param, "radius_server") == 0) {
+ return radius_server_get_mib(hapd->radius_srv, reply,
+ reply_size);
+ }
+#endif /* RADIUS_SERVER */
+ return -1;
+}
+
+
static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
@@ -1170,6 +1140,8 @@
} else if (os_strcmp(buf, "STATUS") == 0) {
reply_len = hostapd_ctrl_iface_status(hapd, reply,
reply_size);
+ } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
+ reply_len = hostapd_drv_status(hapd, reply, reply_size);
} else if (os_strcmp(buf, "MIB") == 0) {
reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
if (reply_len >= 0) {
@@ -1199,6 +1171,9 @@
reply_len += res;
}
#endif /* CONFIG_NO_RADIUS */
+ } else if (os_strncmp(buf, "MIB ", 4) == 0) {
+ reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
+ buf + 4);
} else if (os_strcmp(buf, "STA-FIRST") == 0) {
reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
reply_size);
@@ -1312,6 +1287,9 @@
} else if (os_strncmp(buf, "RADAR ", 6) == 0) {
if (hostapd_ctrl_iface_radar(hapd, buf + 6))
reply_len = -1;
+ } else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
+ if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
+ reply_len = -1;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
if (hostapd_ctrl_iface_chan_switch(hapd, buf + 12))
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 3f2924b..60f2c04 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -96,10 +96,9 @@
#CONFIG_EAP_GPSK_SHA256=y
# EAP-FAST for the integrated EAP server
-# Note: Default OpenSSL package does not include support for all the
-# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
-# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
-# to add the needed functions.
+# Note: If OpenSSL is used as the TLS library, OpenSSL 1.0 or newer is needed
+# for EAP-FAST support. Older OpenSSL releases would need to be patched, e.g.,
+# with openssl-0.9.8x-tls-extensions.patch, to add the needed functions.
#CONFIG_EAP_FAST=y
# Wi-Fi Protected Setup (WPS)
@@ -180,7 +179,7 @@
# Note: This requires libnl 3.1 or newer.
#CONFIG_VLAN_NETLINK=y
-# Remove support for dumping state into a file on SIGUSR1 signal
+# Remove support for dumping internal state through control interface commands
# This can be used to reduce binary size at the cost of disabling a debugging
# option.
#CONFIG_NO_DUMP_STATE=y
diff --git a/hostapd/dump_state.c b/hostapd/dump_state.c
deleted file mode 100644
index fcd9890..0000000
--- a/hostapd/dump_state.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * hostapd / State dump
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "utils/includes.h"
-#include <time.h>
-
-#include "utils/common.h"
-#include "radius/radius_client.h"
-#include "radius/radius_server.h"
-#include "eapol_auth/eapol_auth_sm.h"
-#include "eapol_auth/eapol_auth_sm_i.h"
-#include "eap_server/eap.h"
-#include "ap/hostapd.h"
-#include "ap/ap_config.h"
-#include "ap/sta_info.h"
-#include "dump_state.h"
-#include "ap/ap_drv_ops.h"
-
-
-static void fprint_char(FILE *f, char c)
-{
- if (c >= 32 && c < 127)
- fprintf(f, "%c", c);
- else
- fprintf(f, "<%02x>", c);
-}
-
-
-static void ieee802_1x_dump_state(FILE *f, const char *prefix,
- struct sta_info *sta)
-{
- struct eapol_state_machine *sm = sta->eapol_sm;
- if (sm == NULL)
- return;
-
- fprintf(f, "%sIEEE 802.1X:\n", prefix);
-
- if (sm->identity) {
- size_t i;
- fprintf(f, "%sidentity=", prefix);
- for (i = 0; i < sm->identity_len; i++)
- fprint_char(f, sm->identity[i]);
- fprintf(f, "\n");
- }
-
- fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
- "Supplicant: %d (%s)\n", prefix,
- sm->eap_type_authsrv,
- eap_server_get_name(0, sm->eap_type_authsrv),
- sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp));
-
- fprintf(f, "%scached_packets=%s\n", prefix,
- sm->last_recv_radius ? "[RX RADIUS]" : "");
-
- eapol_auth_dump_state(f, prefix, sm);
-}
-
-
-/**
- * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file
- */
-static void hostapd_dump_state(struct hostapd_data *hapd)
-{
- FILE *f;
- time_t now;
- struct sta_info *sta;
- int i;
-#ifndef CONFIG_NO_RADIUS
- char *buf;
-#endif /* CONFIG_NO_RADIUS */
- struct hostap_sta_driver_data data;
-
- if (!hapd->conf->dump_log_name) {
- wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump "
- "request");
- return;
- }
-
- wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'",
- hapd->conf->dump_log_name);
- f = fopen(hapd->conf->dump_log_name, "w");
- if (f == NULL) {
- wpa_printf(MSG_WARNING, "Could not open dump file '%s' for "
- "writing.", hapd->conf->dump_log_name);
- return;
- }
-
- time(&now);
- fprintf(f, "hostapd state dump - %s", ctime(&now));
- fprintf(f, "num_sta=%d num_sta_non_erp=%d "
- "num_sta_no_short_slot_time=%d\n"
- "num_sta_no_short_preamble=%d\n",
- hapd->num_sta, hapd->iface->num_sta_non_erp,
- hapd->iface->num_sta_no_short_slot_time,
- hapd->iface->num_sta_no_short_preamble);
-
- for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
- fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
-
- fprintf(f,
- " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
- "\n"
- " capability=0x%x listen_interval=%d\n",
- sta->aid,
- sta->flags,
- (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
- (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
- (sta->flags & WLAN_STA_PS ? "[PS]" : ""),
- (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
- (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
- (ap_sta_is_authorized(sta) ? "[AUTHORIZED]" : ""),
- (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
- ""),
- (sta->flags & WLAN_STA_SHORT_PREAMBLE ?
- "[SHORT_PREAMBLE]" : ""),
- (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
- (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""),
- (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
- (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
- (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
- (sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
- (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
- (sta->flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
- sta->capability,
- sta->listen_interval);
-
- fprintf(f, " supported_rates=");
- for (i = 0; i < sta->supported_rates_len; i++)
- fprintf(f, "%02x ", sta->supported_rates[i]);
- fprintf(f, "\n");
-
- fprintf(f,
- " timeout_next=%s\n",
- (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" :
- (sta->timeout_next == STA_DISASSOC ? "DISASSOC" :
- "DEAUTH")));
-
- ieee802_1x_dump_state(f, " ", sta);
-
- if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) == 0) {
- fprintf(f, " rx_pkt=%lu tx_pkt=%lu\n"
- " rx_byte=%lu tx_byte=%lu\n",
- data.rx_packets, data.tx_packets,
- data.rx_bytes, data.tx_bytes);
- }
- }
-
-#ifndef CONFIG_NO_RADIUS
- buf = os_malloc(4096);
- if (buf) {
- int count = radius_client_get_mib(hapd->radius, buf, 4096);
- if (count < 0)
- count = 0;
- else if (count > 4095)
- count = 4095;
- buf[count] = '\0';
- fprintf(f, "%s", buf);
-
-#ifdef RADIUS_SERVER
- count = radius_server_get_mib(hapd->radius_srv, buf, 4096);
- if (count < 0)
- count = 0;
- else if (count > 4095)
- count = 4095;
- buf[count] = '\0';
- fprintf(f, "%s", buf);
-#endif /* RADIUS_SERVER */
-
- os_free(buf);
- }
-#endif /* CONFIG_NO_RADIUS */
- fclose(f);
-}
-
-
-int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx)
-{
- size_t i;
-
- for (i = 0; i < iface->num_bss; i++)
- hostapd_dump_state(iface->bss[i]);
-
- return 0;
-}
diff --git a/hostapd/dump_state.h b/hostapd/dump_state.h
deleted file mode 100644
index a209d65..0000000
--- a/hostapd/dump_state.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * hostapd / State dump
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef DUMP_STATE_H
-#define DUMP_STATE_H
-
-int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx);
-
-#endif /* DUMP_STATE_H */
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 9b70d0f..da7817f 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -51,9 +51,6 @@
logger_stdout=-1
logger_stdout_level=2
-# Dump file for state information (on SIGUSR1)
-dump_file=/tmp/hostapd.dump
-
# Interface for separate control program. If this is specified, hostapd
# will create this directory and a UNIX domain socket for listening to requests
# from external programs (CLI/GUI, etc.) for status information and
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index b2d3e5b..eee8504 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1,6 +1,6 @@
/*
* hostapd - command line interface for hostapd daemon
- * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -18,7 +18,7 @@
static const char *hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
static const char *hostapd_cli_license =
@@ -218,12 +218,19 @@
static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
+ if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
+ return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
return wpa_ctrl_command(ctrl, "STATUS");
}
static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
+ if (argc > 0) {
+ char buf[100];
+ os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
+ return wpa_ctrl_command(ctrl, buf);
+ }
return wpa_ctrl_command(ctrl, "MIB");
}
@@ -276,12 +283,15 @@
static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char buf[64];
- if (argc != 1) {
- printf("Invalid 'sta' command - exactly one argument, STA "
+ if (argc < 1) {
+ printf("Invalid 'sta' command - at least one argument, STA "
"address, is required.\n");
return -1;
}
- snprintf(buf, sizeof(buf), "STA %s", argv[0]);
+ if (argc > 1)
+ snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
+ else
+ snprintf(buf, sizeof(buf), "STA %s", argv[0]);
return wpa_ctrl_command(ctrl, buf);
}
diff --git a/hostapd/main.c b/hostapd/main.c
index 4e9fe40..5a1b0a9 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -25,17 +25,9 @@
#include "ap/ap_drv_ops.h"
#include "config_file.h"
#include "eap_register.h"
-#include "dump_state.h"
#include "ctrl_iface.h"
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-extern int wpa_debug_timestamp;
-
-extern struct wpa_driver_ops *wpa_drivers[];
-
-
struct hapd_global {
void **drv_priv;
size_t drv_count;
@@ -302,10 +294,7 @@
static void handle_dump_state(int sig, void *signal_ctx)
{
-#ifdef HOSTAPD_DUMP_STATE
- struct hapd_interfaces *interfaces = signal_ctx;
- hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL);
-#endif /* HOSTAPD_DUMP_STATE */
+ /* Not used anymore - ignore signal */
}
#endif /* CONFIG_NATIVE_WINDOWS */
@@ -424,7 +413,7 @@
"hostapd v" VERSION_STR "\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
- "Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> "
+ "Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi> "
"and contributors\n");
}
diff --git a/src/ap/accounting.c b/src/ap/accounting.c
index a1f67f0..6290d3f 100644
--- a/src/ap/accounting.c
+++ b/src/ap/accounting.c
@@ -10,7 +10,6 @@
#include "utils/common.h"
#include "utils/eloop.h"
-#include "drivers/driver.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "hostapd.h"
@@ -202,7 +201,6 @@
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
{
struct radius_msg *msg;
- struct os_time t;
int interval;
if (sta->acct_session_started)
@@ -213,8 +211,7 @@
"starting accounting session %08X-%08X",
sta->acct_session_id_hi, sta->acct_session_id_lo);
- os_get_time(&t);
- sta->acct_session_start = t.sec;
+ os_get_reltime(&sta->acct_session_start);
sta->last_rx_bytes = sta->last_tx_bytes = 0;
sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
hostapd_drv_sta_clear_stats(hapd, sta->addr);
@@ -244,6 +241,7 @@
struct radius_msg *msg;
int cause = sta->acct_terminate_cause;
struct hostap_sta_driver_data data;
+ struct os_reltime now_r, diff;
struct os_time now;
u32 gigawords;
@@ -258,9 +256,11 @@
return;
}
+ os_get_reltime(&now_r);
os_get_time(&now);
+ os_reltime_sub(&now_r, &sta->acct_session_start, &diff);
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
- now.sec - sta->acct_session_start)) {
+ diff.sec)) {
wpa_printf(MSG_INFO, "Could not add Acct-Session-Time");
goto fail;
}
diff --git a/src/ap/acs.c b/src/ap/acs.c
index 9ef221e..f58b091 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -280,7 +280,7 @@
}
-void acs_fail(struct hostapd_iface *iface)
+static void acs_fail(struct hostapd_iface *iface)
{
wpa_printf(MSG_ERROR, "ACS: Failed to start");
acs_cleanup(iface);
diff --git a/src/ap/acs.h b/src/ap/acs.h
index a41f17f..fc85259 100644
--- a/src/ap/acs.h
+++ b/src/ap/acs.h
@@ -13,7 +13,6 @@
#ifdef CONFIG_ACS
enum hostapd_chan_status acs_init(struct hostapd_iface *iface);
-int hostapd_acs_completed(struct hostapd_iface *iface, int err);
#else /* CONFIG_ACS */
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 65a6f12..a29f4d0 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -433,7 +433,6 @@
}
os_free(conf->eap_user_sqlite);
- os_free(conf->dump_log_name);
os_free(conf->eap_req_id_text);
os_free(conf->accept_mac);
os_free(conf->deny_mac);
@@ -759,7 +758,9 @@
if (conf->ieee80211n && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
- !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))) {
+ !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
+ WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
+ {
bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
"requires CCMP/GCMP to be enabled, disabling HT "
@@ -792,7 +793,9 @@
#ifdef CONFIG_HS20
if (bss->hs20 &&
(!(bss->wpa & 2) ||
- !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) {
+ !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
+ WPA_CIPHER_CCMP_256 |
+ WPA_CIPHER_GCMP_256)))) {
wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP "
"configuration is required for Hotspot 2.0 "
"functionality");
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 09b2778..af30ac4 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -189,8 +189,6 @@
unsigned int logger_syslog; /* module bitfield */
unsigned int logger_stdout; /* module bitfield */
- char *dump_log_name; /* file name for state dump (SIGUSR1) */
-
int max_num_sta; /* maximum number of STAs in station table */
int dtim_period;
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 09b5f68..893e6d9 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -9,7 +9,6 @@
#include "utils/includes.h"
#include "utils/common.h"
-#include "drivers/driver.h"
#include "common/ieee802_11_defs.h"
#include "wps/wps.h"
#include "p2p/p2p.h"
@@ -715,7 +714,7 @@
const u8 *peer, u8 *buf, u16 *buf_len)
{
if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
- return 0;
+ return -1;
return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
buf_len);
}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index b5f6a02..15a4b26 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -1,6 +1,6 @@
/*
* hostapd - Driver operations
- * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -272,4 +272,12 @@
return hapd->driver->switch_channel(hapd->drv_priv, settings);
}
+static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf,
+ size_t buflen)
+{
+ if (hapd->driver == NULL || hapd->driver->status == NULL)
+ return -1;
+ return hapd->driver->status(hapd->drv_priv, buf, buflen);
+}
+
#endif /* AP_DRV_OPS */
diff --git a/src/ap/ap_list.c b/src/ap/ap_list.c
index 0dab39f..f9b1540 100644
--- a/src/ap/ap_list.c
+++ b/src/ap/ap_list.c
@@ -14,7 +14,6 @@
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
-#include "drivers/driver.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ieee802_11.h"
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 0e0dae4..5318ecb 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -4,14 +4,8 @@
* Copyright (c) 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2008-2012, 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "utils/includes.h"
@@ -21,7 +15,6 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
-#include "drivers/driver.h"
#include "wps/wps_defs.h"
#include "p2p/p2p.h"
#include "hostapd.h"
@@ -207,10 +200,10 @@
{
u8 chan;
- if (!hapd->iface->cs_freq)
+ if (!hapd->iface->cs_freq_params.freq)
return eid;
- if (ieee80211_freq_to_chan(hapd->iface->cs_freq, &chan) ==
+ if (ieee80211_freq_to_chan(hapd->iface->cs_freq_params.freq, &chan) ==
NUM_HOSTAPD_MODES)
return eid;
@@ -224,13 +217,56 @@
}
+static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 sec_ch;
+
+ if (!hapd->iface->cs_freq_params.sec_channel_offset)
+ return eid;
+
+ if (hapd->iface->cs_freq_params.sec_channel_offset == -1)
+ sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
+ else if (hapd->iface->cs_freq_params.sec_channel_offset == 1)
+ sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
+ else
+ return eid;
+
+ *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
+ *eid++ = 1;
+ *eid++ = sec_ch;
+
+ return eid;
+}
+
+
+static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
+ u8 *start, unsigned int *csa_counter_off)
+{
+ u8 *old_pos = pos;
+
+ if (!csa_counter_off)
+ return pos;
+
+ *csa_counter_off = 0;
+ pos = hostapd_eid_csa(hapd, pos);
+
+ if (pos != old_pos) {
+ /* save an offset to the counter - should be last byte */
+ *csa_counter_off = pos - start - 1;
+ pos = hostapd_eid_secondary_channel(hapd, pos);
+ }
+
+ return pos;
+}
+
+
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
struct sta_info *sta,
const struct ieee80211_mgmt *req,
int is_p2p, size_t *resp_len)
{
struct ieee80211_mgmt *resp;
- u8 *pos, *epos, *old_pos;
+ u8 *pos, *epos;
size_t buflen;
#define MAX_PROBERESP_LEN 768
@@ -304,13 +340,8 @@
pos = hostapd_eid_adv_proto(hapd, pos);
pos = hostapd_eid_roaming_consortium(hapd, pos);
- old_pos = pos;
- pos = hostapd_eid_csa(hapd, pos);
-
- /* save an offset to the counter - should be last byte */
- hapd->iface->cs_c_off_proberesp = (pos != old_pos) ?
- pos - (u8 *) resp - 1 : 0;
-
+ pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
+ &hapd->iface->cs_c_off_proberesp);
#ifdef CONFIG_IEEE80211AC
pos = hostapd_eid_vht_capabilities(hapd, pos);
pos = hostapd_eid_vht_operation(hapd, pos);
@@ -626,7 +657,7 @@
size_t resp_len = 0;
#ifdef NEED_AP_MLME
u16 capab_info;
- u8 *pos, *tailpos, *old_pos;
+ u8 *pos, *tailpos;
#define BEACON_HEAD_BUF_SIZE 256
#define BEACON_TAIL_BUF_SIZE 512
@@ -721,11 +752,8 @@
tailpos = hostapd_eid_interworking(hapd, tailpos);
tailpos = hostapd_eid_adv_proto(hapd, tailpos);
tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
- old_pos = tailpos;
- tailpos = hostapd_eid_csa(hapd, tailpos);
- hapd->iface->cs_c_off_beacon = (old_pos != tailpos) ?
- tailpos - tail - 1 : 0;
-
+ tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
+ &hapd->iface->cs_c_off_beacon);
#ifdef CONFIG_IEEE80211AC
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
@@ -844,20 +872,21 @@
}
-void ieee802_11_set_beacon(struct hostapd_data *hapd)
+int ieee802_11_set_beacon(struct hostapd_data *hapd)
{
struct wpa_driver_ap_params params;
struct wpabuf *beacon, *proberesp, *assocresp;
+ int res, ret = -1;
if (hapd->iface->csa_in_progress) {
wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
- return;
+ return -1;
}
hapd->beacon_set_done = 1;
if (ieee802_11_build_ap_params(hapd, ¶ms) < 0)
- return;
+ return -1;
if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
0)
@@ -867,31 +896,46 @@
params.proberesp_ies = proberesp;
params.assocresp_ies = assocresp;
- if (hostapd_drv_set_ap(hapd, ¶ms))
- wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
+ res = hostapd_drv_set_ap(hapd, ¶ms);
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
+ if (res)
+ wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
+ else
+ ret = 0;
fail:
ieee802_11_free_ap_params(¶ms);
+ return ret;
}
-void ieee802_11_set_beacons(struct hostapd_iface *iface)
+int ieee802_11_set_beacons(struct hostapd_iface *iface)
{
size_t i;
+ int ret = 0;
+
for (i = 0; i < iface->num_bss; i++) {
- if (iface->bss[i]->started)
- ieee802_11_set_beacon(iface->bss[i]);
+ if (iface->bss[i]->started &&
+ ieee802_11_set_beacon(iface->bss[i]) < 0)
+ ret = -1;
}
+
+ return ret;
}
/* only update beacons if started */
-void ieee802_11_update_beacons(struct hostapd_iface *iface)
+int ieee802_11_update_beacons(struct hostapd_iface *iface)
{
size_t i;
- for (i = 0; i < iface->num_bss; i++)
- if (iface->bss[i]->beacon_set_done && iface->bss[i]->started)
- ieee802_11_set_beacon(iface->bss[i]);
+ int ret = 0;
+
+ for (i = 0; i < iface->num_bss; i++) {
+ if (iface->bss[i]->beacon_set_done && iface->bss[i]->started &&
+ ieee802_11_set_beacon(iface->bss[i]) < 0)
+ ret = -1;
+ }
+
+ return ret;
}
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/src/ap/beacon.h b/src/ap/beacon.h
index a04a829..722159a 100644
--- a/src/ap/beacon.h
+++ b/src/ap/beacon.h
@@ -3,14 +3,8 @@
* Copyright (c) 2002-2004, Instant802 Networks, Inc.
* Copyright (c) 2005-2006, Devicescape Software, Inc.
*
- * 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef BEACON_H
@@ -21,9 +15,9 @@
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len,
int ssi_signal);
-void ieee802_11_set_beacon(struct hostapd_data *hapd);
-void ieee802_11_set_beacons(struct hostapd_iface *iface);
-void ieee802_11_update_beacons(struct hostapd_iface *iface);
+int ieee802_11_set_beacon(struct hostapd_data *hapd);
+int ieee802_11_set_beacons(struct hostapd_iface *iface);
+int ieee802_11_update_beacons(struct hostapd_iface *iface);
int ieee802_11_build_ap_params(struct hostapd_data *hapd,
struct wpa_driver_ap_params *params);
void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params);
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 4125fd5..3fb9e04 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -10,6 +10,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
+#include "eapol_auth/eapol_auth_sm.h"
#include "hostapd.h"
#include "ieee802_1x.h"
#include "wpa_auth.h"
@@ -21,24 +22,61 @@
#include "ap_drv_ops.h"
+static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ char *buf, size_t buflen)
+{
+ struct hostap_sta_driver_data data;
+ int ret;
+
+ if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+ return 0;
+
+ ret = os_snprintf(buf, buflen, "rx_packets=%lu\ntx_packets=%lu\n"
+ "rx_bytes=%lu\ntx_bytes=%lu\n",
+ data.rx_packets, data.tx_packets,
+ data.rx_bytes, data.tx_bytes);
+ if (ret < 0 || (size_t) ret >= buflen)
+ return 0;
+ return ret;
+}
+
+
static int hostapd_get_sta_conn_time(struct sta_info *sta,
char *buf, size_t buflen)
{
struct os_reltime age;
- int len = 0, ret;
+ int ret;
if (!sta->connected_time.sec)
return 0;
os_reltime_age(&sta->connected_time, &age);
- ret = os_snprintf(buf + len, buflen - len, "connected_time=%u\n",
+ ret = os_snprintf(buf, buflen, "connected_time=%u\n",
(unsigned int) age.sec);
- if (ret < 0 || (size_t) ret >= buflen - len)
- return len;
- len += ret;
+ if (ret < 0 || (size_t) ret >= buflen)
+ return 0;
+ return ret;
+}
- return len;
+
+static const char * timeout_next_str(int val)
+{
+ switch (val) {
+ case STA_NULLFUNC:
+ return "NULLFUNC POLL";
+ case STA_DISASSOC:
+ return "DISASSOC";
+ case STA_DEAUTH:
+ return "DEAUTH";
+ case STA_REMOVE:
+ return "REMOVE";
+ case STA_DISASSOC_FROM_CLI:
+ return "DISASSOC_FROM_CLI";
+ }
+
+ return "?";
}
@@ -46,22 +84,42 @@
struct sta_info *sta,
char *buf, size_t buflen)
{
- int len, res, ret;
-
- if (sta == NULL) {
- ret = os_snprintf(buf, buflen, "FAIL\n");
- if (ret < 0 || (size_t) ret >= buflen)
- return 0;
- return ret;
- }
+ int len, res, ret, i;
len = 0;
- ret = os_snprintf(buf + len, buflen - len, MACSTR "\n",
+ ret = os_snprintf(buf + len, buflen - len, MACSTR "\nflags=",
MAC2STR(sta->addr));
if (ret < 0 || (size_t) ret >= buflen - len)
return len;
len += ret;
+ ret = ap_sta_flags_txt(sta->flags, buf + len, buflen - len);
+ if (ret < 0)
+ return len;
+ len += ret;
+
+ ret = os_snprintf(buf + len, buflen - len, "\naid=%d\ncapability=0x%x\n"
+ "listen_interval=%d\nsupported_rates=",
+ sta->aid, sta->capability, sta->listen_interval);
+ if (ret < 0 || (size_t) ret >= buflen - len)
+ return len;
+ len += ret;
+
+ for (i = 0; i < sta->supported_rates_len; i++) {
+ ret = os_snprintf(buf + len, buflen - len, "%02x%s",
+ sta->supported_rates[i],
+ i + 1 < sta->supported_rates_len ? " " : "");
+ if (ret < 0 || (size_t) ret >= buflen - len)
+ return len;
+ len += ret;
+ }
+
+ ret = os_snprintf(buf + len, buflen - len, "\ntimeout_next=%s\n",
+ timeout_next_str(sta->timeout_next));
+ if (ret < 0 || (size_t) ret >= buflen - len)
+ return len;
+ len += ret;
+
res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
if (res >= 0)
len += res;
@@ -79,9 +137,8 @@
if (res >= 0)
len += res;
- res = hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
- if (res >= 0)
- len += res;
+ len += hostapd_get_sta_tx_rx(hapd, sta, buf + len, buflen - len);
+ len += hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
return len;
}
@@ -99,6 +156,8 @@
{
u8 addr[ETH_ALEN];
int ret;
+ const char *pos;
+ struct sta_info *sta;
if (hwaddr_aton(txtaddr, addr)) {
ret = os_snprintf(buf, buflen, "FAIL\n");
@@ -106,8 +165,28 @@
return 0;
return ret;
}
- return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr),
- buf, buflen);
+
+ sta = ap_get_sta(hapd, addr);
+ if (sta == NULL)
+ return -1;
+
+ pos = os_strchr(txtaddr, ' ');
+ if (pos) {
+ pos++;
+
+#ifdef HOSTAPD_DUMP_STATE
+ if (os_strcmp(pos, "eapol") == 0) {
+ if (sta->eapol_sm == NULL)
+ return -1;
+ return eapol_auth_dump_state(sta->eapol_sm, buf,
+ buflen);
+ }
+#endif /* HOSTAPD_DUMP_STATE */
+
+ return -1;
+ }
+
+ return hostapd_ctrl_iface_sta_mib(hapd, sta, buf, buflen);
}
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index b066bff..9af9646 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -299,6 +299,7 @@
new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+ sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
@@ -439,7 +440,8 @@
hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
- if (hapd->iface->csa_in_progress && freq == hapd->iface->cs_freq) {
+ if (hapd->iface->csa_in_progress &&
+ freq == hapd->iface->cs_freq_params.freq) {
hostapd_cleanup_cs_params(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d",
@@ -556,39 +558,48 @@
static void hostapd_action_rx(struct hostapd_data *hapd,
- struct rx_action *action)
+ struct rx_mgmt *drv_mgmt)
{
+ struct ieee80211_mgmt *mgmt;
struct sta_info *sta;
+ size_t plen __maybe_unused;
+ u16 fc;
+
+ if (drv_mgmt->frame_len < 24 + 1)
+ return;
+
+ plen = drv_mgmt->frame_len - 24 - 1;
+
+ mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame;
+ fc = le_to_host16(mgmt->frame_control);
+ if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION)
+ return; /* handled by the driver */
wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
- action->category, (int) action->len);
+ mgmt->u.action.category, (int) plen);
- sta = ap_get_sta(hapd, action->sa);
+ sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL) {
wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
return;
}
#ifdef CONFIG_IEEE80211R
- if (action->category == WLAN_ACTION_FT) {
- wpa_printf(MSG_DEBUG, "%s: FT_ACTION length %d",
- __func__, (int) action->len);
- wpa_ft_action_rx(sta->wpa_sm, action->data, action->len);
+ if (mgmt->u.action.category == WLAN_ACTION_FT) {
+ const u8 *payload = drv_mgmt->frame + 24 + 1;
+ wpa_ft_action_rx(sta->wpa_sm, payload, plen);
}
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
- if (action->category == WLAN_ACTION_SA_QUERY && action->len >= 4) {
- wpa_printf(MSG_DEBUG, "%s: SA_QUERY_ACTION length %d",
- __func__, (int) action->len);
- ieee802_11_sa_query_action(hapd, action->sa,
- *(action->data + 1),
- action->data + 2);
+ if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) {
+ ieee802_11_sa_query_action(
+ hapd, mgmt->sa,
+ mgmt->u.action.u.sa_query_resp.action,
+ mgmt->u.action.u.sa_query_resp.trans_id);
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WNM
- if (action->category == WLAN_ACTION_WNM) {
- wpa_printf(MSG_DEBUG, "%s: WNM_ACTION length %d",
- __func__, (int) action->len);
- ieee802_11_rx_wnm_action_ap(hapd, action);
+ if (mgmt->u.action.category == WLAN_ACTION_WNM) {
+ ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
}
#endif /* CONFIG_WNM */
}
@@ -630,17 +641,18 @@
}
-static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
+static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
{
struct hostapd_iface *iface = hapd->iface;
const struct ieee80211_hdr *hdr;
const u8 *bssid;
struct hostapd_frame_info fi;
+ int ret;
hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
if (bssid == NULL)
- return;
+ return 0;
hapd = get_hapd_bssid(iface, bssid);
if (hapd == NULL) {
@@ -655,7 +667,7 @@
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
hapd = iface->bss[0];
else
- return;
+ return 0;
}
os_memset(&fi, 0, sizeof(fi));
@@ -664,53 +676,19 @@
if (hapd == HAPD_BROADCAST) {
size_t i;
- for (i = 0; i < iface->num_bss; i++)
- ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
- rx_mgmt->frame_len, &fi);
+ ret = 0;
+ for (i = 0; i < iface->num_bss; i++) {
+ if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
+ rx_mgmt->frame_len, &fi) > 0)
+ ret = 1;
+ }
} else
- ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi);
+ ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len,
+ &fi);
random_add_randomness(&fi, sizeof(fi));
-}
-
-static void hostapd_rx_action(struct hostapd_data *hapd,
- struct rx_action *rx_action)
-{
- struct rx_mgmt rx_mgmt;
- u8 *buf;
- struct ieee80211_hdr *hdr;
-
- wpa_printf(MSG_DEBUG, "EVENT_RX_ACTION DA=" MACSTR " SA=" MACSTR
- " BSSID=" MACSTR " category=%u",
- MAC2STR(rx_action->da), MAC2STR(rx_action->sa),
- MAC2STR(rx_action->bssid), rx_action->category);
- wpa_hexdump(MSG_MSGDUMP, "Received action frame contents",
- rx_action->data, rx_action->len);
-
- buf = os_zalloc(24 + 1 + rx_action->len);
- if (buf == NULL)
- return;
- hdr = (struct ieee80211_hdr *) buf;
- hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_ACTION);
- if (rx_action->category == WLAN_ACTION_SA_QUERY) {
- /*
- * Assume frame was protected; it would have been dropped if
- * not.
- */
- hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
- }
- os_memcpy(hdr->addr1, rx_action->da, ETH_ALEN);
- os_memcpy(hdr->addr2, rx_action->sa, ETH_ALEN);
- os_memcpy(hdr->addr3, rx_action->bssid, ETH_ALEN);
- buf[24] = rx_action->category;
- os_memcpy(buf + 24 + 1, rx_action->data, rx_action->len);
- os_memset(&rx_mgmt, 0, sizeof(rx_mgmt));
- rx_mgmt.frame = buf;
- rx_mgmt.frame_len = 24 + 1 + rx_action->len;
- hostapd_mgmt_rx(hapd, &rx_mgmt);
- os_free(buf);
+ return ret;
}
@@ -952,10 +930,14 @@
data->rx_from_unknown.addr,
data->rx_from_unknown.wds);
break;
- case EVENT_RX_MGMT:
- hostapd_mgmt_rx(hapd, &data->rx_mgmt);
- break;
#endif /* NEED_AP_MLME */
+ case EVENT_RX_MGMT:
+#ifdef NEED_AP_MLME
+ if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0)
+ break;
+#endif /* NEED_AP_MLME */
+ hostapd_action_rx(hapd, &data->rx_mgmt);
+ break;
case EVENT_RX_PROBE_REQ:
if (data->rx_probe_req.sa == NULL ||
data->rx_probe_req.ie == NULL)
@@ -994,15 +976,6 @@
break;
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
break;
- case EVENT_RX_ACTION:
- if (data->rx_action.da == NULL || data->rx_action.sa == NULL ||
- data->rx_action.bssid == NULL)
- break;
-#ifdef NEED_AP_MLME
- hostapd_rx_action(hapd, &data->rx_action);
-#endif /* NEED_AP_MLME */
- hostapd_action_rx(hapd, &data->rx_action);
- break;
case EVENT_AUTH:
hostapd_notif_auth(hapd, &data->auth);
break;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index a436c2a..44d05c5 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -14,7 +14,6 @@
#include "common/wpa_ctrl.h"
#include "radius/radius_client.h"
#include "radius/radius_das.h"
-#include "drivers/driver.h"
#include "hostapd.h"
#include "authsrv.h"
#include "sta_info.h"
@@ -42,9 +41,6 @@
static int setup_interface2(struct hostapd_iface *iface);
static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
-extern int wpa_debug_level;
-extern struct wpa_driver_ops *wpa_drivers[];
-
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
@@ -811,8 +807,8 @@
return -1;
}
- if (!hapd->conf->start_disabled)
- ieee802_11_set_beacon(hapd);
+ if (!hapd->conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+ return -1;
if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
return -1;
@@ -2200,7 +2196,7 @@
return ret;
/* set channel switch parameters for csa ie */
- iface->cs_freq = settings->freq_params.freq;
+ iface->cs_freq_params = settings->freq_params;
iface->cs_count = settings->cs_count;
iface->cs_block_tx = settings->block_tx;
@@ -2219,7 +2215,8 @@
void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
{
- hapd->iface->cs_freq = 0;
+ os_memset(&hapd->iface->cs_freq_params, 0,
+ sizeof(hapd->iface->cs_freq_params));
hapd->iface->cs_count = 0;
hapd->iface->cs_block_tx = 0;
hapd->iface->cs_c_off_beacon = 0;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 84468de..489ab16 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -11,14 +11,13 @@
#include "common/defs.h"
#include "ap_config.h"
+#include "drivers/driver.h"
-struct wpa_driver_ops;
struct wpa_ctrl_dst;
struct radius_server_data;
struct upnp_wps_device_sm;
struct hostapd_data;
struct sta_info;
-struct hostap_sta_driver_data;
struct ieee80211_ht_capabilities;
struct full_dynamic_vlan;
enum wps_event;
@@ -27,8 +26,6 @@
struct hostapd_iface;
struct hostapd_dynamic_iface;
-struct csa_settings;
-
struct hapd_interfaces {
int (*reload_config)(struct hostapd_iface *iface);
struct hostapd_config * (*config_read_cb)(const char *config_fname);
@@ -146,7 +143,7 @@
struct eapol_authenticator *eapol_auth;
struct rsn_preauth_interface *preauth_iface;
- time_t michael_mic_failure;
+ struct os_reltime michael_mic_failure;
int michael_mic_failures;
int tkip_countermeasures;
@@ -243,6 +240,10 @@
u8 sae_token_key[8];
struct os_reltime last_sae_token_key_update;
#endif /* CONFIG_SAE */
+
+#ifdef CONFIG_TESTING_OPTIONS
+ int ext_mgmt_frame_handling;
+#endif /* CONFIG_TESTING_OPTIONS */
};
@@ -337,7 +338,7 @@
s8 lowest_nf;
/* channel switch parameters */
- int cs_freq;
+ struct hostapd_freq_params cs_freq_params;
u8 cs_count;
int cs_block_tx;
unsigned int cs_c_off_beacon;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index e95e0e1..4e66379 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -4,14 +4,8 @@
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2008-2012, 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "utils/includes.h"
@@ -21,7 +15,6 @@
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
-#include "drivers/driver.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index abadcd1..783ae5e 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -4,14 +4,8 @@
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2008-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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef HW_FEATURES_H
@@ -21,6 +15,7 @@
void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
size_t num_hw_features);
int hostapd_get_hw_features(struct hostapd_iface *iface);
+int hostapd_acs_completed(struct hostapd_iface *iface, int err);
int hostapd_select_hw_mode(struct hostapd_iface *iface);
const char * hostapd_hw_mode_txt(int mode);
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index e55f843..1e3693d 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -15,7 +15,6 @@
#include "crypto/crypto.h"
#include "crypto/sha256.h"
#include "crypto/random.h"
-#include "drivers/driver.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
@@ -239,13 +238,8 @@
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"authentication OK (shared key)");
-#ifdef IEEE80211_REQUIRE_AUTH_ACK
- /* Station will be marked authenticated if it ACKs the
- * authentication reply. */
-#else
sta->flags |= WLAN_STA_AUTH;
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
-#endif
os_free(sta->challenge);
sta->challenge = NULL;
@@ -691,15 +685,10 @@
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"authentication OK (open system)");
-#ifdef IEEE80211_REQUIRE_AUTH_ACK
- /* Station will be marked authenticated if it ACKs the
- * authentication reply. */
-#else
sta->flags |= WLAN_STA_AUTH;
wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
sta->auth_alg = WLAN_AUTH_OPEN;
mlme_authenticate_indication(hapd, sta);
-#endif
break;
case WLAN_AUTH_SHARED_KEY:
resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
@@ -926,7 +915,7 @@
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "Station does not support "
"mandatory VHT PHY - reject association");
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
}
#endif /* CONFIG_IEEE80211AC */
@@ -1068,7 +1057,9 @@
#ifdef CONFIG_SAE
if (wpa_auth_uses_sae(sta->wpa_sm) &&
- sta->auth_alg != WLAN_AUTH_SAE) {
+ sta->auth_alg != WLAN_AUTH_SAE &&
+ !(sta->auth_alg == WLAN_AUTH_FT &&
+ wpa_auth_uses_ft_sae(sta->wpa_sm))) {
wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
"SAE AKM after non-SAE auth_alg %u",
MAC2STR(sta->addr), sta->auth_alg);
@@ -1544,9 +1535,9 @@
#ifdef CONFIG_IEEE80211W
-static void hostapd_sa_query_action(struct hostapd_data *hapd,
- const struct ieee80211_mgmt *mgmt,
- size_t len)
+static int hostapd_sa_query_action(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *mgmt,
+ size_t len)
{
const u8 *end;
@@ -1555,12 +1546,13 @@
if (((u8 *) mgmt) + len < end) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action "
"frame (len=%lu)", (unsigned long) len);
- return;
+ return 0;
}
ieee802_11_sa_query_action(hapd, mgmt->sa,
mgmt->u.action.u.sa_query_resp.action,
mgmt->u.action.u.sa_query_resp.trans_id);
+ return 1;
}
@@ -1572,29 +1564,8 @@
#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_WNM
-static void hostapd_wnm_action(struct hostapd_data *hapd, struct sta_info *sta,
- const struct ieee80211_mgmt *mgmt,
- size_t len)
-{
- struct rx_action action;
- if (len < IEEE80211_HDRLEN + 2)
- return;
- os_memset(&action, 0, sizeof(action));
- action.da = mgmt->da;
- action.sa = mgmt->sa;
- action.bssid = mgmt->bssid;
- action.category = mgmt->u.action.category;
- action.data = (const u8 *) &mgmt->u.action.u.wnm_sleep_req.action;
- action.len = len - IEEE80211_HDRLEN - 1;
- action.freq = hapd->iface->freq;
- ieee802_11_rx_wnm_action_ap(hapd, &action);
-}
-#endif /* CONFIG_WNM */
-
-
-static void handle_action(struct hostapd_data *hapd,
- const struct ieee80211_mgmt *mgmt, size_t len)
+static int handle_action(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *mgmt, size_t len)
{
struct sta_info *sta;
sta = ap_get_sta(hapd, mgmt->sa);
@@ -1604,7 +1575,7 @@
HOSTAPD_LEVEL_DEBUG,
"handle_action - too short payload (len=%lu)",
(unsigned long) len);
- return;
+ return 0;
}
if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
@@ -1612,7 +1583,7 @@
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
"frame (category=%u) from unassociated STA " MACSTR,
MAC2STR(mgmt->sa), mgmt->u.action.category);
- return;
+ return 0;
}
#ifdef CONFIG_IEEE80211W
@@ -1623,7 +1594,7 @@
HOSTAPD_LEVEL_DEBUG,
"Dropped unprotected Robust Action frame from "
"an MFP STA");
- return;
+ return 0;
}
#endif /* CONFIG_IEEE80211W */
@@ -1633,20 +1604,19 @@
if (wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
len - IEEE80211_HDRLEN))
break;
- return;
+ return 1;
#endif /* CONFIG_IEEE80211R */
case WLAN_ACTION_WMM:
hostapd_wmm_action(hapd, mgmt, len);
- return;
+ return 1;
#ifdef CONFIG_IEEE80211W
case WLAN_ACTION_SA_QUERY:
- hostapd_sa_query_action(hapd, mgmt, len);
- return;
+ return hostapd_sa_query_action(hapd, mgmt, len);
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WNM
case WLAN_ACTION_WNM:
- hostapd_wnm_action(hapd, sta, mgmt, len);
- return;
+ ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
+ return 1;
#endif /* CONFIG_WNM */
case WLAN_ACTION_PUBLIC:
if (hapd->public_action_cb) {
@@ -1660,14 +1630,14 @@
hapd->iface->freq);
}
if (hapd->public_action_cb || hapd->public_action_cb2)
- return;
+ return 1;
break;
case WLAN_ACTION_VENDOR_SPECIFIC:
if (hapd->vendor_action_cb) {
if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
(u8 *) mgmt, len,
hapd->iface->freq) == 0)
- return;
+ return 1;
}
break;
}
@@ -1690,7 +1660,7 @@
"frame back to sender");
resp = os_malloc(len);
if (resp == NULL)
- return;
+ return 0;
os_memcpy(resp, mgmt, len);
os_memcpy(resp->da, resp->sa, ETH_ALEN);
os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
@@ -1703,6 +1673,8 @@
}
os_free(resp);
}
+
+ return 1;
}
@@ -1719,15 +1691,29 @@
* addition, it can be called to re-inserted pending frames (e.g., when using
* external RADIUS server as an MAC ACL).
*/
-void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
- struct hostapd_frame_info *fi)
+int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
+ struct hostapd_frame_info *fi)
{
struct ieee80211_mgmt *mgmt;
int broadcast;
u16 fc, stype;
+ int ret = 0;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->ext_mgmt_frame_handling) {
+ size_t hex_len = 2 * len + 1;
+ char *hex = os_malloc(hex_len);
+ if (hex) {
+ wpa_snprintf_hex(hex, hex_len, buf, len);
+ wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex);
+ os_free(hex);
+ }
+ return 1;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
if (len < 24)
- return;
+ return 0;
mgmt = (struct ieee80211_mgmt *) buf;
fc = le_to_host16(mgmt->frame_control);
@@ -1735,7 +1721,7 @@
if (stype == WLAN_FC_STYPE_BEACON) {
handle_beacon(hapd, mgmt, len, fi);
- return;
+ return 1;
}
broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
@@ -1751,13 +1737,13 @@
os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
MAC2STR(mgmt->bssid));
- return;
+ return 0;
}
if (stype == WLAN_FC_STYPE_PROBE_REQ) {
handle_probe_req(hapd, mgmt, len, fi->ssi_signal);
- return;
+ return 1;
}
if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
@@ -1765,33 +1751,38 @@
HOSTAPD_LEVEL_DEBUG,
"MGMT: DA=" MACSTR " not our address",
MAC2STR(mgmt->da));
- return;
+ return 0;
}
switch (stype) {
case WLAN_FC_STYPE_AUTH:
wpa_printf(MSG_DEBUG, "mgmt::auth");
handle_auth(hapd, mgmt, len);
+ ret = 1;
break;
case WLAN_FC_STYPE_ASSOC_REQ:
wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
handle_assoc(hapd, mgmt, len, 0);
+ ret = 1;
break;
case WLAN_FC_STYPE_REASSOC_REQ:
wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
handle_assoc(hapd, mgmt, len, 1);
+ ret = 1;
break;
case WLAN_FC_STYPE_DISASSOC:
wpa_printf(MSG_DEBUG, "mgmt::disassoc");
handle_disassoc(hapd, mgmt, len);
+ ret = 1;
break;
case WLAN_FC_STYPE_DEAUTH:
wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
handle_deauth(hapd, mgmt, len);
+ ret = 1;
break;
case WLAN_FC_STYPE_ACTION:
wpa_printf(MSG_DEBUG, "mgmt::action");
- handle_action(hapd, mgmt, len);
+ ret = handle_action(hapd, mgmt, len);
break;
default:
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
@@ -1799,6 +1790,8 @@
"unknown mgmt frame subtype %d", stype);
break;
}
+
+ return ret;
}
@@ -1919,6 +1912,7 @@
if (sta->flags & WLAN_STA_ASSOC)
new_assoc = 0;
sta->flags |= WLAN_STA_ASSOC;
+ sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
sta->auth_alg == WLAN_AUTH_FT) {
/*
@@ -2075,6 +2069,14 @@
const struct ieee80211_mgmt *mgmt;
mgmt = (const struct ieee80211_mgmt *) buf;
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->ext_mgmt_frame_handling) {
+ wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-TX-STATUS stype=%u ok=%d",
+ stype, ok);
+ return;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
switch (stype) {
case WLAN_FC_STYPE_AUTH:
wpa_printf(MSG_DEBUG, "mgmt::auth cb");
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 61f1316..5edeb71 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -15,8 +15,8 @@
struct hostapd_frame_info;
struct ieee80211_ht_capabilities;
-void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
- struct hostapd_frame_info *fi);
+int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
+ struct hostapd_frame_info *fi);
void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
u16 stype, int ok);
void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len);
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 2d53648..31dc47e 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -3,21 +3,14 @@
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007-2008, Intel Corporation
*
- * 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
-#include "drivers/driver.h"
#include "hostapd.h"
#include "ap_config.h"
#include "sta_info.h"
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index 60e6b57..f2ab182 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -12,7 +12,6 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
-#include "drivers/driver.h"
#include "hostapd.h"
#include "ap_config.h"
#include "sta_info.h"
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 4465d12..49b30e4 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -29,6 +29,7 @@
#include "pmksa_cache_auth.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
+#include "wps_hostapd.h"
#include "ieee802_1x.h"
@@ -1951,7 +1952,7 @@
{
int len = 0, ret;
struct eapol_state_machine *sm = sta->eapol_sm;
- struct os_time t;
+ struct os_reltime diff;
if (sm == NULL)
return 0;
@@ -2066,7 +2067,7 @@
len += ret;
/* dot1xAuthSessionStatsTable */
- os_get_time(&t);
+ os_reltime_age(&sta->acct_session_start, &diff);
ret = os_snprintf(buf + len, buflen - len,
/* TODO: dot1xAuthSessionOctetsRx */
/* TODO: dot1xAuthSessionOctetsTx */
@@ -2081,12 +2082,23 @@
(wpa_key_mgmt_wpa_ieee8021x(
wpa_auth_sta_key_mgmt(sta->wpa_sm))) ?
1 : 2,
- (unsigned int) (t.sec - sta->acct_session_start),
+ (unsigned int) diff.sec,
sm->identity);
if (ret < 0 || (size_t) ret >= buflen - len)
return len;
len += ret;
+ ret = os_snprintf(buf + len, buflen - len,
+ "last_eap_type_as=%d (%s)\n"
+ "last_eap_type_sta=%d (%s)\n",
+ sm->eap_type_authsrv,
+ eap_server_get_name(0, sm->eap_type_authsrv),
+ sm->eap_type_supp,
+ eap_server_get_name(0, sm->eap_type_supp));
+ if (ret < 0 || (size_t) ret >= buflen - len)
+ return len;
+ len += ret;
+
return len;
}
@@ -2128,5 +2140,6 @@
os_sleep(0, 10000);
ap_sta_disconnect(hapd, sta, sta->addr,
WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
+ hostapd_wps_eap_completed(hapd);
}
}
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index 40972e9..4720b59 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -91,9 +91,9 @@
static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
{
struct rsn_pmksa_cache *pmksa = eloop_ctx;
- struct os_time now;
+ struct os_reltime now;
- os_get_time(&now);
+ os_get_reltime(&now);
while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
MACSTR, MAC2STR(pmksa->pmksa->spa));
@@ -107,12 +107,12 @@
static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
{
int sec;
- struct os_time now;
+ struct os_reltime now;
eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
if (pmksa->pmksa == NULL)
return;
- os_get_time(&now);
+ os_get_reltime(&now);
sec = pmksa->pmksa->expiration - now.sec;
if (sec < 0)
sec = 0;
@@ -241,7 +241,7 @@
struct eapol_state_machine *eapol, int akmp)
{
struct rsn_pmksa_cache_entry *entry, *pos;
- struct os_time now;
+ struct os_reltime now;
if (pmk_len > PMK_LEN)
return NULL;
@@ -253,7 +253,7 @@
entry->pmk_len = pmk_len;
rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
wpa_key_mgmt_sha256(akmp));
- os_get_time(&now);
+ os_get_reltime(&now);
entry->expiration = now.sec;
if (session_timeout > 0)
entry->expiration += session_timeout;
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index d1d8657..670b834 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -15,7 +15,6 @@
#include "common/sae.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
-#include "drivers/driver.h"
#include "p2p/p2p.h"
#include "hostapd.h"
#include "accounting.h"
@@ -495,7 +494,7 @@
u32 session_timeout)
{
if (eloop_replenish_timeout(session_timeout, 0,
- ap_handle_session_timer, hapd, sta)) {
+ ap_handle_session_timer, hapd, sta) == 1) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "setting session timeout "
"to %d seconds", session_timeout);
@@ -1012,3 +1011,33 @@
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
ap_sta_disassoc_cb_timeout(hapd, sta);
}
+
+
+int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
+{
+ int res;
+
+ buf[0] = '\0';
+ res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ (flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
+ (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
+ (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""),
+ (flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
+ ""),
+ (flags & WLAN_STA_SHORT_PREAMBLE ?
+ "[SHORT_PREAMBLE]" : ""),
+ (flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
+ (flags & WLAN_STA_WMM ? "[WMM]" : ""),
+ (flags & WLAN_STA_MFP ? "[MFP]" : ""),
+ (flags & WLAN_STA_WPS ? "[WPS]" : ""),
+ (flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
+ (flags & WLAN_STA_WDS ? "[WDS]" : ""),
+ (flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
+ (flags & WLAN_STA_WPS2 ? "[WPS2]" : ""),
+ (flags & WLAN_STA_GAS ? "[GAS]" : ""),
+ (flags & WLAN_STA_VHT ? "[VHT]" : ""),
+ (flags & WLAN_STA_WNM_SLEEP_MODE ?
+ "[WNM_SLEEP_MODE]" : ""));
+
+ return res;
+}
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index ea3fe40..9b77e06 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -12,9 +12,6 @@
/* STA flags */
#define WLAN_STA_AUTH BIT(0)
#define WLAN_STA_ASSOC BIT(1)
-#define WLAN_STA_PS BIT(2)
-#define WLAN_STA_TIM BIT(3)
-#define WLAN_STA_PERM BIT(4)
#define WLAN_STA_AUTHORIZED BIT(5)
#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
#define WLAN_STA_SHORT_PREAMBLE BIT(7)
@@ -29,6 +26,7 @@
#define WLAN_STA_WPS2 BIT(16)
#define WLAN_STA_GAS BIT(17)
#define WLAN_STA_VHT BIT(18)
+#define WLAN_STA_WNM_SLEEP_MODE BIT(19)
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
#define WLAN_STA_NONERP BIT(31)
@@ -78,7 +76,7 @@
u32 acct_session_id_hi;
u32 acct_session_id_lo;
- time_t acct_session_start;
+ struct os_reltime acct_session_start;
int acct_session_started;
int acct_terminate_cause; /* Acct-Terminate-Cause */
int acct_interim_interval; /* Acct-Interim-Interval */
@@ -195,4 +193,6 @@
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
+int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen);
+
#endif /* STA_INFO_H */
diff --git a/src/ap/tkip_countermeasures.c b/src/ap/tkip_countermeasures.c
index 4a2ea06..4725e2b 100644
--- a/src/ap/tkip_countermeasures.c
+++ b/src/ap/tkip_countermeasures.c
@@ -68,7 +68,7 @@
int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
{
- struct os_time now;
+ struct os_reltime now;
int ret = 0;
if (addr && local) {
@@ -89,8 +89,8 @@
}
}
- os_get_time(&now);
- if (now.sec > hapd->michael_mic_failure + 60) {
+ os_get_reltime(&now);
+ if (os_reltime_expired(&now, &hapd->michael_mic_failure, 60)) {
hapd->michael_mic_failures = 1;
} else {
hapd->michael_mic_failures++;
@@ -99,7 +99,7 @@
ret = 1;
}
}
- hapd->michael_mic_failure = now.sec;
+ hapd->michael_mic_failure = now;
return ret;
}
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 1afbb8e..509e557 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -4,14 +4,8 @@
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2009, 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "utils/includes.h"
diff --git a/src/ap/vlan_init.h b/src/ap/vlan_init.h
index 382d5de..781eaac 100644
--- a/src/ap/vlan_init.h
+++ b/src/ap/vlan_init.h
@@ -3,14 +3,8 @@
* Copyright 2003, Instant802 Networks, Inc.
* Copyright 2005, Devicescape Software, Inc.
*
- * 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef VLAN_INIT_H
diff --git a/src/ap/wmm.c b/src/ap/wmm.c
index 2851672..6d4177c 100644
--- a/src/ap/wmm.c
+++ b/src/ap/wmm.c
@@ -4,14 +4,8 @@
* Copyright 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2009, 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "utils/includes.h"
diff --git a/src/ap/wmm.h b/src/ap/wmm.h
index 96b04e8..b70b863 100644
--- a/src/ap/wmm.h
+++ b/src/ap/wmm.h
@@ -3,14 +3,8 @@
* Copyright 2002-2003, Instant802 Networks, Inc.
* Copyright 2005-2006, Devicescape Software, Inc.
*
- * 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef WME_H
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index 54a6b85..8e5bdcb 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -1,6 +1,6 @@
/*
* hostapd - WNM
- * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -9,6 +9,7 @@
#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "ap/hostapd.h"
#include "ap/sta_info.h"
@@ -72,7 +73,7 @@
wnmsleep_ie.len = wnmsleep_ie_len - 2;
wnmsleep_ie.action_type = action_type;
wnmsleep_ie.status = WNM_STATUS_SLEEP_ACCEPT;
- wnmsleep_ie.intval = intval;
+ wnmsleep_ie.intval = host_to_le16(intval);
/* TFS IE(s) */
wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN);
@@ -154,6 +155,7 @@
*/
if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT &&
wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) {
+ sta->flags |= WLAN_STA_WNM_SLEEP_MODE;
hostapd_drv_wnm_oper(hapd, WNM_SLEEP_ENTER_CONFIRM,
addr, NULL, NULL);
wpa_set_wnmsleep(sta->wpa_sm, 1);
@@ -167,6 +169,7 @@
wnmsleep_ie.status ==
WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) &&
wnmsleep_ie.action_type == WNM_SLEEP_MODE_EXIT) {
+ sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
wpa_set_wnmsleep(sta->wpa_sm, 0);
hostapd_drv_wnm_oper(hapd, WNM_SLEEP_EXIT_CONFIRM,
addr, NULL, NULL);
@@ -233,7 +236,7 @@
ieee802_11_send_wnmsleep_resp(hapd, addr, dialog_token,
wnmsleep_ie->action_type,
- wnmsleep_ie->intval);
+ le_to_host16(wnmsleep_ie->intval));
if (wnmsleep_ie->action_type == WNM_SLEEP_MODE_EXIT) {
/* clear the tfs after sending the resp frame */
@@ -243,29 +246,263 @@
}
-int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
- struct rx_action *action)
+static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd,
+ const u8 *addr,
+ u8 dialog_token,
+ const char *url)
{
- if (action->len < 1 || action->data == NULL)
+ struct ieee80211_mgmt *mgmt;
+ size_t url_len, len;
+ u8 *pos;
+ int res;
+
+ if (url)
+ url_len = os_strlen(url);
+ else
+ url_len = 0;
+
+ mgmt = os_zalloc(sizeof(*mgmt) + (url_len ? 1 + url_len : 0));
+ if (mgmt == NULL)
+ return -1;
+ os_memcpy(mgmt->da, addr, ETH_ALEN);
+ os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+ mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ mgmt->u.action.category = WLAN_ACTION_WNM;
+ mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
+ mgmt->u.action.u.bss_tm_req.dialog_token = dialog_token;
+ mgmt->u.action.u.bss_tm_req.req_mode = 0;
+ mgmt->u.action.u.bss_tm_req.disassoc_timer = host_to_le16(0);
+ mgmt->u.action.u.bss_tm_req.validity_interval = 1;
+ pos = mgmt->u.action.u.bss_tm_req.variable;
+ if (url) {
+ *pos++ += url_len;
+ os_memcpy(pos, url, url_len);
+ pos += url_len;
+ }
+
+ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
+ MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
+ "validity_interval=%u",
+ MAC2STR(addr), dialog_token,
+ mgmt->u.action.u.bss_tm_req.req_mode,
+ le_to_host16(mgmt->u.action.u.bss_tm_req.disassoc_timer),
+ mgmt->u.action.u.bss_tm_req.validity_interval);
+
+ len = pos - &mgmt->u.action.category;
+ res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0,
+ mgmt->da, &mgmt->u.action.category, len);
+ os_free(mgmt);
+ return res;
+}
+
+
+static void ieee802_11_rx_bss_trans_mgmt_query(struct hostapd_data *hapd,
+ const u8 *addr, const u8 *frm,
+ size_t len)
+{
+ u8 dialog_token, reason;
+ const u8 *pos, *end;
+
+ if (len < 2) {
+ wpa_printf(MSG_DEBUG, "WNM: Ignore too short BSS Transition Management Query from "
+ MACSTR, MAC2STR(addr));
+ return;
+ }
+
+ pos = frm;
+ end = pos + len;
+ dialog_token = *pos++;
+ reason = *pos++;
+
+ wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Query from "
+ MACSTR " dialog_token=%u reason=%u",
+ MAC2STR(addr), dialog_token, reason);
+
+ wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
+ pos, end - pos);
+
+ ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token, NULL);
+}
+
+
+static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd,
+ const u8 *addr, const u8 *frm,
+ size_t len)
+{
+ u8 dialog_token, status_code, bss_termination_delay;
+ const u8 *pos, *end;
+
+ if (len < 3) {
+ wpa_printf(MSG_DEBUG, "WNM: Ignore too short BSS Transition Management Response from "
+ MACSTR, MAC2STR(addr));
+ return;
+ }
+
+ pos = frm;
+ end = pos + len;
+ dialog_token = *pos++;
+ status_code = *pos++;
+ bss_termination_delay = *pos++;
+
+ wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Response from "
+ MACSTR " dialog_token=%u status_code=%u "
+ "bss_termination_delay=%u", MAC2STR(addr), dialog_token,
+ status_code, bss_termination_delay);
+
+ if (status_code == WNM_BSS_TM_ACCEPT) {
+ if (end - pos < ETH_ALEN) {
+ wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field");
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "WNM: Target BSSID: " MACSTR,
+ MAC2STR(pos));
+ pos += ETH_ALEN;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
+ pos, end - pos);
+}
+
+
+int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *mgmt, size_t len)
+{
+ u8 action;
+ const u8 *payload;
+ size_t plen;
+
+ if (len < IEEE80211_HDRLEN + 2)
return -1;
- switch (action->data[0]) {
+ payload = &mgmt->u.action.category;
+ payload++;
+ action = *payload++;
+ plen = (((const u8 *) mgmt) + len) - payload;
+
+ switch (action) {
case WNM_BSS_TRANS_MGMT_QUERY:
- wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management Query");
- /* TODO */
- return -1;
+ ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
+ plen);
+ return 0;
case WNM_BSS_TRANS_MGMT_RESP:
- wpa_printf(MSG_DEBUG, "WNM: BSS Transition Management "
- "Response");
- /* TODO */
- return -1;
+ ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
+ plen);
+ return 0;
case WNM_SLEEP_MODE_REQ:
- ieee802_11_rx_wnmsleep_req(hapd, action->sa, action->data + 1,
- action->len - 1);
+ ieee802_11_rx_wnmsleep_req(hapd, mgmt->sa, payload, plen);
return 0;
}
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
- action->data[0], MAC2STR(action->sa));
+ action, MAC2STR(mgmt->sa));
return -1;
}
+
+
+int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
+ struct sta_info *sta, int disassoc_timer)
+{
+ u8 buf[1000], *pos;
+ struct ieee80211_mgmt *mgmt;
+
+ os_memset(buf, 0, sizeof(buf));
+ mgmt = (struct ieee80211_mgmt *) buf;
+ mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
+ os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+ mgmt->u.action.category = WLAN_ACTION_WNM;
+ mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
+ mgmt->u.action.u.bss_tm_req.dialog_token = 1;
+ mgmt->u.action.u.bss_tm_req.req_mode =
+ WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
+ mgmt->u.action.u.bss_tm_req.disassoc_timer =
+ host_to_le16(disassoc_timer);
+ mgmt->u.action.u.bss_tm_req.validity_interval = 0;
+
+ pos = mgmt->u.action.u.bss_tm_req.variable;
+
+ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
+ MACSTR, disassoc_timer, MAC2STR(sta->addr));
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
+ "Management Request frame");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
+ struct sta_info *sta, const char *url,
+ int disassoc_timer)
+{
+ u8 buf[1000], *pos;
+ struct ieee80211_mgmt *mgmt;
+ size_t url_len;
+
+ os_memset(buf, 0, sizeof(buf));
+ mgmt = (struct ieee80211_mgmt *) buf;
+ mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
+ os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+ mgmt->u.action.category = WLAN_ACTION_WNM;
+ mgmt->u.action.u.bss_tm_req.action = WNM_BSS_TRANS_MGMT_REQ;
+ mgmt->u.action.u.bss_tm_req.dialog_token = 1;
+ mgmt->u.action.u.bss_tm_req.req_mode =
+ WNM_BSS_TM_REQ_DISASSOC_IMMINENT |
+ WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
+ mgmt->u.action.u.bss_tm_req.disassoc_timer =
+ host_to_le16(disassoc_timer);
+ mgmt->u.action.u.bss_tm_req.validity_interval = 0x01;
+
+ pos = mgmt->u.action.u.bss_tm_req.variable;
+
+ /* Session Information URL */
+ url_len = os_strlen(url);
+ if (url_len > 255)
+ return -1;
+ *pos++ = url_len;
+ os_memcpy(pos, url, url_len);
+ pos += url_len;
+
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "Failed to send BSS Transition "
+ "Management Request frame");
+ return -1;
+ }
+
+ /* send disassociation frame after time-out */
+ if (disassoc_timer) {
+ int timeout, beacon_int;
+
+ /*
+ * Prevent STA from reconnecting using cached PMKSA to force
+ * full authentication with the authentication server (which may
+ * decide to reject the connection),
+ */
+ wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
+
+ beacon_int = hapd->iconf->beacon_int;
+ if (beacon_int < 1)
+ beacon_int = 100; /* best guess */
+ /* Calculate timeout in ms based on beacon_int in TU */
+ timeout = disassoc_timer * beacon_int * 128 / 125;
+ wpa_printf(MSG_DEBUG, "Disassociation timer for " MACSTR
+ " set to %d ms", MAC2STR(sta->addr), timeout);
+
+ sta->timeout_next = STA_DISASSOC_FROM_CLI;
+ eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+ eloop_register_timeout(timeout / 1000,
+ timeout % 1000 * 1000,
+ ap_handle_timer, hapd, sta);
+ }
+
+ return 0;
+}
diff --git a/src/ap/wnm_ap.h b/src/ap/wnm_ap.h
index f05726e..eeaf5ec 100644
--- a/src/ap/wnm_ap.h
+++ b/src/ap/wnm_ap.h
@@ -1,6 +1,6 @@
/*
* IEEE 802.11v WNM related functions and structures
- * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -9,9 +9,14 @@
#ifndef WNM_AP_H
#define WNM_AP_H
-struct rx_action;
+struct sta_info;
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
- struct rx_action *action);
+ const struct ieee80211_mgmt *mgmt, size_t len);
+int wnm_send_disassoc_imminent(struct hostapd_data *hapd,
+ struct sta_info *sta, int disassoc_timer);
+int wnm_send_ess_disassoc_imminent(struct hostapd_data *hapd,
+ struct sta_info *sta, const char *url,
+ int disassoc_timer);
#endif /* WNM_AP_H */
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 03b15c2..5993edf 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -437,6 +437,8 @@
wpa_group_sm_step(wpa_auth, group);
group->GInit = FALSE;
wpa_group_sm_step(wpa_auth, group);
+ if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
+ return -1;
return 0;
}
@@ -516,6 +518,9 @@
{
struct wpa_state_machine *sm;
+ if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
+ return NULL;
+
sm = os_zalloc(sizeof(struct wpa_state_machine));
if (sm == NULL)
return NULL;
@@ -2452,7 +2457,7 @@
/* update GTK when exiting WNM-Sleep Mode */
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm)
{
- if (sm->is_wnmsleep)
+ if (sm == NULL || sm->is_wnmsleep)
return;
wpa_group_update_sta(sm, NULL);
@@ -2461,7 +2466,8 @@
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag)
{
- sm->is_wnmsleep = !!flag;
+ if (sm)
+ sm->is_wnmsleep = !!flag;
}
@@ -2587,6 +2593,29 @@
}
+static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx)
+{
+ if (sm->group == ctx) {
+ wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
+ " for discconnection due to fatal failure",
+ MAC2STR(sm->addr));
+ sm->Disconnect = TRUE;
+ }
+
+ return 0;
+}
+
+
+static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth,
+ struct wpa_group *group)
+{
+ wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE");
+ group->changed = TRUE;
+ group->wpa_group_state = WPA_GROUP_FATAL_FAILURE;
+ wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group);
+}
+
+
static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
@@ -2595,8 +2624,10 @@
group->changed = TRUE;
group->wpa_group_state = WPA_GROUP_SETKEYSDONE;
- if (wpa_group_config_group_keys(wpa_auth, group) < 0)
+ if (wpa_group_config_group_keys(wpa_auth, group) < 0) {
+ wpa_group_fatal_failure(wpa_auth, group);
return -1;
+ }
return 0;
}
@@ -2607,6 +2638,8 @@
{
if (group->GInit) {
wpa_group_gtk_init(wpa_auth, group);
+ } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) {
+ /* Do not allow group operations */
} else if (group->wpa_group_state == WPA_GROUP_GTK_INIT &&
group->GTKAuthenticator) {
wpa_group_setkeysdone(wpa_auth, group);
@@ -3015,6 +3048,9 @@
if (sm->group == group)
return 0;
+ if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
+ return -1;
+
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
"machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
@@ -3059,3 +3095,11 @@
return 0;
return wpa_key_mgmt_sae(sm->wpa_key_mgmt);
}
+
+
+int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm)
+{
+ if (sm == NULL)
+ return 0;
+ return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE;
+}
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 47503d0..da45ae4 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -203,7 +203,7 @@
int (*send_ft_action)(void *ctx, const u8 *dst,
const u8 *data, size_t data_len);
int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie,
- size_t tspec_ielen);
+ size_t tspec_ielen);
#endif /* CONFIG_IEEE80211R */
};
@@ -295,5 +295,6 @@
int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
int wpa_auth_uses_sae(struct wpa_state_machine *sm);
+int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm);
#endif /* WPA_AUTH_H */
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 29d9d29..c22c4cc 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -57,7 +57,7 @@
u8 *tspec_ie, size_t tspec_ielen)
{
if (wpa_auth->cb.add_tspec == NULL) {
- wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
+ wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
return -1;
}
return wpa_auth->cb.add_tspec(wpa_auth->cb.ctx, sta_addr, tspec_ie,
@@ -570,8 +570,8 @@
else {
/* TSPEC accepted; include updated TSPEC in
* response */
- rdie->descr_count = 1;
- pos += sizeof(*tspec);
+ rdie->descr_count = 1;
+ pos += sizeof(*tspec);
}
return pos;
}
@@ -633,8 +633,7 @@
conf = &sm->wpa_auth->conf;
- if (sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
- sm->wpa_key_mgmt != WPA_KEY_MGMT_FT_PSK)
+ if (!wpa_key_mgmt_ft(sm->wpa_key_mgmt))
return pos;
end = pos + max_len;
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index cbaab9f..4c1d625 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -15,7 +15,6 @@
#include "eapol_auth/eapol_auth_sm_i.h"
#include "eap_server/eap.h"
#include "l2_packet/l2_packet.h"
-#include "drivers/driver.h"
#include "hostapd.h"
#include "ieee802_1x.h"
#include "preauth_auth.h"
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 12e59bc..9736874 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -139,7 +139,8 @@
enum {
WPA_GROUP_GTK_INIT = 0,
- WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE
+ WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE,
+ WPA_GROUP_FATAL_FAILURE
} wpa_group_state;
u8 GMK[WPA_GMK_LEN];
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 294a39d..4c94210 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -287,6 +287,20 @@
}
+void hostapd_wps_eap_completed(struct hostapd_data *hapd)
+{
+ /*
+ * Reduce race condition of the station trying to reconnect immediately
+ * after AP reconfiguration through WPS by rescheduling the reload
+ * timeout to happen after EAP completion rather than the originally
+ * scheduled 100 ms after new configuration became known.
+ */
+ if (eloop_deplete_timeout(0, 0, wps_reload_config, hapd->iface, NULL) ==
+ 1)
+ wpa_printf(MSG_DEBUG, "WPS: Reschedule immediate configuration reload");
+}
+
+
static void hapd_new_ap_event(struct hostapd_data *hapd, const u8 *attr,
size_t attr_len)
{
@@ -1227,6 +1241,7 @@
{
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
+ eloop_cancel_timeout(wps_reload_config, hapd->iface, NULL);
if (hapd->wps == NULL)
return;
#ifdef CONFIG_WPS_UPNP
diff --git a/src/ap/wps_hostapd.h b/src/ap/wps_hostapd.h
index a2c2cf0..a292598 100644
--- a/src/ap/wps_hostapd.h
+++ b/src/ap/wps_hostapd.h
@@ -16,6 +16,7 @@
int hostapd_init_wps_complete(struct hostapd_data *hapd);
void hostapd_deinit_wps(struct hostapd_data *hapd);
void hostapd_update_wps(struct hostapd_data *hapd);
+void hostapd_wps_eap_completed(struct hostapd_data *hapd);
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
const char *uuid, const char *pin, int timeout);
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
@@ -61,6 +62,10 @@
{
}
+static inline void hostapd_wps_eap_completed(struct hostapd_data *hapd)
+{
+}
+
static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd,
const u8 *addr,
char *buf, size_t buflen)
diff --git a/src/common/defs.h b/src/common/defs.h
index 0c90c24..4811e8e 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -23,11 +23,15 @@
#define WPA_CIPHER_WEP104 BIT(2)
#define WPA_CIPHER_TKIP BIT(3)
#define WPA_CIPHER_CCMP BIT(4)
-#ifdef CONFIG_IEEE80211W
#define WPA_CIPHER_AES_128_CMAC BIT(5)
-#endif /* CONFIG_IEEE80211W */
#define WPA_CIPHER_GCMP BIT(6)
#define WPA_CIPHER_SMS4 BIT(7)
+#define WPA_CIPHER_GCMP_256 BIT(8)
+#define WPA_CIPHER_CCMP_256 BIT(9)
+#define WPA_CIPHER_BIP_GMAC_128 BIT(11)
+#define WPA_CIPHER_BIP_GMAC_256 BIT(12)
+#define WPA_CIPHER_BIP_CMAC_256 BIT(13)
+#define WPA_CIPHER_GTK_NOT_USED BIT(14)
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
#define WPA_KEY_MGMT_PSK BIT(1)
@@ -58,7 +62,8 @@
return !!(akm & (WPA_KEY_MGMT_PSK |
WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_PSK_SHA256 |
- WPA_KEY_MGMT_SAE));
+ WPA_KEY_MGMT_SAE |
+ WPA_KEY_MGMT_FT_SAE));
}
static inline int wpa_key_mgmt_ft(int akm)
@@ -83,7 +88,8 @@
static inline int wpa_key_mgmt_wpa(int akm)
{
return wpa_key_mgmt_wpa_ieee8021x(akm) ||
- wpa_key_mgmt_wpa_psk(akm);
+ wpa_key_mgmt_wpa_psk(akm) ||
+ wpa_key_mgmt_sae(akm);
}
static inline int wpa_key_mgmt_wpa_any(int akm)
@@ -117,41 +123,12 @@
WPA_ALG_PMK,
WPA_ALG_GCMP,
WPA_ALG_SMS4,
- WPA_ALG_KRK
-};
-
-/**
- * enum wpa_cipher - Cipher suites
- */
-enum wpa_cipher {
- CIPHER_NONE,
- CIPHER_WEP40,
- CIPHER_TKIP,
- CIPHER_CCMP,
- CIPHER_WEP104,
- CIPHER_GCMP,
- CIPHER_SMS4
-};
-
-/**
- * enum wpa_key_mgmt - Key management suites
- */
-enum wpa_key_mgmt {
- KEY_MGMT_802_1X,
- KEY_MGMT_PSK,
- KEY_MGMT_NONE,
- KEY_MGMT_802_1X_NO_WPA,
- KEY_MGMT_WPA_NONE,
- KEY_MGMT_FT_802_1X,
- KEY_MGMT_FT_PSK,
- KEY_MGMT_802_1X_SHA256,
- KEY_MGMT_PSK_SHA256,
- KEY_MGMT_WPS,
- KEY_MGMT_SAE,
- KEY_MGMT_FT_SAE,
- KEY_MGMT_WAPI_PSK,
- KEY_MGMT_WAPI_CERT,
- KEY_MGMT_CCKM
+ WPA_ALG_KRK,
+ WPA_ALG_GCMP_256,
+ WPA_ALG_CCMP_256,
+ WPA_ALG_BIP_GMAC_128,
+ WPA_ALG_BIP_GMAC_256,
+ WPA_ALG_BIP_CMAC_256
};
/**
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 304dfc6..809089f 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -189,25 +189,12 @@
elems->supp_rates = pos;
elems->supp_rates_len = elen;
break;
- case WLAN_EID_FH_PARAMS:
- elems->fh_params = pos;
- elems->fh_params_len = elen;
- break;
case WLAN_EID_DS_PARAMS:
elems->ds_params = pos;
elems->ds_params_len = elen;
break;
case WLAN_EID_CF_PARAMS:
- elems->cf_params = pos;
- elems->cf_params_len = elen;
- break;
case WLAN_EID_TIM:
- elems->tim = pos;
- elems->tim_len = elen;
- break;
- case WLAN_EID_IBSS_PARAMS:
- elems->ibss_params = pos;
- elems->ibss_params_len = elen;
break;
case WLAN_EID_CHALLENGE:
elems->challenge = pos;
@@ -232,8 +219,6 @@
elems->rsn_ie_len = elen;
break;
case WLAN_EID_PWR_CAPABILITY:
- elems->power_cap = pos;
- elems->power_cap_len = elen;
break;
case WLAN_EID_SUPPORTED_CHANNELS:
elems->supp_channels = pos;
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index c4618b2..b84dd9e 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -13,11 +13,7 @@
struct ieee802_11_elems {
const u8 *ssid;
const u8 *supp_rates;
- const u8 *fh_params;
const u8 *ds_params;
- const u8 *cf_params;
- const u8 *tim;
- const u8 *ibss_params;
const u8 *challenge;
const u8 *erp_info;
const u8 *ext_supp_rates;
@@ -26,7 +22,6 @@
const u8 *wmm; /* WMM Information or Parameter Element */
const u8 *wmm_tspec;
const u8 *wps_ie;
- const u8 *power_cap;
const u8 *supp_channels;
const u8 *mdie;
const u8 *ftie;
@@ -48,11 +43,7 @@
u8 ssid_len;
u8 supp_rates_len;
- u8 fh_params_len;
u8 ds_params_len;
- u8 cf_params_len;
- u8 tim_len;
- u8 ibss_params_len;
u8 challenge_len;
u8 erp_info_len;
u8 ext_supp_rates_len;
@@ -61,7 +52,6 @@
u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */
u8 wmm_tspec_len;
u8 wps_ie_len;
- u8 power_cap_len;
u8 supp_channels_len;
u8 mdie_len;
u8 ftie_len;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 9b2d54f..7d78648 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -161,6 +161,7 @@
#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
+#define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
#define WLAN_REASON_UNSPECIFIED 1
@@ -1024,6 +1025,11 @@
#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06
#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07
#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
+#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
+#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0A
+#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B
+#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C
+#define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D
#define WLAN_CIPHER_SUITE_SMS4 0x00147201
diff --git a/src/common/sae.c b/src/common/sae.c
index 4e9e461..08bf054 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -701,6 +701,11 @@
return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
}
+ if (sae->tmp == NULL) {
+ wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized");
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
if (sae->tmp->dh && !allowed_groups) {
wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
"explicit configuration enabling it", group);
@@ -797,7 +802,7 @@
/* element x and y coordinates < p */
if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 ||
- os_memcmp(pos + sae->tmp->prime_len + sae->tmp->prime_len, prime,
+ os_memcmp(pos + sae->tmp->prime_len, prime,
sae->tmp->prime_len) >= 0) {
wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
"element");
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index c3afbfd..37b265d 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -353,6 +353,16 @@
#endif /* CONFIG_IEEE80211W */
if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP)
return WPA_CIPHER_GCMP;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256)
+ return WPA_CIPHER_CCMP_256;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256)
+ return WPA_CIPHER_GCMP_256;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128)
+ return WPA_CIPHER_BIP_GMAC_128;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256)
+ return WPA_CIPHER_BIP_GMAC_256;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
+ return WPA_CIPHER_BIP_CMAC_256;
return 0;
}
@@ -912,6 +922,12 @@
return "CCMP+TKIP";
case WPA_CIPHER_GCMP:
return "GCMP";
+ case WPA_CIPHER_GCMP_256:
+ return "GCMP-256";
+ case WPA_CIPHER_CCMP_256:
+ return "CCMP-256";
+ case WPA_CIPHER_GTK_NOT_USED:
+ return "GTK_NOT_USED";
default:
return "UNKNOWN";
}
@@ -1078,6 +1094,9 @@
int wpa_cipher_key_len(int cipher)
{
switch (cipher) {
+ case WPA_CIPHER_CCMP_256:
+ case WPA_CIPHER_GCMP_256:
+ return 32;
case WPA_CIPHER_CCMP:
case WPA_CIPHER_GCMP:
return 16;
@@ -1096,6 +1115,8 @@
int wpa_cipher_rsc_len(int cipher)
{
switch (cipher) {
+ case WPA_CIPHER_CCMP_256:
+ case WPA_CIPHER_GCMP_256:
case WPA_CIPHER_CCMP:
case WPA_CIPHER_GCMP:
case WPA_CIPHER_TKIP:
@@ -1112,6 +1133,10 @@
int wpa_cipher_to_alg(int cipher)
{
switch (cipher) {
+ case WPA_CIPHER_CCMP_256:
+ return WPA_ALG_CCMP_256;
+ case WPA_CIPHER_GCMP_256:
+ return WPA_ALG_GCMP_256;
case WPA_CIPHER_CCMP:
return WPA_ALG_CCMP;
case WPA_CIPHER_GCMP:
@@ -1126,29 +1151,11 @@
}
-enum wpa_cipher wpa_cipher_to_suite_driver(int cipher)
-{
- switch (cipher) {
- case WPA_CIPHER_NONE:
- return CIPHER_NONE;
- case WPA_CIPHER_WEP40:
- return CIPHER_WEP40;
- case WPA_CIPHER_WEP104:
- return CIPHER_WEP104;
- case WPA_CIPHER_CCMP:
- return CIPHER_CCMP;
- case WPA_CIPHER_GCMP:
- return CIPHER_GCMP;
- case WPA_CIPHER_TKIP:
- default:
- return CIPHER_TKIP;
- }
-}
-
-
int wpa_cipher_valid_pairwise(int cipher)
{
- return cipher == WPA_CIPHER_CCMP ||
+ return cipher == WPA_CIPHER_CCMP_256 ||
+ cipher == WPA_CIPHER_GCMP_256 ||
+ cipher == WPA_CIPHER_CCMP ||
cipher == WPA_CIPHER_GCMP ||
cipher == WPA_CIPHER_TKIP;
}
@@ -1156,6 +1163,10 @@
u32 wpa_cipher_to_suite(int proto, int cipher)
{
+ if (cipher & WPA_CIPHER_CCMP_256)
+ return RSN_CIPHER_SUITE_CCMP_256;
+ if (cipher & WPA_CIPHER_GCMP_256)
+ return RSN_CIPHER_SUITE_GCMP_256;
if (cipher & WPA_CIPHER_CCMP)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP);
@@ -1173,6 +1184,8 @@
if (cipher & WPA_CIPHER_NONE)
return (proto == WPA_PROTO_RSN ?
RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
+ if (cipher & WPA_CIPHER_GTK_NOT_USED)
+ return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
return 0;
}
@@ -1181,6 +1194,16 @@
{
int num_suites = 0;
+ if (ciphers & WPA_CIPHER_CCMP_256) {
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256);
+ pos += RSN_SELECTOR_LEN;
+ num_suites++;
+ }
+ if (ciphers & WPA_CIPHER_GCMP_256) {
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256);
+ pos += RSN_SELECTOR_LEN;
+ num_suites++;
+ }
if (ciphers & WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
pos += RSN_SELECTOR_LEN;
@@ -1232,6 +1255,10 @@
int wpa_pick_pairwise_cipher(int ciphers, int none_allowed)
{
+ if (ciphers & WPA_CIPHER_CCMP_256)
+ return WPA_CIPHER_CCMP_256;
+ if (ciphers & WPA_CIPHER_GCMP_256)
+ return WPA_CIPHER_GCMP_256;
if (ciphers & WPA_CIPHER_CCMP)
return WPA_CIPHER_CCMP;
if (ciphers & WPA_CIPHER_GCMP)
@@ -1246,10 +1273,16 @@
int wpa_pick_group_cipher(int ciphers)
{
+ if (ciphers & WPA_CIPHER_CCMP_256)
+ return WPA_CIPHER_CCMP_256;
+ if (ciphers & WPA_CIPHER_GCMP_256)
+ return WPA_CIPHER_GCMP_256;
if (ciphers & WPA_CIPHER_CCMP)
return WPA_CIPHER_CCMP;
if (ciphers & WPA_CIPHER_GCMP)
return WPA_CIPHER_GCMP;
+ if (ciphers & WPA_CIPHER_GTK_NOT_USED)
+ return WPA_CIPHER_GTK_NOT_USED;
if (ciphers & WPA_CIPHER_TKIP)
return WPA_CIPHER_TKIP;
if (ciphers & WPA_CIPHER_WEP104)
@@ -1280,7 +1313,11 @@
end++;
last = *end == '\0';
*end = '\0';
- if (os_strcmp(start, "CCMP") == 0)
+ if (os_strcmp(start, "CCMP-256") == 0)
+ val |= WPA_CIPHER_CCMP_256;
+ else if (os_strcmp(start, "GCMP-256") == 0)
+ val |= WPA_CIPHER_GCMP_256;
+ else if (os_strcmp(start, "CCMP") == 0)
val |= WPA_CIPHER_CCMP;
else if (os_strcmp(start, "GCMP") == 0)
val |= WPA_CIPHER_GCMP;
@@ -1292,6 +1329,8 @@
val |= WPA_CIPHER_WEP40;
else if (os_strcmp(start, "NONE") == 0)
val |= WPA_CIPHER_NONE;
+ else if (os_strcmp(start, "GTK_NOT_USED") == 0)
+ val |= WPA_CIPHER_GTK_NOT_USED;
else {
os_free(buf);
return -1;
@@ -1312,6 +1351,20 @@
char *pos = start;
int ret;
+ if (ciphers & WPA_CIPHER_CCMP_256) {
+ ret = os_snprintf(pos, end - pos, "%sCCMP-256",
+ pos == start ? "" : delim);
+ if (ret < 0 || ret >= end - pos)
+ return -1;
+ pos += ret;
+ }
+ if (ciphers & WPA_CIPHER_GCMP_256) {
+ ret = os_snprintf(pos, end - pos, "%sGCMP-256",
+ pos == start ? "" : delim);
+ if (ret < 0 || ret >= end - pos)
+ return -1;
+ pos += ret;
+ }
if (ciphers & WPA_CIPHER_CCMP) {
ret = os_snprintf(pos, end - pos, "%sCCMP",
pos == start ? "" : delim);
@@ -1373,5 +1426,11 @@
return WPA_CIPHER_TKIP;
if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP)
return WPA_CIPHER_GCMP;
+ if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP |
+ WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256)
+ return WPA_CIPHER_GCMP_256;
+ if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP |
+ WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256)
+ return WPA_CIPHER_CCMP_256;
return WPA_CIPHER_CCMP;
}
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 2d63662..62505f1 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -21,10 +21,12 @@
#define WPA_GTK_MAX_LEN 32
#define WPA_ALLOWED_PAIRWISE_CIPHERS \
-(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)
+(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE | \
+WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256)
#define WPA_ALLOWED_GROUP_CIPHERS \
(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 | \
-WPA_CIPHER_WEP40)
+WPA_CIPHER_WEP40 | WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \
+WPA_CIPHER_GTK_NOT_USED)
#define WPA_SELECTOR_LEN 4
#define WPA_VERSION 1
@@ -60,6 +62,10 @@
#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
#define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
+#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
+#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_384 RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
+#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_384 \
+RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
#define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00)
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
@@ -75,6 +81,11 @@
#endif /* CONFIG_IEEE80211W */
#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
#define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
+#define RSN_CIPHER_SUITE_GCMP_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
+#define RSN_CIPHER_SUITE_CCMP_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 10)
+#define RSN_CIPHER_SUITE_BIP_GMAC_128 RSN_SELECTOR(0x00, 0x0f, 0xac, 11)
+#define RSN_CIPHER_SUITE_BIP_GMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 12)
+#define RSN_CIPHER_SUITE_BIP_CMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
/* EAPOL-Key Key Data Encapsulation
* GroupKey and PeerKey require encryption, otherwise, encryption is optional.
@@ -392,7 +403,6 @@
int wpa_cipher_key_len(int cipher);
int wpa_cipher_rsc_len(int cipher);
int wpa_cipher_to_alg(int cipher);
-enum wpa_cipher wpa_cipher_to_suite_driver(int cipher);
int wpa_cipher_valid_pairwise(int cipher);
u32 wpa_cipher_to_suite(int proto, int cipher);
int rsn_cipher_put_suites(u8 *pos, int ciphers);
diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
index 83788d7..f4af94a 100644
--- a/src/common/wpa_ctrl.c
+++ b/src/common/wpa_ctrl.c
@@ -391,7 +391,7 @@
void (*msg_cb)(char *msg, size_t len))
{
struct timeval tv;
- struct os_time started_at;
+ struct os_reltime started_at;
int res;
fd_set rfds;
const char *_cmd;
@@ -430,12 +430,12 @@
* longer before giving up.
*/
if (started_at.sec == 0)
- os_get_time(&started_at);
+ os_get_reltime(&started_at);
else {
- struct os_time n;
- os_get_time(&n);
+ struct os_reltime n;
+ os_get_reltime(&n);
/* Try for a few seconds. */
- if (n.sec > started_at.sec + 5)
+ if (os_reltime_expired(&n, &started_at, 5))
goto send_err;
}
os_sleep(1, 0);
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 88bfb4d..9bd59a9 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -54,6 +54,8 @@
#define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED "
/** Temporarily disabled network block re-enabled */
#define WPA_EVENT_REENABLED "CTRL-EVENT-SSID-REENABLED "
+/** New scan started */
+#define WPA_EVENT_SCAN_STARTED "CTRL-EVENT-SCAN-STARTED "
/** New scan results available */
#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
/** wpa_supplicant state change */
@@ -145,6 +147,7 @@
#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT "
#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED "
#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id="
+#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE "
/* parameters: <PMF enabled> <timeout in ms> <Session Information URL> */
#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
@@ -154,6 +157,13 @@
#define INTERWORKING_ALREADY_CONNECTED "INTERWORKING-ALREADY-CONNECTED "
#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO "
+/* parameters: <addr> <dialog_token> <freq> */
+#define GAS_QUERY_START "GAS-QUERY-START "
+/* parameters: <addr> <dialog_token> <freq> <status_code> <result> */
+#define GAS_QUERY_DONE "GAS-QUERY-DONE "
+
+#define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START "
+#define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT "
/* hostapd control interface - fixed message prefixes */
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 5215c00..1da2b9f 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -26,6 +26,8 @@
#include "common.h"
#include "wpabuf.h"
#include "dh_group5.h"
+#include "sha1.h"
+#include "sha256.h"
#include "crypto.h"
#if OPENSSL_VERSION_NUMBER < 0x00907000
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index feba13f..287fd33 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -41,7 +41,8 @@
TLS_FAIL_ALTSUBJECT_MISMATCH = 6,
TLS_FAIL_BAD_CERTIFICATE = 7,
TLS_FAIL_SERVER_CHAIN_PROBE = 8,
- TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9
+ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9,
+ TLS_FAIL_SERVER_USED_CLIENT_CERT = 10
};
union tls_event_data {
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index a5d72f4..cb23eb9 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -125,8 +125,6 @@
}
-extern int wpa_debug_show_keys;
-
void * tls_init(const struct tls_config *conf)
{
struct tls_global *global;
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index eeaf859..4cfa5f4 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -105,6 +105,7 @@
unsigned int ca_cert_verify:1;
unsigned int cert_probe:1;
unsigned int server_cert_only:1;
+ unsigned int server:1;
u8 srv_cert_hash[32];
@@ -112,6 +113,7 @@
X509 *peer_cert;
X509 *peer_issuer;
+ X509 *peer_issuer_issuer;
};
@@ -1385,6 +1387,8 @@
conn->peer_cert = err_cert;
else if (depth == 1)
conn->peer_issuer = err_cert;
+ else if (depth == 2)
+ conn->peer_issuer_issuer = err_cert;
context = conn->context;
match = conn->subject_match;
@@ -1478,6 +1482,16 @@
TLS_FAIL_SERVER_CHAIN_PROBE);
}
+ if (!conn->server && err_cert && preverify_ok && depth == 0 &&
+ (err_cert->ex_flags & EXFLAG_XKUSAGE) &&
+ (err_cert->ex_xkusage & XKU_SSL_CLIENT)) {
+ wpa_printf(MSG_WARNING, "TLS: Server used client certificate");
+ openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+ "Server used client certificate",
+ TLS_FAIL_SERVER_USED_CLIENT_CERT);
+ preverify_ok = 0;
+ }
+
if (preverify_ok && context->event_cb != NULL)
context->event_cb(context->cb_ctx,
TLS_CERT_CHAIN_SUCCESS, NULL);
@@ -2529,6 +2543,8 @@
int res;
struct wpabuf *out_data;
+ conn->server = !!server;
+
/*
* Give TLS handshake data from the server (if available) to OpenSSL
* for processing.
@@ -2890,7 +2906,6 @@
static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
{
#ifndef CONFIG_NO_STDOUT_DEBUG
- extern int wpa_debug_level;
BIO *out;
size_t rlen;
char *txt;
@@ -2931,6 +2946,8 @@
OCSP_BASICRESP *basic;
OCSP_CERTID *id;
ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
+ X509_STORE *store;
+ STACK_OF(X509) *certs = NULL;
len = SSL_get_tlsext_status_ocsp_resp(s, &p);
if (!p) {
@@ -2961,8 +2978,41 @@
return 0;
}
- status = OCSP_basic_verify(basic, NULL, SSL_CTX_get_cert_store(s->ctx),
- 0);
+ store = SSL_CTX_get_cert_store(s->ctx);
+ if (conn->peer_issuer) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: Add issuer");
+ X509_print_fp(stdout, conn->peer_issuer);
+
+ if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
+ tls_show_errors(MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer to certificate store\n");
+ }
+ certs = sk_X509_new_null();
+ if (certs) {
+ X509 *cert;
+ cert = X509_dup(conn->peer_issuer);
+ if (cert && !sk_X509_push(certs, cert)) {
+ tls_show_errors(
+ MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer to OCSP responder trust store\n");
+ X509_free(cert);
+ sk_X509_free(certs);
+ certs = NULL;
+ }
+ if (conn->peer_issuer_issuer) {
+ cert = X509_dup(conn->peer_issuer_issuer);
+ if (cert && !sk_X509_push(certs, cert)) {
+ tls_show_errors(
+ MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer to OCSP responder trust store\n");
+ X509_free(cert);
+ }
+ }
+ }
+ }
+
+ status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
+ sk_X509_pop_free(certs, X509_free);
if (status <= 0) {
tls_show_errors(MSG_INFO, __func__,
"OpenSSL: OCSP response failed verification");
diff --git a/src/drivers/android_drv.h b/src/drivers/android_drv.h
index 5906527..31d9440 100644
--- a/src/drivers/android_drv.h
+++ b/src/drivers/android_drv.h
@@ -1,12 +1,8 @@
/*
* 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.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#ifndef ANDROID_DRV_H
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index a3602ed..db34ed1 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1,6 +1,6 @@
/*
* Driver interface definition
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -233,7 +233,7 @@
struct wpa_scan_results {
struct wpa_scan_res **res;
size_t num;
- struct os_time fetch_time;
+ struct os_reltime fetch_time;
};
/**
@@ -340,6 +340,21 @@
* and not to transmit the frames at any of those rates.
*/
u8 p2p_probe;
+
+ /**
+ * only_new_results - Request driver to report only new results
+ *
+ * This is used to request the driver to report only BSSes that have
+ * been detected after this scan request has been started, i.e., to
+ * flush old cached BSS entries.
+ */
+ int only_new_results;
+
+ /*
+ * NOTE: Whenever adding new parameters here, please make sure
+ * wpa_scan_clone_params() and wpa_scan_free_params() get updated with
+ * matching changes.
+ */
};
/**
@@ -442,25 +457,25 @@
unsigned int wpa_proto;
/**
- * pairwise_suite - Selected pairwise cipher suite
+ * pairwise_suite - Selected pairwise cipher suite (WPA_CIPHER_*)
*
* This is usually ignored if @wpa_ie is used.
*/
- enum wpa_cipher pairwise_suite;
+ unsigned int pairwise_suite;
/**
- * group_suite - Selected group cipher suite
+ * group_suite - Selected group cipher suite (WPA_CIPHER_*)
*
* This is usually ignored if @wpa_ie is used.
*/
- enum wpa_cipher group_suite;
+ unsigned int group_suite;
/**
- * key_mgmt_suite - Selected key management suite
+ * key_mgmt_suite - Selected key management suite (WPA_KEY_MGMT_*)
*
* This is usually ignored if @wpa_ie is used.
*/
- enum wpa_key_mgmt key_mgmt_suite;
+ unsigned int key_mgmt_suite;
/**
* auth_alg - Allowed authentication algorithms
@@ -833,6 +848,12 @@
#define WPA_DRIVER_CAPA_ENC_CCMP 0x00000008
#define WPA_DRIVER_CAPA_ENC_WEP128 0x00000010
#define WPA_DRIVER_CAPA_ENC_GCMP 0x00000020
+#define WPA_DRIVER_CAPA_ENC_GCMP_256 0x00000040
+#define WPA_DRIVER_CAPA_ENC_CCMP_256 0x00000080
+#define WPA_DRIVER_CAPA_ENC_BIP 0x00000100
+#define WPA_DRIVER_CAPA_ENC_BIP_GMAC_128 0x00000200
+#define WPA_DRIVER_CAPA_ENC_BIP_GMAC_256 0x00000400
+#define WPA_DRIVER_CAPA_ENC_BIP_CMAC_256 0x00000800
unsigned int enc;
#define WPA_DRIVER_AUTH_OPEN 0x00000001
@@ -856,8 +877,7 @@
#define WPA_DRIVER_FLAGS_AP 0x00000040
/* Driver needs static WEP key setup after association has been completed */
#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE 0x00000080
-/* Driver takes care of P2P management operations */
-#define WPA_DRIVER_FLAGS_P2P_MGMT 0x00000100
+/* unused: 0x00000100 */
/* Driver supports concurrent P2P operations */
#define WPA_DRIVER_FLAGS_P2P_CONCURRENT 0x00000200
/*
@@ -910,6 +930,10 @@
#define WPA_DRIVER_FLAGS_RADAR 0x10000000
/* Driver supports a dedicated interface for P2P Device */
#define WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE 0x20000000
+/* Driver supports QoS Mapping */
+#define WPA_DRIVER_FLAGS_QOS_MAPPING 0x40000000
+/* Driver supports CSA in AP mode */
+#define WPA_DRIVER_FLAGS_AP_CSA 0x80000000
unsigned int flags;
int max_scan_ssids;
@@ -1099,17 +1123,6 @@
#define WPA_STA_MFP BIT(3)
#define WPA_STA_TDLS_PEER BIT(4)
-/**
- * struct p2p_params - P2P parameters for driver-based P2P management
- */
-struct p2p_params {
- const char *dev_name;
- u8 pri_dev_type[8];
-#define DRV_MAX_SEC_DEV_TYPES 5
- u8 sec_dev_type[DRV_MAX_SEC_DEV_TYPES][8];
- size_t num_sec_dev_types;
-};
-
enum tdls_oper {
TDLS_DISCOVERY_REQ,
TDLS_SETUP,
@@ -1265,7 +1278,9 @@
* @priv: private driver interface data
* @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
* %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK,
- * %WPA_ALG_GCMP);
+ * %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, %WPA_ALG_CCMP_256,
+ * %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256,
+ * %WPA_ALG_BIP_CMAC_256);
* %WPA_ALG_NONE clears the key.
* @addr: Address of the peer STA (BSSID of the current AP when setting
* pairwise key in station mode), ff:ff:ff:ff:ff:ff for
@@ -2206,7 +2221,7 @@
*
* This command is used to request the driver to remain awake on the
* specified channel for the specified duration and report received
- * Action frames with EVENT_RX_ACTION events. Optionally, received
+ * Action frames with EVENT_RX_MGMT events. Optionally, received
* Probe Request frames may also be requested to be reported by calling
* probe_req_report(). These will be reported with EVENT_RX_PROBE_REQ.
*
@@ -2388,222 +2403,6 @@
const char * (*get_radio_name)(void *priv);
/**
- * p2p_find - Start P2P Device Discovery
- * @priv: Private driver interface data
- * @timeout: Timeout for find operation in seconds or 0 for no timeout
- * @type: Device Discovery type (enum p2p_discovery_type)
- * Returns: 0 on success, -1 on failure
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_find)(void *priv, unsigned int timeout, int type);
-
- /**
- * p2p_stop_find - Stop P2P Device Discovery
- * @priv: Private driver interface data
- * Returns: 0 on success, -1 on failure
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_stop_find)(void *priv);
-
- /**
- * p2p_listen - Start P2P Listen state for specified duration
- * @priv: Private driver interface data
- * @timeout: Listen state duration in milliseconds
- * Returns: 0 on success, -1 on failure
- *
- * This function can be used to request the P2P module to keep the
- * device discoverable on the listen channel for an extended set of
- * time. At least in its current form, this is mainly used for testing
- * purposes and may not be of much use for normal P2P operations.
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_listen)(void *priv, unsigned int timeout);
-
- /**
- * p2p_connect - Start P2P group formation (GO negotiation)
- * @priv: Private driver interface data
- * @peer_addr: MAC address of the peer P2P client
- * @wps_method: enum p2p_wps_method value indicating config method
- * @go_intent: Local GO intent value (1..15)
- * @own_interface_addr: Intended interface address to use with the
- * group
- * @force_freq: The only allowed channel frequency in MHz or 0
- * @persistent_group: Whether to create persistent group
- * Returns: 0 on success, -1 on failure
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_connect)(void *priv, const u8 *peer_addr, int wps_method,
- int go_intent, const u8 *own_interface_addr,
- unsigned int force_freq, int persistent_group);
-
- /**
- * wps_success_cb - Report successfully completed WPS provisioning
- * @priv: Private driver interface data
- * @peer_addr: Peer address
- * Returns: 0 on success, -1 on failure
- *
- * This function is used to report successfully completed WPS
- * provisioning during group formation in both GO/Registrar and
- * client/Enrollee roles.
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*wps_success_cb)(void *priv, const u8 *peer_addr);
-
- /**
- * p2p_group_formation_failed - Report failed WPS provisioning
- * @priv: Private driver interface data
- * Returns: 0 on success, -1 on failure
- *
- * This function is used to report failed group formation. This can
- * happen either due to failed WPS provisioning or due to 15 second
- * timeout during the provisioning phase.
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_group_formation_failed)(void *priv);
-
- /**
- * p2p_set_params - Set P2P parameters
- * @priv: Private driver interface data
- * @params: P2P parameters
- * Returns: 0 on success, -1 on failure
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_set_params)(void *priv, const struct p2p_params *params);
-
- /**
- * p2p_prov_disc_req - Send Provision Discovery Request
- * @priv: Private driver interface data
- * @peer_addr: MAC address of the peer P2P client
- * @config_methods: WPS Config Methods value (only one bit set)
- * Returns: 0 on success, -1 on failure
- *
- * This function can be used to request a discovered P2P peer to
- * display a PIN (config_methods = WPS_CONFIG_DISPLAY) or be prepared
- * to enter a PIN from us (config_methods = WPS_CONFIG_KEYPAD). The
- * Provision Discovery Request frame is transmitted once immediately
- * and if no response is received, the frame will be sent again
- * whenever the target device is discovered during device dsicovery
- * (start with a p2p_find() call). Response from the peer is indicated
- * with the EVENT_P2P_PROV_DISC_RESPONSE event.
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_prov_disc_req)(void *priv, const u8 *peer_addr,
- u16 config_methods, int join);
-
- /**
- * p2p_sd_request - Schedule a service discovery query
- * @priv: Private driver interface data
- * @dst: Destination peer or %NULL to apply for all peers
- * @tlvs: P2P Service Query TLV(s)
- * Returns: Reference to the query or 0 on failure
- *
- * Response to the query is indicated with the
- * EVENT_P2P_SD_RESPONSE driver event.
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- u64 (*p2p_sd_request)(void *priv, const u8 *dst,
- const struct wpabuf *tlvs);
-
- /**
- * p2p_sd_cancel_request - Cancel a pending service discovery query
- * @priv: Private driver interface data
- * @req: Query reference from p2p_sd_request()
- * Returns: 0 on success, -1 on failure
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_sd_cancel_request)(void *priv, u64 req);
-
- /**
- * p2p_sd_response - Send response to a service discovery query
- * @priv: Private driver interface data
- * @freq: Frequency from EVENT_P2P_SD_REQUEST event
- * @dst: Destination address from EVENT_P2P_SD_REQUEST event
- * @dialog_token: Dialog token from EVENT_P2P_SD_REQUEST event
- * @resp_tlvs: P2P Service Response TLV(s)
- * Returns: 0 on success, -1 on failure
- *
- * This function is called as a response to the request indicated with
- * the EVENT_P2P_SD_REQUEST driver event.
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_sd_response)(void *priv, int freq, const u8 *dst,
- u8 dialog_token,
- const struct wpabuf *resp_tlvs);
-
- /**
- * p2p_service_update - Indicate a change in local services
- * @priv: Private driver interface data
- * Returns: 0 on success, -1 on failure
- *
- * This function needs to be called whenever there is a change in
- * availability of the local services. This will increment the
- * Service Update Indicator value which will be used in SD Request and
- * Response frames.
- *
- * This function is only used if the driver implements P2P management,
- * i.e., if it sets WPA_DRIVER_FLAGS_P2P_MGMT in
- * struct wpa_driver_capa.
- */
- int (*p2p_service_update)(void *priv);
-
- /**
- * p2p_reject - Reject peer device (explicitly block connections)
- * @priv: Private driver interface data
- * @addr: MAC address of the peer
- * Returns: 0 on success, -1 on failure
- */
- int (*p2p_reject)(void *priv, const u8 *addr);
-
- /**
- * p2p_invite - Invite a P2P Device into a group
- * @priv: Private driver interface data
- * @peer: Device Address of the peer P2P Device
- * @role: Local role in the group
- * @bssid: Group BSSID or %NULL if not known
- * @ssid: Group SSID
- * @ssid_len: Length of ssid in octets
- * @go_dev_addr: Forced GO Device Address or %NULL if none
- * @persistent_group: Whether this is to reinvoke a persistent group
- * Returns: 0 on success, -1 on failure
- */
- int (*p2p_invite)(void *priv, const u8 *peer, int role,
- const u8 *bssid, const u8 *ssid, size_t ssid_len,
- const u8 *go_dev_addr, int persistent_group);
-
- /**
* send_tdls_mgmt - for sending TDLS management packets
* @priv: private driver interface data
* @dst: Destination (peer) MAC address
@@ -3092,15 +2891,6 @@
EVENT_RX_MGMT,
/**
- * EVENT_RX_ACTION - Action frame received
- *
- * This event is used to indicate when an Action frame has been
- * received. Information about the received frame is included in
- * union wpa_event_data::rx_action.
- */
- EVENT_RX_ACTION,
-
- /**
* EVENT_REMAIN_ON_CHANNEL - Remain-on-channel duration started
*
* This event is used to indicate when the driver has started the
@@ -3247,38 +3037,6 @@
EVENT_STATION_LOW_ACK,
/**
- * EVENT_P2P_DEV_FOUND - Report a discovered P2P device
- *
- * This event is used only if the driver implements P2P management
- * internally. Event data is stored in
- * union wpa_event_data::p2p_dev_found.
- */
- EVENT_P2P_DEV_FOUND,
-
- /**
- * EVENT_P2P_GO_NEG_REQ_RX - Report reception of GO Negotiation Request
- *
- * This event is used only if the driver implements P2P management
- * internally. Event data is stored in
- * union wpa_event_data::p2p_go_neg_req_rx.
- */
- EVENT_P2P_GO_NEG_REQ_RX,
-
- /**
- * EVENT_P2P_GO_NEG_COMPLETED - Report completion of GO Negotiation
- *
- * This event is used only if the driver implements P2P management
- * internally. Event data is stored in
- * union wpa_event_data::p2p_go_neg_completed.
- */
- EVENT_P2P_GO_NEG_COMPLETED,
-
- EVENT_P2P_PROV_DISC_REQUEST,
- EVENT_P2P_PROV_DISC_RESPONSE,
- EVENT_P2P_SD_REQUEST,
- EVENT_P2P_SD_RESPONSE,
-
- /**
* EVENT_IBSS_PEER_LOST - IBSS peer not reachable anymore
*/
EVENT_IBSS_PEER_LOST,
@@ -3365,17 +3123,27 @@
*/
EVENT_DFS_NOP_FINISHED,
- /*
- * EVENT_SURVEY - Received survey data
- *
- * This event gets triggered when a driver query is issued for survey
- * data and the requested data becomes available. The returned data is
- * stored in struct survey_results. The results provide at most one
- * survey entry for each frequency and at minimum will provide one survey
- * entry for one frequency. The survey data can be os_malloc()'d and
- * then os_free()'d, so the event callback must only copy data.
- */
- EVENT_SURVEY
+ /**
+ * EVENT_SURVEY - Received survey data
+ *
+ * This event gets triggered when a driver query is issued for survey
+ * data and the requested data becomes available. The returned data is
+ * stored in struct survey_results. The results provide at most one
+ * survey entry for each frequency and at minimum will provide one
+ * survey entry for one frequency. The survey data can be os_malloc()'d
+ * and then os_free()'d, so the event callback must only copy data.
+ */
+ EVENT_SURVEY,
+
+ /**
+ * EVENT_SCAN_STARTED - Scan started
+ *
+ * This indicates that driver has started a scan operation either based
+ * on a request from wpa_supplicant/hostapd or from another application.
+ * EVENT_SCAN_RESULTS is used to indicate when the scan has been
+ * completed (either successfully or by getting cancelled).
+ */
+ EVENT_SCAN_STARTED
};
@@ -3743,48 +3511,17 @@
const u8 *frame;
size_t frame_len;
u32 datarate;
- int ssi_signal; /* dBm */
- } rx_mgmt;
-
- /**
- * struct rx_action - Data for EVENT_RX_ACTION events
- */
- struct rx_action {
- /**
- * da - Destination address of the received Action frame
- */
- const u8 *da;
-
- /**
- * sa - Source address of the received Action frame
- */
- const u8 *sa;
-
- /**
- * bssid - Address 3 of the received Action frame
- */
- const u8 *bssid;
-
- /**
- * category - Action frame category
- */
- u8 category;
-
- /**
- * data - Action frame body after category field
- */
- const u8 *data;
-
- /**
- * len - Length of data in octets
- */
- size_t len;
/**
* freq - Frequency (in MHz) on which the frame was received
*/
int freq;
- } rx_action;
+
+ /**
+ * ssi_signal - Signal strength in dBm (or 0 if not available)
+ */
+ int ssi_signal;
+ } rx_mgmt;
/**
* struct remain_on_channel - Data for EVENT_REMAIN_ON_CHANNEL events
@@ -3924,66 +3661,6 @@
} low_ack;
/**
- * struct p2p_dev_found - Data for EVENT_P2P_DEV_FOUND
- */
- struct p2p_dev_found {
- const u8 *addr;
- const u8 *dev_addr;
- const u8 *pri_dev_type;
- const char *dev_name;
- u16 config_methods;
- u8 dev_capab;
- u8 group_capab;
- } p2p_dev_found;
-
- /**
- * struct p2p_go_neg_req_rx - Data for EVENT_P2P_GO_NEG_REQ_RX
- */
- struct p2p_go_neg_req_rx {
- const u8 *src;
- u16 dev_passwd_id;
- } p2p_go_neg_req_rx;
-
- /**
- * struct p2p_go_neg_completed - Data for EVENT_P2P_GO_NEG_COMPLETED
- */
- struct p2p_go_neg_completed {
- struct p2p_go_neg_results *res;
- } p2p_go_neg_completed;
-
- struct p2p_prov_disc_req {
- 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;
- } p2p_prov_disc_req;
-
- struct p2p_prov_disc_resp {
- const u8 *peer;
- u16 config_methods;
- } p2p_prov_disc_resp;
-
- struct p2p_sd_req {
- int freq;
- const u8 *sa;
- u8 dialog_token;
- u16 update_indic;
- const u8 *tlvs;
- size_t tlvs_len;
- } p2p_sd_req;
-
- struct p2p_sd_resp {
- const u8 *sa;
- u16 update_indic;
- const u8 *tlvs;
- size_t tlvs_len;
- } p2p_sd_resp;
-
- /**
* struct ibss_peer_lost - Data for EVENT_IBSS_PEER_LOST
*/
struct ibss_peer_lost {
@@ -4143,4 +3820,7 @@
/* Convert wpa_event_type to a string for logging */
const char * event_to_string(enum wpa_event_type event);
+/* NULL terminated array of linked in driver wrappers */
+extern struct wpa_driver_ops *wpa_drivers[];
+
#endif /* DRIVER_H */
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index 7d301f7..23a4e2b 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -806,16 +806,10 @@
drv_event_assoc(drv->hapd, mgmt->sa, iebuf, ielen, 1);
break;
case WLAN_FC_STYPE_ACTION:
- if (&mgmt->u.action.category > buf + len)
- break;
os_memset(&event, 0, sizeof(event));
- event.rx_action.da = mgmt->da;
- event.rx_action.sa = mgmt->sa;
- event.rx_action.bssid = mgmt->bssid;
- event.rx_action.category = mgmt->u.action.category;
- event.rx_action.data = &mgmt->u.action.category;
- event.rx_action.len = buf + len - event.rx_action.data;
- wpa_supplicant_event(drv->hapd, EVENT_RX_ACTION, &event);
+ event.rx_mgmt.frame = buf;
+ event.rx_mgmt.frame_len = len;
+ wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
break;
case WLAN_FC_STYPE_AUTH:
if (len - IEEE80211_HDRLEN < sizeof(mgmt->u.auth))
@@ -954,16 +948,10 @@
switch (stype) {
case WLAN_FC_STYPE_ACTION:
- if (&mgmt->u.action.category > buf + len)
- break;
os_memset(&event, 0, sizeof(event));
- event.rx_action.da = mgmt->da;
- event.rx_action.sa = mgmt->sa;
- event.rx_action.bssid = mgmt->bssid;
- event.rx_action.category = mgmt->u.action.category;
- event.rx_action.data = &mgmt->u.action.category;
- event.rx_action.len = buf + len - event.rx_action.data;
- wpa_supplicant_event(drv->hapd, EVENT_RX_ACTION, &event);
+ event.rx_mgmt.frame = buf;
+ event.rx_mgmt.frame_len = len;
+ wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
break;
default:
break;
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index fb6402d..7f5e231 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -1110,9 +1110,9 @@
if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
return -1;
- privacy = !(params->pairwise_suite == CIPHER_NONE &&
- params->group_suite == CIPHER_NONE &&
- params->key_mgmt_suite == KEY_MGMT_NONE &&
+ privacy = !(params->pairwise_suite == WPA_CIPHER_NONE &&
+ params->group_suite == WPA_CIPHER_NONE &&
+ params->key_mgmt_suite == WPA_KEY_MGMT_NONE &&
params->wpa_ie_len == 0);
wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index 8d1d22e..64bdddb 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -49,7 +49,6 @@
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);
@@ -65,13 +64,6 @@
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);
@@ -85,6 +77,7 @@
E2S(DFS_CAC_ABORTED);
E2S(DFS_NOP_FINISHED);
E2S(SURVEY);
+ E2S(SCAN_STARTED);
}
return "UNKNOWN";
diff --git a/src/drivers/driver_madwifi.c b/src/drivers/driver_madwifi.c
index 0930834..1635c1f 100644
--- a/src/drivers/driver_madwifi.c
+++ b/src/drivers/driver_madwifi.c
@@ -1,5 +1,5 @@
/*
- * WPA Supplicant - driver interaction with MADWIFI 802.11 driver
+ * hostapd - driver interaction with MADWIFI 802.11 driver
* Copyright (c) 2004, Sam Leffler <sam@errno.com>
* Copyright (c) 2004, Video54 Technologies
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
@@ -7,10 +7,9 @@
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*
- * While this driver wrapper supports both AP (hostapd) and station
- * (wpa_supplicant) operations, the station side is deprecated and
- * driver_wext.c should be used instead. This driver wrapper should only be
- * used with hostapd for AP mode functionality.
+ * This driver wrapper is only for hostapd AP mode functionality. Station
+ * (wpa_supplicant) operations with madwifi are supported by the driver_wext.c
+ * wrapper.
*/
#include "includes.h"
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 4656c1b..4953af6 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -1074,8 +1074,8 @@
/* Try to continue anyway */
}
- if (params->key_mgmt_suite == KEY_MGMT_NONE ||
- params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) {
+ if (params->key_mgmt_suite == WPA_KEY_MGMT_NONE ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
/* Re-set WEP keys if static WEP configuration is used. */
int i;
for (i = 0; i < 4; i++) {
@@ -1102,12 +1102,12 @@
priv_mode = Ndis802_11PrivFilterAcceptAll;
} else if (params->wpa_ie[0] == WLAN_EID_RSN) {
priv_mode = Ndis802_11PrivFilter8021xWEP;
- if (params->key_mgmt_suite == KEY_MGMT_PSK)
+ if (params->key_mgmt_suite == WPA_KEY_MGMT_PSK)
auth_mode = Ndis802_11AuthModeWPA2PSK;
else
auth_mode = Ndis802_11AuthModeWPA2;
#ifdef CONFIG_WPS
- } else if (params->key_mgmt_suite == KEY_MGMT_WPS) {
+ } else if (params->key_mgmt_suite == WPA_KEY_MGMT_WPS) {
auth_mode = Ndis802_11AuthModeOpen;
priv_mode = Ndis802_11PrivFilterAcceptAll;
if (params->wps == WPS_MODE_PRIVACY) {
@@ -1129,35 +1129,35 @@
#endif /* CONFIG_WPS */
} else {
priv_mode = Ndis802_11PrivFilter8021xWEP;
- if (params->key_mgmt_suite == KEY_MGMT_WPA_NONE)
+ if (params->key_mgmt_suite == WPA_KEY_MGMT_WPA_NONE)
auth_mode = Ndis802_11AuthModeWPANone;
- else if (params->key_mgmt_suite == KEY_MGMT_PSK)
+ else if (params->key_mgmt_suite == WPA_KEY_MGMT_PSK)
auth_mode = Ndis802_11AuthModeWPAPSK;
else
auth_mode = Ndis802_11AuthModeWPA;
}
switch (params->pairwise_suite) {
- case CIPHER_CCMP:
+ case WPA_CIPHER_CCMP:
encr = Ndis802_11Encryption3Enabled;
break;
- case CIPHER_TKIP:
+ case WPA_CIPHER_TKIP:
encr = Ndis802_11Encryption2Enabled;
break;
- case CIPHER_WEP40:
- case CIPHER_WEP104:
+ case WPA_CIPHER_WEP40:
+ case WPA_CIPHER_WEP104:
encr = Ndis802_11Encryption1Enabled;
break;
- case CIPHER_NONE:
+ case WPA_CIPHER_NONE:
#ifdef CONFIG_WPS
if (params->wps == WPS_MODE_PRIVACY) {
encr = Ndis802_11Encryption1Enabled;
break;
}
#endif /* CONFIG_WPS */
- if (params->group_suite == CIPHER_CCMP)
+ if (params->group_suite == WPA_CIPHER_CCMP)
encr = Ndis802_11Encryption3Enabled;
- else if (params->group_suite == CIPHER_TKIP)
+ else if (params->group_suite == WPA_CIPHER_TKIP)
encr = Ndis802_11Encryption2Enabled;
else
encr = Ndis802_11EncryptionDisabled;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 42dddf0..fce6efd 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1,6 +1,6 @@
/*
* Driver interaction with Linux nl80211/cfg80211
- * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2004, Instant802 Networks, Inc.
* Copyright (c) 2005-2006, Devicescape Software, Inc.
* Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
@@ -300,7 +300,6 @@
unsigned int hostapd:1;
unsigned int start_mode_ap:1;
unsigned int start_iface_up:1;
- unsigned int channel_switch_supported:1;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
@@ -497,6 +496,11 @@
C2S(NL80211_CMD_FT_EVENT)
C2S(NL80211_CMD_CRIT_PROTOCOL_START)
C2S(NL80211_CMD_CRIT_PROTOCOL_STOP)
+ C2S(NL80211_CMD_GET_COALESCE)
+ C2S(NL80211_CMD_SET_COALESCE)
+ C2S(NL80211_CMD_CHANNEL_SWITCH)
+ C2S(NL80211_CMD_VENDOR)
+ C2S(NL80211_CMD_SET_QOS_MAP)
default:
return "NL80211_CMD_UNKNOWN";
}
@@ -1045,49 +1049,55 @@
}
-static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv,
- char *buf, size_t len, int del)
+static void wpa_driver_nl80211_event_newlink(
+ struct wpa_driver_nl80211_data *drv, char *ifname)
{
union wpa_event_data event;
- os_memset(&event, 0, sizeof(event));
- if (len > sizeof(event.interface_status.ifname))
- len = sizeof(event.interface_status.ifname) - 1;
- os_memcpy(event.interface_status.ifname, buf, len);
- event.interface_status.ievent = del ? EVENT_INTERFACE_REMOVED :
- EVENT_INTERFACE_ADDED;
-
- wpa_printf(MSG_DEBUG, "RTM_%sLINK, IFLA_IFNAME: Interface '%s' %s",
- del ? "DEL" : "NEW",
- event.interface_status.ifname,
- del ? "removed" : "added");
-
- if (os_strcmp(drv->first_bss->ifname, event.interface_status.ifname) ==
- 0) {
- if (del) {
- if (drv->if_removed) {
- wpa_printf(MSG_DEBUG, "nl80211: if_removed "
- "already set - ignore event");
- return;
- }
- drv->if_removed = 1;
- } else {
- if (if_nametoindex(drv->first_bss->ifname) == 0) {
- wpa_printf(MSG_DEBUG, "nl80211: Interface %s "
- "does not exist - ignore "
- "RTM_NEWLINK",
- drv->first_bss->ifname);
- return;
- }
- if (!drv->if_removed) {
- wpa_printf(MSG_DEBUG, "nl80211: if_removed "
- "already cleared - ignore event");
- return;
- }
- drv->if_removed = 0;
+ if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
+ if (if_nametoindex(drv->first_bss->ifname) == 0) {
+ wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
+ drv->first_bss->ifname);
+ return;
}
+ if (!drv->if_removed)
+ return;
+ wpa_printf(MSG_DEBUG, "nl80211: Mark if_removed=0 for %s based on RTM_NEWLINK event",
+ drv->first_bss->ifname);
+ drv->if_removed = 0;
}
+ os_memset(&event, 0, sizeof(event));
+ os_strlcpy(event.interface_status.ifname, ifname,
+ sizeof(event.interface_status.ifname));
+ event.interface_status.ievent = EVENT_INTERFACE_ADDED;
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+}
+
+
+static void wpa_driver_nl80211_event_dellink(
+ struct wpa_driver_nl80211_data *drv, char *ifname)
+{
+ union wpa_event_data event;
+
+ if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
+ if (drv->if_removed) {
+ wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
+ ifname);
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed - mark if_removed=1",
+ ifname);
+ drv->if_removed = 1;
+ } else {
+ wpa_printf(MSG_DEBUG, "RTM_DELLINK: Interface '%s' removed",
+ ifname);
+ }
+
+ os_memset(&event, 0, sizeof(event));
+ os_strlcpy(event.interface_status.ifname, ifname,
+ sizeof(event.interface_status.ifname));
+ event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
}
@@ -1154,21 +1164,57 @@
{
struct nl80211_global *global = ctx;
struct wpa_driver_nl80211_data *drv;
- int attrlen, rta_len;
+ int attrlen;
struct rtattr *attr;
u32 brid = 0;
char namebuf[IFNAMSIZ];
+ char ifname[IFNAMSIZ + 1];
+ char extra[100], *pos, *end;
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);
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d",
+ ifi->ifi_index);
return;
}
- wpa_printf(MSG_DEBUG, "RTM_NEWLINK: operstate=%d ifi_flags=0x%x "
- "(%s%s%s%s)",
- drv->operstate, ifi->ifi_flags,
+ extra[0] = '\0';
+ pos = extra;
+ end = pos + sizeof(extra);
+ ifname[0] = '\0';
+
+ attrlen = len;
+ attr = (struct rtattr *) buf;
+ while (RTA_OK(attr, attrlen)) {
+ switch (attr->rta_type) {
+ case IFLA_IFNAME:
+ if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
+ break;
+ os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
+ ifname[RTA_PAYLOAD(attr)] = '\0';
+ break;
+ case IFLA_MASTER:
+ brid = nla_get_u32((struct nlattr *) attr);
+ pos += os_snprintf(pos, end - pos, " master=%u", brid);
+ break;
+ case IFLA_WIRELESS:
+ pos += os_snprintf(pos, end - pos, " wext");
+ break;
+ case IFLA_OPERSTATE:
+ pos += os_snprintf(pos, end - pos, " operstate=%u",
+ nla_get_u32((struct nlattr *) attr));
+ break;
+ case IFLA_LINKMODE:
+ pos += os_snprintf(pos, end - pos, " linkmode=%u",
+ nla_get_u32((struct nlattr *) attr));
+ break;
+ }
+ attr = RTA_NEXT(attr, attrlen);
+ }
+ extra[sizeof(extra) - 1] = '\0';
+
+ wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_flags=0x%x (%s%s%s%s)",
+ ifi->ifi_index, ifname, extra, ifi->ifi_flags,
(ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
(ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
@@ -1225,24 +1271,15 @@
*/
if (drv->operstate == 1 &&
(ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
- !(ifi->ifi_flags & IFF_RUNNING))
+ !(ifi->ifi_flags & IFF_RUNNING)) {
+ wpa_printf(MSG_DEBUG, "nl80211: Set IF_OPER_UP again based on ifi_flags and expected operstate");
netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
-1, IF_OPER_UP);
-
- attrlen = len;
- attr = (struct rtattr *) buf;
- rta_len = RTA_ALIGN(sizeof(struct rtattr));
- while (RTA_OK(attr, attrlen)) {
- if (attr->rta_type == IFLA_IFNAME) {
- wpa_driver_nl80211_event_link(
- drv,
- ((char *) attr) + rta_len,
- attr->rta_len - rta_len, 0);
- } else if (attr->rta_type == IFLA_MASTER)
- brid = nla_get_u32((struct nlattr *) attr);
- attr = RTA_NEXT(attr, attrlen);
}
+ if (ifname[0])
+ wpa_driver_nl80211_event_newlink(drv, ifname);
+
if (ifi->ifi_family == AF_BRIDGE && brid) {
/* device has been added to bridge */
if_indextoname(brid, namebuf);
@@ -1259,32 +1296,40 @@
{
struct nl80211_global *global = ctx;
struct wpa_driver_nl80211_data *drv;
- int attrlen, rta_len;
+ int attrlen;
struct rtattr *attr;
u32 brid = 0;
+ char ifname[IFNAMSIZ + 1];
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);
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d",
+ ifi->ifi_index);
return;
}
+ ifname[0] = '\0';
+
attrlen = len;
attr = (struct rtattr *) buf;
-
- rta_len = RTA_ALIGN(sizeof(struct rtattr));
while (RTA_OK(attr, attrlen)) {
- if (attr->rta_type == IFLA_IFNAME) {
- wpa_driver_nl80211_event_link(
- drv,
- ((char *) attr) + rta_len,
- attr->rta_len - rta_len, 1);
- } else if (attr->rta_type == IFLA_MASTER)
+ switch (attr->rta_type) {
+ case IFLA_IFNAME:
+ if (RTA_PAYLOAD(attr) >= IFNAMSIZ)
+ break;
+ os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr));
+ ifname[RTA_PAYLOAD(attr)] = '\0';
+ break;
+ case IFLA_MASTER:
brid = nla_get_u32((struct nlattr *) attr);
+ break;
+ }
attr = RTA_NEXT(attr, attrlen);
}
+ if (ifname[0])
+ wpa_driver_nl80211_event_dellink(drv, ifname);
+
if (ifi->ifi_family == AF_BRIDGE && brid) {
/* device has been removed from bridge */
char namebuf[IFNAMSIZ];
@@ -1602,7 +1647,7 @@
wpa_printf(MSG_MSGDUMP, "nl80211: Frame event");
mgmt = (const struct ieee80211_mgmt *) frame;
if (len < 24) {
- wpa_printf(MSG_DEBUG, "nl80211: Too short action frame");
+ wpa_printf(MSG_DEBUG, "nl80211: Too short management frame");
return;
}
@@ -1614,26 +1659,16 @@
os_memset(&event, 0, sizeof(event));
if (freq) {
- event.rx_action.freq = nla_get_u32(freq);
- rx_freq = drv->last_mgmt_freq = event.rx_action.freq;
+ event.rx_mgmt.freq = nla_get_u32(freq);
+ rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
}
wpa_printf(MSG_DEBUG,
"nl80211: RX frame freq=%d ssi_signal=%d stype=%u len=%u",
rx_freq, ssi_signal, stype, (unsigned int) len);
- if (stype == WLAN_FC_STYPE_ACTION) {
- event.rx_action.da = mgmt->da;
- event.rx_action.sa = mgmt->sa;
- event.rx_action.bssid = mgmt->bssid;
- event.rx_action.category = mgmt->u.action.category;
- 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);
- } else {
- event.rx_mgmt.frame = frame;
- event.rx_mgmt.frame_len = len;
- event.rx_mgmt.ssi_signal = ssi_signal;
- wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
- }
+ event.rx_mgmt.frame = frame;
+ event.rx_mgmt.frame_len = len;
+ event.rx_mgmt.ssi_signal = ssi_signal;
+ wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
}
@@ -2037,21 +2072,36 @@
&info->ssids[info->num_ssids];
s->ssid = nla_data(nl);
s->ssid_len = nla_len(nl);
+ wpa_printf(MSG_DEBUG, "nl80211: Scan probed for SSID '%s'",
+ wpa_ssid_txt(s->ssid, s->ssid_len));
info->num_ssids++;
if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
break;
}
}
if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
+ char msg[200], *pos, *end;
+ int res;
+
+ pos = msg;
+ end = pos + sizeof(msg);
+ *pos = '\0';
+
nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem)
{
freqs[num_freqs] = nla_get_u32(nl);
+ res = os_snprintf(pos, end - pos, " %d",
+ freqs[num_freqs]);
+ if (res > 0 && end - pos > res)
+ pos += res;
num_freqs++;
if (num_freqs == MAX_REPORT_FREQS - 1)
break;
}
info->freqs = freqs;
info->num_freqs = num_freqs;
+ wpa_printf(MSG_DEBUG, "nl80211: Scan included frequencies:%s",
+ msg);
}
wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
}
@@ -2666,6 +2716,48 @@
}
+static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
+ struct nlattr **tb)
+{
+ u32 vendor_id, subcmd, wiphy = 0;
+ int wiphy_idx;
+ u8 *data = NULL;
+ size_t len = 0;
+
+ if (!tb[NL80211_ATTR_VENDOR_ID] ||
+ !tb[NL80211_ATTR_VENDOR_SUBCMD])
+ return;
+
+ vendor_id = nla_get_u32(tb[NL80211_ATTR_VENDOR_ID]);
+ subcmd = nla_get_u32(tb[NL80211_ATTR_VENDOR_SUBCMD]);
+
+ if (tb[NL80211_ATTR_WIPHY])
+ wiphy = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
+
+ wpa_printf(MSG_DEBUG, "nl80211: Vendor event: wiphy=%u vendor_id=0x%x subcmd=%u",
+ wiphy, vendor_id, subcmd);
+
+ if (tb[NL80211_ATTR_VENDOR_DATA]) {
+ data = nla_data(tb[NL80211_ATTR_VENDOR_DATA]);
+ len = nla_len(tb[NL80211_ATTR_VENDOR_DATA]);
+ wpa_hexdump(MSG_MSGDUMP, "nl80211: Vendor data", data, len);
+ }
+
+ wiphy_idx = nl80211_get_wiphy_index(drv->first_bss);
+ if (wiphy_idx >= 0 && wiphy_idx != (int) wiphy) {
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore vendor event for foreign wiphy %u (own: %d)",
+ wiphy, wiphy_idx);
+ return;
+ }
+
+ switch (vendor_id) {
+ default:
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
+ break;
+ }
+}
+
+
static void do_process_drv_event(struct i802_bss *bss, int cmd,
struct nlattr **tb)
{
@@ -2687,6 +2779,7 @@
case NL80211_CMD_TRIGGER_SCAN:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
drv->scan_state = SCAN_STARTED;
+ wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
break;
case NL80211_CMD_START_SCHED_SCAN:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
@@ -2838,6 +2931,9 @@
case NL80211_CMD_STOP_AP:
nl80211_stop_ap(drv, tb);
break;
+ case NL80211_CMD_VENDOR:
+ nl80211_vendor_event(drv, tb);
+ break;
default:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", cmd);
@@ -3105,6 +3201,7 @@
unsigned int p2p_client_supported:1;
unsigned int p2p_concurrent:1;
unsigned int channel_switch_supported:1;
+ unsigned int set_qos_map_supported:1;
};
@@ -3265,6 +3362,65 @@
case NL80211_CMD_CHANNEL_SWITCH:
info->channel_switch_supported = 1;
break;
+ case NL80211_CMD_SET_QOS_MAP:
+ info->set_qos_map_supported = 1;
+ break;
+ }
+ }
+}
+
+
+static void wiphy_info_cipher_suites(struct wiphy_info_data *info,
+ struct nlattr *tb)
+{
+ int i, num;
+ u32 *ciphers;
+
+ if (tb == NULL)
+ return;
+
+ num = nla_len(tb) / sizeof(u32);
+ ciphers = nla_data(tb);
+ for (i = 0; i < num; i++) {
+ u32 c = ciphers[i];
+
+ wpa_printf(MSG_DEBUG, "nl80211: Supported cipher %02x-%02x-%02x:%d",
+ c >> 24, (c >> 16) & 0xff,
+ (c >> 8) & 0xff, c & 0xff);
+ switch (c) {
+ case WLAN_CIPHER_SUITE_CCMP_256:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP_256;
+ break;
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP_256;
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_CCMP;
+ break;
+ case WLAN_CIPHER_SUITE_GCMP:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_GCMP;
+ break;
+ case WLAN_CIPHER_SUITE_TKIP:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_TKIP;
+ break;
+ case WLAN_CIPHER_SUITE_WEP104:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP104;
+ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_WEP40;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_128;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_GMAC_256;
+ break;
+ case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+ info->capa->enc |= WPA_DRIVER_CAPA_ENC_BIP_CMAC_256;
+ break;
}
}
}
@@ -3369,6 +3525,7 @@
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
+ wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]);
if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
@@ -3421,6 +3578,38 @@
}
}
+ if (tb[NL80211_ATTR_VENDOR_DATA]) {
+ struct nlattr *nl;
+ int rem;
+
+ nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_DATA], rem) {
+ struct nl80211_vendor_cmd_info *vinfo;
+ if (nla_len(nl) != sizeof(vinfo)) {
+ wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
+ continue;
+ }
+ vinfo = nla_data(nl);
+ wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
+ vinfo->vendor_id, vinfo->subcmd);
+ }
+ }
+
+ if (tb[NL80211_ATTR_VENDOR_EVENTS]) {
+ struct nlattr *nl;
+ int rem;
+
+ nla_for_each_nested(nl, tb[NL80211_ATTR_VENDOR_EVENTS], rem) {
+ struct nl80211_vendor_cmd_info *vinfo;
+ if (nla_len(nl) != sizeof(vinfo)) {
+ wpa_printf(MSG_DEBUG, "nl80211: Unexpected vendor data info");
+ continue;
+ }
+ vinfo = nla_data(nl);
+ wpa_printf(MSG_DEBUG, "nl80211: Supported vendor event: vendor_id=0x%x subcmd=%u",
+ vinfo->vendor_id, vinfo->subcmd);
+ }
+ }
+
return NL_SKIP;
}
@@ -3479,6 +3668,9 @@
if (!drv->capa.max_remain_on_chan)
drv->capa.max_remain_on_chan = 5000;
+ if (info->channel_switch_supported)
+ drv->capa.flags |= WPA_DRIVER_FLAGS_AP_CSA;
+
return 0;
nla_put_failure:
nlmsg_free(msg);
@@ -3496,15 +3688,10 @@
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 |
WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
- drv->capa.enc = WPA_DRIVER_CAPA_ENC_WEP40 |
- WPA_DRIVER_CAPA_ENC_WEP104 |
- WPA_DRIVER_CAPA_ENC_TKIP |
- WPA_DRIVER_CAPA_ENC_CCMP;
drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
WPA_DRIVER_AUTH_SHARED |
WPA_DRIVER_AUTH_LEAP;
@@ -3526,7 +3713,8 @@
drv->device_ap_sme = info.device_ap_sme;
drv->poll_command_supported = info.poll_command_supported;
drv->data_tx_status = info.data_tx_status;
- drv->channel_switch_supported = info.channel_switch_supported;
+ if (info.set_qos_map_supported)
+ drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;
/*
* If poll command and tx status are supported, mac80211 is new enough
@@ -3652,6 +3840,16 @@
/* Continue without regulatory events */
}
+ ret = nl_get_multicast_id(global, "nl80211", "vendor");
+ if (ret >= 0)
+ ret = nl_socket_add_membership(global->nl_event, ret);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "nl80211: Could not add multicast "
+ "membership for vendor events: %d (%s)",
+ ret, strerror(-ret));
+ /* Continue without vendor events */
+ }
+
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,
@@ -3912,15 +4110,16 @@
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
int ret = -1;
+ char buf[30];
msg = nlmsg_alloc();
if (!msg)
return -1;
- 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);
+ buf[0] = '\0';
+ wpa_snprintf_hex(buf, sizeof(buf), match, match_len);
+ wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x nl_handle=%p match=%s",
+ type, nl_handle, buf);
nl80211_cmd(drv, msg, 0, NL80211_CMD_REGISTER_ACTION);
@@ -3985,6 +4184,7 @@
static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
+ int ret = 0;
if (nl80211_alloc_mgmt_handle(bss))
return -1;
@@ -4001,65 +4201,65 @@
#ifdef CONFIG_INTERWORKING
/* QoS Map Configure */
if (nl80211_register_action_frame(bss, (u8 *) "\x01\x04", 2) < 0)
- return -1;
+ ret = -1;
#endif /* CONFIG_INTERWORKING */
#if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING)
/* GAS Initial Request */
if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0a", 2) < 0)
- return -1;
+ ret = -1;
/* GAS Initial Response */
if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0b", 2) < 0)
- return -1;
+ ret = -1;
/* GAS Comeback Request */
if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0c", 2) < 0)
- return -1;
+ ret = -1;
/* GAS Comeback Response */
if (nl80211_register_action_frame(bss, (u8 *) "\x04\x0d", 2) < 0)
- return -1;
+ ret = -1;
#endif /* CONFIG_P2P || CONFIG_INTERWORKING */
#ifdef CONFIG_P2P
/* P2P Public Action */
if (nl80211_register_action_frame(bss,
(u8 *) "\x04\x09\x50\x6f\x9a\x09",
6) < 0)
- return -1;
+ ret = -1;
/* P2P Action */
if (nl80211_register_action_frame(bss,
(u8 *) "\x7f\x50\x6f\x9a\x09",
5) < 0)
- return -1;
+ ret = -1;
#endif /* CONFIG_P2P */
#ifdef CONFIG_IEEE80211W
/* SA Query Response */
if (nl80211_register_action_frame(bss, (u8 *) "\x08\x01", 2) < 0)
- return -1;
+ ret = -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;
+ ret = -1;
}
#endif /* CONFIG_TDLS */
/* FT Action frames */
if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
- return -1;
+ ret = -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;
+ ret = -1;
/* WNM-Sleep Mode Response */
if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
- return -1;
+ ret = -1;
nl80211_mgmt_handle_register_eloop(bss);
- return 0;
+ return ret;
}
@@ -4521,6 +4721,12 @@
params->filter_ssids = NULL;
drv->num_filter_ssids = params->num_filter_ssids;
+ if (params->only_new_results) {
+ wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH");
+ NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS,
+ NL80211_SCAN_FLAG_FLUSH);
+ }
+
return msg;
fail:
@@ -4931,7 +5137,8 @@
* BSSID,SSID pair is seen on multiple channels. wpa_supplicant does
* not use frequency as a separate key in the BSS table, so filter out
* duplicated entries. Prefer associated BSS entry in such a case in
- * order to get the correct frequency into the BSS table.
+ * order to get the correct frequency into the BSS table. Similarly,
+ * prefer newer entries over older.
*/
for (i = 0; i < res->num; i++) {
const u8 *s1, *s2;
@@ -4949,8 +5156,9 @@
wpa_printf(MSG_DEBUG, "nl80211: Remove duplicated scan result "
"for " MACSTR, MAC2STR(r->bssid));
- if ((r->flags & WPA_SCAN_ASSOCIATED) &&
- !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) {
+ if (((r->flags & WPA_SCAN_ASSOCIATED) &&
+ !(res->res[i]->flags & WPA_SCAN_ASSOCIATED)) ||
+ r->age < res->res[i]->age) {
os_free(res->res[i]);
res->res[i] = r;
} else
@@ -5116,6 +5324,95 @@
}
+static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len)
+{
+ switch (alg) {
+ case WPA_ALG_WEP:
+ if (key_len == 5)
+ return WLAN_CIPHER_SUITE_WEP40;
+ return WLAN_CIPHER_SUITE_WEP104;
+ case WPA_ALG_TKIP:
+ return WLAN_CIPHER_SUITE_TKIP;
+ case WPA_ALG_CCMP:
+ return WLAN_CIPHER_SUITE_CCMP;
+ case WPA_ALG_GCMP:
+ return WLAN_CIPHER_SUITE_GCMP;
+ case WPA_ALG_CCMP_256:
+ return WLAN_CIPHER_SUITE_CCMP_256;
+ case WPA_ALG_GCMP_256:
+ return WLAN_CIPHER_SUITE_GCMP_256;
+ case WPA_ALG_IGTK:
+ return WLAN_CIPHER_SUITE_AES_CMAC;
+ case WPA_ALG_BIP_GMAC_128:
+ return WLAN_CIPHER_SUITE_BIP_GMAC_128;
+ case WPA_ALG_BIP_GMAC_256:
+ return WLAN_CIPHER_SUITE_BIP_GMAC_256;
+ case WPA_ALG_BIP_CMAC_256:
+ return WLAN_CIPHER_SUITE_BIP_CMAC_256;
+ case WPA_ALG_SMS4:
+ return WLAN_CIPHER_SUITE_SMS4;
+ case WPA_ALG_KRK:
+ return WLAN_CIPHER_SUITE_KRK;
+ case WPA_ALG_NONE:
+ case WPA_ALG_PMK:
+ wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d",
+ alg);
+ return 0;
+ }
+
+ wpa_printf(MSG_ERROR, "nl80211: Unsupported encryption algorithm %d",
+ alg);
+ return 0;
+}
+
+
+static u32 wpa_cipher_to_cipher_suite(unsigned int cipher)
+{
+ switch (cipher) {
+ case WPA_CIPHER_CCMP_256:
+ return WLAN_CIPHER_SUITE_CCMP_256;
+ case WPA_CIPHER_GCMP_256:
+ return WLAN_CIPHER_SUITE_GCMP_256;
+ case WPA_CIPHER_CCMP:
+ return WLAN_CIPHER_SUITE_CCMP;
+ case WPA_CIPHER_GCMP:
+ return WLAN_CIPHER_SUITE_GCMP;
+ case WPA_CIPHER_TKIP:
+ return WLAN_CIPHER_SUITE_TKIP;
+ case WPA_CIPHER_WEP104:
+ return WLAN_CIPHER_SUITE_WEP104;
+ case WPA_CIPHER_WEP40:
+ return WLAN_CIPHER_SUITE_WEP40;
+ }
+
+ return 0;
+}
+
+
+static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[],
+ int max_suites)
+{
+ int num_suites = 0;
+
+ if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP_256)
+ suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP_256;
+ if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP_256)
+ suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP_256;
+ if (num_suites < max_suites && ciphers & WPA_CIPHER_CCMP)
+ suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
+ if (num_suites < max_suites && ciphers & WPA_CIPHER_GCMP)
+ suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;
+ if (num_suites < max_suites && ciphers & WPA_CIPHER_TKIP)
+ suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP;
+ if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP104)
+ suites[num_suites++] = WLAN_CIPHER_SUITE_WEP104;
+ if (num_suites < max_suites && ciphers & WPA_CIPHER_WEP40)
+ suites[num_suites++] = WLAN_CIPHER_SUITE_WEP40;
+
+ return num_suites;
+}
+
+
static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
enum wpa_alg alg, const u8 *addr,
int key_idx, int set_tx,
@@ -5153,45 +5450,8 @@
} else {
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:
- if (key_len == 5)
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- WLAN_CIPHER_SUITE_WEP40);
- else
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- WLAN_CIPHER_SUITE_WEP104);
- break;
- case WPA_ALG_TKIP:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- WLAN_CIPHER_SUITE_TKIP);
- break;
- case WPA_ALG_CCMP:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- WLAN_CIPHER_SUITE_CCMP);
- break;
- case WPA_ALG_GCMP:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- WLAN_CIPHER_SUITE_GCMP);
- break;
- case WPA_ALG_IGTK:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- WLAN_CIPHER_SUITE_AES_CMAC);
- break;
- case WPA_ALG_SMS4:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- WLAN_CIPHER_SUITE_SMS4);
- break;
- case WPA_ALG_KRK:
- NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
- WLAN_CIPHER_SUITE_KRK);
- break;
- default:
- wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
- "algorithm %d", __func__, alg);
- nlmsg_free(msg);
- return -1;
- }
+ NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
+ wpa_alg_to_cipher_suite(alg, key_len));
}
if (seq && seq_len)
@@ -5296,33 +5556,8 @@
NLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);
- switch (alg) {
- case WPA_ALG_WEP:
- if (key_len == 5)
- NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
- WLAN_CIPHER_SUITE_WEP40);
- else
- NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
- WLAN_CIPHER_SUITE_WEP104);
- break;
- case WPA_ALG_TKIP:
- NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_TKIP);
- break;
- case WPA_ALG_CCMP:
- NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP);
- break;
- case WPA_ALG_GCMP:
- NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_GCMP);
- break;
- case WPA_ALG_IGTK:
- NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
- WLAN_CIPHER_SUITE_AES_CMAC);
- break;
- default:
- wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
- "algorithm %d", __func__, alg);
- return -1;
- }
+ NLA_PUT_U32(msg, NL80211_KEY_CIPHER,
+ wpa_alg_to_cipher_suite(alg, key_len));
if (seq && seq_len)
NLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);
@@ -5784,10 +6019,8 @@
if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
chan->flag |= HOSTAPD_CHAN_DISABLED;
- if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])
- chan->flag |= HOSTAPD_CHAN_PASSIVE_SCAN;
- if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])
- chan->flag |= HOSTAPD_CHAN_NO_IBSS;
+ if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR])
+ chan->flag |= HOSTAPD_CHAN_PASSIVE_SCAN | HOSTAPD_CHAN_NO_IBSS;
if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
chan->flag |= HOSTAPD_CHAN_RADAR;
@@ -5816,8 +6049,7 @@
static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
[NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
[NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
- [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
- [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
[NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
[NL80211_FREQUENCY_ATTR_DFS_STATE] = { .type = NLA_U32 },
@@ -6113,24 +6345,11 @@
}
-static void nl80211_reg_rule_max_eirp(struct nlattr *tb[],
+static void nl80211_reg_rule_max_eirp(u32 start, u32 end, u32 max_eirp,
struct phy_info_arg *results)
{
- u32 start, end, max_eirp;
u16 m;
- if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
- tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
- tb[NL80211_ATTR_POWER_RULE_MAX_EIRP] == NULL)
- return;
-
- start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
- end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
- max_eirp = nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_EIRP]) / 100;
-
- wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u mBm",
- start, end, max_eirp);
-
for (m = 0; m < *results->num_modes; m++) {
int c;
struct hostapd_hw_modes *mode = &results->modes[m];
@@ -6145,26 +6364,11 @@
}
-static void nl80211_reg_rule_ht40(struct nlattr *tb[],
+static void nl80211_reg_rule_ht40(u32 start, u32 end,
struct phy_info_arg *results)
{
- u32 start, end, max_bw;
u16 m;
- if (tb[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
- tb[NL80211_ATTR_FREQ_RANGE_END] == NULL ||
- tb[NL80211_ATTR_FREQ_RANGE_MAX_BW] == NULL)
- return;
-
- start = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
- end = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
- max_bw = nla_get_u32(tb[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
-
- wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz",
- start, end, max_bw);
- if (max_bw < 40)
- return;
-
for (m = 0; m < *results->num_modes; m++) {
if (!(results->modes[m].ht_capab &
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
@@ -6285,10 +6489,26 @@
nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
{
+ u32 start, end, max_eirp = 0, max_bw = 0;
nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
nla_data(nl_rule), nla_len(nl_rule), reg_policy);
- nl80211_reg_rule_ht40(tb_rule, results);
- nl80211_reg_rule_max_eirp(tb_rule, results);
+ if (tb_rule[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
+ tb_rule[NL80211_ATTR_FREQ_RANGE_END] == NULL)
+ continue;
+ start = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_START]) / 1000;
+ end = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_END]) / 1000;
+ if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
+ max_eirp = nla_get_u32(tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP]) / 100;
+ if (tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW])
+ max_bw = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
+
+ wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm",
+ start, end, max_bw, max_eirp);
+ if (max_bw >= 40)
+ nl80211_reg_rule_ht40(start, end, results);
+ if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
+ nl80211_reg_rule_max_eirp(start, end, max_eirp,
+ results);
}
nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
@@ -6648,7 +6868,7 @@
int beacon_set;
int ifindex = if_nametoindex(bss->ifname);
int num_suites;
- u32 suites[10];
+ u32 suites[10], suite;
u32 ver;
beacon_set = bss->beacon_set;
@@ -6743,17 +6963,8 @@
wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
params->pairwise_ciphers);
- num_suites = 0;
- if (params->pairwise_ciphers & WPA_CIPHER_CCMP)
- suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP;
- if (params->pairwise_ciphers & WPA_CIPHER_GCMP)
- suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP;
- 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;
+ num_suites = wpa_cipher_to_cipher_suites(params->pairwise_ciphers,
+ suites, ARRAY_SIZE(suites));
if (num_suites) {
NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
num_suites * sizeof(u32), suites);
@@ -6761,28 +6972,9 @@
wpa_printf(MSG_DEBUG, "nl80211: group_cipher=0x%x",
params->group_cipher);
- 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_GCMP:
- NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP,
- WLAN_CIPHER_SUITE_GCMP);
- 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;
- }
+ suite = wpa_cipher_to_cipher_suite(params->group_cipher);
+ if (suite)
+ NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite);
if (params->beacon_ies) {
wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
@@ -7977,10 +8169,10 @@
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
}
- if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
- params->key_mgmt_suite == KEY_MGMT_PSK ||
- params->key_mgmt_suite == KEY_MGMT_802_1X_SHA256 ||
- params->key_mgmt_suite == KEY_MGMT_PSK_SHA256) {
+ if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256) {
wpa_printf(MSG_DEBUG, " * control port");
NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
}
@@ -8018,40 +8210,32 @@
}
-static int wpa_driver_nl80211_try_connect(
- struct wpa_driver_nl80211_data *drv,
- struct wpa_driver_associate_params *params)
+static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
+ struct wpa_driver_associate_params *params,
+ struct nl_msg *msg)
{
- struct nl_msg *msg;
- enum nl80211_auth_type type;
- int ret = 0;
- int algs;
-
- msg = nlmsg_alloc();
- if (!msg)
- return -1;
-
- wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
- nl80211_cmd(drv, msg, 0, NL80211_CMD_CONNECT);
-
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
if (params->bssid) {
wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
MAC2STR(params->bssid));
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
}
+
if (params->freq) {
wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
drv->assoc_freq = params->freq;
} else
drv->assoc_freq = 0;
+
if (params->bg_scan_period >= 0) {
wpa_printf(MSG_DEBUG, " * bg scan period=%d",
params->bg_scan_period);
NLA_PUT_U16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
params->bg_scan_period);
}
+
if (params->ssid) {
wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
params->ssid, params->ssid_len);
@@ -8062,11 +8246,122 @@
os_memcpy(drv->ssid, params->ssid, params->ssid_len);
drv->ssid_len = params->ssid_len;
}
+
wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
if (params->wpa_ie)
NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
params->wpa_ie);
+ if (params->wpa_proto) {
+ enum nl80211_wpa_versions ver = 0;
+
+ 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 Versions 0x%x", ver);
+ NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
+ }
+
+ if (params->pairwise_suite != WPA_CIPHER_NONE) {
+ u32 cipher = wpa_cipher_to_cipher_suite(params->pairwise_suite);
+ wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher);
+ NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
+ }
+
+ if (params->group_suite != WPA_CIPHER_NONE) {
+ u32 cipher = wpa_cipher_to_cipher_suite(params->group_suite);
+ wpa_printf(MSG_DEBUG, " * group=0x%x", cipher);
+ NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
+ }
+
+ if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_FT_IEEE8021X ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_CCKM) {
+ int mgmt = WLAN_AKM_SUITE_PSK;
+
+ switch (params->key_mgmt_suite) {
+ case WPA_KEY_MGMT_CCKM:
+ mgmt = WLAN_AKM_SUITE_CCKM;
+ break;
+ case WPA_KEY_MGMT_IEEE8021X:
+ mgmt = WLAN_AKM_SUITE_8021X;
+ break;
+ case WPA_KEY_MGMT_FT_IEEE8021X:
+ mgmt = WLAN_AKM_SUITE_FT_8021X;
+ break;
+ case WPA_KEY_MGMT_FT_PSK:
+ mgmt = WLAN_AKM_SUITE_FT_PSK;
+ break;
+ case WPA_KEY_MGMT_PSK:
+ default:
+ mgmt = WLAN_AKM_SUITE_PSK;
+ break;
+ }
+ NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);
+ }
+
+ NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
+
+ if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)
+ NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);
+
+ if (params->disable_ht)
+ NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);
+
+ if (params->htcaps && params->htcaps_mask) {
+ int sz = sizeof(struct ieee80211_ht_capabilities);
+ NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);
+ NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
+ params->htcaps_mask);
+ }
+
+#ifdef CONFIG_VHT_OVERRIDES
+ if (params->disable_vht) {
+ wpa_printf(MSG_DEBUG, " * VHT disabled");
+ NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
+ }
+
+ if (params->vhtcaps && params->vhtcaps_mask) {
+ int sz = sizeof(struct ieee80211_vht_capabilities);
+ NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
+ NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
+ params->vhtcaps_mask);
+ }
+#endif /* CONFIG_VHT_OVERRIDES */
+
+ if (params->p2p)
+ wpa_printf(MSG_DEBUG, " * P2P group");
+
+ return 0;
+nla_put_failure:
+ return -1;
+}
+
+
+static int wpa_driver_nl80211_try_connect(
+ struct wpa_driver_nl80211_data *drv,
+ struct wpa_driver_associate_params *params)
+{
+ struct nl_msg *msg;
+ enum nl80211_auth_type type;
+ int ret;
+ int algs;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_CONNECT);
+
+ ret = nl80211_connect_common(drv, params, msg);
+ if (ret)
+ goto nla_put_failure;
+
algs = 0;
if (params->auth_alg & WPA_AUTH_ALG_OPEN)
algs++;
@@ -8095,129 +8390,6 @@
NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, type);
skip_auth_type:
- if (params->wpa_proto) {
- enum nl80211_wpa_versions ver = 0;
-
- 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 Versions 0x%x", ver);
- NLA_PUT_U32(msg, NL80211_ATTR_WPA_VERSIONS, ver);
- }
-
- if (params->pairwise_suite != CIPHER_NONE) {
- int cipher;
-
- switch (params->pairwise_suite) {
- case CIPHER_SMS4:
- cipher = WLAN_CIPHER_SUITE_SMS4;
- break;
- case CIPHER_WEP40:
- cipher = WLAN_CIPHER_SUITE_WEP40;
- break;
- case CIPHER_WEP104:
- cipher = WLAN_CIPHER_SUITE_WEP104;
- break;
- case CIPHER_CCMP:
- cipher = WLAN_CIPHER_SUITE_CCMP;
- break;
- case CIPHER_GCMP:
- cipher = WLAN_CIPHER_SUITE_GCMP;
- break;
- case CIPHER_TKIP:
- default:
- cipher = WLAN_CIPHER_SUITE_TKIP;
- break;
- }
- NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
- }
-
- if (params->group_suite != CIPHER_NONE) {
- int cipher;
-
- switch (params->group_suite) {
- case CIPHER_SMS4:
- cipher = WLAN_CIPHER_SUITE_SMS4;
- break;
- case CIPHER_WEP40:
- cipher = WLAN_CIPHER_SUITE_WEP40;
- break;
- case CIPHER_WEP104:
- cipher = WLAN_CIPHER_SUITE_WEP104;
- break;
- case CIPHER_CCMP:
- cipher = WLAN_CIPHER_SUITE_CCMP;
- break;
- case CIPHER_GCMP:
- cipher = WLAN_CIPHER_SUITE_GCMP;
- break;
- case CIPHER_TKIP:
- default:
- cipher = WLAN_CIPHER_SUITE_TKIP;
- break;
- }
- NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
- }
-
- if (params->key_mgmt_suite == KEY_MGMT_802_1X ||
- params->key_mgmt_suite == KEY_MGMT_PSK ||
- params->key_mgmt_suite == KEY_MGMT_FT_802_1X ||
- params->key_mgmt_suite == KEY_MGMT_FT_PSK ||
- params->key_mgmt_suite == KEY_MGMT_CCKM) {
- int mgmt = WLAN_AKM_SUITE_PSK;
-
- switch (params->key_mgmt_suite) {
- case KEY_MGMT_CCKM:
- mgmt = WLAN_AKM_SUITE_CCKM;
- break;
- case KEY_MGMT_802_1X:
- mgmt = WLAN_AKM_SUITE_8021X;
- break;
- case KEY_MGMT_FT_802_1X:
- mgmt = WLAN_AKM_SUITE_FT_8021X;
- break;
- case KEY_MGMT_FT_PSK:
- mgmt = WLAN_AKM_SUITE_FT_PSK;
- break;
- case KEY_MGMT_PSK:
- default:
- mgmt = WLAN_AKM_SUITE_PSK;
- break;
- }
- NLA_PUT_U32(msg, NL80211_ATTR_AKM_SUITES, mgmt);
- }
-
-#ifdef CONFIG_IEEE80211W
- if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)
- NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);
-#endif /* CONFIG_IEEE80211W */
-
- if (params->disable_ht)
- NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);
-
- if (params->htcaps && params->htcaps_mask) {
- int sz = sizeof(struct ieee80211_ht_capabilities);
- NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);
- NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
- params->htcaps_mask);
- }
-
-#ifdef CONFIG_VHT_OVERRIDES
- if (params->disable_vht) {
- wpa_printf(MSG_DEBUG, " * VHT disabled");
- NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
- }
-
- if (params->vhtcaps && params->vhtcaps_mask) {
- int sz = sizeof(struct ieee80211_vht_capabilities);
- NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
- NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
- params->vhtcaps_mask);
- }
-#endif /* CONFIG_VHT_OVERRIDES */
-
ret = nl80211_set_conn_keys(params, msg);
if (ret)
goto nla_put_failure;
@@ -8267,7 +8439,7 @@
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
- int ret = -1;
+ int ret;
struct nl_msg *msg;
if (params->mode == IEEE80211_MODE_AP)
@@ -8295,95 +8467,9 @@
drv->ifindex);
nl80211_cmd(drv, msg, 0, NL80211_CMD_ASSOCIATE);
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
- if (params->bssid) {
- wpa_printf(MSG_DEBUG, " * bssid=" MACSTR,
- MAC2STR(params->bssid));
- NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid);
- }
- if (params->freq) {
- wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
- drv->assoc_freq = params->freq;
- } else
- drv->assoc_freq = 0;
- if (params->bg_scan_period >= 0) {
- wpa_printf(MSG_DEBUG, " * bg scan period=%d",
- params->bg_scan_period);
- NLA_PUT_U16(msg, NL80211_ATTR_BG_SCAN_PERIOD,
- params->bg_scan_period);
- }
- if (params->ssid) {
- wpa_hexdump_ascii(MSG_DEBUG, " * SSID",
- params->ssid, params->ssid_len);
- NLA_PUT(msg, NL80211_ATTR_SSID, params->ssid_len,
- params->ssid);
- if (params->ssid_len > sizeof(drv->ssid))
- goto nla_put_failure;
- os_memcpy(drv->ssid, params->ssid, params->ssid_len);
- drv->ssid_len = params->ssid_len;
- }
- wpa_hexdump(MSG_DEBUG, " * IEs", params->wpa_ie, params->wpa_ie_len);
- if (params->wpa_ie)
- NLA_PUT(msg, NL80211_ATTR_IE, params->wpa_ie_len,
- params->wpa_ie);
-
- if (params->pairwise_suite != CIPHER_NONE) {
- int cipher;
-
- switch (params->pairwise_suite) {
- case CIPHER_WEP40:
- cipher = WLAN_CIPHER_SUITE_WEP40;
- break;
- case CIPHER_WEP104:
- cipher = WLAN_CIPHER_SUITE_WEP104;
- break;
- case CIPHER_CCMP:
- cipher = WLAN_CIPHER_SUITE_CCMP;
- break;
- case CIPHER_GCMP:
- cipher = WLAN_CIPHER_SUITE_GCMP;
- break;
- case CIPHER_TKIP:
- default:
- cipher = WLAN_CIPHER_SUITE_TKIP;
- break;
- }
- wpa_printf(MSG_DEBUG, " * pairwise=0x%x", cipher);
- NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, cipher);
- }
-
- if (params->group_suite != CIPHER_NONE) {
- int cipher;
-
- switch (params->group_suite) {
- case CIPHER_WEP40:
- cipher = WLAN_CIPHER_SUITE_WEP40;
- break;
- case CIPHER_WEP104:
- cipher = WLAN_CIPHER_SUITE_WEP104;
- break;
- case CIPHER_CCMP:
- cipher = WLAN_CIPHER_SUITE_CCMP;
- break;
- case CIPHER_GCMP:
- cipher = WLAN_CIPHER_SUITE_GCMP;
- break;
- case CIPHER_TKIP:
- default:
- cipher = WLAN_CIPHER_SUITE_TKIP;
- break;
- }
- wpa_printf(MSG_DEBUG, " * group=0x%x", cipher);
- NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, cipher);
- }
-
-#ifdef CONFIG_IEEE80211W
- if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED)
- NLA_PUT_U32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED);
-#endif /* CONFIG_IEEE80211W */
-
- NLA_PUT_FLAG(msg, NL80211_ATTR_CONTROL_PORT);
+ ret = nl80211_connect_common(drv, params, msg);
+ if (ret)
+ goto nla_put_failure;
if (params->prev_bssid) {
wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
@@ -8392,33 +8478,6 @@
params->prev_bssid);
}
- if (params->disable_ht)
- NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_HT);
-
- if (params->htcaps && params->htcaps_mask) {
- int sz = sizeof(struct ieee80211_ht_capabilities);
- NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY, sz, params->htcaps);
- NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK, sz,
- params->htcaps_mask);
- }
-
-#ifdef CONFIG_VHT_OVERRIDES
- if (params->disable_vht) {
- wpa_printf(MSG_DEBUG, " * VHT disabled");
- NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
- }
-
- if (params->vhtcaps && params->vhtcaps_mask) {
- int sz = sizeof(struct ieee80211_vht_capabilities);
- NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
- NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
- params->vhtcaps_mask);
- }
-#endif /* CONFIG_VHT_OVERRIDES */
-
- if (params->p2p)
- wpa_printf(MSG_DEBUG, " * P2P group");
-
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
@@ -8593,8 +8652,9 @@
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
- wpa_printf(MSG_DEBUG, "%s: operstate %d->%d (%s)",
- __func__, drv->operstate, state, state ? "UP" : "DORMANT");
+ wpa_printf(MSG_DEBUG, "nl80211: Set %s operstate %d->%d (%s)",
+ bss->ifname, drv->operstate, state,
+ state ? "UP" : "DORMANT");
drv->operstate = state;
return netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, -1,
state ? IF_OPER_UP : IF_OPER_DORMANT);
@@ -8607,6 +8667,12 @@
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
struct nl80211_sta_flag_update upd;
+ int ret = -ENOBUFS;
+
+ if (!drv->associated && is_zero_ether_addr(drv->bssid) && !authorized) {
+ wpa_printf(MSG_DEBUG, "nl80211: Skip set_supp_port(unauthorized) while not associated");
+ return 0;
+ }
wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
@@ -8627,10 +8693,15 @@
upd.set = BIT(NL80211_STA_FLAG_AUTHORIZED);
NLA_PUT(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd);
- return send_and_recv_msgs(drv, msg, NULL, NULL);
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (!ret)
+ return 0;
nla_put_failure:
nlmsg_free(msg);
- return -ENOBUFS;
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)",
+ ret, strerror(-ret));
+ return ret;
}
@@ -10209,6 +10280,18 @@
}
#endif /* CONFIG_P2P */
+ if (os_strstr(param, "use_monitor=1")) {
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ drv->use_monitor = 1;
+ }
+
+ if (os_strstr(param, "force_connect_cmd=1")) {
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
+ }
+
return 0;
}
@@ -11321,7 +11404,7 @@
settings->freq_params.center_freq1,
settings->freq_params.center_freq2);
- if (!drv->channel_switch_supported) {
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_AP_CSA)) {
wpa_printf(MSG_DEBUG, "nl80211: Driver does not support channel switch command");
return -EOPNOTSUPP;
}
@@ -11397,6 +11480,37 @@
}
+static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set,
+ u8 qos_map_set_len)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ wpa_hexdump(MSG_DEBUG, "nl80211: Setting QoS Map",
+ qos_map_set, qos_map_set_len);
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_QOS_MAP);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+ NLA_PUT(msg, NL80211_ATTR_QOS_MAP, qos_map_set_len, qos_map_set);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret)
+ wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed");
+
+ return ret;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@@ -11485,4 +11599,5 @@
#ifdef ANDROID
.driver_cmd = wpa_driver_nl80211_driver_cmd,
#endif /* ANDROID */
+ .set_qos_map = nl80211_set_qos_map,
};
diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c
index 5742b98..7d30655 100644
--- a/src/drivers/driver_test.c
+++ b/src/drivers/driver_test.c
@@ -28,7 +28,6 @@
#include "common/ieee802_11_defs.h"
#include "crypto/sha1.h"
#include "l2_packet/l2_packet.h"
-#include "p2p/p2p.h"
#include "wps/wps.h"
#include "driver.h"
@@ -102,20 +101,6 @@
unsigned int remain_on_channel_duration;
int current_freq;
-
- struct p2p_data *p2p;
- unsigned int off_channel_freq;
- struct wpabuf *pending_action_tx;
- u8 pending_action_src[ETH_ALEN];
- 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;
- struct sockaddr *probe_from;
- socklen_t probe_from_len;
};
@@ -125,7 +110,6 @@
static void wpa_driver_test_close_test_socket(
struct wpa_driver_test_data *drv);
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx);
-static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv);
static void test_driver_free_bss(struct test_driver_bss *bss)
@@ -479,34 +463,6 @@
event.tx_status.ack = ret >= 0;
wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event);
-#ifdef CONFIG_P2P
- if (drv->p2p &&
- WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
- WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
- if (drv->pending_action_tx == NULL) {
- wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - "
- "no pending operation");
- return ret;
- }
-
- if (os_memcmp(hdr->addr1, drv->pending_action_dst, ETH_ALEN) !=
- 0) {
- wpa_printf(MSG_DEBUG, "P2P: Ignore Action TX status - "
- "unknown destination address");
- return ret;
- }
-
- wpabuf_free(drv->pending_action_tx);
- drv->pending_action_tx = NULL;
-
- p2p_send_action_cb(drv->p2p, drv->pending_action_freq,
- drv->pending_action_dst,
- drv->pending_action_src,
- drv->pending_action_bssid,
- ret >= 0);
- }
-#endif /* CONFIG_P2P */
-
return ret;
}
@@ -553,10 +509,6 @@
event.rx_probe_req.ie = ie;
event.rx_probe_req.ie_len = ielen;
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event);
-#ifdef CONFIG_P2P
- if (drv->p2p)
- p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
-#endif /* CONFIG_P2P */
}
dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) {
@@ -1313,25 +1265,7 @@
static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx)
{
- struct wpa_driver_test_data *drv = eloop_ctx;
wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
- if (drv->pending_p2p_scan && drv->p2p) {
-#ifdef CONFIG_P2P
- size_t i;
- struct os_time now;
- os_get_time(&now);
- for (i = 0; i < drv->num_scanres; i++) {
- struct wpa_scan_res *bss = drv->scanres[i];
- if (p2p_scan_res_handler(drv->p2p, bss->bssid,
- bss->freq, &now, bss->level,
- (const u8 *) (bss + 1),
- bss->ie_len) > 0)
- return;
- }
- p2p_scan_res_handled(drv->p2p);
-#endif /* CONFIG_P2P */
- return;
- }
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
}
@@ -1949,30 +1883,8 @@
data_len - (mgmt->u.probe_req.variable - data);
wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ,
&event);
-#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 */
}
}
-
-#ifdef CONFIG_P2P
- if (drv->p2p &&
- WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
- WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
- size_t hdr_len;
- hdr_len = (const u8 *)
- &mgmt->u.action.u.vs_public_action.action - data;
- p2p_rx_action(drv->p2p, mgmt->da, mgmt->sa, mgmt->bssid,
- mgmt->u.action.category,
- &mgmt->u.action.u.vs_public_action.action,
- data_len - hdr_len, freq);
- }
-#endif /* CONFIG_P2P */
-
}
@@ -1988,29 +1900,6 @@
bss = dl_list_first(&drv->bss, struct test_driver_bss, list);
/* data: optional [ STA-addr | ' ' | IEs(hex) ] */
-#ifdef CONFIG_P2P
- if (drv->probe_req_report && drv->p2p && data_len) {
- const char *d = (const char *) data;
- u8 sa[ETH_ALEN];
- u8 ie[512];
- size_t ielen;
-
- if (hwaddr_aton(d, sa))
- return;
- d += 18;
- while (*d == ' ')
- d++;
- ielen = os_strlen(d) / 2;
- if (ielen > sizeof(ie))
- ielen = sizeof(ie);
- if (hexstr2bin(d, ie, ielen) < 0)
- ielen = 0;
- drv->probe_from = from;
- drv->probe_from_len = fromlen;
- p2p_probe_req_rx(drv->p2p, sa, NULL, NULL, ie, ielen);
- drv->probe_from = NULL;
- }
-#endif /* CONFIG_P2P */
if (!drv->ibss)
return;
@@ -2167,12 +2056,6 @@
struct test_client_socket *cli, *prev;
int i;
-#ifdef CONFIG_P2P
- if (drv->p2p)
- p2p_deinit(drv->p2p);
- wpabuf_free(drv->pending_action_tx);
-#endif /* CONFIG_P2P */
-
cli = drv->cli;
while (cli) {
prev = cli;
@@ -2369,13 +2252,6 @@
drv->use_associnfo = 1;
}
- if (os_strstr(param, "p2p_mgmt=1")) {
- wpa_printf(MSG_DEBUG, "test_driver: Use internal P2P "
- "management");
- if (wpa_driver_test_init_p2p(drv) < 0)
- return -1;
- }
-
return 0;
}
@@ -2465,8 +2341,6 @@
static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa)
{
- struct test_driver_bss *dbss = priv;
- struct wpa_driver_test_data *drv = dbss->drv;
os_memset(capa, 0, sizeof(*capa));
capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
@@ -2482,8 +2356,6 @@
capa->auth = WPA_DRIVER_AUTH_OPEN |
WPA_DRIVER_AUTH_SHARED |
WPA_DRIVER_AUTH_LEAP;
- if (drv->p2p)
- capa->flags |= WPA_DRIVER_FLAGS_P2P_MGMT;
capa->flags |= WPA_DRIVER_FLAGS_AP;
capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
capa->flags |= WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE;
@@ -2691,33 +2563,6 @@
}
-#ifdef CONFIG_P2P
-static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx)
-{
- struct wpa_driver_test_data *drv = eloop_ctx;
-
- if (drv->pending_action_tx == NULL)
- return;
-
- if (drv->off_channel_freq != drv->pending_action_freq) {
- wpa_printf(MSG_DEBUG, "P2P: Pending Action frame TX "
- "waiting for another freq=%u",
- drv->pending_action_freq);
- return;
- }
- wpa_printf(MSG_DEBUG, "P2P: Sending pending Action frame to "
- MACSTR, MAC2STR(drv->pending_action_dst));
- 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 */
-
-
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_test_data *drv = eloop_ctx;
@@ -2729,9 +2574,6 @@
data.remain_on_channel.freq = drv->remain_on_channel_freq;
data.remain_on_channel.duration = drv->remain_on_channel_duration;
- if (drv->p2p)
- drv->off_channel_freq = 0;
-
drv->remain_on_channel_freq = 0;
wpa_supplicant_event(drv->ctx, EVENT_CANCEL_REMAIN_ON_CHANNEL, &data);
@@ -2765,18 +2607,6 @@
data.remain_on_channel.duration = duration;
wpa_supplicant_event(drv->ctx, EVENT_REMAIN_ON_CHANNEL, &data);
-#ifdef CONFIG_P2P
- if (drv->p2p) {
- drv->off_channel_freq = drv->remain_on_channel_freq;
- test_send_action_cb(drv, NULL);
- if (drv->off_channel_freq == drv->pending_listen_freq) {
- p2p_listen_cb(drv->p2p, drv->pending_listen_freq,
- drv->pending_listen_duration);
- drv->pending_listen_freq = 0;
- }
- }
-#endif /* CONFIG_P2P */
-
return 0;
}
@@ -2804,470 +2634,6 @@
}
-#ifdef CONFIG_P2P
-
-static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type)
-{
- struct test_driver_bss *dbss = priv;
- struct wpa_driver_test_data *drv = dbss->drv;
- wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout);
- if (!drv->p2p)
- return -1;
- return p2p_find(drv->p2p, timeout, type, 0, NULL, NULL, 0);
-}
-
-
-static int wpa_driver_test_p2p_stop_find(void *priv)
-{
- struct test_driver_bss *dbss = priv;
- struct wpa_driver_test_data *drv = dbss->drv;
- wpa_printf(MSG_DEBUG, "%s", __func__);
- if (!drv->p2p)
- return -1;
- p2p_stop_find(drv->p2p);
- return 0;
-}
-
-
-static int wpa_driver_test_p2p_listen(void *priv, unsigned int timeout)
-{
- struct test_driver_bss *dbss = priv;
- struct wpa_driver_test_data *drv = dbss->drv;
- wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout);
- if (!drv->p2p)
- return -1;
- return p2p_listen(drv->p2p, timeout);
-}
-
-
-static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr,
- int wps_method, int go_intent,
- const u8 *own_interface_addr,
- unsigned int force_freq,
- int persistent_group)
-{
- struct test_driver_bss *dbss = priv;
- struct wpa_driver_test_data *drv = dbss->drv;
- wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR " wps_method=%d "
- "go_intent=%d "
- "own_interface_addr=" MACSTR " force_freq=%u "
- "persistent_group=%d)",
- __func__, MAC2STR(peer_addr), wps_method, go_intent,
- MAC2STR(own_interface_addr), force_freq, persistent_group);
- if (!drv->p2p)
- return -1;
- return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent,
- own_interface_addr, force_freq, persistent_group,
- NULL, 0, 0, 0);
-}
-
-
-static int wpa_driver_test_wps_success_cb(void *priv, const u8 *peer_addr)
-{
- struct test_driver_bss *dbss = priv;
- struct wpa_driver_test_data *drv = dbss->drv;
- wpa_printf(MSG_DEBUG, "%s(peer_addr=" MACSTR ")",
- __func__, MAC2STR(peer_addr));
- if (!drv->p2p)
- return -1;
- p2p_wps_success_cb(drv->p2p, peer_addr);
- return 0;
-}
-
-
-static int wpa_driver_test_p2p_group_formation_failed(void *priv)
-{
- struct test_driver_bss *dbss = priv;
- struct wpa_driver_test_data *drv = dbss->drv;
- wpa_printf(MSG_DEBUG, "%s", __func__);
- if (!drv->p2p)
- return -1;
- p2p_group_formation_failed(drv->p2p);
- return 0;
-}
-
-
-static int wpa_driver_test_p2p_set_params(void *priv,
- const struct p2p_params *params)
-{
- struct test_driver_bss *dbss = priv;
- struct wpa_driver_test_data *drv = dbss->drv;
- wpa_printf(MSG_DEBUG, "%s", __func__);
- if (!drv->p2p)
- return -1;
- if (p2p_set_dev_name(drv->p2p, params->dev_name) < 0 ||
- p2p_set_pri_dev_type(drv->p2p, params->pri_dev_type) < 0 ||
- p2p_set_sec_dev_types(drv->p2p, params->sec_dev_type,
- params->num_sec_dev_types) < 0)
- return -1;
- return 0;
-}
-
-
-static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
- unsigned int num_req_dev_types,
- const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
-{
- struct wpa_driver_test_data *drv = ctx;
- struct wpa_driver_scan_params params;
- 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);
-
- os_memset(¶ms, 0, sizeof(params));
-
- /* P2P Wildcard SSID */
- params.num_ssids = 1;
- params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
- params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
-
-#if 0 /* TODO: WPS IE */
- wpa_s->wps->dev.p2p = 1;
- wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
- wpa_s->wps->uuid, WPS_REQ_ENROLLEE);
-#else
- wps_ie = wpabuf_alloc(1);
-#endif
- if (wps_ie == NULL)
- return -1;
-
- 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;
- }
- wpabuf_put_buf(ies, wps_ie);
- wpabuf_free(wps_ie);
-
- p2p_scan_ie(drv->p2p, ies, dev_id);
-
- params.extra_ies = wpabuf_head(ies);
- params.extra_ies_len = wpabuf_len(ies);
-
- switch (type) {
- case P2P_SCAN_SOCIAL:
- params.freqs = social_channels;
- break;
- case P2P_SCAN_FULL:
- break;
- case P2P_SCAN_SOCIAL_PLUS_ONE:
- social_channels[3] = freq;
- params.freqs = social_channels;
- break;
- }
-
- drv->pending_p2p_scan = 1;
- ret = wpa_driver_test_scan(drv, ¶ms);
-
- wpabuf_free(ies);
-
- return ret;
-}
-
-
-static int test_send_action(void *ctx, unsigned int freq, const u8 *dst,
- const u8 *src, const u8 *bssid, const u8 *buf,
- size_t len, unsigned int wait_time)
-{
- struct wpa_driver_test_data *drv = ctx;
-
- wpa_printf(MSG_DEBUG, "%s(freq=%u dst=" MACSTR " src=" MACSTR
- " bssid=" MACSTR " len=%d",
- __func__, freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid),
- (int) len);
- if (freq <= 0) {
- wpa_printf(MSG_WARNING, "P2P: No frequency specified for "
- "action frame TX");
- return -1;
- }
-
- if (drv->pending_action_tx) {
- wpa_printf(MSG_DEBUG, "P2P: Dropped pending Action frame TX "
- "to " MACSTR, MAC2STR(drv->pending_action_dst));
- wpabuf_free(drv->pending_action_tx);
- }
- drv->pending_action_tx = wpabuf_alloc(len);
- if (drv->pending_action_tx == NULL)
- return -1;
- wpabuf_put_data(drv->pending_action_tx, buf, len);
- os_memcpy(drv->pending_action_src, src, ETH_ALEN);
- 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 */
- /* TODO: Would there ever be need to extend the current
- * duration on the channel? */
- eloop_cancel_timeout(test_send_action_cb, drv, NULL);
- eloop_register_timeout(0, 0, test_send_action_cb, drv, NULL);
- return 0;
- }
-
- wpa_printf(MSG_DEBUG, "P2P: Schedule Action frame to be transmitted "
- "once the driver gets to the requested channel");
- if (wpa_driver_test_remain_on_channel(drv, freq, wait_time) < 0) {
- wpa_printf(MSG_DEBUG, "P2P: Failed to request driver "
- "to remain on channel (%u MHz) for Action "
- "Frame TX", freq);
- return -1;
- }
-
- return 0;
-}
-
-
-static void test_send_action_done(void *ctx)
-{
- wpa_printf(MSG_DEBUG, "%s", __func__);
- /* TODO */
-}
-
-
-static void test_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
-{
- struct wpa_driver_test_data *drv = ctx;
- union wpa_event_data event;
- wpa_printf(MSG_DEBUG, "%s", __func__);
- os_memset(&event, 0, sizeof(event));
- event.p2p_go_neg_completed.res = res;
- wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_COMPLETED, &event);
-}
-
-
-static void test_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
-{
- struct wpa_driver_test_data *drv = ctx;
- union wpa_event_data event;
- wpa_printf(MSG_DEBUG, "%s(src=" MACSTR ")", __func__, MAC2STR(src));
- os_memset(&event, 0, sizeof(event));
- event.p2p_go_neg_req_rx.src = src;
- event.p2p_go_neg_req_rx.dev_passwd_id = dev_passwd_id;
- wpa_supplicant_event(drv->ctx, EVENT_P2P_GO_NEG_REQ_RX, &event);
-}
-
-
-static void test_dev_found(void *ctx, const u8 *addr,
- const struct p2p_peer_info *info, int new_device)
-{
- struct wpa_driver_test_data *drv = ctx;
- union wpa_event_data event;
- char devtype[WPS_DEV_TYPE_BUFSIZE];
- wpa_printf(MSG_DEBUG, "%s(" MACSTR " p2p_dev_addr=" MACSTR
- " pri_dev_type=%s name='%s' config_methods=0x%x "
- "dev_capab=0x%x group_capab=0x%x)",
- __func__, MAC2STR(addr), MAC2STR(info->p2p_device_addr),
- wps_dev_type_bin2str(info->pri_dev_type, devtype,
- sizeof(devtype)),
- info->device_name, info->config_methods, info->dev_capab,
- info->group_capab);
-
- os_memset(&event, 0, sizeof(event));
- event.p2p_dev_found.addr = addr;
- event.p2p_dev_found.dev_addr = info->p2p_device_addr;
- event.p2p_dev_found.pri_dev_type = info->pri_dev_type;
- event.p2p_dev_found.dev_name = info->device_name;
- event.p2p_dev_found.config_methods = info->config_methods;
- event.p2p_dev_found.dev_capab = info->dev_capab;
- event.p2p_dev_found.group_capab = info->group_capab;
- wpa_supplicant_event(drv->ctx, EVENT_P2P_DEV_FOUND, &event);
-}
-
-
-static int test_start_listen(void *ctx, unsigned int freq,
- unsigned int duration,
- const struct wpabuf *probe_resp_ie)
-{
- struct wpa_driver_test_data *drv = ctx;
-
- wpa_printf(MSG_DEBUG, "%s(freq=%u duration=%u)",
- __func__, freq, duration);
-
- if (wpa_driver_test_probe_req_report(drv, 1) < 0)
- return -1;
-
- drv->pending_listen_freq = freq;
- drv->pending_listen_duration = duration;
-
- if (wpa_driver_test_remain_on_channel(drv, freq, duration) < 0) {
- drv->pending_listen_freq = 0;
- return -1;
- }
-
- return 0;
-}
-
-
-static void test_stop_listen(void *ctx)
-{
- wpa_printf(MSG_DEBUG, "%s", __func__);
- /* TODO */
-}
-
-
-static int test_send_probe_resp(void *ctx, const struct wpabuf *buf)
-{
- struct wpa_driver_test_data *drv = ctx;
- char resp[512], *pos, *end;
- int ret;
- const struct ieee80211_mgmt *mgmt;
- const u8 *ie, *ie_end;
-
- wpa_printf(MSG_DEBUG, "%s", __func__);
- wpa_hexdump_buf(MSG_MSGDUMP, "Probe Response", buf);
- if (wpabuf_len(buf) < 24)
- return -1;
- if (!drv->probe_from) {
- wpa_printf(MSG_DEBUG, "%s: probe_from not set", __func__);
- return -1;
- }
-
- pos = resp;
- end = resp + sizeof(resp);
-
- mgmt = wpabuf_head(buf);
-
- /* reply: SCANRESP BSSID SSID IEs */
- ret = os_snprintf(pos, end - pos, "SCANRESP " MACSTR " ",
- MAC2STR(mgmt->bssid));
- if (ret < 0 || ret >= end - pos)
- return -1;
- pos += ret;
-
- ie = mgmt->u.probe_resp.variable;
- ie_end = wpabuf_head_u8(buf) + wpabuf_len(buf);
- if (ie_end - ie < 2 || ie[0] != WLAN_EID_SSID ||
- ie + 2 + ie[1] > ie_end)
- return -1;
- pos += wpa_snprintf_hex(pos, end - pos, ie + 2, ie[1]);
-
- ret = os_snprintf(pos, end - pos, " ");
- if (ret < 0 || ret >= end - pos)
- return -1;
- pos += ret;
- pos += wpa_snprintf_hex(pos, end - pos, ie, ie_end - ie);
-
- sendto(drv->test_socket, resp, pos - resp, 0,
- drv->probe_from, drv->probe_from_len);
-
- return 0;
-}
-
-
-static void test_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
- u16 update_indic, const u8 *tlvs, size_t tlvs_len)
-{
- wpa_printf(MSG_DEBUG, "%s", __func__);
- /* TODO */
-}
-
-
-static void test_sd_response(void *ctx, const u8 *sa, u16 update_indic,
- const u8 *tlvs, size_t tlvs_len)
-{
- wpa_printf(MSG_DEBUG, "%s", __func__);
- /* TODO */
-}
-
-
-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,
- 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);
- /* TODO */
-}
-
-
-static void test_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
-{
- wpa_printf(MSG_DEBUG, "%s(peer=" MACSTR " config_methods=0x%x)",
- __func__, MAC2STR(peer), config_methods);
- /* TODO */
-}
-
-
-static void test_p2p_debug_print(void *ctx, int level, const char *msg)
-{
- wpa_printf(level, "P2P: %s", msg);
-}
-
-#endif /* CONFIG_P2P */
-
-
-static int wpa_driver_test_init_p2p(struct wpa_driver_test_data *drv)
-{
-#ifdef CONFIG_P2P
- struct p2p_config p2p;
- unsigned int r;
- int i;
-
- os_memset(&p2p, 0, sizeof(p2p));
- p2p.cb_ctx = drv;
- p2p.debug_print = test_p2p_debug_print;
- p2p.p2p_scan = test_p2p_scan;
- p2p.send_action = test_send_action;
- p2p.send_action_done = test_send_action_done;
- p2p.go_neg_completed = test_go_neg_completed;
- p2p.go_neg_req_rx = test_go_neg_req_rx;
- p2p.dev_found = test_dev_found;
- p2p.start_listen = test_start_listen;
- p2p.stop_listen = test_stop_listen;
- p2p.send_probe_resp = test_send_probe_resp;
- p2p.sd_request = test_sd_request;
- p2p.sd_response = test_sd_response;
- p2p.prov_disc_req = test_prov_disc_req;
- p2p.prov_disc_resp = test_prov_disc_resp;
-
- os_memcpy(p2p.dev_addr, drv->own_addr, ETH_ALEN);
-
- p2p.reg_class = 12; /* TODO: change depending on location */
- /*
- * Pick one of the social channels randomly as the listen
- * channel.
- */
- os_get_random((u8 *) &r, sizeof(r));
- p2p.channel = 1 + (r % 3) * 5;
-
- /* TODO: change depending on location */
- p2p.op_reg_class = 12;
- /*
- * For initial tests, pick the operation channel randomly.
- * TODO: Use scan results (etc.) to select the best channel.
- */
- p2p.op_channel = 1 + r % 11;
-
- os_memcpy(p2p.country, "US ", 3);
-
- /* FIX: fetch available channels from the driver */
- p2p.channels.reg_classes = 1;
- p2p.channels.reg_class[0].reg_class = 12; /* US/12 = 2.4 GHz band */
- p2p.channels.reg_class[0].channels = 11;
- for (i = 0; i < 11; i++)
- p2p.channels.reg_class[0].channel[i] = i + 1;
-
- p2p.max_peers = 100;
-
- drv->p2p = p2p_init(&p2p);
- if (drv->p2p == NULL)
- return -1;
- return 0;
-#else /* CONFIG_P2P */
- wpa_printf(MSG_INFO, "driver_test: P2P support not included");
- return -1;
-#endif /* CONFIG_P2P */
-}
-
-
const struct wpa_driver_ops wpa_driver_test_ops = {
"test",
"wpa_supplicant test driver",
@@ -3309,14 +2675,4 @@
.remain_on_channel = wpa_driver_test_remain_on_channel,
.cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel,
.probe_req_report = wpa_driver_test_probe_req_report,
-#ifdef CONFIG_P2P
- .p2p_find = wpa_driver_test_p2p_find,
- .p2p_stop_find = wpa_driver_test_p2p_stop_find,
- .p2p_listen = wpa_driver_test_p2p_listen,
- .p2p_connect = wpa_driver_test_p2p_connect,
- .wps_success_cb = wpa_driver_test_wps_success_cb,
- .p2p_group_formation_failed =
- wpa_driver_test_p2p_group_formation_failed,
- .p2p_set_params = wpa_driver_test_p2p_set_params,
-#endif /* CONFIG_P2P */
};
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 6e2e771..e5734bd 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -31,10 +31,6 @@
#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);
static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv);
@@ -299,14 +295,6 @@
}
wpa_supplicant_event(ctx, EVENT_STKSTART, &data);
#endif /* CONFIG_PEERKEY */
-#ifdef ANDROID
- } else if (os_strncmp(custom, "STOP", 4) == 0) {
- wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
- } else if (os_strncmp(custom, "START", 5) == 0) {
- wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
- } else if (os_strncmp(custom, "HANG", 4) == 0) {
- wpa_msg(ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
-#endif /* ANDROID */
}
}
@@ -858,12 +846,6 @@
drv->mlme_sock = -1;
-#ifdef ANDROID
- drv->errors = 0;
- drv->driver_is_started = TRUE;
- drv->bgscan_enabled = 0;
-#endif /* ANDROID */
-
if (wpa_driver_wext_finish_drv_init(drv) < 0)
goto err3;
@@ -1869,10 +1851,8 @@
{
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,
@@ -1893,7 +1873,6 @@
"selection on disconnect");
}
-#ifndef ANDROID
if (drv->cfg80211) {
/*
* cfg80211 supports SIOCSIWMLME commands, so there is
@@ -1919,7 +1898,6 @@
wpa_printf(MSG_DEBUG, "WEXT: Failed to set bogus "
"SSID to disconnect");
}
-#endif /* ANDROID */
}
}
@@ -1960,15 +1938,15 @@
int wpa_driver_wext_cipher2wext(int cipher)
{
switch (cipher) {
- case CIPHER_NONE:
+ case WPA_CIPHER_NONE:
return IW_AUTH_CIPHER_NONE;
- case CIPHER_WEP40:
+ case WPA_CIPHER_WEP40:
return IW_AUTH_CIPHER_WEP40;
- case CIPHER_TKIP:
+ case WPA_CIPHER_TKIP:
return IW_AUTH_CIPHER_TKIP;
- case CIPHER_CCMP:
+ case WPA_CIPHER_CCMP:
return IW_AUTH_CIPHER_CCMP;
- case CIPHER_WEP104:
+ case WPA_CIPHER_WEP104:
return IW_AUTH_CIPHER_WEP104;
default:
return 0;
@@ -1979,10 +1957,10 @@
int wpa_driver_wext_keymgmt2wext(int keymgmt)
{
switch (keymgmt) {
- case KEY_MGMT_802_1X:
- case KEY_MGMT_802_1X_NO_WPA:
+ case WPA_KEY_MGMT_IEEE8021X:
+ case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
return IW_AUTH_KEY_MGMT_802_1X;
- case KEY_MGMT_PSK:
+ case WPA_KEY_MGMT_PSK:
return IW_AUTH_KEY_MGMT_PSK;
default:
return 0;
@@ -2099,9 +2077,9 @@
if (wpa_driver_wext_set_auth_param(drv,
IW_AUTH_KEY_MGMT, value) < 0)
ret = -1;
- value = params->key_mgmt_suite != KEY_MGMT_NONE ||
- params->pairwise_suite != CIPHER_NONE ||
- params->group_suite != CIPHER_NONE ||
+ value = params->key_mgmt_suite != WPA_KEY_MGMT_NONE ||
+ params->pairwise_suite != WPA_CIPHER_NONE ||
+ params->group_suite != WPA_CIPHER_NONE ||
params->wpa_ie_len;
if (wpa_driver_wext_set_auth_param(drv,
IW_AUTH_PRIVACY_INVOKED, value) < 0)
@@ -2110,8 +2088,8 @@
/* 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)
+ if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
+ params->key_mgmt_suite == WPA_KEY_MGMT_PSK)
allow_unencrypted_eapol = 0;
else
allow_unencrypted_eapol = 1;
@@ -2338,129 +2316,6 @@
}
-#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_strlcpy(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)",
@@ -2480,8 +2335,4 @@
.get_capa = wpa_driver_wext_get_capa,
.set_operstate = wpa_driver_wext_set_operstate,
.get_radio_name = wext_get_radio_name,
-#ifdef ANDROID
- .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 c4a5bc9..b4b5960 100644
--- a/src/drivers/driver_wext.h
+++ b/src/drivers/driver_wext.h
@@ -44,12 +44,6 @@
int cfg80211; /* whether driver is using cfg80211 */
u8 max_level;
-
-#ifdef ANDROID
- int errors;
- int driver_is_started;
- int bgscan_enabled;
-#endif /* ANDROID */
};
int wpa_driver_wext_get_bssid(void *priv, u8 *bssid);
diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
index 04eb4fd..446ab63 100644
--- a/src/drivers/drivers.c
+++ b/src/drivers/drivers.c
@@ -6,8 +6,9 @@
* See README for more details.
*/
-#include "includes.h"
-
+#include "utils/includes.h"
+#include "utils/common.h"
+#include "driver.h"
#ifdef CONFIG_DRIVER_WEXT
extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
diff --git a/src/drivers/netlink.c b/src/drivers/netlink.c
index 6c60550..2fa20b1 100644
--- a/src/drivers/netlink.c
+++ b/src/drivers/netlink.c
@@ -1,6 +1,6 @@
/*
* Netlink helper functions for driver wrappers
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -137,6 +137,35 @@
os_free(netlink);
}
+
+static const char * linkmode_str(int mode)
+{
+ switch (mode) {
+ case -1:
+ return "no change";
+ case 0:
+ return "kernel-control";
+ case 1:
+ return "userspace-control";
+ }
+ return "?";
+}
+
+
+static const char * operstate_str(int state)
+{
+ switch (state) {
+ case -1:
+ return "no change";
+ case IF_OPER_DORMANT:
+ return "IF_OPER_DORMANT";
+ case IF_OPER_UP:
+ return "IF_OPER_UP";
+ }
+ return "?";
+}
+
+
int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex,
int linkmode, int operstate)
{
@@ -184,8 +213,9 @@
RTA_LENGTH(sizeof(char));
}
- wpa_printf(MSG_DEBUG, "netlink: Operstate: linkmode=%d, operstate=%d",
- linkmode, operstate);
+ wpa_printf(MSG_DEBUG, "netlink: Operstate: ifindex=%d linkmode=%d (%s), operstate=%d (%s)",
+ ifindex, linkmode, linkmode_str(linkmode),
+ operstate, operstate_str(operstate));
ret = send(netlink->sock, &req, req.hdr.nlmsg_len, 0);
if (ret < 0) {
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index f752e98..91054fd 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -581,7 +581,14 @@
* operation, %NL80211_ATTR_MAC contains the peer MAC address, and
* %NL80211_ATTR_REASON_CODE the reason code to be used (only with
* %NL80211_TDLS_TEARDOWN).
- * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
+ * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. The
+ * %NL80211_ATTR_TDLS_ACTION attribute determines the type of frame to be
+ * sent. Public Action codes (802.11-2012 8.1.5.1) will be sent as
+ * 802.11 management frames, while TDLS action codes (802.11-2012
+ * 8.5.13.1) will be encapsulated and sent as data frames. The currently
+ * supported Public Action code is %WLAN_PUB_ACTION_TDLS_DISCOVER_RES
+ * and the currently supported TDLS actions codes are given in
+ * &enum ieee80211_tdls_actioncode.
*
* @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
* (or GO) interface (i.e. hostapd) to ask for unexpected frames to
@@ -686,6 +693,21 @@
* other station that transmission must be blocked until the channel
* switch is complete.
*
+ * @NL80211_CMD_VENDOR: Vendor-specified command/event. The command is specified
+ * by the %NL80211_ATTR_VENDOR_ID attribute and a sub-command in
+ * %NL80211_ATTR_VENDOR_SUBCMD. Parameter(s) can be transported in
+ * %NL80211_ATTR_VENDOR_DATA.
+ * For feature advertisement, the %NL80211_ATTR_VENDOR_DATA attribute is
+ * used in the wiphy data as a nested attribute containing descriptions
+ * (&struct nl80211_vendor_cmd_info) of the supported vendor commands.
+ * This may also be sent as an event with the same attributes.
+ *
+ * @NL80211_CMD_SET_QOS_MAP: Set Interworking QoS mapping for IP DSCP values.
+ * The QoS mapping information is included in %NL80211_ATTR_QOS_MAP. If
+ * that attribute is not included, QoS mapping is disabled. Since this
+ * QoS mapping is relevant for IP packets, it is only valid during an
+ * association. This is cleared on disassociation and AP restart.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -853,6 +875,10 @@
NL80211_CMD_CHANNEL_SWITCH,
+ NL80211_CMD_VENDOR,
+
+ NL80211_CMD_SET_QOS_MAP,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1508,6 +1534,27 @@
* to react to radar events, e.g. initiate a channel switch or leave the
* IBSS network.
*
+ * @NL80211_ATTR_SUPPORT_5_MHZ: A flag indicating that the device supports
+ * 5 MHz channel bandwidth.
+ * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports
+ * 10 MHz channel bandwidth.
+ *
+ * @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode
+ * Notification Element based on association request when used with
+ * %NL80211_CMD_NEW_STATION; u8 attribute.
+ *
+ * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if
+ * %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet)
+ * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command
+ * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this
+ * attribute is also used for vendor command feature advertisement
+ * @NL80211_ATTR_VENDOR_EVENTS: used for event list advertising in the wiphy
+ * info, containing a nested array of possible events
+ *
+ * @NL80211_ATTR_QOS_MAP: IP DSCP mapping for Interworking QoS mapping. This
+ * data is in the format defined for the payload of the QoS Map Set element
+ * in IEEE Std 802.11-2012, 8.4.2.97.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1824,6 +1871,18 @@
NL80211_ATTR_HANDLE_DFS,
+ NL80211_ATTR_SUPPORT_5_MHZ,
+ NL80211_ATTR_SUPPORT_10_MHZ,
+
+ NL80211_ATTR_OPMODE_NOTIF,
+
+ NL80211_ATTR_VENDOR_ID,
+ NL80211_ATTR_VENDOR_SUBCMD,
+ NL80211_ATTR_VENDOR_DATA,
+ NL80211_ATTR_VENDOR_EVENTS,
+
+ NL80211_ATTR_QOS_MAP,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -2224,10 +2283,9 @@
* @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
* @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
* regulatory domain.
- * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
- * permitted on this channel in current regulatory domain.
- * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
- * on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation
+ * are permitted on this channel, this includes sending probe
+ * requests, or modes of operation that require beaconing.
* @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
* on this channel in current regulatory domain.
* @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
@@ -2254,8 +2312,8 @@
__NL80211_FREQUENCY_ATTR_INVALID,
NL80211_FREQUENCY_ATTR_FREQ,
NL80211_FREQUENCY_ATTR_DISABLED,
- NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
- NL80211_FREQUENCY_ATTR_NO_IBSS,
+ NL80211_FREQUENCY_ATTR_NO_IR,
+ __NL80211_FREQUENCY_ATTR_NO_IBSS,
NL80211_FREQUENCY_ATTR_RADAR,
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
NL80211_FREQUENCY_ATTR_DFS_STATE,
@@ -2271,6 +2329,9 @@
};
#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER
+#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR
+#define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR
+#define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR
/**
* enum nl80211_bitrate_attr - bitrate attributes
@@ -2413,8 +2474,9 @@
* @NL80211_RRF_DFS: DFS support is required to be used
* @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
* @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
- * @NL80211_RRF_PASSIVE_SCAN: passive scan is required
- * @NL80211_RRF_NO_IBSS: no IBSS is allowed
+ * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed,
+ * this includes probe requests or modes of operation that require
+ * beaconing.
*/
enum nl80211_reg_rule_flags {
NL80211_RRF_NO_OFDM = 1<<0,
@@ -2424,10 +2486,17 @@
NL80211_RRF_DFS = 1<<4,
NL80211_RRF_PTP_ONLY = 1<<5,
NL80211_RRF_PTMP_ONLY = 1<<6,
- NL80211_RRF_PASSIVE_SCAN = 1<<7,
- NL80211_RRF_NO_IBSS = 1<<8,
+ NL80211_RRF_NO_IR = 1<<7,
+ __NL80211_RRF_NO_IBSS = 1<<8,
};
+#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
+#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR
+#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR
+
+/* For backport compatibility with older userspace */
+#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
+
/**
* enum nl80211_dfs_regions - regulatory DFS regions
*
@@ -3058,21 +3127,35 @@
* in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with
* 1 = 500 kbps) but without the IE length restriction (at most
* %NL80211_MAX_SUPP_RATES in a single array).
- * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection
+ * @NL80211_TXRATE_HT: HT (MCS) rates allowed for TX rate selection
* in an array of MCS numbers.
+ * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection,
+ * see &struct nl80211_txrate_vht
* @__NL80211_TXRATE_AFTER_LAST: internal
* @NL80211_TXRATE_MAX: highest TX rate attribute
*/
enum nl80211_tx_rate_attributes {
__NL80211_TXRATE_INVALID,
NL80211_TXRATE_LEGACY,
- NL80211_TXRATE_MCS,
+ NL80211_TXRATE_HT,
+ NL80211_TXRATE_VHT,
/* keep last */
__NL80211_TXRATE_AFTER_LAST,
NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1
};
+#define NL80211_TXRATE_MCS NL80211_TXRATE_HT
+#define NL80211_VHT_NSS_MAX 8
+
+/**
+ * struct nl80211_txrate_vht - VHT MCS/NSS txrate bitmap
+ * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.)
+ */
+struct nl80211_txrate_vht {
+ __u16 mcs[NL80211_VHT_NSS_MAX];
+};
+
/**
* enum nl80211_band - Frequency band
* @NL80211_BAND_2GHZ: 2.4 GHz ISM band
@@ -3934,4 +4017,24 @@
NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0,
};
+/*
+ * If this flag is unset, the lower 24 bits are an OUI, if set
+ * a Linux nl80211 vendor ID is used (no such IDs are allocated
+ * yet, so that's not valid so far)
+ */
+#define NL80211_VENDOR_ID_IS_LINUX 0x80000000
+
+/**
+ * struct nl80211_vendor_cmd_info - vendor command data
+ * @vendor_id: If the %NL80211_VENDOR_ID_IS_LINUX flag is clear, then the
+ * value is a 24-bit OUI; if it is set then a separately allocated ID
+ * may be used, but no such IDs are allocated yet. New IDs should be
+ * added to this file when needed.
+ * @subcmd: sub-command ID for the command
+ */
+struct nl80211_vendor_cmd_info {
+ __u32 vendor_id;
+ __u32 subcmd;
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/src/drivers/priv_netlink.h b/src/drivers/priv_netlink.h
index 74d6ce5..6232088 100644
--- a/src/drivers/priv_netlink.h
+++ b/src/drivers/priv_netlink.h
@@ -69,6 +69,7 @@
(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len)))
#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
#define RTA_DATA(rta) ((void *) (((char *) (rta)) + RTA_LENGTH(0)))
+#define RTA_PAYLOAD(rta) ((int) ((rta)->rta_len) - RTA_LENGTH(0))
struct sockaddr_nl
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 3439c2d..98abd4e 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -1,6 +1,6 @@
/*
* EAP peer state machines (RFC 4137)
- * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -388,10 +388,11 @@
sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret,
eapReqData);
wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s "
- "methodState=%s decision=%s",
+ "methodState=%s decision=%s eapRespData=%p",
ret.ignore ? "TRUE" : "FALSE",
eap_sm_method_state_txt(ret.methodState),
- eap_sm_decision_txt(ret.decision));
+ eap_sm_decision_txt(ret.decision),
+ sm->eapRespData);
sm->ignore = ret.ignore;
if (sm->ignore)
@@ -432,8 +433,10 @@
sm->lastId = sm->reqId;
sm->lastRespData = wpabuf_dup(sm->eapRespData);
eapol_set_bool(sm, EAPOL_eapResp, TRUE);
- } else
+ } else {
+ wpa_printf(MSG_DEBUG, "EAP: No eapRespData available");
sm->lastRespData = NULL;
+ }
eapol_set_bool(sm, EAPOL_eapReq, FALSE);
eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout);
}
@@ -724,8 +727,19 @@
SM_ENTER(EAP, SEND_RESPONSE);
break;
case EAP_METHOD:
+ /*
+ * Note: RFC 4137 uses methodState == DONE && decision == FAIL
+ * as the condition. eapRespData == NULL here is used to allow
+ * final EAP method response to be sent without having to change
+ * all methods to either use methodState MAY_CONT or leaving
+ * decision to something else than FAIL in cases where the only
+ * expected response is EAP-Failure.
+ */
if (sm->ignore)
SM_ENTER(EAP, DISCARD);
+ else if (sm->methodState == METHOD_DONE &&
+ sm->decision == DECISION_FAIL && !sm->eapRespData)
+ SM_ENTER(EAP, FAILURE);
else
SM_ENTER(EAP, SEND_RESPONSE);
break;
diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c
index c71db5f..864ea1d 100644
--- a/src/eap_peer/eap_eke.c
+++ b/src/eap_peer/eap_eke.c
@@ -28,6 +28,10 @@
u8 nonce_p[EAP_EKE_MAX_NONCE_LEN];
u8 nonce_s[EAP_EKE_MAX_NONCE_LEN];
struct wpabuf *msgs;
+ u8 dhgroup; /* forced DH group or 0 to allow all supported */
+ u8 encr; /* forced encryption algorithm or 0 to allow all supported */
+ u8 prf; /* forced PRF or 0 to allow all supported */
+ u8 mac; /* forced MAC or 0 to allow all supported */
};
@@ -66,6 +70,7 @@
struct eap_eke_data *data;
const u8 *identity, *password;
size_t identity_len, password_len;
+ const char *phase1;
password = eap_get_config_password(sm, &password_len);
if (!password) {
@@ -89,6 +94,39 @@
data->peerid_len = identity_len;
}
+ phase1 = eap_get_config_phase1(sm);
+ if (phase1) {
+ const char *pos;
+
+ pos = os_strstr(phase1, "dhgroup=");
+ if (pos) {
+ data->dhgroup = atoi(pos + 8);
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Forced dhgroup %u",
+ data->dhgroup);
+ }
+
+ pos = os_strstr(phase1, "encr=");
+ if (pos) {
+ data->encr = atoi(pos + 5);
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Forced encr %u",
+ data->encr);
+ }
+
+ pos = os_strstr(phase1, "prf=");
+ if (pos) {
+ data->prf = atoi(pos + 4);
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Forced prf %u",
+ data->prf);
+ }
+
+ pos = os_strstr(phase1, "mac=");
+ if (pos) {
+ data->mac = atoi(pos + 4);
+ wpa_printf(MSG_DEBUG, "EAP-EKE: Forced mac %u",
+ data->mac);
+ }
+ }
+
return data;
}
@@ -226,16 +264,20 @@
i, pos[0], pos[1], pos[2], pos[3]);
pos += 4;
- if (!eap_eke_supp_dhgroup(*tmp))
+ if ((data->dhgroup && data->dhgroup != *tmp) ||
+ !eap_eke_supp_dhgroup(*tmp))
continue;
tmp++;
- if (!eap_eke_supp_encr(*tmp))
+ if ((data->encr && data->encr != *tmp) ||
+ !eap_eke_supp_encr(*tmp))
continue;
tmp++;
- if (!eap_eke_supp_prf(*tmp))
+ if ((data->prf && data->prf != *tmp) ||
+ !eap_eke_supp_prf(*tmp))
continue;
tmp++;
- if (!eap_eke_supp_mac(*tmp))
+ if ((data->mac && data->mac != *tmp) ||
+ !eap_eke_supp_mac(*tmp))
continue;
prop = tmp - 3;
diff --git a/src/eap_peer/eap_gpsk.c b/src/eap_peer/eap_gpsk.c
index 8a0644d..5b023c7 100644
--- a/src/eap_peer/eap_gpsk.c
+++ b/src/eap_peer/eap_gpsk.c
@@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-GPSK (RFC 5433)
- * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -33,6 +33,7 @@
int specifier; /* CSuite/Specifier */
u8 *psk;
size_t psk_len;
+ u16 forced_cipher; /* force cipher or 0 to allow all supported */
};
@@ -80,6 +81,7 @@
struct eap_gpsk_data *data;
const u8 *identity, *password;
size_t identity_len, password_len;
+ const char *phase1;
password = eap_get_config_password(sm, &password_len);
if (password == NULL) {
@@ -103,6 +105,18 @@
data->id_peer_len = identity_len;
}
+ phase1 = eap_get_config_phase1(sm);
+ if (phase1) {
+ const char *pos;
+
+ pos = os_strstr(phase1, "cipher=");
+ if (pos) {
+ data->forced_cipher = atoi(pos + 7);
+ wpa_printf(MSG_DEBUG, "EAP-GPSK: Forced cipher %u",
+ data->forced_cipher);
+ }
+ }
+
data->psk = os_malloc(password_len);
if (data->psk == NULL) {
eap_gpsk_deinit(sm, data);
@@ -195,7 +209,9 @@
i, vendor, specifier);
if (data->vendor == EAP_GPSK_VENDOR_IETF &&
data->specifier == EAP_GPSK_CIPHER_RESERVED &&
- eap_gpsk_supported_ciphersuite(vendor, specifier)) {
+ eap_gpsk_supported_ciphersuite(vendor, specifier) &&
+ (!data->forced_cipher || data->forced_cipher == specifier))
+ {
data->vendor = vendor;
data->specifier = specifier;
}
@@ -273,6 +289,7 @@
pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list,
&csuite_list_len, pos, end);
if (pos == NULL) {
+ ret->methodState = METHOD_DONE;
eap_gpsk_state(data, FAILURE);
return NULL;
}
diff --git a/src/eap_peer/eap_ikev2.c b/src/eap_peer/eap_ikev2.c
index 09a655e..2d7841d 100644
--- a/src/eap_peer/eap_ikev2.c
+++ b/src/eap_peer/eap_ikev2.c
@@ -1,6 +1,6 @@
/*
* EAP-IKEv2 peer (RFC 5106)
- * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -60,6 +60,7 @@
struct eap_ikev2_data *data;
const u8 *identity, *password;
size_t identity_len, password_len;
+ int fragment_size;
identity = eap_get_config_identity(sm, &identity_len);
if (identity == NULL) {
@@ -71,7 +72,11 @@
if (data == NULL)
return NULL;
data->state = WAIT_START;
- data->fragment_size = IKEV2_FRAGMENT_SIZE;
+ fragment_size = eap_get_config_fragment_size(sm);
+ if (fragment_size <= 0)
+ data->fragment_size = IKEV2_FRAGMENT_SIZE;
+ else
+ data->fragment_size = fragment_size;
data->ikev2.state = SA_INIT;
data->ikev2.peer_auth = PEER_AUTH_SECRET;
data->ikev2.key_pad = (u8 *) os_strdup("Key Pad for EAP-IKEv2");
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index 3b93209..8634f75 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -22,7 +22,6 @@
/* Maximum supported PEAP version
* 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
* 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
- * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
*/
#define EAP_PEAP_VERSION 1
@@ -315,8 +314,6 @@
len[1] = 1;
tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
- if (data->peap_version >= 2)
- tlv_type |= EAP_TLV_TYPE_MANDATORY;
wpabuf_put_be16(buf, tlv_type);
wpabuf_put_be16(buf, 56);
@@ -580,33 +577,6 @@
}
-static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
-{
- struct wpabuf *e;
- struct eap_tlv_hdr *tlv;
-
- if (buf == NULL)
- return NULL;
-
- /* Encapsulate EAP packet in EAP-Payload TLV */
- wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
- e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
- if (e == NULL) {
- wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
- "for TLV encapsulation");
- wpabuf_free(buf);
- return NULL;
- }
- tlv = wpabuf_put(e, sizeof(*tlv));
- tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
- EAP_TLV_EAP_PAYLOAD_TLV);
- tlv->length = host_to_be16(wpabuf_len(buf));
- wpabuf_put_buf(e, buf);
- wpabuf_free(buf);
- return e;
-}
-
-
static int eap_peap_phase2_request(struct eap_sm *sm,
struct eap_peap_data *data,
struct eap_method_ret *ret,
@@ -837,49 +807,6 @@
in_decrypted = nmsg;
}
- if (data->peap_version >= 2) {
- struct eap_tlv_hdr *tlv;
- struct wpabuf *nmsg;
-
- if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
- "EAP TLV");
- wpabuf_free(in_decrypted);
- return 0;
- }
- tlv = wpabuf_mhead(in_decrypted);
- if ((be_to_host16(tlv->tlv_type) & 0x3fff) !=
- EAP_TLV_EAP_PAYLOAD_TLV) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
- wpabuf_free(in_decrypted);
- return 0;
- }
- if (sizeof(*tlv) + be_to_host16(tlv->length) >
- wpabuf_len(in_decrypted)) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
- "length");
- wpabuf_free(in_decrypted);
- return 0;
- }
- hdr = (struct eap_hdr *) (tlv + 1);
- if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
- "EAP packet in EAP TLV");
- wpabuf_free(in_decrypted);
- return 0;
- }
-
- nmsg = wpabuf_alloc(be_to_host16(hdr->length));
- if (nmsg == NULL) {
- wpabuf_free(in_decrypted);
- return 0;
- }
-
- wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
- wpabuf_free(in_decrypted);
- in_decrypted = nmsg;
- }
-
hdr = wpabuf_mhead(in_decrypted);
if (wpabuf_len(in_decrypted) < sizeof(*hdr)) {
wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
@@ -996,11 +923,6 @@
wpa_hexdump_buf_key(MSG_DEBUG,
"EAP-PEAP: Encrypting Phase 2 data", resp);
/* PEAP version changes */
- if (data->peap_version >= 2) {
- resp = eap_peapv2_tlv_eap_payload(resp);
- if (resp == NULL)
- return -1;
- }
if (wpabuf_len(resp) >= 5 &&
wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE &&
eap_get_type(resp) == EAP_TYPE_TLV)
@@ -1091,7 +1013,7 @@
* label, "client EAP encryption", instead. Use the old
* label by default, but allow it to be configured with
* phase1 parameter peaplabel=1. */
- if (data->peap_version > 1 || data->force_new_label)
+ if (data->force_new_label)
label = "client PEAP encryption";
else
label = "client EAP encryption";
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 267d0a5..fef4783 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -81,6 +81,7 @@
struct eap_pwd_data *data;
const u8 *identity, *password;
size_t identity_len, password_len;
+ int fragment_size;
password = eap_get_config_password(sm, &password_len);
if (password == NULL) {
@@ -127,7 +128,11 @@
data->out_frag_pos = data->in_frag_pos = 0;
data->inbuf = data->outbuf = NULL;
- data->mtu = 1020; /* default from RFC 5931, make it configurable! */
+ fragment_size = eap_get_config_fragment_size(sm);
+ if (fragment_size <= 0)
+ data->mtu = 1020; /* default from RFC 5931 */
+ else
+ data->mtu = fragment_size;
data->state = PWD_ID_Req;
diff --git a/src/eap_peer/ikev2.c b/src/eap_peer/ikev2.c
index fcf4712..1ccc352 100644
--- a/src/eap_peer/ikev2.c
+++ b/src/eap_peer/ikev2.c
@@ -1257,6 +1257,7 @@
wpabuf_free(msg);
return NULL;
}
+ wpabuf_free(plain);
data->state = IKEV2_FAILED;
} else {
/* HDR, N */
diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c
index 68253c4..defcb3c 100644
--- a/src/eap_server/eap_server_peap.c
+++ b/src/eap_server/eap_server_peap.c
@@ -22,7 +22,6 @@
/* Maximum supported PEAP version
* 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
* 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
- * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
*/
#define EAP_PEAP_VERSION 1
@@ -99,33 +98,6 @@
}
-static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
-{
- struct wpabuf *e;
- struct eap_tlv_hdr *tlv;
-
- if (buf == NULL)
- return NULL;
-
- /* Encapsulate EAP packet in EAP-Payload TLV */
- wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
- e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
- if (e == NULL) {
- wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
- "for TLV encapsulation");
- wpabuf_free(buf);
- return NULL;
- }
- tlv = wpabuf_put(e, sizeof(*tlv));
- tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
- EAP_TLV_EAP_PAYLOAD_TLV);
- tlv->length = host_to_be16(wpabuf_len(buf));
- wpabuf_put_buf(e, buf);
- wpabuf_free(buf);
- return e;
-}
-
-
static void eap_peap_req_success(struct eap_sm *sm,
struct eap_peap_data *data)
{
@@ -239,8 +211,6 @@
return NULL;
}
buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
- if (data->peap_version >= 2 && buf)
- buf = eap_peapv2_tlv_eap_payload(buf);
if (buf == NULL)
return NULL;
@@ -425,8 +395,6 @@
len[1] = 1;
tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
- if (data->peap_version >= 2)
- tlv_type |= EAP_TLV_TYPE_MANDATORY;
wpabuf_put_be16(buf, tlv_type);
wpabuf_put_be16(buf, 56);
@@ -505,8 +473,7 @@
return eap_peap_build_start(sm, data, id);
case PHASE1:
case PHASE1_ID2:
- if (data->peap_version < 2 &&
- tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
+ if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, "
"starting Phase2");
eap_peap_state(data, PHASE2_START);
@@ -1079,47 +1046,6 @@
wpabuf_free(in_decrypted);
in_decrypted = nbuf;
- } else if (data->peap_version >= 2) {
- struct eap_tlv_hdr *tlv;
- struct wpabuf *nmsg;
-
- if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
- "EAP TLV");
- wpabuf_free(in_decrypted);
- return;
- }
- tlv = wpabuf_mhead(in_decrypted);
- if ((be_to_host16(tlv->tlv_type) & EAP_TLV_TYPE_MASK) !=
- EAP_TLV_EAP_PAYLOAD_TLV) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
- wpabuf_free(in_decrypted);
- return;
- }
- if (sizeof(*tlv) + be_to_host16(tlv->length) >
- wpabuf_len(in_decrypted)) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
- "length");
- wpabuf_free(in_decrypted);
- return;
- }
- hdr = (struct eap_hdr *) (tlv + 1);
- if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
- "EAP packet in EAP TLV");
- wpabuf_free(in_decrypted);
- return;
- }
-
- nmsg = wpabuf_alloc(be_to_host16(hdr->length));
- if (nmsg == NULL) {
- wpabuf_free(in_decrypted);
- return;
- }
-
- wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
- wpabuf_free(in_decrypted);
- in_decrypted = nmsg;
}
hdr = wpabuf_head(in_decrypted);
@@ -1168,53 +1094,6 @@
}
-static int eap_peapv2_start_phase2(struct eap_sm *sm,
- struct eap_peap_data *data)
-{
- struct wpabuf *buf, *buf2;
-
- wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Phase1 done, include first Phase2 "
- "payload in the same message");
- eap_peap_state(data, PHASE1_ID2);
- if (eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY))
- return -1;
-
- /* TODO: which Id to use here? */
- buf = data->phase2_method->buildReq(sm, data->phase2_priv, 6);
- if (buf == NULL)
- return -1;
-
- buf2 = eap_peapv2_tlv_eap_payload(buf);
- if (buf2 == NULL)
- return -1;
-
- wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Identity Request", buf2);
-
- buf = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
- buf2);
- wpabuf_free(buf2);
-
- if (buf == NULL) {
- wpa_printf(MSG_INFO, "EAP-PEAPv2: Failed to encrypt Phase 2 "
- "data");
- return -1;
- }
-
- wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAPv2: Encrypted Identity Request",
- buf);
-
- /* Append TLS data into the pending buffer after the Server Finished */
- if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(buf)) < 0) {
- wpabuf_free(buf);
- return -1;
- }
- wpabuf_put_buf(data->ssl.tls_out, buf);
- wpabuf_free(buf);
-
- return 0;
-}
-
-
static int eap_peap_process_version(struct eap_sm *sm, void *priv,
int peer_version)
{
@@ -1249,14 +1128,6 @@
eap_peap_state(data, FAILURE);
break;
}
-
- if (data->peap_version >= 2 &&
- tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
- if (eap_peapv2_start_phase2(sm, data)) {
- eap_peap_state(data, FAILURE);
- break;
- }
- }
break;
case PHASE2_START:
eap_peap_state(data, PHASE2_ID);
diff --git a/src/eap_server/eap_sim_db.c b/src/eap_server/eap_sim_db.c
index 345c788..45660ed 100644
--- a/src/eap_server/eap_sim_db.c
+++ b/src/eap_server/eap_sim_db.c
@@ -38,7 +38,6 @@
char imsi[20];
enum { PENDING, SUCCESS, FAILURE } state;
void *cb_session_ctx;
- struct os_time timestamp;
int aka;
union {
struct {
@@ -935,7 +934,6 @@
if (entry == NULL)
return EAP_SIM_DB_FAILURE;
- os_get_time(&entry->timestamp);
os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
entry->cb_session_ctx = cb_session_ctx;
entry->state = PENDING;
@@ -1395,7 +1393,6 @@
if (entry == NULL)
return EAP_SIM_DB_FAILURE;
- os_get_time(&entry->timestamp);
entry->aka = 1;
os_strlcpy(entry->imsi, imsi, sizeof(entry->imsi));
entry->cb_session_ctx = cb_session_ctx;
diff --git a/src/eapol_auth/eapol_auth_dump.c b/src/eapol_auth/eapol_auth_dump.c
index b6e0b13..6c6969b 100644
--- a/src/eapol_auth/eapol_auth_dump.c
+++ b/src/eapol_auth/eapol_auth_dump.c
@@ -1,6 +1,6 @@
/*
* IEEE 802.1X-2004 Authenticator - State dump
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -118,108 +118,172 @@
}
-void eapol_auth_dump_state(FILE *f, const char *prefix,
- struct eapol_state_machine *sm)
+int eapol_auth_dump_state(struct eapol_state_machine *sm, char *buf,
+ size_t buflen)
{
- fprintf(f, "%sEAPOL state machine:\n", prefix);
- fprintf(f, "%s aWhile=%d quietWhile=%d reAuthWhen=%d\n", prefix,
- sm->aWhile, sm->quietWhile, sm->reAuthWhen);
+ char *pos, *end;
+ int ret;
+
+ pos = buf;
+ end = pos + buflen;
+
+ ret = os_snprintf(pos, end - pos, "aWhile=%d\nquietWhile=%d\n"
+ "reAuthWhen=%d\n",
+ sm->aWhile, sm->quietWhile, sm->reAuthWhen);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+
#define _SB(b) ((b) ? "TRUE" : "FALSE")
- fprintf(f,
- "%s authAbort=%s authFail=%s authPortStatus=%s authStart=%s\n"
- "%s authTimeout=%s authSuccess=%s eapFail=%s eapolEap=%s\n"
- "%s eapSuccess=%s eapTimeout=%s initialize=%s "
- "keyAvailable=%s\n"
- "%s keyDone=%s keyRun=%s keyTxEnabled=%s portControl=%s\n"
- "%s portEnabled=%s portValid=%s reAuthenticate=%s\n",
- prefix, _SB(sm->authAbort), _SB(sm->authFail),
- port_state_txt(sm->authPortStatus), _SB(sm->authStart),
- prefix, _SB(sm->authTimeout), _SB(sm->authSuccess),
- _SB(sm->eap_if->eapFail), _SB(sm->eapolEap),
- prefix, _SB(sm->eap_if->eapSuccess),
- _SB(sm->eap_if->eapTimeout),
- _SB(sm->initialize), _SB(sm->eap_if->eapKeyAvailable),
- prefix, _SB(sm->keyDone), _SB(sm->keyRun),
- _SB(sm->keyTxEnabled), port_type_txt(sm->portControl),
- prefix, _SB(sm->eap_if->portEnabled), _SB(sm->portValid),
- _SB(sm->reAuthenticate));
+ ret = os_snprintf(pos, end - pos,
+ "authAbort=%s\n"
+ "authFail=%s\n"
+ "authPortStatus=%s\n"
+ "authStart=%s\n"
+ "authTimeout=%s\n"
+ "authSuccess=%s\n"
+ "eapFail=%s\n"
+ "eapolEap=%s\n"
+ "eapSuccess=%s\n"
+ "eapTimeout=%s\n"
+ "initialize=%s\n"
+ "keyAvailable=%s\n"
+ "keyDone=%s\n"
+ "keyRun=%s\n"
+ "keyTxEnabled=%s\n"
+ "portControl=%s\n"
+ "portEnabled=%s\n"
+ "portValid=%s\n"
+ "reAuthenticate=%s\n",
+ _SB(sm->authAbort),
+ _SB(sm->authFail),
+ port_state_txt(sm->authPortStatus),
+ _SB(sm->authStart),
+ _SB(sm->authTimeout),
+ _SB(sm->authSuccess),
+ _SB(sm->eap_if->eapFail),
+ _SB(sm->eapolEap),
+ _SB(sm->eap_if->eapSuccess),
+ _SB(sm->eap_if->eapTimeout),
+ _SB(sm->initialize),
+ _SB(sm->eap_if->eapKeyAvailable),
+ _SB(sm->keyDone), _SB(sm->keyRun),
+ _SB(sm->keyTxEnabled),
+ port_type_txt(sm->portControl),
+ _SB(sm->eap_if->portEnabled),
+ _SB(sm->portValid),
+ _SB(sm->reAuthenticate));
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
- fprintf(f, "%s Authenticator PAE:\n"
- "%s state=%s\n"
- "%s eapolLogoff=%s eapolStart=%s eapRestart=%s\n"
- "%s portMode=%s reAuthCount=%d\n"
- "%s quietPeriod=%d reAuthMax=%d\n"
- "%s authEntersConnecting=%d\n"
- "%s authEapLogoffsWhileConnecting=%d\n"
- "%s authEntersAuthenticating=%d\n"
- "%s authAuthSuccessesWhileAuthenticating=%d\n"
- "%s authAuthTimeoutsWhileAuthenticating=%d\n"
- "%s authAuthFailWhileAuthenticating=%d\n"
- "%s authAuthEapStartsWhileAuthenticating=%d\n"
- "%s authAuthEapLogoffWhileAuthenticating=%d\n"
- "%s authAuthReauthsWhileAuthenticated=%d\n"
- "%s authAuthEapStartsWhileAuthenticated=%d\n"
- "%s authAuthEapLogoffWhileAuthenticated=%d\n",
- prefix, prefix, auth_pae_state_txt(sm->auth_pae_state), prefix,
- _SB(sm->eapolLogoff), _SB(sm->eapolStart),
- _SB(sm->eap_if->eapRestart),
- prefix, port_type_txt(sm->portMode), sm->reAuthCount,
- prefix, sm->quietPeriod, sm->reAuthMax,
- prefix, sm->authEntersConnecting,
- prefix, sm->authEapLogoffsWhileConnecting,
- prefix, sm->authEntersAuthenticating,
- prefix, sm->authAuthSuccessesWhileAuthenticating,
- prefix, sm->authAuthTimeoutsWhileAuthenticating,
- prefix, sm->authAuthFailWhileAuthenticating,
- prefix, sm->authAuthEapStartsWhileAuthenticating,
- prefix, sm->authAuthEapLogoffWhileAuthenticating,
- prefix, sm->authAuthReauthsWhileAuthenticated,
- prefix, sm->authAuthEapStartsWhileAuthenticated,
- prefix, sm->authAuthEapLogoffWhileAuthenticated);
+ ret = os_snprintf(pos, end - pos,
+ "auth_pae_state=%s\n"
+ "eapolLogoff=%s\n"
+ "eapolStart=%s\n"
+ "eapRestart=%s\n"
+ "portMode=%s\n"
+ "reAuthCount=%d\n"
+ "quietPeriod=%d\n"
+ "reAuthMax=%d\n"
+ "authEntersConnecting=%d\n"
+ "authEapLogoffsWhileConnecting=%d\n"
+ "authEntersAuthenticating=%d\n"
+ "authAuthSuccessesWhileAuthenticating=%d\n"
+ "authAuthTimeoutsWhileAuthenticating=%d\n"
+ "authAuthFailWhileAuthenticating=%d\n"
+ "authAuthEapStartsWhileAuthenticating=%d\n"
+ "authAuthEapLogoffWhileAuthenticating=%d\n"
+ "authAuthReauthsWhileAuthenticated=%d\n"
+ "authAuthEapStartsWhileAuthenticated=%d\n"
+ "authAuthEapLogoffWhileAuthenticated=%d\n",
+ auth_pae_state_txt(sm->auth_pae_state),
+ _SB(sm->eapolLogoff),
+ _SB(sm->eapolStart),
+ _SB(sm->eap_if->eapRestart),
+ port_type_txt(sm->portMode),
+ sm->reAuthCount,
+ sm->quietPeriod, sm->reAuthMax,
+ sm->authEntersConnecting,
+ sm->authEapLogoffsWhileConnecting,
+ sm->authEntersAuthenticating,
+ sm->authAuthSuccessesWhileAuthenticating,
+ sm->authAuthTimeoutsWhileAuthenticating,
+ sm->authAuthFailWhileAuthenticating,
+ sm->authAuthEapStartsWhileAuthenticating,
+ sm->authAuthEapLogoffWhileAuthenticating,
+ sm->authAuthReauthsWhileAuthenticated,
+ sm->authAuthEapStartsWhileAuthenticated,
+ sm->authAuthEapLogoffWhileAuthenticated);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
- fprintf(f, "%s Backend Authentication:\n"
- "%s state=%s\n"
- "%s eapNoReq=%s eapReq=%s eapResp=%s\n"
- "%s serverTimeout=%d\n"
- "%s backendResponses=%d\n"
- "%s backendAccessChallenges=%d\n"
- "%s backendOtherRequestsToSupplicant=%d\n"
- "%s backendAuthSuccesses=%d\n"
- "%s backendAuthFails=%d\n",
- prefix, prefix,
- be_auth_state_txt(sm->be_auth_state),
- prefix, _SB(sm->eap_if->eapNoReq), _SB(sm->eap_if->eapReq),
- _SB(sm->eap_if->eapResp),
- prefix, sm->serverTimeout,
- prefix, sm->backendResponses,
- prefix, sm->backendAccessChallenges,
- prefix, sm->backendOtherRequestsToSupplicant,
- prefix, sm->backendAuthSuccesses,
- prefix, sm->backendAuthFails);
+ ret = os_snprintf(pos, end - pos,
+ "be_auth_state=%s\n"
+ "eapNoReq=%s\n"
+ "eapReq=%s\n"
+ "eapResp=%s\n"
+ "serverTimeout=%d\n"
+ "backendResponses=%d\n"
+ "backendAccessChallenges=%d\n"
+ "backendOtherRequestsToSupplicant=%d\n"
+ "backendAuthSuccesses=%d\n"
+ "backendAuthFails=%d\n",
+ be_auth_state_txt(sm->be_auth_state),
+ _SB(sm->eap_if->eapNoReq),
+ _SB(sm->eap_if->eapReq),
+ _SB(sm->eap_if->eapResp),
+ sm->serverTimeout,
+ sm->backendResponses,
+ sm->backendAccessChallenges,
+ sm->backendOtherRequestsToSupplicant,
+ sm->backendAuthSuccesses,
+ sm->backendAuthFails);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
- fprintf(f, "%s Reauthentication Timer:\n"
- "%s state=%s\n"
- "%s reAuthPeriod=%d reAuthEnabled=%s\n", prefix, prefix,
- reauth_timer_state_txt(sm->reauth_timer_state), prefix,
- sm->reAuthPeriod, _SB(sm->reAuthEnabled));
+ ret = os_snprintf(pos, end - pos,
+ "reauth_timer_state=%s\n"
+ "reAuthPeriod=%d\n"
+ "reAuthEnabled=%s\n",
+ reauth_timer_state_txt(sm->reauth_timer_state),
+ sm->reAuthPeriod,
+ _SB(sm->reAuthEnabled));
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
- fprintf(f, "%s Authenticator Key Transmit:\n"
- "%s state=%s\n", prefix, prefix,
- auth_key_tx_state_txt(sm->auth_key_tx_state));
+ ret = os_snprintf(pos, end - pos,
+ "auth_key_tx_state=%s\n",
+ auth_key_tx_state_txt(sm->auth_key_tx_state));
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
- fprintf(f, "%s Key Receive:\n"
- "%s state=%s\n"
- "%s rxKey=%s\n", prefix, prefix,
- key_rx_state_txt(sm->key_rx_state), prefix, _SB(sm->rxKey));
+ ret = os_snprintf(pos, end - pos,
+ "key_rx_state=%s\n"
+ "rxKey=%s\n",
+ key_rx_state_txt(sm->key_rx_state),
+ _SB(sm->rxKey));
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
- fprintf(f, "%s Controlled Directions:\n"
- "%s state=%s\n"
- "%s adminControlledDirections=%s "
- "operControlledDirections=%s\n"
- "%s operEdge=%s\n", prefix, prefix,
- ctrl_dir_state_txt(sm->ctrl_dir_state),
- prefix, ctrl_dir_txt(sm->adminControlledDirections),
- ctrl_dir_txt(sm->operControlledDirections),
- prefix, _SB(sm->operEdge));
+ ret = os_snprintf(pos, end - pos,
+ "ctrl_dir_state=%s\n"
+ "adminControlledDirections=%s\n"
+ "operControlledDirections=%s\n"
+ "operEdge=%s\n",
+ ctrl_dir_state_txt(sm->ctrl_dir_state),
+ ctrl_dir_txt(sm->adminControlledDirections),
+ ctrl_dir_txt(sm->operControlledDirections),
+ _SB(sm->operEdge));
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
#undef _SB
+
+ return pos - buf;
}
diff --git a/src/eapol_auth/eapol_auth_sm.h b/src/eapol_auth/eapol_auth_sm.h
index 3a0f450..f0ff464 100644
--- a/src/eapol_auth/eapol_auth_sm.h
+++ b/src/eapol_auth/eapol_auth_sm.h
@@ -83,8 +83,8 @@
const char *identity, const char *radius_cui);
void eapol_auth_free(struct eapol_state_machine *sm);
void eapol_auth_step(struct eapol_state_machine *sm);
-void eapol_auth_dump_state(FILE *f, const char *prefix,
- struct eapol_state_machine *sm);
+int eapol_auth_dump_state(struct eapol_state_machine *sm, char *buf,
+ size_t buflen);
int eapol_auth_eap_pending_cb(struct eapol_state_machine *sm, void *ctx);
#endif /* EAPOL_AUTH_SM_H */
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index 9d7aef0..05b9851 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -137,6 +137,9 @@
Boolean cached_pmk;
Boolean unicast_key_received, broadcast_key_received;
+
+ Boolean force_authorized_update;
+
#ifdef CONFIG_EAP_PROXY
Boolean use_eap_proxy;
struct eap_proxy_sm *eap_proxy;
@@ -210,7 +213,6 @@
SM_ENTRY(SUPP_PAE, LOGOFF);
eapol_sm_txLogoff(sm);
sm->logoffSent = TRUE;
- sm->suppPortStatus = Unauthorized;
eapol_sm_set_port_unauthorized(sm);
}
@@ -221,7 +223,6 @@
sm->sPortMode = Auto;
sm->startCount = 0;
sm->logoffSent = FALSE;
- sm->suppPortStatus = Unauthorized;
eapol_sm_set_port_unauthorized(sm);
sm->suppAbort = TRUE;
@@ -286,7 +287,6 @@
SM_ENTRY(SUPP_PAE, HELD);
sm->heldWhile = sm->heldPeriod;
eapol_enable_timer_tick(sm);
- sm->suppPortStatus = Unauthorized;
eapol_sm_set_port_unauthorized(sm);
sm->cb_status = EAPOL_CB_FAILURE;
}
@@ -295,7 +295,6 @@
SM_STATE(SUPP_PAE, AUTHENTICATED)
{
SM_ENTRY(SUPP_PAE, AUTHENTICATED);
- sm->suppPortStatus = Authorized;
eapol_sm_set_port_authorized(sm);
sm->cb_status = EAPOL_CB_SUCCESS;
}
@@ -311,7 +310,6 @@
SM_STATE(SUPP_PAE, S_FORCE_AUTH)
{
SM_ENTRY(SUPP_PAE, S_FORCE_AUTH);
- sm->suppPortStatus = Authorized;
eapol_sm_set_port_authorized(sm);
sm->sPortMode = ForceAuthorized;
}
@@ -320,7 +318,6 @@
SM_STATE(SUPP_PAE, S_FORCE_UNAUTH)
{
SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH);
- sm->suppPortStatus = Unauthorized;
eapol_sm_set_port_unauthorized(sm);
sm->sPortMode = ForceUnauthorized;
eapol_sm_txLogoff(sm);
@@ -879,14 +876,24 @@
static void eapol_sm_set_port_authorized(struct eapol_sm *sm)
{
- if (sm->ctx->port_cb)
+ int cb;
+
+ cb = sm->suppPortStatus != Authorized || sm->force_authorized_update;
+ sm->force_authorized_update = FALSE;
+ sm->suppPortStatus = Authorized;
+ if (cb && sm->ctx->port_cb)
sm->ctx->port_cb(sm->ctx->ctx, 1);
}
static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm)
{
- if (sm->ctx->port_cb)
+ int cb;
+
+ cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update;
+ sm->force_authorized_update = FALSE;
+ sm->suppPortStatus = Unauthorized;
+ if (cb && sm->ctx->port_cb)
sm->ctx->port_cb(sm->ctx->ctx, 0);
}
@@ -1370,6 +1377,8 @@
return;
wpa_printf(MSG_DEBUG, "EAPOL: External notification - "
"portEnabled=%d", enabled);
+ if (sm->portEnabled != enabled)
+ sm->force_authorized_update = TRUE;
sm->portEnabled = enabled;
eapol_sm_step(sm);
}
@@ -1608,7 +1617,6 @@
return;
sm->cached_pmk = FALSE;
sm->SUPP_PAE_state = SUPP_PAE_CONNECTING;
- sm->suppPortStatus = Unauthorized;
eapol_sm_set_port_unauthorized(sm);
/* Make sure we do not start sending EAPOL-Start frames first, but
@@ -2002,6 +2010,7 @@
#endif /* CONFIG_EAP_PROXY */
/* Initialize EAPOL state machines */
+ sm->force_authorized_update = TRUE;
sm->initialize = TRUE;
eapol_sm_step(sm);
sm->initialize = FALSE;
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index e77563b..61cafe4 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -78,10 +78,10 @@
static void p2p_expire_peers(struct p2p_data *p2p)
{
struct p2p_device *dev, *n;
- struct os_time now;
+ struct os_reltime now;
size_t i;
- os_get_time(&now);
+ os_get_reltime(&now);
dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) {
if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec)
continue;
@@ -93,7 +93,7 @@
* We are connected as a client to a group in which the
* peer is the GO, so do not expire the peer entry.
*/
- os_get_time(&dev->last_seen);
+ os_get_reltime(&dev->last_seen);
continue;
}
@@ -107,7 +107,7 @@
* The peer is connected as a client in a group where
* we are the GO, so do not expire the peer entry.
*/
- os_get_time(&dev->last_seen);
+ os_get_reltime(&dev->last_seen);
continue;
}
@@ -170,10 +170,6 @@
return "INVITE";
case P2P_INVITE_LISTEN:
return "INVITE_LISTEN";
- case P2P_SEARCH_WHEN_READY:
- return "SEARCH_WHEN_READY";
- case P2P_CONTINUE_SEARCH_WHEN_READY:
- return "CONTINUE_SEARCH_WHEN_READY";
default:
return "?";
}
@@ -420,7 +416,7 @@
dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
count++;
if (oldest == NULL ||
- os_time_before(&dev->last_seen, &oldest->last_seen))
+ os_reltime_before(&dev->last_seen, &oldest->last_seen))
oldest = dev;
}
if (count + 1 > p2p->cfg->max_peers && oldest) {
@@ -528,7 +524,7 @@
os_memcpy(dev->interface_addr, cli->p2p_interface_addr,
ETH_ALEN);
- os_get_time(&dev->last_seen);
+ os_get_reltime(&dev->last_seen);
os_memcpy(dev->member_in_go_dev, go_dev_addr, ETH_ALEN);
os_memcpy(dev->member_in_go_iface, go_interface_addr,
ETH_ALEN);
@@ -644,14 +640,14 @@
* Info attributes.
*/
int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
- struct os_time *rx_time, int level, const u8 *ies,
+ struct os_reltime *rx_time, int level, const u8 *ies,
size_t ies_len, int scan_res)
{
struct p2p_device *dev;
struct p2p_message msg;
const u8 *p2p_dev_addr;
int i;
- struct os_time time_now;
+ struct os_reltime time_now;
os_memset(&msg, 0, sizeof(msg));
if (p2p_parse_ies(ies, ies_len, &msg)) {
@@ -685,7 +681,7 @@
}
if (rx_time == NULL) {
- os_get_time(&time_now);
+ os_get_reltime(&time_now);
rx_time = &time_now;
}
@@ -694,7 +690,7 @@
* entry is newer than the one previously stored.
*/
if (dev->last_seen.sec > 0 &&
- os_time_before(rx_time, &dev->last_seen)) {
+ os_reltime_before(rx_time, &dev->last_seen)) {
p2p_dbg(p2p, "Do not update peer entry based on old frame (rx_time=%u.%06u last_seen=%u.%06u)",
(unsigned int) rx_time->sec,
(unsigned int) rx_time->usec,
@@ -704,7 +700,7 @@
return -1;
}
- os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_time));
+ os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_reltime));
dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
@@ -932,9 +928,6 @@
if (res < 0) {
p2p_dbg(p2p, "Scan request failed");
p2p_continue_find(p2p);
- } else if (res == 1) {
- p2p_dbg(p2p, "Could not start p2p_scan at this point - will try again after previous scan completes");
- p2p_set_state(p2p, P2P_CONTINUE_SEARCH_WHEN_READY);
} else {
p2p_dbg(p2p, "Running p2p_scan");
p2p->p2p_scan_running = 1;
@@ -1038,7 +1031,7 @@
int res;
p2p_dbg(p2p, "Starting find (type=%d)", type);
- os_get_time(&p2p->find_start);
+ os_get_reltime(&p2p->find_start);
if (p2p->p2p_scan_running) {
p2p_dbg(p2p, "p2p_scan is already running");
}
@@ -1097,11 +1090,9 @@
eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout,
p2p, NULL);
- } else if (res == 1) {
- p2p_dbg(p2p, "Could not start p2p_scan at this point - will try again after previous scan completes");
- res = 0;
- p2p_set_state(p2p, P2P_SEARCH_WHEN_READY);
- eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
+ } else if (p2p->p2p_scan_running) {
+ p2p_dbg(p2p, "Failed to start p2p_scan - another p2p_scan was already running");
+ /* wait for the previous p2p_scan to complete */
} else {
p2p_dbg(p2p, "Failed to start p2p_scan");
p2p_set_state(p2p, P2P_IDLE);
@@ -1112,34 +1103,12 @@
}
-int p2p_other_scan_completed(struct p2p_data *p2p)
-{
- if (p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY) {
- p2p_set_state(p2p, P2P_SEARCH);
- p2p_search(p2p);
- return 1;
- }
- if (p2p->state != P2P_SEARCH_WHEN_READY)
- return 0;
- p2p_dbg(p2p, "Starting pending P2P find now that previous scan was completed");
- if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
- p2p->num_req_dev_types, p2p->req_dev_types,
- p2p->find_dev_id, p2p->search_delay) < 0) {
- p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
- return 0;
- }
- return 1;
-}
-
-
void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq)
{
p2p_dbg(p2p, "Stopping find");
eloop_cancel_timeout(p2p_find_timeout, p2p, NULL);
p2p_clear_timeout(p2p);
- if (p2p->state == P2P_SEARCH ||
- p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY ||
- p2p->state == P2P_SEARCH_WHEN_READY)
+ if (p2p->state == P2P_SEARCH)
p2p->cfg->find_stopped(p2p->cfg->cb_ctx);
p2p_set_state(p2p, P2P_IDLE);
p2p_free_req_dev_types(p2p);
@@ -1527,7 +1496,7 @@
void p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
struct p2p_device *dev, struct p2p_message *msg)
{
- os_get_time(&dev->last_seen);
+ os_get_reltime(&dev->last_seen);
p2p_copy_wps_info(p2p, dev, 0, msg);
@@ -1866,7 +1835,7 @@
if (dev) {
if (dev->country[0] == 0 && msg.listen_channel)
os_memcpy(dev->country, msg.listen_channel, 3);
- os_get_time(&dev->last_seen);
+ os_get_reltime(&dev->last_seen);
p2p_parse_free(&msg);
return; /* already known */
}
@@ -1877,7 +1846,7 @@
return;
}
- os_get_time(&dev->last_seen);
+ os_get_reltime(&dev->last_seen);
dev->flags |= P2P_DEV_PROBE_REQ_ONLY;
if (msg.listen_channel) {
@@ -1911,7 +1880,7 @@
dev = p2p_get_device(p2p, addr);
if (dev) {
- os_get_time(&dev->last_seen);
+ os_get_reltime(&dev->last_seen);
return dev; /* already known */
}
@@ -2868,10 +2837,10 @@
int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
- struct os_time *rx_time, int level, const u8 *ies,
+ struct os_reltime *rx_time, int level, const u8 *ies,
size_t ies_len)
{
- if (os_time_before(rx_time, &p2p->find_start)) {
+ if (os_reltime_before(rx_time, &p2p->find_start)) {
/*
* The driver may have cached (e.g., in cfg80211 BSS table) the
* scan results for relatively long time. To avoid reporting
@@ -3467,10 +3436,6 @@
case P2P_INVITE_LISTEN:
p2p_timeout_invite_listen(p2p);
break;
- case P2P_SEARCH_WHEN_READY:
- break;
- case P2P_CONTINUE_SEARCH_WHEN_READY:
- break;
}
}
@@ -3553,7 +3518,7 @@
struct p2p_device *dev;
int res;
char *pos, *end;
- struct os_time now;
+ struct os_reltime now;
if (info == NULL)
return -1;
@@ -3564,7 +3529,7 @@
pos = buf;
end = buf + buflen;
- os_get_time(&now);
+ os_get_reltime(&now);
res = os_snprintf(pos, end - pos,
"age=%d\n"
"listen_freq=%d\n"
@@ -3868,6 +3833,11 @@
return;
}
+ if (p2p->cfg->presence_resp) {
+ p2p->cfg->presence_resp(p2p->cfg->cb_ctx, sa, *msg.status,
+ msg.noa, msg.noa_len);
+ }
+
if (*msg.status) {
p2p_dbg(p2p, "P2P Presence Request was rejected: status %u",
*msg.status);
@@ -4276,8 +4246,7 @@
{
if (p2p == NULL)
return 0;
- if (p2p->state == P2P_SEARCH || p2p->state == P2P_SEARCH_WHEN_READY ||
- p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY)
+ if (p2p->state == P2P_SEARCH)
return 2;
return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
}
@@ -4293,13 +4262,6 @@
}
-void p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay)
-{
- if (p2p && p2p->search_delay < delay)
- p2p->search_delay = delay;
-}
-
-
#ifdef CONFIG_WIFI_DISPLAY
static void p2p_update_wfd_ie_groups(struct p2p_data *p2p)
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 22d0c58..25a91e7 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -778,6 +778,17 @@
* or 0 if not.
*/
int (*go_connected)(void *ctx, const u8 *dev_addr);
+
+ /**
+ * presence_resp - Callback on Presence Response
+ * @ctx: Callback context from cb_ctx
+ * @src: Source address (GO's P2P Interface Address)
+ * @status: Result of the request (P2P_SC_*)
+ * @noa: Returned NoA value
+ * @noa_len: Length of the NoA buffer in octets
+ */
+ void (*presence_resp)(void *ctx, const u8 *src, u8 status,
+ const u8 *noa, size_t noa_len);
};
@@ -1245,7 +1256,7 @@
* start of a pending operation, e.g., to start a pending GO negotiation.
*/
int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
- struct os_time *rx_time, int level, const u8 *ies,
+ struct os_reltime *rx_time, int level, const u8 *ies,
size_t ies_len);
/**
@@ -1815,13 +1826,6 @@
*/
int p2p_in_progress(struct p2p_data *p2p);
-/**
- * p2p_other_scan_completed - Notify completion of non-P2P scan
- * @p2p: P2P module context from p2p_init()
- * Returns: 0 if P2P module is idle or 1 if an operation was started
- */
-int p2p_other_scan_completed(struct p2p_data *p2p);
-
const char * p2p_wps_method_text(enum p2p_wps_method method);
/**
@@ -1833,8 +1837,6 @@
void p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout,
u8 client_timeout);
-void p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay);
-
int p2p_set_wfd_ie_beacon(struct p2p_data *p2p, struct wpabuf *ie);
int p2p_set_wfd_ie_probe_req(struct p2p_data *p2p, struct wpabuf *ie);
int p2p_set_wfd_ie_probe_resp(struct p2p_data *p2p, struct wpabuf *ie);
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 008651e..0e688a9 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -1040,6 +1040,7 @@
wpabuf_head(conf), wpabuf_len(conf), 0) < 0) {
p2p_dbg(p2p, "Failed to send Action frame");
p2p_go_neg_failed(p2p, dev, -1);
+ p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
}
wpabuf_free(conf);
if (status != P2P_SC_SUCCESS) {
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index e980be6..fef223f 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -23,7 +23,7 @@
*/
struct p2p_device {
struct dl_list list;
- struct os_time last_seen;
+ struct os_reltime last_seen;
int listen_freq;
enum p2p_wps_method wps_method;
@@ -205,16 +205,6 @@
* P2P_INVITE_LISTEN - Listen during Invite
*/
P2P_INVITE_LISTEN,
-
- /**
- * P2P_SEARCH_WHEN_READY - Waiting to start Search
- */
- P2P_SEARCH_WHEN_READY,
-
- /**
- * P2P_CONTINUE_SEARCH_WHEN_READY - Waiting to continue Search
- */
- P2P_CONTINUE_SEARCH_WHEN_READY,
} state;
/**
@@ -403,7 +393,7 @@
u8 *find_dev_id;
u8 find_dev_id_buf[ETH_ALEN];
- struct os_time find_start; /* time of last p2p_find start */
+ struct os_reltime find_start; /* time of last p2p_find start */
struct p2p_group **groups;
size_t num_groups;
@@ -726,7 +716,7 @@
void p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
struct p2p_device *dev, struct p2p_message *msg);
int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
- struct os_time *rx_time, int level, const u8 *ies,
+ struct os_reltime *rx_time, int level, const u8 *ies,
size_t ies_len, int scan_res);
struct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr);
struct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index 290c7c8..7625996 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -122,7 +122,7 @@
/**
* last_attempt - Time of the last transmission attempt
*/
- struct os_time last_attempt;
+ struct os_reltime last_attempt;
/**
* shared_secret - Shared secret with the target RADIUS server
@@ -351,7 +351,7 @@
HOSTAPD_LEVEL_DEBUG, "Resending RADIUS message (id=%d)",
radius_msg_get_hdr(entry->msg)->identifier);
- os_get_time(&entry->last_attempt);
+ os_get_reltime(&entry->last_attempt);
buf = radius_msg_get_buf(entry->msg);
if (send(s, wpabuf_head(buf), wpabuf_len(buf), 0) < 0)
radius_client_handle_send_error(radius, s, entry->msg_type);
@@ -373,7 +373,7 @@
{
struct radius_client_data *radius = eloop_ctx;
struct hostapd_radius_servers *conf = radius->conf;
- struct os_time now;
+ struct os_reltime now;
os_time_t first;
struct radius_msg_list *entry, *prev, *tmp;
int auth_failover = 0, acct_failover = 0;
@@ -383,7 +383,7 @@
if (!entry)
return;
- os_get_time(&now);
+ os_get_reltime(&now);
first = 0;
prev = NULL;
@@ -481,7 +481,7 @@
static void radius_client_update_timeout(struct radius_client_data *radius)
{
- struct os_time now;
+ struct os_reltime now;
os_time_t first;
struct radius_msg_list *entry;
@@ -497,7 +497,7 @@
first = entry->next_try;
}
- os_get_time(&now);
+ os_get_reltime(&now);
if (first < now.sec)
first = now.sec;
eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius,
@@ -536,7 +536,7 @@
entry->msg_type = msg_type;
entry->shared_secret = shared_secret;
entry->shared_secret_len = shared_secret_len;
- os_get_time(&entry->last_attempt);
+ os_get_reltime(&entry->last_attempt);
entry->first_try = entry->last_attempt.sec;
entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT;
entry->attempts = 1;
@@ -692,7 +692,7 @@
struct radius_rx_handler *handlers;
size_t num_handlers, i;
struct radius_msg_list *req, *prev_req;
- struct os_time now;
+ struct os_reltime now;
struct hostapd_radius_server *rconf;
int invalid_authenticator = 0;
@@ -772,7 +772,7 @@
goto fail;
}
- os_get_time(&now);
+ os_get_reltime(&now);
roundtrip = (now.sec - req->last_attempt.sec) * 100 +
(now.usec - req->last_attempt.usec) / 10000;
hostapd_logger(radius->ctx, req->addr, HOSTAPD_MODULE_RADIUS,
diff --git a/src/radius/radius_das.c b/src/radius/radius_das.c
index 418b160..b2a2773 100644
--- a/src/radius/radius_das.c
+++ b/src/radius/radius_das.c
@@ -16,9 +16,6 @@
#include "radius_das.h"
-extern int wpa_debug_level;
-
-
struct radius_das_data {
int sock;
u8 *shared_secret;
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index fe19770..1063d65 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -244,7 +244,7 @@
/**
* start_time - Timestamp of server start
*/
- struct os_time start_time;
+ struct os_reltime start_time;
/**
* counters - Statistics counters for server operations
@@ -298,8 +298,6 @@
};
-extern int wpa_debug_level;
-
#define RADIUS_DEBUG(args...) \
wpa_printf(MSG_DEBUG, "RADIUS SRV: " args)
#define RADIUS_ERROR(args...) \
@@ -1261,7 +1259,7 @@
if (data == NULL)
return NULL;
- os_get_time(&data->start_time);
+ os_get_reltime(&data->start_time);
data->conf_ctx = conf->conf_ctx;
data->eap_sim_db_priv = conf->eap_sim_db_priv;
data->ssl_ctx = conf->ssl_ctx;
@@ -1375,7 +1373,7 @@
int ret, uptime;
unsigned int idx;
char *end, *pos;
- struct os_time now;
+ struct os_reltime now;
struct radius_client *cli;
/* RFC 2619 - RADIUS Authentication Server MIB */
@@ -1386,7 +1384,7 @@
pos = buf;
end = buf + buflen;
- os_get_time(&now);
+ os_get_reltime(&now);
uptime = (now.sec - data->start_time.sec) * 100 +
((now.usec - data->start_time.usec) / 10000) % 100;
ret = os_snprintf(pos, end - pos,
diff --git a/src/rsn_supp/peerkey.c b/src/rsn_supp/peerkey.c
index 789ac25..cb86dfb 100644
--- a/src/rsn_supp/peerkey.c
+++ b/src/rsn_supp/peerkey.c
@@ -516,7 +516,6 @@
struct wpa_peerkey *peerkey;
struct wpa_eapol_ie_parse kde;
u32 lifetime;
- struct os_time now;
if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
@@ -568,10 +567,8 @@
lifetime = WPA_GET_BE32(kde.lifetime);
wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime);
if (lifetime > 1000000000)
- lifetime = 1000000000; /* avoid overflowing expiration time */
+ lifetime = 1000000000; /* avoid overflowing eloop time */
peerkey->lifetime = lifetime;
- os_get_time(&now);
- peerkey->expiration = now.sec + lifetime;
eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
sm, peerkey);
@@ -736,7 +733,6 @@
struct wpa_eapol_ie_parse *kde)
{
u32 lifetime;
- struct os_time now;
if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime))
return;
@@ -755,8 +751,6 @@
lifetime, peerkey->lifetime);
peerkey->lifetime = lifetime;
- os_get_time(&now);
- peerkey->expiration = now.sec + lifetime;
eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
sm, peerkey);
@@ -1116,7 +1110,7 @@
while (peerkey) {
prev = peerkey;
peerkey = peerkey->next;
- os_free(prev);
+ wpa_supplicant_peerkey_free(sm, prev);
}
sm->peerkey = NULL;
}
diff --git a/src/rsn_supp/peerkey.h b/src/rsn_supp/peerkey.h
index b8845f7..f420691 100644
--- a/src/rsn_supp/peerkey.h
+++ b/src/rsn_supp/peerkey.h
@@ -24,7 +24,6 @@
int smk_complete;
u8 smkid[PMKID_LEN];
u32 lifetime;
- os_time_t expiration;
int cipher; /* Selected cipher (WPA_CIPHER_*) */
u8 replay_counter[WPA_REPLAY_COUNTER_LEN];
int replay_counter_set;
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index 33fa1a2..0960815 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -53,9 +53,9 @@
static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
{
struct rsn_pmksa_cache *pmksa = eloop_ctx;
- struct os_time now;
+ struct os_reltime now;
- os_get_time(&now);
+ os_get_reltime(&now);
while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
pmksa->pmksa = entry->next;
@@ -80,13 +80,13 @@
{
int sec;
struct rsn_pmksa_cache_entry *entry;
- struct os_time now;
+ struct os_reltime now;
eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL);
if (pmksa->pmksa == NULL)
return;
- os_get_time(&now);
+ os_get_reltime(&now);
sec = pmksa->pmksa->expiration - now.sec;
if (sec < 0)
sec = 0;
@@ -125,7 +125,7 @@
const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
{
struct rsn_pmksa_cache_entry *entry, *pos, *prev;
- struct os_time now;
+ struct os_reltime now;
if (pmk_len > PMK_LEN)
return NULL;
@@ -137,7 +137,7 @@
entry->pmk_len = pmk_len;
rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
wpa_key_mgmt_sha256(akmp));
- os_get_time(&now);
+ os_get_reltime(&now);
entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime;
entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime *
pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100;
@@ -466,9 +466,9 @@
int i, ret;
char *pos = buf;
struct rsn_pmksa_cache_entry *entry;
- struct os_time now;
+ struct os_reltime now;
- os_get_time(&now);
+ os_get_reltime(&now);
ret = os_snprintf(pos, buf + len - pos,
"Index / AA / PMKID / expiration (in seconds) / "
"opportunistic\n");
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index d4f86e6..a294730 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -688,10 +688,11 @@
os_memcpy(gd.gtk, gtk, gtk_len);
gd.gtk_len = gtk_len;
- if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
- gtk_len, gtk_len,
- &gd.key_rsc_len, &gd.alg) ||
- wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) {
+ if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
+ (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
+ gtk_len, gtk_len,
+ &gd.key_rsc_len, &gd.alg) ||
+ wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: Failed to install GTK");
return -1;
@@ -1112,7 +1113,10 @@
}
wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
- if (ie.gtk &&
+ if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
+ wpa_supplicant_key_neg_complete(sm, sm->bssid,
+ key_info & WPA_KEY_INFO_SECURE);
+ } else if (ie.gtk &&
wpa_supplicant_pairwise_gtk(sm, key,
ie.gtk, ie.gtk_len, key_info) < 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
@@ -2094,6 +2098,7 @@
*/
void wpa_sm_notify_disassoc(struct wpa_sm *sm)
{
+ peerkey_deinit(sm);
rsn_preauth_deinit(sm);
pmksa_cache_clear_current(sm);
if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE)
@@ -2705,3 +2710,24 @@
return 0;
}
#endif /* CONFIG_WNM */
+
+
+#ifdef CONFIG_PEERKEY
+int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
+ const u8 *buf, size_t len)
+{
+ struct wpa_peerkey *peerkey;
+
+ for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
+ if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0)
+ break;
+ }
+
+ if (!peerkey)
+ return 0;
+
+ wpa_sm_rx_eapol(sm, src_addr, buf, len);
+
+ return 1;
+}
+#endif /* CONFIG_PEERKEY */
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index db7f0db..e189a58 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -306,11 +306,19 @@
#ifdef CONFIG_PEERKEY
int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer);
+int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
+ const u8 *buf, size_t len);
#else /* CONFIG_PEERKEY */
static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
{
return -1;
}
+
+static inline int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr,
+ const u8 *buf, size_t len)
+{
+ return 0;
+}
#endif /* CONFIG_PEERKEY */
#ifdef CONFIG_IEEE80211R
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 3a40c96..c8d8cfc 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -207,6 +207,8 @@
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK)
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
+ else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE)
+ RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
else {
wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)",
sm->key_mgmt);
@@ -400,8 +402,7 @@
}
}
- if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
- sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
+ if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
"enabled for this connection");
return -1;
@@ -526,8 +527,7 @@
if (sm == NULL)
return 0;
- if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
- sm->key_mgmt != WPA_KEY_MGMT_FT_PSK)
+ if (!wpa_key_mgmt_ft(sm->key_mgmt))
return 0;
return sm->ft_completed;
@@ -678,8 +678,7 @@
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
- if (sm->key_mgmt != WPA_KEY_MGMT_FT_IEEE8021X &&
- sm->key_mgmt != WPA_KEY_MGMT_FT_PSK) {
+ if (!wpa_key_mgmt_ft(sm->key_mgmt)) {
wpa_printf(MSG_DEBUG, "FT: Reject FT IEs since FT is not "
"enabled for this connection");
return -1;
diff --git a/src/utils/common.c b/src/utils/common.c
index 257bb6d..39751d4 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -735,3 +735,95 @@
return buf;
}
+
+
+int int_array_len(const int *a)
+{
+ int i;
+ for (i = 0; a && a[i]; i++)
+ ;
+ return i;
+}
+
+
+void int_array_concat(int **res, const int *a)
+{
+ int reslen, alen, i;
+ int *n;
+
+ reslen = int_array_len(*res);
+ alen = int_array_len(a);
+
+ n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
+ if (n == NULL) {
+ os_free(*res);
+ *res = NULL;
+ return;
+ }
+ for (i = 0; i <= alen; i++)
+ n[reslen + i] = a[i];
+ *res = n;
+}
+
+
+static int freq_cmp(const void *a, const void *b)
+{
+ int _a = *(int *) a;
+ int _b = *(int *) b;
+
+ if (_a == 0)
+ return 1;
+ if (_b == 0)
+ return -1;
+ return _a - _b;
+}
+
+
+void int_array_sort_unique(int *a)
+{
+ int alen;
+ int i, j;
+
+ if (a == NULL)
+ return;
+
+ alen = int_array_len(a);
+ qsort(a, alen, sizeof(int), freq_cmp);
+
+ i = 0;
+ j = 1;
+ while (a[i] && a[j]) {
+ if (a[i] == a[j]) {
+ j++;
+ continue;
+ }
+ a[++i] = a[j++];
+ }
+ if (a[i])
+ i++;
+ a[i] = 0;
+}
+
+
+void int_array_add_unique(int **res, int a)
+{
+ int reslen;
+ int *n;
+
+ for (reslen = 0; *res && (*res)[reslen]; reslen++) {
+ if ((*res)[reslen] == a)
+ return; /* already in the list */
+ }
+
+ n = os_realloc_array(*res, reslen + 2, sizeof(int));
+ if (n == NULL) {
+ os_free(*res);
+ *res = NULL;
+ return;
+ }
+
+ n[reslen] = a;
+ n[reslen + 1] = 0;
+
+ *res = n;
+}
diff --git a/src/utils/common.h b/src/utils/common.h
index 028a5ef..a85cc15 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -459,6 +459,14 @@
#endif /* __GNUC__ */
#endif /* __must_check */
+#ifndef __maybe_unused
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#define __maybe_unused __attribute__((unused))
+#else
+#define __maybe_unused
+#endif /* __GNUC__ */
+#endif /* __must_check */
+
int hwaddr_aton(const char *txt, u8 *addr);
int hwaddr_compact_aton(const char *txt, u8 *addr);
int hwaddr_aton2(const char *txt, u8 *addr);
@@ -519,6 +527,11 @@
unsigned int freq);
char * freq_range_list_str(const struct wpa_freq_range_list *list);
+int int_array_len(const int *a);
+void int_array_concat(int **res, const int *a);
+void int_array_sort_unique(int *a);
+void int_array_add_unique(int **res, int a);
+
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index e983edc..f83a232 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -623,10 +623,11 @@
user_data);
return 1;
}
+ return 0;
}
}
- return 0;
+ return -1;
}
@@ -654,10 +655,11 @@
user_data);
return 1;
}
+ return 0;
}
}
- return 0;
+ return -1;
}
diff --git a/src/utils/eloop.h b/src/utils/eloop.h
index d3980fa..07b8c0d 100644
--- a/src/utils/eloop.h
+++ b/src/utils/eloop.h
@@ -229,7 +229,8 @@
* @handler: Matching callback function
* @eloop_data: Matching eloop_data
* @user_data: Matching user_data
- * Returns: 1 if the timeout is depleted, 0 if no change is made
+ * Returns: 1 if the timeout is depleted, 0 if no change is made, -1 if no
+ * timeout matched
*
* Find a registered matching <handler,eloop_data,user_data> timeout. If found,
* deplete the timeout if remaining time is more than the requested time.
@@ -245,7 +246,8 @@
* @handler: Matching callback function
* @eloop_data: Matching eloop_data
* @user_data: Matching user_data
- * Returns: 1 if the timeout is replenished, 0 if no change is made
+ * Returns: 1 if the timeout is replenished, 0 if no change is made, -1 if no
+ * timeout matched
*
* Find a registered matching <handler,eloop_data,user_data> timeout. If found,
* replenish the timeout if remaining time is less than the requested time.
diff --git a/src/utils/eloop_win.c b/src/utils/eloop_win.c
index a1f9996..de47fb2 100644
--- a/src/utils/eloop_win.c
+++ b/src/utils/eloop_win.c
@@ -378,10 +378,11 @@
user_data);
return 1;
}
+ return 0;
}
}
- return 0;
+ return -1;
}
@@ -409,10 +410,11 @@
user_data);
return 1;
}
+ return 0;
}
}
- return 0;
+ return -1;
}
diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c
index 38ea8aa..7846c1e 100644
--- a/src/utils/wpa_debug.c
+++ b/src/utils/wpa_debug.c
@@ -375,19 +375,19 @@
#endif /* CONFIG_ANDROID_LOG */
}
-void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len)
+void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
{
_wpa_hexdump(level, title, buf, len, 1);
}
-void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
+void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len)
{
_wpa_hexdump(level, title, buf, len, wpa_debug_show_keys);
}
-static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
+static void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
size_t len, int show)
{
size_t i, llen;
@@ -407,7 +407,7 @@
/* can do ascii processing in userspace */
for (i = 0; i < len; i++)
fprintf(wpa_debug_tracing_file,
- " %02x", buf[i]);
+ " %02x", pos[i]);
}
fflush(wpa_debug_tracing_file);
}
@@ -495,13 +495,14 @@
}
-void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len)
+void wpa_hexdump_ascii(int level, const char *title, const void *buf,
+ size_t len)
{
_wpa_hexdump_ascii(level, title, buf, len, 1);
}
-void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
+void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
size_t len)
{
_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
diff --git a/src/utils/wpa_debug.h b/src/utils/wpa_debug.h
index 2ed1bd8..50e8ae9 100644
--- a/src/utils/wpa_debug.h
+++ b/src/utils/wpa_debug.h
@@ -11,6 +11,10 @@
#include "wpabuf.h"
+extern int wpa_debug_level;
+extern int wpa_debug_show_keys;
+extern int wpa_debug_timestamp;
+
/* Debugging function - conditional printf and hex dump. Driver wrappers can
* use these for debugging purposes. */
@@ -77,7 +81,7 @@
* output may be directed to stdout, stderr, and/or syslog based on
* configuration. The contents of buf is printed out has hex dump.
*/
-void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
+void wpa_hexdump(int level, const char *title, const void *buf, size_t len);
static inline void wpa_hexdump_buf(int level, const char *title,
const struct wpabuf *buf)
@@ -99,7 +103,7 @@
* like wpa_hexdump(), but by default, does not include secret keys (passwords,
* etc.) in debug output.
*/
-void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);
+void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len);
static inline void wpa_hexdump_buf_key(int level, const char *title,
const struct wpabuf *buf)
@@ -121,7 +125,7 @@
* the hex numbers and ASCII characters (for printable range) are shown. 16
* bytes per line will be shown.
*/
-void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
+void wpa_hexdump_ascii(int level, const char *title, const void *buf,
size_t len);
/**
@@ -138,7 +142,7 @@
* bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
* default, does not include secret keys (passwords, etc.) in debug output.
*/
-void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
+void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
size_t len);
/*
diff --git a/src/wps/httpread.c b/src/wps/httpread.c
index ad4f4a1..b51d975 100644
--- a/src/wps/httpread.c
+++ b/src/wps/httpread.c
@@ -67,8 +67,6 @@
int timeout_seconds; /* 0 or total duration timeout period */
/* dynamically used information follows */
- int sd_registered; /* nonzero if we need to unregister socket */
- int to_registered; /* nonzero if we need to unregister timeout */
int got_hdr; /* nonzero when header is finalized */
char hdr[HTTPREAD_HEADER_MAX_SIZE+1]; /* headers stored here */
@@ -129,19 +127,6 @@
}
-/* convert hex to binary
- * Requires that c have been previously tested true with isxdigit().
- */
-static int hex_value(int c)
-{
- if (isdigit(c))
- return c - '0';
- if (islower(c))
- return 10 + c - 'a';
- return 10 + c - 'A';
-}
-
-
static void httpread_timeout_handler(void *eloop_data, void *user_ctx);
/* httpread_destroy -- if h is non-NULL, clean up
@@ -156,12 +141,8 @@
if (!h)
return;
- if (h->to_registered)
- eloop_cancel_timeout(httpread_timeout_handler, NULL, h);
- h->to_registered = 0;
- if (h->sd_registered)
- eloop_unregister_sock(h->sd, EVENT_TYPE_READ);
- h->sd_registered = 0;
+ eloop_cancel_timeout(httpread_timeout_handler, NULL, h);
+ eloop_unregister_sock(h->sd, EVENT_TYPE_READ);
os_free(h->body);
os_free(h->uri);
os_memset(h, 0, sizeof(*h)); /* aid debugging */
@@ -176,7 +157,6 @@
{
struct httpread *h = user_ctx;
wpa_printf(MSG_DEBUG, "httpread timeout (%p)", h);
- h->to_registered = 0; /* is self-cancelling */
(*h->cb)(h, h->cookie, HTTPREAD_EVENT_TIMEOUT);
}
@@ -295,8 +275,7 @@
int c = *rawuri;
if (c == '%' &&
isxdigit(rawuri[1]) && isxdigit(rawuri[2])) {
- *uri++ = (hex_value(rawuri[1]) << 4) |
- hex_value(rawuri[2]);
+ *uri++ = hex2byte(rawuri + 1);
rawuri += 3;
} else {
*uri++ = c;
@@ -703,15 +682,11 @@
* and just in case somehow we don't get destroyed right away,
* unregister now.
*/
- if (h->sd_registered)
- eloop_unregister_sock(h->sd, EVENT_TYPE_READ);
- h->sd_registered = 0;
+ eloop_unregister_sock(h->sd, EVENT_TYPE_READ);
/* The application can destroy us whenever they feel like...
* cancel timeout.
*/
- if (h->to_registered)
- eloop_cancel_timeout(httpread_timeout_handler, NULL, h);
- h->to_registered = 0;
+ eloop_cancel_timeout(httpread_timeout_handler, NULL, h);
(*h->cb)(h, h->cookie, HTTPREAD_EVENT_FILE_READY);
}
@@ -749,21 +724,17 @@
h->max_bytes = max_bytes;
h->timeout_seconds = timeout_seconds;
- if (timeout_seconds > 0) {
- if (eloop_register_timeout(timeout_seconds, 0,
- httpread_timeout_handler,
- NULL, h)) {
- /* No way to recover (from malloc failure) */
- goto fail;
- }
- h->to_registered = 1;
+ if (timeout_seconds > 0 &&
+ eloop_register_timeout(timeout_seconds, 0,
+ httpread_timeout_handler, NULL, h)) {
+ /* No way to recover (from malloc failure) */
+ goto fail;
}
if (eloop_register_sock(sd, EVENT_TYPE_READ, httpread_read_handler,
NULL, h)) {
/* No way to recover (from malloc failure) */
goto fail;
}
- h->sd_registered = 1;
return h;
fail:
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index b232754..336246e 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -201,6 +201,11 @@
#ifdef CONFIG_WPS2
u8 *len;
+#ifdef CONFIG_WPS_TESTING
+ if (WPS_VERSION == 0x10)
+ return 0;
+#endif /* CONFIG_WPS_TESTING */
+
if (wpabuf_tailroom(msg) <
7 + 3 + (req_to_enroll ? 3 : 0) +
(auth_macs ? 2 + auth_macs_count * ETH_ALEN : 0))
diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c
index 1b12b5a..fe736f3 100644
--- a/src/wps/wps_dev_attr.c
+++ b/src/wps/wps_dev_attr.c
@@ -409,25 +409,6 @@
}
-void wps_device_data_dup(struct wps_device_data *dst,
- const struct wps_device_data *src)
-{
- if (src->device_name)
- dst->device_name = os_strdup(src->device_name);
- if (src->manufacturer)
- dst->manufacturer = os_strdup(src->manufacturer);
- if (src->model_name)
- dst->model_name = os_strdup(src->model_name);
- if (src->model_number)
- dst->model_number = os_strdup(src->model_number);
- if (src->serial_number)
- dst->serial_number = os_strdup(src->serial_number);
- os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN);
- dst->os_version = src->os_version;
- dst->rf_bands = src->rf_bands;
-}
-
-
void wps_device_data_free(struct wps_device_data *dev)
{
os_free(dev->device_name);
diff --git a/src/wps/wps_dev_attr.h b/src/wps/wps_dev_attr.h
index 0158cdc..f0169a7 100644
--- a/src/wps/wps_dev_attr.h
+++ b/src/wps/wps_dev_attr.h
@@ -29,8 +29,6 @@
struct wps_parse_attr *attr);
int wps_process_os_version(struct wps_device_data *dev, const u8 *ver);
int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands);
-void wps_device_data_dup(struct wps_device_data *dst,
- const struct wps_device_data *src);
void wps_device_data_free(struct wps_device_data *dev);
int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg);
int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg,
diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c
index 5694997..e729617 100644
--- a/src/wps/wps_er.c
+++ b/src/wps/wps_er.c
@@ -185,10 +185,8 @@
dl_list_del(&ap->list);
wps_er_ap_free(ap);
- if (er->deinitializing && dl_list_empty(&er->ap_unsubscribing)) {
- eloop_cancel_timeout(wps_er_deinit_finish, er, NULL);
+ if (er->deinitializing && dl_list_empty(&er->ap_unsubscribing))
wps_er_deinit_finish(er, NULL);
- }
}
@@ -1347,9 +1345,19 @@
struct wps_er *er = eloop_data;
void (*deinit_done_cb)(void *ctx);
void *deinit_done_ctx;
+ struct wps_er_ap *ap, *tmp;
wpa_printf(MSG_DEBUG, "WPS ER: Finishing deinit");
+ dl_list_for_each_safe(ap, tmp, &er->ap_unsubscribing, struct wps_er_ap,
+ list) {
+ wpa_printf(MSG_DEBUG, "WPS ER: AP entry for %s (%s) still in ap_unsubscribing list - free it",
+ inet_ntoa(ap->addr), ap->location);
+ dl_list_del(&ap->list);
+ wps_er_ap_free(ap);
+ }
+
+ eloop_cancel_timeout(wps_er_deinit_finish, er, NULL);
deinit_done_cb = er->deinit_done_cb;
deinit_done_ctx = er->deinit_done_ctx;
os_free(er->ip_addr_text);
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index ef17617..19490a1 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -82,7 +82,7 @@
#define PIN_LOCKED BIT(0)
#define PIN_EXPIRES BIT(1)
int flags;
- struct os_time expiration;
+ struct os_reltime expiration;
u8 enrollee_addr[ETH_ALEN];
};
@@ -113,7 +113,7 @@
struct wps_pbc_session *next;
u8 addr[ETH_ALEN];
u8 uuid_e[WPS_UUID_LEN];
- struct os_time timestamp;
+ struct os_reltime timestamp;
};
@@ -183,7 +183,9 @@
u8 p2p_dev_addr[ETH_ALEN];
u8 pbc_ignore_uuid[WPS_UUID_LEN];
- struct os_time pbc_ignore_start;
+#ifdef WPS_WORKAROUNDS
+ struct os_reltime pbc_ignore_start;
+#endif /* WPS_WORKAROUNDS */
};
@@ -311,9 +313,9 @@
const u8 *addr, const u8 *uuid_e)
{
struct wps_pbc_session *pbc, *prev = NULL;
- struct os_time now;
+ struct os_reltime now;
- os_get_time(&now);
+ os_get_reltime(&now);
pbc = reg->pbc_sessions;
while (pbc) {
@@ -347,7 +349,8 @@
pbc = pbc->next;
while (pbc) {
- if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) {
+ if (os_reltime_expired(&now, &pbc->timestamp,
+ WPS_PBC_WALK_TIME)) {
prev->next = NULL;
wps_free_pbc_sessions(pbc);
break;
@@ -395,9 +398,9 @@
int count = 0;
struct wps_pbc_session *pbc;
struct wps_pbc_session *first = NULL;
- struct os_time now;
+ struct os_reltime now;
- os_get_time(&now);
+ os_get_reltime(&now);
wpa_printf(MSG_DEBUG, "WPS: Checking active PBC sessions for overlap");
@@ -413,9 +416,9 @@
MAC2STR(pbc->addr));
wpa_hexdump(MSG_DEBUG, "WPS: UUID-E",
pbc->uuid_e, WPS_UUID_LEN);
- if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) {
- wpa_printf(MSG_DEBUG, "WPS: PBC walk time has "
- "expired");
+ if (os_reltime_expired(&now, &pbc->timestamp,
+ WPS_PBC_WALK_TIME)) {
+ wpa_printf(MSG_DEBUG, "WPS: PBC walk time has expired");
break;
}
if (first &&
@@ -748,7 +751,7 @@
if (timeout) {
p->flags |= PIN_EXPIRES;
- os_get_time(&p->expiration);
+ os_get_reltime(&p->expiration);
p->expiration.sec += timeout;
}
@@ -797,13 +800,13 @@
static void wps_registrar_expire_pins(struct wps_registrar *reg)
{
struct wps_uuid_pin *pin, *prev;
- struct os_time now;
+ struct os_reltime now;
- os_get_time(&now);
+ os_get_reltime(&now);
dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list)
{
if ((pin->flags & PIN_EXPIRES) &&
- os_time_before(&pin->expiration, &now)) {
+ os_reltime_before(&pin->expiration, &now)) {
wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID",
pin->uuid, WPS_UUID_LEN);
wps_registrar_remove_pin(reg, pin);
@@ -1037,7 +1040,9 @@
wps_registrar_remove_pbc_session(registrar,
uuid_e, NULL);
wps_registrar_pbc_completed(registrar);
- os_get_time(®istrar->pbc_ignore_start);
+#ifdef WPS_WORKAROUNDS
+ os_get_reltime(®istrar->pbc_ignore_start);
+#endif /* WPS_WORKAROUNDS */
os_memcpy(registrar->pbc_ignore_uuid, uuid_e, WPS_UUID_LEN);
} else {
wps_registrar_pin_completed(registrar);
@@ -1140,9 +1145,9 @@
#ifdef WPS_WORKAROUNDS
if (reg->pbc_ignore_start.sec &&
os_memcmp(attr.uuid_e, reg->pbc_ignore_uuid, WPS_UUID_LEN) == 0) {
- struct os_time now, dur;
- os_get_time(&now);
- os_time_sub(&now, ®->pbc_ignore_start, &dur);
+ struct os_reltime now, dur;
+ os_get_reltime(&now);
+ os_reltime_sub(&now, ®->pbc_ignore_start, &dur);
if (dur.sec >= 0 && dur.sec < 5) {
wpa_printf(MSG_DEBUG, "WPS: Ignore PBC activation "
"based on Probe Request from the Enrollee "
@@ -3189,7 +3194,9 @@
wps->uuid_e,
wps->p2p_dev_addr);
wps_registrar_pbc_completed(wps->wps->registrar);
- os_get_time(&wps->wps->registrar->pbc_ignore_start);
+#ifdef WPS_WORKAROUNDS
+ os_get_reltime(&wps->wps->registrar->pbc_ignore_start);
+#endif /* WPS_WORKAROUNDS */
os_memcpy(wps->wps->registrar->pbc_ignore_uuid, wps->uuid_e,
WPS_UUID_LEN);
} else {
@@ -3446,7 +3453,7 @@
struct wps_credential *cred)
{
#ifdef CONFIG_WPS2
- printf("encr_type=0x%x\n", cred->encr_type);
+ wpa_printf(MSG_DEBUG, "WPS: encr_type=0x%x", cred->encr_type);
if (!(cred->encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP |
WPS_ENCR_AES))) {
if (cred->encr_type & WPS_ENCR_WEP) {
diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c
index bea2b33..6fb3d4c 100644
--- a/src/wps/wps_upnp.c
+++ b/src/wps/wps_upnp.c
@@ -432,23 +432,6 @@
}
-int send_wpabuf(int fd, struct wpabuf *buf)
-{
- wpa_printf(MSG_DEBUG, "WPS UPnP: Send %lu byte message",
- (unsigned long) wpabuf_len(buf));
- errno = 0;
- if (write(fd, wpabuf_head(buf), wpabuf_len(buf)) !=
- (int) wpabuf_len(buf)) {
- wpa_printf(MSG_ERROR, "WPS UPnP: Failed to send buffer: "
- "errno=%d (%s)",
- errno, strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
-
static void wpabuf_put_property(struct wpabuf *buf, const char *name,
const char *value)
{
@@ -480,14 +463,14 @@
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
const char *format_tail = "</e:propertyset>\n";
- struct os_time now;
+ struct os_reltime now;
if (dl_list_empty(&sm->subscriptions)) {
/* optimize */
return;
}
- if (os_get_time(&now) == 0) {
+ if (os_get_reltime(&now) == 0) {
if (now.sec != sm->last_event_sec) {
sm->last_event_sec = now.sec;
sm->num_events_in_sec = 1;
diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h
index 5c39f7e..f289fe6 100644
--- a/src/wps/wps_upnp_i.h
+++ b/src/wps/wps_upnp_i.h
@@ -158,7 +158,6 @@
struct subscription * subscription_find(struct upnp_wps_device_sm *sm,
const u8 uuid[UUID_LEN]);
void subscr_addr_delete(struct subscr_addr *a);
-int send_wpabuf(int fd, struct wpabuf *buf);
int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text,
u8 mac[ETH_ALEN]);
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 260c0ae..2c709c3 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -10,11 +10,17 @@
export BINDIR ?= /usr/local/sbin/
PKG_CONFIG ?= pkg-config
-CFLAGS += -I../src
-CFLAGS += -I../src/utils
+CFLAGS += -I$(abspath ../src)
+CFLAGS += -I$(abspath ../src/utils)
-include .config
+ifdef CONFIG_TESTING_OPTIONS
+CFLAGS += -DCONFIG_TESTING_OPTIONS
+CONFIG_WPS_TESTING=y
+CONFIG_TDLS_TESTING=y
+endif
+
BINALL=wpa_supplicant wpa_cli
ifndef CONFIG_NO_WPA_PASSPHRASE
@@ -1622,9 +1628,15 @@
$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \
-D$(*F:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init
+ifdef CONFIG_CODE_COVERAGE
+%.o: %.c
+ @$(E) " CC " $<
+ $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
+else
%.o: %.c
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
+endif
%.service: %.service.in
sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
@@ -1676,6 +1688,10 @@
fips:
$(MAKE) CC=$(FIPSLD) FIPSLD_CC="$(CC)"
+lcov-html: wpa_supplicant.gcda
+ lcov -c -d .. > lcov.info
+ genhtml lcov.info --output-directory lcov-html
+
clean:
$(MAKE) -C ../src clean
$(MAKE) -C dbus clean
@@ -1683,5 +1699,7 @@
rm -f eap_*.so $(ALL) $(WINALL) eapol_test preauth_test
rm -f wpa_priv
rm -f nfc_pw_token
+ rm -f lcov.info
+ rm -rf lcov-html
-include $(OBJS:%.o=%.d)
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index 8e9cc45..7f88cd6 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -1,7 +1,7 @@
WPA Supplicant
==============
-Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
@@ -983,3 +983,71 @@
suitable mode to allow wpa_supplicant to create sockets
there. Alternatively, other directory or abstract socket namespace could
be used for the control interface.
+
+
+External requests for radio control
+-----------------------------------
+
+External programs can request wpa_supplicant to not start offchannel
+operations during other tasks that may need exclusive control of the
+radio. The RADIO_WORK control interface command can be used for this.
+
+"RADIO_WORK add <name> [freq=<MHz>] [timeout=<seconds>]" command can be
+used to reserve a slot for radio access. If freq is specified, other
+radio work items on the same channel may be completed in
+parallel. Otherwise, all other radio work items are blocked during
+execution. Timeout is set to 10 seconds by default to avoid blocking
+wpa_supplicant operations for excessive time. If a longer (or shorter)
+safety timeout is needed, that can be specified with the optional
+timeout parameter. This command returns an identifier for the radio work
+item.
+
+Once the radio work item has been started, "EXT-RADIO-WORK-START <id>"
+event message is indicated that the external processing can start. Once
+the operation has been completed, "RADIO_WORK done <id>" is used to
+indicate that to wpa_supplicant. This allows other radio works to be
+performed. If this command is forgotten (e.g., due to the external
+program terminating), wpa_supplicant will time out the radio owrk item
+and send "EXT-RADIO-WORK-TIMEOUT <id>" event ot indicate that this has
+happened. "RADIO_WORK done <id>" can also be used to cancel items that
+have not yet been started.
+
+For example, in wpa_cli interactive mode:
+
+> radio_work add test
+1
+<3>EXT-RADIO-WORK-START 1
+> radio_work show
+ext:test@wlan0:0:1:2.487797
+> radio_work done 1
+OK
+> radio_work show
+
+
+> radio_work done 3
+OK
+> radio_work show
+ext:test freq=2412 timeout=30@wlan0:2412:1:28.583483
+<3>EXT-RADIO-WORK-TIMEOUT 2
+
+
+> radio_work add test2 freq=2412 timeout=60
+5
+<3>EXT-RADIO-WORK-START 5
+> radio_work add test3
+6
+> radio_work add test4
+7
+> radio_work show
+ext:test2 freq=2412 timeout=60@wlan0:2412:1:9.751844
+ext:test3@wlan0:0:0:5.071812
+ext:test4@wlan0:0:0:3.143870
+> radio_work done 6
+OK
+> radio_work show
+ext:test2 freq=2412 timeout=60@wlan0:2412:1:16.287869
+ext:test4@wlan0:0:0:9.679895
+> radio_work done 5
+OK
+<3>EXT-RADIO-WORK-START 7
+<3>EXT-RADIO-WORK-TIMEOUT 7
diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20
index 61e4a4d..ad29ef7 100644
--- a/wpa_supplicant/README-HS20
+++ b/wpa_supplicant/README-HS20
@@ -109,6 +109,8 @@
#
# credential fields:
#
+# temporary: Whether this credential is temporary and not to be saved
+#
# priority: Priority group
# By default, all networks and credentials get the same priority group
# (0). This field can be used to give higher priority for credentials
@@ -269,6 +271,8 @@
OK
> set_cred 0 priority 1
OK
+> set_cred 0 temporary 1
+OK
Add a SIM credential using a simulated SIM/USIM card for testing:
diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P
index ffc2baf..08d39e2 100644
--- a/wpa_supplicant/README-P2P
+++ b/wpa_supplicant/README-P2P
@@ -418,9 +418,11 @@
Send a P2P Presence Request to the GO (this is only available when
acting as a P2P client). If no duration/interval pairs are given, the
request indicates that this client has no special needs for GO
-presence. the first parameter pair gives the preferred duration and
+presence. The first parameter pair gives the preferred duration and
interval values in microseconds. If the second pair is included, that
-indicates which value would be acceptable.
+indicates which value would be acceptable. This command returns OK
+immediately and the response from the GO is indicated in a
+P2P-PRESENCE-RESPONSE event message.
Parameters
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 501137c..ec7df03 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -20,63 +20,6 @@
# used to fix build issues on such systems (krb5.h not found).
#CFLAGS += -I/usr/include/kerberos
-# Example configuration for various cross-compilation platforms
-
-#### sveasoft (e.g., for Linksys WRT54G) ######################################
-#CC=mipsel-uclibc-gcc
-#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
-#CFLAGS += -Os
-#CPPFLAGS += -I../src/include -I../../src/router/openssl/include
-#LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl
-###############################################################################
-
-#### openwrt (e.g., for Linksys WRT54G) #######################################
-#CC=mipsel-uclibc-gcc
-#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
-#CFLAGS += -Os
-#CPPFLAGS=-I../src/include -I../openssl-0.9.7d/include \
-# -I../WRT54GS/release/src/include
-#LIBS = -lssl
-###############################################################################
-
-
-# Driver interface for Host AP driver
-#CONFIG_DRIVER_HOSTAP=y
-
-# Driver interface for Agere driver
-#CONFIG_DRIVER_HERMES=y
-# Change include directories to match with the local setup
-#CFLAGS += -I../../hcf -I../../include -I../../include/hcf
-#CFLAGS += -I../../include/wireless
-
-# Driver interface for madwifi driver
-# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
-#CONFIG_DRIVER_MADWIFI=y
-# Set include directory to the madwifi source tree
-#CFLAGS += -I../../madwifi
-
-# Driver interface for ndiswrapper
-# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
-#CONFIG_DRIVER_NDISWRAPPER=y
-
-# Driver interface for Atmel driver
-#CONFIG_DRIVER_ATMEL=y
-
-# Driver interface for old Broadcom driver
-# Please note that the newer Broadcom driver ("hybrid Linux driver") supports
-# Linux wireless extensions and does not need (or even work) with the old
-# driver wrapper. Use CONFIG_DRIVER_WEXT=y with that driver.
-#CONFIG_DRIVER_BROADCOM=y
-# Example path for wlioctl.h; change to match your configuration
-#CFLAGS += -I/opt/WRT54GS/release/src/include
-
-# Driver interface for Intel ipw2100/2200 driver
-# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
-#CONFIG_DRIVER_IPW=y
-
-# Driver interface for Ralink driver
-#CONFIG_DRIVER_RALINK=y
-
# Driver interface for generic Linux wireless extensions
# Note: WEXT is deprecated in the current Linux kernel version and no new
# functionality is added to it. nl80211-based interface is the new
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 394ab30..ea4e6bb 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -276,7 +276,9 @@
if (bss->wpa_group_rekey < 86400 && (bss->wpa & 2) &&
(bss->wpa_group == WPA_CIPHER_CCMP ||
- bss->wpa_group == WPA_CIPHER_GCMP)) {
+ bss->wpa_group == WPA_CIPHER_GCMP ||
+ bss->wpa_group == WPA_CIPHER_CCMP_256 ||
+ bss->wpa_group == WPA_CIPHER_GCMP_256)) {
/*
* Strong ciphers do not need frequent rekeying, so increase
* the default GTK rekeying period to 24 hours.
@@ -511,7 +513,7 @@
wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
else
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
- params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
+ params.key_mgmt_suite = wpa_s->key_mgmt;
wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher,
1);
@@ -520,8 +522,7 @@
"cipher.");
return -1;
}
- params.pairwise_suite =
- wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher);
+ params.pairwise_suite = wpa_s->pairwise_cipher;
params.group_suite = params.pairwise_suite;
#ifdef CONFIG_P2P
@@ -679,6 +680,8 @@
{
#ifdef NEED_AP_MLME
struct wpa_supplicant *wpa_s = ctx;
+ if (!wpa_s->ap_iface)
+ return;
hostapd_tx_status(wpa_s->ap_iface->bss[0], dst, data, len, ack);
#endif /* NEED_AP_MLME */
}
diff --git a/wpa_supplicant/bgscan_learn.c b/wpa_supplicant/bgscan_learn.c
index 07d31e4..6a92b73 100644
--- a/wpa_supplicant/bgscan_learn.c
+++ b/wpa_supplicant/bgscan_learn.c
@@ -34,7 +34,7 @@
int signal_threshold;
int short_interval; /* use if signal < threshold */
int long_interval; /* use if signal > threshold */
- struct os_time last_bgscan;
+ struct os_reltime last_bgscan;
char *fname;
struct dl_list bss;
int *supp_freqs;
@@ -240,17 +240,14 @@
if (data->supp_freqs == NULL)
return freqs;
- idx = data->probe_idx + 1;
- while (idx != data->probe_idx) {
- if (data->supp_freqs[idx] == 0) {
- if (data->probe_idx == 0)
- break;
- idx = 0;
- }
+ idx = data->probe_idx;
+ do {
if (!in_array(freqs, data->supp_freqs[idx])) {
wpa_printf(MSG_DEBUG, "bgscan learn: Probe new freq "
"%u", data->supp_freqs[idx]);
- data->probe_idx = idx;
+ data->probe_idx = idx + 1;
+ if (data->supp_freqs[data->probe_idx] == 0)
+ data->probe_idx = 0;
n = os_realloc_array(freqs, count + 2, sizeof(int));
if (n == NULL)
return freqs;
@@ -262,7 +259,9 @@
}
idx++;
- }
+ if (data->supp_freqs[idx] == 0)
+ idx = 0;
+ } while (idx != data->probe_idx);
return freqs;
}
@@ -311,7 +310,7 @@
eloop_register_timeout(data->scan_interval, 0,
bgscan_learn_timeout, data, NULL);
} else
- os_get_time(&data->last_bgscan);
+ os_get_reltime(&data->last_bgscan);
os_free(freqs);
}
@@ -363,6 +362,9 @@
for (j = 0; j < modes[i].num_channels; j++) {
if (modes[i].channels[j].flag & HOSTAPD_CHAN_DISABLED)
continue;
+ /* some hw modes (e.g. 11b & 11g) contain same freqs */
+ if (in_array(freqs, modes[i].channels[j].freq))
+ continue;
n = os_realloc_array(freqs, count + 2, sizeof(int));
if (n == NULL)
continue;
@@ -419,6 +421,14 @@
data->supp_freqs = bgscan_learn_get_supp_freqs(wpa_s);
data->scan_interval = data->short_interval;
+ if (data->signal_threshold) {
+ /* Poll for signal info to set initial scan interval */
+ struct wpa_signal_info siginfo;
+ if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 &&
+ siginfo.current_signal >= data->signal_threshold)
+ data->scan_interval = data->long_interval;
+ }
+
eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout,
data, NULL);
@@ -428,7 +438,7 @@
* us skip an immediate new scan in cases where the current signal
* level is below the bgscan threshold.
*/
- os_get_time(&data->last_bgscan);
+ os_get_reltime(&data->last_bgscan);
return data;
}
@@ -555,7 +565,7 @@
{
struct bgscan_learn_data *data = priv;
int scan = 0;
- struct os_time now;
+ struct os_reltime now;
if (data->short_interval == data->long_interval ||
data->signal_threshold == 0)
@@ -569,7 +579,7 @@
wpa_printf(MSG_DEBUG, "bgscan learn: Start using short bgscan "
"interval");
data->scan_interval = data->short_interval;
- os_get_time(&now);
+ os_get_reltime(&now);
if (now.sec > data->last_bgscan.sec + 1)
scan = 1;
} else if (data->scan_interval == data->short_interval && above) {
@@ -584,7 +594,7 @@
* Signal dropped further 4 dB. Request a new scan if we have
* not yet scanned in a while.
*/
- os_get_time(&now);
+ os_get_reltime(&now);
if (now.sec > data->last_bgscan.sec + 10)
scan = 1;
}
diff --git a/wpa_supplicant/bgscan_simple.c b/wpa_supplicant/bgscan_simple.c
index 479f703..a467cc5 100644
--- a/wpa_supplicant/bgscan_simple.c
+++ b/wpa_supplicant/bgscan_simple.c
@@ -26,7 +26,7 @@
int max_short_scans; /* maximum times we short-scan before back-off */
int short_interval; /* use if signal < threshold */
int long_interval; /* use if signal > threshold */
- struct os_time last_bgscan;
+ struct os_reltime last_bgscan;
};
@@ -75,7 +75,7 @@
*/
data->short_scan_count--;
}
- os_get_time(&data->last_bgscan);
+ os_get_reltime(&data->last_bgscan);
}
}
@@ -159,7 +159,7 @@
* us skip an immediate new scan in cases where the current signal
* level is below the bgscan threshold.
*/
- os_get_time(&data->last_bgscan);
+ os_get_reltime(&data->last_bgscan);
return data;
}
@@ -211,7 +211,7 @@
{
struct bgscan_simple_data *data = priv;
int scan = 0;
- struct os_time now;
+ struct os_reltime now;
if (data->short_interval == data->long_interval ||
data->signal_threshold == 0)
@@ -225,7 +225,7 @@
wpa_printf(MSG_DEBUG, "bgscan simple: Start using short "
"bgscan interval");
data->scan_interval = data->short_interval;
- os_get_time(&now);
+ os_get_reltime(&now);
if (now.sec > data->last_bgscan.sec + 1 &&
data->short_scan_count <= data->max_short_scans)
/*
@@ -259,7 +259,7 @@
* Signal dropped further 4 dB. Request a new scan if we have
* not yet scanned in a while.
*/
- os_get_time(&now);
+ os_get_reltime(&now);
if (now.sec > data->last_bgscan.sec + 10)
scan = 1;
}
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index df1a0c8..9ea6903 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -224,9 +224,9 @@
}
-static void calculate_update_time(const struct os_time *fetch_time,
+static void calculate_update_time(const struct os_reltime *fetch_time,
unsigned int age_ms,
- struct os_time *update_time)
+ struct os_reltime *update_time)
{
os_time_t usec;
@@ -243,7 +243,7 @@
static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
- struct os_time *fetch_time)
+ struct os_reltime *fetch_time)
{
dst->flags = src->flags;
os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
@@ -326,7 +326,7 @@
static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
const u8 *ssid, size_t ssid_len,
struct wpa_scan_res *res,
- struct os_time *fetch_time)
+ struct os_reltime *fetch_time)
{
struct wpa_bss *bss;
@@ -492,7 +492,7 @@
static struct wpa_bss *
wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
- struct wpa_scan_res *res, struct os_time *fetch_time)
+ struct wpa_scan_res *res, struct os_reltime *fetch_time)
{
u32 changes;
@@ -587,17 +587,18 @@
*/
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *res,
- struct os_time *fetch_time)
+ struct os_reltime *fetch_time)
{
const u8 *ssid, *p2p;
struct wpa_bss *bss;
if (wpa_s->conf->ignore_old_scan_res) {
- struct os_time update;
+ struct os_reltime update;
calculate_update_time(fetch_time, res->age, &update);
- if (os_time_before(&update, &wpa_s->scan_trigger_time)) {
- struct os_time age;
- os_time_sub(&wpa_s->scan_trigger_time, &update, &age);
+ if (os_reltime_before(&update, &wpa_s->scan_trigger_time)) {
+ struct os_reltime age;
+ os_reltime_sub(&wpa_s->scan_trigger_time, &update,
+ &age);
wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Ignore driver BSS "
"table entry that is %u.%06u seconds older "
"than our scan trigger",
@@ -731,26 +732,10 @@
{
struct wpa_bss *bss, *n;
- wpa_s->last_scan_full = 0;
- os_get_time(&wpa_s->last_scan);
+ os_get_reltime(&wpa_s->last_scan);
if (!new_scan)
return; /* do not expire entries without new scan */
- if (info && !info->aborted && !info->freqs) {
- size_t i;
- if (info->num_ssids == 0) {
- wpa_s->last_scan_full = 1;
- } else {
- for (i = 0; i < info->num_ssids; i++) {
- if (info->ssids[i].ssid == NULL ||
- info->ssids[i].ssid_len == 0) {
- wpa_s->last_scan_full = 1;
- break;
- }
- }
- }
- }
-
dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
if (wpa_bss_in_use(wpa_s, bss))
continue;
@@ -764,10 +749,8 @@
}
}
- wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u "
- "last_scan_full=%d",
- wpa_s->last_scan_res_used, wpa_s->last_scan_res_size,
- wpa_s->last_scan_full);
+ wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u",
+ wpa_s->last_scan_res_used, wpa_s->last_scan_res_size);
}
@@ -781,19 +764,19 @@
void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age)
{
struct wpa_bss *bss, *n;
- struct os_time t;
+ struct os_reltime t;
if (dl_list_empty(&wpa_s->bss))
return;
- os_get_time(&t);
+ os_get_reltime(&t);
t.sec -= age;
dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
if (wpa_bss_in_use(wpa_s, bss))
continue;
- if (os_time_before(&bss->last_update, &t)) {
+ if (os_reltime_before(&bss->last_update, &t)) {
wpa_bss_remove(wpa_s, bss, __func__);
} else
break;
@@ -837,6 +820,8 @@
{
struct wpa_bss *bss, *n;
+ wpa_s->clear_driver_scan_cache = 1;
+
if (wpa_s->bss.next == NULL)
return; /* BSS table not yet initialized */
@@ -900,7 +885,7 @@
if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
continue;
if (found == NULL ||
- os_time_before(&found->last_update, &bss->last_update))
+ os_reltime_before(&found->last_update, &bss->last_update))
found = bss;
}
return found;
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 0d2693f..4deeb5f 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -84,7 +84,7 @@
/** Timestamp of last Beacon/Probe Response frame */
u64 tsf;
/** Time of the last update (i.e., Beacon or Probe Response RX) */
- struct os_time last_update;
+ struct os_reltime last_update;
/** ANQP data */
struct wpa_bss_anqp *anqp;
/** Length of the following IE field in octets (from Probe Response) */
@@ -98,7 +98,7 @@
void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *res,
- struct os_time *fetch_time);
+ struct os_reltime *fetch_time);
void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
int new_scan);
int wpa_bss_init(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 9ceaaf8..5301ed7 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2393,6 +2393,11 @@
char *val;
size_t len;
+ if (os_strcmp(var, "temporary") == 0) {
+ cred->temporary = atoi(value);
+ return 0;
+ }
+
if (os_strcmp(var, "priority") == 0) {
cred->priority = atoi(value);
return 0;
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 068679e..e24772d 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -52,6 +52,11 @@
int id;
/**
+ * temporary - Whether this credential is temporary and not to be saved
+ */
+ int temporary;
+
+ /**
* priority - Priority group
*
* By default, all networks and credentials get the same priority group
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 7d32867..6312a77 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1110,6 +1110,8 @@
wpa_config_write_global(f, config);
for (cred = config->cred; cred; cred = cred->next) {
+ if (cred->temporary)
+ continue;
fprintf(f, "\ncred={\n");
wpa_config_write_cred(f, cred);
fprintf(f, "}\n");
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 0102da9..d515030 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -315,12 +315,13 @@
* 4 = P2P Group Formation (used internally; not in configuration
* files)
*
- * Note: IBSS can only be used with key_mgmt NONE (plaintext and
- * static WEP) and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In
- * addition, ap_scan has to be set to 2 for IBSS. WPA-None requires
- * following network block options: proto=WPA, key_mgmt=WPA-NONE,
- * pairwise=NONE, group=TKIP (or CCMP, but not both), and psk must also
- * be set (either directly or using ASCII passphrase).
+ * Note: IBSS can only be used with key_mgmt NONE (plaintext and static
+ * WEP) and WPA-PSK (with proto=RSN). In addition, key_mgmt=WPA-NONE
+ * (fixed group key TKIP/CCMP) is available for backwards compatibility,
+ * but its use is deprecated. WPA-None requires following network block
+ * options: proto=WPA, key_mgmt=WPA-NONE, pairwise=NONE, group=TKIP (or
+ * CCMP, but not both), and psk must also be set (either directly or
+ * using ASCII passphrase).
*/
enum wpas_mode {
WPAS_MODE_INFRA = 0,
@@ -610,7 +611,7 @@
/**
* disabled_until - Network block disabled until this time if non-zero
*/
- struct os_time disabled_until;
+ struct os_reltime disabled_until;
/**
* parent_cred - Pointer to parent wpa_cred entry
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 4e344b8..cb299db 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,6 +10,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
+#include "utils/uuid.h"
#include "common/version.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
@@ -40,8 +41,6 @@
#include "autoscan.h"
#include "wnm_sta.h"
-extern struct wpa_driver_ops *wpa_drivers[];
-
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
char *buf, int len);
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
@@ -361,13 +360,13 @@
} else if (os_strcasecmp(cmd, "ampdu") == 0) {
if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
ret = -1;
+#ifdef CONFIG_TDLS
#ifdef CONFIG_TDLS_TESTING
} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
extern unsigned int tdls_testing;
tdls_testing = strtol(value, NULL, 0);
wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
#endif /* CONFIG_TDLS_TESTING */
-#ifdef CONFIG_TDLS
} else if (os_strcasecmp(cmd, "tdls_disabled") == 0) {
int disabled = atoi(value);
wpa_printf(MSG_DEBUG, "TDLS: tdls_disabled=%d", disabled);
@@ -1629,6 +1628,17 @@
if (res >= 0)
pos += res;
+#ifdef CONFIG_WPS
+ {
+ char uuid_str[100];
+ uuid_bin2str(wpa_s->wps->uuid, uuid_str, sizeof(uuid_str));
+ ret = os_snprintf(pos, end - pos, "uuid=%s\n", uuid_str);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ }
+#endif /* CONFIG_WPS */
+
#ifdef ANDROID
wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE
"id=%d state=%d BSSID=" MACSTR " SSID=%s",
@@ -1740,9 +1750,6 @@
}
-extern int wpa_debug_level;
-extern int wpa_debug_timestamp;
-
static const char * debug_level_str(int level)
{
switch (level) {
@@ -2658,6 +2665,24 @@
#endif /* CONFIG_NO_CONFIG_WRITE */
+struct cipher_info {
+ unsigned int capa;
+ const char *name;
+ int group_only;
+};
+
+static const struct cipher_info ciphers[] = {
+ { WPA_DRIVER_CAPA_ENC_CCMP_256, "CCMP-256", 0 },
+ { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 },
+ { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 },
+ { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 },
+ { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 },
+ { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 },
+ { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 },
+ { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 }
+};
+
+
static int ctrl_iface_get_capability_pairwise(int res, char *strict,
struct wpa_driver_capa *capa,
char *buf, size_t buflen)
@@ -2665,6 +2690,7 @@
int ret, first = 1;
char *pos, *end;
size_t len;
+ unsigned int i;
pos = buf;
end = pos + buflen;
@@ -2678,36 +2704,15 @@
return len;
}
- if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
- ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
- }
-
- if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
- ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
- }
-
- if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
- ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
- }
-
- if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
- ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
+ for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
+ if (!ciphers[i].group_only && capa->enc & ciphers[i].capa) {
+ ret = os_snprintf(pos, end - pos, "%s%s",
+ first ? "" : " ", ciphers[i].name);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ first = 0;
+ }
}
return pos - buf;
@@ -2721,6 +2726,7 @@
int ret, first = 1;
char *pos, *end;
size_t len;
+ unsigned int i;
pos = buf;
end = pos + buflen;
@@ -2734,45 +2740,15 @@
return len;
}
- if (capa->enc & WPA_DRIVER_CAPA_ENC_CCMP) {
- ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
- }
-
- if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) {
- ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
- }
-
- if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) {
- ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
- }
-
- if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP104) {
- ret = os_snprintf(pos, end - pos, "%sWEP104",
- first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
- }
-
- if (capa->enc & WPA_DRIVER_CAPA_ENC_WEP40) {
- ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
- if (ret < 0 || ret >= end - pos)
- return pos - buf;
- pos += ret;
- first = 0;
+ for (i = 0; i < ARRAY_SIZE(ciphers); i++) {
+ if (capa->enc & ciphers[i].capa) {
+ ret = os_snprintf(pos, end - pos, "%s%s",
+ first ? "" : " ", ciphers[i].name);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ first = 0;
+ }
}
return pos - buf;
@@ -3248,9 +3224,9 @@
}
if (mask & WPA_BSS_MASK_AGE) {
- struct os_time now;
+ struct os_reltime now;
- os_get_time(&now);
+ os_get_reltime(&now);
ret = os_snprintf(pos, end - pos, "age=%d\n",
(int) (now.sec - bss->last_update.sec));
if (ret < 0 || ret >= end - pos)
@@ -4688,7 +4664,68 @@
#endif /* CONFIG_P2P */
+static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val)
+{
+ struct wpa_freq_range_list ranges;
+ int *freqs = NULL;
+ struct hostapd_hw_modes *mode;
+ u16 i;
+
+ if (wpa_s->hw.modes == NULL)
+ return NULL;
+
+ os_memset(&ranges, 0, sizeof(ranges));
+ if (freq_range_list_parse(&ranges, val) < 0)
+ return NULL;
+
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ int j;
+
+ mode = &wpa_s->hw.modes[i];
+ for (j = 0; j < mode->num_channels; j++) {
+ unsigned int freq;
+
+ if (mode->channels[j].flag & HOSTAPD_CHAN_DISABLED)
+ continue;
+
+ freq = mode->channels[j].freq;
+ if (!freq_range_list_includes(&ranges, freq))
+ continue;
+
+ int_array_add_unique(&freqs, freq);
+ }
+ }
+
+ os_free(ranges.range);
+ return freqs;
+}
+
+
#ifdef CONFIG_INTERWORKING
+
+static int ctrl_interworking_select(struct wpa_supplicant *wpa_s, char *param)
+{
+ int auto_sel = 0;
+ int *freqs = NULL;
+
+ if (param) {
+ char *pos;
+
+ auto_sel = os_strstr(param, "auto") != NULL;
+
+ pos = os_strstr(param, "freq=");
+ if (pos) {
+ freqs = freq_range_to_channel_list(wpa_s, pos + 5);
+ if (freqs == NULL)
+ return -1;
+ }
+
+ }
+
+ return interworking_select(wpa_s, auto_sel, freqs);
+}
+
+
static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
{
u8 bssid[ETH_ALEN];
@@ -4812,9 +4849,8 @@
int used;
char *pos;
size_t resp_len, start, requested_len;
-
- if (!wpa_s->last_gas_resp)
- return -1;
+ struct wpabuf *resp;
+ int ret;
used = hwaddr_aton2(cmd, addr);
if (used < 0)
@@ -4825,11 +4861,18 @@
pos++;
dialog_token = atoi(pos);
- if (os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) != 0 ||
- dialog_token != wpa_s->last_gas_dialog_token)
+ if (wpa_s->last_gas_resp &&
+ os_memcmp(addr, wpa_s->last_gas_addr, ETH_ALEN) == 0 &&
+ dialog_token == wpa_s->last_gas_dialog_token)
+ resp = wpa_s->last_gas_resp;
+ else if (wpa_s->prev_gas_resp &&
+ os_memcmp(addr, wpa_s->prev_gas_addr, ETH_ALEN) == 0 &&
+ dialog_token == wpa_s->prev_gas_dialog_token)
+ resp = wpa_s->prev_gas_resp;
+ else
return -1;
- resp_len = wpabuf_len(wpa_s->last_gas_resp);
+ resp_len = wpabuf_len(resp);
start = 0;
requested_len = resp_len;
@@ -4850,9 +4893,24 @@
if (requested_len * 2 + 1 > buflen)
return os_snprintf(buf, buflen, "FAIL-Too long response");
- return wpa_snprintf_hex(buf, buflen,
- wpabuf_head_u8(wpa_s->last_gas_resp) + start,
- requested_len);
+ ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(resp) + start,
+ requested_len);
+
+ if (start + requested_len == resp_len) {
+ /*
+ * Free memory by dropping the response after it has been
+ * fetched.
+ */
+ if (resp == wpa_s->prev_gas_resp) {
+ wpabuf_free(wpa_s->prev_gas_resp);
+ wpa_s->prev_gas_resp = NULL;
+ } else {
+ wpabuf_free(wpa_s->last_gas_resp);
+ wpa_s->last_gas_resp = NULL;
+ }
+ }
+
+ return ret;
}
#endif /* CONFIG_INTERWORKING */
@@ -5191,6 +5249,9 @@
wpas_p2p_stop_find(wpa_s);
p2p_ctrl_flush(wpa_s);
wpas_p2p_group_remove(wpa_s, "*");
+ wpas_p2p_service_flush(wpa_s);
+ wpa_s->global->p2p_disabled = 0;
+ wpa_s->global->p2p_per_sta_psk = 0;
#endif /* CONFIG_P2P */
#ifdef CONFIG_WPS_TESTING
@@ -5198,16 +5259,17 @@
wps_testing_dummy_cred = 0;
#endif /* CONFIG_WPS_TESTING */
#ifdef CONFIG_WPS
+ wpa_s->wps_fragment_size = 0;
wpas_wps_cancel(wpa_s);
#endif /* CONFIG_WPS */
wpa_s->after_wps = 0;
wpa_s->known_wps_freq = 0;
+#ifdef CONFIG_TDLS
#ifdef CONFIG_TDLS_TESTING
extern unsigned int tdls_testing;
tdls_testing = 0;
#endif /* CONFIG_TDLS_TESTING */
-#ifdef CONFIG_TDLS
wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
wpa_tdls_enable(wpa_s->wpa, 1);
#endif /* CONFIG_TDLS */
@@ -5234,6 +5296,193 @@
wpa_s->extra_blacklist_count = 0;
wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
+
+ wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200);
+ wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70);
+ wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60);
+ eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
+
+ radio_remove_unstarted_work(wpa_s, NULL);
+}
+
+
+static int wpas_ctrl_radio_work_show(struct wpa_supplicant *wpa_s,
+ char *buf, size_t buflen)
+{
+ struct wpa_radio_work *work;
+ char *pos, *end;
+ struct os_reltime now, diff;
+
+ pos = buf;
+ end = buf + buflen;
+
+ os_get_reltime(&now);
+
+ dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
+ {
+ int ret;
+
+ os_reltime_sub(&now, &work->time, &diff);
+ ret = os_snprintf(pos, end - pos, "%s@%s:%u:%u:%ld.%06ld\n",
+ work->type, work->wpa_s->ifname, work->freq,
+ work->started, diff.sec, diff.usec);
+ if (ret < 0 || ret >= end - pos)
+ break;
+ pos += ret;
+ }
+
+ return pos - buf;
+}
+
+
+static void wpas_ctrl_radio_work_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_radio_work *work = eloop_ctx;
+ struct wpa_external_work *ework = work->ctx;
+
+ wpa_dbg(work->wpa_s, MSG_DEBUG,
+ "Timing out external radio work %u (%s)",
+ ework->id, work->type);
+ wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_TIMEOUT "%u", ework->id);
+ os_free(ework);
+ radio_work_done(work);
+}
+
+
+static void wpas_ctrl_radio_work_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_external_work *ework = work->ctx;
+
+ if (deinit) {
+ os_free(ework);
+ return;
+ }
+
+ wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
+ ework->id, ework->type);
+ wpa_msg(work->wpa_s, MSG_INFO, EXT_RADIO_WORK_START "%u", ework->id);
+ if (!ework->timeout)
+ ework->timeout = 10;
+ eloop_register_timeout(ework->timeout, 0, wpas_ctrl_radio_work_timeout,
+ work, NULL);
+}
+
+
+static int wpas_ctrl_radio_work_add(struct wpa_supplicant *wpa_s, char *cmd,
+ char *buf, size_t buflen)
+{
+ struct wpa_external_work *ework;
+ char *pos, *pos2;
+ size_t type_len;
+ int ret;
+ unsigned int freq = 0;
+
+ /* format: <name> [freq=<MHz>] [timeout=<seconds>] */
+
+ ework = os_zalloc(sizeof(*ework));
+ if (ework == NULL)
+ return -1;
+
+ pos = os_strchr(cmd, ' ');
+ if (pos) {
+ type_len = pos - cmd;
+ pos++;
+
+ pos2 = os_strstr(pos, "freq=");
+ if (pos2)
+ freq = atoi(pos2 + 5);
+
+ pos2 = os_strstr(pos, "timeout=");
+ if (pos2)
+ ework->timeout = atoi(pos2 + 8);
+ } else {
+ type_len = os_strlen(cmd);
+ }
+ if (4 + type_len >= sizeof(ework->type))
+ type_len = sizeof(ework->type) - 4 - 1;
+ os_strlcpy(ework->type, "ext:", sizeof(ework->type));
+ os_memcpy(ework->type + 4, cmd, type_len);
+ ework->type[4 + type_len] = '\0';
+
+ wpa_s->ext_work_id++;
+ if (wpa_s->ext_work_id == 0)
+ wpa_s->ext_work_id++;
+ ework->id = wpa_s->ext_work_id;
+
+ if (radio_add_work(wpa_s, freq, ework->type, 0, wpas_ctrl_radio_work_cb,
+ ework) < 0) {
+ os_free(ework);
+ return -1;
+ }
+
+ ret = os_snprintf(buf, buflen, "%u", ework->id);
+ if (ret < 0 || (size_t) ret >= buflen)
+ return -1;
+ return ret;
+}
+
+
+static int wpas_ctrl_radio_work_done(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ struct wpa_radio_work *work;
+ unsigned int id = atoi(cmd);
+
+ dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
+ {
+ struct wpa_external_work *ework;
+
+ if (os_strncmp(work->type, "ext:", 4) != 0)
+ continue;
+ ework = work->ctx;
+ if (id && ework->id != id)
+ continue;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Completed external radio work %u (%s)",
+ ework->id, ework->type);
+ eloop_cancel_timeout(wpas_ctrl_radio_work_timeout, work, NULL);
+ os_free(ework);
+ radio_work_done(work);
+ return 3; /* "OK\n" */
+ }
+
+ return -1;
+}
+
+
+static int wpas_ctrl_radio_work(struct wpa_supplicant *wpa_s, char *cmd,
+ char *buf, size_t buflen)
+{
+ if (os_strcmp(cmd, "show") == 0)
+ return wpas_ctrl_radio_work_show(wpa_s, buf, buflen);
+ if (os_strncmp(cmd, "add ", 4) == 0)
+ return wpas_ctrl_radio_work_add(wpa_s, cmd + 4, buf, buflen);
+ if (os_strncmp(cmd, "done ", 5) == 0)
+ return wpas_ctrl_radio_work_done(wpa_s, cmd + 4);
+ return -1;
+}
+
+
+void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_radio_work *work, *tmp;
+
+ dl_list_for_each_safe(work, tmp, &wpa_s->radio->work,
+ struct wpa_radio_work, list) {
+ struct wpa_external_work *ework;
+
+ if (os_strncmp(work->type, "ext:", 4) != 0)
+ continue;
+ ework = work->ctx;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Flushing %sexternal radio work %u (%s)",
+ work->started ? " started" : "", ework->id,
+ ework->type);
+ if (work->started)
+ eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
+ work, NULL);
+ os_free(ework);
+ radio_work_done(work);
+ }
}
@@ -5244,6 +5493,97 @@
}
+static int set_scan_freqs(struct wpa_supplicant *wpa_s, char *val)
+{
+ int *freqs = NULL;
+
+ freqs = freq_range_to_channel_list(wpa_s, val);
+ if (freqs == NULL)
+ return -1;
+
+ os_free(wpa_s->manual_scan_freqs);
+ wpa_s->manual_scan_freqs = freqs;
+
+ return 0;
+}
+
+
+static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
+ char *reply, int reply_size, int *reply_len)
+{
+ char *pos;
+
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ *reply_len = -1;
+ return;
+ }
+
+ wpa_s->manual_scan_passive = 0;
+ wpa_s->manual_scan_use_id = 0;
+ wpa_s->manual_scan_only_new = 0;
+
+ if (params) {
+ if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
+ wpa_s->scan_res_handler = scan_only_handler;
+
+ pos = os_strstr(params, "freq=");
+ if (pos && set_scan_freqs(wpa_s, pos + 5) < 0) {
+ *reply_len = -1;
+ return;
+ }
+
+ pos = os_strstr(params, "passive=");
+ if (pos)
+ wpa_s->manual_scan_passive = !!atoi(pos + 8);
+
+ pos = os_strstr(params, "use_id=");
+ if (pos)
+ wpa_s->manual_scan_use_id = atoi(pos + 7);
+
+ pos = os_strstr(params, "only_new=1");
+ if (pos)
+ wpa_s->manual_scan_only_new = 1;
+ } else {
+ os_free(wpa_s->manual_scan_freqs);
+ wpa_s->manual_scan_freqs = NULL;
+ if (wpa_s->scan_res_handler == scan_only_handler)
+ wpa_s->scan_res_handler = NULL;
+ }
+
+ if (!wpa_s->sched_scanning && !wpa_s->scanning &&
+ ((wpa_s->wpa_state <= WPA_SCANNING) ||
+ (wpa_s->wpa_state == WPA_COMPLETED))) {
+ wpa_s->normal_scans = 0;
+ wpa_s->scan_req = MANUAL_SCAN_REQ;
+ wpa_s->after_wps = 0;
+ wpa_s->known_wps_freq = 0;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ if (wpa_s->manual_scan_use_id) {
+ wpa_s->manual_scan_id++;
+ wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
+ wpa_s->manual_scan_id);
+ *reply_len = os_snprintf(reply, reply_size, "%u\n",
+ wpa_s->manual_scan_id);
+ }
+ } else if (wpa_s->sched_scanning) {
+ wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to allow requested full scan to proceed");
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_s->scan_req = MANUAL_SCAN_REQ;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ if (wpa_s->manual_scan_use_id) {
+ wpa_s->manual_scan_id++;
+ *reply_len = os_snprintf(reply, reply_size, "%u\n",
+ wpa_s->manual_scan_id);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Assigned scan id %u",
+ wpa_s->manual_scan_id);
+ }
+ } else {
+ wpa_printf(MSG_DEBUG, "Ongoing scan action - reject new request");
+ *reply_len = os_snprintf(reply, reply_size, "FAIL-BUSY\n");
+ }
+}
+
+
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
char *buf, size_t *resp_len)
{
@@ -5252,18 +5592,25 @@
int reply_len;
if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ||
- os_strncmp(buf, "SET_NETWORK ", 12) == 0 ||
- os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
- os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0 ||
- os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
+ os_strncmp(buf, "SET_NETWORK ", 12) == 0) {
+ if (wpa_debug_show_keys)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Control interface command '%s'", buf);
+ else
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Control interface command '%s [REMOVED]'",
+ os_strncmp(buf, WPA_CTRL_RSP,
+ os_strlen(WPA_CTRL_RSP)) == 0 ?
+ WPA_CTRL_RSP : "SET_NETWORK");
+ } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 ||
+ os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0 ||
+ os_strncmp(buf, "NFC_RX_HANDOVER_SEL", 19) == 0) {
wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
(const u8 *) buf, os_strlen(buf));
} else {
int level = MSG_DEBUG;
if (os_strcmp(buf, "PING") == 0)
level = MSG_EXCESSIVE;
- wpa_hexdump_ascii(level, "RX ctrl_iface",
- (const u8 *) buf, os_strlen(buf));
wpa_dbg(wpa_s, level, "Control interface command '%s'", buf);
}
@@ -5557,9 +5904,11 @@
reply_len = -1;
} else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
interworking_stop_fetch_anqp(wpa_s);
- } else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) {
- if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") !=
- NULL) < 0)
+ } else if (os_strcmp(buf, "INTERWORKING_SELECT") == 0) {
+ if (ctrl_interworking_select(wpa_s, NULL) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "INTERWORKING_SELECT ", 20) == 0) {
+ if (ctrl_interworking_select(wpa_s, buf + 20) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
@@ -5622,36 +5971,10 @@
wpa_supplicant_cancel_scan(wpa_s);
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
- } else if (os_strcmp(buf, "SCAN") == 0 ||
- os_strncmp(buf, "SCAN ", 5) == 0) {
- if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
- reply_len = -1;
- else {
- if (os_strlen(buf) > 4 &&
- os_strncasecmp(buf + 5, "TYPE=ONLY", 9) == 0)
- wpa_s->scan_res_handler = scan_only_handler;
- if (!wpa_s->sched_scanning && !wpa_s->scanning &&
- ((wpa_s->wpa_state <= WPA_SCANNING) ||
- (wpa_s->wpa_state == WPA_COMPLETED))) {
- wpa_s->normal_scans = 0;
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- wpa_s->after_wps = 0;
- wpa_s->known_wps_freq = 0;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- } else if (wpa_s->sched_scanning) {
- wpa_printf(MSG_DEBUG, "Stop ongoing "
- "sched_scan to allow requested "
- "full scan to proceed");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_s->scan_req = MANUAL_SCAN_REQ;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- } else {
- wpa_printf(MSG_DEBUG, "Ongoing scan action - "
- "reject new request");
- reply_len = os_snprintf(reply, reply_size,
- "FAIL-BUSY\n");
- }
- }
+ } else if (os_strcmp(buf, "SCAN") == 0) {
+ wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
+ } else if (os_strncmp(buf, "SCAN ", 5) == 0) {
+ wpas_ctrl_scan(wpa_s, buf + 5, reply, reply_size, &reply_len);
} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
reply_len = wpa_supplicant_ctrl_iface_scan_results(
wpa_s, reply, reply_size);
@@ -5792,6 +6115,9 @@
#endif /* CONFIG_WNM */
} else if (os_strcmp(buf, "FLUSH") == 0) {
wpa_supplicant_ctrl_iface_flush(wpa_s);
+ } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
+ reply_len = wpas_ctrl_radio_work(wpa_s, buf + 11, reply,
+ reply_size);
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h
index a329ef3..b0dec53 100644
--- a/wpa_supplicant/ctrl_iface.h
+++ b/wpa_supplicant/ctrl_iface.h
@@ -113,6 +113,8 @@
void wpa_supplicant_global_ctrl_iface_deinit(
struct ctrl_iface_global_priv *priv);
+void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s);
+
#else /* CONFIG_CTRL_IFACE */
static inline struct ctrl_iface_priv *
@@ -148,6 +150,10 @@
{
}
+static inline void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s)
+{
+}
+
#endif /* CONFIG_CTRL_IFACE */
#endif /* CTRL_IFACE_H */
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 7135d06..8fb217d 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / UNIX domain socket -based control interface
- * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -75,6 +75,7 @@
socklen_t fromlen)
{
struct wpa_ctrl_dst *dst;
+ char addr_txt[200];
dst = os_zalloc(sizeof(*dst));
if (dst == NULL)
@@ -83,9 +84,10 @@
dst->addrlen = fromlen;
dst->debug_level = MSG_INFO;
dl_list_add(ctrl_dst, &dst->list);
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
- (u8 *) from->sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path));
+ printf_encode(addr_txt, sizeof(addr_txt),
+ (u8 *) from->sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path));
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s", addr_txt);
return 0;
}
@@ -101,10 +103,13 @@
os_memcmp(from->sun_path, dst->addr.sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path))
== 0) {
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
- (u8 *) from->sun_path,
- fromlen -
- offsetof(struct sockaddr_un, sun_path));
+ char addr_txt[200];
+ printf_encode(addr_txt, sizeof(addr_txt),
+ (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s",
+ addr_txt);
dl_list_del(&dst->list);
os_free(dst);
return 0;
@@ -128,11 +133,13 @@
os_memcmp(from->sun_path, dst->addr.sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path))
== 0) {
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
- "level", (u8 *) from->sun_path,
- fromlen -
- offsetof(struct sockaddr_un, sun_path));
+ char addr_txt[200];
dst->debug_level = atoi(level);
+ printf_encode(addr_txt, sizeof(addr_txt),
+ (u8 *) from->sun_path, fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level to %d for %s",
+ dst->debug_level, addr_txt);
return 0;
}
}
@@ -676,32 +683,33 @@
msg.msg_iov = io;
msg.msg_iovlen = idx;
- idx = -1;
dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
int _errno;
+ char addr_txt[200];
- idx++;
if (level < dst->debug_level)
continue;
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
- (u8 *) dst->addr.sun_path, dst->addrlen -
- offsetof(struct sockaddr_un, sun_path));
+ printf_encode(addr_txt, sizeof(addr_txt),
+ (u8 *) dst->addr.sun_path, dst->addrlen -
+ offsetof(struct sockaddr_un, sun_path));
msg.msg_name = (void *) &dst->addr;
msg.msg_namelen = dst->addrlen;
if (sendmsg(sock, &msg, MSG_DONTWAIT) >= 0) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor sent successfully to %s",
+ addr_txt);
dst->errors = 0;
- idx++;
continue;
}
_errno = errno;
- wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: %d - %s",
- idx, errno, strerror(errno));
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor[%s]: %d - %s",
+ addr_txt, errno, strerror(errno));
dst->errors++;
if (dst->errors > 10 || _errno == ENOENT || _errno == EPERM) {
- wpa_printf(MSG_INFO, "CTRL_IFACE: Detach monitor that cannot receive messages");
+ wpa_printf(MSG_INFO, "CTRL_IFACE: Detach monitor %s that cannot receive messages",
+ addr_txt);
wpa_supplicant_ctrl_iface_detach(ctrl_dst, &dst->addr,
dst->addrlen);
}
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index fdf9a0a..5380b43 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -28,10 +28,6 @@
#include "dbus_dict_helpers.h"
#include "dbus_common_i.h"
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-extern int wpa_debug_timestamp;
-
static const char *debug_strings[] = {
"excessive", "msgdump", "debug", "info", "warning", "error", NULL
};
@@ -2260,6 +2256,18 @@
&iter_array))
goto nomem;
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) {
+ if (!wpa_dbus_dict_string_array_add_element(
+ &iter_array, "ccmp-256"))
+ goto nomem;
+ }
+
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) {
+ if (!wpa_dbus_dict_string_array_add_element(
+ &iter_array, "gcmp-256"))
+ goto nomem;
+ }
+
if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
if (!wpa_dbus_dict_string_array_add_element(
&iter_array, "ccmp"))
@@ -2307,6 +2315,18 @@
&iter_array))
goto nomem;
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP_256) {
+ if (!wpa_dbus_dict_string_array_add_element(
+ &iter_array, "ccmp-256"))
+ goto nomem;
+ }
+
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP_256) {
+ if (!wpa_dbus_dict_string_array_add_element(
+ &iter_array, "gcmp-256"))
+ goto nomem;
+ }
+
if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
if (!wpa_dbus_dict_string_array_add_element(
&iter_array, "ccmp"))
@@ -3601,7 +3621,7 @@
{
DBusMessageIter iter_dict, variant_iter;
const char *group;
- const char *pairwise[3]; /* max 3 pairwise ciphers is supported */
+ const char *pairwise[5]; /* max 5 pairwise ciphers is supported */
const char *key_mgmt[7]; /* max 7 key managements may be supported */
int n;
@@ -3650,6 +3670,12 @@
case WPA_CIPHER_WEP104:
group = "wep104";
break;
+ case WPA_CIPHER_CCMP_256:
+ group = "ccmp-256";
+ break;
+ case WPA_CIPHER_GCMP_256:
+ group = "gcmp-256";
+ break;
default:
group = "";
break;
@@ -3666,6 +3692,10 @@
pairwise[n++] = "ccmp";
if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP)
pairwise[n++] = "gcmp";
+ if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP_256)
+ pairwise[n++] = "ccmp-256";
+ if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP_256)
+ pairwise[n++] = "gcmp-256";
if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
pairwise, n))
diff --git a/wpa_supplicant/dbus/dbus_old_handlers.c b/wpa_supplicant/dbus/dbus_old_handlers.c
index 6d178f4..7c4630e 100644
--- a/wpa_supplicant/dbus/dbus_old_handlers.c
+++ b/wpa_supplicant/dbus/dbus_old_handlers.c
@@ -25,10 +25,6 @@
#include "dbus_old_handlers.h"
#include "dbus_dict_helpers.h"
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-extern int wpa_debug_timestamp;
-
/**
* wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
* @message: Pointer to incoming dbus message this error refers to
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index ea0db04..0627661 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -20,63 +20,6 @@
# used to fix build issues on such systems (krb5.h not found).
#CFLAGS += -I/usr/include/kerberos
-# Example configuration for various cross-compilation platforms
-
-#### sveasoft (e.g., for Linksys WRT54G) ######################################
-#CC=mipsel-uclibc-gcc
-#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
-#CFLAGS += -Os
-#CPPFLAGS += -I../src/include -I../../src/router/openssl/include
-#LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl
-###############################################################################
-
-#### openwrt (e.g., for Linksys WRT54G) #######################################
-#CC=mipsel-uclibc-gcc
-#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
-#CFLAGS += -Os
-#CPPFLAGS=-I../src/include -I../openssl-0.9.7d/include \
-# -I../WRT54GS/release/src/include
-#LIBS = -lssl
-###############################################################################
-
-
-# Driver interface for Host AP driver
-CONFIG_DRIVER_HOSTAP=y
-
-# Driver interface for Agere driver
-#CONFIG_DRIVER_HERMES=y
-# Change include directories to match with the local setup
-#CFLAGS += -I../../hcf -I../../include -I../../include/hcf
-#CFLAGS += -I../../include/wireless
-
-# Driver interface for madwifi driver
-# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
-#CONFIG_DRIVER_MADWIFI=y
-# Set include directory to the madwifi source tree
-#CFLAGS += -I../../madwifi
-
-# Driver interface for ndiswrapper
-# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
-#CONFIG_DRIVER_NDISWRAPPER=y
-
-# Driver interface for Atmel driver
-CONFIG_DRIVER_ATMEL=y
-
-# Driver interface for old Broadcom driver
-# Please note that the newer Broadcom driver ("hybrid Linux driver") supports
-# Linux wireless extensions and does not need (or even work) with the old
-# driver wrapper. Use CONFIG_DRIVER_WEXT=y with that driver.
-#CONFIG_DRIVER_BROADCOM=y
-# Example path for wlioctl.h; change to match your configuration
-#CFLAGS += -I/opt/WRT54GS/release/src/include
-
-# Driver interface for Intel ipw2100/2200 driver
-# Deprecated; use CONFIG_DRIVER_WEXT=y instead.
-#CONFIG_DRIVER_IPW=y
-
-# Driver interface for Ralink driver
-#CONFIG_DRIVER_RALINK=y
-
# Driver interface for generic Linux wireless extensions
# Note: WEXT is deprecated in the current Linux kernel version and no new
# functionality is added to it. nl80211-based interface is the new
@@ -147,10 +90,9 @@
CONFIG_EAP_TTLS=y
# EAP-FAST
-# Note: Default OpenSSL package does not include support for all the
-# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
-# the OpenSSL library must be patched (openssl-0.9.8d-tls-extensions.patch)
-# to add the needed functions.
+# Note: If OpenSSL is used as the TLS library, OpenSSL 1.0 or newer is needed
+# for EAP-FAST support. Older OpenSSL releases would need to be patched, e.g.,
+# with openssl-0.9.8x-tls-extensions.patch, to add the needed functions.
#CONFIG_EAP_FAST=y
# EAP-GTC
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 7f196de..0691b6c 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -117,11 +117,16 @@
static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s,
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)
+ const u8 *seq, size_t seq_len,
+ const u8 *key, size_t key_len)
{
+ if (alg != WPA_ALG_NONE) {
+ if (key_idx >= 0 && key_idx <= 6)
+ wpa_s->keys_cleared &= ~BIT(key_idx);
+ else
+ wpa_s->keys_cleared = 0;
+ }
if (wpa_s->driver->set_key) {
- wpa_s->keys_cleared = 0;
return wpa_s->driver->set_key(wpa_s->ifname, wpa_s->drv_priv,
alg, addr, key_idx, set_tx,
seq, seq_len, key, key_len);
@@ -516,134 +521,6 @@
return wpa_s->driver->ampdu(wpa_s->drv_priv, ampdu);
}
-static inline int wpa_drv_p2p_find(struct wpa_supplicant *wpa_s,
- unsigned int timeout, int type)
-{
- if (!wpa_s->driver->p2p_find)
- return -1;
- return wpa_s->driver->p2p_find(wpa_s->drv_priv, timeout, type);
-}
-
-static inline int wpa_drv_p2p_stop_find(struct wpa_supplicant *wpa_s)
-{
- if (!wpa_s->driver->p2p_stop_find)
- return -1;
- return wpa_s->driver->p2p_stop_find(wpa_s->drv_priv);
-}
-
-static inline int wpa_drv_p2p_listen(struct wpa_supplicant *wpa_s,
- unsigned int timeout)
-{
- if (!wpa_s->driver->p2p_listen)
- return -1;
- return wpa_s->driver->p2p_listen(wpa_s->drv_priv, timeout);
-}
-
-static inline int wpa_drv_p2p_connect(struct wpa_supplicant *wpa_s,
- const u8 *peer_addr, int wps_method,
- int go_intent,
- const u8 *own_interface_addr,
- unsigned int force_freq,
- int persistent_group)
-{
- if (!wpa_s->driver->p2p_connect)
- return -1;
- return wpa_s->driver->p2p_connect(wpa_s->drv_priv, peer_addr,
- wps_method, go_intent,
- own_interface_addr, force_freq,
- persistent_group);
-}
-
-static inline int wpa_drv_wps_success_cb(struct wpa_supplicant *wpa_s,
- const u8 *peer_addr)
-{
- if (!wpa_s->driver->wps_success_cb)
- return -1;
- return wpa_s->driver->wps_success_cb(wpa_s->drv_priv, peer_addr);
-}
-
-static inline int
-wpa_drv_p2p_group_formation_failed(struct wpa_supplicant *wpa_s)
-{
- if (!wpa_s->driver->p2p_group_formation_failed)
- return -1;
- return wpa_s->driver->p2p_group_formation_failed(wpa_s->drv_priv);
-}
-
-static inline int wpa_drv_p2p_set_params(struct wpa_supplicant *wpa_s,
- const struct p2p_params *params)
-{
- if (!wpa_s->driver->p2p_set_params)
- return -1;
- return wpa_s->driver->p2p_set_params(wpa_s->drv_priv, params);
-}
-
-static inline int wpa_drv_p2p_prov_disc_req(struct wpa_supplicant *wpa_s,
- const u8 *peer_addr,
- u16 config_methods, int join)
-{
- if (!wpa_s->driver->p2p_prov_disc_req)
- return -1;
- return wpa_s->driver->p2p_prov_disc_req(wpa_s->drv_priv, peer_addr,
- config_methods, join);
-}
-
-static inline u64 wpa_drv_p2p_sd_request(struct wpa_supplicant *wpa_s,
- const u8 *dst,
- const struct wpabuf *tlvs)
-{
- if (!wpa_s->driver->p2p_sd_request)
- return 0;
- return wpa_s->driver->p2p_sd_request(wpa_s->drv_priv, dst, tlvs);
-}
-
-static inline int wpa_drv_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s,
- u64 req)
-{
- if (!wpa_s->driver->p2p_sd_cancel_request)
- return -1;
- return wpa_s->driver->p2p_sd_cancel_request(wpa_s->drv_priv, req);
-}
-
-static inline int wpa_drv_p2p_sd_response(struct wpa_supplicant *wpa_s,
- int freq, const u8 *dst,
- u8 dialog_token,
- const struct wpabuf *resp_tlvs)
-{
- if (!wpa_s->driver->p2p_sd_response)
- return -1;
- return wpa_s->driver->p2p_sd_response(wpa_s->drv_priv, freq, dst,
- dialog_token, resp_tlvs);
-}
-
-static inline int wpa_drv_p2p_service_update(struct wpa_supplicant *wpa_s)
-{
- if (!wpa_s->driver->p2p_service_update)
- return -1;
- return wpa_s->driver->p2p_service_update(wpa_s->drv_priv);
-}
-
-static inline int wpa_drv_p2p_reject(struct wpa_supplicant *wpa_s,
- const u8 *addr)
-{
- if (!wpa_s->driver->p2p_reject)
- return -1;
- return wpa_s->driver->p2p_reject(wpa_s->drv_priv, addr);
-}
-
-static inline int wpa_drv_p2p_invite(struct wpa_supplicant *wpa_s,
- const u8 *peer, int role, const u8 *bssid,
- const u8 *ssid, size_t ssid_len,
- const u8 *go_dev_addr,
- int persistent_group)
-{
- if (!wpa_s->driver->p2p_invite)
- return -1;
- return wpa_s->driver->p2p_invite(wpa_s->drv_priv, peer, role, bssid,
- ssid, ssid_len, go_dev_addr,
- persistent_group);
-}
-
static inline int wpa_drv_send_tdls_mgmt(struct wpa_supplicant *wpa_s,
const u8 *dst, u8 action_code,
u8 dialog_token, u16 status_code,
diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c
index 2b25b69..cb71475 100644
--- a/wpa_supplicant/eapol_test.c
+++ b/wpa_supplicant/eapol_test.c
@@ -30,9 +30,6 @@
#include "wpas_glue.h"
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-
struct wpa_driver_ops *wpa_drivers[] = { NULL };
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index c03dcc2..49c4058 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - Driver event processing
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -53,12 +53,12 @@
static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
- struct os_time now;
+ struct os_reltime now;
if (ssid == NULL || ssid->disabled_until.sec == 0)
return 0;
- os_get_time(&now);
+ os_get_reltime(&now);
if (ssid->disabled_until.sec > now.sec)
return ssid->disabled_until.sec - now.sec;
@@ -978,9 +978,6 @@
wpa_dbg(wpa_s, MSG_DEBUG, "Short-circuit new scan request "
"since there are no enabled networks");
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
-#ifdef CONFIG_P2P
- wpa_s->sta_scan_pending = 0;
-#endif /* CONFIG_P2P */
return;
}
@@ -1181,7 +1178,8 @@
union wpa_event_data *data,
int own_request)
{
- struct wpa_scan_results *scan_res;
+ struct wpa_scan_results *scan_res = NULL;
+ int ret = 0;
int ap = 0;
#ifndef CONFIG_NO_RANDOM_POOL
size_t i, num;
@@ -1194,24 +1192,6 @@
wpa_supplicant_notify_scanning(wpa_s, 0);
-#ifdef CONFIG_P2P
- if (own_request && wpa_s->global->p2p_cb_on_scan_complete &&
- !wpa_s->global->p2p_disabled &&
- wpa_s->global->p2p != NULL && !wpa_s->sta_scan_pending &&
- !wpa_s->scan_res_handler) {
- wpa_s->global->p2p_cb_on_scan_complete = 0;
- if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
- "stopped scan processing");
- wpa_s->scan_req = wpa_s->last_scan_req;
- wpa_s->sta_scan_pending = 1;
- wpa_supplicant_req_scan(wpa_s, 5, 0);
- return -1;
- }
- }
- wpa_s->sta_scan_pending = 0;
-#endif /* CONFIG_P2P */
-
scan_res = wpa_supplicant_get_scan_results(wpa_s,
data ? &data->scan_info :
NULL, 1);
@@ -1224,7 +1204,8 @@
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try "
"scanning again");
wpa_supplicant_req_new_scan(wpa_s, 1, 0);
- return -1;
+ ret = -1;
+ goto scan_work_done;
}
#ifndef CONFIG_NO_RANDOM_POOL
@@ -1243,16 +1224,16 @@
}
#endif /* CONFIG_NO_RANDOM_POOL */
- if (own_request && wpa_s->scan_res_handler) {
+ if (own_request && wpa_s->scan_res_handler &&
+ (wpa_s->own_scan_running || !wpa_s->external_scan_running)) {
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
scan_res_handler = wpa_s->scan_res_handler;
wpa_s->scan_res_handler = NULL;
scan_res_handler(wpa_s, scan_res);
-
- wpa_scan_results_free(scan_res);
- return -2;
+ ret = -2;
+ goto scan_work_done;
}
if (ap) {
@@ -1261,48 +1242,67 @@
if (wpa_s->ap_iface->scan_cb)
wpa_s->ap_iface->scan_cb(wpa_s->ap_iface);
#endif /* CONFIG_AP */
- wpa_scan_results_free(scan_res);
- return 0;
+ goto scan_work_done;
}
- wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available");
- wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
+ wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)",
+ wpa_s->own_scan_running, wpa_s->external_scan_running);
+ if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
+ wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
+ wpa_s->manual_scan_id);
+ wpa_s->manual_scan_use_id = 0;
+ } else {
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
+ }
wpas_notify_scan_results(wpa_s);
wpas_notify_scan_done(wpa_s, 1);
- if (sme_proc_obss_scan(wpa_s) > 0) {
+ if (!wpa_s->own_scan_running && wpa_s->external_scan_running) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Do not use results from externally requested scan operation for network selection");
wpa_scan_results_free(scan_res);
return 0;
}
- if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) {
- wpa_scan_results_free(scan_res);
- return 0;
- }
+ if (sme_proc_obss_scan(wpa_s) > 0)
+ goto scan_work_done;
- if (autoscan_notify_scan(wpa_s, scan_res)) {
- wpa_scan_results_free(scan_res);
- return 0;
- }
+ if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
+ goto scan_work_done;
+
+ if (autoscan_notify_scan(wpa_s, scan_res))
+ goto scan_work_done;
if (wpa_s->disconnected) {
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
- wpa_scan_results_free(scan_res);
- return 0;
+ goto scan_work_done;
}
if (!wpas_driver_bss_selection(wpa_s) &&
- bgscan_notify_scan(wpa_s, scan_res) == 1) {
- wpa_scan_results_free(scan_res);
- return 0;
- }
+ bgscan_notify_scan(wpa_s, scan_res) == 1)
+ goto scan_work_done;
wpas_wps_update_ap_info(wpa_s, scan_res);
wpa_scan_results_free(scan_res);
+ if (wpa_s->scan_work) {
+ struct wpa_radio_work *work = wpa_s->scan_work;
+ wpa_s->scan_work = NULL;
+ radio_work_done(work);
+ }
+
return wpas_select_network_from_last_scan(wpa_s, 1, own_request);
+
+scan_work_done:
+ wpa_scan_results_free(scan_res);
+ if (wpa_s->scan_work) {
+ struct wpa_radio_work *work = wpa_s->scan_work;
+ wpa_s->scan_work = NULL;
+ radio_work_done(work);
+ }
+ return ret;
}
@@ -1381,6 +1381,16 @@
return 1;
}
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_WPS
+ if (wpa_s->after_wps > 0 || wpas_wps_searching(wpa_s)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Use shorter wait during WPS processing");
+ timeout_sec = 0;
+ timeout_usec = 500000;
+ wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
+ timeout_usec);
+ return 0;
+ }
+#endif /* CONFIG_WPS */
if (wpa_supplicant_req_sched_scan(wpa_s))
wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
timeout_usec);
@@ -1428,13 +1438,13 @@
#ifdef CONFIG_NO_SCAN_PROCESSING
return -1;
#else /* CONFIG_NO_SCAN_PROCESSING */
- struct os_time now;
+ struct os_reltime now;
if (wpa_s->last_scan_res_used <= 0)
return -1;
- os_get_time(&now);
- if (now.sec - wpa_s->last_scan.sec > 5) {
+ os_get_reltime(&now);
+ if (os_reltime_expired(&now, &wpa_s->last_scan, 5)) {
wpa_printf(MSG_DEBUG, "Fast associate: Old scan results");
return -1;
}
@@ -1955,9 +1965,9 @@
wpa_s->last_eapol_matches_bssid = 0;
if (wpa_s->pending_eapol_rx) {
- struct os_time now, age;
- os_get_time(&now);
- os_time_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
+ struct os_reltime now, age;
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
if (age.sec == 0 && age.usec < 100000 &&
os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) ==
0) {
@@ -2143,7 +2153,6 @@
wpas_notify_disconnect_reason(wpa_s);
if (wpa_supplicant_dynamic_keys(wpa_s)) {
wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - remove keys");
- wpa_s->keys_cleared = 0;
wpa_clear_keys(wpa_s, wpa_s->bssid);
}
last_ssid = wpa_s->current_ssid;
@@ -2187,13 +2196,13 @@
union wpa_event_data *data)
{
int pairwise;
- struct os_time t;
+ struct os_reltime t;
wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected");
pairwise = (data && data->michael_mic_failure.unicast);
- os_get_time(&t);
- if ((wpa_s->last_michael_mic_error &&
- t.sec - wpa_s->last_michael_mic_error <= 60) ||
+ os_get_reltime(&t);
+ if ((wpa_s->last_michael_mic_error.sec &&
+ !os_reltime_expired(&t, &wpa_s->last_michael_mic_error, 60)) ||
wpa_s->pending_mic_error_report) {
if (wpa_s->pending_mic_error_report) {
/*
@@ -2271,7 +2280,7 @@
wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
}
- wpa_s->last_michael_mic_error = t.sec;
+ wpa_s->last_michael_mic_error = t;
wpa_s->mic_errors_seen++;
}
@@ -2687,6 +2696,87 @@
}
+static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
+ const struct ieee80211_mgmt *mgmt,
+ size_t len, int freq)
+{
+ const u8 *payload;
+ size_t plen;
+ u8 category;
+
+ if (len < IEEE80211_HDRLEN + 2)
+ return;
+
+ payload = &mgmt->u.action.category;
+ category = *payload++;
+ plen = (((const u8 *) mgmt) + len) - payload;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR
+ " Category=%u DataLen=%d freq=%d MHz",
+ MAC2STR(mgmt->sa), category, (int) plen, freq);
+
+#ifdef CONFIG_IEEE80211R
+ if (category == WLAN_ACTION_FT) {
+ ft_rx_action(wpa_s, payload, plen);
+ return;
+ }
+#endif /* CONFIG_IEEE80211R */
+
+#ifdef CONFIG_IEEE80211W
+#ifdef CONFIG_SME
+ if (category == WLAN_ACTION_SA_QUERY) {
+ sme_sa_query_rx(wpa_s, mgmt->sa, payload, plen);
+ return;
+ }
+#endif /* CONFIG_SME */
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_WNM
+ if (mgmt->u.action.category == WLAN_ACTION_WNM) {
+ ieee802_11_rx_wnm_action(wpa_s, mgmt, len);
+ return;
+ }
+#endif /* CONFIG_WNM */
+
+#ifdef CONFIG_GAS
+ if (mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
+ gas_query_rx(wpa_s->gas, mgmt->da, mgmt->sa, mgmt->bssid,
+ payload, plen, freq) == 0)
+ return;
+#endif /* CONFIG_GAS */
+
+#ifdef CONFIG_TDLS
+ if (category == WLAN_ACTION_PUBLIC && plen >= 4 &&
+ payload[0] == WLAN_TDLS_DISCOVERY_RESPONSE) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "TDLS: Received Discovery Response from " MACSTR,
+ MAC2STR(mgmt->sa));
+ return;
+ }
+#endif /* CONFIG_TDLS */
+
+#ifdef CONFIG_INTERWORKING
+ if (category == WLAN_ACTION_QOS && plen >= 1 &&
+ payload[0] == QOS_QOS_MAP_CONFIG) {
+ const u8 *pos = payload + 1;
+ size_t qlen = plen - 1;
+ wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
+ MACSTR, MAC2STR(mgmt->sa));
+ if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) == 0 &&
+ qlen > 2 && pos[0] == WLAN_EID_QOS_MAP_SET &&
+ pos[1] <= qlen - 2 && pos[1] >= 16)
+ wpas_qos_map_set(wpa_s, pos + 2, pos[1]);
+ return;
+ }
+#endif /* CONFIG_INTERWORKING */
+
+#ifdef CONFIG_P2P
+ wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
+ category, payload, plen, freq);
+#endif /* CONFIG_P2P */
+}
+
+
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
@@ -2740,11 +2830,44 @@
wpa_supplicant_event_michael_mic_failure(wpa_s, data);
break;
#ifndef CONFIG_NO_SCAN_PROCESSING
+ case EVENT_SCAN_STARTED:
+ os_get_reltime(&wpa_s->scan_start_time);
+ if (wpa_s->own_scan_requested) {
+ struct os_reltime diff;
+
+ os_reltime_sub(&wpa_s->scan_start_time,
+ &wpa_s->scan_trigger_time, &diff);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Own scan request started a scan in %ld.%06ld seconds",
+ diff.sec, diff.usec);
+ wpa_s->own_scan_requested = 0;
+ wpa_s->own_scan_running = 1;
+ if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
+ wpa_s->manual_scan_use_id) {
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED "id=%u",
+ wpa_s->manual_scan_id);
+ } else {
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
+ }
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
+ wpa_s->external_scan_running = 1;
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
+ }
+ break;
case EVENT_SCAN_RESULTS:
+ if (os_reltime_initialized(&wpa_s->scan_start_time)) {
+ struct os_reltime now, diff;
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &wpa_s->scan_start_time, &diff);
+ wpa_s->scan_start_time.sec = 0;
+ wpa_s->scan_start_time.usec = 0;
+ wpa_dbg(wpa_s, MSG_DEBUG, "Scan completed in %ld.%06ld seconds",
+ diff.sec, diff.usec);
+ }
wpa_supplicant_event_scan_results(wpa_s, data);
- if (wpa_s->wpa_state != WPA_AUTHENTICATING &&
- wpa_s->wpa_state != WPA_ASSOCIATING)
- wpas_p2p_continue_after_scan(wpa_s);
+ wpa_s->own_scan_running = 0;
+ wpa_s->external_scan_running = 0;
+ radio_work_check_next(wpa_s);
break;
#endif /* CONFIG_NO_SCAN_PROCESSING */
case EVENT_ASSOCINFO:
@@ -2901,7 +3024,6 @@
data->ch_switch.cf2);
break;
#endif /* CONFIG_AP */
-#if defined(CONFIG_AP) || defined(CONFIG_IBSS_RSN)
case EVENT_RX_MGMT: {
u16 fc, stype;
const struct ieee80211_mgmt *mgmt;
@@ -2936,6 +3058,14 @@
break;
}
#endif /* CONFIG_IBSS_RSN */
+
+ if (stype == WLAN_FC_STYPE_ACTION) {
+ wpas_event_rx_mgmt_action(
+ wpa_s, mgmt, data->rx_mgmt.frame_len,
+ data->rx_mgmt.freq);
+ break;
+ }
+
wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received "
"management frame in non-AP mode");
break;
@@ -2958,79 +3088,6 @@
#endif /* CONFIG_AP */
break;
}
-#endif /* CONFIG_AP || CONFIG_IBSS_RSN */
- case EVENT_RX_ACTION:
- wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR
- " Category=%u DataLen=%d freq=%d MHz",
- MAC2STR(data->rx_action.sa),
- data->rx_action.category, (int) data->rx_action.len,
- data->rx_action.freq);
-#ifdef CONFIG_IEEE80211R
- if (data->rx_action.category == WLAN_ACTION_FT) {
- ft_rx_action(wpa_s, data->rx_action.data,
- data->rx_action.len);
- break;
- }
-#endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_IEEE80211W
-#ifdef CONFIG_SME
- if (data->rx_action.category == WLAN_ACTION_SA_QUERY) {
- sme_sa_query_rx(wpa_s, data->rx_action.sa,
- data->rx_action.data,
- data->rx_action.len);
- break;
- }
-#endif /* CONFIG_SME */
-#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_WNM
- if (data->rx_action.category == WLAN_ACTION_WNM) {
- ieee802_11_rx_wnm_action(wpa_s, &data->rx_action);
- break;
- }
-#endif /* CONFIG_WNM */
-#ifdef CONFIG_GAS
- if (data->rx_action.category == WLAN_ACTION_PUBLIC &&
- gas_query_rx(wpa_s->gas, data->rx_action.da,
- data->rx_action.sa, data->rx_action.bssid,
- data->rx_action.data, data->rx_action.len,
- data->rx_action.freq) == 0)
- break;
-#endif /* CONFIG_GAS */
-#ifdef CONFIG_TDLS
- if (data->rx_action.category == WLAN_ACTION_PUBLIC &&
- data->rx_action.len >= 4 &&
- data->rx_action.data[0] == WLAN_TDLS_DISCOVERY_RESPONSE) {
- wpa_dbg(wpa_s, MSG_DEBUG, "TDLS: Received Discovery "
- "Response from " MACSTR,
- MAC2STR(data->rx_action.sa));
- break;
- }
-#endif /* CONFIG_TDLS */
-#ifdef CONFIG_INTERWORKING
- if (data->rx_action.category == WLAN_ACTION_QOS &&
- data->rx_action.len >= 1 &&
- data->rx_action.data[0] == QOS_QOS_MAP_CONFIG) {
- const u8 *pos = data->rx_action.data + 1;
- size_t len = data->rx_action.len - 1;
- wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
- MACSTR, MAC2STR(data->rx_action.sa));
- if (os_memcmp(data->rx_action.sa, wpa_s->bssid,
- ETH_ALEN) == 0 &&
- len > 2 && pos[0] == WLAN_EID_QOS_MAP_SET &&
- pos[1] <= len - 2 && pos[1] >= 16)
- wpas_qos_map_set(wpa_s, pos + 2, pos[1]);
- break;
- }
-#endif /* CONFIG_INTERWORKING */
-#ifdef CONFIG_P2P
- wpas_p2p_rx_action(wpa_s, data->rx_action.da,
- data->rx_action.sa,
- data->rx_action.bssid,
- data->rx_action.category,
- data->rx_action.data,
- data->rx_action.len, data->rx_action.freq);
-#endif /* CONFIG_P2P */
- break;
case EVENT_RX_PROBE_REQ:
if (data->rx_probe_req.sa == NULL ||
data->rx_probe_req.ie == NULL)
@@ -3078,71 +3135,6 @@
wpa_s, data->remain_on_channel.freq);
#endif /* CONFIG_P2P */
break;
-#ifdef CONFIG_P2P
- case EVENT_P2P_DEV_FOUND: {
- struct p2p_peer_info peer_info;
-
- os_memset(&peer_info, 0, sizeof(peer_info));
- if (data->p2p_dev_found.dev_addr)
- os_memcpy(peer_info.p2p_device_addr,
- data->p2p_dev_found.dev_addr, ETH_ALEN);
- if (data->p2p_dev_found.pri_dev_type)
- os_memcpy(peer_info.pri_dev_type,
- data->p2p_dev_found.pri_dev_type,
- sizeof(peer_info.pri_dev_type));
- if (data->p2p_dev_found.dev_name)
- os_strlcpy(peer_info.device_name,
- data->p2p_dev_found.dev_name,
- sizeof(peer_info.device_name));
- peer_info.config_methods = data->p2p_dev_found.config_methods;
- peer_info.dev_capab = data->p2p_dev_found.dev_capab;
- peer_info.group_capab = data->p2p_dev_found.group_capab;
-
- /*
- * FIX: new_device=1 is not necessarily correct. We should
- * maintain a P2P peer database in wpa_supplicant and update
- * this information based on whether the peer is truly new.
- */
- wpas_dev_found(wpa_s, data->p2p_dev_found.addr, &peer_info, 1);
- break;
- }
- case EVENT_P2P_GO_NEG_REQ_RX:
- wpas_go_neg_req_rx(wpa_s, data->p2p_go_neg_req_rx.src,
- data->p2p_go_neg_req_rx.dev_passwd_id);
- break;
- case EVENT_P2P_GO_NEG_COMPLETED:
- wpas_go_neg_completed(wpa_s, data->p2p_go_neg_completed.res);
- break;
- case EVENT_P2P_PROV_DISC_REQUEST:
- wpas_prov_disc_req(wpa_s, data->p2p_prov_disc_req.peer,
- data->p2p_prov_disc_req.config_methods,
- data->p2p_prov_disc_req.dev_addr,
- data->p2p_prov_disc_req.pri_dev_type,
- data->p2p_prov_disc_req.dev_name,
- data->p2p_prov_disc_req.supp_config_methods,
- data->p2p_prov_disc_req.dev_capab,
- data->p2p_prov_disc_req.group_capab,
- NULL, 0);
- break;
- case EVENT_P2P_PROV_DISC_RESPONSE:
- wpas_prov_disc_resp(wpa_s, data->p2p_prov_disc_resp.peer,
- data->p2p_prov_disc_resp.config_methods);
- break;
- case EVENT_P2P_SD_REQUEST:
- wpas_sd_request(wpa_s, data->p2p_sd_req.freq,
- data->p2p_sd_req.sa,
- data->p2p_sd_req.dialog_token,
- data->p2p_sd_req.update_indic,
- data->p2p_sd_req.tlvs,
- data->p2p_sd_req.tlvs_len);
- break;
- case EVENT_P2P_SD_RESPONSE:
- wpas_sd_response(wpa_s, data->p2p_sd_resp.sa,
- data->p2p_sd_resp.update_indic,
- data->p2p_sd_resp.tlvs,
- data->p2p_sd_resp.tlvs_len);
- break;
-#endif /* CONFIG_P2P */
case EVENT_EAPOL_RX:
wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
data->eapol_rx.data,
diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c
index f9885e3..f002fd5 100644
--- a/wpa_supplicant/gas_query.c
+++ b/wpa_supplicant/gas_query.c
@@ -2,6 +2,7 @@
* Generic advertisement service (GAS) query
* Copyright (c) 2009, Atheros Communications
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -13,6 +14,7 @@
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/gas.h"
+#include "common/wpa_ctrl.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "offchannel.h"
@@ -21,8 +23,6 @@
/** GAS query timeout in seconds */
#define GAS_QUERY_TIMEOUT_PERIOD 2
-/** Retry period for GAS query requests in milliseconds */
-#define GAS_SERVICE_RETRY_PERIOD_MS 500
/**
@@ -30,6 +30,7 @@
*/
struct gas_query_pending {
struct dl_list list;
+ struct gas_query *gas;
u8 addr[ETH_ALEN];
u8 dialog_token;
u8 next_frag_id;
@@ -54,12 +55,12 @@
struct wpa_supplicant *wpa_s;
struct dl_list pending; /* struct gas_query_pending */
struct gas_query_pending *current;
+ struct wpa_radio_work *work;
};
static void gas_query_tx_comeback_timeout(void *eloop_data, void *user_ctx);
static void gas_query_timeout(void *eloop_data, void *user_ctx);
-static void gas_service_timeout(void *eloop_data, void *user_ctx);
/**
@@ -82,24 +83,66 @@
}
+static const char * gas_result_txt(enum gas_query_result result)
+{
+ switch (result) {
+ case GAS_QUERY_SUCCESS:
+ return "SUCCESS";
+ case GAS_QUERY_FAILURE:
+ return "FAILURE";
+ case GAS_QUERY_TIMEOUT:
+ return "TIMEOUT";
+ case GAS_QUERY_PEER_ERROR:
+ return "PEER_ERROR";
+ case GAS_QUERY_INTERNAL_ERROR:
+ return "INTERNAL_ERROR";
+ case GAS_QUERY_CANCELLED:
+ return "CANCELLED";
+ case GAS_QUERY_DELETED_AT_DEINIT:
+ return "DELETED_AT_DEINIT";
+ }
+
+ return "N/A";
+}
+
+
+static void gas_query_free(struct gas_query_pending *query, int del_list)
+{
+ struct gas_query *gas = query->gas;
+
+ if (del_list)
+ dl_list_del(&query->list);
+
+ if (gas->work && gas->work->ctx == query) {
+ radio_work_done(gas->work);
+ gas->work = NULL;
+ }
+
+ wpabuf_free(query->req);
+ wpabuf_free(query->adv_proto);
+ wpabuf_free(query->resp);
+ os_free(query);
+}
+
+
static void gas_query_done(struct gas_query *gas,
struct gas_query_pending *query,
enum gas_query_result result)
{
+ wpa_msg(gas->wpa_s, MSG_INFO, GAS_QUERY_DONE "addr=" MACSTR
+ " dialog_token=%u freq=%d status_code=%u result=%s",
+ MAC2STR(query->addr), query->dialog_token, query->freq,
+ query->status_code, gas_result_txt(result));
if (gas->current == query)
gas->current = NULL;
if (query->offchannel_tx_started)
offchannel_send_action_done(gas->wpa_s);
eloop_cancel_timeout(gas_query_tx_comeback_timeout, gas, query);
eloop_cancel_timeout(gas_query_timeout, gas, query);
- eloop_cancel_timeout(gas_service_timeout, gas, query);
dl_list_del(&query->list);
query->cb(query->ctx, query->addr, query->dialog_token, result,
query->adv_proto, query->resp, query->status_code);
- wpabuf_free(query->req);
- wpabuf_free(query->adv_proto);
- wpabuf_free(query->resp);
- os_free(query);
+ gas_query_free(query, 0);
}
@@ -480,43 +523,6 @@
}
-static void gas_service_timeout(void *eloop_data, void *user_ctx)
-{
- struct gas_query *gas = eloop_data;
- struct wpa_supplicant *wpa_s = gas->wpa_s;
- struct gas_query_pending *query = user_ctx;
- int conn;
-
- conn = wpas_wpa_is_in_progress(wpa_s, 1);
- if (conn || wpa_s->scanning || gas->current) {
- wpa_printf(MSG_DEBUG, "GAS: Delaying GAS query Tx while another operation is in progress:%s%s%s",
- conn ? " connection" : "",
- wpa_s->scanning ? " scanning" : "",
- gas->current ? " gas_query" : "");
- eloop_register_timeout(
- GAS_SERVICE_RETRY_PERIOD_MS / 1000,
- (GAS_SERVICE_RETRY_PERIOD_MS % 1000) * 1000,
- gas_service_timeout, gas, query);
- return;
- }
-
- if (gas_query_tx(gas, query, query->req) < 0) {
- wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
- MACSTR, MAC2STR(query->addr));
- dl_list_del(&query->list);
- wpabuf_free(query->req);
- os_free(query);
- return;
- }
- gas->current = query;
-
- wpa_printf(MSG_DEBUG, "GAS: Starting query timeout for dialog token %u",
- query->dialog_token);
- eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
- gas_query_timeout, gas, query);
-}
-
-
static int gas_query_dialog_token_available(struct gas_query *gas,
const u8 *dst, u8 dialog_token)
{
@@ -531,6 +537,34 @@
}
+static void gas_query_start_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct gas_query_pending *query = work->ctx;
+ struct gas_query *gas = query->gas;
+
+ if (deinit) {
+ gas_query_free(query, 1);
+ return;
+ }
+
+ gas->work = work;
+
+ if (gas_query_tx(gas, query, query->req) < 0) {
+ wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
+ MACSTR, MAC2STR(query->addr));
+ gas_query_free(query, 1);
+ return;
+ }
+ gas->current = query;
+
+ wpa_printf(MSG_DEBUG, "GAS: Starting query timeout for dialog token %u",
+ query->dialog_token);
+ eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
+ gas_query_timeout, gas, query);
+
+}
+
+
/**
* gas_query_req - Request a GAS query
* @gas: GAS query data from gas_query_init()
@@ -571,6 +605,7 @@
if (query == NULL)
return -1;
+ query->gas = gas;
os_memcpy(query->addr, dst, ETH_ALEN);
query->dialog_token = dialog_token;
query->freq = freq;
@@ -581,10 +616,15 @@
*(wpabuf_mhead_u8(req) + 2) = dialog_token;
- wpa_printf(MSG_DEBUG, "GAS: Starting request for " MACSTR
- " dialog_token %u", MAC2STR(dst), dialog_token);
+ wpa_msg(gas->wpa_s, MSG_INFO, GAS_QUERY_START "addr=" MACSTR
+ " dialog_token=%u freq=%d",
+ MAC2STR(query->addr), query->dialog_token, query->freq);
- eloop_register_timeout(0, 0, gas_service_timeout, gas, query);
+ if (radio_add_work(gas->wpa_s, freq, "gas-query", 0, gas_query_start_cb,
+ query) < 0) {
+ gas_query_free(query, 1);
+ return -1;
+ }
return dialog_token;
}
@@ -605,9 +645,3 @@
gas_query_done(gas, query, GAS_QUERY_CANCELLED);
}
-
-
-int gas_query_in_progress(struct gas_query *gas)
-{
- return gas->current != NULL;
-}
diff --git a/wpa_supplicant/gas_query.h b/wpa_supplicant/gas_query.h
index 6b6c77c..5c3d161 100644
--- a/wpa_supplicant/gas_query.h
+++ b/wpa_supplicant/gas_query.h
@@ -18,7 +18,6 @@
void gas_query_deinit(struct gas_query *gas);
int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
const u8 *bssid, const u8 *data, size_t len, int freq);
-int gas_query_in_progress(struct gas_query *gas);
/**
* enum gas_query_result - GAS query result
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 47ef35e..3083dd8 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -590,7 +590,7 @@
peer->authentication_status |= IBSS_RSN_AUTH_BY_US;
return ibss_rsn_auth_init(ibss_rsn, peer);
} else {
- os_get_time(&peer->own_auth_tx);
+ os_get_reltime(&peer->own_auth_tx);
eloop_register_timeout(1, 0, ibss_rsn_auth_timeout, peer, NULL);
}
@@ -834,9 +834,9 @@
if (peer &&
peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) {
if (peer->own_auth_tx.sec) {
- struct os_time now, diff;
- os_get_time(&now);
- os_time_sub(&now, &peer->own_auth_tx, &diff);
+ struct os_reltime now, diff;
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &peer->own_auth_tx, &diff);
if (diff.sec == 0 && diff.usec < 500000) {
wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX",
(int) diff.usec);
diff --git a/wpa_supplicant/ibss_rsn.h b/wpa_supplicant/ibss_rsn.h
index 3089283..67fae2d 100644
--- a/wpa_supplicant/ibss_rsn.h
+++ b/wpa_supplicant/ibss_rsn.h
@@ -40,7 +40,7 @@
struct wpa_state_machine *auth;
int authentication_status;
- struct os_time own_auth_tx;
+ struct os_reltime own_auth_tx;
};
struct ibss_rsn {
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 93652d8..da8971d 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -1,6 +1,7 @@
/*
* Interworking (IEEE 802.11u)
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -520,12 +521,13 @@
if (eap_get_name(EAP_VENDOR_IETF, eap->method) == NULL)
return 0; /* method not supported */
- if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP) {
+ if (eap->method != EAP_TYPE_TTLS && eap->method != EAP_TYPE_PEAP &&
+ eap->method != EAP_TYPE_FAST) {
/* Only tunneled methods with username/password supported */
return 0;
}
- if (eap->method == EAP_TYPE_PEAP) {
+ if (eap->method == EAP_TYPE_PEAP || eap->method == EAP_TYPE_FAST) {
if (eap->inner_method &&
eap_get_name(EAP_VENDOR_IETF, eap->inner_method) == NULL)
return 0;
@@ -1416,6 +1418,13 @@
}
break;
case EAP_TYPE_PEAP:
+ case EAP_TYPE_FAST:
+ if (wpa_config_set(ssid, "phase1", "\"fast_provisioning=2\"",
+ 0) < 0)
+ goto fail;
+ if (wpa_config_set(ssid, "pac_file",
+ "\"blob://pac_interworking\"", 0) < 0)
+ goto fail;
os_snprintf(buf, sizeof(buf), "\"auth=%s\"",
eap_get_name(EAP_VENDOR_IETF,
eap->inner_method ?
@@ -2194,7 +2203,8 @@
}
-int interworking_select(struct wpa_supplicant *wpa_s, int auto_select)
+int interworking_select(struct wpa_supplicant *wpa_s, int auto_select,
+ int *freqs)
{
interworking_stop_fetch_anqp(wpa_s);
wpa_s->network_select = 1;
@@ -2206,6 +2216,8 @@
wpa_s->scan_res_handler = interworking_scan_res_handler;
wpa_s->normal_scans = 0;
wpa_s->scan_req = MANUAL_SCAN_REQ;
+ os_free(wpa_s->manual_scan_freqs);
+ wpa_s->manual_scan_freqs = freqs;
wpa_s->after_wps = 0;
wpa_s->known_wps_freq = 0;
wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -2220,6 +2232,7 @@
const struct wpabuf *resp, u16 status_code)
{
struct wpa_supplicant *wpa_s = ctx;
+ struct wpabuf *n;
wpa_msg(wpa_s, MSG_INFO, GAS_RESPONSE_INFO "addr=" MACSTR
" dialog_token=%d status_code=%d resp_len=%d",
@@ -2228,10 +2241,14 @@
if (!resp)
return;
- wpabuf_free(wpa_s->last_gas_resp);
- wpa_s->last_gas_resp = wpabuf_dup(resp);
- if (wpa_s->last_gas_resp == NULL)
+ n = wpabuf_dup(resp);
+ if (n == NULL)
return;
+ wpabuf_free(wpa_s->prev_gas_resp);
+ wpa_s->prev_gas_resp = wpa_s->last_gas_resp;
+ os_memcpy(wpa_s->prev_gas_addr, wpa_s->last_gas_addr, ETH_ALEN);
+ wpa_s->prev_gas_dialog_token = wpa_s->last_gas_dialog_token;
+ wpa_s->last_gas_resp = n;
os_memcpy(wpa_s->last_gas_addr, addr, ETH_ALEN);
wpa_s->last_gas_dialog_token = dialog_token;
}
diff --git a/wpa_supplicant/interworking.h b/wpa_supplicant/interworking.h
index 4a4af82..c8e7093 100644
--- a/wpa_supplicant/interworking.h
+++ b/wpa_supplicant/interworking.h
@@ -22,7 +22,8 @@
const struct wpabuf *query);
int interworking_fetch_anqp(struct wpa_supplicant *wpa_s);
void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s);
-int interworking_select(struct wpa_supplicant *wpa_s, int auto_select);
+int interworking_select(struct wpa_supplicant *wpa_s, int auto_select,
+ int *freqs);
int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss);
void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s);
int interworking_home_sp_cred(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index 39b837e..37f0c78 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -16,8 +16,6 @@
#include "driver_i.h"
#include "p2p_supplicant.h"
-extern struct wpa_driver_ops *wpa_drivers[];
-
static void usage(void)
{
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index e6a88e6..41d5102 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1,6 +1,7 @@
/*
* wpa_supplicant - P2P
* Copyright (c) 2009-2010, Atheros Communications
+ * Copyright (c) 2010-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -196,6 +197,12 @@
{
size_t i;
+ if (wpa_s->p2p_scan_work) {
+ struct wpa_radio_work *work = wpa_s->p2p_scan_work;
+ wpa_s->p2p_scan_work = NULL;
+ radio_work_done(work);
+ }
+
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return;
@@ -204,13 +211,13 @@
for (i = 0; i < scan_res->num; i++) {
struct wpa_scan_res *bss = scan_res->res[i];
- struct os_time time_tmp_age, entry_ts;
+ struct os_reltime time_tmp_age, entry_ts;
const u8 *ies;
size_t ies_len;
time_tmp_age.sec = bss->age / 1000;
time_tmp_age.usec = (bss->age % 1000) * 1000;
- os_time_sub(&scan_res->fetch_time, &time_tmp_age, &entry_ts);
+ os_reltime_sub(&scan_res->fetch_time, &time_tmp_age, &entry_ts);
ies = (const u8 *) (bss + 1);
ies_len = bss->ie_len;
@@ -234,94 +241,125 @@
}
+static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpa_driver_scan_params *params = work->ctx;
+ int ret;
+
+ if (deinit) {
+ wpa_scan_free_params(params);
+ return;
+ }
+
+ ret = wpa_drv_scan(wpa_s, params);
+ wpa_scan_free_params(params);
+ work->ctx = NULL;
+ if (ret) {
+ radio_work_done(work);
+ return;
+ }
+
+ os_get_reltime(&wpa_s->scan_trigger_time);
+ wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
+ wpa_s->own_scan_requested = 1;
+ wpa_s->p2p_scan_work = work;
+}
+
+
static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
unsigned int num_req_dev_types,
const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
{
struct wpa_supplicant *wpa_s = ctx;
- struct wpa_supplicant *ifs;
- struct wpa_driver_scan_params params;
- int ret;
+ struct wpa_driver_scan_params *params = NULL;
struct wpabuf *wps_ie, *ies;
- int social_channels[] = { 2412, 2437, 2462, 0, 0 };
size_t ielen;
+ u8 *n;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
- for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
- if (ifs->sta_scan_pending &&
- (wpas_scan_scheduled(ifs) || ifs->scanning) &&
- wpas_p2p_in_progress(wpa_s) == 2) {
- wpa_printf(MSG_DEBUG, "Delaying P2P scan to allow "
- "pending station mode scan to be "
- "completed on interface %s", ifs->ifname);
- wpa_s->global->p2p_cb_on_scan_complete = 1;
- wpa_supplicant_req_scan(ifs, 0, 0);
- return 1;
- }
+ if (wpa_s->p2p_scan_work) {
+ wpa_dbg(wpa_s, MSG_INFO, "P2P: Reject scan trigger since one is already pending");
+ return -1;
}
- os_memset(¶ms, 0, sizeof(params));
+ params = os_zalloc(sizeof(*params));
+ if (params == NULL)
+ return -1;
/* P2P Wildcard SSID */
- params.num_ssids = 1;
- params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
- params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
+ params->num_ssids = 1;
+ n = os_malloc(P2P_WILDCARD_SSID_LEN);
+ if (n == NULL)
+ goto fail;
+ os_memcpy(n, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
+ params->ssids[0].ssid = n;
+ params->ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
wpa_s->wps->dev.p2p = 1;
wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
wpa_s->wps->uuid, WPS_REQ_ENROLLEE,
num_req_dev_types, req_dev_types);
if (wps_ie == NULL)
- return -1;
+ goto fail;
ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
if (ies == NULL) {
wpabuf_free(wps_ie);
- return -1;
+ goto fail;
}
wpabuf_put_buf(ies, wps_ie);
wpabuf_free(wps_ie);
p2p_scan_ie(wpa_s->global->p2p, ies, dev_id);
- params.p2p_probe = 1;
- params.extra_ies = wpabuf_head(ies);
- params.extra_ies_len = wpabuf_len(ies);
+ params->p2p_probe = 1;
+ n = os_malloc(wpabuf_len(ies));
+ if (n == NULL) {
+ wpabuf_free(ies);
+ goto fail;
+ }
+ os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies));
+ params->extra_ies = n;
+ params->extra_ies_len = wpabuf_len(ies);
+ wpabuf_free(ies);
switch (type) {
case P2P_SCAN_SOCIAL:
- params.freqs = social_channels;
+ params->freqs = os_malloc(4 * sizeof(int));
+ if (params->freqs == NULL)
+ goto fail;
+ params->freqs[0] = 2412;
+ params->freqs[1] = 2437;
+ params->freqs[2] = 2462;
+ params->freqs[3] = 0;
break;
case P2P_SCAN_FULL:
break;
case P2P_SCAN_SOCIAL_PLUS_ONE:
- social_channels[3] = freq;
- params.freqs = social_channels;
+ params->freqs = os_malloc(5 * sizeof(int));
+ if (params->freqs == NULL)
+ goto fail;
+ params->freqs[0] = 2412;
+ params->freqs[1] = 2437;
+ params->freqs[2] = 2462;
+ params->freqs[3] = freq;
+ params->freqs[4] = 0;
break;
}
- ret = wpa_drv_scan(wpa_s, ¶ms);
+ radio_remove_unstarted_work(wpa_s, "p2p-scan");
+ if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb,
+ params) < 0)
+ goto fail;
+ return 0;
- wpabuf_free(ies);
-
- if (ret) {
- for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
- if (ifs->scanning ||
- ifs->scan_res_handler == wpas_p2p_scan_res_handler) {
- wpa_s->global->p2p_cb_on_scan_complete = 1;
- ret = 1;
- break;
- }
- }
- } else {
- os_get_time(&wpa_s->scan_trigger_time);
- wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
- }
-
- return ret;
+fail:
+ wpa_scan_free_params(params);
+ return -1;
}
@@ -488,6 +526,8 @@
os_free(wpa_s->go_params);
wpa_s->go_params = NULL;
+ wpa_s->waiting_presence_resp = 0;
+
wpa_printf(MSG_DEBUG, "P2P: Remove temporary group network");
if (ssid && (ssid->p2p_group ||
ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
@@ -510,7 +550,6 @@
wpa_config_remove_network(wpa_s->conf, id);
wpa_supplicant_clear_status(wpa_s);
wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_s->sta_scan_pending = 0;
} else {
wpa_printf(MSG_DEBUG, "P2P: Temporary group network not "
"found");
@@ -853,11 +892,37 @@
network_id = ssid->id;
if (!client) {
wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
- os_get_time(&wpa_s->global->p2p_go_wait_client);
+ os_get_reltime(&wpa_s->global->p2p_go_wait_client);
}
}
+struct send_action_work {
+ unsigned int freq;
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
+ size_t len;
+ unsigned int wait_time;
+ u8 buf[0];
+};
+
+
+static void wpas_p2p_send_action_work_timeout(void *eloop_ctx,
+ void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+
+ if (!wpa_s->p2p_send_action_work)
+ return;
+
+ wpa_printf(MSG_DEBUG, "P2P: Send Action frame radio work timed out");
+ os_free(wpa_s->p2p_send_action_work->ctx);
+ radio_work_done(wpa_s->p2p_send_action_work);
+ wpa_s->p2p_send_action_work = NULL;
+}
+
+
static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
unsigned int freq,
const u8 *dst, const u8 *src,
@@ -868,10 +933,31 @@
{
enum p2p_send_action_result res = P2P_SEND_ACTION_SUCCESS;
+ if (wpa_s->p2p_send_action_work) {
+ struct send_action_work *awork;
+ awork = wpa_s->p2p_send_action_work->ctx;
+ if (awork->wait_time == 0) {
+ os_free(awork);
+ radio_work_done(wpa_s->p2p_send_action_work);
+ wpa_s->p2p_send_action_work = NULL;
+ } else {
+ /*
+ * In theory, this should not be needed, but number of
+ * places in the P2P code is still using non-zero wait
+ * time for the last Action frame in the sequence and
+ * some of these do not call send_action_done().
+ */
+ eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
+ wpa_s, NULL);
+ eloop_register_timeout(
+ 0, awork->wait_time * 1000,
+ wpas_p2p_send_action_work_timeout,
+ wpa_s, NULL);
+ }
+ }
+
if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
return;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return;
switch (result) {
case OFFCHANNEL_SEND_ACTION_SUCCESS:
@@ -901,11 +987,81 @@
}
+static void wpas_send_action_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct send_action_work *awork = work->ctx;
+
+ if (deinit) {
+ os_free(awork);
+ return;
+ }
+
+ if (offchannel_send_action(wpa_s, awork->freq, awork->dst, awork->src,
+ awork->bssid, awork->buf, awork->len,
+ awork->wait_time,
+ wpas_p2p_send_action_tx_status, 1) < 0) {
+ os_free(awork);
+ radio_work_done(work);
+ return;
+ }
+ wpa_s->p2p_send_action_work = work;
+}
+
+
+static int wpas_send_action_work(struct wpa_supplicant *wpa_s,
+ unsigned int freq, const u8 *dst,
+ const u8 *src, const u8 *bssid, const u8 *buf,
+ size_t len, unsigned int wait_time)
+{
+ struct send_action_work *awork;
+
+ if (wpa_s->p2p_send_action_work) {
+ wpa_printf(MSG_DEBUG, "P2P: Cannot schedule new p2p-send-action work since one is already pending");
+ return -1;
+ }
+
+ awork = os_zalloc(sizeof(*awork) + len);
+ if (awork == NULL)
+ return -1;
+
+ awork->freq = freq;
+ os_memcpy(awork->dst, dst, ETH_ALEN);
+ os_memcpy(awork->src, src, ETH_ALEN);
+ os_memcpy(awork->bssid, bssid, ETH_ALEN);
+ awork->len = len;
+ awork->wait_time = wait_time;
+ os_memcpy(awork->buf, buf, len);
+
+ if (radio_add_work(wpa_s, freq, "p2p-send-action", 0,
+ wpas_send_action_cb, awork) < 0) {
+ os_free(awork);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst,
const u8 *src, const u8 *bssid, const u8 *buf,
size_t len, unsigned int wait_time)
{
struct wpa_supplicant *wpa_s = ctx;
+ int listen_freq = -1, send_freq = -1;
+
+ if (wpa_s->p2p_listen_work)
+ listen_freq = wpa_s->p2p_listen_work->freq;
+ if (wpa_s->p2p_send_action_work)
+ send_freq = wpa_s->p2p_send_action_work->freq;
+ if (listen_freq != (int) freq && send_freq != (int) freq) {
+ wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d)",
+ listen_freq, send_freq);
+ return wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
+ len, wait_time);
+ }
+
+ wpa_printf(MSG_DEBUG, "P2P: Use ongoing radio work for Action frame TX");
return offchannel_send_action(wpa_s, freq, dst, src, bssid, buf, len,
wait_time,
wpas_p2p_send_action_tx_status, 1);
@@ -915,6 +1071,15 @@
static void wpas_send_action_done(void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
+
+ if (wpa_s->p2p_send_action_work) {
+ eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
+ wpa_s, NULL);
+ os_free(wpa_s->p2p_send_action_work->ctx);
+ radio_work_done(wpa_s->p2p_send_action_work);
+ wpa_s->p2p_send_action_work = NULL;
+ }
+
offchannel_send_action_done(wpa_s);
}
@@ -1030,7 +1195,7 @@
" [PERSISTENT]" : "");
}
- os_get_time(&wpa_s->global->p2p_go_wait_client);
+ os_get_reltime(&wpa_s->global->p2p_go_wait_client);
if (params->persistent_group) {
network_id = wpas_p2p_store_persistent_group(
wpa_s->parent, ssid,
@@ -1328,12 +1493,21 @@
wpa_s->parent, NULL);
if (wpa_s->global->p2p)
p2p_group_formation_failed(wpa_s->global->p2p);
- else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- wpa_drv_p2p_group_formation_failed(wpa_s);
wpas_group_formation_completed(wpa_s, 0);
}
+static void wpas_p2p_grpform_fail_after_wps(struct wpa_supplicant *wpa_s)
+{
+ wpa_printf(MSG_DEBUG, "P2P: Reject group formation due to WPS provisioning failure");
+ eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
+ wpa_s->parent, NULL);
+ eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
+ wpa_s->parent, NULL);
+ wpa_s->global->p2p_fail_on_wps_complete = 0;
+}
+
+
void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s)
{
if (wpa_s->global->p2p_group_formation != wpa_s)
@@ -1346,7 +1520,7 @@
}
-void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
+static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -1433,7 +1607,7 @@
}
-void wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
+static void wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id)
{
struct wpa_supplicant *wpa_s = ctx;
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_REQUEST MACSTR
@@ -1443,9 +1617,9 @@
}
-void wpas_dev_found(void *ctx, const u8 *addr,
- const struct p2p_peer_info *info,
- int new_device)
+static void wpas_dev_found(void *ctx, const u8 *addr,
+ const struct p2p_peer_info *info,
+ int new_device)
{
#ifndef CONFIG_NO_STDOUT_DEBUG
struct wpa_supplicant *wpa_s = ctx;
@@ -1494,32 +1668,104 @@
}
+struct wpas_p2p_listen_work {
+ unsigned int freq;
+ unsigned int duration;
+ struct wpabuf *probe_resp_ie;
+};
+
+
+static void wpas_p2p_listen_work_free(struct wpas_p2p_listen_work *lwork)
+{
+ if (lwork == NULL)
+ return;
+ wpabuf_free(lwork->probe_resp_ie);
+ os_free(lwork);
+}
+
+
+static void wpas_p2p_listen_work_done(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_p2p_listen_work *lwork;
+
+ if (!wpa_s->p2p_listen_work)
+ return;
+
+ lwork = wpa_s->p2p_listen_work->ctx;
+ wpas_p2p_listen_work_free(lwork);
+ radio_work_done(wpa_s->p2p_listen_work);
+ wpa_s->p2p_listen_work = NULL;
+}
+
+
+static void wpas_start_listen_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpas_p2p_listen_work *lwork = work->ctx;
+
+ if (deinit) {
+ wpas_p2p_listen_work_free(lwork);
+ return;
+ }
+
+ wpa_s->p2p_listen_work = work;
+
+ wpa_drv_set_ap_wps_ie(wpa_s, NULL, lwork->probe_resp_ie, NULL);
+
+ if (wpa_drv_probe_req_report(wpa_s, 1) < 0) {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver to "
+ "report received Probe Request frames");
+ wpas_p2p_listen_work_done(wpa_s);
+ return;
+ }
+
+ wpa_s->pending_listen_freq = lwork->freq;
+ wpa_s->pending_listen_duration = lwork->duration;
+
+ if (wpa_drv_remain_on_channel(wpa_s, lwork->freq, lwork->duration) < 0)
+ {
+ wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver "
+ "to remain on channel (%u MHz) for Listen "
+ "state", lwork->freq);
+ wpas_p2p_listen_work_done(wpa_s);
+ wpa_s->pending_listen_freq = 0;
+ return;
+ }
+ wpa_s->off_channel_freq = 0;
+ wpa_s->roc_waiting_drv_freq = lwork->freq;
+}
+
+
static int wpas_start_listen(void *ctx, unsigned int freq,
unsigned int duration,
const struct wpabuf *probe_resp_ie)
{
struct wpa_supplicant *wpa_s = ctx;
+ struct wpas_p2p_listen_work *lwork;
- wpa_drv_set_ap_wps_ie(wpa_s, NULL, probe_resp_ie, NULL);
-
- if (wpa_drv_probe_req_report(wpa_s, 1) < 0) {
- wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver to "
- "report received Probe Request frames");
+ if (wpa_s->p2p_listen_work) {
+ wpa_printf(MSG_DEBUG, "P2P: Reject start_listen since p2p_listen_work already exists");
return -1;
}
- wpa_s->pending_listen_freq = freq;
- wpa_s->pending_listen_duration = duration;
+ lwork = os_zalloc(sizeof(*lwork));
+ if (lwork == NULL)
+ return -1;
+ lwork->freq = freq;
+ lwork->duration = duration;
+ if (probe_resp_ie) {
+ lwork->probe_resp_ie = wpabuf_dup(probe_resp_ie);
+ if (lwork->probe_resp_ie == NULL) {
+ wpas_p2p_listen_work_free(lwork);
+ return -1;
+ }
+ }
- if (wpa_drv_remain_on_channel(wpa_s, freq, duration) < 0) {
- wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver "
- "to remain on channel (%u MHz) for Listen "
- "state", freq);
- wpa_s->pending_listen_freq = 0;
+ if (radio_add_work(wpa_s, freq, "p2p-listen", 0, wpas_start_listen_cb,
+ lwork) < 0) {
+ wpas_p2p_listen_work_free(lwork);
return -1;
}
- wpa_s->off_channel_freq = 0;
- wpa_s->roc_waiting_drv_freq = freq;
return 0;
}
@@ -1535,6 +1781,7 @@
}
wpa_drv_set_ap_wps_ie(wpa_s, NULL, NULL, NULL);
wpa_drv_probe_req_report(wpa_s, 0);
+ wpas_p2p_listen_work_done(wpa_s);
}
@@ -2035,8 +2282,8 @@
#endif /* CONFIG_WIFI_DISPLAY */
-void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
- u16 update_indic, const u8 *tlvs, size_t tlvs_len)
+static void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
+ u16 update_indic, const u8 *tlvs, size_t tlvs_len)
{
struct wpa_supplicant *wpa_s = ctx;
const u8 *pos = tlvs;
@@ -2153,8 +2400,8 @@
}
-void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
- const u8 *tlvs, size_t tlvs_len)
+static void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
+ const u8 *tlvs, size_t tlvs_len)
{
struct wpa_supplicant *wpa_s = ctx;
const u8 *pos = tlvs;
@@ -2221,8 +2468,6 @@
u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
const struct wpabuf *tlvs)
{
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return wpa_drv_p2p_sd_request(wpa_s, dst, tlvs);
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return 0;
return (uintptr_t) p2p_sd_request(wpa_s->global->p2p, dst, tlvs);
@@ -2254,8 +2499,6 @@
static u64 wpas_p2p_sd_request_wfd(struct wpa_supplicant *wpa_s, const u8 *dst,
const struct wpabuf *tlvs)
{
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return 0;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return 0;
return (uintptr_t) p2p_sd_request_wfd(wpa_s->global->p2p, dst, tlvs);
@@ -2333,8 +2576,6 @@
int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, u64 req)
{
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return wpa_drv_p2p_sd_cancel_request(wpa_s, req);
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
return p2p_sd_cancel_request(wpa_s->global->p2p,
@@ -2346,11 +2587,6 @@
const u8 *dst, u8 dialog_token,
const struct wpabuf *resp_tlvs)
{
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
- wpa_drv_p2p_sd_response(wpa_s, freq, dst, dialog_token,
- resp_tlvs);
- return;
- }
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return;
p2p_sd_response(wpa_s->global->p2p, freq, dst, dialog_token,
@@ -2360,10 +2596,6 @@
void wpas_p2p_sd_service_update(struct wpa_supplicant *wpa_s)
{
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
- wpa_drv_p2p_service_update(wpa_s);
- return;
- }
if (wpa_s->global->p2p)
p2p_sd_service_update(wpa_s->global->p2p);
}
@@ -2488,11 +2720,11 @@
}
-void wpas_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, const u8 *group_id,
- size_t group_id_len)
+static void wpas_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, const u8 *group_id,
+ size_t group_id_len)
{
struct wpa_supplicant *wpa_s = ctx;
char devtype[WPS_DEV_TYPE_BUFSIZE];
@@ -2545,7 +2777,7 @@
}
-void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
+static void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
{
struct wpa_supplicant *wpa_s = ctx;
unsigned int generated_pin = 0;
@@ -3388,6 +3620,28 @@
}
+static void wpas_presence_resp(void *ctx, const u8 *src, u8 status,
+ const u8 *noa, size_t noa_len)
+{
+ struct wpa_supplicant *wpa_s, *intf = ctx;
+ char hex[100];
+
+ for (wpa_s = intf->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ if (wpa_s->waiting_presence_resp)
+ break;
+ }
+ if (!wpa_s) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No group interface was waiting for presence response");
+ return;
+ }
+ wpa_s->waiting_presence_resp = 0;
+
+ wpa_snprintf_hex(hex, sizeof(hex), noa, noa_len);
+ wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PRESENCE_RESPONSE "src=" MACSTR
+ " status=%u noa=%s", MAC2STR(src), status, hex);
+}
+
+
/**
* wpas_p2p_init - Initialize P2P module for %wpa_supplicant
* @global: Pointer to global data from wpa_supplicant_init()
@@ -3409,25 +3663,6 @@
if (global->p2p)
return 0;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
- struct p2p_params params;
-
- wpa_printf(MSG_DEBUG, "P2P: Use driver-based P2P management");
- os_memset(¶ms, 0, sizeof(params));
- params.dev_name = wpa_s->conf->device_name;
- os_memcpy(params.pri_dev_type, wpa_s->conf->device_type,
- WPS_DEV_TYPE_LEN);
- params.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
- os_memcpy(params.sec_dev_type,
- wpa_s->conf->sec_device_type,
- params.num_sec_dev_types * WPS_DEV_TYPE_LEN);
-
- if (wpa_drv_p2p_set_params(wpa_s, ¶ms) < 0)
- return -1;
-
- return 0;
- }
-
os_memset(&p2p, 0, sizeof(p2p));
p2p.cb_ctx = wpa_s;
p2p.debug_print = wpas_p2p_debug_print;
@@ -3452,6 +3687,7 @@
p2p.invitation_result = wpas_invitation_result;
p2p.get_noa = wpas_get_noa;
p2p.go_connected = wpas_go_connected;
+ p2p.presence_resp = wpas_presence_resp;
os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
@@ -3588,6 +3824,13 @@
eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
wpas_p2p_remove_pending_group_interface(wpa_s);
eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
+ wpas_p2p_listen_work_done(wpa_s);
+ if (wpa_s->p2p_send_action_work) {
+ os_free(wpa_s->p2p_send_action_work->ctx);
+ radio_work_done(wpa_s->p2p_send_action_work);
+ wpa_s->p2p_send_action_work = NULL;
+ }
+ eloop_cancel_timeout(wpas_p2p_send_action_work_timeout, wpa_s, NULL);
/* TODO: remove group interface from the driver if this wpa_s instance
* is on top of a P2P group interface */
@@ -3672,12 +3915,6 @@
if (persistent_group && wpa_s->conf->persistent_reconnect)
persistent_group = 2;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
- return wpa_drv_p2p_connect(wpa_s, peer_addr, wps_method,
- go_intent, own_interface_addr,
- force_freq, persistent_group);
- }
-
/*
* Increase GO config timeout if HT40 is used since it takes some time
* to scan channels for coex purposes before the BSS can be started.
@@ -3703,9 +3940,6 @@
if (persistent_group && wpa_s->conf->persistent_reconnect)
persistent_group = 2;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return -1;
-
return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
go_intent, own_interface_addr, force_freq,
persistent_group, ssid ? ssid->ssid : NULL,
@@ -3789,7 +4023,8 @@
return 0;
}
- updated = os_time_before(&wpa_s->p2p_auto_started, &bss->last_update);
+ updated = os_reltime_before(&wpa_s->p2p_auto_started,
+ &bss->last_update);
wpa_printf(MSG_DEBUG, "P2P: Current BSS entry for peer updated at "
"%ld.%06ld (%supdated in last scan)",
bss->last_update.sec, bss->last_update.usec,
@@ -4044,8 +4279,9 @@
*/
ret = wpa_drv_scan(wpa_s, ¶ms);
if (!ret) {
- os_get_time(&wpa_s->scan_trigger_time);
+ os_get_reltime(&wpa_s->scan_trigger_time);
wpa_s->scan_res_handler = wpas_p2p_scan_res_join;
+ wpa_s->own_scan_requested = 1;
}
wpabuf_free(ies);
@@ -4287,6 +4523,8 @@
os_free(wpa_s->global->add_psk);
wpa_s->global->add_psk = NULL;
+ wpa_s->global->p2p_fail_on_wps_complete = 0;
+
if (go_intent < 0)
go_intent = wpa_s->conf->p2p_go_intent;
@@ -4331,7 +4569,7 @@
dev_addr);
}
if (auto_join) {
- os_get_time(&wpa_s->p2p_auto_started);
+ os_get_reltime(&wpa_s->p2p_auto_started);
wpa_printf(MSG_DEBUG, "P2P: Auto join started at "
"%ld.%06ld",
wpa_s->p2p_auto_started.sec,
@@ -4417,9 +4655,6 @@
if (timeout > wpa_s->max_remain_on_chan)
timeout = wpa_s->max_remain_on_chan;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return wpa_drv_p2p_listen(wpa_s, timeout);
-
return p2p_listen(wpa_s->global->p2p, timeout);
}
@@ -4439,6 +4674,7 @@
wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel callback "
"(p2p_long_listen=%d ms pending_action_tx=%p)",
wpa_s->p2p_long_listen, offchannel_pending_action_tx(wpa_s));
+ wpas_p2p_listen_work_done(wpa_s);
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return;
if (p2p_listen_end(wpa_s->global->p2p, freq) > 0)
@@ -4916,9 +5152,14 @@
if (!wpa_s->ap_iface)
return;
wpa_printf(MSG_DEBUG, "P2P: GO - group %sidle", idle ? "" : "not ");
- if (idle)
+ if (idle) {
+ if (wpa_s->global->p2p_fail_on_wps_complete &&
+ wpa_s->p2p_in_provisioning) {
+ wpas_p2p_grpform_fail_after_wps(wpa_s);
+ return;
+ }
wpas_p2p_set_group_idle_timeout(wpa_s);
- else
+ } else
eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
}
@@ -4929,8 +5170,6 @@
struct p2p_group *group;
struct p2p_group_config *cfg;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return NULL;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return NULL;
@@ -5019,8 +5258,6 @@
}
if (wpa_s->global->p2p)
p2p_wps_success_cb(wpa_s->global->p2p, peer_addr);
- else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- wpa_drv_wps_success_cb(wpa_s, peer_addr);
wpas_group_formation_completed(wpa_s, 1);
}
@@ -5041,6 +5278,31 @@
}
wpas_notify_p2p_wps_failed(wpa_s, fail);
+
+ if (wpa_s == wpa_s->global->p2p_group_formation) {
+ /*
+ * Allow some time for the failed WPS negotiation exchange to
+ * complete, but remove the group since group formation cannot
+ * succeed after provisioning failure.
+ */
+ wpa_printf(MSG_DEBUG, "P2P: WPS step failed during group formation - reject connection from timeout");
+ wpa_s->global->p2p_fail_on_wps_complete = 1;
+ eloop_deplete_timeout(0, 50000,
+ wpas_p2p_group_formation_timeout,
+ wpa_s->parent, NULL);
+ }
+}
+
+
+int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->global->p2p_fail_on_wps_complete ||
+ !wpa_s->p2p_in_provisioning)
+ return 0;
+
+ wpas_p2p_grpform_fail_after_wps(wpa_s);
+
+ return 1;
}
@@ -5073,7 +5335,7 @@
wpa_s->auto_pd_scan_retry = 0;
wpas_p2p_stop_find(wpa_s);
wpa_s->p2p_join_scan_count = 0;
- os_get_time(&wpa_s->p2p_auto_started);
+ os_get_reltime(&wpa_s->p2p_auto_started);
wpa_printf(MSG_DEBUG, "P2P: Auto PD started at %ld.%06ld",
wpa_s->p2p_auto_started.sec,
wpa_s->p2p_auto_started.usec);
@@ -5081,12 +5343,6 @@
return 0;
}
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
- return wpa_drv_p2p_prov_disc_req(wpa_s, peer_addr,
- config_methods,
- use == WPAS_P2P_PD_FOR_JOIN);
- }
-
if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
return -1;
@@ -5122,9 +5378,6 @@
wpas_p2p_clear_pending_action_tx(wpa_s);
wpa_s->p2p_long_listen = 0;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return wpa_drv_p2p_find(wpa_s, timeout, type);
-
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
wpa_s->p2p_in_provisioning)
return -1;
@@ -5143,12 +5396,6 @@
wpa_s->p2p_long_listen = 0;
eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
- wpa_s->global->p2p_cb_on_scan_complete = 0;
-
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
- wpa_drv_p2p_stop_find(wpa_s);
- return 1;
- }
if (wpa_s->global->p2p)
p2p_stop_find(wpa_s->global->p2p);
@@ -5302,9 +5549,6 @@
{
wpa_s->p2p_long_listen = 0;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return wpa_drv_p2p_reject(wpa_s, addr);
-
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
@@ -5360,11 +5604,6 @@
if (res)
return res;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
- ssid->ssid, ssid->ssid_len,
- go_dev_addr, 1);
-
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
@@ -5442,11 +5681,6 @@
}
wpa_s->parent->pending_invite_ssid_id = -1;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
- ssid->ssid, ssid->ssid_len,
- go_dev_addr, persistent);
-
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
@@ -5477,7 +5711,7 @@
}
if (!wpa_s->show_group_started || !ssid)
- goto done;
+ return;
wpa_s->show_group_started = 0;
@@ -5519,17 +5753,14 @@
if (network_id < 0)
network_id = ssid->id;
wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 1);
-
-done:
- wpas_p2p_continue_after_scan(wpa_s);
}
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
u32 interval1, u32 duration2, u32 interval2)
{
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return -1;
+ int ret;
+
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
@@ -5538,18 +5769,19 @@
wpa_s->current_ssid->mode != WPAS_MODE_INFRA)
return -1;
- return p2p_presence_req(wpa_s->global->p2p, wpa_s->bssid,
- wpa_s->own_addr, wpa_s->assoc_freq,
- duration1, interval1, duration2, interval2);
+ ret = p2p_presence_req(wpa_s->global->p2p, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->assoc_freq,
+ duration1, interval1, duration2, interval2);
+ if (ret == 0)
+ wpa_s->waiting_presence_resp = 1;
+
+ return ret;
}
int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
unsigned int interval)
{
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return -1;
-
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
@@ -5651,8 +5883,6 @@
{
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return 0;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return 0;
if (!locally_generated)
p2p_deauth_notif(wpa_s->global->p2p, bssid, reason_code, ie,
@@ -5680,8 +5910,6 @@
{
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return;
if (!locally_generated)
p2p_disassoc_notif(wpa_s->global->p2p, bssid, reason_code, ie,
@@ -5831,8 +6059,6 @@
{
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
- return -1;
wpa_s->global->cross_connection = enabled;
p2p_set_cross_connect(wpa_s->global->p2p, enabled);
@@ -6090,7 +6316,7 @@
int freq_24, int freq_5, int freq_overall)
{
struct p2p_data *p2p = wpa_s->global->p2p;
- if (p2p == NULL || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT))
+ if (p2p == NULL)
return;
p2p_set_best_channels(p2p, freq_24, freq_5, freq_overall);
}
@@ -6101,7 +6327,7 @@
u8 peer[ETH_ALEN];
struct p2p_data *p2p = wpa_s->global->p2p;
- if (p2p == NULL || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT))
+ if (p2p == NULL)
return -1;
if (hwaddr_aton(addr, peer))
@@ -6158,10 +6384,10 @@
}
if (!ret && wpa_s->global->p2p_go_wait_client.sec) {
- struct os_time now;
- os_get_time(&now);
- if (now.sec > wpa_s->global->p2p_go_wait_client.sec +
- P2P_MAX_INITIAL_CONN_WAIT_GO) {
+ struct os_reltime now;
+ os_get_reltime(&now);
+ if (os_reltime_expired(&now, &wpa_s->global->p2p_go_wait_client,
+ P2P_MAX_INITIAL_CONN_WAIT_GO)) {
/* Wait for the first client has expired */
wpa_s->global->p2p_go_wait_client.sec = 0;
} else {
@@ -6324,30 +6550,6 @@
}
-void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s)
-{
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Station mode scan operation not "
- "pending anymore (sta_scan_pending=%d "
- "p2p_cb_on_scan_complete=%d)", wpa_s->sta_scan_pending,
- wpa_s->global->p2p_cb_on_scan_complete);
- wpa_s->sta_scan_pending = 0;
-
- if (!wpa_s->global->p2p_cb_on_scan_complete)
- return;
- wpa_s->global->p2p_cb_on_scan_complete = 0;
-
- if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
- return;
-
- if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
- "continued after successful connection");
- p2p_increase_search_delay(wpa_s->global->p2p,
- wpas_p2p_search_delay(wpa_s));
- }
-}
-
-
static int wpas_p2p_remove_psk_entry(struct wpa_supplicant *wpa_s,
struct wpa_ssid *s, const u8 *addr,
int iface_addr)
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 9630eb5..7abfb12 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -74,22 +74,7 @@
u8 category, const u8 *data, size_t len, int freq);
void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies);
void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s);
-void wpas_dev_found(void *ctx, const u8 *addr,
- const struct p2p_peer_info *info,
- int new_device);
void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s);
-void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res);
-void wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id);
-void wpas_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, const u8 *group_id,
- size_t group_id_len);
-void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods);
-void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token,
- u16 update_indic, const u8 *tlvs, size_t tlvs_len);
-void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
- const u8 *tlvs, size_t tlvs_len);
u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst,
const struct wpabuf *tlvs);
u64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst,
@@ -143,6 +128,7 @@
int wpas_p2p_disconnect(struct wpa_supplicant *wpa_s);
void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
struct wps_event_fail *fail);
+int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s);
int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s);
void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
@@ -164,14 +150,9 @@
int iface_addr);
#ifdef CONFIG_P2P
-void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s);
int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);
void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s);
#else /* CONFIG_P2P */
-static inline void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s)
-{
-}
-
static inline int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
{
return 0;
diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c
index ff2ae74..ed57085 100644
--- a/wpa_supplicant/preauth_test.c
+++ b/wpa_supplicant/preauth_test.c
@@ -27,9 +27,6 @@
#include "drivers/driver.h"
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-
struct wpa_driver_ops *wpa_drivers[] = { NULL };
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index f38dfbb..da827bd 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - Scanning
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -21,7 +21,6 @@
#include "hs20_supplicant.h"
#include "notify.h"
#include "bss.h"
-#include "gas_query.h"
#include "scan.h"
@@ -142,71 +141,37 @@
}
-static int int_array_len(const int *a)
+static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
{
- int i;
- for (i = 0; a && a[i]; i++)
- ;
- return i;
-}
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpa_driver_scan_params *params = work->ctx;
+ int ret;
-
-static void int_array_concat(int **res, const int *a)
-{
- int reslen, alen, i;
- int *n;
-
- reslen = int_array_len(*res);
- alen = int_array_len(a);
-
- n = os_realloc_array(*res, reslen + alen + 1, sizeof(int));
- if (n == NULL) {
- os_free(*res);
- *res = NULL;
+ if (deinit) {
+ wpa_scan_free_params(params);
return;
}
- for (i = 0; i <= alen; i++)
- n[reslen + i] = a[i];
- *res = n;
-}
+ wpa_supplicant_notify_scanning(wpa_s, 1);
-static int freq_cmp(const void *a, const void *b)
-{
- int _a = *(int *) a;
- int _b = *(int *) b;
-
- if (_a == 0)
- return 1;
- if (_b == 0)
- return -1;
- return _a - _b;
-}
-
-
-static void int_array_sort_unique(int *a)
-{
- int alen;
- int i, j;
-
- if (a == NULL)
+ if (wpa_s->clear_driver_scan_cache)
+ params->only_new_results = 1;
+ ret = wpa_drv_scan(wpa_s, params);
+ wpa_scan_free_params(params);
+ work->ctx = NULL;
+ if (ret) {
+ wpa_supplicant_notify_scanning(wpa_s, 0);
+ wpas_notify_scan_done(wpa_s, 0);
+ radio_work_done(work);
return;
-
- alen = int_array_len(a);
- qsort(a, alen, sizeof(int), freq_cmp);
-
- i = 0;
- j = 1;
- while (a[i] && a[j]) {
- if (a[i] == a[j]) {
- j++;
- continue;
- }
- a[++i] = a[j++];
}
- if (a[i])
- i++;
- a[i] = 0;
+
+ os_get_reltime(&wpa_s->scan_trigger_time);
+ wpa_s->scan_runs++;
+ wpa_s->normal_scans++;
+ wpa_s->own_scan_requested = 1;
+ wpa_s->clear_driver_scan_cache = 0;
+ wpa_s->scan_work = work;
}
@@ -219,21 +184,24 @@
int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params)
{
- int ret;
+ struct wpa_driver_scan_params *ctx;
- wpa_supplicant_notify_scanning(wpa_s, 1);
-
- ret = wpa_drv_scan(wpa_s, params);
- if (ret) {
- wpa_supplicant_notify_scanning(wpa_s, 0);
- wpas_notify_scan_done(wpa_s, 0);
- } else {
- os_get_time(&wpa_s->scan_trigger_time);
- wpa_s->scan_runs++;
- wpa_s->normal_scans++;
+ if (wpa_s->scan_work) {
+ wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending");
+ return -1;
}
- return ret;
+ ctx = wpa_scan_clone_params(params);
+ if (ctx == NULL)
+ return -1;
+
+ if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
+ {
+ wpa_scan_free_params(ctx);
+ return -1;
+ }
+
+ return 0;
}
@@ -366,7 +334,8 @@
if (params->freqs)
params->freqs[0] = wpa_s->wps_freq;
wpa_s->after_wps--;
- }
+ } else if (wpa_s->after_wps)
+ wpa_s->after_wps--;
if (params->freqs == NULL && wpa_s->known_wps_freq && wpa_s->wps_freq)
{
@@ -554,14 +523,12 @@
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled");
- wpas_p2p_continue_after_scan(wpa_s);
return;
}
if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan");
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
- wpas_p2p_continue_after_scan(wpa_s);
return;
}
@@ -579,7 +546,6 @@
wpa_s->scan_req == NORMAL_SCAN_REQ) {
wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
- wpas_p2p_continue_after_scan(wpa_s);
return;
}
@@ -597,29 +563,12 @@
}
#ifdef CONFIG_P2P
- if (wpas_p2p_in_progress(wpa_s) || wpas_wpa_is_in_progress(wpa_s, 0)) {
- if (wpa_s->sta_scan_pending &&
- wpas_p2p_in_progress(wpa_s) == 2 &&
- wpa_s->global->p2p_cb_on_scan_complete) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Process pending station "
- "mode scan during P2P search");
- } else {
- wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan "
- "while P2P operation is in progress");
- wpa_s->sta_scan_pending = 1;
- wpa_supplicant_req_scan(wpa_s, 5, 0);
- return;
- }
- }
-#endif /* CONFIG_P2P */
-
-#ifdef CONFIG_GAS
- if (gas_query_in_progress(wpa_s->gas)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Delay scan while GAS query is in progress");
- wpa_supplicant_req_scan(wpa_s, 1, 0);
+ if (wpas_p2p_in_progress(wpa_s)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress");
+ wpa_supplicant_req_scan(wpa_s, 5, 0);
return;
}
-#endif /* CONFIG_GAS */
+#endif /* CONFIG_P2P */
if (wpa_s->conf->ap_scan == 2)
max_ssids = 1;
@@ -766,6 +715,9 @@
wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in "
"the scan request");
params.num_ssids++;
+ } else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
+ wpa_s->manual_scan_passive && params.num_ssids == 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request");
} else {
wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
params.num_ssids++;
@@ -779,6 +731,17 @@
wpa_supplicant_optimize_freqs(wpa_s, ¶ms);
extra_ie = wpa_supplicant_extra_ies(wpa_s);
+ if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
+ wpa_s->manual_scan_only_new)
+ params.only_new_results = 1;
+
+ if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL &&
+ wpa_s->manual_scan_freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels");
+ params.freqs = wpa_s->manual_scan_freqs;
+ wpa_s->manual_scan_freqs = NULL;
+ }
+
if (params.freqs == NULL && wpa_s->next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
"generated frequency list");
@@ -867,6 +830,13 @@
ret = wpa_supplicant_trigger_scan(wpa_s, scan_params);
+ if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs &&
+ !wpa_s->manual_scan_freqs) {
+ /* Restore manual_scan_freqs for the next attempt */
+ wpa_s->manual_scan_freqs = params.freqs;
+ params.freqs = NULL;
+ }
+
wpabuf_free(extra_ie);
os_free(params.freqs);
os_free(params.filter_ssids);
@@ -918,17 +888,19 @@
*/
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
{
- if (eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL))
- {
- wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d sec %d usec",
+ int res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s,
+ NULL);
+ if (res == 1) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Rescheduling scan request: %d.%06d sec",
sec, usec);
- return;
+ } else if (res == 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Ignore new scan request for %d.%06d sec since an earlier request is scheduled to trigger sooner",
+ sec, usec);
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d.%06d sec",
+ sec, usec);
+ eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
}
-
- wpa_dbg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
- sec, usec);
- eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
- eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
}
@@ -1200,7 +1172,6 @@
{
wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request");
eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
- wpas_p2p_continue_after_scan(wpa_s);
}
@@ -1663,12 +1634,12 @@
* Make sure we have a valid timestamp if the driver wrapper
* does not set this.
*/
- os_get_time(&scan_res->fetch_time);
+ os_get_reltime(&scan_res->fetch_time);
}
filter_scan_res(wpa_s, scan_res);
#ifdef CONFIG_WPS
- if (wpas_wps_in_progress(wpa_s)) {
+ if (wpas_wps_searching(wpa_s)) {
wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS "
"provisioning rules");
compar = wpa_scan_result_wps_compar;
@@ -1720,9 +1691,21 @@
struct wpa_scan_results *scan_res)
{
wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received");
- wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
+ if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
+ wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
+ wpa_s->manual_scan_id);
+ wpa_s->manual_scan_use_id = 0;
+ } else {
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
+ }
wpas_notify_scan_results(wpa_s);
wpas_notify_scan_done(wpa_s, 1);
+ if (wpa_s->scan_work) {
+ struct wpa_radio_work *work = wpa_s->scan_work;
+ wpa_s->scan_work = NULL;
+ radio_work_done(work);
+ }
}
@@ -1730,3 +1713,82 @@
{
return eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL);
}
+
+
+struct wpa_driver_scan_params *
+wpa_scan_clone_params(const struct wpa_driver_scan_params *src)
+{
+ struct wpa_driver_scan_params *params;
+ size_t i;
+ u8 *n;
+
+ params = os_zalloc(sizeof(*params));
+ if (params == NULL)
+ return NULL;
+
+ for (i = 0; i < src->num_ssids; i++) {
+ if (src->ssids[i].ssid) {
+ n = os_malloc(src->ssids[i].ssid_len);
+ if (n == NULL)
+ goto failed;
+ os_memcpy(n, src->ssids[i].ssid,
+ src->ssids[i].ssid_len);
+ params->ssids[i].ssid = n;
+ params->ssids[i].ssid_len = src->ssids[i].ssid_len;
+ }
+ }
+ params->num_ssids = src->num_ssids;
+
+ if (src->extra_ies) {
+ n = os_malloc(src->extra_ies_len);
+ if (n == NULL)
+ goto failed;
+ os_memcpy(n, src->extra_ies, src->extra_ies_len);
+ params->extra_ies = n;
+ params->extra_ies_len = src->extra_ies_len;
+ }
+
+ if (src->freqs) {
+ int len = int_array_len(src->freqs);
+ params->freqs = os_malloc((len + 1) * sizeof(int));
+ if (params->freqs == NULL)
+ goto failed;
+ os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int));
+ }
+
+ if (src->filter_ssids) {
+ params->filter_ssids = os_malloc(sizeof(params->filter_ssids) *
+ src->num_filter_ssids);
+ if (params->filter_ssids == NULL)
+ goto failed;
+ os_memcpy(params->filter_ssids, src->filter_ssids,
+ sizeof(params->filter_ssids) * src->num_filter_ssids);
+ params->num_filter_ssids = src->num_filter_ssids;
+ }
+
+ params->filter_rssi = src->filter_rssi;
+ params->p2p_probe = src->p2p_probe;
+ params->only_new_results = src->only_new_results;
+
+ return params;
+
+failed:
+ wpa_scan_free_params(params);
+ return NULL;
+}
+
+
+void wpa_scan_free_params(struct wpa_driver_scan_params *params)
+{
+ size_t i;
+
+ if (params == NULL)
+ return;
+
+ for (i = 0; i < params->num_ssids; i++)
+ os_free((u8 *) params->ssids[i].ssid);
+ os_free((u8 *) params->extra_ies);
+ os_free(params->freqs);
+ os_free(params->filter_ssids);
+ os_free(params);
+}
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index b6fe070..e4c8989 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - Scanning
- * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -43,5 +43,8 @@
struct wpa_driver_scan_params *params,
int interval);
int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s);
+struct wpa_driver_scan_params *
+wpa_scan_clone_params(const struct wpa_driver_scan_params *src);
+void wpa_scan_free_params(struct wpa_driver_scan_params *params);
#endif /* SCAN_H */
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 87c14ae..43f40cd 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1,6 +1,6 @@
/*
* wpa_supplicant - SME
- * Copyright (c) 2009-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -157,6 +157,7 @@
if (bss == NULL) {
wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
"the network");
+ wpas_connect_work_done(wpa_s);
return;
}
@@ -244,6 +245,7 @@
&wpa_s->sme.assoc_req_ie_len)) {
wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
"key management and encryption suites");
+ wpas_connect_work_done(wpa_s);
return;
}
} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
@@ -263,6 +265,7 @@
wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
"key management and encryption suites (no "
"scan results)");
+ wpas_connect_work_done(wpa_s);
return;
}
#ifdef CONFIG_WPS
@@ -386,8 +389,10 @@
bss->bssid);
else
resp = sme_auth_build_sae_confirm(wpa_s);
- if (resp == NULL)
+ if (resp == NULL) {
+ wpas_connect_work_done(wpa_s);
return;
+ }
params.sae_data = wpabuf_head(resp);
params.sae_data_len = wpabuf_len(resp);
wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
@@ -417,6 +422,7 @@
wpas_connection_failed(wpa_s, bss->bssid);
wpa_supplicant_mark_disassoc(wpa_s);
wpabuf_free(resp);
+ wpas_connect_work_done(wpa_s);
return;
}
@@ -432,15 +438,56 @@
}
+static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_connect_work *cwork = work->ctx;
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+
+ if (deinit) {
+ wpas_connect_work_free(cwork);
+ return;
+ }
+
+ wpa_s->connect_work = work;
+
+ if (!wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
+ sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
+}
+
+
void sme_authenticate(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, struct wpa_ssid *ssid)
{
+ struct wpa_connect_work *cwork;
+
+ if (bss == NULL || ssid == NULL)
+ return;
+ if (wpa_s->connect_work) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
+ return;
+ }
+
+ cwork = os_zalloc(sizeof(*cwork));
+ if (cwork == NULL)
+ return;
+ cwork->bss = bss;
+ cwork->ssid = ssid;
+ cwork->sme = 1;
+
#ifdef CONFIG_SAE
wpa_s->sme.sae.state = SAE_NOTHING;
wpa_s->sme.sae.send_confirm = 0;
wpa_s->sme.sae_group_index = 0;
#endif /* CONFIG_SAE */
- sme_send_authentication(wpa_s, bss, ssid, 1);
+
+ if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
+ sme_auth_start_cb, cwork) < 0)
+ wpas_connect_work_free(cwork);
}
@@ -651,9 +698,8 @@
params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
wpa_s->sme.assoc_req_ie : NULL;
params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
- params.pairwise_suite =
- wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher);
- params.group_suite = wpa_cipher_to_suite_driver(wpa_s->group_cipher);
+ params.pairwise_suite = wpa_s->pairwise_cipher;
+ params.group_suite = wpa_s->group_cipher;
#ifdef CONFIG_HT_OVERRIDES
os_memset(&htcaps, 0, sizeof(htcaps));
os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
@@ -1151,9 +1197,9 @@
static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
{
u32 tu;
- struct os_time now, passed;
- os_get_time(&now);
- os_time_sub(&now, &wpa_s->sme.sa_query_start, &passed);
+ struct os_reltime now, passed;
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
tu = (passed.sec * 1000000 + passed.usec) / 1024;
if (sa_query_max_timeout < tu) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
@@ -1203,7 +1249,7 @@
return;
if (wpa_s->sme.sa_query_count == 0) {
/* Starting a new SA Query procedure */
- os_get_time(&wpa_s->sme.sa_query_start);
+ os_get_reltime(&wpa_s->sme.sa_query_start);
}
trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
wpa_s->sme.sa_query_trans_id = nbuf;
diff --git a/wpa_supplicant/tests/test_wpa.c b/wpa_supplicant/tests/test_wpa.c
index 484a406..39971f2 100644
--- a/wpa_supplicant/tests/test_wpa.c
+++ b/wpa_supplicant/tests/test_wpa.c
@@ -17,10 +17,6 @@
#include "ap/wpa_auth.h"
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-
-
struct wpa {
u8 auth_addr[ETH_ALEN];
u8 supp_addr[ETH_ALEN];
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 4f8d895..65b2783 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -181,7 +181,7 @@
/* Install GTK/IGTK */
/* point to key data field */
- ptr = (u8 *) frm + 1 + 1 + 2;
+ ptr = (u8 *) frm + 1 + 2;
end = ptr + key_len_total;
wpa_hexdump_key(MSG_DEBUG, "WNM: Key Data", ptr, key_len_total);
@@ -237,16 +237,16 @@
* Action [1] | Diaglog Token [1] | Key Data Len [2] | Key Data |
* WNM-Sleep Mode IE | TFS Response IE
*/
- u8 *pos = (u8 *) frm; /* point to action field */
+ u8 *pos = (u8 *) frm; /* point to payload after the action field */
u16 key_len_total = le_to_host16(*((u16 *)(frm+2)));
struct wnm_sleep_element *wnmsleep_ie = NULL;
/* multiple TFS Resp IE (assuming consecutive) */
u8 *tfsresp_ie_start = NULL;
u8 *tfsresp_ie_end = NULL;
- wpa_printf(MSG_DEBUG, "action=%d token = %d key_len_total = %d",
- frm[0], frm[1], key_len_total);
- pos += 4 + key_len_total;
+ wpa_printf(MSG_DEBUG, "WNM-Sleep Mode Response token=%u key_len_total=%d",
+ frm[0], key_len_total);
+ pos += 3 + key_len_total;
if (pos > frm + len) {
wpa_printf(MSG_INFO, "WNM: Too short frame for Key Data field");
return;
@@ -473,6 +473,10 @@
if (scan_res == NULL || num_neigh_rep == 0)
return 0;
+ wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d",
+ MAC2STR(wpa_s->bssid),
+ wpa_s->current_bss ? wpa_s->current_bss->level : 0);
+
for (i = 0; i < num_neigh_rep; i++) {
for (j = 0; j < scan_res->num; j++) {
/* Check for a better RSSI AP */
@@ -483,8 +487,16 @@
/* Got a BSSID with better RSSI value */
os_memcpy(bssid_to_connect, neigh_rep[i].bssid,
ETH_ALEN);
+ wpa_printf(MSG_DEBUG, "Found a BSS " MACSTR
+ " with better scan RSSI %d",
+ MAC2STR(scan_res->res[j]->bssid),
+ scan_res->res[j]->level);
return 1;
}
+ wpa_printf(MSG_DEBUG, "scan_res[%d] " MACSTR
+ " RSSI %d", j,
+ MAC2STR(scan_res->res[j]->bssid),
+ scan_res->res[j]->level);
}
}
@@ -521,6 +533,14 @@
if (target_bssid) {
os_memcpy(pos, target_bssid, ETH_ALEN);
pos += ETH_ALEN;
+ } else if (status == WNM_BSS_TM_ACCEPT) {
+ /*
+ * P802.11-REVmc clarifies that the Target BSSID field is always
+ * present when status code is zero, so use a fake value here if
+ * no BSSID is yet known.
+ */
+ os_memset(pos, 0, ETH_ALEN);
+ pos += ETH_ALEN;
}
len = pos - (u8 *) &mgmt->u.action.category;
@@ -562,7 +582,7 @@
wnm_send_bss_transition_mgmt_resp(wpa_s,
wpa_s->wnm_dialog_token,
WNM_BSS_TM_ACCEPT,
- 0, NULL);
+ 0, bssid);
}
wpa_s->reassociate = 1;
@@ -717,7 +737,7 @@
WLAN_FC_STYPE_ACTION);
mgmt->u.action.category = WLAN_ACTION_WNM;
mgmt->u.action.u.bss_tm_query.action = WNM_BSS_TRANS_MGMT_QUERY;
- mgmt->u.action.u.bss_tm_query.dialog_token = 0;
+ mgmt->u.action.u.bss_tm_query.dialog_token = 1;
mgmt->u.action.u.bss_tm_query.query_reason = query_reason;
pos = mgmt->u.action.u.bss_tm_query.variable;
@@ -732,22 +752,23 @@
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
- struct rx_action *action)
+ const struct ieee80211_mgmt *mgmt, size_t len)
{
const u8 *pos, *end;
u8 act;
- if (action->data == NULL || action->len == 0)
+ if (len < IEEE80211_HDRLEN + 2)
return;
- pos = action->data;
- end = pos + action->len;
+ pos = &mgmt->u.action.category;
+ pos++;
act = *pos++;
+ end = ((const u8 *) mgmt) + len;
wpa_printf(MSG_DEBUG, "WNM: RX action %u from " MACSTR,
- act, MAC2STR(action->sa));
+ act, MAC2STR(mgmt->sa));
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
- os_memcmp(action->sa, wpa_s->bssid, ETH_ALEN) != 0) {
+ os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) {
wpa_printf(MSG_DEBUG, "WNM: Ignore unexpected WNM Action "
"frame");
return;
@@ -756,10 +777,10 @@
switch (act) {
case WNM_BSS_TRANS_MGMT_REQ:
ieee802_11_rx_bss_trans_mgmt_req(wpa_s, pos, end,
- !(action->da[0] & 0x01));
+ !(mgmt->da[0] & 0x01));
break;
case WNM_SLEEP_MODE_RESP:
- ieee802_11_rx_wnmsleep_resp(wpa_s, action->data, action->len);
+ ieee802_11_rx_wnmsleep_resp(wpa_s, pos, end - pos);
break;
default:
wpa_printf(MSG_ERROR, "WNM: Unknown request");
diff --git a/wpa_supplicant/wnm_sta.h b/wpa_supplicant/wnm_sta.h
index 2933926..de87301 100644
--- a/wpa_supplicant/wnm_sta.h
+++ b/wpa_supplicant/wnm_sta.h
@@ -9,9 +9,6 @@
#ifndef WNM_STA_H
#define WNM_STA_H
-struct rx_action;
-struct wpa_supplicant;
-
struct tsf_info {
u8 present;
u8 tsf_offset[2];
@@ -78,7 +75,7 @@
u8 action, u16 intval, struct wpabuf *tfs_req);
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
- struct rx_action *action);
+ const struct ieee80211_mgmt *mgmt, size_t len);
void wnm_scan_response(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index aabaa3c..358c2fe 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -28,7 +28,7 @@
static const char *wpa_cli_version =
"wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi> and contributors";
static const char *wpa_cli_license =
@@ -2426,6 +2426,12 @@
}
+static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
+}
+
+
enum wpa_cli_cmd_flags {
cli_cmd_flag_none = 0x00,
cli_cmd_flag_sensitive = 0x01
@@ -2893,6 +2899,8 @@
{ "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
"<command> = driver private commands" },
#endif /* ANDROID */
+ { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
+ "= radio_work <show/add/done>" },
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};
diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
index 4afaae9..5426177 100644
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -552,8 +552,6 @@
}
-extern struct wpa_driver_ops *wpa_drivers[];
-
static struct wpa_priv_interface *
wpa_priv_interface_init(const char *dir, const char *params)
{
@@ -946,8 +944,6 @@
}
-extern int wpa_debug_level;
-
int main(int argc, char *argv[])
{
int c, i;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 2d6272b..187e5d9 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -54,7 +54,7 @@
const char *wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> and contributors";
const char *wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
@@ -104,11 +104,6 @@
"\n";
#endif /* CONFIG_NO_STDOUT_DEBUG */
-extern int wpa_debug_level;
-extern int wpa_debug_show_keys;
-extern int wpa_debug_timestamp;
-extern struct wpa_driver_ops *wpa_drivers[];
-
/* Configure default/group WEP keys for static WEP */
int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
{
@@ -200,8 +195,6 @@
* So, wait a second until scanning again.
*/
wpa_supplicant_req_scan(wpa_s, 1, 0);
-
- wpas_p2p_continue_after_scan(wpa_s);
}
@@ -459,6 +452,9 @@
os_free(wpa_s->next_scan_freqs);
wpa_s->next_scan_freqs = NULL;
+ os_free(wpa_s->manual_scan_freqs);
+ wpa_s->manual_scan_freqs = NULL;
+
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
@@ -481,6 +477,9 @@
wpa_s->ext_pw = NULL;
wpabuf_free(wpa_s->last_gas_resp);
+ wpa_s->last_gas_resp = NULL;
+ wpabuf_free(wpa_s->prev_gas_resp);
+ wpa_s->prev_gas_resp = NULL;
os_free(wpa_s->last_scan_res);
wpa_s->last_scan_res = NULL;
@@ -497,29 +496,23 @@
*/
void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
{
- if (wpa_s->keys_cleared) {
- /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have
- * timing issues with keys being cleared just before new keys
- * are set or just after association or something similar. This
- * shows up in group key handshake failing often because of the
- * client not receiving the first encrypted packets correctly.
- * Skipping some of the extra key clearing steps seems to help
- * in completing group key handshake more reliably. */
- wpa_dbg(wpa_s, MSG_DEBUG, "No keys have been configured - "
- "skip key clearing");
- return;
- }
+ int i, max;
+
+#ifdef CONFIG_IEEE80211W
+ max = 6;
+#else /* CONFIG_IEEE80211W */
+ max = 4;
+#endif /* CONFIG_IEEE80211W */
/* MLME-DELETEKEYS.request */
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
-#ifdef CONFIG_IEEE80211W
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
- wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
-#endif /* CONFIG_IEEE80211W */
- if (addr) {
+ for (i = 0; i < max; i++) {
+ if (wpa_s->keys_cleared & BIT(i))
+ continue;
+ wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
+ NULL, 0);
+ }
+ if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
+ !is_zero_ether_addr(addr)) {
wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
0);
/* MLME-SETPROTECTION.request(None) */
@@ -528,7 +521,7 @@
MLME_SETPROTECTION_PROTECT_TYPE_NONE,
MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
}
- wpa_s->keys_cleared = 1;
+ wpa_s->keys_cleared = (u32) -1;
}
@@ -659,6 +652,9 @@
wpa_supplicant_state_txt(wpa_s->wpa_state),
wpa_supplicant_state_txt(state));
+ if (state == WPA_COMPLETED)
+ wpas_connect_work_done(wpa_s);
+
if (state != WPA_SCANNING)
wpa_supplicant_notify_scanning(wpa_s, 0);
@@ -699,7 +695,7 @@
#ifdef CONFIG_BGSCAN
if (state == WPA_COMPLETED)
wpa_supplicant_start_bgscan(wpa_s);
- else
+ else if (state < WPA_ASSOCIATED)
wpa_supplicant_stop_bgscan(wpa_s);
#endif /* CONFIG_BGSCAN */
@@ -725,6 +721,7 @@
#ifdef CONFIG_WPS
struct wpa_supplicant *wpa_s = global->ifaces;
while (wpa_s) {
+ struct wpa_supplicant *next = wpa_s->next;
#ifdef CONFIG_P2P
if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
(wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
@@ -732,7 +729,7 @@
#endif /* CONFIG_P2P */
if (wpas_wps_terminate_pending(wpa_s) == 1)
pending = 1;
- wpa_s = wpa_s->next;
+ wpa_s = next;
}
#endif /* CONFIG_WPS */
if (pending)
@@ -861,34 +858,6 @@
}
-enum wpa_key_mgmt key_mgmt2driver(int key_mgmt)
-{
- switch (key_mgmt) {
- case WPA_KEY_MGMT_NONE:
- return KEY_MGMT_NONE;
- case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
- return KEY_MGMT_802_1X_NO_WPA;
- case WPA_KEY_MGMT_IEEE8021X:
- return KEY_MGMT_802_1X;
- case WPA_KEY_MGMT_WPA_NONE:
- return KEY_MGMT_WPA_NONE;
- case WPA_KEY_MGMT_FT_IEEE8021X:
- return KEY_MGMT_FT_802_1X;
- case WPA_KEY_MGMT_FT_PSK:
- return KEY_MGMT_FT_PSK;
- case WPA_KEY_MGMT_IEEE8021X_SHA256:
- return KEY_MGMT_802_1X_SHA256;
- case WPA_KEY_MGMT_PSK_SHA256:
- return KEY_MGMT_PSK_SHA256;
- case WPA_KEY_MGMT_WPS:
- return KEY_MGMT_WPS;
- case WPA_KEY_MGMT_PSK:
- default:
- return KEY_MGMT_PSK;
- }
-}
-
-
static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct wpa_ie_data *ie)
@@ -1229,7 +1198,8 @@
break;
case 4: /* Bits 32-39 */
#ifdef CONFIG_INTERWORKING
- *pos |= 0x01; /* Bit 32 - QoS Map */
+ if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
+ *pos |= 0x01; /* Bit 32 - QoS Map */
#endif /* CONFIG_INTERWORKING */
break;
case 5: /* Bits 40-47 */
@@ -1270,6 +1240,70 @@
}
+static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *test_bss)
+{
+ struct wpa_bss *bss;
+
+ dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ if (bss == test_bss)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *test_ssid)
+{
+ struct wpa_ssid *ssid;
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (ssid == test_ssid)
+ return 1;
+ }
+
+ return 0;
+}
+
+
+int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
+ struct wpa_ssid *test_ssid)
+{
+ if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
+ return 0;
+
+ return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
+}
+
+
+void wpas_connect_work_free(struct wpa_connect_work *cwork)
+{
+ if (cwork == NULL)
+ return;
+ os_free(cwork);
+}
+
+
+void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_connect_work *cwork;
+ struct wpa_radio_work *work = wpa_s->connect_work;
+
+ if (!work)
+ return;
+
+ wpa_s->connect_work = NULL;
+ cwork = work->ctx;
+ work->ctx = NULL;
+ wpas_connect_work_free(cwork);
+ radio_work_done(work);
+}
+
+
+static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
+
/**
* wpa_supplicant_associate - Request association
* @wpa_s: Pointer to wpa_supplicant data
@@ -1281,19 +1315,7 @@
void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, struct wpa_ssid *ssid)
{
- u8 wpa_ie[200];
- size_t wpa_ie_len;
- int use_crypt, ret, i, bssid_changed;
- int algs = WPA_AUTH_ALG_OPEN;
- enum wpa_cipher cipher_pairwise, cipher_group;
- struct wpa_driver_associate_params params;
- int wep_keys_set = 0;
- int assoc_failed = 0;
- struct wpa_ssid *old_ssid;
-#ifdef CONFIG_HT_OVERRIDES
- struct ieee80211_ht_capabilities htcaps;
- struct ieee80211_ht_capabilities htcaps_mask;
-#endif /* CONFIG_HT_OVERRIDES */
+ struct wpa_connect_work *cwork;
#ifdef CONFIG_IBSS_RSN
ibss_rsn_deinit(wpa_s->ibss_rsn);
@@ -1334,6 +1356,58 @@
return;
}
+ if (wpa_s->connect_work) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
+ return;
+ }
+
+ cwork = os_zalloc(sizeof(*cwork));
+ if (cwork == NULL)
+ return;
+
+ cwork->bss = bss;
+ cwork->ssid = ssid;
+
+ if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
+ wpas_start_assoc_cb, cwork) < 0) {
+ os_free(cwork);
+ }
+}
+
+
+static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_connect_work *cwork = work->ctx;
+ struct wpa_bss *bss = cwork->bss;
+ struct wpa_ssid *ssid = cwork->ssid;
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ u8 wpa_ie[200];
+ size_t wpa_ie_len;
+ int use_crypt, ret, i, bssid_changed;
+ int algs = WPA_AUTH_ALG_OPEN;
+ unsigned int cipher_pairwise, cipher_group;
+ struct wpa_driver_associate_params params;
+ int wep_keys_set = 0;
+ int assoc_failed = 0;
+ struct wpa_ssid *old_ssid;
+#ifdef CONFIG_HT_OVERRIDES
+ struct ieee80211_ht_capabilities htcaps;
+ struct ieee80211_ht_capabilities htcaps_mask;
+#endif /* CONFIG_HT_OVERRIDES */
+
+ if (deinit) {
+ wpas_connect_work_free(cwork);
+ return;
+ }
+
+ wpa_s->connect_work = work;
+
+ if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
os_memset(¶ms, 0, sizeof(params));
wpa_s->reassociate = 0;
if (bss && !wpas_driver_bss_selection(wpa_s)) {
@@ -1526,8 +1600,8 @@
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
- cipher_pairwise = wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher);
- cipher_group = wpa_cipher_to_suite_driver(wpa_s->group_cipher);
+ cipher_pairwise = wpa_s->pairwise_cipher;
+ cipher_group = wpa_s->group_cipher;
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
@@ -1551,7 +1625,7 @@
/* Assume that dynamic WEP-104 keys will be used and
* set cipher suites in order for drivers to expect
* encryption. */
- cipher_pairwise = cipher_group = CIPHER_WEP104;
+ cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
}
}
#endif /* IEEE8021X_EAPOL */
@@ -1592,7 +1666,7 @@
params.wpa_ie_len = wpa_ie_len;
params.pairwise_suite = cipher_pairwise;
params.group_suite = cipher_group;
- params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
+ params.key_mgmt_suite = wpa_s->key_mgmt;
params.wpa_proto = wpa_s->wpa_proto;
params.auth_alg = algs;
params.mode = ssid->mode;
@@ -1605,8 +1679,8 @@
params.wep_tx_keyidx = ssid->wep_tx_keyidx;
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
- (params.key_mgmt_suite == KEY_MGMT_PSK ||
- params.key_mgmt_suite == KEY_MGMT_FT_PSK)) {
+ (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
+ params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
params.passphrase = ssid->passphrase;
if (ssid->psk_set)
params.psk = ssid->psk;
@@ -2323,6 +2397,16 @@
wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
+#ifdef CONFIG_PEERKEY
+ if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
+ wpa_s->current_ssid->peerkey &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
+ wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
+ return;
+ }
+#endif /* CONFIG_PEERKEY */
+
if (wpa_s->wpa_state < WPA_ASSOCIATED ||
(wpa_s->last_eapol_matches_bssid &&
#ifdef CONFIG_AP
@@ -2348,7 +2432,7 @@
wpabuf_free(wpa_s->pending_eapol_rx);
wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
if (wpa_s->pending_eapol_rx) {
- os_get_time(&wpa_s->pending_eapol_rx_time);
+ os_get_reltime(&wpa_s->pending_eapol_rx_time);
os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
ETH_ALEN);
}
@@ -2918,12 +3002,89 @@
if (rn)
os_strlcpy(radio->name, rn, sizeof(radio->name));
dl_list_init(&radio->ifaces);
+ dl_list_init(&radio->work);
dl_list_add(&radio->ifaces, &wpa_s->radio_list);
return radio;
}
+static void radio_work_free(struct wpa_radio_work *work)
+{
+ if (work->wpa_s->scan_work == work) {
+ /* This should not really happen. */
+ wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
+ work->type, work, work->started);
+ work->wpa_s->scan_work = NULL;
+ }
+
+#ifdef CONFIG_P2P
+ if (work->wpa_s->p2p_scan_work == work) {
+ /* This should not really happen. */
+ wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
+ work->type, work, work->started);
+ work->wpa_s->p2p_scan_work = NULL;
+ }
+#endif /* CONFIG_P2P */
+
+ dl_list_del(&work->list);
+ os_free(work);
+}
+
+
+static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_radio *radio = eloop_ctx;
+ struct wpa_radio_work *work;
+ struct os_reltime now, diff;
+ struct wpa_supplicant *wpa_s;
+
+ work = dl_list_first(&radio->work, struct wpa_radio_work, list);
+ if (work == NULL)
+ return;
+
+ if (work->started)
+ return; /* already started and still in progress */
+
+ wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
+ radio_list);
+ if (wpa_s && wpa_s->external_scan_running) {
+ wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
+ return;
+ }
+
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &work->time, &diff);
+ wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
+ work->type, work, diff.sec, diff.usec);
+ work->started = 1;
+ work->time = now;
+ work->cb(work, 0);
+}
+
+
+void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s, const char *type)
+{
+ struct wpa_radio_work *work, *tmp;
+ struct wpa_radio *radio = wpa_s->radio;
+
+ dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
+ list) {
+ if (type && (work->started || os_strcmp(type, work->type) != 0))
+ continue;
+ if (work->started) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Leaving started radio work '%s'@%p in the list",
+ work->type, work);
+ continue;
+ }
+ wpa_dbg(wpa_s, MSG_DEBUG, "Remove unstarted radio work '%s'@%p",
+ work->type, work);
+ work->cb(work, 1);
+ radio_work_free(work);
+ }
+}
+
+
static void radio_remove_interface(struct wpa_supplicant *wpa_s)
{
struct wpa_radio *radio = wpa_s->radio;
@@ -2934,16 +3095,112 @@
wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
wpa_s->ifname, radio->name);
dl_list_del(&wpa_s->radio_list);
- wpa_s->radio = NULL;
-
- if (!dl_list_empty(&radio->ifaces))
+ if (!dl_list_empty(&radio->ifaces)) {
+ wpa_s->radio = NULL;
return; /* Interfaces remain for this radio */
+ }
wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
+ radio_remove_unstarted_work(wpa_s, NULL);
+ eloop_cancel_timeout(radio_start_next_work, radio, NULL);
+ wpa_s->radio = NULL;
os_free(radio);
}
+void radio_work_check_next(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_radio *radio = wpa_s->radio;
+
+ if (dl_list_empty(&radio->work))
+ return;
+ eloop_cancel_timeout(radio_start_next_work, radio, NULL);
+ eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
+}
+
+
+/**
+ * radio_add_work - Add a radio work item
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @freq: Frequency of the offchannel operation in MHz or 0
+ * @type: Unique identifier for each type of work
+ * @next: Force as the next work to be executed
+ * @cb: Callback function for indicating when radio is available
+ * @ctx: Context pointer for the work (work->ctx in cb())
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to request time for an operation that requires
+ * exclusive radio control. Once the radio is available, the registered callback
+ * function will be called. radio_work_done() must be called once the exclusive
+ * radio operation has been completed, so that the radio is freed for other
+ * operations. The special case of deinit=1 is used to free the context data
+ * during interface removal. That does not allow the callback function to start
+ * the radio operation, i.e., it must free any resources allocated for the radio
+ * work and return.
+ *
+ * The @freq parameter can be used to indicate a single channel on which the
+ * offchannel operation will occur. This may allow multiple radio work
+ * operations to be performed in parallel if they apply for the same channel.
+ * Setting this to 0 indicates that the work item may use multiple channels or
+ * requires exclusive control of the radio.
+ */
+int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
+ const char *type, int next,
+ void (*cb)(struct wpa_radio_work *work, int deinit),
+ void *ctx)
+{
+ struct wpa_radio_work *work;
+ int was_empty;
+
+ work = os_zalloc(sizeof(*work));
+ if (work == NULL)
+ return -1;
+ wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
+ os_get_reltime(&work->time);
+ work->freq = freq;
+ work->type = type;
+ work->wpa_s = wpa_s;
+ work->cb = cb;
+ work->ctx = ctx;
+
+ was_empty = dl_list_empty(&wpa_s->radio->work);
+ if (next)
+ dl_list_add(&wpa_s->radio->work, &work->list);
+ else
+ dl_list_add_tail(&wpa_s->radio->work, &work->list);
+ if (was_empty) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
+ radio_work_check_next(wpa_s);
+ }
+
+ return 0;
+}
+
+
+/**
+ * radio_work_done - Indicate that a radio work item has been completed
+ * @work: Completed work
+ *
+ * This function is called once the callback function registered with
+ * radio_add_work() has completed its work.
+ */
+void radio_work_done(struct wpa_radio_work *work)
+{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct os_reltime now, diff;
+ unsigned int started = work->started;
+
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &work->time, &diff);
+ wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
+ work->type, work, started ? "done" : "canceled",
+ diff.sec, diff.usec);
+ radio_work_free(work);
+ if (started)
+ radio_work_check_next(wpa_s);
+}
+
+
static int wpas_init_driver(struct wpa_supplicant *wpa_s,
struct wpa_interface *iface)
{
@@ -3263,6 +3520,7 @@
}
#endif /* CONFIG_P2P */
+ wpas_ctrl_radio_work_flush(wpa_s);
radio_remove_interface(wpa_s);
if (wpa_s->drv_priv)
@@ -3751,6 +4009,8 @@
int count;
int *freqs = NULL;
+ wpas_connect_work_done(wpa_s);
+
/*
* Remove possible authentication timeout since the connection failed.
*/
@@ -3837,8 +4097,6 @@
*/
wpa_supplicant_req_scan(wpa_s, timeout / 1000,
1000 * (timeout % 1000));
-
- wpas_p2p_continue_after_scan(wpa_s);
}
@@ -3978,7 +4236,7 @@
{
struct wpa_ssid *ssid = wpa_s->current_ssid;
int dur;
- struct os_time now;
+ struct os_reltime now;
if (ssid == NULL) {
wpa_printf(MSG_DEBUG, "Authentication failure but no known "
@@ -4015,7 +4273,7 @@
else
dur = 10;
- os_get_time(&now);
+ os_get_reltime(&now);
if (now.sec + dur <= ssid->disabled_until.sec)
return;
@@ -4103,42 +4361,6 @@
}
-static int wpas_conn_in_progress(struct wpa_supplicant *wpa_s)
-{
- return wpa_s->wpa_state >= WPA_AUTHENTICATING &&
- wpa_s->wpa_state != WPA_COMPLETED;
-}
-
-
-/**
- * wpas_wpa_is_in_progress - Check whether a connection is in progress
- * @wpa_s: Pointer to wpa_supplicant data
- * @include_current: Whether to consider specified interface
- *
- * This function is to check if the wpa state is in beginning of the connection
- * during 4-way handshake or group key handshake with WPA on any shared
- * interface.
- */
-int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s, int include_current)
-{
- struct wpa_supplicant *ifs;
-
- dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
- radio_list) {
- if (!include_current && ifs == wpa_s)
- continue;
-
- if (wpas_conn_in_progress(ifs)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "Connection is in progress "
- "on interface %s - defer", ifs->ifname);
- return 1;
- }
- }
-
- return 0;
-}
-
-
void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
int *freq_array, unsigned int len)
{
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 0ecfaa6..9d3bf6d 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -342,6 +342,8 @@
#
# credential fields:
#
+# temporary: Whether this credential is temporary and not to be saved
+#
# priority: Priority group
# By default, all networks and credentials get the same priority group
# (0). This field can be used to give higher priority for credentials
@@ -506,9 +508,10 @@
# 0 = infrastructure (Managed) mode, i.e., associate with an AP (default)
# 1 = IBSS (ad-hoc, peer-to-peer)
# 2 = AP (access point)
-# Note: IBSS can only be used with key_mgmt NONE (plaintext and static WEP)
-# and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). WPA-None requires
-# following network block options:
+# Note: IBSS can only be used with key_mgmt NONE (plaintext and static WEP) and
+# WPA-PSK (with proto=RSN). In addition, key_mgmt=WPA-NONE (fixed group key
+# TKIP/CCMP) is available for backwards compatibility, but its use is
+# deprecated. WPA-None requires following network block options:
# proto=WPA, key_mgmt=WPA-NONE, pairwise=NONE, group=TKIP (or CCMP, but not
# both), and psk must also be set.
#
@@ -1163,7 +1166,19 @@
}
-# IBSS/ad-hoc network with WPA-None/TKIP.
+# IBSS/ad-hoc network with RSN
+network={
+ ssid="ibss-rsn"
+ key_mgmt=WPA-PSK
+ proto=RSN
+ psk="12345678"
+ mode=1
+ frequency=2412
+ pairwise=CCMP
+ group=CCMP
+}
+
+# IBSS/ad-hoc network with WPA-None/TKIP (deprecated)
network={
ssid="test adhoc"
mode=1
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 8cc813c..d1ea77b 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1,6 +1,6 @@
/*
* wpa_supplicant - Internal definitions
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -246,7 +246,7 @@
struct wpa_supplicant *p2p_group_formation;
struct wpa_supplicant *p2p_invite_group;
u8 p2p_dev_addr[ETH_ALEN];
- struct os_time p2p_go_wait_client;
+ struct os_reltime p2p_go_wait_client;
struct dl_list p2p_srv_bonjour; /* struct p2p_srv_bonjour */
struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
int p2p_disabled;
@@ -257,8 +257,8 @@
WPA_CONC_PREF_STA,
WPA_CONC_PREF_P2P
} conc_pref;
- unsigned int p2p_cb_on_scan_complete:1;
unsigned int p2p_per_sta_psk:1;
+ unsigned int p2p_fail_on_wps_complete:1;
#ifdef CONFIG_WIFI_DISPLAY
int wifi_display;
@@ -281,6 +281,47 @@
char name[16]; /* from driver_ops get_radio_name() or empty if not
* available */
struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
+ struct dl_list work; /* struct wpa_radio_work::list entries */
+};
+
+/**
+ * struct wpa_radio_work - Radio work item
+ */
+struct wpa_radio_work {
+ struct dl_list list;
+ unsigned int freq; /* known frequency (MHz) or 0 for multiple/unknown */
+ const char *type;
+ struct wpa_supplicant *wpa_s;
+ void (*cb)(struct wpa_radio_work *work, int deinit);
+ void *ctx;
+ unsigned int started:1;
+ struct os_reltime time;
+};
+
+int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
+ const char *type, int next,
+ void (*cb)(struct wpa_radio_work *work, int deinit),
+ void *ctx);
+void radio_work_done(struct wpa_radio_work *work);
+void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s,
+ const char *type);
+void radio_work_check_next(struct wpa_supplicant *wpa_s);
+
+struct wpa_connect_work {
+ unsigned int sme:1;
+ struct wpa_bss *bss;
+ struct wpa_ssid *ssid;
+};
+
+int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
+ struct wpa_ssid *test_ssid);
+void wpas_connect_work_free(struct wpa_connect_work *cwork);
+void wpas_connect_work_done(struct wpa_supplicant *wpa_s);
+
+struct wpa_external_work {
+ unsigned int id;
+ char type[100];
+ unsigned int timeout;
};
/**
@@ -302,7 +343,7 @@
WPS_AP_SEL_REG_OUR
} type;
unsigned int tries;
- struct os_time last_attempt;
+ struct os_reltime last_attempt;
};
struct wpa_ssid_value {
@@ -344,7 +385,7 @@
char *confanother;
struct wpa_config *conf;
int countermeasures;
- os_time_t last_michael_mic_error;
+ struct os_reltime last_michael_mic_error;
u8 bssid[ETH_ALEN];
u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this
* field contains the target BSSID. */
@@ -408,8 +449,7 @@
struct wpa_bss **last_scan_res;
unsigned int last_scan_res_used;
unsigned int last_scan_res_size;
- int last_scan_full;
- struct os_time last_scan;
+ struct os_reltime last_scan;
struct wpa_driver_ops *driver;
int interface_removed; /* whether the network interface has been
@@ -420,6 +460,7 @@
struct ctrl_iface_priv *ctrl_iface;
enum wpa_states wpa_state;
+ struct wpa_radio_work *scan_work;
int scanning;
int sched_scanning;
int new_connection;
@@ -433,7 +474,8 @@
unsigned char last_eapol_src[ETH_ALEN];
- int keys_cleared;
+ unsigned int keys_cleared; /* bitfield of key indexes that the driver is
+ * known not to be configured with a key */
struct wpa_blacklist *blacklist;
@@ -479,9 +521,18 @@
*/
MANUAL_SCAN_REQ
} scan_req, last_scan_req;
- struct os_time scan_trigger_time;
+ struct os_reltime scan_trigger_time, scan_start_time;
int scan_runs; /* number of scan runs since WPS was started */
int *next_scan_freqs;
+ int *manual_scan_freqs;
+ unsigned int manual_scan_passive:1;
+ unsigned int manual_scan_use_id:1;
+ unsigned int manual_scan_only_new:1;
+ unsigned int own_scan_requested:1;
+ unsigned int own_scan_running:1;
+ unsigned int external_scan_running:1;
+ unsigned int clear_driver_scan_cache:1;
+ unsigned int manual_scan_id;
int scan_interval; /* time in sec between scans to find suitable AP */
int normal_scans; /* normal scans run before sched_scan */
int scan_for_connection; /* whether the scan request was triggered for
@@ -517,7 +568,7 @@
int blacklist_cleared;
struct wpabuf *pending_eapol_rx;
- struct os_time pending_eapol_rx_time;
+ struct os_reltime pending_eapol_rx_time;
u8 pending_eapol_rx_src[ETH_ALEN];
unsigned int last_eapol_matches_bssid:1;
@@ -551,7 +602,7 @@
u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
* sa_query_count octets of pending
* SA Query transaction identifiers */
- struct os_time sa_query_start;
+ struct os_reltime sa_query_start;
u8 sched_obss_scan;
u16 obss_scan_int;
u16 bss_max_idle_period;
@@ -647,7 +698,6 @@
*/
char cross_connect_uplink[100];
- unsigned int sta_scan_pending:1;
unsigned int p2p_auto_join:1;
unsigned int p2p_auto_pd:1;
unsigned int p2p_persistent_group:1;
@@ -657,13 +707,17 @@
unsigned int p2p_go_vht:1;
unsigned int user_initiated_pd:1;
unsigned int p2p_go_group_formation_completed:1;
+ unsigned int waiting_presence_resp;
int p2p_first_connection_timeout;
int p2p_persistent_go_freq;
int p2p_persistent_id;
int p2p_go_intent;
int p2p_connect_freq;
- struct os_time p2p_auto_started;
+ struct os_reltime p2p_auto_started;
struct wpa_ssid *p2p_last_4way_hs_fail;
+ struct wpa_radio_work *p2p_scan_work;
+ struct wpa_radio_work *p2p_listen_work;
+ struct wpa_radio_work *p2p_send_action_work;
#endif /* CONFIG_P2P */
struct wpa_ssid *bgscan_ssid;
@@ -717,9 +771,9 @@
struct ext_password_data *ext_pw;
- struct wpabuf *last_gas_resp;
- u8 last_gas_addr[ETH_ALEN];
- u8 last_gas_dialog_token;
+ struct wpabuf *last_gas_resp, *prev_gas_resp;
+ u8 last_gas_addr[ETH_ALEN], prev_gas_addr[ETH_ALEN];
+ u8 last_gas_dialog_token, prev_gas_dialog_token;
unsigned int no_keep_alive:1;
@@ -740,6 +794,9 @@
#endif /* CONFIG_TESTING_GET_GTK */
unsigned int num_multichan_concurrent;
+ struct wpa_radio_work *connect_work;
+
+ unsigned int ext_work_id;
};
@@ -821,7 +878,6 @@
void wpa_supplicant_terminate_proc(struct wpa_global *global);
void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len);
-enum wpa_key_mgmt key_mgmt2driver(int key_mgmt);
void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s);
void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s);
void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid);
@@ -835,7 +891,6 @@
size_t ssid_len);
void wpas_request_connection(struct wpa_supplicant *wpa_s);
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf);
-int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s, int include_current);
/**
* wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 0b3c892..038c7fa 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -1,6 +1,6 @@
/*
* wpa_supplicant / WPS integration
- * Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2008-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -54,6 +54,11 @@
int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
{
+#ifdef CONFIG_P2P
+ if (wpas_p2p_wps_eapol_cb(wpa_s) > 0)
+ return 1;
+#endif /* CONFIG_P2P */
+
if (!wpa_s->wps_success &&
wpa_s->current_ssid &&
eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
@@ -260,31 +265,6 @@
ssid->group_cipher != new_ssid->group_cipher)
continue;
- if (ssid->passphrase && new_ssid->passphrase) {
- if (os_strlen(ssid->passphrase) !=
- os_strlen(new_ssid->passphrase))
- continue;
- if (os_strcmp(ssid->passphrase, new_ssid->passphrase) !=
- 0)
- continue;
- } else if (ssid->passphrase || new_ssid->passphrase)
- continue;
-
- if ((ssid->psk_set || new_ssid->psk_set) &&
- os_memcmp(ssid->psk, new_ssid->psk, sizeof(ssid->psk)) != 0)
- continue;
-
- if (ssid->auth_alg == WPA_ALG_WEP) {
- if (ssid->wep_tx_keyidx != new_ssid->wep_tx_keyidx)
- continue;
- if (os_memcmp(ssid->wep_key, new_ssid->wep_key,
- sizeof(ssid->wep_key)))
- continue;
- if (os_memcmp(ssid->wep_key_len, new_ssid->wep_key_len,
- sizeof(ssid->wep_key_len)))
- continue;
- }
-
/* Remove the duplicated older network entry. */
wpa_printf(MSG_DEBUG, "Remove duplicate network %d", ssid->id);
wpas_notify_network_removed(wpa_s, ssid);
@@ -891,6 +871,7 @@
wpas_wps_reenable_networks(wpa_s);
eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL);
/* Remove any existing WPS network from configuration */
ssid = wpa_s->conf->ssid;
@@ -1160,6 +1141,9 @@
} else {
wpas_wps_reenable_networks(wpa_s);
wpas_wps_clear_ap_info(wpa_s);
+ if (eloop_cancel_timeout(wpas_wps_clear_timeout, wpa_s, NULL) >
+ 0)
+ wpas_clear_wps(wpa_s);
}
wpa_s->after_wps = 0;
@@ -1298,7 +1282,9 @@
static void wpas_wps_set_uuid(struct wpa_supplicant *wpa_s,
struct wps_context *wps)
{
- wpa_printf(MSG_DEBUG, "WPS: Set UUID for interface %s", wpa_s->ifname);
+ char buf[50];
+ const char *src;
+
if (is_nil_uuid(wpa_s->conf->uuid)) {
struct wpa_supplicant *first;
first = wpa_s->global->ifaces;
@@ -1309,18 +1295,18 @@
os_memcpy(wps->uuid,
wpa_s->global->ifaces->wps->uuid,
WPS_UUID_LEN);
- wpa_hexdump(MSG_DEBUG, "WPS: UUID from the first "
- "interface", wps->uuid, WPS_UUID_LEN);
+ src = "from the first interface";
} else {
uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
- wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC "
- "address", wps->uuid, WPS_UUID_LEN);
+ src = "based on MAC address";
}
} else {
os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
- wpa_hexdump(MSG_DEBUG, "WPS: UUID based on configuration",
- wps->uuid, WPS_UUID_LEN);
+ src = "based on configuration";
}
+
+ uuid_bin2str(wps->uuid, buf, sizeof(buf));
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPS: UUID %s: %s", src, buf);
}
@@ -1959,19 +1945,6 @@
}
-int wpas_wps_in_progress(struct wpa_supplicant *wpa_s)
-{
- struct wpa_ssid *ssid;
-
- for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
- if (!ssid->disabled && ssid->key_mgmt == WPA_KEY_MGMT_WPS)
- return 1;
- }
-
- return 0;
-}
-
-
void wpas_wps_update_config(struct wpa_supplicant *wpa_s)
{
struct wps_context *wps = wpa_s->wps;
@@ -2260,8 +2233,9 @@
#ifdef CONFIG_WPS_NFC
-struct wpabuf * wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s,
- int ndef, const char *uuid)
+static struct wpabuf *
+wpas_wps_er_nfc_handover_sel(struct wpa_supplicant *wpa_s, int ndef,
+ const char *uuid)
{
#ifdef CONFIG_WPS_ER
struct wpabuf *ret;
@@ -2355,12 +2329,10 @@
#endif /* CONFIG_WPS_NFC */
-extern int wpa_debug_level;
-
static void wpas_wps_dump_ap_info(struct wpa_supplicant *wpa_s)
{
size_t i;
- struct os_time now;
+ struct os_reltime now;
if (wpa_debug_level > MSG_DEBUG)
return;
@@ -2368,7 +2340,7 @@
if (wpa_s->wps_ap == NULL)
return;
- os_get_time(&now);
+ os_get_reltime(&now);
for (i = 0; i < wpa_s->num_wps_ap; i++) {
struct wps_ap_info *ap = &wpa_s->wps_ap[i];
@@ -2481,5 +2453,5 @@
if (ap == NULL)
return;
ap->tries++;
- os_get_time(&ap->last_attempt);
+ os_get_reltime(&ap->last_attempt);
}
diff --git a/wpa_supplicant/wps_supplicant.h b/wpa_supplicant/wps_supplicant.h
index 2a212ca..3fcfbbe 100644
--- a/wpa_supplicant/wps_supplicant.h
+++ b/wpa_supplicant/wps_supplicant.h
@@ -60,7 +60,6 @@
struct wpabuf * wpas_wps_er_nfc_config_token(struct wpa_supplicant *wpa_s,
int ndef, const char *uuid);
int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s);
-int wpas_wps_in_progress(struct wpa_supplicant *wpa_s);
void wpas_wps_update_config(struct wpa_supplicant *wpa_s);
struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
int ndef, const char *id_str);