diff options
34 files changed, 456 insertions, 87 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk index 0d97a21b..7ecbc657 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -57,3 +57,5 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/hostapd_intermediat $(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 21104d30..62136cab 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2893,6 +2893,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, 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 6a1c500b..86015bf1 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1540,6 +1540,9 @@ own_ip_addr=127.0.0.1 # # 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 70b26a6e..7ab86fca 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -168,6 +168,7 @@ struct hostapd_config * hostapd_config_defaults(void) 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 f9629a2c..16134da9 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -526,6 +526,7 @@ struct hostapd_config { 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 4f1f6fbc..18ae86c8 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1232,7 +1232,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, 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 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, } 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 465eec6a..9126b90d 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -160,6 +160,9 @@ struct wpa_auth_config { #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 fdaaaff5..e2be1ea6 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 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, #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 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) 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 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) 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 61250154..213f3c38 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2747,9 +2747,6 @@ static void wiphy_info_supp_cmds(struct wiphy_info_data *info, 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 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv, "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 @@ static int wpa_driver_nl80211_sta_add(void *priv, 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 79da8710..d1e48b5e 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 @@ enum nl80211_commands { 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 @@ enum nl80211_commands { * @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 @@ enum nl80211_attrs { 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 @@ enum nl80211_protocol_features { 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 069e22be..81e2a5c0 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -127,6 +127,8 @@ struct wpa_tdls_peer { u8 qos_info; + u16 aid; + u8 *ext_capab; size_t ext_capab_len; }; @@ -696,13 +698,8 @@ int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code) 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 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, 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: 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 @@ static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) } /* 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 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, 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 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) 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 d4533a81..78dfb523 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -56,7 +56,7 @@ struct wpa_sm_ctx { 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 877e6de1..0e0d373f 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_oper(struct wpa_sm *sm, int oper, 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 @@ wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add, { 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 652197ff..ba203e62 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -430,6 +430,9 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len, } 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 82a5c08c..2c788012 100644 --- a/src/rsn_supp/wpa_ie.h +++ b/src/rsn_supp/wpa_ie.h @@ -54,6 +54,7 @@ struct wpa_eapol_ie_parse { 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 b01e08df..177ecf41 100644 --- a/src/utils/edit.c +++ b/src/utils/edit.c @@ -345,7 +345,7 @@ static void insert_char(int c) 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 c6d6c7fd..02900130 100644 --- a/src/wps/http_client.c +++ b/src/wps/http_client.c @@ -92,7 +92,7 @@ static void http_client_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) (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 b86c4c7a..331940c8 100644 --- a/wpa_supplicant/android.config +++ b/wpa_supplicant/android.config @@ -176,7 +176,7 @@ CONFIG_EAP_PWD=y 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 @@ CONFIG_WPS=y # 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 @@ CONFIG_SMARTCARD=y # 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 @@ CONFIG_L2_PACKET=linux # 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 @@ CONFIG_ANDROID_LOG=y # 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 @@ CONFIG_IEEE80211N=y # Disable roaming in wpa_supplicant CONFIG_NO_ROAMING=y -# Enable TDLS -CONFIG_TDLS=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 -# Enable P2P +# 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_AP=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 2de78450..b25e0f67 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1826,6 +1826,7 @@ void wpa_config_free(struct wpa_config *config) 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_global_config_parse_bin(const struct global_parse_data *data, } +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 @@ static const struct global_parse_data global_fields[] = { { 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 4a175ce9..a1a52399 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -645,6 +645,14 @@ struct wpa_config { 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 @@ struct wpa_config { * 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 8604ae8a..8ff42852 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1015,6 +1015,20 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) 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 e867bae6..5663a5fc 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -423,6 +423,10 @@ CONFIG_PEERKEY=y # 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 @@ CONFIG_PEERKEY=y # 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 @@ CONFIG_PEERKEY=y # 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 650221a0..cf2800ec 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1679,7 +1679,6 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, { u8 bssid[ETH_ALEN]; int ft_completed; - struct wpa_driver_capa capa; #ifdef CONFIG_AP if (wpa_s->ap_iface) { @@ -1785,6 +1784,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, 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 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, 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 14042419..4048cf76 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -33,6 +33,35 @@ void wpas_hs20_add_indication(struct wpabuf *buf) } +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 6eb3926d..1c8481bf 100644 --- a/wpa_supplicant/hs20_supplicant.h +++ b/wpa_supplicant/hs20_supplicant.h @@ -16,5 +16,7 @@ struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload, 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 5fcaf292..f1e15ffc 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1003,6 +1003,7 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst, 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 db73a186..02c11b06 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -453,6 +453,11 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) #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 @@ ssid_list_set: 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 @@ ssid_list_set: 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 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) 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 982e1249..03716280 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -353,7 +353,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #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 204d13e1..b66dcd05 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -582,52 +582,81 @@ static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) } -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) { + res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long SET command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); } - if (argc != 1 && argc != 2) { - printf("Invalid SET command: needs two arguments (variable " - "name and value)\n"); - return -1; - } + return wpa_cli_cmd(ctrl, "SET", 2, argc, argv); +} - 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; + +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; } - return wpa_ctrl_command(ctrl, cmd); + + if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0) + return cli_txt_list_array(&bsses); + + return NULL; } @@ -2372,7 +2401,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "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 start_edit(void) } +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 @@ static void try_connection(void *eloop_ctx, void *timeout_ctx) 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 a66f6544..c807888f 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -126,8 +126,8 @@ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) } -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 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, 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 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, #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 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, 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 0935a062..87dd3970 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -524,6 +524,9 @@ fast_reauth=1 # 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 @@ SGVsbG8gV29ybGQhCg== 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 f96b245b..c53421de 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -702,6 +702,8 @@ void wpa_supplicant_apply_vht_overrides( 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 cd518738..1a64df38 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -551,7 +551,7 @@ static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer) 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 @@ static int wpa_supplicant_tdls_peer_addset( 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 9af60849..b376fb08 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -219,6 +219,80 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s, } +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 @@ static int wpa_supplicant_wps_cred(void *ctx, 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)) { |