P2P: Add automatic GO Negotiation vs. join-a-group selection
p2p_connect command can now be used with an optional "auto" parameter to request wpa_supplicant to determine automatically whether to use join-a-group operation (if the peer is operating as a GO) or group formation. This makes it easier for external programs to handle connection type selection by offloading this to wpa_supplicant. The previously used p2p_connect join commands can be replaced with p2p_connect auto to use this new mechanism. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
7b63c6396a
commit
b31be3a0fd
5 changed files with 81 additions and 17 deletions
|
@ -2858,6 +2858,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
||||||
int persistent_group;
|
int persistent_group;
|
||||||
int join;
|
int join;
|
||||||
int auth;
|
int auth;
|
||||||
|
int automatic;
|
||||||
int go_intent = -1;
|
int go_intent = -1;
|
||||||
int freq = 0;
|
int freq = 0;
|
||||||
|
|
||||||
|
@ -2875,6 +2876,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
||||||
persistent_group = os_strstr(pos, " persistent") != NULL;
|
persistent_group = os_strstr(pos, " persistent") != NULL;
|
||||||
join = os_strstr(pos, " join") != NULL;
|
join = os_strstr(pos, " join") != NULL;
|
||||||
auth = os_strstr(pos, " auth") != NULL;
|
auth = os_strstr(pos, " auth") != NULL;
|
||||||
|
automatic = os_strstr(pos, " auto") != NULL;
|
||||||
|
|
||||||
pos2 = os_strstr(pos, " go_intent=");
|
pos2 = os_strstr(pos, " go_intent=");
|
||||||
if (pos2) {
|
if (pos2) {
|
||||||
|
@ -2909,8 +2911,8 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
||||||
persistent_group, join, auth, go_intent,
|
persistent_group, automatic, join,
|
||||||
freq);
|
auth, go_intent, freq);
|
||||||
if (new_pin == -2) {
|
if (new_pin == -2) {
|
||||||
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
|
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
|
||||||
return 25;
|
return 25;
|
||||||
|
|
|
@ -508,7 +508,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
|
||||||
goto inv_args;
|
goto inv_args;
|
||||||
|
|
||||||
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
||||||
persistent_group, join, authorize_only,
|
persistent_group, 0, join, authorize_only,
|
||||||
go_intent, freq);
|
go_intent, freq);
|
||||||
|
|
||||||
if (new_pin >= 0) {
|
if (new_pin >= 0) {
|
||||||
|
|
|
@ -55,7 +55,8 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
|
||||||
static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s);
|
static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s);
|
||||||
static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
|
static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
|
||||||
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
|
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
|
||||||
const u8 *dev_addr, enum p2p_wps_method wps_method);
|
const u8 *dev_addr, enum p2p_wps_method wps_method,
|
||||||
|
int auto_join);
|
||||||
static void wpas_p2p_pd_before_join_timeout(void *eloop_ctx,
|
static void wpas_p2p_pd_before_join_timeout(void *eloop_ctx,
|
||||||
void *timeout_ctx);
|
void *timeout_ctx);
|
||||||
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
|
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
|
||||||
|
@ -1969,7 +1970,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
|
||||||
wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0);
|
wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0);
|
||||||
} else if (bssid) {
|
} else if (bssid) {
|
||||||
wpas_p2p_join(wpa_s, bssid, go_dev_addr,
|
wpas_p2p_join(wpa_s, bssid, go_dev_addr,
|
||||||
wpa_s->p2p_wps_method);
|
wpa_s->p2p_wps_method, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2647,6 +2648,31 @@ static int wpas_check_freq_conflict(struct wpa_supplicant *wpa_s, int freq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_p2p_peer_go(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *peer_dev_addr)
|
||||||
|
{
|
||||||
|
struct wpa_bss *bss;
|
||||||
|
int updated;
|
||||||
|
|
||||||
|
bss = wpa_bss_get_p2p_dev_addr(wpa_s, peer_dev_addr);
|
||||||
|
if (bss == NULL)
|
||||||
|
return 0;
|
||||||
|
if (bss->last_update_idx < wpa_s->bss_update_idx) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Peer BSS entry not updated in the "
|
||||||
|
"last scan");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
updated = os_time_before(&wpa_s->p2p_auto_started, &bss->last_update);
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Current BSS entry for peer updated at "
|
||||||
|
"%ld.%06ld (%supdated in last scan)",
|
||||||
|
bss->last_update.sec, bss->last_update.usec,
|
||||||
|
updated ? "": "not ");
|
||||||
|
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
|
static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_scan_results *scan_res)
|
struct wpa_scan_results *scan_res)
|
||||||
{
|
{
|
||||||
|
@ -2659,12 +2685,29 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
|
||||||
if (wpa_s->global->p2p_disabled)
|
if (wpa_s->global->p2p_disabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS) for join",
|
wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS) for %sjoin",
|
||||||
scan_res ? (int) scan_res->num : -1);
|
scan_res ? (int) scan_res->num : -1,
|
||||||
|
wpa_s->p2p_auto_join ? "auto_" : "");
|
||||||
|
|
||||||
if (scan_res)
|
if (scan_res)
|
||||||
wpas_p2p_scan_res_handler(wpa_s, scan_res);
|
wpas_p2p_scan_res_handler(wpa_s, scan_res);
|
||||||
|
|
||||||
|
if (wpa_s->p2p_auto_join) {
|
||||||
|
if (!wpas_p2p_peer_go(wpa_s, wpa_s->pending_join_dev_addr)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
|
||||||
|
"running a GO -> use GO Negotiation");
|
||||||
|
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
|
||||||
|
wpa_s->p2p_pin, wpa_s->p2p_wps_method,
|
||||||
|
wpa_s->p2p_persistent_group, 0, 0, 0,
|
||||||
|
wpa_s->p2p_go_intent,
|
||||||
|
wpa_s->p2p_connect_freq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Peer was found running GO -> try "
|
||||||
|
"to join the group");
|
||||||
|
}
|
||||||
|
|
||||||
freq = p2p_get_oper_freq(wpa_s->global->p2p,
|
freq = p2p_get_oper_freq(wpa_s->global->p2p,
|
||||||
wpa_s->pending_join_iface_addr);
|
wpa_s->pending_join_iface_addr);
|
||||||
if (freq < 0 &&
|
if (freq < 0 &&
|
||||||
|
@ -2836,12 +2879,15 @@ static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
|
||||||
|
|
||||||
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
|
static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
|
||||||
const u8 *dev_addr, enum p2p_wps_method wps_method)
|
const u8 *dev_addr, enum p2p_wps_method wps_method,
|
||||||
|
int auto_join)
|
||||||
{
|
{
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
|
wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
|
||||||
MACSTR " dev " MACSTR ")",
|
MACSTR " dev " MACSTR ")%s",
|
||||||
MAC2STR(iface_addr), MAC2STR(dev_addr));
|
MAC2STR(iface_addr), MAC2STR(dev_addr),
|
||||||
|
auto_join ? " (auto_join)" : "");
|
||||||
|
|
||||||
|
wpa_s->p2p_auto_join = !!auto_join;
|
||||||
os_memcpy(wpa_s->pending_join_iface_addr, iface_addr, ETH_ALEN);
|
os_memcpy(wpa_s->pending_join_iface_addr, iface_addr, ETH_ALEN);
|
||||||
os_memcpy(wpa_s->pending_join_dev_addr, dev_addr, ETH_ALEN);
|
os_memcpy(wpa_s->pending_join_dev_addr, dev_addr, ETH_ALEN);
|
||||||
wpa_s->pending_join_wps_method = wps_method;
|
wpa_s->pending_join_wps_method = wps_method;
|
||||||
|
@ -2912,6 +2958,7 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
|
||||||
* @peer_addr: Address of the peer P2P Device
|
* @peer_addr: Address of the peer P2P Device
|
||||||
* @pin: PIN to use during provisioning or %NULL to indicate PBC mode
|
* @pin: PIN to use during provisioning or %NULL to indicate PBC mode
|
||||||
* @persistent_group: Whether to create a persistent group
|
* @persistent_group: Whether to create a persistent group
|
||||||
|
* @auto_join: Whether to select join vs. GO Negotiation automatically
|
||||||
* @join: Whether to join an existing group (as a client) instead of starting
|
* @join: Whether to join an existing group (as a client) instead of starting
|
||||||
* Group Owner negotiation; @peer_addr is BSSID in that case
|
* Group Owner negotiation; @peer_addr is BSSID in that case
|
||||||
* @auth: Whether to only authorize the connection instead of doing that and
|
* @auth: Whether to only authorize the connection instead of doing that and
|
||||||
|
@ -2924,8 +2971,8 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
|
||||||
*/
|
*/
|
||||||
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
const char *pin, enum p2p_wps_method wps_method,
|
const char *pin, enum p2p_wps_method wps_method,
|
||||||
int persistent_group, int join, int auth, int go_intent,
|
int persistent_group, int auto_join, int join, int auth,
|
||||||
int freq)
|
int go_intent, int freq)
|
||||||
{
|
{
|
||||||
int force_freq = 0, oper_freq = 0;
|
int force_freq = 0, oper_freq = 0;
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
|
@ -2943,6 +2990,9 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
wpa_s->p2p_long_listen = 0;
|
wpa_s->p2p_long_listen = 0;
|
||||||
|
|
||||||
wpa_s->p2p_wps_method = wps_method;
|
wpa_s->p2p_wps_method = wps_method;
|
||||||
|
wpa_s->p2p_persistent_group = !!persistent_group;
|
||||||
|
wpa_s->p2p_go_intent = go_intent;
|
||||||
|
wpa_s->p2p_connect_freq = freq;
|
||||||
|
|
||||||
if (pin)
|
if (pin)
|
||||||
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
|
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
|
||||||
|
@ -2955,7 +3005,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
} else
|
} else
|
||||||
wpa_s->p2p_pin[0] = '\0';
|
wpa_s->p2p_pin[0] = '\0';
|
||||||
|
|
||||||
if (join) {
|
if (join || auto_join) {
|
||||||
u8 iface_addr[ETH_ALEN], dev_addr[ETH_ALEN];
|
u8 iface_addr[ETH_ALEN], dev_addr[ETH_ALEN];
|
||||||
if (auth) {
|
if (auth) {
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Authorize invitation to "
|
wpa_printf(MSG_DEBUG, "P2P: Authorize invitation to "
|
||||||
|
@ -2971,8 +3021,15 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
p2p_get_dev_addr(wpa_s->global->p2p, peer_addr,
|
p2p_get_dev_addr(wpa_s->global->p2p, peer_addr,
|
||||||
dev_addr);
|
dev_addr);
|
||||||
}
|
}
|
||||||
if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method) <
|
if (auto_join) {
|
||||||
0)
|
os_get_time(&wpa_s->p2p_auto_started);
|
||||||
|
wpa_printf(MSG_DEBUG, "P2P: Auto join started at "
|
||||||
|
"%ld.%06ld",
|
||||||
|
wpa_s->p2p_auto_started.sec,
|
||||||
|
wpa_s->p2p_auto_started.usec);
|
||||||
|
}
|
||||||
|
if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
|
||||||
|
auto_join) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s);
|
||||||
void wpas_p2p_deinit_global(struct wpa_global *global);
|
void wpas_p2p_deinit_global(struct wpa_global *global);
|
||||||
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
const char *pin, enum p2p_wps_method wps_method,
|
const char *pin, enum p2p_wps_method wps_method,
|
||||||
int persistent_group, int join, int auth, int go_intent,
|
int persistent_group, int auto_join, int join,
|
||||||
int freq);
|
int auth, int go_intent, int freq);
|
||||||
void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
||||||
unsigned int freq, unsigned int duration);
|
unsigned int freq, unsigned int duration);
|
||||||
void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
||||||
|
|
|
@ -508,6 +508,11 @@ struct wpa_supplicant {
|
||||||
} removal_reason;
|
} removal_reason;
|
||||||
|
|
||||||
unsigned int p2p_cb_on_scan_complete:1;
|
unsigned int p2p_cb_on_scan_complete:1;
|
||||||
|
unsigned int p2p_auto_join:1;
|
||||||
|
unsigned int p2p_persistent_group:1;
|
||||||
|
int p2p_go_intent;
|
||||||
|
int p2p_connect_freq;
|
||||||
|
struct os_time p2p_auto_started;
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
struct wpa_ssid *bgscan_ssid;
|
struct wpa_ssid *bgscan_ssid;
|
||||||
|
|
Loading…
Reference in a new issue