]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2PS: Callback to send P2PS provisioning events
authorKrishna Vamsi <vamsin@qti.qualcomm.com>
Wed, 10 Dec 2014 13:43:23 +0000 (19:13 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 2 Feb 2015 23:35:07 +0000 (01:35 +0200)
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/common/wpa_ctrl.h
src/p2p/p2p.h
wpa_supplicant/p2p_supplicant.c

index 252ede9ce2848409c759f7645373d10f89d4a01d..c8e302a8c574a670eeb1282c61e7afce762e424e 100644 (file)
@@ -178,6 +178,9 @@ extern "C" {
 #define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
 #define P2P_EVENT_REMOVE_AND_REFORM_GROUP "P2P-REMOVE-AND-REFORM-GROUP "
 
+#define P2P_EVENT_P2PS_PROVISION_START "P2PS-PROV-START "
+#define P2P_EVENT_P2PS_PROVISION_DONE "P2PS-PROV-DONE "
+
 #define INTERWORKING_AP "INTERWORKING-AP "
 #define INTERWORKING_BLACKLISTED "INTERWORKING-BLACKLISTED "
 #define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
index ea3f679505c0fcf95746b533574042bdc8e166b1..11388dae74dd82840381b7672658a5c6ba920721 100644 (file)
@@ -981,6 +981,20 @@ struct p2p_config {
        int (*remove_stale_groups)(void *ctx, const u8 *peer, const u8 *go,
                                   const u8 *ssid, size_t ssid_len);
 
+       /**
+        * p2ps_prov_complete - P2PS provisioning complete
+        *
+        * When P2PS provisioning completes (successfully or not) we must
+        * transmit all of the results to the upper layers.
+        */
+       void (*p2ps_prov_complete)(void *ctx, u8 status, const u8 *dev,
+                                  const u8 *adv_mac, const u8 *ses_mac,
+                                  const u8 *grp_mac, u32 adv_id, u32 ses_id,
+                                  u8 conncap, int passwd_id,
+                                  const u8 *persist_ssid,
+                                  size_t persist_ssid_size, int response_done,
+                                  int prov_start, const char *session_info);
+
        /**
         * prov_disc_resp_cb - Callback for indicating completion of PD Response
         * @ctx: Callback context from cb_ctx
index dcfba79329b507cf10bb554948b927ed3302a2e9..2b619815b5e00cb04b7a9976ab9fa95e8ca31cea 100644 (file)
@@ -477,6 +477,30 @@ static int wpas_p2p_disconnect_safely(struct wpa_supplicant *wpa_s,
 }
 
 
+/* Determine total number of clients in active groups where we are the GO */
+static unsigned int p2p_group_go_member_count(struct wpa_supplicant *wpa_s)
+{
+       unsigned int count = 0;
+       struct wpa_ssid *s;
+
+       for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+               for (s = wpa_s->conf->ssid; s; s = s->next) {
+                       wpa_printf(MSG_DEBUG,
+                                  "P2P: sup:%p ssid:%p disabled:%d p2p:%d mode:%d",
+                                  wpa_s, s, s->disabled, s->p2p_group,
+                                  s->mode);
+                       if (!s->disabled && s->p2p_group &&
+                           s->mode == WPAS_MODE_P2P_GO) {
+                               count += p2p_get_group_num_members(
+                                       wpa_s->p2p_group);
+                       }
+               }
+       }
+
+       return count;
+}
+
+
 /* Find an interface for a P2P group where we are the GO */
 static struct wpa_supplicant *
 wpas_p2p_get_go_group(struct wpa_supplicant *wpa_s)
@@ -4729,6 +4753,234 @@ static int wpas_remove_stale_groups(void *ctx, const u8 *peer, const u8 *go,
 }
 
 
+static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
+                                   const u8 *adv_mac, const u8 *ses_mac,
+                                   const u8 *grp_mac, u32 adv_id, u32 ses_id,
+                                   u8 conncap, int passwd_id,
+                                   const u8 *persist_ssid,
+                                   size_t persist_ssid_size, int response_done,
+                                   int prov_start, const char *session_info)
+{
+       struct wpa_supplicant *wpa_s = ctx;
+       u8 mac[ETH_ALEN];
+       struct wpa_ssid *persistent_go, *stale, *s;
+       int save_config = 0;
+       struct wpa_supplicant *go_wpa_s;
+
+       if (!dev)
+               return;
+
+       os_memset(mac, 0, ETH_ALEN);
+       if (!adv_mac)
+               adv_mac = mac;
+       if (!ses_mac)
+               ses_mac = mac;
+       if (!grp_mac)
+               grp_mac = mac;
+
+       if (prov_start) {
+               if (session_info == NULL) {
+                       wpa_msg_global(wpa_s, MSG_INFO,
+                                      P2P_EVENT_P2PS_PROVISION_START MACSTR
+                                      " adv_id=%x conncap=%x"
+                                      " adv_mac=" MACSTR
+                                      " session=%x mac=" MACSTR
+                                      " dev_passwd_id=%d",
+                                      MAC2STR(dev), adv_id, conncap,
+                                      MAC2STR(adv_mac),
+                                      ses_id, MAC2STR(ses_mac),
+                                      passwd_id);
+               } else {
+                       wpa_msg_global(wpa_s, MSG_INFO,
+                                      P2P_EVENT_P2PS_PROVISION_START MACSTR
+                                      " adv_id=%x conncap=%x"
+                                      " adv_mac=" MACSTR
+                                      " session=%x mac=" MACSTR
+                                      " dev_passwd_id=%d info='%s'",
+                                      MAC2STR(dev), adv_id, conncap,
+                                      MAC2STR(adv_mac),
+                                      ses_id, MAC2STR(ses_mac),
+                                      passwd_id, session_info);
+               }
+               return;
+       }
+
+       go_wpa_s = wpas_p2p_get_go_group(wpa_s);
+       persistent_go = wpas_p2p_get_persistent_go(wpa_s);
+
+       if (status && status != P2P_SC_SUCCESS_DEFERRED) {
+               if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
+                       wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
+
+               if (persistent_go && !persistent_go->num_p2p_clients) {
+                       /* remove empty persistent GO */
+                       wpa_config_remove_network(wpa_s->conf,
+                                                 persistent_go->id);
+               }
+
+               wpa_msg_global(wpa_s, MSG_INFO,
+                              P2P_EVENT_P2PS_PROVISION_DONE MACSTR
+                              " status=%d"
+                              " adv_id=%x adv_mac=" MACSTR
+                              " session=%x mac=" MACSTR,
+                              MAC2STR(dev), status,
+                              adv_id, MAC2STR(adv_mac),
+                              ses_id, MAC2STR(ses_mac));
+               return;
+       }
+
+       /* Clean up stale persistent groups with this device */
+       s = wpas_p2p_get_persistent(wpa_s, dev, persist_ssid,
+                                   persist_ssid_size);
+       for (;;) {
+               stale = wpas_p2p_get_persistent(wpa_s, dev, NULL, 0);
+               if (!stale)
+                       break;
+
+               if (s && s->ssid_len == stale->ssid_len &&
+                   os_memcmp(stale->bssid, s->bssid, ETH_ALEN) == 0 &&
+                   os_memcmp(stale->ssid, s->ssid, s->ssid_len) == 0)
+                       break;
+
+               /* Remove stale persistent group */
+               if (stale->mode != WPAS_MODE_P2P_GO ||
+                   stale->num_p2p_clients <= 1) {
+                       wpa_config_remove_network(wpa_s->conf, stale->id);
+               } else {
+                       size_t i;
+
+                       for (i = 0; i < stale->num_p2p_clients; i++) {
+                               if (os_memcmp(stale->p2p_client_list +
+                                             i * ETH_ALEN,
+                                             dev, ETH_ALEN) == 0) {
+                                       os_memmove(stale->p2p_client_list +
+                                                  i * ETH_ALEN,
+                                                  stale->p2p_client_list +
+                                                  (i + 1) * ETH_ALEN,
+                                                  (stale->num_p2p_clients -
+                                                   i - 1) * ETH_ALEN);
+                                       break;
+                               }
+                       }
+                       stale->num_p2p_clients--;
+               }
+               save_config = 1;
+       }
+
+       if (save_config)
+               p2p_config_write(wpa_s);
+
+       if (s) {
+               if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
+                       wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
+
+               if (persistent_go && s != persistent_go &&
+                   !persistent_go->num_p2p_clients) {
+                       /* remove empty persistent GO */
+                       wpa_config_remove_network(wpa_s->conf,
+                                                 persistent_go->id);
+                       /* Save config */
+               }
+
+               wpa_msg_global(wpa_s, MSG_INFO,
+                              P2P_EVENT_P2PS_PROVISION_DONE MACSTR
+                              " status=%d"
+                              " adv_id=%x adv_mac=" MACSTR
+                              " session=%x mac=" MACSTR
+                              " persist=%d",
+                              MAC2STR(dev), status,
+                              adv_id, MAC2STR(adv_mac),
+                              ses_id, MAC2STR(ses_mac), s->id);
+               return;
+       }
+
+       if (conncap == P2PS_SETUP_GROUP_OWNER) {
+               const char *go_ifname = NULL;
+               if (!go_wpa_s) {
+                       wpa_s->global->pending_p2ps_group = 1;
+
+                       if (wpa_s->conf->p2p_no_group_iface)
+                               go_ifname = wpa_s->ifname;
+                       else if (wpa_s->pending_interface_name[0])
+                               go_ifname = wpa_s->pending_interface_name;
+
+                       if (!go_ifname) {
+                               wpas_p2ps_prov_complete(
+                                       wpa_s, P2P_SC_FAIL_UNKNOWN_GROUP,
+                                       dev, adv_mac, ses_mac,
+                                       NULL, adv_id, ses_id, 0, 0,
+                                       NULL, 0, 0, 0, NULL);
+                               return;
+                       }
+
+                       /* If PD Resp complete, start up the GO */
+                       if (response_done && persistent_go) {
+                               wpas_p2p_group_add_persistent(
+                                       wpa_s, persistent_go,
+                                       0, 0, 0, 0, 0, NULL,
+                                       persistent_go->mode ==
+                                       WPAS_MODE_P2P_GO ?
+                                       P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
+                                       0);
+                       } else if (response_done) {
+                               wpas_p2p_group_add(wpa_s, 1, 0, 0, 0);
+                       }
+               } else if (passwd_id == DEV_PW_P2PS_DEFAULT) {
+                       go_ifname = go_wpa_s->ifname;
+
+                       wpa_dbg(go_wpa_s, MSG_DEBUG,
+                               "P2P: Setting PIN-1 For " MACSTR, MAC2STR(dev));
+                       wpa_supplicant_ap_wps_pin(go_wpa_s, dev, "12345670",
+                                                 NULL, 0, 0);
+               }
+
+               wpa_msg_global(wpa_s, MSG_INFO,
+                              P2P_EVENT_P2PS_PROVISION_DONE MACSTR
+                              " status=%d conncap=%x"
+                              " adv_id=%x adv_mac=" MACSTR
+                              " session=%x mac=" MACSTR
+                              " dev_passwd_id=%d go=%s",
+                              MAC2STR(dev), status, conncap,
+                              adv_id, MAC2STR(adv_mac),
+                              ses_id, MAC2STR(ses_mac),
+                              passwd_id, go_ifname);
+               return;
+       }
+
+       if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
+               wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
+
+       if (persistent_go && !persistent_go->num_p2p_clients) {
+               /* remove empty persistent GO */
+               wpa_config_remove_network(wpa_s->conf, persistent_go->id);
+       }
+
+       if (conncap == P2PS_SETUP_CLIENT) {
+               wpa_msg_global(wpa_s, MSG_INFO,
+                              P2P_EVENT_P2PS_PROVISION_DONE MACSTR
+                              " status=%d conncap=%x"
+                              " adv_id=%x adv_mac=" MACSTR
+                              " session=%x mac=" MACSTR
+                              " dev_passwd_id=%d join=" MACSTR,
+                              MAC2STR(dev), status, conncap,
+                              adv_id, MAC2STR(adv_mac),
+                              ses_id, MAC2STR(ses_mac),
+                              passwd_id, MAC2STR(grp_mac));
+       } else {
+               wpa_msg_global(wpa_s, MSG_INFO,
+                              P2P_EVENT_P2PS_PROVISION_DONE MACSTR
+                              " status=%d conncap=%x"
+                              " adv_id=%x adv_mac=" MACSTR
+                              " session=%x mac=" MACSTR
+                              " dev_passwd_id=%d",
+                              MAC2STR(dev), status, conncap,
+                              adv_id, MAC2STR(adv_mac),
+                              ses_id, MAC2STR(ses_mac),
+                              passwd_id);
+       }
+}
+
+
 static int _wpas_p2p_in_progress(void *ctx)
 {
        struct wpa_supplicant *wpa_s = ctx;
@@ -4813,6 +5065,7 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
        p2p.get_persistent_group = wpas_get_persistent_group;
        p2p.get_go_info = wpas_get_go_info;
        p2p.remove_stale_groups = wpas_remove_stale_groups;
+       p2p.p2ps_prov_complete = wpas_p2ps_prov_complete;
        p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb;
 
        os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);