P2P: Add option for Provision Discovery before GO Negotiation
This is a workaround for interoperability issues with some deployed P2P implementations that require a Provision Discovery exchange to be used before GO Negotiation. The new provdisc parameter for the p2p_connect command can be used to request this behavior without having to run a separate p2p_prov_disc command. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
1cbe86e2d6
commit
3bc462cb88
12 changed files with 65 additions and 14 deletions
|
@ -2868,7 +2868,7 @@ static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr,
|
||||||
return -1;
|
return -1;
|
||||||
return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent,
|
return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent,
|
||||||
own_interface_addr, force_freq, persistent_group,
|
own_interface_addr, force_freq, persistent_group,
|
||||||
NULL, 0);
|
NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1173,16 +1173,17 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
enum p2p_wps_method wps_method,
|
enum p2p_wps_method wps_method,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group,
|
unsigned int force_freq, int persistent_group,
|
||||||
const u8 *force_ssid, size_t force_ssid_len)
|
const u8 *force_ssid, size_t force_ssid_len,
|
||||||
|
int pd_before_go_neg)
|
||||||
{
|
{
|
||||||
struct p2p_device *dev;
|
struct p2p_device *dev;
|
||||||
|
|
||||||
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
|
||||||
"P2P: Request to start group negotiation - peer=" MACSTR
|
"P2P: Request to start group negotiation - peer=" MACSTR
|
||||||
" GO Intent=%d Intended Interface Address=" MACSTR
|
" GO Intent=%d Intended Interface Address=" MACSTR
|
||||||
" wps_method=%d persistent_group=%d",
|
" wps_method=%d persistent_group=%d pd_before_go_neg=%d",
|
||||||
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
|
MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr),
|
||||||
wps_method, persistent_group);
|
wps_method, persistent_group, pd_before_go_neg);
|
||||||
|
|
||||||
if (p2p_prepare_channel(p2p, force_freq) < 0)
|
if (p2p_prepare_channel(p2p, force_freq) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1232,6 +1233,10 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
||||||
dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
|
dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
|
||||||
dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
|
dev->flags &= ~P2P_DEV_WAIT_GO_NEG_CONFIRM;
|
||||||
|
if (pd_before_go_neg)
|
||||||
|
dev->flags |= P2P_DEV_PD_BEFORE_GO_NEG;
|
||||||
|
else
|
||||||
|
dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
|
||||||
dev->connect_reqs = 0;
|
dev->connect_reqs = 0;
|
||||||
dev->go_neg_req_sent = 0;
|
dev->go_neg_req_sent = 0;
|
||||||
dev->go_state = UNKNOWN_GO;
|
dev->go_state = UNKNOWN_GO;
|
||||||
|
|
|
@ -880,13 +880,17 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout);
|
||||||
* @force_ssid: Forced SSID for the group if we become GO or %NULL to generate
|
* @force_ssid: Forced SSID for the group if we become GO or %NULL to generate
|
||||||
* a new SSID
|
* a new SSID
|
||||||
* @force_ssid_len: Length of $force_ssid buffer
|
* @force_ssid_len: Length of $force_ssid buffer
|
||||||
|
* @pd_before_go_neg: Whether to send Provision Discovery prior to GO
|
||||||
|
* Negotiation as an interoperability workaround when initiating group
|
||||||
|
* formation
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||||
enum p2p_wps_method wps_method,
|
enum p2p_wps_method wps_method,
|
||||||
int go_intent, const u8 *own_interface_addr,
|
int go_intent, const u8 *own_interface_addr,
|
||||||
unsigned int force_freq, int persistent_group,
|
unsigned int force_freq, int persistent_group,
|
||||||
const u8 *force_ssid, size_t force_ssid_len);
|
const u8 *force_ssid, size_t force_ssid_len,
|
||||||
|
int pd_before_go_neg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* p2p_authorize - Authorize P2P group formation (GO negotiation)
|
* p2p_authorize - Authorize P2P group formation (GO negotiation)
|
||||||
|
|
|
@ -184,6 +184,23 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
|
||||||
struct wpabuf *req;
|
struct wpabuf *req;
|
||||||
int freq;
|
int freq;
|
||||||
|
|
||||||
|
if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
|
||||||
|
u16 config_method;
|
||||||
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
|
||||||
|
"P2P: Use PD-before-GO-Neg workaround for " MACSTR,
|
||||||
|
MAC2STR(dev->info.p2p_device_addr));
|
||||||
|
if (dev->wps_method == WPS_PIN_DISPLAY)
|
||||||
|
config_method = WPS_CONFIG_KEYPAD;
|
||||||
|
else if (dev->wps_method == WPS_PIN_KEYPAD)
|
||||||
|
config_method = WPS_CONFIG_DISPLAY;
|
||||||
|
else if (dev->wps_method == WPS_PBC)
|
||||||
|
config_method = WPS_CONFIG_PUSHBUTTON;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
return p2p_prov_disc_req(p2p, dev->info.p2p_device_addr,
|
||||||
|
config_method, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
|
freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
|
||||||
if (freq <= 0) {
|
if (freq <= 0) {
|
||||||
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
|
||||||
|
|
|
@ -90,6 +90,7 @@ struct p2p_device {
|
||||||
#define P2P_DEV_PD_FOR_JOIN BIT(14)
|
#define P2P_DEV_PD_FOR_JOIN BIT(14)
|
||||||
#define P2P_DEV_REPORTED_ONCE BIT(15)
|
#define P2P_DEV_REPORTED_ONCE BIT(15)
|
||||||
#define P2P_DEV_PREFER_PERSISTENT_RECONN BIT(16)
|
#define P2P_DEV_PREFER_PERSISTENT_RECONN BIT(16)
|
||||||
|
#define P2P_DEV_PD_BEFORE_GO_NEG BIT(17)
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
int status; /* enum p2p_status_code */
|
int status; /* enum p2p_status_code */
|
||||||
|
|
|
@ -288,6 +288,15 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
|
||||||
out:
|
out:
|
||||||
dev->req_config_methods = 0;
|
dev->req_config_methods = 0;
|
||||||
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
|
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
|
||||||
|
if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
|
||||||
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
|
||||||
|
"P2P: Start GO Neg after the PD-before-GO-Neg "
|
||||||
|
"workaround with " MACSTR,
|
||||||
|
MAC2STR(dev->info.p2p_device_addr));
|
||||||
|
dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
|
||||||
|
p2p_connect_send(p2p, dev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (success && p2p->cfg->prov_disc_resp)
|
if (success && p2p->cfg->prov_disc_resp)
|
||||||
p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
|
p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
|
||||||
report_config_methods);
|
report_config_methods);
|
||||||
|
|
|
@ -119,7 +119,7 @@ join-a-group style PD instead of GO Negotiation style PD.
|
||||||
|
|
||||||
p2p_connect <peer device address> <pbc|pin|PIN#> [display|keypad]
|
p2p_connect <peer device address> <pbc|pin|PIN#> [display|keypad]
|
||||||
[persistent|persistent=<network id>] [join|auth]
|
[persistent|persistent=<network id>] [join|auth]
|
||||||
[go_intent=<0..15>] [freq=<in MHz>]
|
[go_intent=<0..15>] [freq=<in MHz>] [provdisc]
|
||||||
|
|
||||||
Start P2P group formation with a discovered P2P peer. This includes
|
Start P2P group formation with a discovered P2P peer. This includes
|
||||||
optional group owner negotiation, group interface setup, provisioning,
|
optional group owner negotiation, group interface setup, provisioning,
|
||||||
|
@ -155,6 +155,11 @@ Negotiation.
|
||||||
"freq" can be used to set a forced operating channel (e.g., freq=2412
|
"freq" can be used to set a forced operating channel (e.g., freq=2412
|
||||||
to select 2.4 GHz channel 1).
|
to select 2.4 GHz channel 1).
|
||||||
|
|
||||||
|
"provdisc" can be used to request a Provision Discovery exchange to be
|
||||||
|
used prior to starting GO Negotiation as a workaround with some deployed
|
||||||
|
P2P implementations that require this to allow the user to accept the
|
||||||
|
connection.
|
||||||
|
|
||||||
p2p_group_add [persistent|persistent=<network id>] [freq=<freq in MHz>]
|
p2p_group_add [persistent|persistent=<network id>] [freq=<freq in MHz>]
|
||||||
|
|
||||||
Set up a P2P group owner manually (i.e., without group owner
|
Set up a P2P group owner manually (i.e., without group owner
|
||||||
|
|
|
@ -2824,10 +2824,11 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
||||||
int automatic;
|
int automatic;
|
||||||
int go_intent = -1;
|
int go_intent = -1;
|
||||||
int freq = 0;
|
int freq = 0;
|
||||||
|
int pd;
|
||||||
|
|
||||||
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
|
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
|
||||||
* [persistent|persistent=<network id>]
|
* [persistent|persistent=<network id>]
|
||||||
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */
|
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] */
|
||||||
|
|
||||||
if (hwaddr_aton(cmd, addr))
|
if (hwaddr_aton(cmd, addr))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2854,6 +2855,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
||||||
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;
|
automatic = os_strstr(pos, " auto") != NULL;
|
||||||
|
pd = os_strstr(pos, " provdisc") != NULL;
|
||||||
|
|
||||||
pos2 = os_strstr(pos, " go_intent=");
|
pos2 = os_strstr(pos, " go_intent=");
|
||||||
if (pos2) {
|
if (pos2) {
|
||||||
|
@ -2889,7 +2891,7 @@ 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, automatic, join,
|
persistent_group, automatic, join,
|
||||||
auth, go_intent, freq, persistent_id);
|
auth, go_intent, freq, persistent_id, pd);
|
||||||
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;
|
||||||
|
|
|
@ -504,7 +504,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
|
||||||
|
|
||||||
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
||||||
persistent_group, 0, join, authorize_only,
|
persistent_group, 0, join, authorize_only,
|
||||||
go_intent, freq, -1);
|
go_intent, freq, -1, 0);
|
||||||
|
|
||||||
if (new_pin >= 0) {
|
if (new_pin >= 0) {
|
||||||
char npin[9];
|
char npin[9];
|
||||||
|
|
|
@ -2611,7 +2611,8 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
|
return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
|
||||||
go_intent, own_interface_addr, force_freq,
|
go_intent, own_interface_addr, force_freq,
|
||||||
persistent_group, ssid ? ssid->ssid : NULL,
|
persistent_group, ssid ? ssid->ssid : NULL,
|
||||||
ssid ? ssid->ssid_len : 0);
|
ssid ? ssid->ssid_len : 0,
|
||||||
|
wpa_s->p2p_pd_before_go_neg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2791,7 +2792,8 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
|
||||||
wpa_s->p2p_persistent_group, 0, 0, 0,
|
wpa_s->p2p_persistent_group, 0, 0, 0,
|
||||||
wpa_s->p2p_go_intent,
|
wpa_s->p2p_go_intent,
|
||||||
wpa_s->p2p_connect_freq,
|
wpa_s->p2p_connect_freq,
|
||||||
wpa_s->p2p_persistent_id);
|
wpa_s->p2p_persistent_id,
|
||||||
|
wpa_s->p2p_pd_before_go_neg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3064,6 +3066,8 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
|
||||||
* @freq: Frequency for the group or 0 for auto-selection
|
* @freq: Frequency for the group or 0 for auto-selection
|
||||||
* @persistent_id: Persistent group credentials to use for forcing GO
|
* @persistent_id: Persistent group credentials to use for forcing GO
|
||||||
* parameters or -1 to generate new values (SSID/passphrase)
|
* parameters or -1 to generate new values (SSID/passphrase)
|
||||||
|
* @pd: Whether to send Provision Discovery prior to GO Negotiation as an
|
||||||
|
* interoperability workaround when initiating group formation
|
||||||
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
|
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
|
||||||
* failure, -2 on failure due to channel not currently available,
|
* failure, -2 on failure due to channel not currently available,
|
||||||
* -3 if forced channel is not supported
|
* -3 if forced channel is not supported
|
||||||
|
@ -3071,7 +3075,7 @@ 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 auto_join, int join, int auth,
|
int persistent_group, int auto_join, int join, int auth,
|
||||||
int go_intent, int freq, int persistent_id)
|
int go_intent, int freq, int persistent_id, int pd)
|
||||||
{
|
{
|
||||||
int force_freq = 0, oper_freq = 0;
|
int force_freq = 0, oper_freq = 0;
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
|
@ -3102,6 +3106,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
wpa_s->p2p_go_intent = go_intent;
|
wpa_s->p2p_go_intent = go_intent;
|
||||||
wpa_s->p2p_connect_freq = freq;
|
wpa_s->p2p_connect_freq = freq;
|
||||||
wpa_s->p2p_fallback_to_go_neg = 0;
|
wpa_s->p2p_fallback_to_go_neg = 0;
|
||||||
|
wpa_s->p2p_pd_before_go_neg = !!pd;
|
||||||
|
|
||||||
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));
|
||||||
|
@ -4845,7 +4850,8 @@ static void wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
|
||||||
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin,
|
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,
|
wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
|
||||||
0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
|
0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
|
||||||
wpa_s->p2p_persistent_id);
|
wpa_s->p2p_persistent_id,
|
||||||
|
wpa_s->p2p_pd_before_go_neg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ 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 auto_join, int join,
|
int persistent_group, int auto_join, int join,
|
||||||
int auth, int go_intent, int freq, int persistent_id);
|
int auth, int go_intent, int freq, int persistent_id,
|
||||||
|
int pd);
|
||||||
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,
|
||||||
|
|
|
@ -520,6 +520,7 @@ struct wpa_supplicant {
|
||||||
unsigned int p2p_auto_pd:1;
|
unsigned int p2p_auto_pd:1;
|
||||||
unsigned int p2p_persistent_group:1;
|
unsigned int p2p_persistent_group:1;
|
||||||
unsigned int p2p_fallback_to_go_neg:1;
|
unsigned int p2p_fallback_to_go_neg:1;
|
||||||
|
unsigned int p2p_pd_before_go_neg:1;
|
||||||
int p2p_persistent_id;
|
int p2p_persistent_id;
|
||||||
int p2p_go_intent;
|
int p2p_go_intent;
|
||||||
int p2p_connect_freq;
|
int p2p_connect_freq;
|
||||||
|
|
Loading…
Add table
Reference in a new issue