P2P: Add option to force SSID/passphrase for GO Negotiation
An existing persistent group information can now be used to force GO Negotiation to use the previously used SSID/passphrase from a persistent group if we become a GO. This can be used as an alternative to inviting a new P2P peer to join the group (i.e., use GO Negotiation with GO intent 15 instead of starting an autonomous GO and using invitation), e.g., in case a GO Negotiation Request is received from a peer while we are not running as a GO. The persistent group to use for parameters is indicated with persistent=<network id> parameter to p2p_connect. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
0918c4bf3b
commit
23c84252a4
9 changed files with 101 additions and 21 deletions
|
@ -2867,7 +2867,8 @@ static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr,
|
|||
if (!drv->p2p)
|
||||
return -1;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1172,7 +1172,8 @@ static void p2p_set_dev_persistent(struct p2p_device *dev,
|
|||
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||
enum p2p_wps_method wps_method,
|
||||
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)
|
||||
{
|
||||
struct p2p_device *dev;
|
||||
|
||||
|
@ -1186,7 +1187,6 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
if (p2p_prepare_channel(p2p, force_freq) < 0)
|
||||
return -1;
|
||||
|
||||
p2p->ssid_set = 0;
|
||||
dev = p2p_get_device(p2p, peer_addr);
|
||||
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
|
||||
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
|
||||
|
@ -1219,6 +1219,15 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
*/
|
||||
}
|
||||
|
||||
p2p->ssid_set = 0;
|
||||
if (force_ssid) {
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
|
||||
force_ssid, force_ssid_len);
|
||||
os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
|
||||
p2p->ssid_len = force_ssid_len;
|
||||
p2p->ssid_set = 1;
|
||||
}
|
||||
|
||||
dev->flags &= ~P2P_DEV_NOT_YET_READY;
|
||||
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
||||
dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
|
||||
|
@ -1270,7 +1279,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
||||
enum p2p_wps_method wps_method,
|
||||
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)
|
||||
{
|
||||
struct p2p_device *dev;
|
||||
|
||||
|
@ -1292,6 +1302,15 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
return -1;
|
||||
}
|
||||
|
||||
p2p->ssid_set = 0;
|
||||
if (force_ssid) {
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
|
||||
force_ssid, force_ssid_len);
|
||||
os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
|
||||
p2p->ssid_len = force_ssid_len;
|
||||
p2p->ssid_set = 1;
|
||||
}
|
||||
|
||||
dev->flags &= ~P2P_DEV_NOT_YET_READY;
|
||||
dev->flags &= ~P2P_DEV_USER_REJECTED;
|
||||
dev->go_neg_req_sent = 0;
|
||||
|
|
|
@ -877,12 +877,16 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout);
|
|||
* @persistent_group: Whether to create a persistent group (0 = no, 1 =
|
||||
* persistent group without persistent reconnect, 2 = persistent group with
|
||||
* persistent reconnect)
|
||||
* @force_ssid: Forced SSID for the group if we become GO or %NULL to generate
|
||||
* a new SSID
|
||||
* @force_ssid_len: Length of $force_ssid buffer
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
||||
enum p2p_wps_method wps_method,
|
||||
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);
|
||||
|
||||
/**
|
||||
* p2p_authorize - Authorize P2P group formation (GO negotiation)
|
||||
|
@ -895,6 +899,9 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
* @persistent_group: Whether to create a persistent group (0 = no, 1 =
|
||||
* persistent group without persistent reconnect, 2 = persistent group with
|
||||
* persistent reconnect)
|
||||
* @force_ssid: Forced SSID for the group if we become GO or %NULL to generate
|
||||
* a new SSID
|
||||
* @force_ssid_len: Length of $force_ssid buffer
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This is like p2p_connect(), but the actual group negotiation is not
|
||||
|
@ -903,7 +910,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
|
|||
int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
|
||||
enum p2p_wps_method wps_method,
|
||||
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);
|
||||
|
||||
/**
|
||||
* p2p_reject - Reject peer device (explicitly block connection attempts)
|
||||
|
|
|
@ -118,7 +118,8 @@ out whether the peer device is operating as a GO and if so, use
|
|||
join-a-group style PD instead of GO Negotiation style PD.
|
||||
|
||||
p2p_connect <peer device address> <pbc|pin|PIN#> [display|keypad]
|
||||
[persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>]
|
||||
[persistent|persistent=<network id>] [join|auth]
|
||||
[go_intent=<0..15>] [freq=<in MHz>]
|
||||
|
||||
Start P2P group formation with a discovered P2P peer. This includes
|
||||
optional group owner negotiation, group interface setup, provisioning,
|
||||
|
@ -131,7 +132,12 @@ the command return code), PIN# means that a pre-selected PIN can be
|
|||
used (e.g., 12345670). [display|keypad] is used with PIN method
|
||||
to specify which PIN is used (display=dynamically generated random PIN
|
||||
from local display, keypad=PIN entered from peer display). "persistent"
|
||||
parameter can be used to request a persistent group to be formed.
|
||||
parameter can be used to request a persistent group to be formed. The
|
||||
"persistent=<network id>" alternative can be used to pre-populate
|
||||
SSID/passphrase configuration based on a previously used persistent
|
||||
group where this device was the GO. The previously used parameters will
|
||||
then be used if the local end becomes the GO in GO Negotiation (which
|
||||
can be forced with go_intent=15).
|
||||
|
||||
"join" indicates that this is a command to join an existing group as a
|
||||
client. It skips the GO Negotiation part. This will send a Provision
|
||||
|
|
|
@ -2855,14 +2855,15 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
|||
enum p2p_wps_method wps_method;
|
||||
int new_pin;
|
||||
int ret;
|
||||
int persistent_group;
|
||||
int persistent_group, persistent_id = -1;
|
||||
int join;
|
||||
int auth;
|
||||
int automatic;
|
||||
int go_intent = -1;
|
||||
int freq = 0;
|
||||
|
||||
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] [persistent]
|
||||
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
|
||||
* [persistent|persistent=<network id>]
|
||||
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */
|
||||
|
||||
if (hwaddr_aton(cmd, addr))
|
||||
|
@ -2874,6 +2875,19 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
|||
pos++;
|
||||
|
||||
persistent_group = os_strstr(pos, " persistent") != NULL;
|
||||
pos2 = os_strstr(pos, " persistent=");
|
||||
if (pos2) {
|
||||
struct wpa_ssid *ssid;
|
||||
persistent_id = atoi(pos2 + 12);
|
||||
ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
|
||||
if (ssid == NULL || ssid->disabled != 2 ||
|
||||
ssid->mode != WPAS_MODE_P2P_GO) {
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
|
||||
"SSID id=%d for persistent P2P group (GO)",
|
||||
persistent_id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
join = os_strstr(pos, " join") != NULL;
|
||||
auth = os_strstr(pos, " auth") != NULL;
|
||||
automatic = os_strstr(pos, " auto") != NULL;
|
||||
|
@ -2912,7 +2926,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
|||
|
||||
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
||||
persistent_group, automatic, join,
|
||||
auth, go_intent, freq);
|
||||
auth, go_intent, freq, persistent_id);
|
||||
if (new_pin == -2) {
|
||||
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
|
||||
return 25;
|
||||
|
|
|
@ -509,7 +509,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
|
|||
|
||||
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
|
||||
persistent_group, 0, join, authorize_only,
|
||||
go_intent, freq);
|
||||
go_intent, freq, -1);
|
||||
|
||||
if (new_pin >= 0) {
|
||||
char npin[9];
|
||||
|
|
|
@ -987,6 +987,20 @@ void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
|
|||
wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS);
|
||||
wpas_notify_p2p_go_neg_completed(wpa_s, res);
|
||||
|
||||
if (res->role_go && wpa_s->p2p_persistent_id >= 0) {
|
||||
struct wpa_ssid *ssid;
|
||||
ssid = wpa_config_get_network(wpa_s->conf,
|
||||
wpa_s->p2p_persistent_id);
|
||||
if (ssid && ssid->disabled == 2 &&
|
||||
ssid->mode == WPAS_MODE_P2P_GO && ssid->passphrase) {
|
||||
size_t len = os_strlen(ssid->passphrase);
|
||||
wpa_printf(MSG_DEBUG, "P2P: Override passphrase based "
|
||||
"on requested persistent group");
|
||||
os_memcpy(res->passphrase, ssid->passphrase, len);
|
||||
res->passphrase[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (wpa_s->create_p2p_iface) {
|
||||
struct wpa_supplicant *group_wpa_s =
|
||||
wpas_p2p_init_group_interface(wpa_s, res->role_go);
|
||||
|
@ -2559,7 +2573,8 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
|
|||
const u8 *peer_addr,
|
||||
enum p2p_wps_method wps_method,
|
||||
int go_intent, const u8 *own_interface_addr,
|
||||
unsigned int force_freq, int persistent_group)
|
||||
unsigned int force_freq, int persistent_group,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
if (persistent_group && wpa_s->conf->persistent_reconnect)
|
||||
persistent_group = 2;
|
||||
|
@ -2572,7 +2587,8 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
|
|||
|
||||
return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
|
||||
go_intent, own_interface_addr, force_freq,
|
||||
persistent_group);
|
||||
persistent_group, ssid ? ssid->ssid : NULL,
|
||||
ssid ? ssid->ssid_len : 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2580,7 +2596,8 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
|
|||
const u8 *peer_addr,
|
||||
enum p2p_wps_method wps_method,
|
||||
int go_intent, const u8 *own_interface_addr,
|
||||
unsigned int force_freq, int persistent_group)
|
||||
unsigned int force_freq, int persistent_group,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
if (persistent_group && wpa_s->conf->persistent_reconnect)
|
||||
persistent_group = 2;
|
||||
|
@ -2590,7 +2607,8 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
|
|||
|
||||
return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
|
||||
go_intent, own_interface_addr, force_freq,
|
||||
persistent_group);
|
||||
persistent_group, ssid ? ssid->ssid : NULL,
|
||||
ssid ? ssid->ssid_len : 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2745,7 +2763,8 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
|
|||
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);
|
||||
wpa_s->p2p_connect_freq,
|
||||
wpa_s->p2p_persistent_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3012,6 +3031,8 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
|
|||
* initiating Group Owner negotiation
|
||||
* @go_intent: GO Intent or -1 to use default
|
||||
* @freq: Frequency for the group or 0 for auto-selection
|
||||
* @persistent_id: Persistent group credentials to use for forcing GO
|
||||
* parameters or -1 to generate new values (SSID/passphrase)
|
||||
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
|
||||
* failure, -2 on failure due to channel not currently available,
|
||||
* -3 if forced channel is not supported
|
||||
|
@ -3019,17 +3040,25 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
|
|||
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||
const char *pin, enum p2p_wps_method wps_method,
|
||||
int persistent_group, int auto_join, int join, int auth,
|
||||
int go_intent, int freq)
|
||||
int go_intent, int freq, int persistent_id)
|
||||
{
|
||||
int force_freq = 0, oper_freq = 0;
|
||||
u8 bssid[ETH_ALEN];
|
||||
int ret = 0;
|
||||
enum wpa_driver_if_type iftype;
|
||||
const u8 *if_addr;
|
||||
struct wpa_ssid *ssid = NULL;
|
||||
|
||||
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
|
||||
return -1;
|
||||
|
||||
if (persistent_id >= 0) {
|
||||
ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
|
||||
if (ssid == NULL || ssid->disabled != 2 ||
|
||||
ssid->mode != WPAS_MODE_P2P_GO)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (go_intent < 0)
|
||||
go_intent = wpa_s->conf->p2p_go_intent;
|
||||
|
||||
|
@ -3038,6 +3067,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
|||
|
||||
wpa_s->p2p_wps_method = wps_method;
|
||||
wpa_s->p2p_persistent_group = !!persistent_group;
|
||||
wpa_s->p2p_persistent_id = persistent_id;
|
||||
wpa_s->p2p_go_intent = go_intent;
|
||||
wpa_s->p2p_connect_freq = freq;
|
||||
|
||||
|
@ -3149,14 +3179,15 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
|||
if (auth) {
|
||||
if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method,
|
||||
go_intent, if_addr,
|
||||
force_freq, persistent_group) < 0)
|
||||
force_freq, persistent_group, ssid) <
|
||||
0)
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method,
|
||||
go_intent, if_addr, force_freq,
|
||||
persistent_group) < 0) {
|
||||
persistent_group, ssid) < 0) {
|
||||
if (wpa_s->create_p2p_iface)
|
||||
wpas_p2p_remove_pending_group_interface(wpa_s);
|
||||
return -1;
|
||||
|
|
|
@ -20,7 +20,7 @@ void wpas_p2p_deinit_global(struct wpa_global *global);
|
|||
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||
const char *pin, enum p2p_wps_method wps_method,
|
||||
int persistent_group, int auto_join, int join,
|
||||
int auth, int go_intent, int freq);
|
||||
int auth, int go_intent, int freq, int persistent_id);
|
||||
void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
||||
unsigned int freq, unsigned int duration);
|
||||
void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
|
||||
|
|
|
@ -515,6 +515,7 @@ struct wpa_supplicant {
|
|||
unsigned int p2p_auto_join:1;
|
||||
unsigned int p2p_auto_pd:1;
|
||||
unsigned int p2p_persistent_group:1;
|
||||
int p2p_persistent_id;
|
||||
int p2p_go_intent;
|
||||
int p2p_connect_freq;
|
||||
struct os_time p2p_auto_started;
|
||||
|
|
Loading…
Reference in a new issue