P2P: Handle improper WPS termination on GO during group formation

A P2P Client may be able to connect to the GO even if the WPS
provisioning step has not terminated cleanly (e.g., P2P Client does not
send WSC_Done). Such group formation attempt missed the event
notification about started group on the GO and also did not set the
internal state corresponding to the successful group formation.

This commit addresses the missing part by completing GO side group
formation on a successful first data connection if WPS does not complete
cleanly. Also, this commit reorders the STA authorization indications to
ensure that the group formation success notification is given prior to
the first STA connection to handle such scenarios.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Sunil Dutt 2014-10-01 18:06:53 +05:30 committed by Jouni Malinen
parent 58b40fdbfd
commit 61fc90483f
3 changed files with 28 additions and 8 deletions

View file

@ -949,6 +949,11 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED))
return; return;
if (authorized)
sta->flags |= WLAN_STA_AUTHORIZED;
else
sta->flags &= ~WLAN_STA_AUTHORIZED;
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
if (hapd->p2p_group == NULL) { if (hapd->p2p_group == NULL) {
if (sta->p2p_ie != NULL && if (sta->p2p_ie != NULL &&
@ -964,6 +969,10 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
if (hapd->sta_authorized_cb)
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
sta->addr, authorized, dev_addr);
if (authorized) { if (authorized) {
char ip_addr[100]; char ip_addr[100];
ip_addr[0] = '\0'; ip_addr[0] = '\0';
@ -984,8 +993,6 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_CONNECTED "%s%s", AP_STA_CONNECTED "%s%s",
buf, ip_addr); buf, ip_addr);
sta->flags |= WLAN_STA_AUTHORIZED;
} else { } else {
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
@ -993,13 +1000,7 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
hapd->msg_ctx_parent != hapd->msg_ctx) hapd->msg_ctx_parent != hapd->msg_ctx)
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_DISCONNECTED "%s", buf); AP_STA_DISCONNECTED "%s", buf);
sta->flags &= ~WLAN_STA_AUTHORIZED;
} }
if (hapd->sta_authorized_cb)
hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx,
sta->addr, authorized, dev_addr);
} }

View file

@ -891,6 +891,7 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
wpa_s->p2p_in_provisioning = 0; wpa_s->p2p_in_provisioning = 0;
} }
wpa_s->p2p_in_invitation = 0; wpa_s->p2p_in_invitation = 0;
wpa_s->group_formation_reported = 1;
if (!success) { if (!success) {
wpa_msg_global(wpa_s->parent, MSG_INFO, wpa_msg_global(wpa_s->parent, MSG_INFO,
@ -1178,6 +1179,7 @@ static int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s,
static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s, static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *res) struct p2p_go_neg_results *res)
{ {
wpa_s->group_formation_reported = 0;
wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR
" dev_addr " MACSTR " wps_method %d", " dev_addr " MACSTR " wps_method %d",
MAC2STR(res->peer_interface_addr), MAC2STR(res->peer_interface_addr),
@ -1266,6 +1268,7 @@ static void p2p_go_configured(void *ctx, void *data)
params->passphrase, params->passphrase,
wpa_s->global->p2p_dev_addr, wpa_s->global->p2p_dev_addr,
params->persistent_group, ""); params->persistent_group, "");
wpa_s->group_formation_reported = 1;
os_get_reltime(&wpa_s->global->p2p_go_wait_client); os_get_reltime(&wpa_s->global->p2p_go_wait_client);
if (params->persistent_group) { if (params->persistent_group) {
@ -1350,6 +1353,7 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
wpa_s->show_group_started = 0; wpa_s->show_group_started = 0;
wpa_s->p2p_go_group_formation_completed = 0; wpa_s->p2p_go_group_formation_completed = 0;
wpa_s->group_formation_reported = 0;
wpa_config_set_network_defaults(ssid); wpa_config_set_network_defaults(ssid);
ssid->temporary = 1; ssid->temporary = 1;
@ -6896,6 +6900,20 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
* provisioning step. * provisioning step.
*/ */
wpa_printf(MSG_DEBUG, "P2P: Canceled P2P group formation timeout on data connection"); wpa_printf(MSG_DEBUG, "P2P: Canceled P2P group formation timeout on data connection");
if (!wpa_s->p2p_go_group_formation_completed &&
!wpa_s->group_formation_reported) {
/*
* GO has not yet notified group formation success since
* the WPS step was not completed cleanly. Do that
* notification now since the P2P Client was able to
* connect and as such, must have received the
* credential from the WPS step.
*/
if (wpa_s->global->p2p)
p2p_wps_success_cb(wpa_s->global->p2p, addr);
wpas_group_formation_completed(wpa_s, 1);
}
} }
if (!wpa_s->p2p_go_group_formation_completed) { if (!wpa_s->p2p_go_group_formation_completed) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Marking group formation completed on GO on first data connection"); wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Marking group formation completed on GO on first data connection");

View file

@ -753,6 +753,7 @@ struct wpa_supplicant {
unsigned int p2p_go_vht:1; unsigned int p2p_go_vht:1;
unsigned int user_initiated_pd:1; unsigned int user_initiated_pd:1;
unsigned int p2p_go_group_formation_completed:1; unsigned int p2p_go_group_formation_completed:1;
unsigned int group_formation_reported:1;
unsigned int waiting_presence_resp; unsigned int waiting_presence_resp;
int p2p_first_connection_timeout; int p2p_first_connection_timeout;
unsigned int p2p_nfc_tag_enabled:1; unsigned int p2p_nfc_tag_enabled:1;