@@ -240,7 +240,7 @@ void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
/**
* 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 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
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;
@@ -7128,7 +7128,7 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
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, 0);
+ NULL, 0, 0, allow_6ghz, 0, false);
}
@@ -356,6 +356,7 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
int persistent_group = 0;
int freq = 0;
int retry_limit = 0;
+ int force_go_bssid = 0;
char *iface = NULL;
unsigned int group_id = 0;
struct wpa_ssid *ssid;
@@ -382,6 +383,9 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
retry_limit = entry.int32_value;
if (retry_limit <= 0)
goto inv_args_clear;
+ } else if (os_strcmp(entry.key, "force_go_bssid") &&
+ entry.type == DBUS_TYPE_BOOLEAN) {
+ force_go_bssid = entry.bool_value;
} else if (os_strcmp(entry.key, "persistent_group_object") ==
0 &&
entry.type == DBUS_TYPE_OBJECT_PATH)
@@ -432,7 +436,8 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
0, 0, 0, 0, NULL, 0, 0,
- false, retry_limit)) {
+ false, retry_limit,
+ force_go_bssid)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
@@ -1162,7 +1162,7 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
}
-static int disabled_freq(struct wpa_supplicant *wpa_s, int freq)
+int disabled_freq(struct wpa_supplicant *wpa_s, int freq)
{
int i, j;
@@ -3299,7 +3299,8 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
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), 0);
+ 1, is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
+ false);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
wpa_msg_global(wpa_s, MSG_INFO,
@@ -3529,7 +3530,8 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
ssid->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
0, 1,
- is_p2p_allow_6ghz(wpa_s->global->p2p), 0);
+ is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
+ false);
}
@@ -4615,7 +4617,7 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
persistent_go->mode ==
WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
- 0, 0, false, 0);
+ 0, 0, false, 0, false);
} else if (response_done) {
wpas_p2p_group_add(wpa_s, 1, freq,
0, 0, 0, 0, 0, 0, false);
@@ -4738,7 +4740,7 @@ static int wpas_prov_disc_resp_cb(void *ctx)
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), 0);
+ is_p2p_allow_6ghz(wpa_s->global->p2p), 0, false);
} else {
wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
is_p2p_allow_6ghz(wpa_s->global->p2p));
@@ -6911,7 +6913,8 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
struct wpa_ssid *params, int addr_allocated,
- int freq, int force_scan, int retry_limit)
+ int freq, int force_scan, int retry_limit,
+ bool force_go_bssid)
{
struct wpa_ssid *ssid;
int other_iface_found = 0;
@@ -6954,6 +6957,11 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
if (params->passphrase)
ssid->passphrase = os_strdup(params->passphrase);
+ if (force_go_bssid && 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;
@@ -7000,7 +7008,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
int edmg,
const struct p2p_channels *channels,
int connection_timeout, int force_scan,
- bool allow_6ghz, int retry_limit)
+ bool allow_6ghz, int retry_limit,
+ bool force_go_bssid)
{
struct p2p_go_neg_results params;
int go = 0, freq;
@@ -7068,7 +7077,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
}
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq,
- force_scan, retry_limit);
+ force_scan, retry_limit,
+ force_go_bssid);
} else {
return -1;
}
@@ -52,7 +52,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
int max_oper_chwidth, int he, int edmg,
const struct p2p_channels *channels,
int connection_timeout, int force_scan,
- bool allow_6ghz, int retry_limit);
+ bool allow_6ghz, int retry_limit,
+ bool force_go_bssid);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
enum wpas_p2p_prov_disc_use {
@@ -445,11 +445,36 @@ static void wpa_supplicant_optimize_freqs(
}
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) {
if (wpa_s->p2p_invite_go_freq == 2 ||
wpa_s->p2p_invite_go_freq == 5) {
@@ -1823,6 +1823,7 @@ int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
int *freq_array, unsigned int len,
bool exclude_current);
+int disabled_freq(struct wpa_supplicant *wpa_s, int freq);
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx);