18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Direct - P2P provision discovery
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2009-2010, Atheros Communications
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
132e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt#include "common/wpa_ctrl.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_defs.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/*
2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Number of retries to attempt for provision discovery requests
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * in case the peer is not listening.
2275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
23d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#define MAX_PROV_DISC_REQ_RETRIES 120
2475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
2575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    u16 config_methods)
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = wpabuf_put(buf, 1);
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Config Methods */
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(buf, 2);
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(buf, config_methods);
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u8 dialog_token,
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u16 config_methods,
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       struct p2p_device *go)
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_prov_disc_req)
5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
572e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
582e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
592e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(1000 + extra);
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
6704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
6804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_group_id(buf, go->info.p2p_device_addr,
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     go->oper_ssid, go->oper_ssid_len);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* WPS IE with Config Methods attribute */
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_wps_ie_config_methods(buf, config_methods);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
8061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_prov_disc_req)
8161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
8261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
8361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
842e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
852e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
862e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						u8 dialog_token,
9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						u16 config_methods,
9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						const u8 *group_id,
9561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						size_t group_id_len)
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
9961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
10161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
10261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wfd_ie && group_id) {
10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		size_t i;
10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		for (i = 0; i < p2p->num_groups; i++) {
10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			struct p2p_group *g = p2p->groups[i];
10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			struct wpabuf *ie;
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (!p2p_group_is_group_id_match(g, group_id,
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt							 group_id_len))
10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				continue;
11061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			ie = p2p_group_get_wfd_ie(g);
11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (ie) {
11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				wfd_ie = ie;
11361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				break;
11461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			}
11561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
11661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wfd_ie)
11861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(wfd_ie);
11961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1212e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
1222e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
1232e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(100 + extra);
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token);
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* WPS IE with Config Methods attribute */
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_wps_ie_config_methods(buf, config_methods);
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wfd_ie)
13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, wfd_ie);
13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1382e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
1392e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
1402e67f06149ff649fb6f8782bad041d3d9124685eDmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const u8 *data, size_t len, int rx_freq)
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reject = 1;
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg))
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
157b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" with config methods 0x%x (freq=%d)",
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(sa), msg.wps_config_methods, rx_freq);
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, sa);
1621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
163b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Provision Discovery Request from unknown peer "
164b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR, MAC2STR(sa));
165a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
166f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
167a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				   0)) {
168b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Provision Discovery Request add device failed "
169b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt				MACSTR, MAC2STR(sa));
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (msg.wfd_subelems) {
17261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
17361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(msg.wps_config_methods &
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD |
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       WPS_CONFIG_PUSHBUTTON))) {
179b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unsupported Config Methods in Provision Discovery Request");
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (msg.group_id) {
18404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		size_t i;
18504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		for (i = 0; i < p2p->num_groups; i++) {
18604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (p2p_group_is_group_id_match(p2p->groups[i],
18704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt							msg.group_id,
18804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt							msg.group_id_len))
18904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				break;
19004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
19104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (i == p2p->num_groups) {
192b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "PD request for unknown P2P Group ID - reject");
19304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			goto out;
19404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
19504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
19604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				P2P_DEV_PD_PEER_KEYPAD);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
201b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" requested us to show a PIN on display", MAC2STR(sa));
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev)
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
206b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" requested us to write its PIN using keypad",
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(sa));
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev)
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reject = 0;
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_prov_disc_resp(p2p, msg.dialog_token,
21761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					reject ? 0 : msg.wps_config_methods,
21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					msg.group_id, msg.group_id_len);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL) {
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
223b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Sending Provision Discovery Response");
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rx_freq > 0)
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = rx_freq;
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2274b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
230b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Unknown regulatory class/channel");
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(resp);
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    p2p->cfg->dev_addr,
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
239b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
2404582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt	} else
2414582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		p2p->send_action_in_progress = 1;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!reject && p2p->cfg->prov_disc_req) {
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *dev_addr = sa;
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.p2p_device_addr)
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev_addr = msg.p2p_device_addr;
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa,
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg.wps_config_methods,
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					dev_addr, msg.pri_dev_type,
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg.device_name, msg.config_methods,
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg.capability ? msg.capability[0] : 0,
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg.capability ? msg.capability[1] :
2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					0,
2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					msg.group_id, msg.group_id_len);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *data, size_t len)
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
267444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	u16 report_config_methods = 0, req_config_methods;
26804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int success = 0;
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg))
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
273b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" with config methods 0x%x",
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(sa), msg.wps_config_methods);
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, sa);
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || !dev->req_config_methods) {
279b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore Provision Discovery Response from " MACSTR
280b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			" with no pending request", MAC2STR(sa));
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->dialog_token != msg.dialog_token) {
286b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Ignore Provision Discovery Response with unexpected Dialog Token %u (expected %u)",
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.dialog_token, dev->dialog_token);
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29291c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt	if (p2p->pending_action_state == P2P_PENDING_PD) {
29391c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt		os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
29491c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
29591c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt	}
29691c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt
29775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
298444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	 * Use a local copy of the requested config methods since
299444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	 * p2p_reset_pending_pd() can clear this in the peer entry.
300444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	 */
301444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	req_config_methods = dev->req_config_methods;
302444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt
303444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	/*
30475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * If the response is from the peer to whom a user initiated request
30575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * was sent earlier, we reset that state info here.
30675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
30775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd &&
30875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	    os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0)
30975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
31075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
311444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	if (msg.wps_config_methods != req_config_methods) {
312b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer rejected our Provision Discovery Request (received config_methods 0x%x expected 0x%x",
313444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt			msg.wps_config_methods, req_config_methods);
31475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
31575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
31675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 P2P_PROV_DISC_REJECTED);
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
321444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	report_config_methods = req_config_methods;
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			P2P_DEV_PD_PEER_KEYPAD);
324444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt	if (req_config_methods & WPS_CONFIG_DISPLAY) {
325b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" accepted to show a PIN on display", MAC2STR(sa));
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
329b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Peer " MACSTR
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" accepted to write our PIN using keypad",
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(sa));
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* Store the provisioning info */
3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev->wps_prov_info = msg.wps_config_methods;
3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
33904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	success = 1;
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->req_config_methods = 0;
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
34404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
345b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Start GO Neg after the PD-before-GO-Neg workaround with "
346b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR, MAC2STR(dev->info.p2p_device_addr));
34704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
34804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_connect_send(p2p, dev);
34904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
35004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
35104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (success && p2p->cfg->prov_disc_resp)
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 report_config_methods);
35437d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
35537d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	if (p2p->state == P2P_PD_DURING_FIND) {
35637d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		p2p_clear_timeout(p2p);
35737d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		p2p_continue_find(p2p);
35837d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	}
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   int join, int force_freq)
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
367497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt
3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (force_freq > 0)
3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		freq = force_freq;
3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		freq = dev->listen_freq > 0 ? dev->listen_freq :
3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			dev->oper_freq;
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq <= 0) {
374b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
375b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR " to send Provision Discovery Request",
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
383b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			p2p_dbg(p2p, "Cannot use PD with P2P Device " MACSTR
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr));
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: use device discoverability request through GO */
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_prov_disc_req(p2p, dev->dialog_token,
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      dev->req_config_methods,
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      join ? dev : NULL);
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->state != P2P_IDLE)
39804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_stop_listen_for_freq(p2p, freq);
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_PENDING_PD;
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
403b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Failed to send Action frame");
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(req);
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN);
40975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
416d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		      u16 config_methods, int join, int force_freq,
417d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		      int user_initiated_pd)
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device_interface(p2p, peer_addr);
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
425b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Provision Discovery Request destination " MACSTR
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" not yet known", MAC2STR(peer_addr));
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
430b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt	p2p_dbg(p2p, "Provision Discovery Request with " MACSTR
431b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		" (config methods 0x%x)",
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), config_methods);
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config_methods == 0)
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* Reset provisioning info */
4371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev->wps_prov_info = 0;
4381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->req_config_methods = config_methods;
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (join)
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_PD_FOR_JOIN;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PD_FOR_JOIN;
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
445c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH &&
446c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	    p2p->state != P2P_LISTEN_ONLY) {
447b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt		p2p_dbg(p2p, "Busy with other operations; postpone Provision Discovery Request with "
448b6e9aaf735990dc64cdb6efccc03d076768eabf3Dmitry Shmidt			MACSTR " (config methods 0x%x)",
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr), config_methods);
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
453d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	p2p->user_initiated_pd = user_initiated_pd;
454051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	p2p->pd_force_freq = force_freq;
45575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
45661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->user_initiated_pd)
45775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;
45875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
459a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	/*
460a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * Assign dialog token here to use the same value in each retry within
461a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * the same PD exchange.
462a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 */
463a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	dev->dialog_token++;
464a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (dev->dialog_token == 0)
465a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		dev->dialog_token = 1;
466a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
4671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_send_prov_disc_req(p2p, dev, join, force_freq);
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
47075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
47175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenvoid p2p_reset_pending_pd(struct p2p_data *p2p)
47275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
4731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
4741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(p2p->pending_pd_devaddr,
4771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      dev->info.p2p_device_addr, ETH_ALEN))
4781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
4791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!dev->req_config_methods)
4801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
4811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (dev->flags & P2P_DEV_PD_FOR_JOIN)
4821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
4831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Reset the config methods of the device */
4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->req_config_methods = 0;
4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
4861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
48775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->user_initiated_pd = 0;
48875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
48975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pd_retries = 0;
490051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	p2p->pd_force_freq = 0;
49175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
492