[PATCH] Add an option to suppress provision discovery during P2P Join

Jithu Jance jithu at broadcom.com
Fri Nov 25 04:06:05 EST 2011


Hi Jouni,

I have generated a patch addressing your suggestions below. Please see whether its fine.

>Anyway, the proper way to address this is to extend
>p2p_prov_disc behavior

I have extended the p2p_prov_disc command to include an optional "join" argument. This will allow to include GROUP ID.

> For this particular case of joining a running group, I think it would be
> fine to store the information when the extended p2p_prov_disc command is
> used and that could then be used on the following p2p_connect join
> operation.



 Signed-hostap: Jithu Jance <jithu at broadcom.com>

---
 src/drivers/driver.h                        |    2 +-
 src/p2p/p2p.c                               |   30 +++++++++++++++++++
 src/p2p/p2p.h                               |   18 ++++++++++++
 src/p2p/p2p_i.h                             |    6 ++++
 src/p2p/p2p_pd.c                            |    7 ++++
 wpa_supplicant/ctrl_iface.c                 |    6 +++-
 wpa_supplicant/dbus/dbus_new_handlers_p2p.c |    2 +-
 wpa_supplicant/driver_i.h                   |    4 +-
 wpa_supplicant/p2p_supplicant.c             |   41 +++++++++++++++++++++-----
 wpa_supplicant/p2p_supplicant.h             |    2 +-
 wpa_supplicant/wpa_cli.c                    |   16 ++++++----
 11 files changed, 114 insertions(+), 20 deletions(-)

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index ce25d03..03e6047 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2197,7 +2197,7 @@ struct wpa_driver_ops {
         * struct wpa_driver_capa.
         */
        int (*p2p_prov_disc_req)(void *priv, const u8 *peer_addr,
-                                u16 config_methods);
+                                u16 config_methods, int join);

        /**
         * p2p_sd_request - Schedule a service discovery query
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index c307505..27acb4b 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -113,6 +113,36 @@ static const char * p2p_state_txt(int state)
        }
 }

+int p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr)
+{
+struct p2p_device *dev = NULL;
+
+       if(!addr || !p2p) {
+               return 0;
+       }
+
+       dev = p2p_get_device(p2p, addr);
+       if(dev)
+               return dev->wps_prov_info;
+       else
+               return 0;
+}
+
+void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *iface_addr)
+{
+       struct p2p_device *dev = NULL;
+
+       if(!iface_addr || !p2p) {
+               return;
+       }
+
+       dev = p2p_get_device_interface(p2p, iface_addr);
+       if(dev)
+               dev->wps_prov_info = 0;
+       else
+       wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: "
+               "Device ("MACSTR") not Found", MAC2STR(iface_addr));
+}

 void p2p_set_state(struct p2p_data *p2p, int new_state)
 {
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 1501a20..05a50fe 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1035,6 +1035,24 @@ void p2p_wps_success_cb(struct p2p_data *p2p, const u8 *mac_addr);
  */
 void p2p_group_formation_failed(struct p2p_data *p2p);

+/**
+ * p2p_clear_provisioning_info - Clear any stored provisioning info
+ * @p2p: P2P module context from p2p_init()
+ * @mac_addr: Peer Interface address
+ *
+ * This function is used to clear stored WPS provisioning info
+ */
+void p2p_clear_provisioning_info(struct p2p_data *p2p, const u8 *iface_addr);
+
+/**
+ * p2p_get_provisioning_info - get any stored provisioning info
+ * @p2p: P2P module context from p2p_init()
+ * @mac_addr: Peer Device address
+ *
+ * This function is used to retreive stored WPS provisioning Info for a given
+ * peer mac_addr.
+ */
+int p2p_get_provisioning_info(struct p2p_data *p2p, const u8 *addr);

 /* Event notifications from lower layer driver operations */

diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index 9d72a1c..081ef2d 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -73,6 +73,12 @@ struct p2p_device {
         */
        u16 req_config_methods;

+       /**
+        * wps_prov_info - Store provision info till Group formation is
+        * completed (failure or success).
+        */
+       u16 wps_prov_info;
+
 #define P2P_DEV_PROBE_REQ_ONLY BIT(0)
 #define P2P_DEV_REPORTED BIT(1)
 #define P2P_DEV_NOT_YET_READY BIT(2)
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index f7ff06c..ac086b9 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -267,6 +267,10 @@ void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
                        MAC2STR(sa));
                dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
        }
+
+       /* Store the provisioning info */
+       dev->wps_prov_info = msg.wps_config_methods;
+
        p2p_parse_free(&msg);

 out:
@@ -352,6 +356,9 @@ int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
        if (config_methods == 0)
                return -1;

