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/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);