P2P: Add option to force SSID/passphrase for GO Negotiation
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 27 Apr 2012 15:17:10 +0000 (18:17 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 27 Apr 2012 15:25:30 +0000 (18:25 +0300)
An existing persistent group information can now be used to force GO
Negotiation to use the previously used SSID/passphrase from a persistent
group if we become a GO. This can be used as an alternative to inviting
a new P2P peer to join the group (i.e., use GO Negotiation with GO
intent 15 instead of starting an autonomous GO and using invitation),
e.g., in case a GO Negotiation Request is received from a peer while we
are not running as a GO. The persistent group to use for parameters is
indicated with persistent=<network id> parameter to p2p_connect.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/drivers/driver_test.c
src/p2p/p2p.c
src/p2p/p2p.h
wpa_supplicant/README-P2P
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers_p2p.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h
wpa_supplicant/wpa_supplicant_i.h

index b37d9f7..06cc349 100644 (file)
@@ -2867,7 +2867,8 @@ static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr,
        if (!drv->p2p)
                return -1;
        return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent,
-                          own_interface_addr, force_freq, persistent_group);
+                          own_interface_addr, force_freq, persistent_group,
+                          NULL, 0);
 }
 
 
index 474dd73..2f5a0a0 100644 (file)
@@ -1172,7 +1172,8 @@ static void p2p_set_dev_persistent(struct p2p_device *dev,
 int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
                enum p2p_wps_method wps_method,
                int go_intent, const u8 *own_interface_addr,
-               unsigned int force_freq, int persistent_group)
+               unsigned int force_freq, int persistent_group,
+               const u8 *force_ssid, size_t force_ssid_len)
 {
        struct p2p_device *dev;
 
@@ -1186,7 +1187,6 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
        if (p2p_prepare_channel(p2p, force_freq) < 0)
                return -1;
 
-       p2p->ssid_set = 0;
        dev = p2p_get_device(p2p, peer_addr);
        if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
@@ -1219,6 +1219,15 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
                 */
        }
 
+       p2p->ssid_set = 0;
+       if (force_ssid) {
+               wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
+                                 force_ssid, force_ssid_len);
+               os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
+               p2p->ssid_len = force_ssid_len;
+               p2p->ssid_set = 1;
+       }
+
        dev->flags &= ~P2P_DEV_NOT_YET_READY;
        dev->flags &= ~P2P_DEV_USER_REJECTED;
        dev->flags &= ~P2P_DEV_WAIT_GO_NEG_RESPONSE;
@@ -1270,7 +1279,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
 int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
                  enum p2p_wps_method wps_method,
                  int go_intent, const u8 *own_interface_addr,
-                 unsigned int force_freq, int persistent_group)
+                 unsigned int force_freq, int persistent_group,
+                 const u8 *force_ssid, size_t force_ssid_len)
 {
        struct p2p_device *dev;
 
@@ -1292,6 +1302,15 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
                return -1;
        }
 
+       p2p->ssid_set = 0;
+       if (force_ssid) {
+               wpa_hexdump_ascii(MSG_DEBUG, "P2P: Forced SSID",
+                                 force_ssid, force_ssid_len);
+               os_memcpy(p2p->ssid, force_ssid, force_ssid_len);
+               p2p->ssid_len = force_ssid_len;
+               p2p->ssid_set = 1;
+       }
+
        dev->flags &= ~P2P_DEV_NOT_YET_READY;
        dev->flags &= ~P2P_DEV_USER_REJECTED;
        dev->go_neg_req_sent = 0;
index a4d4256..44162f6 100644 (file)
@@ -877,12 +877,16 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout);
  * @persistent_group: Whether to create a persistent group (0 = no, 1 =
  * persistent group without persistent reconnect, 2 = persistent group with
  * persistent reconnect)
+ * @force_ssid: Forced SSID for the group if we become GO or %NULL to generate
+ *     a new SSID
+ * @force_ssid_len: Length of $force_ssid buffer
  * Returns: 0 on success, -1 on failure
  */
 int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
                enum p2p_wps_method wps_method,
                int go_intent, const u8 *own_interface_addr,
