From 360182ed7c0d1dd6807e6b6d8a84eeb595011cc2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 27 Feb 2012 23:14:35 +0200 Subject: [PATCH] P2P: Advertise immediate availability of WPS credential 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 --- src/drivers/driver_test.c | 6 +++--- src/p2p/p2p.c | 20 ++++++++++++++++---- src/p2p/p2p.h | 3 ++- src/p2p/p2p_build.c | 15 +++++++++------ src/p2p/p2p_go_neg.c | 2 +- src/p2p/p2p_i.h | 3 ++- src/wps/wps.c | 8 ++++---- src/wps/wps.h | 2 +- wpa_supplicant/p2p_supplicant.c | 11 ++++++----- wpa_supplicant/scan.c | 4 +++- 10 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index 43b30e998..839bf7415 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -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 diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 6a48dba6b..b9c431f17 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -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); diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index ce3a79b00..a5192f49e 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -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 diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index 2106964e2..def422de6 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -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); diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index 1a0c7d497..52162121a 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -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: diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index eecef5488..30a83d506 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -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, diff --git a/src/wps/wps.c b/src/wps/wps.c index 9422c713d..64b80d808 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -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) || diff --git a/src/wps/wps.h b/src/wps/wps.h index 22e029fb2..18446cb0d 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -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, diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index b4aac1b0b..ae9136e35 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -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; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 5fe38650d..25b56b7d6 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -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) {