P2P: Add p2p_prov_disc auto mechanism

wpa_supplicant can now be requested to automatically figure out whether
the indicated peer is operating as a GO and if so, use join-a-group
style PD instead of pre-GO Negotiation PD.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2012-04-26 17:13:03 +03:00 committed by Jouni Malinen
parent 25a94f525c
commit 0918c4bf3b
6 changed files with 86 additions and 14 deletions

View file

@ -101,7 +101,7 @@ Flush P2P peer table and state.
Group Formation Group Formation
p2p_prov_disc <peer device address> <display|keypad|pbc> [join] p2p_prov_disc <peer device address> <display|keypad|pbc> [join|auto]
Send P2P provision discovery request to the specified peer. The Send P2P provision discovery request to the specified peer. The
parameters for this command are the P2P device address of the peer and parameters for this command are the P2P device address of the peer and
@ -112,7 +112,10 @@ to enter a PIN that we display.
The optional "join" parameter can be used to indicate that this command The optional "join" parameter can be used to indicate that this command
is requesting an already running GO to prepare for a new client. This is is requesting an already running GO to prepare for a new client. This is
mainly used with "display" to request it to display a PIN. mainly used with "display" to request it to display a PIN. The "auto"
parameter can be used to request wpa_supplicant to automatically figure
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] p2p_connect <peer device address> <pbc|pin|PIN#> [display|keypad]
[persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>] [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>]

View file

@ -2946,8 +2946,9 @@ static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
{ {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
char *pos; char *pos;
enum wpas_p2p_prov_disc_use use = WPAS_P2P_PD_FOR_GO_NEG;
/* <addr> <config method> [join] */ /* <addr> <config method> [join|auto] */
if (hwaddr_aton(cmd, addr)) if (hwaddr_aton(cmd, addr))
return -1; return -1;
@ -2957,8 +2958,12 @@ static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
return -1; return -1;
pos++; pos++;
return wpas_p2p_prov_disc(wpa_s, addr, pos, if (os_strstr(pos, " join") != NULL)
os_strstr(pos, "join") != NULL); use = WPAS_P2P_PD_FOR_JOIN;
else if (os_strstr(pos, " auto") != NULL)
use = WPAS_P2P_PD_AUTO;
return wpas_p2p_prov_disc(wpa_s, addr, pos, use);
} }

View file

@ -692,7 +692,8 @@ DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
os_strcmp(config_method, "pushbutton")) os_strcmp(config_method, "pushbutton"))
return wpas_dbus_error_invalid_args(message, NULL); return wpas_dbus_error_invalid_args(message, NULL);
if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method, 0) < 0) if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method,
WPAS_P2P_PD_FOR_GO_NEG) < 0)
return wpas_dbus_error_unknown_error(message, return wpas_dbus_error_unknown_error(message,
"Failed to send provision discovery request"); "Failed to send provision discovery request");

View file