-               unsigned int force_freq, int persistent_group);
+               unsigned int force_freq, int persistent_group,
+               const u8 *force_ssid, size_t force_ssid_len);
 
 /**
  * p2p_authorize - Authorize P2P group formation (GO negotiation)
@@ -895,6 +899,9 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
  * @persistent_group: Whether to create a persistent group (0 = no, 1 =
  * persistent group without persistent reconnect, 2 = persistent group with
  * persistent reconnect)
+ * @force_ssid: Forced SSID for the group if we become GO or %NULL to generate
+ *     a new SSID
+ * @force_ssid_len: Length of $force_ssid buffer
  * Returns: 0 on success, -1 on failure
  *
  * This is like p2p_connect(), but the actual group negotiation is not
@@ -903,7 +910,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr,
 int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr,
                  enum p2p_wps_method wps_method,
                  int go_intent, const u8 *own_interface_addr,
-                 unsigned int force_freq, int persistent_group);
+                 unsigned int force_freq, int persistent_group,
+                 const u8 *force_ssid, size_t force_ssid_len);
 
 /**
  * p2p_reject - Reject peer device (explicitly block connection attempts)
index cd28aae..090b3a9 100644 (file)
@@ -118,7 +118,8 @@ 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]
-       [persistent] [join|auth] [go_intent=<0..15>] [freq=<in MHz>]
+       [persistent|persistent=<network id>] [join|auth]
+       [go_intent=<0..15>] [freq=<in MHz>]
 
 Start P2P group formation with a discovered P2P peer. This includes
 optional group owner negotiation, group interface setup, provisioning,
@@ -131,7 +132,12 @@ the command return code), PIN# means that a pre-selected PIN can be
 used (e.g., 12345670). [display|keypad] is used with PIN method
 to specify which PIN is used (display=dynamically generated random PIN
 from local display, keypad=PIN entered from peer display). "persistent"
-parameter can be used to request a persistent group to be formed.
+parameter can be used to request a persistent group to be formed. The
+"persistent=<network id>" alternative can be used to pre-populate
+SSID/passphrase configuration based on a previously used persistent
+group where this device was the GO. The previously used parameters will
+then be used if the local end becomes the GO in GO Negotiation (which
+can be forced with go_intent=15).
 
 "join" indicates that this is a command to join an existing group as a
 client. It skips the GO Negotiation part. This will send a Provision
index e51846b..6745be6 100644 (file)
@@ -2855,14 +2855,15 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
        enum p2p_wps_method wps_method;
        int new_pin;
        int ret;
-       int persistent_group;
+       int persistent_group, persistent_id = -1;
        int join;
        int auth;
        int automatic;
        int go_intent = -1;
        int freq = 0;
 
-       /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad] [persistent]
+       /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad]
+        * [persistent|persistent=<network id>]
         * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] */
 
        if (hwaddr_aton(cmd, addr))
@@ -2874,6 +2875,19 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
        pos++;
 
        persistent_group = os_strstr(pos, " persistent") != NULL;
+       pos2 = os_strstr(pos, " persistent=");
+       if (pos2) {
+               struct wpa_ssid *ssid;
+               persistent_id = atoi(pos2 + 12);
+               ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
+               if (ssid == NULL || ssid->disabled != 2 ||
+                   ssid->mode != WPAS_MODE_P2P_GO) {
+                       wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
+                                  "SSID id=%d for persistent P2P group (GO)",
+                                  persistent_id);
+                       return -1;
+               }
+       }
        join = os_strstr(pos, " join") != NULL;
        auth = os_strstr(pos, " auth") != NULL;
        automatic = os_strstr(pos, " auto") != NULL;
@@ -2912,7 +2926,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
 
        new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
                                   persistent_group, automatic, join,
-                                  auth, go_intent, freq);
+                                  auth, go_intent, freq, persistent_id);
        if (new_pin == -2) {
                os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
                return 25;
index badec75..89ad484 100644 (file)
@@ -509,7 +509,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
 
        new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
                                   persistent_group, 0, join, authorize_only,
-                                  go_intent, freq);
+                                  go_intent, freq, -1);
 
        if (new_pin >= 0) {
                char npin[9];
index 3ff2e17..65c399a 100644 (file)
@@ -987,6 +987,20 @@ void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
        wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS);
        wpas_notify_p2p_go_neg_completed(wpa_s, res);
 
+       if (res->role_go && wpa_s->p2p_persistent_id >= 0) {
+               struct wpa_ssid *ssid;
+               ssid = wpa_config_get_network(wpa_s->conf,
+                                             wpa_s->p2p_persistent_id);
+               if (ssid && ssid->disabled == 2 &&
+                   ssid->mode == WPAS_MODE_P2P_GO && ssid->passphrase) {
+                       size_t len = os_strlen(ssid->passphrase);
+                       wpa_printf(MSG_DEBUG, "P2P: Override passphrase based "
+                                  "on requested persistent group");
+                       os_memcpy(res->passphrase, ssid->passphrase, len);
+                       res->passphrase[len] = '\0';
+               }
+       }
+
        if (wpa_s->create_p2p_iface) {
                struct wpa_supplicant *group_wpa_s =
                        wpas_p2p_init_group_interface(wpa_s, res->role_go);
@@ -2559,7 +2573,8 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
                                 const u8 *peer_addr,
                                 enum p2p_wps_method wps_method,
                                 int go_intent, const u8 *own_interface_addr,
-                                unsigned int force_freq, int persistent_group)
+                                unsigned int force_freq, int persistent_group,
+                                struct wpa_ssid *ssid)
 {
        if (persistent_group && wpa_s->conf->persistent_reconnect)
                persistent_group = 2;
@@ -2572,7 +2587,8 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
 
        return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
                           go_intent, own_interface_addr, force_freq,
-                          persistent_group);
+                          persistent_group, ssid ? ssid->ssid : NULL,
+                          ssid ? ssid->ssid_len : 0);
 }
 
 
