diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 2f4c1147c..e7ce2308f 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -2096,6 +2096,32 @@ int p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end) } +int p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr) +{ + struct wpabuf *p2p_ie; + struct p2p_message msg; + + p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, + P2P_IE_VENDOR_TYPE); + if (p2p_ie == NULL) + return -1; + os_memset(&msg, 0, sizeof(msg)); + if (p2p_parse_p2p_ie(p2p_ie, &msg)) { + wpabuf_free(p2p_ie); + return -1; + } + + if (msg.p2p_device_addr == NULL) { + wpabuf_free(p2p_ie); + return -1; + } + + os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN); + wpabuf_free(p2p_ie); + return 0; +} + + static void p2p_clear_go_neg(struct p2p_data *p2p) { p2p->go_neg_peer = NULL; diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 0924db5cc..9c4070c93 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1376,6 +1376,15 @@ int p2p_ie_text(struct wpabuf *p2p_ie, char *buf, char *end); */ int p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end); +/** + * p2p_parse_dev_addr - Parse P2P Device Address from P2P IE(s) + * @ies: Information elements from scan results + * @ies_len: ies buffer length in octets + * @dev_addr: Buffer for returning P2P Device Address + * Returns: 0 on success or -1 if P2P Device Address could not be parsed + */ +int p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr); + /** * p2p_assoc_req_ie - Build P2P IE for (Re)Association Request frame * @p2p: P2P module context from p2p_init() diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 078e22d7c..1e7965895 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -540,6 +540,23 @@ struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, } +#ifdef CONFIG_P2P +struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, + const u8 *dev_addr) +{ + struct wpa_bss *bss; + dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) { + u8 addr[ETH_ALEN]; + if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, + addr) == 0 && + os_memcmp(addr, dev_addr, ETH_ALEN) == 0) + return bss; + } + return NULL; +} +#endif /* CONFIG_P2P */ + + struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id) { struct wpa_bss *bss; diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index bb19f492c..9f1329868 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -94,6 +94,8 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid, const u8 *ssid, size_t ssid_len); struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid); +struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, + const u8 *dev_addr); struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id); const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 6a3223e36..7f4fb0974 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2210,6 +2210,13 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, bss = dl_list_entry(next, struct wpa_bss, list_id); } +#ifdef CONFIG_P2P + } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { + if (hwaddr_aton(cmd + 13, bssid) == 0) + bss = wpa_bss_get_p2p_dev_addr(wpa_s, bssid); + else + bss = NULL; +#endif /* CONFIG_P2P */ } else if (hwaddr_aton(cmd, bssid) == 0) bss = wpa_bss_get_bssid(wpa_s, bssid); else {