]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Advertise immediate availability of WPS credential
authorJouni Malinen <jouni@qca.qualcomm.com>
Mon, 27 Feb 2012 21:14:35 +0000 (23:14 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 27 Feb 2012 21:14:35 +0000 (23:14 +0200)
Use Device Password ID in WSC IE of Probe Request and Probe Response
frames to advertise immediate availability of WPS credentials per P2P
specification sections 3.1.2.1.1 (Listen State), 3.1.2.1.2 (Scan Phase),
and 3.1.2.1.3 (Find Phase).

For now, the Device Password ID is set only for the case where we are
active GO Negotiation with a specific peer. In practice, this means that
the Probe Response frames during pending GO Negotiation (whenever in
Listen state) indicate availability of the credential.

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

src/drivers/driver_test.c
src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_build.c
src/p2p/p2p_go_neg.c
src/p2p/p2p_i.h
src/wps/wps.c
src/wps/wps.h
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/scan.c

index 43b30e9985c2d199446519c01c67785a7d774f24..839bf7415e844e7a6b5d88544d31a606b6a08fa4 100644 (file)
@@ -2912,7 +2912,7 @@ static int wpa_driver_test_p2p_set_params(void *priv,
 
 static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
                         unsigned int num_req_dev_types,
-                        const u8 *req_dev_types, const u8 *dev_id)
+                        const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
 {
        struct wpa_driver_test_data *drv = ctx;
        struct wpa_driver_scan_params params;
@@ -2933,8 +2933,8 @@ static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
 
 #if 0 /* TODO: WPS IE */
        wpa_s->wps->dev.p2p = 1;
-       wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid,
-                                       WPS_REQ_ENROLLEE);
+       wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
+                                       wpa_s->wps->uuid, WPS_REQ_ENROLLEE);
 #else
        wps_ie = wpabuf_alloc(1);
 #endif
index 6a48dba6b25d1e536c94b4b4030dbed905a54aa2..b9c431f173541d4ce50b16b089deb8ba701b916c 100644 (file)
@@ -775,6 +775,7 @@ static void p2p_search(struct p2p_data *p2p)
 {
        int freq = 0;
        enum p2p_scan_type type;
+       u16 pw_id = DEV_PW_DEFAULT;
 
        if (p2p->drv_in_listen) {
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still "
@@ -795,6 +796,9 @@ static void p2p_search(struct p2p_data *p2p)
                type = P2P_SCAN_SPECIFIC;
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
                        "for freq %u (GO Neg)", freq);
+
+               /* Advertise immediate availability of WPS credential */
+               pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
        } else if (p2p->invite_peer) {
                /*
                 * Only scan the known listen frequency of the peer
@@ -818,7 +822,7 @@ static void p2p_search(struct p2p_data *p2p)
 
        if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
                               p2p->num_req_dev_types, p2p->req_dev_types,
-                              p2p->find_dev_id)) {
+                              p2p->find_dev_id, pw_id)) {
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
                        "P2P: Scan request failed");
                p2p_continue_find(p2p);
@@ -962,12 +966,14 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
        case P2P_FIND_PROGRESSIVE:
                res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
                                         p2p->num_req_dev_types,
-                                        p2p->req_dev_types, dev_id);
+                                        p2p->req_dev_types, dev_id,
+                                        DEV_PW_DEFAULT);
                break;
        case P2P_FIND_ONLY_SOCIAL:
                res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
                                         p2p->num_req_dev_types,
-                                        p2p->req_dev_types, dev_id);
+                                        p2p->req_dev_types, dev_id,
+                                        DEV_PW_DEFAULT);
                break;
        default:
                return -1;
@@ -1765,12 +1771,18 @@ struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
 {
        struct wpabuf *buf;
        u8 *len;
+       int pw_id = -1;
 
        buf = wpabuf_alloc(1000);
        if (buf == NULL)
                return NULL;
 
-       p2p_build_wps_ie(p2p, buf, DEV_PW_DEFAULT, 1);
+       if (p2p->go_neg_peer) {
+               /* Advertise immediate availability of WPS credential */
+               pw_id = p2p_wps_method_pw_id(p2p->go_neg_peer->wps_method);
+       }
+
+       p2p_build_wps_ie(p2p, buf, pw_id, 1);
 
        /* P2P IE */
        len = p2p_buf_add_ie_hdr(buf);