+       /* Reset provisioning info */
+       dev->wps_prov_info = 0;
+
        dev->req_config_methods = config_methods;
        if (join)
                dev->flags |= P2P_DEV_PD_FOR_JOIN;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index b2789be..015a692 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -2463,6 +2463,7 @@ static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
 {
        u8 addr[ETH_ALEN];
        char *pos;
+       int join = FALSE;

        /* <addr> <config method> */

@@ -2474,7 +2475,10 @@ static int p2p_ctrl_prov_disc(struct wpa_supplicant *wpa_s, char *cmd)
                return -1;
        pos++;

-       return wpas_p2p_prov_disc(wpa_s, addr, pos);
+       if (os_strstr(pos, "join") != NULL)
+               join = TRUE;
+
+       return wpas_p2p_prov_disc(wpa_s, addr, pos, join);
 }


diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index f2c5a18..39faeae 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -692,7 +692,7 @@ DBusMessage * wpas_dbus_handler_p2p_prov_disc_req(DBusMessage *message,
            os_strcmp(config_method, "pushbutton"))
                return wpas_dbus_error_invalid_args(message, NULL);

-       if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method) < 0)
+       if (wpas_p2p_prov_disc(wpa_s, peer_addr, config_method, join) < 0)
                return wpas_dbus_error_unknown_error(message,
                                "Failed to send provision discovery request");

diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 8b584db..d61b3fd 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -569,12 +569,12 @@ static inline int wpa_drv_p2p_set_params(struct wpa_supplicant *wpa_s,

 static inline int wpa_drv_p2p_prov_disc_req(struct wpa_supplicant *wpa_s,
                                            const u8 *peer_addr,
-                                           u16 config_methods)
+                                           u16 config_methods, int join)
 {
        if (!wpa_s->driver->p2p_prov_disc_req)
                return -1;
        return wpa_s->driver->p2p_prov_disc_req(wpa_s->drv_priv, peer_addr,
-                                               config_methods);
+                                               config_methods, join);
 }

 static inline u64 wpa_drv_p2p_sd_request(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index c6484af..13003a6 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -2294,6 +2294,12 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
 {
        if (wpa_s->driver && wpa_s->drv_priv)
                wpa_drv_probe_req_report(wpa_s, 0);
+
+       if(wpa_s->go_params) {
+               /* Clear any stored provisioning info */
+               p2p_clear_provisioning_info(wpa_s->global->p2p, wpa_s->go_params->peer_interface_addr);
+       }
+
        os_free(wpa_s->go_params);
        wpa_s->go_params = NULL;
        eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
@@ -2503,6 +2509,15 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
                        break;
                }

+               if((p2p_get_provisioning_info(wpa_s->global->p2p,
+                                                       wpa_s->pending_join_dev_addr) == method)) {
+                       /* We already have the provisioning info. Proceed to Join */
+                       wpa_printf(MSG_DEBUG, "P2P: Provisioning for "MACSTR "already done"
+                               "Proceed to Join", MAC2STR(wpa_s->pending_join_dev_addr));
+                       wpa_s->pending_pd_before_join = 0;
+                       goto start;
+               }
+
                if (p2p_prov_disc_req(wpa_s->global->p2p,
                                      wpa_s->pending_join_dev_addr, method, 1)
                    < 0) {
@@ -3256,6 +3271,9 @@ void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                return;
        }

+       /* Clear any stored provisioning info */
+       p2p_clear_provisioning_info(wpa_s->global->p2p, peer_addr);
+
        eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
                             NULL);
        if (wpa_s->global->p2p)
@@ -3274,35 +3292,42 @@ void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
                           "provisioning not in progress");
                return;
        }
+
+       if(wpa_s->go_params) {
+               p2p_clear_provisioning_info(wpa_s->global->p2p, wpa_s->go_params->peer_interface_addr);
+       }
+
        wpas_notify_p2p_wps_failed(wpa_s, fail);
 }


 int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
-                      const char *config_method)
+                      const char *config_method, int join)
 {
        u16 config_methods;

-       if (os_strcmp(config_method, "display") == 0)
+       if (os_strncmp(config_method, "display", 7) == 0)
                config_methods = WPS_CONFIG_DISPLAY;
-       else if (os_strcmp(config_method, "keypad") == 0)
+       else if (os_strncmp(config_method, "keypad", 6) == 0)
                config_methods = WPS_CONFIG_KEYPAD;
-       else if (os_strcmp(config_method, "pbc") == 0 ||
-                os_strcmp(config_method, "pushbutton") == 0)
+       else if (os_strncmp(config_method, "pbc", 3) == 0 ||
+                os_strncmp(config_method, "pushbutton", 10) == 0)
                config_methods = WPS_CONFIG_PUSHBUTTON;
-       else
+       else {
+               wpa_printf(MSG_DEBUG, "P2P: Unkown config method");
                return -1;
+       }

        if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {
                return wpa_drv_p2p_prov_disc_req(wpa_s, peer_addr,
-                                                config_methods);
+                                                config_methods, join);
        }

        if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
                return -1;

        return p2p_prov_disc_req(wpa_s->global->p2p, peer_addr,
-                                config_methods, 0);
+                                config_methods, join);
 }


diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 9a13f9f..33b22db 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -43,7 +43,7 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
 void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                          int registrar);
 int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
-                      const char *config_method);
+                      const char *config_method, int join);
 void wpas_send_action_tx_status(struct wpa_supplicant *wpa_s, const u8 *dst,
                                const u8 *data, size_t data_len,
                                enum p2p_send_action_result result);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 3311a01..9ebb0ab 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -2074,15 +2074,19 @@ static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
        char cmd[128];
        int res;

-       if (argc != 2) {
-               printf("Invalid P2P_PROV_DISC command: needs two arguments "
-                      "(address and config method\n"
-                      "(display, keypad, or pbc)\n");
+       if (argc != 2 && argc != 3) {
+               printf("Invalid P2P_PROV_DISC command: needs at least "
+                               "two arguments, address and config method\n"
+                      "(display, keypad, or pbc) and an optional join\n");
                return -1;
        }

-       res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
-                         argv[0], argv[1]);
+       if(argc == 3)
+               res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s %s",
+                                 argv[0], argv[1], argv[2]);
+       else
+               res = os_snprintf(cmd, sizeof(cmd), "P2P_PROV_DISC %s %s",
+                                 argv[0], argv[1]);
        if (res < 0 || (size_t) res >= sizeof(cmd))
                return -1;
        cmd[sizeof(cmd) - 1] = '\0';
--
1.7.4.1





________________________________________
From: hostap-bounces at lists.shmoo.com [hostap-bounces at lists.shmoo.com] On Behalf Of Jouni Malinen [j at w1.fi]
Sent: Tuesday, November 22, 2011 8:35 PM
To: hostap at lists.shmoo.com
Subject: Re: [PATCH] Add an option to suppress provision discovery during P2P Join

On Tue, Nov 22, 2011 at 03:10:57AM -0800, Jithu Jance wrote:
> Consider a scenario where a P2P client wants to Join P2P GO whose wps config method is
> advertised as DISPLAY.
>
> In this case, I think we have to use explicit provision discovery before issuing
> p2p_connect. The explicit discovery is used to retreive the PIN from GO side.

Well, this depends on the GO implementation. Some GO devices may have a
PIN displayed somehow all the time. Anyway, yes, there may be cases
where a Provision Discovery request may be needed.

>   Device A (P2P Client)                                       Device B (P2P GO with PIN DISPLAY)
> -------------------------------------------------------------------------------------------
> p2p_find
>
> P2p_prov_disc <GO_DEV_ADDRESS> display
>
>                                             PROV_DISC_SHOW_PIN EVENT >>> DISPLAY GO's PIN

This is not correct. The Provision Discovery Request sent by
p2p_prov_disc is for the purpose of starting group formation while you
are trying to get the already running GO to display a PIN. The
difference is in whether the Group Id attribute is included in the
message (it needs to be included for this join-a-group case, but that
p2p_prov_disc command does not add it).

>    p2p_connect <GO_DEV_ADDR> <GO_PIN> join
>    [since we have already done the PD, I think we shouldn't repeat it.
>     Otherwise the GO may regenerate the PIN on receipt of prov disc request.]

If the previous step had actually sent a Provision Discovery Request
with Group Id attribute, I would agree with this. However, it didn't and
as such, leaving out the correct frame here would result in incorrect
behavior. Anyway, the proper way to address this is to extend
p2p_prov_disc behavior

> The command that I have used is p2p_prov_disc <go_dev_addr> <req_config_method>
> The prov disc req is sent from Client's p2p_device address interface. The group id
> will only be created on the subsequent p2p_connect command. Is group id really
> required in this scenario??. Correct me, if my understanding is wrong.

Yes, the Group Id is required in Provision Discovery Request that is
sent prior to joining a running group. Since the group is already
running, the Group Id is known and no new Group Id gets created with
p2p_connect. If you were talking about forming a new group, the Group Id
would indeed be known only after the p2p_connect (and GO Negotiation).

> Agree with you. The sending of provision discovery should be based on the availablity of provisioning info.
> But, if we store the provisioning info, when should it be cleared/reset?? Is it safe to assume that the
> provisioning info received for a particular GO will hold good till there is a change in advertised Config methods
> or till DEVICE_LOST event??

For this particular case of joining a running group, I think it would be
fine to store the information when the extended p2p_prov_disc command is
used and that could then be used on the following p2p_connect join
operation. In theory, there could be some kind of time limit added to
clear the configuration (e.g., the 2 minute WPS walk time), but other
than that, I don't see any particular need for additional clearing of
this information.

--
Jouni Malinen                                            PGP id EFC895FA
_______________________________________________
HostAP mailing list
HostAP at lists.shmoo.com
http://lists.shmoo.com/mailman/listinfo/hostap




More information about the HostAP mailing list