P2P: Handle improper WPS termination on GO during group formation
authorSunil Dutt <usdutt@qti.qualcomm.com>
Wed, 1 Oct 2014 12:36:53 +0000 (18:06 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 10 Oct 2014 15:40:57 +0000 (18:40 +0300)
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>
src/ap/sta_info.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index efd2a72..f0f01b4 100644 (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))
                return;
 
+       if (authorized)
+               sta->flags |= WLAN_STA_AUTHORIZED;
+       else
+               sta->flags &= ~WLAN_STA_AUTHORIZED;
+
 #ifdef CONFIG_P2P
        if (hapd->p2p_group == 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 */
                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) {
                char ip_addr[100];
                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,
                                          AP_STA_CONNECTED "%s%s",
                                          buf, ip_addr);
-
-               sta->flags |= WLAN_STA_AUTHORIZED;
        } else {
                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)
                        wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
                                          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);
 }
 
 
index 1f54c10..1b6919d 100644 (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_invitation = 0;
+       wpa_s->group_formation_reported = 1;
 
        if (!success) {
                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,
                                    struct p2p_go_neg_results *res)
 {
+       wpa_s->group_formation_reported = 0;
        wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR
                   " dev_addr " MACSTR " wps_method %d",
                   MAC2STR(res->peer_interface_addr),
@@ -1266,6 +1268,7 @@ static void p2p_go_configured(void *ctx, void *data)
                                       params->passphrase,
                                       wpa_s->global->p2p_dev_addr,
                                       params->persistent_group, "");
+               wpa_s->group_formation_reported = 1;
 
                os_get_reltime(&wpa_s->global->p2p_go_wait_client);
                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->p2p_go_group_formation_completed = 0;
+       wpa_s->group_formation_reported = 0;
 
        wpa_config_set_network_defaults(ssid);
        ssid->temporary = 1;
@@ -6896,6 +6900,20 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
                 * provisioning step.
                 */
                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) {
                wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Marking group formation completed on GO on first data connection");
index cbe3e49..0346d84 100644 (file)
@@ -753,6 +753,7 @@ struct wpa_supplicant {
        unsigned int p2p_go_vht:1;
        unsigned int user_initiated_pd:1;
        unsigned int p2p_go_group_formation_completed:1;
+       unsigned int group_formation_reported:1;
        unsigned int waiting_presence_resp;
        int p2p_first_connection_timeout;
        unsigned int p2p_nfc_tag_enabled:1;