index ce3a79b00d1c167d64567fb26296b9b93a363043..a5192f49e7ec1757568716ac0c9c7783103a813e 100644 (file)
@@ -354,6 +354,7 @@ struct p2p_config {
         * @num_req_dev_types: Number of requested device types
         * @req_dev_types: Array containing requested device types
         * @dev_id: Device ID to search for or %NULL to find all devices
+        * @pw_id: Device Password ID
         * Returns: 0 on success, -1 on failure
         *
         * This callback function is used to request a P2P scan or search
@@ -377,7 +378,7 @@ struct p2p_config {
         */
        int (*p2p_scan)(void *ctx, enum p2p_scan_type type, int freq,
                        unsigned int num_req_dev_types,
-                       const u8 *req_dev_types, const u8 *dev_id);
+                       const u8 *req_dev_types, const u8 *dev_id, u16 pw_id);
 
        /**
         * send_probe_resp - Transmit a Probe Response frame
index 2106964e2fc3240ff12c06256b56a9b8c4bf41ac..def422de68d75c70d5b0979f6264a012dc34fc39 100644 (file)
@@ -351,7 +351,7 @@ static void p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
 }
 
 
-void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id,
+void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
                      int all_attr)
 {
        u8 *len;
@@ -369,11 +369,14 @@ void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id,
                wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
        }
 
-       /* Device Password ID */
-       wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
-       wpabuf_put_be16(buf, 2);
-       wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id);
-       wpabuf_put_be16(buf, pw_id);
+       if (pw_id >= 0) {
+               /* Device Password ID */
+               wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
+               wpabuf_put_be16(buf, 2);
+               wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d",
+                          pw_id);
+               wpabuf_put_be16(buf, pw_id);
+       }
 
        if (all_attr) {
                wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
index 1a0c7d4973b981376eb78da3f212878e6f152188..52162121af4821c2e9af3e5ff9d04a626eba660a 100644 (file)
@@ -98,7 +98,7 @@ static int p2p_peer_channels(struct p2p_data *p2p, struct p2p_device *dev,
 }
 
 
-static u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method)
+u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method)
 {
        switch (wps_method) {
        case WPS_PIN_DISPLAY:
index eecef5488643018d7af69e6798fff61999851095..30a83d5060df297da8eaf3757ffa6b3791d05d17 100644 (file)
@@ -580,7 +580,7 @@ void p2p_buf_add_noa(struct wpabuf *buf, u8 noa_index, u8 opp_ps, u8 ctwindow,
 void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
                                   u16 interval);
 void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p);
-void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id,
+void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
                      int all_attr);
 
 /* p2p_sd.c */
@@ -608,6 +608,7 @@ void p2p_process_go_neg_resp(struct p2p_data *p2p, const u8 *sa,
 void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
                             const u8 *data, size_t len);
 int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev);
+u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method);
 
 /* p2p_pd.c */
 void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
index 9422c713d2fd7c38acd905f1ea56f636272d0412..64b80d808ce77580a0296a3b090cf494d0baf489 100644 (file)
@@ -431,7 +431,8 @@ struct wpabuf * wps_build_assoc_resp_ie(void)
 
 /**
  * wps_build_probe_req_ie - Build WPS IE for Probe Request
- * @pbc: Whether searching for PBC mode APs
+ * @pw_id: Password ID (DEV_PW_PUSHBUTTON for active PBC and DEV_PW_DEFAULT for
+ * most other use cases)
  * @dev: Device attributes
  * @uuid: Own UUID
  * @req_type: Value for Request Type attribute
@@ -442,7 +443,7 @@ struct wpabuf * wps_build_assoc_resp_ie(void)
  *
  * The caller is responsible for freeing the buffer.
  */
-struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
+struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev,
                                       const u8 *uuid,
                                       enum wps_request_type req_type,
                                       unsigned int num_req_dev_types,
@@ -464,8 +465,7 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
            wps_build_rf_bands(dev, ie) ||
            wps_build_assoc_state(NULL, ie) ||
            wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
-           wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON :
-                                     DEV_PW_DEFAULT) ||
+           wps_build_dev_password_id(ie, pw_id) ||
 #ifdef CONFIG_WPS2
            wps_build_manufacturer(dev, ie) ||
            wps_build_model_name(dev, ie) ||
index 22e029fb2651da6f1eb2443f91f8a55b1634f9b4..18446cb0d6bd992b3f8580fd93f007be3be2d2ab 100644 (file)
@@ -238,7 +238,7 @@ int wps_is_20(const struct wpabuf *msg);
 
 struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type);
 struct wpabuf * wps_build_assoc_resp_ie(void);
-struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
+struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev,
                                       const u8 *uuid,
                                       enum wps_request_type req_type,
                                       unsigned int num_req_dev_types,
index b4aac1b0b19a39e094940003702b711dbb92eda4..ae9136e3572e2331b6288161e9a90817da0e2536 100644 (file)
@@ -90,7 +90,7 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
 
 static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
                         unsigned int num_req_dev_types,
-                        const u8 *req_dev_types, const u8 *dev_id)
+                        const u8 *req_dev_types, const u8 *dev_id, u16 pw_id)
 {
        struct wpa_supplicant *wpa_s = ctx;
        struct wpa_driver_scan_params params;
@@ -111,8 +111,8 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
        params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
 
        wpa_s->wps->dev.p2p = 1;
-       wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid,
-                                       WPS_REQ_ENROLLEE,
+       wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
+                                       wpa_s->wps->uuid, WPS_REQ_ENROLLEE,
                                        num_req_dev_types, req_dev_types);
        if (wps_ie == NULL)
                return -1;
@@ -2741,8 +2741,9 @@ static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx)
        params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
 
        wpa_s->wps->dev.p2p = 1;
-       wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid,
-                                       WPS_REQ_ENROLLEE, 0, NULL);
+       wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
+                                       wpa_s->wps->uuid, WPS_REQ_ENROLLEE, 0,
+                                       NULL);
        if (wps_ie == NULL) {
                wpas_p2p_scan_res_join(wpa_s, NULL);
                return;
index 5fe38650d26555abb192b0062d28755fabb16960..25b56b7d64f3f20c2700736d947c3603b56f4010 100644 (file)
@@ -400,7 +400,9 @@ wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s,
 
        if (wps) {
                struct wpabuf *wps_ie;
-               wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev,
+               wps_ie = wps_build_probe_req_ie(wps == 2 ? DEV_PW_PUSHBUTTON :
+                                               DEV_PW_DEFAULT,
+                                               &wpa_s->wps->dev,
                                                wpa_s->wps->uuid, req_type,
                                                0, NULL);
                if (wps_ie) {