aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2015-03-05 14:16:04 -0800
committerDmitry Shmidt <dimitrysh@google.com>2015-03-10 11:04:48 -0700
commit203eadb9eda41a1dde4a583edb4684319e3f399e (patch)
tree3b91f63844f16aeca8e1e122ef4c6d49f8164b17
parent34c1202b3e71c63661a850aad81f663e40e48ca1 (diff)
downloadandroid_external_wpa_supplicant_8-203eadb9eda41a1dde4a583edb4684319e3f399e.tar.gz
android_external_wpa_supplicant_8-203eadb9eda41a1dde4a583edb4684319e3f399e.tar.bz2
android_external_wpa_supplicant_8-203eadb9eda41a1dde4a583edb4684319e3f399e.zip
Cumulative patch from commit 6e9023ea499ea9a89b0e858c85e32b455d57264c
6e9023e DFS: Allow wpa_supplicant AP mode to use non-offloaded DFS 02e42ab nl80211: Add vendor event parsing for DFS offload events bd0f68c DFS: wpa_supplicant event processing d7f1aa8 DFS offload: P2P changes for autonomous GO 1e2aaff DFS offload: Indicate AP-CSA-FINISHED for DFS offloaded case c13578c DFS offload: Add main DFS handler for offloaded case 5de81d7 DFS offload: Skip user space processing for CAC operations 192ad3d Interworking: Clear SCANNING state if no match found 95d7b86 P2P: Consider 5 GHz channels also for auto GO a51c40a P2P: Fix regression in start-GO/AP through a "fake" scan dd5c155 eap_proxy: Callback to notify any updates from eap_proxy 9a05d98 atheros: Add a new flag for OSEN support 9feadba Remove unnecessary NULL check to make function more consistent 1772d34 P2P: Fix interface deinit for failed group interface initialization 3f9ebc4 P2P: Allow AP/GO interface to be started while P2P-in-progress b4a9292 RADIUS client: Fix server failover on return-to-primary on error case 9836cb5 Add option to force a specific RADIUS client address to be used 1a7ed38 RADIUS client: Fix a copy-paste error in accounting server failover de7c06e P2P: Continue find in GO-Neg-Resp-fail status corner cases c280590 Do not add blacklist entries based on normal disconnect request cases bdf0518 P2P: Direct P2P_CONNECT command to proper interface 44b9ea5 P2P: Do not allow scan or normal association on cfg80211 P2P Device 9542f21 Clean up p2p_find command parsing and execution fa9f381 P2P: Allow a specific channel to be specified in P2P_FIND eb78a8d P2P: Restore P2P_SCAN_SPECIFIC d988ff7 hostapd: Disable VHT caps for STAs when no valid VHT MCS found 70fd828 RADIUS client: Fix previous failover change c3dabf5 Fix merge issue with IBSS VHT support 8b2b718 Fix minor issue in HT40 max rate determination 347c55e RADIUS client: Re-try connection if socket is closed on retransmit 94b39e5 RADIUS client: Fix server connection recovery after initial failure bbee36e Allow RADIUS server address to be replaced efb4008 TLS: Remove placeholders for SIGN_ALG_DSA support Change-Id: I8e5d0dfd5fddb6de2f8d8211b708c3bb6674098b Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r--hostapd/config_file.c26
-rw-r--r--hostapd/hostapd.conf6
-rw-r--r--src/ap/dfs.c85
-rw-r--r--src/ap/dfs.h4
-rw-r--r--src/ap/drv_callbacks.c26
-rw-r--r--src/ap/hostapd.c31
-rw-r--r--src/ap/ieee802_11_vht.c44
-rw-r--r--src/common/ieee802_11_common.c7
-rw-r--r--src/common/ieee802_11_common.h1
-rw-r--r--src/drivers/driver_atheros.c2
-rw-r--r--src/drivers/driver_nl80211.c3
-rw-r--r--src/drivers/driver_nl80211_event.c93
-rw-r--r--src/eap_peer/eap.h8
-rw-r--r--src/eapol_supp/eapol_supp_sm.c14
-rw-r--r--src/eapol_supp/eapol_supp_sm.h8
-rw-r--r--src/p2p/p2p.c23
-rw-r--r--src/p2p/p2p.h10
-rw-r--r--src/radius/radius_client.c157
-rw-r--r--src/tls/tlsv1_client_write.c30
-rw-r--r--src/tls/tlsv1_common.c23
-rw-r--r--src/tls/tlsv1_server_read.c30
-rw-r--r--src/utils/utils_module_tests.c159
-rw-r--r--wpa_supplicant/README-P2P6
-rw-r--r--wpa_supplicant/ap.c74
-rw-r--r--wpa_supplicant/ap.h11
-rw-r--r--wpa_supplicant/ctrl_iface.c40
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.c2
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers_p2p.c2
-rw-r--r--wpa_supplicant/dbus/dbus_old_handlers.c2
-rw-r--r--wpa_supplicant/events.c29
-rw-r--r--wpa_supplicant/interworking.c4
-rw-r--r--wpa_supplicant/main.c2
-rw-r--r--wpa_supplicant/main_none.c2
-rw-r--r--wpa_supplicant/main_winmain.c2
-rw-r--r--wpa_supplicant/main_winsvc.c2
-rw-r--r--wpa_supplicant/mesh.c3
-rw-r--r--wpa_supplicant/p2p_supplicant.c89
-rw-r--r--wpa_supplicant/p2p_supplicant.h2
-rw-r--r--wpa_supplicant/scan.c59
-rw-r--r--wpa_supplicant/wpa_supplicant.c34
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h4
-rw-r--r--wpa_supplicant/wpas_glue.c22
-rw-r--r--wpa_supplicant/wps_supplicant.c8
43 files changed, 997 insertions, 192 deletions
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 9edbe632..53143f76 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2189,6 +2189,14 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_free(bss->nas_identifier);
bss->nas_identifier = os_strdup(pos);
#ifndef CONFIG_NO_RADIUS
+ } else if (os_strcmp(buf, "radius_client_addr") == 0) {
+ if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid IP address '%s'",
+ line, pos);
+ return 1;
+ }
+ bss->radius->force_client_addr = 1;
} else if (os_strcmp(buf, "auth_server_addr") == 0) {
if (hostapd_config_read_radius_addr(
&bss->radius->auth_servers,
@@ -2200,6 +2208,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
} else if (bss->radius->auth_server &&
+ os_strcmp(buf, "auth_server_addr_replace") == 0) {
+ if (hostapd_parse_ip_addr(pos,
+ &bss->radius->auth_server->addr)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid IP address '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (bss->radius->auth_server &&
os_strcmp(buf, "auth_server_port") == 0) {
bss->radius->auth_server->port = atoi(pos);
} else if (bss->radius->auth_server &&
@@ -2225,6 +2242,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
} else if (bss->radius->acct_server &&
+ os_strcmp(buf, "acct_server_addr_replace") == 0) {
+ if (hostapd_parse_ip_addr(pos,
+ &bss->radius->acct_server->addr)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid IP address '%s'",
+ line, pos);
+ return 1;
+ }
+ } else if (bss->radius->acct_server &&
os_strcmp(buf, "acct_server_port") == 0) {
bss->radius->acct_server->port = atoi(pos);
} else if (bss->radius->acct_server &&
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index dd05c2ff..9e81e9e9 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -885,6 +885,12 @@ own_ip_addr=127.0.0.1
# 48 octets long.
#nas_identifier=ap.example.com
+# RADIUS client forced local IP address for the access point
+# Normally the local IP address is determined automatically based on configured
+# IP addresses, but this field can be used to force a specific address to be
+# used, e.g., when the device has multiple IP addresses.
+#radius_client_addr=127.0.0.1
+
# RADIUS authentication server
#auth_server_addr=127.0.0.1
#auth_server_port=1812
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index fc8d7adf..da6fd464 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1,7 +1,7 @@
/*
* DFS - Dynamic Frequency Selection
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
- * Copyright (c) 2013, Qualcomm Atheros, Inc.
+ * Copyright (c) 2013-2015, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -748,11 +748,19 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
if (success) {
/* Complete iface/ap configuration */
- set_dfs_state(iface, freq, ht_enabled, chan_offset,
- chan_width, cf1, cf2,
- HOSTAPD_CHAN_DFS_AVAILABLE);
- iface->cac_started = 0;
- hostapd_setup_interface_complete(iface, 0);
+ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
+ /* Complete AP configuration for the first bring up. */
+ if (iface->state != HAPD_IFACE_ENABLED)
+ hostapd_setup_interface_complete(iface, 0);
+ else
+ iface->cac_started = 0;
+ } else {
+ set_dfs_state(iface, freq, ht_enabled, chan_offset,
+ chan_width, cf1, cf2,
+ HOSTAPD_CHAN_DFS_AVAILABLE);
+ iface->cac_started = 0;
+ hostapd_setup_interface_complete(iface, 0);
+ }
}
return 0;
@@ -934,13 +942,17 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
{
int res;
- if (!iface->conf->ieee80211h)
- return 0;
-
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
+ /* Proceed only if DFS is not offloaded to the driver */
+ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
+ return 0;
+
+ if (!iface->conf->ieee80211h)
+ return 0;
+
/* mark radar frequency as invalid */
set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
@@ -964,6 +976,11 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
+
+ /* Proceed only if DFS is not offloaded to the driver */
+ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
+ return 0;
+
/* TODO add correct implementation here */
set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
cf1, cf2, HOSTAPD_CHAN_DFS_USABLE);
@@ -995,3 +1012,53 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1);
return res;
}
+
+
+int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+ int ht_enabled, int chan_offset, int chan_width,
+ int cf1, int cf2)
+{
+ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+ "freq=%d chan=%d chan_offset=%d width=%d seg0=%d "
+ "seg1=%d cac_time=%ds",
+ freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60);
+ iface->cac_started = 1;
+ return 0;
+}
+
+
+/*
+ * Main DFS handler for offloaded case.
+ * 2 - continue channel/AP setup for non-DFS channel
+ * 1 - continue channel/AP setup for DFS channel
+ * 0 - channel/AP setup will be continued after CAC
+ * -1 - hit critical error
+ */
+int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
+{
+ wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
+ __func__, iface->cac_started);
+
+ /*
+ * If DFS has already been started, then we are being called from a
+ * callback to continue AP/channel setup. Reset the CAC start flag and
+ * return.
+ */
+ if (iface->cac_started) {
+ wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
+ __func__, iface->cac_started);
+ iface->cac_started = 0;
+ return 1;
+ }
+
+ if (ieee80211_is_dfs(iface->freq)) {
+ wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS",
+ __func__, iface->freq);
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "%s: freq %d MHz does not require DFS. Continue channel/AP setup",
+ __func__, iface->freq);
+ return 2;
+}
diff --git a/src/ap/dfs.h b/src/ap/dfs.h
index a619c55c..be8c0e60 100644
--- a/src/ap/dfs.h
+++ b/src/ap/dfs.h
@@ -22,5 +22,9 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
int ht_enabled,
int chan_offset, int chan_width, int cf1, int cf2);
int hostapd_is_dfs_required(struct hostapd_iface *iface);
+int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+ int ht_enabled, int chan_offset, int chan_width,
+ int cf1, int cf2);
+int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
#endif /* DFS_H */
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index c39989c3..a0adc67d 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -439,7 +439,7 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
int offset, int width, int cf1, int cf2)
{
#ifdef NEED_AP_MLME
- int channel, chwidth, seg0_idx = 0, seg1_idx = 0;
+ int channel, chwidth, seg0_idx = 0, seg1_idx = 0, is_dfs;
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO,
@@ -497,13 +497,18 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
+ is_dfs = ieee80211_is_dfs(freq);
+
if (hapd->csa_in_progress &&
freq == hapd->cs_freq_params.freq) {
hostapd_cleanup_cs_params(hapd);
ieee802_11_set_beacon(hapd);
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d",
- freq);
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
+ "freq=%d dfs=%d", freq, is_dfs);
+ } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
+ "freq=%d dfs=%d", freq, is_dfs);
}
#endif /* NEED_AP_MLME */
}
@@ -1032,6 +1037,16 @@ static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd,
radar->cf1, radar->cf2);
}
+
+static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
+ struct dfs_event *radar)
+{
+ wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq);
+ hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled,
+ radar->chan_offset, radar->chan_width,
+ radar->cf1, radar->cf2);
+}
+
#endif /* NEED_AP_MLME */
@@ -1207,6 +1222,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
hostapd_channel_list_updated(
hapd->iface, data->channel_list_changed.initiator);
break;
+ case EVENT_DFS_CAC_STARTED:
+ if (!data)
+ break;
+ hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
+ break;
#endif /* NEED_AP_MLME */
case EVENT_INTERFACE_ENABLED:
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index e641b129..f6019ac2 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1377,6 +1377,7 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
size_t j;
u8 *prev_addr;
int delay_apply_cfg = 0;
+ int res_dfs_offload = 0;
if (err)
goto fail;
@@ -1403,6 +1404,23 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
goto fail;
return res;
}
+ } else {
+ /* If DFS is offloaded to the driver */
+ res_dfs_offload = hostapd_handle_dfs_offload(iface);
+ if (res_dfs_offload <= 0) {
+ if (res_dfs_offload < 0)
+ goto fail;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "Proceed with AP/channel setup");
+ /*
+ * If this is a DFS channel, move to completing
+ * AP setup.
+ */
+ if (res_dfs_offload == 1)
+ goto dfs_offload;
+ /* Otherwise fall through. */
+ }
}
#endif /* NEED_AP_MLME */
@@ -1497,6 +1515,19 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
goto fail;
}
+ if ((iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+ !res_dfs_offload) {
+ /*
+ * If freq is DFS, and DFS is offloaded to the driver, then wait
+ * for CAC to complete.
+ */
+ wpa_printf(MSG_DEBUG, "%s: Wait for CAC to complete", __func__);
+ return res_dfs_offload;
+ }
+
+#ifdef NEED_AP_MLME
+dfs_offload:
+#endif /* NEED_AP_MLME */
hostapd_set_state(iface, HAPD_IFACE_ENABLED);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
if (hapd->setup_complete_cb)
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index 159693f6..171538ad 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -90,13 +90,55 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
}
+static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
+ const u8 *sta_vht_capab)
+{
+ const struct ieee80211_vht_capabilities *vht_cap;
+ struct ieee80211_vht_capabilities ap_vht_cap;
+ u16 sta_rx_mcs_set, ap_tx_mcs_set;
+ int i;
+
+ if (!mode)
+ return 1;
+
+ /*
+ * Disable VHT caps for STAs for which there is not even a single
+ * allowed MCS in any supported number of streams, i.e., STA is
+ * advertising 3 (not supported) as VHT MCS rates for all supported
+ * stream cases.
+ */
+ os_memcpy(&ap_vht_cap.vht_supported_mcs_set, mode->vht_mcs_set,
+ sizeof(ap_vht_cap.vht_supported_mcs_set));
+ vht_cap = (const struct ieee80211_vht_capabilities *) sta_vht_capab;
+
+ /* AP Tx MCS map vs. STA Rx MCS map */
+ sta_rx_mcs_set = le_to_host16(vht_cap->vht_supported_mcs_set.rx_map);
+ ap_tx_mcs_set = le_to_host16(ap_vht_cap.vht_supported_mcs_set.tx_map);
+
+ for (i = 0; i < VHT_RX_NSS_MAX_STREAMS; i++) {
+ if ((ap_tx_mcs_set & (0x3 << (i * 2))) == 3)
+ continue;
+
+ if ((sta_rx_mcs_set & (0x3 << (i * 2))) == 3)
+ continue;
+
+ return 1;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "No matching VHT MCS found between AP TX and STA RX");
+ return 0;
+}
+
+
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_capab, size_t vht_capab_len)
{
/* Disable VHT caps for STAs associated to no-VHT BSSes. */
if (!vht_capab ||
vht_capab_len < sizeof(struct ieee80211_vht_capabilities) ||
- hapd->conf->disable_11ac) {
+ hapd->conf->disable_11ac ||
+ !check_valid_vht_mcs(hapd->iface->current_mode, vht_capab)) {
sta->flags &= ~WLAN_STA_VHT;
os_free(sta->vht_capabilities);
sta->vht_capabilities = NULL;
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index ed8d4661..aca0b732 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -826,6 +826,13 @@ int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
}
+int ieee80211_is_dfs(int freq)
+{
+ /* TODO: this could be more accurate to better cover all domains */
+ return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700);
+}
+
+
static int is_11b(u8 rate)
{
return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index 05fe32b4..7f0b296d 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -108,6 +108,7 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
const char *name, const char *val);
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan);
+int ieee80211_is_dfs(int freq);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index 350d5059..f4644216 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -1810,7 +1810,7 @@ static int atheros_set_ap(void *priv, struct wpa_driver_ap_params *params)
wpa_hexdump_buf(MSG_DEBUG, "atheros: assocresp_ies",
params->assocresp_ies);
-#if defined(CONFIG_HS20) && defined(IEEE80211_PARAM_OSEN)
+#if defined(CONFIG_HS20) && (defined(IEEE80211_PARAM_OSEN) || defined(CONFIG_ATHEROS_OSEN))
if (params->osen) {
struct wpa_bss_params bss_params;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 2dce242a..2a2ef6f1 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4301,7 +4301,8 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
return -1;
}
- if (nl80211_set_channel(drv->first_bss, &params->freq, 0)) {
+ if (params->freq.freq &&
+ nl80211_set_channel(drv->first_bss, &params->freq, 0)) {
if (old_mode != nlmode)
wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
nl80211_remove_monitor_interface(drv);
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 6a7b509e..b59d1390 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1531,6 +1531,92 @@ static void qca_nl80211_key_mgmt_auth(struct wpa_driver_nl80211_data *drv,
}
+static void qca_nl80211_dfs_offload_radar_event(
+ struct wpa_driver_nl80211_data *drv, u32 subcmd, u8 *msg, int length)
+{
+ union wpa_event_data data;
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: DFS offload radar vendor event received");
+
+ if (nla_parse(tb, NL80211_ATTR_MAX,
+ (struct nlattr *) msg, length, NULL))
+ return;
+
+ if (!tb[NL80211_ATTR_WIPHY_FREQ]) {
+ wpa_printf(MSG_INFO,
+ "nl80211: Error parsing WIPHY_FREQ in FS offload radar vendor event");
+ return;
+ }
+
+ os_memset(&data, 0, sizeof(data));
+ data.dfs_event.freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
+
+ wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz",
+ data.dfs_event.freq);
+
+ /* Check HT params */
+ if (tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
+ data.dfs_event.ht_enabled = 1;
+ data.dfs_event.chan_offset = 0;
+
+ switch (nla_get_u32(tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
+ case NL80211_CHAN_NO_HT:
+ data.dfs_event.ht_enabled = 0;
+ break;
+ case NL80211_CHAN_HT20:
+ break;
+ case NL80211_CHAN_HT40PLUS:
+ data.dfs_event.chan_offset = 1;
+ break;
+ case NL80211_CHAN_HT40MINUS:
+ data.dfs_event.chan_offset = -1;
+ break;
+ }
+ }
+
+ /* Get VHT params */
+ if (tb[NL80211_ATTR_CHANNEL_WIDTH])
+ data.dfs_event.chan_width =
+ convert2width(nla_get_u32(
+ tb[NL80211_ATTR_CHANNEL_WIDTH]));
+ if (tb[NL80211_ATTR_CENTER_FREQ1])
+ data.dfs_event.cf1 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ1]);
+ if (tb[NL80211_ATTR_CENTER_FREQ2])
+ data.dfs_event.cf2 = nla_get_u32(tb[NL80211_ATTR_CENTER_FREQ2]);
+
+ wpa_printf(MSG_DEBUG, "nl80211: DFS event on freq %d MHz, ht: %d, "
+ "offset: %d, width: %d, cf1: %dMHz, cf2: %dMHz",
+ data.dfs_event.freq, data.dfs_event.ht_enabled,
+ data.dfs_event.chan_offset, data.dfs_event.chan_width,
+ data.dfs_event.cf1, data.dfs_event.cf2);
+
+ switch (subcmd) {
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_RADAR_DETECTED, &data);
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_STARTED, &data);
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_FINISHED, &data);
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_ABORTED, &data);
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_NOP_FINISHED, &data);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Unknown DFS offload radar event %d received",
+ subcmd);
+ break;
+ }
+}
+
+
static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
u32 subcmd, u8 *data, size_t len)
{
@@ -1547,6 +1633,13 @@ static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
qca_nl80211_acs_select_ch(drv, data, len);
break;
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED:
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED:
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED:
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED:
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED:
+ qca_nl80211_dfs_offload_radar_event(drv, subcmd, data, len);
+ break;
default:
wpa_printf(MSG_DEBUG,
"nl80211: Ignore unsupported QCA vendor event %u",
diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h
index 8c4a42f6..702463b9 100644
--- a/src/eap_peer/eap.h
+++ b/src/eap_peer/eap.h
@@ -246,6 +246,14 @@ struct eapol_callbacks {
void (*notify_status)(void *ctx, const char *status,
const char *parameter);
+#ifdef CONFIG_EAP_PROXY
+ /**
+ * eap_proxy_cb - Callback signifying any updates from eap_proxy
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ */
+ void (*eap_proxy_cb)(void *ctx);
+#endif /* CONFIG_EAP_PROXY */
+
/**
* set_anon_id - Set or add anonymous identity
* @ctx: eapol_ctx from eap_peer_sm_init() call
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index f6150512..9cc234a8 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -1977,6 +1977,17 @@ static void eapol_sm_notify_status(void *ctx, const char *status,
}
+#ifdef CONFIG_EAP_PROXY
+static void eapol_sm_eap_proxy_cb(void *ctx)
+{
+ struct eapol_sm *sm = ctx;
+
+ if (sm->ctx->eap_proxy_cb)
+ sm->ctx->eap_proxy_cb(sm->ctx->ctx);
+}
+#endif /* CONFIG_EAP_PROXY */
+
+
static void eapol_sm_set_anon_id(void *ctx, const u8 *id, size_t len)
{
struct eapol_sm *sm = ctx;
@@ -2000,6 +2011,9 @@ static struct eapol_callbacks eapol_cb =
eapol_sm_eap_param_needed,
eapol_sm_notify_cert,
eapol_sm_notify_status,
+#ifdef CONFIG_EAP_PROXY
+ eapol_sm_eap_proxy_cb,
+#endif /* CONFIG_EAP_PROXY */
eapol_sm_set_anon_id
};
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index 03341a30..1309ff75 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -271,6 +271,14 @@ struct eapol_ctx {
void (*status_cb)(void *ctx, const char *status,
const char *parameter);
+#ifdef CONFIG_EAP_PROXY
+ /**
+ * eap_proxy_cb - Callback signifying any updates from eap_proxy
+ * @ctx: eapol_ctx from eap_peer_sm_init() call
+ */
+ void (*eap_proxy_cb)(void *ctx);
+#endif /* CONFIG_EAP_PROXY */
+
/**
* set_anon_id - Set or add anonymous identity
* @ctx: eapol_ctx from eap_peer_sm_init() call
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index d62874ec..6adb3dc2 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1147,7 +1147,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_count, const char **seek)
+ u8 seek_count, const char **seek, int freq)
{
int res;
@@ -1230,6 +1230,19 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
p2p, NULL);
switch (type) {
case P2P_FIND_START_WITH_FULL:
+ if (freq > 0) {
+ /*
+ * Start with the specified channel and then move to
+ * social channels only scans.
+ */
+ res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx,
+ P2P_SCAN_SPECIFIC, freq,
+ p2p->num_req_dev_types,
+ p2p->req_dev_types, dev_id,
+ DEV_PW_DEFAULT);
+ break;
+ }
+ /* fall through */
case P2P_FIND_PROGRESSIVE:
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
p2p->num_req_dev_types,
@@ -3508,13 +3521,19 @@ static void p2p_go_neg_resp_failure_cb(struct p2p_data *p2p, int success,
p2p_dbg(p2p, "GO Negotiation Response (failure) TX callback: success=%d", success);
if (p2p->go_neg_peer && p2p->go_neg_peer->status != P2P_SC_SUCCESS) {
p2p_go_neg_failed(p2p, p2p->go_neg_peer->status);
- } else if (success) {
+ return;
+ }
+
+ if (success) {
struct p2p_device *dev;
dev = p2p_get_device(p2p, addr);
if (dev &&
dev->status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
dev->flags |= P2P_DEV_PEER_WAITING_RESPONSE;
}
+
+ if (p2p->state == P2P_SEARCH || p2p->state == P2P_SD_DURING_FIND)
+ p2p_continue_find(p2p);
}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index b1c89d71..2402db6a 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -245,6 +245,7 @@ struct p2p_data;
enum p2p_scan_type {
P2P_SCAN_SOCIAL,
P2P_SCAN_FULL,
+ P2P_SCAN_SPECIFIC,
P2P_SCAN_SOCIAL_PLUS_ONE
};
@@ -545,7 +546,8 @@ struct p2p_config {
* operation to be completed. Type type argument specifies which type
* of scan is to be done. @P2P_SCAN_SOCIAL indicates that only the
* social channels (1, 6, 11) should be scanned. @P2P_SCAN_FULL
- * indicates that all channels are to be scanned.
+ * indicates that all channels are to be scanned. @P2P_SCAN_SPECIFIC
+ * request a scan of a single channel specified by freq.
* @P2P_SCAN_SOCIAL_PLUS_ONE request scan of all the social channels
* plus one extra channel specified by freq.
*
@@ -1129,13 +1131,17 @@ enum p2p_discovery_type {
* @search_delay: Extra delay in milliseconds between search iterations
* @seek_count: Number of ASP Service Strings in the seek_string array
* @seek_string: ASP Service Strings to query for in Probe Requests
+ * @freq: Requested first scan frequency (in MHz) to modify type ==
+ * P2P_FIND_START_WITH_FULL behavior. 0 = Use normal full scan.
+ * If p2p_find is already in progress, this parameter is ignored and full
+ * scan will be executed.
* Returns: 0 on success, -1 on failure
*/
int p2p_find(struct p2p_data *p2p, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_count, const char **seek_string);
+ u8 seek_count, const char **seek_string, int freq);
/**
* p2p_notify_scan_trigger_status - Indicate scan trigger status
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index 34f56853..693f61ea 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -1,6 +1,6 @@
/*
* RADIUS client
- * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -236,6 +236,8 @@ radius_change_server(struct radius_client_data *radius,
int sock, int sock6, int auth);
static int radius_client_init_acct(struct radius_client_data *radius);
static int radius_client_init_auth(struct radius_client_data *radius);
+static void radius_client_auth_failover(struct radius_client_data *radius);
+static void radius_client_acct_failover(struct radius_client_data *radius);
static void radius_client_msg_free(struct radius_msg_list *req)
@@ -304,7 +306,7 @@ static int radius_client_handle_send_error(struct radius_client_data *radius,
{
#ifndef CONFIG_NATIVE_WINDOWS
int _errno = errno;
- wpa_printf(MSG_INFO, "send[RADIUS]: %s", strerror(errno));
+ wpa_printf(MSG_INFO, "send[RADIUS,s=%d]: %s", s, strerror(errno));
if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
_errno == EBADF || _errno == ENETUNREACH) {
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
@@ -333,9 +335,18 @@ static int radius_client_retransmit(struct radius_client_data *radius,
struct hostapd_radius_servers *conf = radius->conf;
int s;
struct wpabuf *buf;
+ size_t prev_num_msgs;
if (entry->msg_type == RADIUS_ACCT ||
entry->msg_type == RADIUS_ACCT_INTERIM) {
+ if (radius->acct_sock < 0)
+ radius_client_init_acct(radius);
+ if (radius->acct_sock < 0 && conf->num_acct_servers > 1) {
+ prev_num_msgs = radius->num_msgs;
+ radius_client_acct_failover(radius);
+ if (prev_num_msgs != radius->num_msgs)
+ return 0;
+ }
s = radius->acct_sock;
if (entry->attempts == 0)
conf->acct_server->requests++;
@@ -344,6 +355,14 @@ static int radius_client_retransmit(struct radius_client_data *radius,
conf->acct_server->retransmissions++;
}
} else {
+ if (radius->auth_sock < 0)
+ radius_client_init_auth(radius);
+ if (radius->auth_sock < 0 && conf->num_auth_servers > 1) {
+ prev_num_msgs = radius->num_msgs;
+ radius_client_auth_failover(radius);
+ if (prev_num_msgs != radius->num_msgs)
+ return 0;
+ }
s = radius->auth_sock;
if (entry->attempts == 0)
conf->auth_server->requests++;
@@ -352,6 +371,11 @@ static int radius_client_retransmit(struct radius_client_data *radius,
conf->auth_server->retransmissions++;
}
}
+ if (s < 0) {
+ wpa_printf(MSG_INFO,
+ "RADIUS: No valid socket for retransmission");
+ return 1;
+ }
/* retransmit; remove entry if too many attempts */
entry->attempts++;
@@ -388,7 +412,6 @@ static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
os_time_t first;
struct radius_msg_list *entry, *prev, *tmp;
int auth_failover = 0, acct_failover = 0;
- char abuf[50];
size_t prev_num_msgs;
int s;
@@ -453,54 +476,70 @@ static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
(long int) (first - now.sec));
}
- if (auth_failover && conf->num_auth_servers > 1) {
- struct hostapd_radius_server *next, *old;
- old = conf->auth_server;
- hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_NOTICE,
- "No response from Authentication server "
- "%s:%d - failover",
- hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
- old->port);
-
- for (entry = radius->msgs; entry; entry = entry->next) {
- if (entry->msg_type == RADIUS_AUTH)
- old->timeouts++;
- }
+ if (auth_failover && conf->num_auth_servers > 1)
+ radius_client_auth_failover(radius);
+
+ if (acct_failover && conf->num_acct_servers > 1)
+ radius_client_acct_failover(radius);
+}
+
+
+static void radius_client_auth_failover(struct radius_client_data *radius)
+{
+ struct hostapd_radius_servers *conf = radius->conf;
+ struct hostapd_radius_server *next, *old;
+ struct radius_msg_list *entry;
+ char abuf[50];
+
+ old = conf->auth_server;
+ hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
+ HOSTAPD_LEVEL_NOTICE,
+ "No response from Authentication server %s:%d - failover",
+ hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
+ old->port);
- next = old + 1;
- if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
- next = conf->auth_servers;
- conf->auth_server = next;
- radius_change_server(radius, next, old,
- radius->auth_serv_sock,
- radius->auth_serv_sock6, 1);
+ for (entry = radius->msgs; entry; entry = entry->next) {
+ if (entry->msg_type == RADIUS_AUTH)
+ old->timeouts++;
}
- if (acct_failover && conf->num_acct_servers > 1) {
- struct hostapd_radius_server *next, *old;
- old = conf->acct_server;
- hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_NOTICE,
- "No response from Accounting server "
- "%s:%d - failover",
- hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
- old->port);
+ next = old + 1;
+ if (next > &(conf->auth_servers[conf->num_auth_servers - 1]))
+ next = conf->auth_servers;
+ conf->auth_server = next;
+ radius_change_server(radius, next, old,
+ radius->auth_serv_sock,
+ radius->auth_serv_sock6, 1);
+}
- for (entry = radius->msgs; entry; entry = entry->next) {
- if (entry->msg_type == RADIUS_ACCT ||
- entry->msg_type == RADIUS_ACCT_INTERIM)
- old->timeouts++;
- }
- next = old + 1;
- if (next > &conf->acct_servers[conf->num_acct_servers - 1])
- next = conf->acct_servers;
- conf->acct_server = next;
- radius_change_server(radius, next, old,
- radius->acct_serv_sock,
- radius->acct_serv_sock6, 0);
+static void radius_client_acct_failover(struct radius_client_data *radius)
+{
+ struct hostapd_radius_servers *conf = radius->conf;
+ struct hostapd_radius_server *next, *old;
+ struct radius_msg_list *entry;
+ char abuf[50];
+
+ old = conf->acct_server;
+ hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
+ HOSTAPD_LEVEL_NOTICE,
+ "No response from Accounting server %s:%d - failover",
+ hostapd_ip_txt(&old->addr, abuf, sizeof(abuf)),
+ old->port);
+
+ for (entry = radius->msgs; entry; entry = entry->next) {
+ if (entry->msg_type == RADIUS_ACCT ||
+ entry->msg_type == RADIUS_ACCT_INTERIM)
+ old->timeouts++;
}
+
+ next = old + 1;
+ if (next > &conf->acct_servers[conf->num_acct_servers - 1])
+ next = conf->acct_servers;
+ conf->acct_server = next;
+ radius_change_server(radius, next, old,
+ radius->acct_serv_sock,
+ radius->acct_serv_sock6, 0);
}
@@ -658,6 +697,9 @@ int radius_client_send(struct radius_client_data *radius,
}
if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
+ if (conf->acct_server && radius->acct_sock < 0)
+ radius_client_init_acct(radius);
+
if (conf->acct_server == NULL || radius->acct_sock < 0 ||
conf->acct_server->shared_secret == NULL) {
hostapd_logger(radius->ctx, NULL,
@@ -673,6 +715,9 @@ int radius_client_send(struct radius_client_data *radius,
s = radius->acct_sock;
conf->acct_server->requests++;
} else {
+ if (conf->auth_server && radius->auth_sock < 0)
+ radius_client_init_auth(radius);
+
if (conf->auth_server == NULL || radius->auth_sock < 0 ||
conf->auth_server->shared_secret == NULL) {
hostapd_logger(radius->ctx, NULL,
@@ -1131,18 +1176,28 @@ static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx)
conf->auth_server != conf->auth_servers) {
oserv = conf->auth_server;
conf->auth_server = conf->auth_servers;
- radius_change_server(radius, conf->auth_server, oserv,
- radius->auth_serv_sock,
- radius->auth_serv_sock6, 1);
+ if (radius_change_server(radius, conf->auth_server, oserv,
+ radius->auth_serv_sock,
+ radius->auth_serv_sock6, 1) < 0) {
+ conf->auth_server = oserv;
+ radius_change_server(radius, oserv, conf->auth_server,
+ radius->auth_serv_sock,
+ radius->auth_serv_sock6, 1);
+ }
}
if (radius->acct_sock >= 0 && conf->acct_servers &&
conf->acct_server != conf->acct_servers) {
oserv = conf->acct_server;
conf->acct_server = conf->acct_servers;
- radius_change_server(radius, conf->acct_server, oserv,
- radius->acct_serv_sock,
- radius->acct_serv_sock6, 0);
+ if (radius_change_server(radius, conf->acct_server, oserv,
+ radius->acct_serv_sock,
+ radius->acct_serv_sock6, 0) < 0) {
+ conf->acct_server = oserv;
+ radius_change_server(radius, oserv, conf->acct_server,
+ radius->acct_serv_sock,
+ radius->acct_serv_sock6, 0);
+ }
}
if (conf->retry_primary_interval)
diff --git a/src/tls/tlsv1_client_write.c b/src/tls/tlsv1_client_write.c
index 839eb90a..d192f44f 100644
--- a/src/tls/tlsv1_client_write.c
+++ b/src/tls/tlsv1_client_write.c
@@ -432,7 +432,6 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start;
size_t rlen, hlen, clen;
u8 hash[100], *hpos;
- enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
pos = *msgpos;
@@ -505,21 +504,17 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
} else {
#endif /* CONFIG_TLSV12 */
- if (alg == SIGN_ALG_RSA) {
- hlen = MD5_MAC_LEN;
- if (conn->verify.md5_cert == NULL ||
- crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0)
- {
- tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
- TLS_ALERT_INTERNAL_ERROR);
- conn->verify.md5_cert = NULL;
- crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
- conn->verify.sha1_cert = NULL;
- return -1;
- }
- hpos += MD5_MAC_LEN;
- } else
- crypto_hash_finish(conn->verify.md5_cert, NULL, NULL);
+ hlen = MD5_MAC_LEN;
+ if (conn->verify.md5_cert == NULL ||
+ crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) {
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ conn->verify.md5_cert = NULL;
+ crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
+ conn->verify.sha1_cert = NULL;
+ return -1;
+ }
+ hpos += MD5_MAC_LEN;
conn->verify.md5_cert = NULL;
hlen = SHA1_MAC_LEN;
@@ -532,8 +527,7 @@ static int tls_write_client_certificate_verify(struct tlsv1_client *conn,
}
conn->verify.sha1_cert = NULL;
- if (alg == SIGN_ALG_RSA)
- hlen += MD5_MAC_LEN;
+ hlen += MD5_MAC_LEN;
#ifdef CONFIG_TLSV12
}
diff --git a/src/tls/tlsv1_common.c b/src/tls/tlsv1_common.c
index ced28cff..dabc12a1 100644
--- a/src/tls/tlsv1_common.c
+++ b/src/tls/tlsv1_common.c
@@ -366,23 +366,20 @@ int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
{
u8 *hpos;
size_t hlen;
- enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
struct crypto_hash *ctx;
hpos = hash;
- if (alg == SIGN_ALG_RSA) {
- ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
- if (ctx == NULL)
- return -1;
- crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
- crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
- crypto_hash_update(ctx, server_params, server_params_len);
- hlen = MD5_MAC_LEN;
- if (crypto_hash_finish(ctx, hash, &hlen) < 0)
- return -1;
- hpos += hlen;
- }
+ ctx = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0);
+ if (ctx == NULL)
+ return -1;
+ crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
+ crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
+ crypto_hash_update(ctx, server_params, server_params_len);
+ hlen = MD5_MAC_LEN;
+ if (crypto_hash_finish(ctx, hash, &hlen) < 0)
+ return -1;
+ hpos += hlen;
ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0);
if (ctx == NULL)
diff --git a/src/tls/tlsv1_server_read.c b/src/tls/tlsv1_server_read.c
index 310966c2..0f237baf 100644
--- a/src/tls/tlsv1_server_read.c
+++ b/src/tls/tlsv1_server_read.c
@@ -775,7 +775,6 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
u8 type;
size_t hlen;
u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos;
- enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA;
u8 alert;
if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) {
@@ -883,21 +882,17 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
} else {
#endif /* CONFIG_TLSV12 */
- if (alg == SIGN_ALG_RSA) {
- hlen = MD5_MAC_LEN;
- if (conn->verify.md5_cert == NULL ||
- crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0)
- {
- tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
- TLS_ALERT_INTERNAL_ERROR);
- conn->verify.md5_cert = NULL;
- crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
- conn->verify.sha1_cert = NULL;
- return -1;
- }
- hpos += MD5_MAC_LEN;
- } else
- crypto_hash_finish(conn->verify.md5_cert, NULL, NULL);
+ hlen = MD5_MAC_LEN;
+ if (conn->verify.md5_cert == NULL ||
+ crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) {
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ conn->verify.md5_cert = NULL;
+ crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL);
+ conn->verify.sha1_cert = NULL;
+ return -1;
+ }
+ hpos += MD5_MAC_LEN;
conn->verify.md5_cert = NULL;
hlen = SHA1_MAC_LEN;
@@ -910,8 +905,7 @@ static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct,
}
conn->verify.sha1_cert = NULL;
- if (alg == SIGN_ALG_RSA)
- hlen += MD5_MAC_LEN;
+ hlen += MD5_MAC_LEN;
#ifdef CONFIG_TLSV12
}
diff --git a/src/utils/utils_module_tests.c b/src/utils/utils_module_tests.c
index 9a9ec400..4b97dadd 100644
--- a/src/utils/utils_module_tests.c
+++ b/src/utils/utils_module_tests.c
@@ -1,6 +1,6 @@
/*
* utils module tests
- * Copyright (c) 2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -12,6 +12,7 @@
#include "utils/bitfield.h"
#include "utils/ext_password.h"
#include "utils/trace.h"
+#include "utils/base64.h"
struct printf_test_data {
@@ -84,6 +85,15 @@ static int printf_encode_decode_tests(void)
}
}
+ if (printf_decode(bin, 3, "abcde") != 2)
+ errors++;
+
+ if (printf_decode(bin, 3, "\\xa") != 1 || bin[0] != 10)
+ errors++;
+
+ if (printf_decode(bin, 3, "\\a") != 1 || bin[0] != 'a')
+ errors++;
+
if (errors) {
wpa_printf(MSG_ERROR, "%d printf test(s) failed", errors);
return -1;
@@ -167,6 +177,17 @@ static int bitfield_tests(void)
bitfield_free(bf);
+ bf = bitfield_alloc(8);
+ if (bf == NULL)
+ return -1;
+ if (bitfield_get_first_zero(bf) != 0)
+ errors++;
+ for (i = 0; i < 8; i++)
+ bitfield_set(bf, i);
+ if (bitfield_get_first_zero(bf) != -1)
+ errors++;
+ bitfield_free(bf);
+
if (errors) {
wpa_printf(MSG_ERROR, "%d bitfield test(s) failed", errors);
return -1;
@@ -249,6 +270,140 @@ static int trace_tests(void)
}
+static int base64_tests(void)
+{
+ int errors = 0;
+ unsigned char *res;
+ size_t res_len;
+
+ wpa_printf(MSG_INFO, "base64 tests");
+
+ res = base64_encode((const unsigned char *) "", ~0, &res_len);
+ if (res) {
+ errors++;
+ os_free(res);
+ }
+
+ res = base64_encode((const unsigned char *) "=", 1, &res_len);
+ if (!res || res_len != 5 || res[0] != 'P' || res[1] != 'Q' ||
+ res[2] != '=' || res[3] != '=' || res[4] != '\n')
+ errors++;
+ os_free(res);
+
+ res = base64_encode((const unsigned char *) "=", 1, NULL);
+ if (!res || res[0] != 'P' || res[1] != 'Q' ||
+ res[2] != '=' || res[3] != '=' || res[4] != '\n')
+ errors++;
+ os_free(res);
+
+ res = base64_decode((const unsigned char *) "", 0, &res_len);
+ if (res) {
+ errors++;
+ os_free(res);
+ }
+
+ res = base64_decode((const unsigned char *) "a", 1, &res_len);
+ if (res) {
+ errors++;
+ os_free(res);
+ }
+
+ res = base64_decode((const unsigned char *) "====", 4, &res_len);
+ if (res) {
+ errors++;
+ os_free(res);
+ }
+
+ res = base64_decode((const unsigned char *) "PQ==", 4, &res_len);
+ if (!res || res_len != 1 || res[0] != '=')
+ errors++;
+ os_free(res);
+
+ res = base64_decode((const unsigned char *) "P.Q-=!=*", 8, &res_len);
+ if (!res || res_len != 1 || res[0] != '=')
+ errors++;
+ os_free(res);
+
+ if (errors) {
+ wpa_printf(MSG_ERROR, "%d base64 test(s) failed", errors);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int common_tests(void)
+{
+ char buf[3];
+ u8 addr[ETH_ALEN] = { 1, 2, 3, 4, 5, 6 };
+ u8 bin[3];
+ int errors = 0;
+ struct wpa_freq_range_list ranges;
+
+ wpa_printf(MSG_INFO, "common tests");
+
+ if (hwaddr_mask_txt(buf, 3, addr, addr) != -1)
+ errors++;
+
+ if (wpa_scnprintf(buf, 0, "hello") != 0 ||
+ wpa_scnprintf(buf, 3, "hello") != 2)
+ errors++;
+
+ if (wpa_snprintf_hex(buf, 0, addr, ETH_ALEN) != 0 ||
+ wpa_snprintf_hex(buf, 3, addr, ETH_ALEN) != 2)
+ errors++;
+
+ if (merge_byte_arrays(bin, 3, addr, ETH_ALEN, NULL, 0) != 3 ||
+ merge_byte_arrays(bin, 3, NULL, 0, addr, ETH_ALEN) != 3)
+ errors++;
+
+ if (dup_binstr(NULL, 0) != NULL)
+ errors++;
+
+ if (freq_range_list_includes(NULL, 0) != 0)
+ errors++;
+
+ os_memset(&ranges, 0, sizeof(ranges));
+ if (freq_range_list_parse(&ranges, "") != 0 ||
+ freq_range_list_includes(&ranges, 0) != 0 ||
+ freq_range_list_str(&ranges) != NULL)
+ errors++;
+
+ if (utf8_unescape(NULL, 0, buf, sizeof(buf)) != 0 ||
+ utf8_unescape("a", 1, NULL, 0) != 0 ||
+ utf8_unescape("a\\", 2, buf, sizeof(buf)) != 0 ||
+ utf8_unescape("abcde", 5, buf, sizeof(buf)) != 0 ||
+ utf8_unescape("abc", 3, buf, 3) != 3)
+ errors++;
+
+ if (utf8_unescape("a", 0, buf, sizeof(buf)) != 1 || buf[0] != 'a')
+ errors++;
+
+ if (utf8_unescape("\\b", 2, buf, sizeof(buf)) != 1 || buf[0] != 'b')
+ errors++;
+
+ if (utf8_escape(NULL, 0, buf, sizeof(buf)) != 0 ||
+ utf8_escape("a", 1, NULL, 0) != 0 ||
+ utf8_escape("abcde", 5, buf, sizeof(buf)) != 0 ||
+ utf8_escape("a\\bcde", 6, buf, sizeof(buf)) != 0 ||
+ utf8_escape("ab\\cde", 6, buf, sizeof(buf)) != 0 ||
+ utf8_escape("abc\\de", 6, buf, sizeof(buf)) != 0 ||
+ utf8_escape("abc", 3, buf, 3) != 3)
+ errors++;
+
+ if (utf8_escape("a", 0, buf, sizeof(buf)) != 1 || buf[0] != 'a')
+ errors++;
+
+ if (errors) {
+ wpa_printf(MSG_ERROR, "%d common test(s) failed", errors);
+ return -1;
+ }
+
+ return 0;
+}
+
+
int utils_module_tests(void)
{
int ret = 0;
@@ -259,6 +414,8 @@ int utils_module_tests(void)
ext_password_tests() < 0 ||
trace_tests() < 0 ||
bitfield_tests() < 0 ||
+ base64_tests() < 0 ||
+ common_tests() < 0 ||
int_array_tests() < 0)
ret = -1;
diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P
index a1d96fb5..6a5b0321 100644
--- a/wpa_supplicant/README-P2P
+++ b/wpa_supplicant/README-P2P
@@ -73,7 +73,7 @@ Device Discovery
p2p_find [timeout in seconds] [type=<social|progressive>] \
[dev_id=<addr>] [dev_type=<device type>] \
- [delay=<search delay in ms>] [seek=<service name>]
+ [delay=<search delay in ms>] [seek=<service name>] [freq=<MHz>]
The default behavior is to run a single full scan in the beginning and
then scan only social channels. type=social will scan only social
@@ -81,7 +81,9 @@ channels, i.e., it skips the initial full scan. type=progressive is
like the default behavior, but it will scan through all the channels
progressively one channel at the time in the Search state rounds. This
will help in finding new groups or groups missed during the initial
-full scan.
+full scan. When the type parameter is not included (i.e., full scan), the
+optional freq parameter can be used to override the first scan to use only
+the specified channel after which only social channels are scanned.
The optional dev_id option can be used to specify a single P2P peer to
search for. The optional delay parameter can be used to request an extra
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index f2c60e7f..ea5b2b4d 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -26,6 +26,7 @@
#include "ap/ieee802_1x.h"
#include "ap/wps_hostapd.h"
#include "ap/ctrl_iface_ap.h"
+#include "ap/dfs.h"
#include "wps/wps.h"
#include "common/ieee802_11_defs.h"
#include "config_ssid.h"
@@ -165,6 +166,13 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
+ if (ieee80211_is_dfs(ssid->frequency) && wpa_s->conf->country[0]) {
+ conf->ieee80211h = 1;
+ conf->ieee80211d = 1;
+ conf->country[0] = wpa_s->conf->country[0];
+ conf->country[1] = wpa_s->conf->country[1];
+ }
+
#ifdef CONFIG_P2P
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
(ssid->mode == WPAS_MODE_P2P_GO ||
@@ -566,6 +574,9 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
else
params.uapsd = -1;
+ if (ieee80211_is_dfs(params.freq.freq))
+ params.freq.freq = 0; /* set channel after CAC */
+
if (wpa_drv_associate(wpa_s, &params) < 0) {
wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
return -1;
@@ -1260,3 +1271,66 @@ int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s)
hapd = wpa_s->ap_iface->bss[0];
return hostapd_ctrl_iface_stop_ap(hapd);
}
+
+
+#ifdef NEED_AP_MLME
+void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+ if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ return;
+ wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
+ hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq,
+ radar->ht_enabled, radar->chan_offset,
+ radar->chan_width,
+ radar->cf1, radar->cf2);
+}
+
+
+void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+ if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ return;
+ wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq);
+ hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq,
+ radar->ht_enabled, radar->chan_offset,
+ radar->chan_width, radar->cf1, radar->cf2);
+}
+
+
+void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+ if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ return;
+ wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
+ hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq,
+ radar->ht_enabled, radar->chan_offset,
+ radar->chan_width, radar->cf1, radar->cf2);
+}
+
+
+void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+ if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ return;
+ wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
+ hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq,
+ radar->ht_enabled, radar->chan_offset,
+ radar->chan_width, radar->cf1, radar->cf2);
+}
+
+
+void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar)
+{
+ if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
+ return;
+ wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
+ hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq,
+ radar->ht_enabled, radar->chan_offset,
+ radar->chan_width, radar->cf1, radar->cf2);
+}
+#endif /* NEED_AP_MLME */
diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h
index 6a118342..3f4151d8 100644
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -82,4 +82,15 @@ void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s);
+void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
+ struct dfs_event *radar);
+
#endif /* AP_H */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index ec198b29..b4aefb65 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -209,6 +209,7 @@ static int set_disallow_aps(struct wpa_supplicant *wpa_s, char *val)
wpa_s->sme.prev_bssid_set = 0;
#endif /* CONFIG_SME */
wpa_s->reassociate = 1;
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -2835,6 +2836,7 @@ static int wpa_supplicant_ctrl_iface_remove_network(
#endif /* CONFIG_SME */
wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
}
@@ -2881,6 +2883,7 @@ static int wpa_supplicant_ctrl_iface_remove_network(
wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
}
@@ -4508,8 +4511,9 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
u8 dev_type[WPS_DEV_TYPE_LEN], *_dev_type = NULL;
char *pos;
unsigned int search_delay;
- const char *seek[P2P_MAX_QUERY_HASH + 1];
+ const char *_seek[P2P_MAX_QUERY_HASH + 1], **seek = NULL;
u8 seek_count = 0;
+ int freq = 0;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_dbg(wpa_s, MSG_INFO,
@@ -4550,27 +4554,28 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd)
char *term;
term = os_strchr(pos + 1, ' ');
- seek[seek_count++] = pos + 6;
+ _seek[seek_count++] = pos + 6;
+ seek = _seek;
pos = os_strstr(pos + 6, " seek=");
if (term)
*term = '\0';
}
-
- if (!seek_count)
- return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL,
- _dev_type, _dev_id,
- search_delay, 0, NULL);
-
if (seek_count > P2P_MAX_QUERY_HASH) {
seek[0] = NULL;
- return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL,
- _dev_type, _dev_id,
- search_delay, 1, seek);
+ seek_count = 1;
+ }
+
+ pos = os_strstr(cmd, "freq=");
+ if (pos) {
+ pos += 5;
+ freq = atoi(pos);
+ if (freq <= 0)
+ return -1;
}
return wpas_p2p_find(wpa_s, timeout, type, _dev_type != NULL, _dev_type,
- _dev_id, search_delay, seek_count, seek);
+ _dev_id, search_delay, seek_count, seek, freq);
}
@@ -4739,6 +4744,14 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
int pd;
int ht40, vht;
+ if (!wpa_s->global->p2p_init_wpa_s)
+ return -1;
+ if (wpa_s->global->p2p_init_wpa_s != wpa_s) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Direct P2P_CONNECT command to %s",
+ wpa_s->global->p2p_init_wpa_s->ifname);
+ wpa_s = wpa_s->global->p2p_init_wpa_s;
+ }
+
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
* [persistent|persistent=<network id>]
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
@@ -6618,6 +6631,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_supplicant_stop_countermeasures(wpa_s, NULL);
wpa_s->no_keep_alive = 0;
+ wpa_s->own_disconnect_req = 0;
os_free(wpa_s->disallow_aps_bssid);
wpa_s->disallow_aps_bssid = NULL;
@@ -8534,7 +8548,7 @@ static int wpa_supplicant_global_iface_add(struct wpa_global *global,
if (wpa_supplicant_get_iface(global, iface.ifname))
return -1;
- return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
+ return wpa_supplicant_add_iface(global, &iface, NULL) ? 0 : -1;
}
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index e7c2dd88..f2e62ca9 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -599,7 +599,7 @@ DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
iface.confname = confname;
iface.bridge_ifname = bridge_ifname;
/* Otherwise, have wpa_supplicant attach to it. */
- wpa_s = wpa_supplicant_add_iface(global, &iface);
+ wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
if (wpa_s) {
const char *path = wpa_s->dbus_new_path;
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index 24822bfd..0eff7638 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -131,7 +131,7 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message,
wpa_s = wpa_s->p2p_dev;
wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types,
- NULL, 0, 0, NULL);
+ NULL, 0, 0, NULL, 0);
os_free(req_dev_types);
return reply;
diff --git a/wpa_supplicant/dbus/dbus_old_handlers.c b/wpa_supplicant/dbus/dbus_old_handlers.c
index 955ea782..773ee8b4 100644
--- a/wpa_supplicant/dbus/dbus_old_handlers.c
+++ b/wpa_supplicant/dbus/dbus_old_handlers.c
@@ -165,7 +165,7 @@ DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
iface.confname = confname;
iface.bridge_ifname = bridge_ifname;
/* Otherwise, have wpa_supplicant attach to it. */
- wpa_s = wpa_supplicant_add_iface(global, &iface);
+ wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
if (wpa_s) {
const char *path = wpa_s->dbus_path;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 1c46d35d..94be68f3 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1421,6 +1421,9 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
struct wpa_bss *selected;
struct wpa_ssid *ssid = NULL;
+ if (wpa_s->p2p_mgmt)
+ return 0; /* no normal connection on p2p_mgmt interface */
+
selected = wpa_supplicant_pick_network(wpa_s, &ssid);
if (selected) {
@@ -2672,6 +2675,9 @@ static void wpas_event_disconnect(struct wpa_supplicant *wpa_s, const u8 *addr,
}
#endif /* CONFIG_AP */
+ if (!locally_generated)
+ wpa_s->own_disconnect_req = 0;
+
wpa_supplicant_event_disassoc(wpa_s, reason_code, locally_generated);
if (((reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
@@ -3301,6 +3307,29 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->ch_switch.cf1,
data->ch_switch.cf2);
break;
+#ifdef NEED_AP_MLME
+ case EVENT_DFS_RADAR_DETECTED:
+ if (data)
+ wpas_event_dfs_radar_detected(wpa_s, &data->dfs_event);
+ break;
+ case EVENT_DFS_CAC_STARTED:
+ if (data)
+ wpas_event_dfs_cac_started(wpa_s, &data->dfs_event);
+ break;
+ case EVENT_DFS_CAC_FINISHED:
+ if (data)
+ wpas_event_dfs_cac_finished(wpa_s, &data->dfs_event);
+ break;
+ case EVENT_DFS_CAC_ABORTED:
+ if (data)
+ wpas_event_dfs_cac_aborted(wpa_s, &data->dfs_event);
+ break;
+ case EVENT_DFS_NOP_FINISHED:
+ if (data)
+ wpas_event_dfs_cac_nop_finished(wpa_s,
+ &data->dfs_event);
+ break;
+#endif /* NEED_AP_MLME */
#endif /* CONFIG_AP */
case EVENT_RX_MGMT: {
u16 fc, stype;
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 90b29915..4a396654 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -77,6 +77,7 @@ static void interworking_reconnect(struct wpa_supplicant *wpa_s)
if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
}
@@ -915,6 +916,7 @@ static void remove_duplicate_network(struct wpa_supplicant *wpa_s,
if (ssid == wpa_s->current_ssid) {
wpa_sm_set_config(wpa_s->wpa, NULL);
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
}
@@ -2489,6 +2491,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
wpa_msg(wpa_s, MSG_INFO, INTERWORKING_NO_MATCH "No network "
"with matching credentials found");
+ if (wpa_s->wpa_state == WPA_SCANNING)
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
}
if (selected) {
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index 13e97694..22827479 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -322,7 +322,7 @@ int main(int argc, char *argv[])
exitcode = -1;
break;
}
- wpa_s = wpa_supplicant_add_iface(global, &ifaces[i]);
+ wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
if (wpa_s == NULL) {
exitcode = -1;
break;
diff --git a/wpa_supplicant/main_none.c b/wpa_supplicant/main_none.c
index 010c30a3..4d3caf2a 100644
--- a/wpa_supplicant/main_none.c
+++ b/wpa_supplicant/main_none.c
@@ -28,7 +28,7 @@ int main(int argc, char *argv[])
memset(&iface, 0, sizeof(iface));
/* TODO: set interface parameters */
- if (wpa_supplicant_add_iface(global, &iface) == NULL)
+ if (wpa_supplicant_add_iface(global, &iface, NULL) == NULL)
exitcode = -1;
if (exitcode == 0)
diff --git a/wpa_supplicant/main_winmain.c b/wpa_supplicant/main_winmain.c
index 93a68f17..e1dded0c 100644
--- a/wpa_supplicant/main_winmain.c
+++ b/wpa_supplicant/main_winmain.c
@@ -61,7 +61,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
exitcode = -1;
break;
}
- if (wpa_supplicant_add_iface(global, &ifaces[i]) == NULL)
+ if (wpa_supplicant_add_iface(global, &ifaces[i], NULL) == NULL)
exitcode = -1;
}
diff --git a/wpa_supplicant/main_winsvc.c b/wpa_supplicant/main_winsvc.c
index 0b7d5ce0..9950aa99 100644
--- a/wpa_supplicant/main_winsvc.c
+++ b/wpa_supplicant/main_winsvc.c
@@ -119,7 +119,7 @@ static int read_interface(struct wpa_global *global, HKEY _hk,
RegCloseKey(hk);
- if (wpa_supplicant_add_iface(global, &iface) == NULL) {
+ if (wpa_supplicant_add_iface(global, &iface, NULL) == NULL) {
if (skip_on_error)
wpa_printf(MSG_DEBUG, "Skipped interface '%s' due to "
"initialization failure", iface.ifname);
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 32506b67..cf3676c2 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -527,7 +527,7 @@ int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
iface.driver_param = wpa_s->conf->driver_param;
iface.ctrl_interface = wpa_s->conf->ctrl_interface;
- mesh_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
+ mesh_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s);
if (!mesh_wpa_s) {
wpa_printf(MSG_ERROR,
"mesh: Failed to create new wpa_supplicant interface");
@@ -535,6 +535,5 @@ int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
return -1;
}
mesh_wpa_s->mesh_if_created = 1;
- mesh_wpa_s->parent = wpa_s;
return 0;
}
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 5e6646ed..b200ca01 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -22,6 +22,7 @@
#include "ap/ap_drv_ops.h"
#include "ap/wps_hostapd.h"
#include "ap/p2p_hostapd.h"
+#include "ap/dfs.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "rsn_supp/wpa.h"
#include "wpa_supplicant_i.h"
@@ -377,6 +378,13 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
break;
case P2P_SCAN_FULL:
break;
+ case P2P_SCAN_SPECIFIC:
+ params->freqs = os_calloc(2, sizeof(int));
+ if (params->freqs == NULL)
+ goto fail;
+ params->freqs[0] = freq;
+ params->freqs[1] = 0;
+ break;
case P2P_SCAN_SOCIAL_PLUS_ONE:
params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 2,
sizeof(int));
@@ -1983,14 +1991,13 @@ wpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go)
else
iface.ctrl_interface = wpa_s->conf->ctrl_interface;
iface.driver_param = wpa_s->conf->driver_param;
- group_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
+ group_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s);
if (group_wpa_s == NULL) {
wpa_printf(MSG_ERROR, "P2P: Failed to create new "
"wpa_supplicant interface");
return NULL;
}
wpa_s->pending_interface_name[0] = '\0';
- group_wpa_s->parent = wpa_s;
group_wpa_s->p2p_group_interface = go ? P2P_GROUP_INTERFACE_GO :
P2P_GROUP_INTERFACE_CLIENT;
wpa_s->global->p2p_group_formation = group_wpa_s;
@@ -4662,12 +4669,11 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s,
}
iface.conf_p2p_dev = NULL;
- p2pdev_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface);
+ p2pdev_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s);
if (!p2pdev_wpa_s) {
wpa_printf(MSG_DEBUG, "P2P: Failed to add P2P Device interface");
return -1;
}
- p2pdev_wpa_s->parent = wpa_s;
wpa_s->p2p_dev = p2pdev_wpa_s;
wpa_s->pending_interface_name[0] = '\0';
@@ -5922,11 +5928,22 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
else
ret = p2p_supported_freq_cli(wpa_s->global->p2p, freq);
if (!ret) {
- wpa_printf(MSG_DEBUG, "P2P: The forced channel "
- "(%u MHz) is not supported for P2P uses",
- freq);
- res = -3;
- goto exit_free;
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+ ieee80211_is_dfs(freq)) {
+ /*
+ * If freq is a DFS channel and DFS is offloaded
+ * to the driver, allow P2P GO to use it.
+ */
+ wpa_printf(MSG_DEBUG,
+ "P2P: The forced channel for GO (%u MHz) is DFS, and DFS is offloaded to the driver",
+ freq);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "P2P: The forced channel (%u MHz) is not supported for P2P uses",
+ freq);
+ res = -3;
+ goto exit_free;
+ }
}
for (i = 0; i < num; i++) {
@@ -6297,6 +6314,17 @@ static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
}
if (freq > 0 && !p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+ ieee80211_is_dfs(freq)) {
+ /*
+ * If freq is a DFS channel and DFS is offloaded to the
+ * driver, allow P2P GO to use it.
+ */
+ wpa_printf(MSG_DEBUG, "P2P: "
+ "%s: The forced channel for GO (%u MHz) is DFS, and DFS is offloaded",
+ __func__, freq);
+ return freq;
+ }
wpa_printf(MSG_DEBUG, "P2P: The forced channel for GO "
"(%u MHz) is not supported for P2P uses",
freq);
@@ -6334,6 +6362,24 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s,
goto out;
}
+ /* try all channels in operating class 115 */
+ for (i = 0; i < 4; i++) {
+ params->freq = 5180 + i * 20;
+ if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
+ freq_included(channels, params->freq) &&
+ p2p_supported_freq(wpa_s->global->p2p, params->freq))
+ goto out;
+ }
+
+ /* try all channels in operating class 124 */
+ for (i = 0; i < 4; i++) {
+ params->freq = 5745 + i * 20;
+ if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
+ freq_included(channels, params->freq) &&
+ p2p_supported_freq(wpa_s->global->p2p, params->freq))
+ goto out;
+ }
+
/* try social channel class 180 channel 2 */
params->freq = 58320 + 1 * 2160;
if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
@@ -6350,7 +6396,7 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s,
goto out;
}
- wpa_printf(MSG_DEBUG, "P2P: No 2.4 and 60 GHz channel allowed");
+ wpa_printf(MSG_DEBUG, "P2P: No 2.4, 5, or 60 GHz channel allowed");
return -1;
out:
wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference known)",
@@ -6560,10 +6606,21 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
return -1;
if (params.freq &&
!p2p_supported_freq_go(wpa_s->global->p2p, params.freq)) {
- wpa_printf(MSG_DEBUG, "P2P: The selected channel for GO "
- "(%u MHz) is not supported for P2P uses",
- params.freq);
- return -1;
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+ ieee80211_is_dfs(params.freq)) {
+ /*
+ * If freq is a DFS channel and DFS is offloaded to the
+ * driver, allow P2P GO to use it.
+ */
+ wpa_printf(MSG_DEBUG,
+ "P2P: %s: The forced channel for GO (%u MHz) is DFS, and DFS is offloaded to driver",
+ __func__, params.freq);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "P2P: The selected channel for GO (%u MHz) is not supported for P2P uses",
+ params.freq);
+ return -1;
+ }
}
p2p_go_params(wpa_s->global->p2p, &params);
params.persistent_group = persistent_group;
@@ -6985,7 +7042,7 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_cnt, const char **seek_string)
+ u8 seek_cnt, const char **seek_string, int freq)
{
wpas_p2p_clear_pending_action_tx(wpa_s);
wpa_s->p2p_long_listen = 0;
@@ -6998,7 +7055,7 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
return p2p_find(wpa_s->global->p2p, timeout, type,
num_req_dev_types, req_dev_types, dev_id,
- search_delay, seek_cnt, seek_string);
+ search_delay, seek_cnt, seek_string, freq);
}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 1cf15736..b7861786 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -59,7 +59,7 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const u8 *req_dev_types,
const u8 *dev_id, unsigned int search_delay,
- u8 seek_cnt, const char **seek_string);
+ u8 seek_cnt, const char **seek_string, int freq);
void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s);
int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout);
int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s, unsigned int timeout);
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 30a66572..805891a8 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -96,6 +96,10 @@ int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s)
{
struct wpa_ssid *ssid = wpa_s->conf->ssid;
int count = 0, disabled = 0;
+
+ if (wpa_s->p2p_mgmt)
+ return 0; /* no normal network profiles on p2p_mgmt interface */
+
while (ssid) {
if (!wpas_network_disabled(wpa_s, ssid))
count++;
@@ -627,6 +631,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
struct wpa_driver_scan_params params;
struct wpa_driver_scan_params *scan_params;
size_t max_ssids;
+ int connect_without_scan = 0;
if (wpa_s->pno || wpa_s->pno_sched_pending) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress");
@@ -674,8 +679,20 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
return;
}
+ ssid = NULL;
+ if (wpa_s->scan_req != MANUAL_SCAN_REQ &&
+ wpa_s->connect_without_scan) {
+ connect_without_scan = 1;
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (ssid == wpa_s->connect_without_scan)
+ break;
+ }
+ }
+
p2p_in_prog = wpas_p2p_in_progress(wpa_s);
- if (p2p_in_prog && p2p_in_prog != 2) {
+ if (p2p_in_prog && p2p_in_prog != 2 &&
+ (!ssid ||
+ (ssid->mode != WPAS_MODE_AP && ssid->mode != WPAS_MODE_P2P_GO))) {
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;
@@ -692,6 +709,16 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
wpa_s->last_scan_req = wpa_s->scan_req;
wpa_s->scan_req = NORMAL_SCAN_REQ;
+ if (connect_without_scan) {
+ wpa_s->connect_without_scan = NULL;
+ if (ssid) {
+ wpa_printf(MSG_DEBUG, "Start a pre-selected network "
+ "without scan step");
+ wpa_supplicant_associate(wpa_s, NULL, ssid);
+ return;
+ }
+ }
+
os_memset(&params, 0, sizeof(params));
wpa_s->scan_prev_wpa_state = wpa_s->wpa_state;
@@ -707,21 +734,6 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
goto scan;
}
- if (wpa_s->last_scan_req != MANUAL_SCAN_REQ &&
- wpa_s->connect_without_scan) {
- for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
- if (ssid == wpa_s->connect_without_scan)
- break;
- }
- wpa_s->connect_without_scan = NULL;
- if (ssid) {
- wpa_printf(MSG_DEBUG, "Start a pre-selected network "
- "without scan step");
- wpa_supplicant_associate(wpa_s, NULL, ssid);
- return;
- }
- }
-
#ifdef CONFIG_P2P
if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) &&
wpa_s->go_params && !wpa_s->conf->passive_scan) {
@@ -1066,8 +1078,17 @@ void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec)
*/
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
{
- int res = eloop_deplete_timeout(sec, usec, wpa_supplicant_scan, wpa_s,
- NULL);
+ int res;
+
+ if (wpa_s->p2p_mgmt) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Ignore scan request (%d.%06d sec) on p2p_mgmt interface",
+ sec, usec);
+ return;
+ }
+
+ 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);
@@ -1861,7 +1882,7 @@ static unsigned int max_ht40_rate(int snr)
return 81000; /* HT40 MCS4 */
if (snr < 22)
return 108000; /* HT40 MCS5 */
- if (snr < 22)
+ if (snr < 24)
return 121500; /* HT40 MCS6 */
return 135000; /* HT40 MCS7 */
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 05b785ea..19fb8900 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -870,6 +870,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
eapol_sm_invalidate_cached_session(wpa_s->eapol);
if (wpa_s->current_ssid) {
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
}
@@ -1865,7 +1866,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
vht_freq.vht_enabled,
freq->sec_channel_offset,
VHT_CHANWIDTH_80MHZ,
- vht80[i] + 6, 0, 0) != 0)
+ vht80[j] + 6, 0, 0) != 0)
return;
*freq = vht_freq;
@@ -2585,6 +2586,7 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
int disconnected = 0;
if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
disconnected = 1;
@@ -3228,7 +3230,8 @@ static int wpa_supplicant_daemon(const char *pid_file)
}
-static struct wpa_supplicant * wpa_supplicant_alloc(void)
+static struct wpa_supplicant *
+wpa_supplicant_alloc(struct wpa_supplicant *parent)
{
struct wpa_supplicant *wpa_s;
@@ -3238,7 +3241,7 @@ static struct wpa_supplicant * wpa_supplicant_alloc(void)
wpa_s->scan_req = INITIAL_SCAN_REQ;
wpa_s->scan_interval = 5;
wpa_s->new_connection = 1;
- wpa_s->parent = wpa_s;
+ wpa_s->parent = parent ? parent : wpa_s;
wpa_s->sched_scanning = 0;
return wpa_s;
@@ -4292,6 +4295,7 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
* wpa_supplicant_add_iface - Add a new network interface
* @global: Pointer to global data from wpa_supplicant_init()
* @iface: Interface configuration options
+ * @parent: Parent interface or %NULL to assign new interface as parent
* Returns: Pointer to the created interface or %NULL on failure
*
* This function is used to add new network interfaces for %wpa_supplicant.
@@ -4301,7 +4305,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
* e.g., when a hotplug network adapter is inserted.
*/
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
- struct wpa_interface *iface)
+ struct wpa_interface *iface,
+ struct wpa_supplicant *parent)
{
struct wpa_supplicant *wpa_s;
struct wpa_interface t_iface;
@@ -4310,7 +4315,7 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
if (global == NULL || iface == NULL)
return NULL;
- wpa_s = wpa_supplicant_alloc();
+ wpa_s = wpa_supplicant_alloc(parent);
if (wpa_s == NULL)
return NULL;
@@ -4792,11 +4797,17 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
*/
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
+ /*
+ * There is no point in blacklisting the AP if this event is
+ * generated based on local request to disconnect.
+ */
+ if (wpa_s->own_disconnect_req) {
+ wpa_s->own_disconnect_req = 0;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Ignore connection failure due to local request to disconnect");
+ return;
+ }
if (wpa_s->disconnected) {
- /*
- * There is no point in blacklisting the AP if this event is
- * generated based on local request to disconnect.
- */
wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
"indication since interface has been put into "
"disconnected state");
@@ -4966,13 +4977,16 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
int i;
unsigned int drv_enc;
+ if (wpa_s->p2p_mgmt)
+ return 1; /* no normal network profiles on p2p_mgmt interface */
+
if (ssid == NULL)
return 1;
if (ssid->disabled)
return 1;
- if (wpa_s && wpa_s->drv_capa_known)
+ if (wpa_s->drv_capa_known)
drv_enc = wpa_s->drv_enc;
else
drv_enc = (unsigned int) -1;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 7949a018..26ff216b 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -915,6 +915,7 @@ struct wpa_supplicant {
unsigned int ext_eapol_frame_io:1;
unsigned int wmm_ac_supported:1;
unsigned int ext_work_in_progress:1;
+ unsigned int own_disconnect_req:1;
#define MAC_ADDR_RAND_SCAN BIT(0)
#define MAC_ADDR_RAND_SCHED_SCAN BIT(1)
@@ -1034,7 +1035,8 @@ void free_hw_features(struct wpa_supplicant *wpa_s);
void wpa_show_license(void);
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
- struct wpa_interface *iface);
+ struct wpa_interface *iface,
+ struct wpa_supplicant *parent);
int wpa_supplicant_remove_iface(struct wpa_global *global,
struct wpa_supplicant *wpa_s,
int terminate);
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 99e73512..1bb82ba7 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -842,6 +842,25 @@ static void wpa_supplicant_eap_param_needed(void *ctx,
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
+#ifdef CONFIG_EAP_PROXY
+static void wpa_supplicant_eap_proxy_cb(void *ctx)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ size_t len;
+
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol,
+ wpa_s->imsi, &len);
+ if (wpa_s->mnc_len > 0) {
+ wpa_s->imsi[len] = '\0';
+ wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
+ wpa_s->imsi, wpa_s->mnc_len);
+ } else {
+ wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
+ }
+}
+#endif /* CONFIG_EAP_PROXY */
+
+
static void wpa_supplicant_port_cb(void *ctx, int authorized)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -947,6 +966,9 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers;
ctx->wps = wpa_s->wps;
ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
+#ifdef CONFIG_EAP_PROXY
+ ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb;
+#endif /* CONFIG_EAP_PROXY */
ctx->port_cb = wpa_supplicant_port_cb;
ctx->cb = wpa_supplicant_eapol_cb;
ctx->cert_cb = wpa_supplicant_cert_cb;
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index b1266c62..eabe9865 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -113,6 +113,7 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - "
"try to associate with the received credential "
"(freq=%u)", freq);
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
if (disabled) {
@@ -160,6 +161,7 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
"for external credential processing");
wpas_clear_wps(wpa_s);
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
return 1;
@@ -913,6 +915,7 @@ static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
while (ssid) {
if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
if (ssid == wpa_s->current_ssid) {
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
}
@@ -1022,9 +1025,11 @@ static void wpas_wps_temp_disable(struct wpa_supplicant *wpa_s,
{
struct wpa_ssid *ssid;
- if (wpa_s->current_ssid)
+ if (wpa_s->current_ssid) {
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
/* Mark all other networks disabled and trigger reassociation */
ssid = wpa_s->conf->ssid;
@@ -1234,6 +1239,7 @@ int wpas_wps_cancel(struct wpa_supplicant *wpa_s)
} else if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
wpa_printf(MSG_DEBUG, "WPS: Cancel operation - "
"deauthenticate");
+ wpa_s->own_disconnect_req = 1;
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
wpas_clear_wps(wpa_s);