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:
Jouni Malinen 2012-04-27 18:17:10 +03:00 committed by Jouni Malinen
parent 0918c4bf3b
commit 23c84252a4
9 changed files with 101 additions and 21 deletions

View file

@ -2867,7 +2867,8 @@ static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr,
if (!drv->p2p) if (!drv->p2p)
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);
} }

View file

@ -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, 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)
{ {
struct p2p_device *dev; 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) if (p2p_prepare_channel(p2p, force_freq) < 0)
return -1; return -1;
p2p->ssid_set = 0;
dev = p2p_get_device(p2p, peer_addr); dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 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_NOT_YET_READY;
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;
@ -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, int p2p_authorize(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)
{ {
struct p2p_device *dev; struct p2p_device *dev;
@ -1292,6 +1302,15 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
return -1; 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_NOT_YET_READY;
dev->flags &= ~P2P_DEV_USER_REJECTED; dev->flags &= ~P2P_DEV_USER_REJECTED;
dev->go_neg_req_sent = 0; dev->go_neg_req_sent = 0;

View file

@ -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: Whether to create a persistent group (0 = no, 1 =
* persistent group without persistent reconnect, 2 = persistent group with * persistent group without persistent reconnect, 2 = persistent group with
* persistent reconnect) * 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 * 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);
/** /**
* p2p_authorize - Authorize P2P group formation (GO negotiation) * 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: Whether to create a persistent group (0 = no, 1 =
* persistent group without persistent reconnect, 2 = persistent group with * persistent group without persistent reconnect, 2 = persistent group with
* persistent reconnect) * 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 * Returns: 0 on success, -1 on failure
* *
* This is like p2p_connect(), but the actual group negotiation is not * 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, int p2p_authorize(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);
/** /**
* p2p_reject - Reject peer device (explicitly block connection attempts) * p2p_reject - Reject peer device (explicitly block connection attempts)

View file

@ -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. 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] [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 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,
@ -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 used (e.g., 12345670). [display|keypad] is used with PIN method
to specify which PIN is used (display=dynamically generated random PIN to specify which PIN is used (display=dynamically generated random PIN
from local display, keypad=PIN entered from peer display). "persistent" 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 "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 client. It skips the GO Negotiation part. This will send a Provision

View file

@ -2855,14 +2855,15 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
enum p2p_wps_method wps_method; enum p2p_wps_method wps_method;
int new_pin; int new_pin;
int ret; int ret;
int persistent_group; int persistent_group, persistent_id = -1;
int join; int join;
int auth; int auth;
int automatic; int automatic;
int go_intent = -1; int go_intent = -1;
int freq = 0; 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>] */ * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */
if (hwaddr_aton(cmd, addr)) if (hwaddr_aton(cmd, addr))
@ -2874,6 +2875,19 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
pos++; pos++;
persistent_group = os_strstr(pos, " persistent") != NULL; 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; 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;
@ -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, new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, automatic, join, persistent_group, automatic, join,
auth, go_intent, freq); auth, go_intent, freq, persistent_id);
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;

View file

@ -509,7 +509,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); go_intent, freq, -1);
if (new_pin >= 0) { if (new_pin >= 0) {
char npin[9]; char npin[9];

View file

@ -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); wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS);
wpas_notify_p2p_go_neg_completed(wpa_s, res); 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) { if (wpa_s->create_p2p_iface) {
struct wpa_supplicant *group_wpa_s = struct wpa_supplicant *group_wpa_s =
wpas_p2p_init_group_interface(wpa_s, res->role_go); 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, 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,
struct wpa_ssid *ssid)
{ {
if (persistent_group && wpa_s->conf->persistent_reconnect) if (persistent_group && wpa_s->conf->persistent_reconnect)
persistent_group = 2; 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, 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); 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, 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,
struct wpa_ssid *ssid)
{ {
if (persistent_group && wpa_s->conf->persistent_reconnect) if (persistent_group && wpa_s->conf->persistent_reconnect)
persistent_group = 2; 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, return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
go_intent, own_interface_addr, force_freq, 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_pin, wpa_s->p2p_wps_method,
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);
return; return;
} }
@ -3012,6 +3031,8 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
* initiating Group Owner negotiation * initiating Group Owner negotiation
* @go_intent: GO Intent or -1 to use default * @go_intent: GO Intent or -1 to use default
* @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
* parameters or -1 to generate new values (SSID/passphrase)
* 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
@ -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, 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 go_intent, int freq, int persistent_id)
{ {
int force_freq = 0, oper_freq = 0; int force_freq = 0, oper_freq = 0;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
int ret = 0; int ret = 0;
enum wpa_driver_if_type iftype; enum wpa_driver_if_type iftype;
const u8 *if_addr; const u8 *if_addr;
struct wpa_ssid *ssid = NULL;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1; 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) if (go_intent < 0)
go_intent = wpa_s->conf->p2p_go_intent; 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_wps_method = wps_method;
wpa_s->p2p_persistent_group = !!persistent_group; wpa_s->p2p_persistent_group = !!persistent_group;
wpa_s->p2p_persistent_id = persistent_id;
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;
@ -3149,14 +3179,15 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
if (auth) { if (auth) {
if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method, if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method,
go_intent, if_addr, go_intent, if_addr,
force_freq, persistent_group) < 0) force_freq, persistent_group, ssid) <
0)
return -1; return -1;
return ret; return ret;
} }
if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method, if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method,
go_intent, if_addr, force_freq, go_intent, if_addr, force_freq,
persistent_group) < 0) { persistent_group, ssid) < 0) {
if (wpa_s->create_p2p_iface) if (wpa_s->create_p2p_iface)
wpas_p2p_remove_pending_group_interface(wpa_s); wpas_p2p_remove_pending_group_interface(wpa_s);
return -1; return -1;

View file

@ -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, 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 auth, int go_intent, int freq, int persistent_id);
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,

View file

@ -515,6 +515,7 @@ struct wpa_supplicant {
unsigned int p2p_auto_join:1; unsigned int p2p_auto_join:1;
unsigned int p2p_auto_pd:1; unsigned int p2p_auto_pd:1;
unsigned int p2p_persistent_group:1; unsigned int p2p_persistent_group:1;
int p2p_persistent_id;
int p2p_go_intent; int p2p_go_intent;
int p2p_connect_freq; int p2p_connect_freq;
struct os_time p2p_auto_started; struct os_time p2p_auto_started;