@ -1821,6 +1821,7 @@ void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
{ {
struct wpa_supplicant *wpa_s = ctx; struct wpa_supplicant *wpa_s = ctx;
unsigned int generated_pin = 0; unsigned int generated_pin = 0;
char params[20];
if (wpa_s->pending_pd_before_join && if (wpa_s->pending_pd_before_join &&
(os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 || (os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
@ -1832,14 +1833,22 @@ void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
return; return;
} }
if (wpa_s->pending_pd_use == AUTO_PD_JOIN ||
wpa_s->pending_pd_use == AUTO_PD_GO_NEG)
os_snprintf(params, sizeof(params), " peer_go=%d",
wpa_s->pending_pd_use == AUTO_PD_JOIN);
else
params[0] = '\0';
if (config_methods & WPS_CONFIG_DISPLAY) if (config_methods & WPS_CONFIG_DISPLAY)
wpas_prov_disc_local_keypad(wpa_s, peer, ""); wpas_prov_disc_local_keypad(wpa_s, peer, params);
else if (config_methods & WPS_CONFIG_KEYPAD) { else if (config_methods & WPS_CONFIG_KEYPAD) {
generated_pin = wps_generate_pin(); generated_pin = wps_generate_pin();
wpas_prov_disc_local_display(wpa_s, peer, "", generated_pin); wpas_prov_disc_local_display(wpa_s, peer, params,
generated_pin);
} else if (config_methods & WPS_CONFIG_PUSHBUTTON) } else if (config_methods & WPS_CONFIG_PUSHBUTTON)
wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP MACSTR, wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP MACSTR
MAC2STR(peer)); "%s", MAC2STR(peer), params);
wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */, wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
P2P_PROV_DISC_SUCCESS, P2P_PROV_DISC_SUCCESS,
@ -2595,6 +2604,13 @@ static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s)
" for join operationg - stop join attempt", " for join operationg - stop join attempt",
MAC2STR(wpa_s->pending_join_iface_addr)); MAC2STR(wpa_s->pending_join_iface_addr));
eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
if (wpa_s->p2p_auto_pd) {
wpa_s->p2p_auto_pd = 0;
wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
" p2p_dev_addr=" MACSTR " status=N/A",
MAC2STR(wpa_s->pending_join_dev_addr));
return;
}
wpa_msg(wpa_s->parent, MSG_INFO, wpa_msg(wpa_s->parent, MSG_INFO,
P2P_EVENT_GROUP_FORMATION_FAILURE); P2P_EVENT_GROUP_FORMATION_FAILURE);
} }
@ -2702,6 +2718,25 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
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_pd) {
int join = wpas_p2p_peer_go(wpa_s,
wpa_s->pending_join_dev_addr);
wpa_s->p2p_auto_pd = 0;
wpa_s->pending_pd_use = join ? AUTO_PD_JOIN : AUTO_PD_GO_NEG;
wpa_printf(MSG_DEBUG, "P2P: Auto PD with " MACSTR " join=%d",
MAC2STR(wpa_s->pending_join_dev_addr), join);
if (p2p_prov_disc_req(wpa_s->global->p2p,
wpa_s->pending_join_dev_addr,
wpa_s->pending_pd_config_methods, join,
0) < 0) {
wpa_s->p2p_auto_pd = 0;
wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
" p2p_dev_addr=" MACSTR " status=N/A",
MAC2STR(wpa_s->pending_join_dev_addr));
}
return;
}
if (wpa_s->p2p_auto_join) { if (wpa_s->p2p_auto_join) {
if (!wpas_p2p_peer_go(wpa_s, wpa_s->pending_join_dev_addr)) { if (!wpas_p2p_peer_go(wpa_s, wpa_s->pending_join_dev_addr)) {
wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be " wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
@ -2898,6 +2933,7 @@ static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
MAC2STR(iface_addr), MAC2STR(dev_addr), MAC2STR(iface_addr), MAC2STR(dev_addr),
auto_join ? " (auto_join)" : ""); auto_join ? " (auto_join)" : "");
wpa_s->p2p_auto_pd = 0;
wpa_s->p2p_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);
@ -3666,10 +3702,12 @@ void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
const char *config_method, int join) const char *config_method,
enum wpas_p2p_prov_disc_use use)
{ {
u16 config_methods; u16 config_methods;
wpa_s->pending_pd_use = NORMAL_PD;
if (os_strncmp(config_method, "display", 7) == 0) if (os_strncmp(config_method, "display", 7) == 0)
config_methods = WPS_CONFIG_DISPLAY; config_methods = WPS_CONFIG_DISPLAY;
else if (os_strncmp(config_method, "keypad", 6) == 0) else if (os_strncmp(config_method, "keypad", 6) == 0)
@ -3682,16 +3720,30 @@ int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
return -1; return -1;
} }
if (use == WPAS_P2P_PD_AUTO) {
os_memcpy(wpa_s->pending_join_dev_addr, peer_addr, ETH_ALEN);
wpa_s->pending_pd_config_methods = config_methods;
wpa_s->p2p_auto_pd = 1;
wpa_s->p2p_auto_join = 0;
wpa_s->pending_pd_before_join = 0;
wpas_p2p_stop_find(wpa_s);
wpa_s->p2p_join_scan_count = 0;
wpas_p2p_join_scan(wpa_s, NULL);
return 0;
}
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) { if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
return wpa_drv_p2p_prov_disc_req(wpa_s, peer_addr, return wpa_drv_p2p_prov_disc_req(wpa_s, peer_addr,
config_methods, join); config_methods,
use == WPAS_P2P_PD_FOR_JOIN);
} }
if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
return -1; return -1;
return p2p_prov_disc_req(wpa_s->global->p2p, peer_addr, return p2p_prov_disc_req(wpa_s->global->p2p, peer_addr,
config_methods, join, 0); config_methods, use == WPAS_P2P_PD_FOR_JOIN,
0);
} }

View file

@ -36,8 +36,14 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
int group_formation); int group_formation);
void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
int registrar); int registrar);
enum wpas_p2p_prov_disc_use {
WPAS_P2P_PD_FOR_GO_NEG,
WPAS_P2P_PD_FOR_JOIN,
WPAS_P2P_PD_AUTO
};
int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
const char *config_method, int join); const char *config_method,
enum wpas_p2p_prov_disc_use use);
void wpas_send_action_tx_status(struct wpa_supplicant *wpa_s, const u8 *dst, void wpas_send_action_tx_status(struct wpa_supplicant *wpa_s, const u8 *dst,
const u8 *data, size_t data_len, const u8 *data, size_t data_len,
enum p2p_send_action_result result); enum p2p_send_action_result result);

View file

@ -477,6 +477,10 @@ struct wpa_supplicant {
int pending_join_wps_method; int pending_join_wps_method;
int p2p_join_scan_count; int p2p_join_scan_count;
int force_long_sd; int force_long_sd;
u16 pending_pd_config_methods;
enum {
NORMAL_PD, AUTO_PD_GO_NEG, AUTO_PD_JOIN
} pending_pd_use;
/* /*
* Whether cross connection is disallowed by the AP to which this * Whether cross connection is disallowed by the AP to which this
@ -509,6 +513,7 @@ struct wpa_supplicant {
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_auto_join:1;
unsigned int p2p_auto_pd:1;
unsigned int p2p_persistent_group:1; unsigned int p2p_persistent_group:1;
int p2p_go_intent; int p2p_go_intent;
int p2p_connect_freq; int p2p_connect_freq;