Accumulative patch from commit 6ea1f4135b72199988393f34dd7f5ad8040b7a42
6ea1f41 Try to set WPA-None key after IBSS-joined event
66562e9 Use cached driver capabilities instead of new fetch for each operation
55293aa TDLS: Do not overwrite the reason code in the Tear Down Request
4aa8186 Add a configration parameter for sched_scan interval
03565bc Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
f11b72c TDLS: Move AID=1 workaround into driver_nl80211.c
7853369 TDLS: Pass peer's AID information to kernel
55a2df4 HS 2.0: Include HS 2.0 Indication element only for HS 2.0 association
ad0685e edit: Fix history processing on running old command
9be3714 wpa_cli: Fetch the current BSSID list when starting interactive mode
69aa334 wpa_cli: Add BSSID tab completion for set bssid_filter
2156587 wpa_cli: Replace set command help with completion routine
f1fb042 wpa_cli: Allow space in the set command value
f5ffc34 wpa_supplicant: Allow global scan frequencies configuration
abfc3ad Synchronize build config comments for wpa_supplicant
a01e10d Android: Enable WPS ER and NFC support in the build
11e5a49 WPS: Do not use void* in arithmetic
0f105f9 HS 2.0: Move Probe Request Indication IE addition to proper place
8543ed8 WPA: Print pairwise EAPOL-Key flag as a bool
7af092a hostapd: Add Key MIC in group EAPOL-Key frames corruption test option
b691dcb nl80211: Fix max_remain_on_chan capability reading
41b1a76 P2P: Clone beacon_int when initializing new group interface
741ed9f WPS: Remove duplicate networks after WPS
Change-Id: I9a2a0cb2acf87dfd7548318d2bda5f342b815884
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0d97a21..7ecbc65 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -57,3 +57,5 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_cli_intermediates/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_supplicant_intermediates/*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/hostapd_intermediates/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/wpa_supplicant_intermediates/*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/hostapd_intermediates/*)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 21104d3..62136ca 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2893,6 +2893,7 @@
PARSE_TEST_PROBABILITY(ignore_auth_probability)
PARSE_TEST_PROBABILITY(ignore_assoc_probability)
PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
+ PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcmp(buf, "vendor_elements") == 0) {
struct wpabuf *elems;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 6a1c500..86015bf 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1540,6 +1540,9 @@
#
# Ignore reassociation requests with the given probability
#ignore_reassoc_probability=0.0
+#
+# Corrupt Key MIC in GTK rekey EAPOL-Key frames with the given probability
+#corrupt_gtk_rekey_mic_probability=0.0
##### Multiple BSSID support ##################################################
#
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 70b26a6..7ab86fc 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -168,6 +168,7 @@
conf->ignore_auth_probability = 0.0d;
conf->ignore_assoc_probability = 0.0d;
conf->ignore_reassoc_probability = 0.0d;
+ conf->corrupt_gtk_rekey_mic_probability = 0.0d;
#endif /* CONFIG_TESTING_OPTIONS */
return conf;
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index f9629a2..16134da 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -526,6 +526,7 @@
double ignore_auth_probability;
double ignore_assoc_probability;
double ignore_reassoc_probability;
+ double corrupt_gtk_rekey_mic_probability;
#endif /* CONFIG_TESTING_OPTIONS */
};
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 4f1f6fb..18ae86c 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1232,7 +1232,7 @@
else
version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
- pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
+ pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE);
wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d "
"ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d "
@@ -1347,6 +1347,16 @@
}
wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len,
key->key_mic);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (!pairwise &&
+ wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0d &&
+ drand48() <
+ wpa_auth->conf.corrupt_gtk_rekey_mic_probability) {
+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ "Corrupting group EAPOL-Key Key MIC");
+ key->key_mic[0]++;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
}
wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx,
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 465eec6..9126b90 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -160,6 +160,9 @@
#endif /* CONFIG_IEEE80211R */
int disable_gtk;
int ap_mlme;
+#ifdef CONFIG_TESTING_OPTIONS
+ double corrupt_gtk_rekey_mic_probability;
+#endif /* CONFIG_TESTING_OPTIONS */
};
typedef enum {
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index fdaaaff..e2be1ea 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -28,6 +28,7 @@
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
+ struct hostapd_config *iconf,
struct wpa_auth_config *wconf)
{
os_memset(wconf, 0, sizeof(*wconf));
@@ -74,6 +75,10 @@
#ifdef CONFIG_HS20
wconf->disable_gtk = conf->disable_dgaf;
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_TESTING_OPTIONS
+ wconf->corrupt_gtk_rekey_mic_probability =
+ iconf->corrupt_gtk_rekey_mic_probability;
+#endif /* CONFIG_TESTING_OPTIONS */
}
@@ -509,7 +514,7 @@
const u8 *wpa_ie;
size_t wpa_ie_len;
- hostapd_wpa_auth_conf(hapd->conf, &_conf);
+ hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
_conf.tx_status = 1;
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
@@ -583,7 +588,7 @@
void hostapd_reconfig_wpa(struct hostapd_data *hapd)
{
struct wpa_auth_config wpa_auth_conf;
- hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf);
+ hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &wpa_auth_conf);
wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
}
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 6125015..213f3c3 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2747,9 +2747,6 @@
static void wiphy_info_max_roc(struct wpa_driver_capa *capa,
struct nlattr *tb)
{
- /* default to 5000 since early versions of mac80211 don't set it */
- capa->max_remain_on_chan = 5000;
-
if (tb)
capa->max_remain_on_chan = nla_get_u32(tb);
}
@@ -2941,6 +2938,11 @@
"concurrent (driver advertised support)");
drv->capa.flags |= WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT;
}
+
+ /* default to 5000 since early versions of mac80211 don't set it */
+ if (!drv->capa.max_remain_on_chan)
+ drv->capa.max_remain_on_chan = 5000;
+
return 0;
nla_put_failure:
nlmsg_free(msg);
@@ -6092,8 +6094,18 @@
wpa_hexdump(MSG_DEBUG, " * supported rates", params->supp_rates,
params->supp_rates_len);
if (!params->set) {
- wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
- NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
+ if (params->aid) {
+ wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
+ NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
+ } else {
+ /*
+ * cfg80211 validates that AID is non-zero, so we have
+ * to make this a non-zero value for the TDLS case where
+ * a dummy STA entry is used for now.
+ */
+ wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)");
+ NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, 1);
+ }
wpa_printf(MSG_DEBUG, " * listen_interval=%u",
params->listen_interval);
NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 79da871..d1e48b5 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -639,6 +639,13 @@
* with the relevant Information Elements. This event is used to report
* received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
*
+ * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running
+ * a critical protocol that needs more reliability in the connection to
+ * complete.
+ *
+ * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
+ * return back to normal.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -798,6 +805,9 @@
NL80211_CMD_UPDATE_FT_IES,
NL80211_CMD_FT_EVENT,
+ NL80211_CMD_CRIT_PROTOCOL_START,
+ NL80211_CMD_CRIT_PROTOCOL_STOP,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1414,6 +1424,11 @@
* @NL80211_ATTR_IE_RIC: Resource Information Container Information
* Element
*
+ * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased
+ * reliability, see &enum nl80211_crit_proto_id (u16).
+ * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
+ * the connection should have increased reliability (u16).
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1709,6 +1724,9 @@
NL80211_ATTR_MDID,
NL80211_ATTR_IE_RIC,
+ NL80211_ATTR_CRIT_PROT_ID,
+ NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3682,4 +3700,25 @@
NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0,
};
+/**
+ * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers
+ *
+ * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified.
+ * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol.
+ * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol.
+ * @NL80211_CRIT_PROTO_APIPA: APIPA protocol.
+ * @NUM_NL80211_CRIT_PROTO: must be kept last.
+ */
+enum nl80211_crit_proto_id {
+ NL80211_CRIT_PROTO_UNSPEC,
+ NL80211_CRIT_PROTO_DHCP,
+ NL80211_CRIT_PROTO_EAPOL,
+ NL80211_CRIT_PROTO_APIPA,
+ /* add other protocols before this one */
+ NUM_NL80211_CRIT_PROTO
+};
+
+/* maximum duration for critical protocol measures */
+#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */
+
#endif /* __LINUX_NL80211_H */
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 069e22b..81e2a5c 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -127,6 +127,8 @@
u8 qos_info;
+ u16 aid;
+
u8 *ext_capab;
size_t ext_capab_len;
};
@@ -696,13 +698,8 @@
return -1;
pos = rbuf;
- if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) {
- if (reason_code != WLAN_REASON_DEAUTH_LEAVING) {
- /* Overwrite the reason code */
- reason_code = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
- }
+ if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
goto skip_ies;
- }
ftie = (struct wpa_tdls_ftie *) pos;
ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
@@ -1558,6 +1555,8 @@
peer->qos_info = kde.qosinfo;
+ peer->aid = kde.aid;
+
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
peer = wpa_tdls_add_peer(sm, src_addr, NULL);
@@ -1735,7 +1734,7 @@
skip_rsn_check:
/* add the peer to the driver as a "setup in progress" peer */
- wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0,
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
NULL, 0);
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
@@ -1777,7 +1776,8 @@
}
/* add supported rates, capabilities, and qos_info to the TDLS peer */
- if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
+ if (wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->aid,
+ peer->capability,
peer->supp_rates, peer->supp_rates_len,
peer->ht_capabilities,
peer->vht_capabilities,
@@ -1908,6 +1908,8 @@
peer->qos_info = kde.qosinfo;
+ peer->aid = kde.aid;
+
if (!wpa_tdls_get_privacy(sm)) {
peer->rsnie_p_len = 0;
peer->cipher = WPA_CIPHER_NONE;
@@ -2235,7 +2237,7 @@
peer->initiator = 1;
/* add the peer to the driver as a "setup in progress" peer */
- wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0,
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0,
NULL, 0);
if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index d4533a8..78dfb52 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -56,7 +56,7 @@
u8 action_code, u8 dialog_token,
u16 status_code, const u8 *buf, size_t len);
int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
- int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add,
+ int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid,
u16 capability, const u8 *supp_rates,
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 877e6de..0e0d373 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -282,7 +282,7 @@
static inline int
wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
- u16 capability, const u8 *supp_rates,
+ u16 aid, u16 capability, const u8 *supp_rates,
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
@@ -290,7 +290,7 @@
{
if (sm->ctx->tdls_peer_addset)
return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
- capability, supp_rates,
+ aid, capability, supp_rates,
supp_rates_len, ht_capab,
vht_capab, qosinfo,
ext_capab, ext_capab_len);
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 652197f..ba203e6 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -430,6 +430,9 @@
} else if (*pos == WLAN_EID_HT_CAP) {
ie->ht_capabilities = pos + 2;
ie->ht_capabilities_len = pos[1];
+ } else if (*pos == WLAN_EID_VHT_AID) {
+ if (pos[1] >= 2)
+ ie->aid = WPA_GET_LE16(pos + 2);
} else if (*pos == WLAN_EID_VHT_CAP) {
ie->vht_capabilities = pos + 2;
ie->vht_capabilities_len = pos[1];
diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h
index 82a5c08..2c78801 100644
--- a/src/rsn_supp/wpa_ie.h
+++ b/src/rsn_supp/wpa_ie.h
@@ -54,6 +54,7 @@
const u8 *vht_capabilities;
size_t vht_capabilities_len;
u8 qosinfo;
+ u16 aid;
};
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
diff --git a/src/utils/edit.c b/src/utils/edit.c
index b01e08d..177ecf4 100644
--- a/src/utils/edit.c
+++ b/src/utils/edit.c
@@ -345,7 +345,7 @@
static void process_cmd(void)
{
-
+ currbuf_valid = 0;
if (cmdbuf_len == 0) {
printf("\n%s> ", ps2 ? ps2 : "");
fflush(stdout);
diff --git a/src/wps/http_client.c b/src/wps/http_client.c
index c6d6c7f..0290013 100644
--- a/src/wps/http_client.c
+++ b/src/wps/http_client.c
@@ -92,7 +92,7 @@
(unsigned long) wpabuf_len(c->req),
(unsigned long) wpabuf_len(c->req) - c->req_pos);
- res = send(c->sd, wpabuf_head(c->req) + c->req_pos,
+ res = send(c->sd, wpabuf_head_u8(c->req) + c->req_pos,
wpabuf_len(c->req) - c->req_pos, 0);
if (res < 0) {
wpa_printf(MSG_DEBUG, "HTTP: Failed to send buffer: %s",
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index b86c4c7..331940c 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -176,7 +176,7 @@
CONFIG_EAP_LEAP=y
# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
-#CONFIG_EAP_AKA=y
+CONFIG_EAP_AKA=y
# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
# This requires CONFIG_EAP_AKA to be enabled, too.
@@ -201,10 +201,12 @@
# Enable WSC 2.0 support
CONFIG_WPS2=y
# Enable WPS external registrar functionality
-#CONFIG_WPS_ER=y
+CONFIG_WPS_ER=y
# Disable credentials for an open network by default when acting as a WPS
# registrar.
#CONFIG_WPS_REG_DISABLE_OPEN=y
+# Enable WPS support with NFC config method
+CONFIG_WPS_NFC=y
# EAP-IKEv2
#CONFIG_EAP_IKEV2=y
@@ -234,6 +236,7 @@
# unix = UNIX domain sockets (default for Linux/*BSD)
# udp = UDP sockets using localhost (127.0.0.1)
# named_pipe = Windows Named Pipe (default for Windows)
+# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
# y = use default (backwards compatibility)
# If this option is commented out, control interface is not included in the
# build.
@@ -325,9 +328,7 @@
# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
CONFIG_PEERKEY=y
-# IEEE 802.11w (management frame protection)
-# This version is an experimental implementation based on IEEE 802.11w/D1.0
-# draft and is subject to change since the standard has not yet been finalized.
+# IEEE 802.11w (management frame protection), also known as PMF
# Driver support is also needed for IEEE 802.11w.
#CONFIG_IEEE80211W=y
@@ -486,6 +487,10 @@
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
CONFIG_IEEE80211N=y
+# Wireless Network Management (IEEE Std 802.11v-2011)
+# Note: This is experimental and not complete implementation.
+#CONFIG_WNM=y
+
# Interworking (IEEE 802.11u)
# This can be used to enable functionality to improve interworking with
# external networks (GAS/ANQP to learn more about the networks and network
@@ -498,12 +503,39 @@
# Disable roaming in wpa_supplicant
CONFIG_NO_ROAMING=y
-# Enable TDLS
-CONFIG_TDLS=y
-
-# Enable P2P
-CONFIG_P2P=y
+# AP mode operations with wpa_supplicant
+# This can be used for controlling AP mode operations with wpa_supplicant. It
+# should be noted that this is mainly aimed at simple cases like
+# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
+# external RADIUS server can be supported with hostapd.
CONFIG_AP=y
+# P2P (Wi-Fi Direct)
+# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
+# more information on P2P operations.
+CONFIG_P2P=y
+
+CONFIG_TDLS=y
+
#Enable Wifi Display
CONFIG_WIFI_DISPLAY=y
+
+# Autoscan
+# This can be used to enable automatic scan support in wpa_supplicant.
+# See wpa_supplicant.conf for more information on autoscan usage.
+#
+# Enabling directly a module will enable autoscan support.
+# For exponential module:
+#CONFIG_AUTOSCAN_EXPONENTIAL=y
+# For periodic module:
+#CONFIG_AUTOSCAN_PERIODIC=y
+
+# Password (and passphrase, etc.) backend for external storage
+# These optional mechanisms can be used to add support for storing passwords
+# and other secrets in external (to wpa_supplicant) location. This allows, for
+# example, operating system specific key storage to be used
+#
+# External password backend for testing purposes (developer use)
+#CONFIG_EXT_PASSWORD_TEST=y
+
+include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 2de7845..b25e0f6 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1826,6 +1826,7 @@
os_free(config->pssid);
os_free(config->p2p_pref_chan);
os_free(config->autoscan);
+ os_free(config->freq_list);
wpabuf_free(config->wps_nfc_dh_pubkey);
wpabuf_free(config->wps_nfc_dh_privkey);
wpabuf_free(config->wps_nfc_dev_pw);
@@ -2733,6 +2734,21 @@
}
+static int wpa_config_process_freq_list(const struct global_parse_data *data,
+ struct wpa_config *config, int line,
+ const char *value)
+{
+ int *freqs;
+
+ freqs = wpa_config_parse_int_array(value);
+ if (freqs == NULL)
+ return -1;
+ os_free(config->freq_list);
+ config->freq_list = freqs;
+ return 0;
+}
+
+
static int wpa_config_process_country(const struct global_parse_data *data,
struct wpa_config *config, int line,
const char *pos)
@@ -3088,6 +3104,8 @@
{ INT(beacon_int), 0 },
{ FUNC(ap_vendor_elements), 0 },
{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
+ { FUNC(freq_list), 0 },
+ { INT(sched_scan_interval), 0 },
};
#undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 4a175ce..a1a5239 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -645,6 +645,14 @@
unsigned int max_num_sta;
/**
+ * freq_list - Array of allowed scan frequencies or %NULL for all
+ *
+ * This is an optional zero-terminated array of frequencies in
+ * megahertz (MHz) to allow for narrowing scanning range.
+ */
+ int *freq_list;
+
+ /**
* changed_parameters - Bitmap of changed parameters since last update
*/
unsigned int changed_parameters;
@@ -854,6 +862,11 @@
* allowing it to update the internal BSS table.
*/
int ignore_old_scan_res;
+
+ /**
+ * sched_scan_interval - schedule scan interval
+ */
+ unsigned int sched_scan_interval;
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 8604ae8..8ff4285 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1015,6 +1015,20 @@
if (config->ignore_old_scan_res)
fprintf(f, "ignore_old_scan_res=%d\n",
config->ignore_old_scan_res);
+
+ if (config->freq_list && config->freq_list[0]) {
+ int i;
+ fprintf(f, "freq_list=");
+ for (i = 0; config->freq_list[i]; i++) {
+ fprintf(f, "%s%u", i > 0 ? " " : "",
+ config->freq_list[i]);
+ }
+ fprintf(f, "\n");
+ }
+
+ if (config->sched_scan_interval)
+ fprintf(f, "sched_scan_interval=%u\n",
+ config->sched_scan_interval);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index e867bae..5663a5f 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -423,6 +423,10 @@
# same file, e.g., using trace-cmd.
#CONFIG_DEBUG_LINUX_TRACING=y
+# Add support for writing debug log to Android logcat instead of standard
+# output
+#CONFIG_ANDROID_LOG=y
+
# Enable privilege separation (see README 'Privilege separation' for details)
#CONFIG_PRIVSEP=y
@@ -495,6 +499,9 @@
# Hotspot 2.0
#CONFIG_HS20=y
+# Disable roaming in wpa_supplicant
+#CONFIG_NO_ROAMING=y
+
# AP mode operations with wpa_supplicant
# This can be used for controlling AP mode operations with wpa_supplicant. It
# should be noted that this is mainly aimed at simple cases like
@@ -507,6 +514,9 @@
# more information on P2P operations.
#CONFIG_P2P=y
+# Enable TDLS support
+#CONFIG_TDLS=y
+
# Autoscan
# This can be used to enable automatic scan support in wpa_supplicant.
# See wpa_supplicant.conf for more information on autoscan usage.
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 650221a..cf2800e 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1679,7 +1679,6 @@
{
u8 bssid[ETH_ALEN];
int ft_completed;
- struct wpa_driver_capa capa;
#ifdef CONFIG_AP
if (wpa_s->ap_iface) {
@@ -1785,6 +1784,16 @@
wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE ||
(wpa_s->current_ssid &&
wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) {
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE &&
+ (wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
+ /*
+ * Set the key after having received joined-IBSS event
+ * from the driver.
+ */
+ wpa_supplicant_set_wpa_none_key(wpa_s,
+ wpa_s->current_ssid);
+ }
wpa_supplicant_cancel_auth_timeout(wpa_s);
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
} else if (!ft_completed) {
@@ -1845,8 +1854,8 @@
if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
- wpa_s->current_ssid && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
- capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE) {
+ wpa_s->current_ssid &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
/* Set static WEP keys again */
wpa_set_wep_keys(wpa_s, wpa_s->current_ssid);
}
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 1404241..4048cf7 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -33,6 +33,35 @@
}
+int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ struct wpa_bss *bss)
+{
+ if (!wpa_s->conf->hs20 || !ssid)
+ return 0;
+
+ if (ssid->parent_cred)
+ return 1;
+
+ if (bss && !wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE))
+ return 0;
+
+ /*
+ * This may catch some non-Hotspot 2.0 cases, but it is safer to do that
+ * than cause Hotspot 2.0 connections without indication element getting
+ * added. Non-Hotspot 2.0 APs should ignore the unknown vendor element.
+ */
+
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X))
+ return 0;
+ if (!(ssid->pairwise_cipher & WPA_CIPHER_CCMP))
+ return 0;
+ if (ssid->proto != WPA_PROTO_RSN)
+ return 0;
+
+ return 1;
+}
+
+
struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
size_t payload_len)
{
diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h
index 6eb3926..1c8481b 100644
--- a/wpa_supplicant/hs20_supplicant.h
+++ b/wpa_supplicant/hs20_supplicant.h
@@ -16,5 +16,7 @@
size_t payload_len);
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *data, size_t slen);
+int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ struct wpa_bss *bss);
#endif /* HS20_SUPPLICANT_H */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 5fcaf29..f1e15ff 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -1003,6 +1003,7 @@
d->max_num_sta = s->max_num_sta;
d->pbc_in_m1 = s->pbc_in_m1;
d->ignore_old_scan_res = s->ignore_old_scan_res;
+ d->beacon_int = s->beacon_int;
}
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index db73a18..02c11b0 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -453,6 +453,11 @@
#endif /* CONFIG_WPS */
+#ifdef CONFIG_HS20
+ if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
+ wpas_hs20_add_indication(extra_ie);
+#endif /* CONFIG_HS20 */
+
return extra_ie;
}
@@ -749,11 +754,6 @@
wpa_supplicant_optimize_freqs(wpa_s, ¶ms);
extra_ie = wpa_supplicant_extra_ies(wpa_s);
-#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0)
- wpas_hs20_add_indication(extra_ie);
-#endif /* CONFIG_HS20 */
-
if (params.freqs == NULL && wpa_s->next_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously "
"generated frequency list");
@@ -762,6 +762,13 @@
os_free(wpa_s->next_scan_freqs);
wpa_s->next_scan_freqs = NULL;
+ /* See if user specified frequencies. If so, scan only those. */
+ if (wpa_s->conf->freq_list && !params.freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Optimize scan based on conf->freq_list");
+ int_array_concat(¶ms.freqs, wpa_s->conf->freq_list);
+ }
+
params.filter_ssids = wpa_supplicant_build_filter_ssids(
wpa_s->conf, ¶ms.num_filter_ssids);
if (extra_ie) {
@@ -1028,7 +1035,9 @@
if (!ssid || !wpa_s->prev_sched_ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
-
+ if (wpa_s->conf->sched_scan_interval)
+ wpa_s->sched_scan_interval =
+ wpa_s->conf->sched_scan_interval;
if (wpa_s->sched_scan_interval == 0)
wpa_s->sched_scan_interval = 10;
wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 982e124..0371628 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -353,7 +353,7 @@
#endif /* CONFIG_P2P */
#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20) {
+ if (is_hs20_network(wpa_s, ssid, bss)) {
struct wpabuf *hs20;
hs20 = wpabuf_alloc(20);
if (hs20) {
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 204d13e..b66dcd0 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -582,52 +582,81 @@
}
-static void wpa_cli_show_variables(void)
-{
- printf("set variables:\n"
- " EAPOL::heldPeriod (EAPOL state machine held period, "
- "in seconds)\n"
- " EAPOL::authPeriod (EAPOL state machine authentication "
- "period, in seconds)\n"
- " EAPOL::startPeriod (EAPOL state machine start period, in "
- "seconds)\n"
- " EAPOL::maxStart (EAPOL state machine maximum start "
- "attempts)\n");
- printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
- "seconds)\n"
- " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
- " threshold\n\tpercentage)\n"
- " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
- "security\n\tassociation in seconds)\n");
-}
-
-
static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
int res;
- if (argc == 0) {
- wpa_cli_show_variables();
- return 0;
- }
-
- if (argc != 1 && argc != 2) {
- printf("Invalid SET command: needs two arguments (variable "
- "name and value)\n");
- return -1;
- }
-
- if (argc == 1)
+ if (argc == 1) {
res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
- else
- res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
- argv[0], argv[1]);
- if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
- printf("Too long SET command.\n");
- return -1;
+ if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ printf("Too long SET command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
}
- return wpa_ctrl_command(ctrl, cmd);
+
+ return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
+}
+
+
+static char ** wpa_cli_complete_set(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ const char *fields[] = {
+ /* runtime values */
+ "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
+ "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
+ "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
+ "wps_fragment_size", "wps_version_number", "ampdu",
+ "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
+ "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
+ "no_keep_alive",
+ /* global configuration parameters */
+ "eapol_version", "ap_scan", "disable_scan_offload",
+ "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
+ "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
+ "driver_param", "dot11RSNAConfigPMKLifetime",
+ "dot11RSNAConfigPMKReauthThreshold",
+ "dot11RSNAConfigSATimeout",
+ "update_config", "load_dynamic_eap", "uuid", "device_name",
+ "manufacturer", "model_name", "model_number", "serial_number",
+ "device_type", "os_version", "config_methods",
+ "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
+ "p2p_listen_reg_class", "p2p_listen_channel",
+ "p2p_oper_reg_class", "p2p_oper_channel",
+ "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
+ "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
+ "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
+ "p2p_ignore_shared_freq", "country", "bss_max_count",
+ "bss_expiration_age", "bss_expiration_scan_count",
+ "filter_ssids", "filter_rssi", "max_num_sta",
+ "disassoc_low_ack", "hs20", "interworking", "hessid",
+ "access_network_type", "pbc_in_m1", "autoscan",
+ "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
+ "wps_nfc_dev_pw", "ext_password_backend",
+ "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
+ "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
+ "ignore_old_scan_res", "freq_list"
+ };
+ int i, num_fields = sizeof(fields) / sizeof(fields[0]);
+
+ if (arg == 1) {
+ char **res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(fields[i]);
+ if (res[i] == NULL)
+ return res;
+ }
+ return res;
+ }
+
+ if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
+ return cli_txt_list_array(&bsses);
+
+ return NULL;
}
@@ -2372,7 +2401,7 @@
{ "quit", wpa_cli_cmd_quit, NULL,
cli_cmd_flag_none,
"= exit wpa_cli" },
- { "set", wpa_cli_cmd_set, NULL,
+ { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
cli_cmd_flag_none,
"= set variables (shows list of variables when run without "
"arguments)" },
@@ -3316,6 +3345,37 @@
}
+static void update_bssid_list(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ char *cmd = "BSS RANGE=ALL MASK=0x2";
+ char *pos, *end;
+
+ if (ctrl == NULL)
+ return;
+ ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+ if (ret < 0)
+ return;
+ buf[len] = '\0';
+
+ pos = buf;
+ while (pos) {
+ pos = os_strstr(pos, "bssid=");
+ if (pos == NULL)
+ break;
+ pos += 6;
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ cli_txt_list_add(&bsses, pos);
+ pos = end + 1;
+ }
+}
+
+
static void try_connection(void *eloop_ctx, void *timeout_ctx)
{
if (ctrl_ifname == NULL)
@@ -3331,6 +3391,8 @@
return;
}
+ update_bssid_list(ctrl_conn);
+
if (warning_displayed)
printf("Connection established.\n");
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index a66f654..c807888 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -126,8 +126,8 @@
}
-static int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
+int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
{
u8 key[32];
size_t keylen;
@@ -1271,7 +1271,6 @@
enum wpa_cipher cipher_pairwise, cipher_group;
struct wpa_driver_associate_params params;
int wep_keys_set = 0;
- struct wpa_driver_capa capa;
int assoc_failed = 0;
struct wpa_ssid *old_ssid;
u8 ext_capab[10];
@@ -1475,7 +1474,7 @@
#endif /* CONFIG_P2P */
#ifdef CONFIG_HS20
- if (wpa_s->conf->hs20) {
+ if (is_hs20_network(wpa_s, ssid, bss)) {
struct wpabuf *hs20;
hs20 = wpabuf_alloc(20);
if (hs20) {
@@ -1686,8 +1685,8 @@
wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
}
- if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
- capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) {
+ if (wep_keys_set &&
+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
/* Set static WEP keys again */
wpa_set_wep_keys(wpa_s, ssid);
}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 0935a06..87dd397 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -524,6 +524,9 @@
# set, scan results that do not match any of the specified frequencies are not
# considered when selecting a BSS.
#
+# This can also be set on the outside of the network block. In this case,
+# it limits the frequencies that will be scanned.
+#
# bgscan: Background scanning
# wpa_supplicant behavior for background scanning can be specified by
# configuring a bgscan module. These modules are responsible for requesting
@@ -1231,3 +1234,10 @@
network={
key_mgmt=NONE
}
+
+
+# Example config file that will only scan on channel 36.
+freq_list=5180
+network={
+ key_mgmt=NONE
+}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index f96b245..c53421d 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -702,6 +702,8 @@
struct wpa_driver_associate_params *params);
int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index cd51873..1a64df3 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -551,7 +551,7 @@
static int wpa_supplicant_tdls_peer_addset(
- void *ctx, const u8 *peer, int add, u16 capability,
+ void *ctx, const u8 *peer, int add, u16 aid, u16 capability,
const u8 *supp_rates, size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
@@ -563,7 +563,7 @@
os_memset(¶ms, 0, sizeof(params));
params.addr = peer;
- params.aid = 1;
+ params.aid = aid;
params.capability = capability;
params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 9af6084..b376fb0 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -219,6 +219,80 @@
}
+static void wpas_wps_remove_dup_network(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *new_ssid)
+{
+ struct wpa_ssid *ssid, *next;
+
+ for (ssid = wpa_s->conf->ssid, next = ssid ? ssid->next : NULL; ssid;
+ ssid = next, next = ssid ? ssid->next : NULL) {
+ /*
+ * new_ssid has already been added to the list in
+ * wpas_wps_add_network(), so skip it.
+ */
+ if (ssid == new_ssid)
+ continue;
+
+ if (ssid->bssid_set || new_ssid->bssid_set) {
+ if (ssid->bssid_set != new_ssid->bssid_set)
+ continue;
+ if (os_memcmp(ssid->bssid, new_ssid->bssid, ETH_ALEN) !=
+ 0)
+ continue;
+ }
+
+ /* compare SSID */
+ if (ssid->ssid_len == 0 || ssid->ssid_len != new_ssid->ssid_len)
+ continue;
+
+ if (ssid->ssid && new_ssid->ssid) {
+ if (os_memcmp(ssid->ssid, new_ssid->ssid,
+ ssid->ssid_len) != 0)
+ continue;
+ } else if (ssid->ssid || new_ssid->ssid)
+ continue;
+
+ /* compare security parameters */
+ if (ssid->auth_alg != new_ssid->auth_alg ||
+ ssid->key_mgmt != new_ssid->key_mgmt ||
+ ssid->proto != new_ssid->proto ||
+ ssid->pairwise_cipher != new_ssid->pairwise_cipher ||
+ 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);
+ wpa_config_remove_network(wpa_s->conf, ssid->id);
+ }
+}
+
+
static int wpa_supplicant_wps_cred(void *ctx,
const struct wps_credential *cred)
{
@@ -438,6 +512,8 @@
if (cred->ap_channel)
wpa_s->wps_ap_channel = cred->ap_channel;
+ wpas_wps_remove_dup_network(wpa_s, ssid);
+
#ifndef CONFIG_NO_CONFIG_WRITE
if (wpa_s->conf->update_config &&
wpa_config_write(wpa_s->confname, wpa_s->conf)) {