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 <jouni@qca.qualcomm.com>
This commit is contained in:
parent
78db55b800
commit
360182ed7c
10 changed files with 47 additions and 27 deletions
|
@ -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,
|
static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
|
||||||
unsigned int num_req_dev_types,
|
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_test_data *drv = ctx;
|
||||||
struct wpa_driver_scan_params params;
|
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 */
|
#if 0 /* TODO: WPS IE */
|
||||||
wpa_s->wps->dev.p2p = 1;
|
wpa_s->wps->dev.p2p = 1;
|
||||||
wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid,
|
wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
|
||||||
WPS_REQ_ENROLLEE);
|
wpa_s->wps->uuid, WPS_REQ_ENROLLEE);
|
||||||
#else
|
#else
|
||||||
wps_ie = wpabuf_alloc(1);
|
wps_ie = wpabuf_alloc(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -775,6 +775,7 @@ static void p2p_search(struct p2p_data *p2p)
|
||||||
{
|
{
|
||||||
int freq = 0;
|
int freq = 0;
|
||||||
enum p2p_scan_type type;
|
enum p2p_scan_type type;
|
||||||
|
u16 pw_id = DEV_PW_DEFAULT;
|
||||||
|
|
||||||
if (p2p->drv_in_listen) {
|
if (p2p->drv_in_listen) {
|
||||||
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still "
|
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;
|
type = P2P_SCAN_SPECIFIC;
|
||||||
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search "
|
||||||
"for freq %u (GO Neg)", freq);
|
"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) {
|
} else if (p2p->invite_peer) {
|
||||||
/*
|
/*
|
||||||
* Only scan the known listen frequency of the 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,
|
if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
|
||||||
p2p->num_req_dev_types, p2p->req_dev_types,
|
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,
|
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
|
||||||
"P2P: Scan request failed");
|
"P2P: Scan request failed");
|
||||||
p2p_continue_find(p2p);
|
p2p_continue_find(p2p);
|
||||||
|
@ -962,12 +966,14 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
|
||||||
case P2P_FIND_PROGRESSIVE:
|
case P2P_FIND_PROGRESSIVE:
|
||||||
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
|
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0,
|
||||||
p2p->num_req_dev_types,
|
p2p->num_req_dev_types,
|
||||||
p2p->req_dev_types, dev_id);
|
p2p->req_dev_types, dev_id,
|
||||||
|
DEV_PW_DEFAULT);
|
||||||
break;
|
break;
|
||||||
case P2P_FIND_ONLY_SOCIAL:
|
case P2P_FIND_ONLY_SOCIAL:
|
||||||
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
|
res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0,
|
||||||
p2p->num_req_dev_types,
|
p2p->num_req_dev_types,
|
||||||
p2p->req_dev_types, dev_id);
|
p2p->req_dev_types, dev_id,
|
||||||
|
DEV_PW_DEFAULT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1765,12 +1771,18 @@ struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf;
|
struct wpabuf *buf;
|
||||||
u8 *len;
|
u8 *len;
|
||||||
|
int pw_id = -1;
|
||||||
|
|
||||||
buf = wpabuf_alloc(1000);
|
buf = wpabuf_alloc(1000);
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
return 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 */
|
/* P2P IE */
|
||||||
len = p2p_buf_add_ie_hdr(buf);
|
len = p2p_buf_add_ie_hdr(buf);
|
||||||
|
|
|
@ -354,6 +354,7 @@ struct p2p_config {
|
||||||
* @num_req_dev_types: Number of requested device types
|
* @num_req_dev_types: Number of requested device types
|
||||||
* @req_dev_types: Array containing requested device types
|
* @req_dev_types: Array containing requested device types
|
||||||
* @dev_id: Device ID to search for or %NULL to find all devices
|
* @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
|
* Returns: 0 on success, -1 on failure
|
||||||
*
|
*
|
||||||
* This callback function is used to request a P2P scan or search
|
* 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,
|
int (*p2p_scan)(void *ctx, enum p2p_scan_type type, int freq,
|
||||||
unsigned int num_req_dev_types,
|
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
|
* send_probe_resp - Transmit a Probe Response frame
|
||||||
|
|
|
@ -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)
|
int all_attr)
|
||||||
{
|
{
|
||||||
u8 *len;
|
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);
|
wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Device Password ID */
|
if (pw_id >= 0) {
|
||||||
wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
|
/* Device Password ID */
|
||||||
wpabuf_put_be16(buf, 2);
|
wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
|
||||||
wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id);
|
wpabuf_put_be16(buf, 2);
|
||||||
wpabuf_put_be16(buf, pw_id);
|
wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d",
|
||||||
|
pw_id);
|
||||||
|
wpabuf_put_be16(buf, pw_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (all_attr) {
|
if (all_attr) {
|
||||||
wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
|
wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
|
||||||
|
|
|
@ -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) {
|
switch (wps_method) {
|
||||||
case WPS_PIN_DISPLAY:
|
case WPS_PIN_DISPLAY:
|
||||||
|
|
|
@ -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,
|
void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
|
||||||
u16 interval);
|
u16 interval);
|
||||||
void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p);
|
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);
|
int all_attr);
|
||||||
|
|
||||||
/* p2p_sd.c */
|
/* 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,
|
void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
|
||||||
const u8 *data, size_t len);
|
const u8 *data, size_t len);
|
||||||
int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev);
|
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 */
|
/* p2p_pd.c */
|
||||||
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
|
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
|
||||||
|
|
|
@ -431,7 +431,8 @@ struct wpabuf * wps_build_assoc_resp_ie(void)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wps_build_probe_req_ie - Build WPS IE for Probe Request
|
* 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
|
* @dev: Device attributes
|
||||||
* @uuid: Own UUID
|
* @uuid: Own UUID
|
||||||
* @req_type: Value for Request Type attribute
|
* @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.
|
* 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,
|
const u8 *uuid,
|
||||||
enum wps_request_type req_type,
|
enum wps_request_type req_type,
|
||||||
unsigned int num_req_dev_types,
|
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_rf_bands(dev, ie) ||
|
||||||
wps_build_assoc_state(NULL, ie) ||
|
wps_build_assoc_state(NULL, ie) ||
|
||||||
wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
|
wps_build_config_error(ie, WPS_CFG_NO_ERROR) ||
|
||||||
wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON :
|
wps_build_dev_password_id(ie, pw_id) ||
|
||||||
DEV_PW_DEFAULT) ||
|
|
||||||
#ifdef CONFIG_WPS2
|
#ifdef CONFIG_WPS2
|
||||||
wps_build_manufacturer(dev, ie) ||
|
wps_build_manufacturer(dev, ie) ||
|
||||||
wps_build_model_name(dev, ie) ||
|
wps_build_model_name(dev, ie) ||
|
||||||
|
|
|
@ -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_req_ie(enum wps_request_type req_type);
|
||||||
struct wpabuf * wps_build_assoc_resp_ie(void);
|
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,
|
const u8 *uuid,
|
||||||
enum wps_request_type req_type,
|
enum wps_request_type req_type,
|
||||||
unsigned int num_req_dev_types,
|
unsigned int num_req_dev_types,
|
||||||
|
|
|
@ -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,
|
static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
|
||||||
unsigned int num_req_dev_types,
|
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_supplicant *wpa_s = ctx;
|
||||||
struct wpa_driver_scan_params params;
|
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;
|
params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
|
||||||
|
|
||||||
wpa_s->wps->dev.p2p = 1;
|
wpa_s->wps->dev.p2p = 1;
|
||||||
wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid,
|
wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
|
||||||
WPS_REQ_ENROLLEE,
|
wpa_s->wps->uuid, WPS_REQ_ENROLLEE,
|
||||||
num_req_dev_types, req_dev_types);
|
num_req_dev_types, req_dev_types);
|
||||||
if (wps_ie == NULL)
|
if (wps_ie == NULL)
|
||||||
return -1;
|
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;
|
params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
|
||||||
|
|
||||||
wpa_s->wps->dev.p2p = 1;
|
wpa_s->wps->dev.p2p = 1;
|
||||||
wps_ie = wps_build_probe_req_ie(0, &wpa_s->wps->dev, wpa_s->wps->uuid,
|
wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
|
||||||
WPS_REQ_ENROLLEE, 0, NULL);
|
wpa_s->wps->uuid, WPS_REQ_ENROLLEE, 0,
|
||||||
|
NULL);
|
||||||
if (wps_ie == NULL) {
|
if (wps_ie == NULL) {
|
||||||
wpas_p2p_scan_res_join(wpa_s, NULL);
|
wpas_p2p_scan_res_join(wpa_s, NULL);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -400,7 +400,9 @@ wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
if (wps) {
|
if (wps) {
|
||||||
struct wpabuf *wps_ie;
|
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,
|
wpa_s->wps->uuid, req_type,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
if (wps_ie) {
|
if (wps_ie) {
|
||||||
|
|
Loading…
Reference in a new issue