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"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps_defs.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_i.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen/*
1961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Number of retries to attempt for provision discovery requests
2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * in case the peer is not listening.
2175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen */
2275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen#define MAX_PROV_DISC_REQ_RETRIES 10
2375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
2475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					    u16 config_methods)
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = wpabuf_put(buf, 1);
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Config Methods */
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(buf, 2);
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(buf, config_methods);
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u8 dialog_token,
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       u16 config_methods,
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       struct p2p_device *go)
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *len;
4961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
5261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_prov_disc_req)
5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(1000 + extra);
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token);
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = p2p_buf_add_ie_hdr(buf);
6304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	p2p_buf_add_capability(buf, p2p->dev_capab &
6404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_device_info(buf, p2p, NULL);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (go) {
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_buf_add_group_id(buf, go->info.p2p_device_addr,
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     go->oper_ssid, go->oper_ssid_len);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_update_ie_hdr(buf, len);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* WPS IE with Config Methods attribute */
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_wps_ie_config_methods(buf, config_methods);
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->wfd_ie_prov_disc_req)
7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						u8 dialog_token,
8661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						u16 config_methods,
8761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						const u8 *group_id,
8861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt						size_t group_id_len)
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *buf;
9161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t extra = 0;
9261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
9561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wfd_ie && group_id) {
9661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		size_t i;
9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		for (i = 0; i < p2p->num_groups; i++) {
9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			struct p2p_group *g = p2p->groups[i];
9961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			struct wpabuf *ie;
10061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (!p2p_group_is_group_id_match(g, group_id,
10161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt							 group_id_len))
10261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				continue;
10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			ie = p2p_group_get_wfd_ie(g);
10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (ie) {
10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				wfd_ie = ie;
10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				break;
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			}
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
11061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wfd_ie)
11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		extra = wpabuf_len(wfd_ie);
11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	buf = wpabuf_alloc(100 + extra);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (buf == NULL)
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token);
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* WPS IE with Config Methods attribute */
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_build_wps_ie_config_methods(buf, config_methods);
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_WIFI_DISPLAY
12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wfd_ie)
12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_put_buf(buf, wfd_ie);
12661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_WIFI_DISPLAY */
12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return buf;
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       const u8 *data, size_t len, int rx_freq)
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int reject = 1;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *resp;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg))
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Received Provision Discovery Request from " MACSTR
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" with config methods 0x%x (freq=%d)",
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(sa), msg.wps_config_methods, rx_freq);
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, sa);
1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Provision Discovery Request from "
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"unknown peer " MACSTR, MAC2STR(sa));
15404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (p2p_add_device(p2p, sa, rx_freq, 0, data + 1, len - 1, 0))
15504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		{
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			        "P2P: Provision Discovery Request add device "
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"failed " MACSTR, MAC2STR(sa));
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
16061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	} else if (msg.wfd_subelems) {
16161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpabuf_free(dev->info.wfd_subelems);
16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(msg.wps_config_methods &
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD |
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       WPS_CONFIG_PUSHBUTTON))) {
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unsupported "
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Config Methods in Provision Discovery Request");
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (msg.group_id) {
17404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		size_t i;
17504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		for (i = 0; i < p2p->num_groups; i++) {
17604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (p2p_group_is_group_id_match(p2p->groups[i],
17704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt							msg.group_id,
17804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt							msg.group_id_len))
17904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				break;
18004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
18104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (i == p2p->num_groups) {
18204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: PD "
18304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"request for unknown P2P Group ID - reject");
18404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			goto out;
18504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
18604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
18704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				P2P_DEV_PD_PEER_KEYPAD);
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" requested us to show a PIN on display", MAC2STR(sa));
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" requested us to write its PIN using keypad",
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(sa));
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev)
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	reject = 0;
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	resp = p2p_build_prov_disc_resp(p2p, msg.dialog_token,
20861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					reject ? 0 : msg.wps_config_methods,
20961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					msg.group_id, msg.group_id_len);
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (resp == NULL) {
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"P2P: Sending Provision Discovery Response");
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rx_freq > 0)
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = rx_freq;
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		freq = p2p_channel_to_freq(p2p->cfg->country,
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->reg_class,
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   p2p->cfg->channel);
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq < 0) {
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Unknown regulatory class/channel");
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(resp);
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    p2p->cfg->dev_addr,
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(resp);
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!reject && p2p->cfg->prov_disc_req) {
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *dev_addr = sa;
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (msg.p2p_device_addr)
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			dev_addr = msg.p2p_device_addr;
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa,
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg.wps_config_methods,
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					dev_addr, msg.pri_dev_type,
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg.device_name, msg.config_methods,
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg.capability ? msg.capability[0] : 0,
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					msg.capability ? msg.capability[1] :
2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					0,
2501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					msg.group_id, msg.group_id_len);
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *data, size_t len)
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_message msg;
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 report_config_methods = 0;
26204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	int success = 0;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_parse(data, len, &msg))
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		"P2P: Received Provision Discovery Response from " MACSTR
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" with config methods 0x%x",
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(sa), msg.wps_config_methods);
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, sa);
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || !dev->req_config_methods) {
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"P2P: Ignore Provision Discovery Response from "
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR " with no pending request", MAC2STR(sa));
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->dialog_token != msg.dialog_token) {
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"P2P: Ignore Provision Discovery Response with "
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"unexpected Dialog Token %u (expected %u)",
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			msg.dialog_token, dev->dialog_token);
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29091c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt	if (p2p->pending_action_state == P2P_PENDING_PD) {
29191c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt		os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
29291c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
29391c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt	}
29491c40cdce17424d9a4718876becf0b7811cf68f2Dmitry Shmidt
29575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
29675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * If the response is from the peer to whom a user initiated request
29775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * was sent earlier, we reset that state info here.
29875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
29975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (p2p->user_initiated_pd &&
30075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	    os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0)
30175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p_reset_pending_pd(p2p);
30275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (msg.wps_config_methods != dev->req_config_methods) {
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer rejected "
3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"our Provision Discovery Request");
30675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (p2p->cfg->prov_disc_fail)
30775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
30875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen						 P2P_PROV_DISC_REJECTED);
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p_parse_free(&msg);
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		goto out;
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	report_config_methods = dev->req_config_methods;
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			P2P_DEV_PD_PEER_KEYPAD);
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->req_config_methods & WPS_CONFIG_DISPLAY) {
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" accepted to show a PIN on display", MAC2STR(sa));
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" accepted to write our PIN using keypad",
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(sa));
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* Store the provisioning info */
3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev->wps_prov_info = msg.wps_config_methods;
3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p_parse_free(&msg);
33104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	success = 1;
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtout:
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->req_config_methods = 0;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
33604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
33704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
33804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"P2P: Start GO Neg after the PD-before-GO-Neg "
33904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			"workaround with " MACSTR,
34004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
34104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
34204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_connect_send(p2p, dev);
34304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
34404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
34504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (success && p2p->cfg->prov_disc_resp)
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 report_config_methods);
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   int join, int force_freq)
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpabuf *req;
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int freq;
356497c1d5e50162d6b3c1cce5dbd9c5fd9da69aaefDmitry Shmidt
3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (force_freq > 0)
3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		freq = force_freq;
3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	else
3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		freq = dev->listen_freq > 0 ? dev->listen_freq :
3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			dev->oper_freq;
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freq <= 0) {
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: No Listen/Operating frequency known for the "
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"peer " MACSTR " to send Provision Discovery Request",
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(dev->info.p2p_device_addr));
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(dev->info.dev_capab &
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"P2P: Cannot use PD with P2P Device " MACSTR
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				" that is in a group and is not discoverable",
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(dev->info.p2p_device_addr));
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: use device discoverability request through GO */
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->dialog_token++;
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->dialog_token == 0)
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->dialog_token = 1;
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	req = p2p_build_prov_disc_req(p2p, dev->dialog_token,
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      dev->req_config_methods,
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      join ? dev : NULL);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (req == NULL)
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
39104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (p2p->state != P2P_IDLE)
39204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		p2p_stop_listen_for_freq(p2p, freq);
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p2p->pending_action_state = P2P_PENDING_PD;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"P2P: Failed to send Action frame");
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(req);
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN);
40475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_free(req);
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
4111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		      u16 config_methods, int join, int force_freq)
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct p2p_device *dev;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev = p2p_get_device(p2p, peer_addr);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL)
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev = p2p_get_device_interface(p2p, peer_addr);
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision "
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"Discovery Request destination " MACSTR
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" not yet known", MAC2STR(peer_addr));
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision Discovery "
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"Request with " MACSTR " (config methods 0x%x)",
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(peer_addr), config_methods);
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (config_methods == 0)
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* Reset provisioning info */
4321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dev->wps_prov_info = 0;
4331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->req_config_methods = config_methods;
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (join)
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags |= P2P_DEV_PD_FOR_JOIN;
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		dev->flags &= ~P2P_DEV_PD_FOR_JOIN;
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
440c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH &&
441c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	    p2p->state != P2P_LISTEN_ONLY) {
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Busy with other "
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"operations; postpone Provision Discovery Request "
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"with " MACSTR " (config methods 0x%x)",
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(peer_addr), config_methods);
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
44975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	/*
45075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * We use the join param as a cue to differentiate between user
45175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 * initiated PD request and one issued during finds (internal).
45275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	 */
45375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->user_initiated_pd = !join;
45475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
45561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (p2p->user_initiated_pd)
45675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;
45775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
4581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return p2p_send_prov_disc_req(p2p, dev, join, force_freq);
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
46075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
46175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
46275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenvoid p2p_reset_pending_pd(struct p2p_data *p2p)
46375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
4641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct p2p_device *dev;
4651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
4661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
4671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(p2p->pending_pd_devaddr,
4681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      dev->info.p2p_device_addr, ETH_ALEN))
4691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
4701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!dev->req_config_methods)
4711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
4721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (dev->flags & P2P_DEV_PD_FOR_JOIN)
4731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
4741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/* Reset the config methods of the device */
4751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		dev->req_config_methods = 0;
4761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
4771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
47875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->user_initiated_pd = 0;
47975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
48075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	p2p->pd_retries = 0;
48175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
482