diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index f8e314b17..8d70b4d86 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -2832,7 +2832,7 @@ static int wpa_driver_test_p2p_find(void *priv, unsigned int timeout, int type) wpa_printf(MSG_DEBUG, "%s(timeout=%u)", __func__, timeout); if (!drv->p2p) return -1; - return p2p_find(drv->p2p, timeout, type, 0, NULL); + return p2p_find(drv->p2p, timeout, type, 0, NULL, NULL); } @@ -2918,7 +2918,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 *req_dev_types, const u8 *dev_id) { struct wpa_driver_test_data *drv = ctx; struct wpa_driver_scan_params params; @@ -2956,7 +2956,7 @@ static int test_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, wpabuf_put_buf(ies, wps_ie); wpabuf_free(wps_ie); - p2p_scan_ie(drv->p2p, ies); + p2p_scan_ie(drv->p2p, ies, dev_id); params.extra_ies = wpabuf_head(ies); params.extra_ies_len = wpabuf_len(ies); diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 001743be7..e61e1336f 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -795,8 +795,8 @@ 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) < 0) - { + p2p->num_req_dev_types, p2p->req_dev_types, + p2p->find_dev_id) < 0) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Scan request failed"); p2p_continue_find(p2p); @@ -895,7 +895,8 @@ static void p2p_free_req_dev_types(struct p2p_data *p2p) int p2p_find(struct p2p_data *p2p, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types) + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id) { int res; @@ -917,6 +918,12 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, p2p->num_req_dev_types = num_req_dev_types; } + if (dev_id) { + os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN); + p2p->find_dev_id = p2p->find_dev_id_buf; + } else + p2p->find_dev_id = NULL; + p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; p2p_clear_timeout(p2p); p2p->cfg->stop_listen(p2p->cfg->cb_ctx); @@ -933,12 +940,12 @@ 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); + p2p->req_dev_types, dev_id); 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); + p2p->req_dev_types, dev_id); break; default: return -1; @@ -975,7 +982,8 @@ int p2p_other_scan_completed(struct p2p_data *p2p) wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find " "now that previous scan was completed"); if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type, - p2p->num_req_dev_types, p2p->req_dev_types) < 0) + p2p->num_req_dev_types, p2p->req_dev_types, + p2p->find_dev_id) < 0) return 0; return 1; } @@ -2533,10 +2541,12 @@ void p2p_scan_res_handled(struct p2p_data *p2p) } -void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies) +void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id) { u8 *len = p2p_buf_add_ie_hdr(ies); p2p_buf_add_capability(ies, p2p->dev_capab, 0); + if (dev_id) + p2p_buf_add_device_id(ies, dev_id); if (p2p->cfg->reg_class && p2p->cfg->channel) p2p_buf_add_listen_channel(ies, p2p->cfg->country, p2p->cfg->reg_class, diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index c9e9fd3ba..762499abf 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -359,6 +359,7 @@ struct p2p_config { * @freq: Specific frequency (MHz) to scan or 0 for no restriction * @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 * Returns: 0 on success, -1 on failure * * This callback function is used to request a P2P scan or search @@ -382,7 +383,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 *req_dev_types, const u8 *dev_id); /** * send_probe_resp - Transmit a Probe Response frame @@ -809,11 +810,13 @@ enum p2p_discovery_type { * @req_dev_types: Requested device types array, must be an array * containing num_req_dev_types * WPS_DEV_TYPE_LEN bytes; %NULL if no * requested device types. + * @dev_id: Device ID to search for or %NULL to find all devices * Returns: 0 on success, -1 on failure */ int p2p_find(struct p2p_data *p2p, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types); + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id); /** * p2p_stop_find - Stop P2P Find (Device Discovery) @@ -1376,8 +1379,9 @@ int p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf, * p2p_scan_ie - Build P2P IE for Probe Request * @p2p: P2P module context from p2p_init() * @ies: Buffer for writing P2P IE + * @dev_id: Device ID to search for or %NULL for any */ -void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies); +void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id); /** * p2p_scan_ie_buf_len - Get maximum buffer length needed for p2p_scan_ie diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 0dc33e76e..a578bb78e 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -381,6 +381,8 @@ struct p2p_data { /* Requested device types for find/search */ unsigned int num_req_dev_types; u8 *req_dev_types; + u8 *find_dev_id; + u8 find_dev_id_buf[ETH_ALEN]; struct p2p_group **groups; size_t num_groups; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index fcb4fa48d..ad3cbb9cb 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2451,13 +2451,23 @@ static int p2p_ctrl_find(struct wpa_supplicant *wpa_s, char *cmd) { unsigned int timeout = atoi(cmd); enum p2p_discovery_type type = P2P_FIND_START_WITH_FULL; + u8 dev_id[ETH_ALEN], *_dev_id = NULL; + char *pos; if (os_strstr(cmd, "type=social")) type = P2P_FIND_ONLY_SOCIAL; else if (os_strstr(cmd, "type=progressive")) type = P2P_FIND_PROGRESSIVE; - return wpas_p2p_find(wpa_s, timeout, type, 0, NULL); + pos = os_strstr(cmd, "dev_id="); + if (pos) { + pos += 7; + if (hwaddr_aton(pos, dev_id)) + return -1; + _dev_id = dev_id; + } + + return wpas_p2p_find(wpa_s, timeout, type, 0, NULL, _dev_id); } diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c index 671d0e5ef..0f6914c83 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c @@ -131,7 +131,8 @@ DBusMessage * wpas_dbus_handler_p2p_find(DBusMessage *message, wpa_dbus_dict_entry_clear(&entry); } - wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types); + wpas_p2p_find(wpa_s, timeout, type, num_req_dev_types, req_dev_types, + NULL); os_free(req_dev_types); return reply; diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 2fb2d0a38..8ef35530c 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -94,7 +94,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 *req_dev_types, const u8 *dev_id) { struct wpa_supplicant *wpa_s = ctx; struct wpa_driver_scan_params params; @@ -130,7 +130,7 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, wpabuf_put_buf(ies, wps_ie); wpabuf_free(wps_ie); - p2p_scan_ie(wpa_s->global->p2p, ies); + p2p_scan_ie(wpa_s->global->p2p, ies, dev_id); params.p2p_probe = 1; params.extra_ies = wpabuf_head(ies); @@ -2667,7 +2667,7 @@ static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx) wpabuf_put_buf(ies, wps_ie); wpabuf_free(wps_ie); - p2p_scan_ie(wpa_s->global->p2p, ies); + p2p_scan_ie(wpa_s->global->p2p, ies, NULL); params.p2p_probe = 1; params.extra_ies = wpabuf_head(ies); @@ -3459,7 +3459,8 @@ static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s) int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types) + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id) { wpas_p2p_clear_pending_action_tx(wpa_s); wpa_s->p2p_long_listen = 0; @@ -3471,7 +3472,7 @@ int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, return -1; return p2p_find(wpa_s->global->p2p, timeout, type, - num_req_dev_types, req_dev_types); + num_req_dev_types, req_dev_types, dev_id); } @@ -3599,7 +3600,7 @@ void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies) if (wpa_s->global->p2p == NULL) return; - p2p_scan_ie(wpa_s->global->p2p, ies); + p2p_scan_ie(wpa_s->global->p2p, ies, NULL); } diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 3150f0499..605741dba 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -52,7 +52,8 @@ int wpas_p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, enum p2p_discovery_type; int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types); + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id); void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s); int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout); int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 512329df0..ffec0ff9d 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1930,7 +1930,10 @@ static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc == 0) return wpa_ctrl_command(ctrl, "P2P_FIND"); - if (argc > 1) + if (argc > 2) + res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s %s", + argv[0], argv[1], argv[2]); + else if (argc > 1) res = os_snprintf(cmd, sizeof(cmd), "P2P_FIND %s %s", argv[0], argv[1]); else