Merge "[Security bug fix] Added peer address check"
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
index a1f8ae9..3c55c5a 100644
--- a/src/pae/ieee802_1x_kay.c
+++ b/src/pae/ieee802_1x_kay.c
@@ -592,6 +592,7 @@
ieee802_1x_kay_create_peer(const u8 *mi, u32 mn)
{
struct ieee802_1x_kay_peer *peer;
+ struct os_reltime now;
peer = os_zalloc(sizeof(*peer));
if (!peer) {
@@ -601,7 +602,8 @@
os_memcpy(peer->mi, mi, MI_LEN);
peer->mn = mn;
- peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
+ os_get_reltime(&now);
+ peer->expire = now.sec + MKA_LIFE_TIME / 1000;
peer->sak_used = false;
peer->missing_sak_use_count = 0;
@@ -678,6 +680,7 @@
{
struct ieee802_1x_kay_peer *peer;
struct receive_sc *rxsc;
+ struct os_reltime now;
peer = ieee802_1x_kay_get_potential_peer(participant, mi);
if (!peer)
@@ -690,7 +693,8 @@
os_memcpy(&peer->sci, &participant->current_peer_sci,
sizeof(peer->sci));
peer->mn = mn;
- peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
+ os_get_reltime(&now);
+ peer->expire = now.sec + MKA_LIFE_TIME / 1000;
wpa_printf(MSG_DEBUG, "KaY: Move potential peer to live peer");
ieee802_1x_kay_dump_peer(peer);
@@ -873,13 +877,15 @@
peer = ieee802_1x_kay_get_peer_sci(participant,
&body->actor_sci);
if (peer) {
- time_t new_expire;
+ os_time_t new_expire;
+ struct os_reltime now;
wpa_printf(MSG_WARNING,
"KaY: duplicated SCI detected - maybe active attacker or peer selected new MI - ignore MKPDU");
/* Reduce timeout to speed up this process but left the
* chance for old one to prove aliveness. */
- new_expire = time(NULL) + MKA_HELLO_TIME * 1.5 / 1000;
+ os_get_reltime(&now);
+ new_expire = now.sec + MKA_HELLO_TIME * 1.5 / 1000;
if (peer->expire > new_expire)
peer->expire = new_expire;
return NULL;
@@ -2130,6 +2136,7 @@
unsigned int key_len;
u8 *key;
struct macsec_ciphersuite *cs;
+ struct os_reltime now;
/* check condition for generating a fresh SAK:
* must have one live peer
@@ -2150,7 +2157,8 @@
* here only check first item and ingore
* && (!dl_list_empty(&participant->potential_peers))) {
*/
- if ((time(NULL) - kay->dist_time) < MKA_LIFE_TIME / 1000) {
+ os_get_reltime(&now);
+ if ((now.sec - kay->dist_time) < MKA_LIFE_TIME / 1000) {
wpa_printf(MSG_ERROR,
"KaY: Life time has not elapsed since prior SAK distributed");
return -1;
@@ -2244,7 +2252,7 @@
if (kay->dist_an > 3)
kay->dist_an = 0;
- kay->dist_time = time(NULL);
+ kay->dist_time = now.sec;
return 0;
@@ -2548,17 +2556,19 @@
struct ieee802_1x_mka_participant *participant;
struct ieee802_1x_kay *kay;
struct ieee802_1x_kay_peer *peer, *pre_peer;
- time_t now = time(NULL);
+ struct os_reltime now;
bool lp_changed;
struct receive_sc *rxsc, *pre_rxsc;
struct transmit_sa *txsa, *pre_txsa;
+ os_get_reltime(&now);
+
participant = (struct ieee802_1x_mka_participant *)eloop_ctx;
kay = participant->kay;
wpa_printf(MSG_DEBUG, "KaY: Participant timer (ifname=%s)",
kay->if_name);
if (participant->cak_life) {
- if (now > participant->cak_life)
+ if (now.sec > participant->cak_life)
goto delete_mka;
}
@@ -2566,7 +2576,7 @@
* when the MKA life elapsed since its creating */
if (participant->mka_life) {
if (dl_list_empty(&participant->live_peers)) {
- if (now > participant->mka_life)
+ if (now.sec > participant->mka_life)
goto delete_mka;
} else {
participant->mka_life = 0;
@@ -2576,7 +2586,7 @@
lp_changed = false;
dl_list_for_each_safe(peer, pre_peer, &participant->live_peers,
struct ieee802_1x_kay_peer, list) {
- if (now > peer->expire) {
+ if (now.sec > peer->expire) {
wpa_printf(MSG_DEBUG, "KaY: Live peer removed");
wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
sizeof(peer->mi));
@@ -2634,7 +2644,7 @@
dl_list_for_each_safe(peer, pre_peer, &participant->potential_peers,
struct ieee802_1x_kay_peer, list) {
- if (now > peer->expire) {
+ if (now.sec > peer->expire) {
wpa_printf(MSG_DEBUG, "KaY: Potential peer removed");
wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
sizeof(peer->mi));
@@ -3371,11 +3381,14 @@
return -1;
}
} else {
+ struct os_reltime now;
+
+ os_get_reltime(&now);
peer->missing_sak_use_count = 0;
/* Only update live peer watchdog after successful
* decode of all parameter sets */
- peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
+ peer->expire = now.sec + MKA_LIFE_TIME / 1000;
}
} else {
/* MKPDU is from new or potential peer */
@@ -3674,8 +3687,12 @@
os_memcpy(participant->cak.key, cak->key, cak->len);
wpa_hexdump_key(MSG_DEBUG, "KaY: CAK", participant->cak.key,
participant->cak.len);
- if (life)
- participant->cak_life = life + time(NULL);
+ if (life) {
+ struct os_reltime now;
+ os_get_reltime(&now);
+
+ participant->cak_life = life + now.sec;
+ }
switch (mode) {
case EAP_EXCHANGE:
@@ -3783,7 +3800,10 @@
* some peer appears.
*/
if (mode != PSK) {
- participant->mka_life = MKA_LIFE_TIME / 1000 + time(NULL) +
+ struct os_reltime now;
+ os_get_reltime(&now);
+
+ participant->mka_life = MKA_LIFE_TIME / 1000 + now.sec +
usecs / 1000000;
}
participant->mode = mode;
diff --git a/src/pae/ieee802_1x_kay.h b/src/pae/ieee802_1x_kay.h
index 11cf7b7..525679f 100644
--- a/src/pae/ieee802_1x_kay.h
+++ b/src/pae/ieee802_1x_kay.h
@@ -213,7 +213,7 @@
u32 dist_kn;
u32 rcvd_keys;
u8 dist_an;
- time_t dist_time;
+ os_time_t dist_time;
u8 mka_version;
u8 algo_agility[4];
diff --git a/src/pae/ieee802_1x_kay_i.h b/src/pae/ieee802_1x_kay_i.h
index 7a04169..e4650b5 100644
--- a/src/pae/ieee802_1x_kay_i.h
+++ b/src/pae/ieee802_1x_kay_i.h
@@ -45,7 +45,7 @@
struct ieee802_1x_mka_sci sci;
u8 mi[MI_LEN];
u32 mn;
- time_t expire;
+ os_time_t expire;
bool is_key_server;
u8 key_server_priority;
bool macsec_desired;
@@ -135,8 +135,8 @@
struct ieee802_1x_mka_peer_id current_peer_id;
struct ieee802_1x_mka_sci current_peer_sci;
- time_t cak_life;
- time_t mka_life;
+ os_time_t cak_life;
+ os_time_t mka_life;
bool to_dist_sak;
bool to_use_sak;
bool new_sak;
diff --git a/wpa_supplicant/aidl/p2p_iface.cpp b/wpa_supplicant/aidl/p2p_iface.cpp
index 45dbaec..694357f 100644
--- a/wpa_supplicant/aidl/p2p_iface.cpp
+++ b/wpa_supplicant/aidl/p2p_iface.cpp
@@ -23,13 +23,7 @@
#include "driver_i.h"
}
-#define P2P_MAX_JOIN_SCAN_ATTEMPTS 3
-// Wait time before triggering the single channel scan to discover Auto GO.
-// Use a shorter wait time when the given frequency is GO operating frequency.
-// The idea is to quickly finish scans and return the status to application.
-#define P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS 200000
-// Wait time before triggering the multiple channel scan to discover Auto GO.
-#define P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS 1000000
+#define P2P_JOIN_LIMIT 3
namespace {
const char kConfigMethodStrPbc[] = "pbc";
@@ -99,138 +93,6 @@
return 1;
}
-static int setBandScanFreqsList(
- struct wpa_supplicant *wpa_s,
- enum hostapd_hw_mode hw_mode,
- bool exclude_dfs,
- struct wpa_driver_scan_params *params)
-{
- struct hostapd_hw_modes *mode;
- int count, i;
-
- mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
- if (mode == NULL || !mode->num_channels) {
- wpa_printf(MSG_ERROR,
- "P2P: No channels supported in this hw_mode: %d", hw_mode);
- return -1;
- }
-
- /*
- * Allocate memory for frequency array, allocate one extra
- * slot for the zero-terminator.
- */
- params->freqs = (int *) os_calloc(mode->num_channels + 1, sizeof(int));
- if (params->freqs == NULL) {
- return -ENOMEM;
- }
- for (count = 0, i = 0; i < mode->num_channels; i++) {
- if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) {
- continue;
- }
- if (exclude_dfs && (mode->channels[i].flag & HOSTAPD_CHAN_RADAR)) {
- continue;
- }
- params->freqs[count++] = mode->channels[i].freq;
- }
- if (!count && params->freqs) {
- wpa_printf(MSG_ERROR,
- "P2P: All channels(exclude_dfs: %d) are disabled in this hw_mode: %d",
- exclude_dfs, hw_mode);
- os_free(params->freqs);
- return -1;
- }
- return 0;
-}
-
-static int setScanFreq(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params,
- int freq, int operating_freq)
-{
- int frequency = operating_freq ? operating_freq : freq;
- if (disabled_freq(wpa_s, frequency)) {
- wpa_printf(MSG_ERROR,
- "P2P: freq %d is not supported for a client.", frequency);
- return -1;
- }
- /*
- * Allocate memory for frequency array, with one extra
- * slot for the zero-terminator.
- */
- params->freqs = new int[2] {frequency, 0};
- return 0;
-}
-
-/**
- * setP2pCliOptimizedScanFreqsList - Fill the frequencies to scan in Scan
- * parameters.
- * @wpa_s: Pointer to wpa_supplicant data
- * @params: Pointer to Scan parameters.
- * @freq: Frequency/Band requested to scan by the application, possible values are,
- * 0 - All the frequencies - full scan
- * 2 - Frequencies in 2.4GHz
- * 5 - Frequencies in 5GHz
- * - Valid frequency
- * @operating_freq: Frequency of BSS if found in scan cache
- * Returns: Pointer to the BSS entry or %NULL if not found
- */
-static int setP2pCliOptimizedScanFreqsList(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params, int freq, int operating_freq)
-{
- int ret;
- /* If BSS is found in scan cache, first scan its operating frequency */
- if (!wpa_s->p2p_join_scan_count && operating_freq) {
- ret = setScanFreq(wpa_s, params, freq, operating_freq);
- if (!ret) {
- return ret;
- }
- }
-
- /* Empty freq params means scan all the frequencies */
- if (freq == 0) {
- return 0;
- }
- else if (freq == 2 || freq == 5) {
- /* Scan the frequencies in the band */
- enum hostapd_hw_mode mode;
- int ret;
- if (wpa_s->hw.modes == NULL) {
- wpa_printf(MSG_DEBUG,
- "P2P: Unknown what %dG channels the driver supports.", freq);
- return 0;
- }
- mode = freq == 5 ? HOSTAPD_MODE_IEEE80211A : HOSTAPD_MODE_IEEE80211G;
- if (wpa_s->p2p_join_scan_count < 2) {
- // scan all non DFS channels in the first two attempts
- ret = setBandScanFreqsList(wpa_s, mode, true, params);
- if (ret < 0 && (-ENOMEM != ret)) {
- // try to scan all channels before returning error
- ret = setBandScanFreqsList(wpa_s, mode, false, params);
- }
- } else {
- // scan all channels
- ret = setBandScanFreqsList(wpa_s, mode, false, params);
- }
- return ret;
- } else {
- /* Scan the frequency requested by the application */
- ret = setScanFreq(wpa_s, params, freq, 0);
- return ret;
- }
- return 0;
-}
-
-/**
- * getP2pJoinScanInterval - Get the delay in triggering the scan to discover
- * Auto GO.
- */
-static int getP2pJoinScanIntervalUsecs(int freq)
-{
- if (freq == 5 || freq == 2 || freq == 0) {
- return P2P_JOIN_MULTIPLE_CHANNEL_SCAN_INTERVAL_USECS;
- } else {
- return P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS;
- }
-}
-
/*
* isAnyEtherAddr - match any ether address
*
@@ -241,56 +103,9 @@
return (a[0] == 2) && !(a[1] | a[2] | a[3] | a[4] | a[5]);
}
-/**
- * findBssBySsid - Fetch a BSS table entry based on SSID and optional BSSID.
- * @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID, 02:00:00:00:00:00 matches any bssid
- * @ssid: SSID
- * @ssid_len: Length of @ssid
- * Returns: Pointer to the BSS entry or %NULL if not found
- */
-struct wpa_bss* findBssBySsid(
- struct wpa_supplicant *wpa_s, const u8 *bssid,
- const u8 *ssid, size_t ssid_len)
-{
- struct wpa_bss *bss;
- dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if ((isAnyEtherAddr(bssid) ||
- os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
- bss->ssid_len == ssid_len &&
- os_memcmp(bss->ssid, ssid, ssid_len) == 0)
- return bss;
- }
- return NULL;
-}
-
-/**
- * findBssBySsidFromAnyInterface - Fetch a BSS table entry based on SSID and optional BSSID
- * by iterating through all the interfaces.
- * @head: Head of Pointer to wpa_supplicant data
- * @bssid: BSSID, 02:00:00:00:00:00 matches any bssid
- * @ssid: SSID
- * @ssid_len: Length of @ssid
- * Returns: Pointer to the BSS entry or %NULL if not found
- */
-struct wpa_bss* findBssBySsidFromAnyInterface(
- struct wpa_supplicant *head, const u8 *bssid,
- const u8 *ssid, size_t ssid_len)
-{
- struct wpa_supplicant *wpa_s;
- struct wpa_bss *bss = NULL;
- for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) {
- bss = findBssBySsid(wpa_s, bssid, ssid, ssid_len);
- if (bss != NULL) {
- return bss;
- }
- }
- return bss;
-}
-
struct wpa_ssid* addGroupClientNetwork(
struct wpa_supplicant* wpa_s,
- uint8_t *group_owner_bssid,
+ const uint8_t *group_owner_bssid,
const std::vector<uint8_t>& ssid,
const std::string& passphrase)
{
@@ -304,22 +119,18 @@
// set P2p network defaults
wpa_network->p2p_group = 1;
wpa_network->mode = wpas_mode::WPAS_MODE_INFRA;
-
- wpa_network->auth_alg = WPA_AUTH_ALG_OPEN;
- wpa_network->key_mgmt = WPA_KEY_MGMT_PSK;
- wpa_network->proto = WPA_PROTO_RSN;
- wpa_network->pairwise_cipher = WPA_CIPHER_CCMP;
- wpa_network->group_cipher = WPA_CIPHER_CCMP;
wpa_network->disabled = 2;
// set necessary fields
- os_memcpy(wpa_network->bssid, group_owner_bssid, ETH_ALEN);
- wpa_network->bssid_set = 1;
+ if (!isAnyEtherAddr(group_owner_bssid)) {
+ os_memcpy(wpa_network->bssid, group_owner_bssid, ETH_ALEN);
+ wpa_network->bssid_set = 1;
+ }
wpa_network->ssid = (uint8_t *)os_malloc(ssid.size());
if (wpa_network->ssid == NULL) {
wpa_config_remove_network(wpa_s->conf, wpa_network->id);
- return NULL;
+ return NULL;
}
memcpy(wpa_network->ssid, ssid.data(), ssid.size());
wpa_network->ssid_len = ssid.size();
@@ -328,7 +139,7 @@
wpa_network->passphrase = dup_binstr(passphrase.c_str(), passphrase.length());
if (wpa_network->passphrase == NULL) {
wpa_config_remove_network(wpa_s->conf, wpa_network->id);
- return NULL;
+ return NULL;
}
wpa_config_update_psk(wpa_network);
@@ -336,13 +147,6 @@
}
-void joinScanWrapper(void *eloop_ctx, void *timeout_ctx)
-{
- if (pending_join_scan_callback) {
- pending_join_scan_callback();
- }
-}
-
void scanResJoinWrapper(
struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
@@ -358,85 +162,6 @@
}
}
-int joinScanReq(
- struct wpa_supplicant* wpa_s,
- const std::vector<uint8_t>& ssid,
- int freq, int operating_freq)
-{
- int ret;
- struct wpa_driver_scan_params params;
- struct wpabuf *ies;
- size_t ielen;
- unsigned int bands;
-
- if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
- wpa_printf(MSG_ERROR,
- "P2P: P2P interface is gone, cancel join scan");
- return -ENXIO;
- }
-
- os_memset(¶ms, 0, sizeof(params));
- if (ssid.size() > 0) {
- params.ssids[0].ssid = ssid.data();
- params.ssids[0].ssid_len = ssid.size();
- } else {
- params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
- params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
- }
- wpa_printf(MSG_DEBUG, "Scan SSID %s for join with frequency %d"
- "BSS operating_freq from scan cache %d",
- wpa_ssid_txt(params.ssids[0].ssid, params.ssids[0].ssid_len), freq, operating_freq);
-
- /* Construct an optimized p2p scan channel list */
- ret = setP2pCliOptimizedScanFreqsList(wpa_s, ¶ms, freq, operating_freq);
- if (ret < 0) {
- wpa_printf(MSG_ERROR,
- "Failed to set frequency in p2p scan params, error = %d", ret);
- return -1;
- }
-
- ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
- ies = wpabuf_alloc(ielen);
- if (ies == NULL) {
- if (params.freqs) {
- os_free(params.freqs);
- }
- return -1;
- }
-
- bands = wpas_get_bands(wpa_s, params.freqs);
- p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
-
- params.p2p_probe = 1;
- params.extra_ies = (u8 *) wpabuf_head(ies);
- params.extra_ies_len = wpabuf_len(ies);
- if (wpa_s->clear_driver_scan_cache) {
- wpa_printf(MSG_DEBUG,
- "Request driver to clear scan cache due to local BSS flush");
- params.only_new_results = 1;
- }
-
- ret = wpa_drv_scan(wpa_s, ¶ms);
- if (!ret) {
- os_get_reltime(&wpa_s->scan_trigger_time);
- if (wpa_s->scan_res_handler) {
- wpa_printf(MSG_DEBUG, "Replace current running scan result handler");
- }
- wpa_s->p2p_join_scan_count++;
- wpa_s->scan_res_handler = scanResJoinWrapper;
- wpa_s->own_scan_requested = 1;
- wpa_s->clear_driver_scan_cache = 0;
- }
-
- if (params.freqs) {
- os_free(params.freqs);
- }
-
- wpabuf_free(ies);
-
- return ret;
-}
-
static bool is6GhzAllowed(struct wpa_supplicant *wpa_s) {
if (!wpa_s->global->p2p) return false;
return wpa_s->global->p2p->allow_6ghz;
@@ -444,9 +169,10 @@
int joinGroup(
struct wpa_supplicant* wpa_s,
- uint8_t *group_owner_bssid,
+ const uint8_t *group_owner_bssid,
const std::vector<uint8_t>& ssid,
- const std::string& passphrase)
+ const std::string& passphrase,
+ uint32_t freq)
{
int ret = 0;
int he = wpa_s->conf->p2p_go_he;
@@ -467,8 +193,8 @@
wpa_network->temporary = 1;
if (wpas_p2p_group_add_persistent(
- wpa_s, wpa_network, 0, 0, 0, 0, ht40, vht,
- CONF_OPER_CHWIDTH_USE_HT, he, 0, NULL, 0, 0, is6GhzAllowed(wpa_s))) {
+ wpa_s, wpa_network, 0, 0, freq, 0, ht40, vht,
+ CONF_OPER_CHWIDTH_USE_HT, he, 0, NULL, 0, 0, is6GhzAllowed(wpa_s), P2P_JOIN_LIMIT)) {
ret = -1;
}
@@ -477,27 +203,6 @@
return ret;
}
-void notifyGroupJoinFailure(
- struct wpa_supplicant* wpa_s)
-{
- u8 zero_addr[ETH_ALEN] = {0};
- std::vector<uint8_t> ssid = {'D', 'I', 'R', 'E','C', 'T', '-'};
- std::string passphrase = "";
- struct wpa_ssid *wpa_network = addGroupClientNetwork(
- wpa_s, zero_addr, ssid, passphrase);
- if (wpa_network) {
- wpa_network->temporary = 1;
- wpas_notify_p2p_group_formation_failure(wpa_s, "Failed to find the group.");
- wpas_notify_p2p_group_removed(
- wpa_s, wpa_network, "client");
- wpa_config_remove_network(
- wpa_s->conf, wpa_network->id);
- } else {
- wpa_printf(MSG_ERROR,
- "P2P: Cannot construct a network.");
- }
-}
-
void scanResJoinIgnore(struct wpa_supplicant *wpa_s, struct wpa_scan_results *scan_res) {
wpa_printf(MSG_DEBUG, "P2P: Ignore group join scan results.");
@@ -1901,7 +1606,7 @@
} else if (ssid->disabled == 2) {
if (wpas_p2p_group_add_persistent(
wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
- CONF_OPER_CHWIDTH_USE_HT, he, edmg, NULL, 0, 0, is6GhzAllowed(wpa_s))) {
+ CONF_OPER_CHWIDTH_USE_HT, he, edmg, NULL, 0, 0, is6GhzAllowed(wpa_s), 0)) {
return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
} else {
return ndk::ScopedAStatus::ok();
@@ -1956,77 +1661,7 @@
// The rest is for group join.
wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND before group join.");
wpas_p2p_stop_find(wpa_s);
-
- if (pending_scan_res_join_callback != NULL) {
- wpa_printf(MSG_WARNING, "P2P: Renew scan result callback with new request.");
- }
-
- pending_join_scan_callback =
- [wpa_s, ssid, peer_address, freq]() {
- if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
- return;
- }
- int operating_freq = 0;
- struct wpa_bss *bss = findBssBySsidFromAnyInterface(
- wpa_s->global->ifaces, peer_address.data(), ssid.data(), ssid.size());
- if (bss != NULL) {
- wpa_printf(MSG_DEBUG, "P2P: Found Group owner " MACSTR "in scan cache",
- MAC2STR(bss->bssid));
- operating_freq = bss->freq;
- }
-
- int ret = joinScanReq(wpa_s, ssid, freq, operating_freq);
- // for BUSY case, the scan might be occupied by WiFi.
- // Do not give up immediately, but try again later.
- if (-EBUSY == ret) {
- // re-schedule this join scan
- eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
- eloop_register_timeout(0, P2P_JOIN_SINGLE_CHANNEL_SCAN_INTERVAL_USECS,
- joinScanWrapper, wpa_s, NULL);
- } else if (0 != ret) {
- notifyGroupJoinFailure(wpa_s);
- pending_scan_res_join_callback = NULL;
- }
- };
-
- pending_scan_res_join_callback = [wpa_s, ssid, passphrase, peer_address, freq, this]() {
- if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
- return;
- }
-
- wpa_printf(MSG_DEBUG, "P2P: Scan results received for join (reinvoke).");
-
- struct wpa_bss *bss = findBssBySsid(
- wpa_s, peer_address.data(), ssid.data(), ssid.size());
- if (bss) {
- if (0 != joinGroup(wpa_s, bss->bssid, ssid, passphrase)) {
- wpa_printf(MSG_ERROR, "P2P: Failed to join a group.");
- }
- // no need to notify group join failure here,
- // it will be handled by wpas_p2p_group_add_persistent
- // called in joinGroup.
- pending_scan_res_join_callback = NULL;
- return;
- }
- wpa_printf(MSG_DEBUG, "P2P: Join scan count %d.", wpa_s->p2p_join_scan_count);
- eloop_cancel_timeout(joinScanWrapper, wpa_s, NULL);
- if (wpa_s->p2p_join_scan_count < P2P_MAX_JOIN_SCAN_ATTEMPTS) {
- wpa_printf(MSG_DEBUG, "P2P: Try join again later.");
- eloop_register_timeout(0, getP2pJoinScanIntervalUsecs(freq),
- joinScanWrapper, wpa_s, this);
- return;
- }
-
- wpa_printf(MSG_ERROR, "P2P: Failed to find the group with "
- "network name %s - stop join attempt",
- wpa_ssid_txt(ssid.data(), ssid.size()));
- notifyGroupJoinFailure(wpa_s);
- pending_scan_res_join_callback = NULL;
- };
-
- wpa_s->p2p_join_scan_count = 0;
- pending_join_scan_callback();
- if (pending_scan_res_join_callback == NULL) {
+ if (joinGroup(wpa_s, peer_address.data(), ssid, passphrase, freq)) {
return createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
"Failed to start scan.");
}
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index a3da86c..dcc28be 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -240,7 +240,7 @@
/**
* wpa_bss_get - Fetch a BSS table entry based on BSSID and SSID
* @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID
+ * @bssid: BSSID, or %NULL to match any BSSID
* @ssid: SSID
* @ssid_len: Length of @ssid
* Returns: Pointer to the BSS entry or %NULL if not found
@@ -252,7 +252,8 @@
if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
return NULL;
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
+ if ((!bssid ||
+ os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) &&
bss->ssid_len == ssid_len &&
os_memcmp(bss->ssid, ssid, ssid_len) == 0)
return bss;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 7118cab..314d741 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -6879,7 +6879,7 @@
return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
vht_center_freq2, 0, ht40, vht,
vht_chwidth, he, edmg,
- NULL, 0, 0, allow_6ghz);
+ NULL, 0, 0, allow_6ghz, 0);
}
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index de79178..370aee2 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -355,6 +355,7 @@
char *pg_object_path = NULL;
int persistent_group = 0;
int freq = 0;
+ int retry_limit = 0;
char *iface = NULL;
unsigned int group_id = 0;
struct wpa_ssid *ssid;
@@ -376,6 +377,11 @@
freq = entry.int32_value;
if (freq <= 0)
goto inv_args_clear;
+ } else if (os_strcmp(entry.key, "retry_limit") == 0 &&
+ entry.type == DBUS_TYPE_INT32) {
+ retry_limit = entry.int32_value;
+ if (retry_limit <= 0)
+ goto inv_args_clear;
} else if (os_strcmp(entry.key, "persistent_group_object") ==
0 &&
entry.type == DBUS_TYPE_OBJECT_PATH)
@@ -426,7 +432,7 @@
if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
0, 0, 0, 0, NULL, 0, 0,
- false)) {
+ false, retry_limit)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index aa01245..b066d62 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2409,6 +2409,9 @@
if (res == 1)
return 0;
+ if (wpas_p2p_retry_limit_exceeded(wpa_s)) {
+ return 0;
+ }
if (wpa_s->p2p_in_provisioning ||
wpa_s->show_group_started ||
wpa_s->p2p_in_invitation) {
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 0bfb962..ab1555e 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -365,9 +365,9 @@
wpa_printf(MSG_DEBUG,
"P2P: Exclude 6 GHz channels - update the scan frequency list");
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
- 0);
+ false, false);
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
- 0);
+ false, false);
}
ret = wpa_drv_scan(wpa_s, params);
if (ret == 0)
@@ -996,6 +996,7 @@
}
wpa_s->p2p_in_invitation = 0;
+ wpa_s->p2p_retry_limit = 0;
eloop_cancel_timeout(wpas_p2p_move_go, wpa_s, NULL);
eloop_cancel_timeout(wpas_p2p_reconsider_moving_go, wpa_s, NULL);
@@ -1390,6 +1391,7 @@
wpa_s->p2p_in_provisioning = 0;
}
wpa_s->p2p_in_invitation = 0;
+ wpa_s->p2p_retry_limit = 0;
wpa_s->group_formation_reported = 1;
if (!success) {
@@ -2407,6 +2409,21 @@
}
+bool wpas_p2p_retry_limit_exceeded(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->p2p_in_invitation || !wpa_s->p2p_retry_limit ||
+ wpa_s->p2p_in_invitation <= wpa_s->p2p_retry_limit) {
+ return false;
+ }
+ wpa_printf(MSG_DEBUG, "P2P: Group join retry limit exceeded");
+ eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
+ wpa_s->p2pdev, NULL);
+ eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
+ wpa_s->p2pdev, NULL);
+ return true;
+}
+
+
static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
{
struct wpa_supplicant *wpa_s = ctx;
@@ -3292,7 +3309,7 @@
wpa_s->conf->p2p_go_he,
wpa_s->conf->p2p_go_edmg, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
- 1, is_p2p_allow_6ghz(wpa_s->global->p2p));
+ 1, is_p2p_allow_6ghz(wpa_s->global->p2p), 0);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
wpa_msg_global(wpa_s, MSG_INFO,
@@ -3522,7 +3539,7 @@
ssid->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
0, 1,
- is_p2p_allow_6ghz(wpa_s->global->p2p));
+ is_p2p_allow_6ghz(wpa_s->global->p2p), 0);
}
@@ -4602,7 +4619,7 @@
persistent_go->mode ==
WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
- 0, 0, false);
+ 0, 0, false, 0);
} else if (response_done) {
wpas_p2p_group_add(wpa_s, 1, freq,
0, 0, 0, 0, 0, 0, false);
@@ -4725,7 +4742,7 @@
NULL,
persistent_go->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0,
- is_p2p_allow_6ghz(wpa_s->global->p2p));
+ is_p2p_allow_6ghz(wpa_s->global->p2p), 0);
} else {
wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
is_p2p_allow_6ghz(wpa_s->global->p2p));
@@ -5543,9 +5560,9 @@
wpa_printf(MSG_DEBUG,
"P2P: 6 GHz disabled - update the scan frequency list");
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, ¶ms,
- 0);
+ false, false);
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms,
- 0);
+ false, false);
}
ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
@@ -6954,7 +6971,7 @@
static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
struct wpa_ssid *params, int addr_allocated,
- int freq, int force_scan)
+ int freq, int force_scan, int retry_limit)
{
struct wpa_ssid *ssid;
int other_iface_found = 0;
@@ -6997,8 +7014,14 @@
if (params->passphrase)
ssid->passphrase = os_strdup(params->passphrase);
+ if (params->bssid_set) {
+ ssid->bssid_set = 1;
+ os_memcpy(ssid->bssid, params->bssid, ETH_ALEN);
+ }
+
wpa_s->show_group_started = 1;
wpa_s->p2p_in_invitation = 1;
+ wpa_s->p2p_retry_limit = retry_limit;
wpa_s->p2p_invite_go_freq = freq;
wpa_s->p2p_go_group_formation_completed = 0;
wpa_s->global->p2p_group_formation = wpa_s;
@@ -7042,7 +7065,7 @@
int edmg,
const struct p2p_channels *channels,
int connection_timeout, int force_scan,
- bool allow_6ghz)
+ bool allow_6ghz, int retry_limit)
{
struct p2p_go_neg_results params;
int go = 0, freq;
@@ -7111,7 +7134,7 @@
}
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq,
- force_scan);
+ force_scan, retry_limit);
} else {
return -1;
}
@@ -7867,6 +7890,7 @@
wpa_s->global->p2p_group_formation = NULL;
wpa_s->p2p_in_provisioning = 0;
wpa_s->p2p_in_invitation = 0;
+ wpa_s->p2p_retry_limit = 0;
}
os_memset(go_dev_addr, 0, ETH_ALEN);
@@ -8696,6 +8720,7 @@
wpa_s->global->p2p_group_formation = NULL;
wpa_s->p2p_in_provisioning = 0;
wpa_s->p2p_in_invitation = 0;
+ wpa_s->p2p_retry_limit = 0;
}
wpa_s->global->p2p_go_wait_client.sec = 0;
if (addr == NULL)
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 5a869e7..949044a 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -52,7 +52,7 @@
int max_oper_chwidth, int he, int edmg,
const struct p2p_channels *channels,
int connection_timeout, int force_scan,
- bool allow_6ghz);
+ bool allow_6ghz, int retry_limit);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
enum wpas_p2p_prov_disc_use {
@@ -206,6 +206,7 @@
int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s);
int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s);
void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s);
+bool wpas_p2p_retry_limit_exceeded(struct wpa_supplicant *wpa_s);
void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s);
void wpas_p2p_deinit_iface(struct wpa_supplicant *wpa_s);
void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index ee90aac..faa97e0 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -444,16 +444,63 @@
if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
/*
+ * Perform a single-channel scan if the GO has already been
+ * discovered on another non-P2P interface. Note that a scan
+ * initiated by a P2P interface (e.g. the device interface)
+ * should already have sufficient IEs and scan results will be
+ * fetched on interface creation in that case.
+ */
+ if (wpa_s->p2p_in_invitation == 1 && wpa_s->current_ssid) {
+ struct wpa_supplicant *ifs;
+ struct wpa_bss *bss = NULL;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ u8 *bssid = ssid->bssid_set ? ssid->bssid : NULL;
+ dl_list_for_each(ifs, &wpa_s->radio->ifaces,
+ struct wpa_supplicant, radio_list) {
+ bss = wpa_bss_get(ifs, bssid, ssid->ssid,
+ ssid->ssid_len);
+ if (bss)
+ break;
+ }
+ if (bss && !disabled_freq(wpa_s, bss->freq)) {
+ params->freqs = os_calloc(2, sizeof(int));
+ if (params->freqs)
+ params->freqs[0] = bss->freq;
+ }
+ }
+ /*
* Optimize scan based on GO information during persistent
* group reinvocation
*/
- if (wpa_s->p2p_in_invitation < 5 &&
+ if (params->freqs == NULL && wpa_s->p2p_in_invitation < 5 &&
wpa_s->p2p_invite_go_freq > 0) {
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
- wpa_s->p2p_invite_go_freq);
- params->freqs = os_calloc(2, sizeof(int));
- if (params->freqs)
- params->freqs[0] = wpa_s->p2p_invite_go_freq;
+ if (wpa_s->p2p_invite_go_freq == 2 ||
+ wpa_s->p2p_invite_go_freq == 5) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred band %d GHz during invitation",
+ wpa_s->p2p_invite_go_freq);
+ enum hostapd_hw_mode mode;
+ if (wpa_s->hw.modes == NULL)
+ return;
+ mode = wpa_s->p2p_invite_go_freq == 5 ?
+ HOSTAPD_MODE_IEEE80211A :
+ HOSTAPD_MODE_IEEE80211G;
+ if (wpa_s->p2p_in_invitation <= 2)
+ wpa_add_scan_freqs_list(wpa_s, mode,
+ params, false,
+ true);
+ if (params->freqs == NULL ||
+ (params->freqs && params->freqs[0] == 0))
+ wpa_add_scan_freqs_list(wpa_s, mode,
+ params, false,
+ false);
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
+ wpa_s->p2p_invite_go_freq);
+ params->freqs = os_calloc(2, sizeof(int));
+ if (params->freqs)
+ params->freqs[0] =
+ wpa_s->p2p_invite_go_freq;
+ }
}
wpa_s->p2p_in_invitation++;
if (wpa_s->p2p_in_invitation > 20) {
@@ -465,6 +512,7 @@
*/
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation");
wpa_s->p2p_in_invitation = 0;
+ wpa_s->p2p_retry_limit = 0;
}
}
#endif /* CONFIG_P2P */
@@ -709,7 +757,8 @@
int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s,
enum hostapd_hw_mode band,
- struct wpa_driver_scan_params *params, bool is_6ghz)
+ struct wpa_driver_scan_params *params, bool is_6ghz,
+ bool exclude_radar)
{
/* Include only supported channels for the specified band */
struct hostapd_hw_modes *mode;
@@ -734,6 +783,8 @@
for (i = 0; i < mode->num_channels; i++) {
if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
continue;
+ if (exclude_radar && (mode->channels[i].flag & HOSTAPD_CHAN_RADAR))
+ continue;
params->freqs[num_chans++] = mode->channels[i].freq;
}
params->freqs[num_chans] = 0;
@@ -752,13 +803,13 @@
if (wpa_s->setband_mask & WPA_SETBAND_5G)
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
- false);
+ false, false);
if (wpa_s->setband_mask & WPA_SETBAND_2G)
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
- false);
+ false, false);
if (wpa_s->setband_mask & WPA_SETBAND_6G)
wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
- true);
+ true, false);
}
@@ -1375,9 +1426,9 @@
* since the 6 GHz band is disabled for P2P uses. */
wpa_printf(MSG_DEBUG,
"P2P: 6 GHz disabled - update the scan frequency list");
- wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, ¶ms, false);
- wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms, false);
- wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211AD, ¶ms, false);
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, ¶ms, false, false);
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms, false, false);
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211AD, ¶ms, false, false);
}
#endif /* CONFIG_P2P */
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index f826d91..52d2696 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -92,6 +92,7 @@
int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s,
enum hostapd_hw_mode band,
struct wpa_driver_scan_params *params,
- bool is_6ghz);
+ bool is_6ghz,
+ bool exclude_radar);
#endif /* SCAN_H */
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index faec32b..e673a9c 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1124,6 +1124,7 @@
int p2p_sd_over_ctrl_iface;
int p2p_in_provisioning;
int p2p_in_invitation;
+ int p2p_retry_limit;
int p2p_invite_go_freq;
int pending_invite_ssid_id;
int show_group_started;