@@ -2580,7 +2596,8 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
                                const u8 *peer_addr,
                                enum p2p_wps_method wps_method,
                                int go_intent, const u8 *own_interface_addr,
-                               unsigned int force_freq, int persistent_group)
+                               unsigned int force_freq, int persistent_group,
+                               struct wpa_ssid *ssid)
 {
        if (persistent_group && wpa_s->conf->persistent_reconnect)
                persistent_group = 2;
@@ -2590,7 +2607,8 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
 
        return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
                             go_intent, own_interface_addr, force_freq,
-                            persistent_group);
+                            persistent_group, ssid ? ssid->ssid : NULL,
+                            ssid ? ssid->ssid_len : 0);
 }
 
 
@@ -2745,7 +2763,8 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
                                         wpa_s->p2p_pin, wpa_s->p2p_wps_method,
                                         wpa_s->p2p_persistent_group, 0, 0, 0,
                                         wpa_s->p2p_go_intent,
-                                        wpa_s->p2p_connect_freq);
+                                        wpa_s->p2p_connect_freq,
+                                        wpa_s->p2p_persistent_id);
                        return;
                }
 
@@ -3012,6 +3031,8 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
  *     initiating Group Owner negotiation
  * @go_intent: GO Intent or -1 to use default
  * @freq: Frequency for the group or 0 for auto-selection
+ * @persistent_id: Persistent group credentials to use for forcing GO
+ *     parameters or -1 to generate new values (SSID/passphrase)
  * Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
  *     failure, -2 on failure due to channel not currently available,
  *     -3 if forced channel is not supported
@@ -3019,17 +3040,25 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s)
 int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                     const char *pin, enum p2p_wps_method wps_method,
                     int persistent_group, int auto_join, int join, int auth,
-                    int go_intent, int freq)
+                    int go_intent, int freq, int persistent_id)
 {
        int force_freq = 0, oper_freq = 0;
        u8 bssid[ETH_ALEN];
        int ret = 0;
        enum wpa_driver_if_type iftype;
        const u8 *if_addr;
+       struct wpa_ssid *ssid = NULL;
 
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
                return -1;
 
+       if (persistent_id >= 0) {
+               ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
+               if (ssid == NULL || ssid->disabled != 2 ||
+                   ssid->mode != WPAS_MODE_P2P_GO)
+                       return -1;
+       }
+
        if (go_intent < 0)
                go_intent = wpa_s->conf->p2p_go_intent;
 
@@ -3038,6 +3067,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 
        wpa_s->p2p_wps_method = wps_method;
        wpa_s->p2p_persistent_group = !!persistent_group;
+       wpa_s->p2p_persistent_id = persistent_id;
        wpa_s->p2p_go_intent = go_intent;
        wpa_s->p2p_connect_freq = freq;
 
@@ -3149,14 +3179,15 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        if (auth) {
                if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method,
                                         go_intent, if_addr,
-                                        force_freq, persistent_group) < 0)
+                                        force_freq, persistent_group, ssid) <
+                   0)
                        return -1;
                return ret;
        }
 
        if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method,
                                  go_intent, if_addr, force_freq,
-                                 persistent_group) < 0) {
+                                 persistent_group, ssid) < 0) {
                if (wpa_s->create_p2p_iface)
                        wpas_p2p_remove_pending_group_interface(wpa_s);
                return -1;
index 42c849b..9779aaa 100644 (file)
@@ -20,7 +20,7 @@ void wpas_p2p_deinit_global(struct wpa_global *global);
 int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                     const char *pin, enum p2p_wps_method wps_method,
                     int persistent_group, int auto_join, int join,
-                    int auth, int go_intent, int freq);
+                    int auth, int go_intent, int freq, int persistent_id);
 void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
                                   unsigned int freq, unsigned int duration);
 void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
index 354c5cc..1f8e79d 100644 (file)
@@ -515,6 +515,7 @@ struct wpa_supplicant {
        unsigned int p2p_auto_join:1;
        unsigned int p2p_auto_pd:1;
        unsigned int p2p_persistent_group:1;
+       int p2p_persistent_id;
        int p2p_go_intent;
        int p2p_connect_freq;
        struct os_time p2p_auto_started;