p2p_pd.c revision 444d567b27731d8572ef37697dd12fd1c37c2f24
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wi-Fi Direct - P2P provision discovery
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2009-2010, Atheros Communications
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This software may be distributed under the terms of the BSD license.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See README for more details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "includes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "common.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "common/ieee802_11_defs.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "wps/wps_defs.h"
148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "p2p_i.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "p2p.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Number of retries to attempt for provision discovery requests
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * in case the peer is not listening.
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define MAX_PROV_DISC_REQ_RETRIES 120
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					    u16 config_methods)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	u8 *len;
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	len = wpabuf_put(buf, 1);
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	/* Config Methods */
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpabuf_put_be16(buf, 2);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpabuf_put_be16(buf, config_methods);
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	p2p_buf_update_ie_hdr(buf, len);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       u8 dialog_token,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       u16 config_methods,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       struct p2p_device *go)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct wpabuf *buf;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	u8 *len;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	size_t extra = 0;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef CONFIG_WIFI_DISPLAY
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (p2p->wfd_ie_prov_disc_req)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_WIFI_DISPLAY */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	buf = wpabuf_alloc(1000 + extra);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (buf == NULL)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	len = p2p_buf_add_ie_hdr(buf);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	p2p_buf_add_capability(buf, p2p->dev_capab &
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			       ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY, 0);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	p2p_buf_add_device_info(buf, p2p, NULL);
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	if (go) {
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		p2p_buf_add_group_id(buf, go->info.p2p_device_addr,
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)				     go->oper_ssid, go->oper_ssid_len);
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	}
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	p2p_buf_update_ie_hdr(buf, len);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* WPS IE with Config Methods attribute */
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	p2p_build_wps_ie_config_methods(buf, config_methods);
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef CONFIG_WIFI_DISPLAY
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (p2p->wfd_ie_prov_disc_req)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif /* CONFIG_WIFI_DISPLAY */
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return buf;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						u8 dialog_token,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						u16 config_methods,
87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch						const u8 *group_id,
88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch						size_t group_id_len)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct wpabuf *buf;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	size_t extra = 0;
92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#ifdef CONFIG_WIFI_DISPLAY
94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	if (wfd_ie && group_id) {
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		size_t i;
97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		for (i = 0; i < p2p->num_groups; i++) {
98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			struct p2p_group *g = p2p->groups[i];
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			struct wpabuf *ie;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			if (!p2p_group_is_group_id_match(g, group_id,
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)							 group_id_len))
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				continue;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			ie = p2p_group_get_wfd_ie(g);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			if (ie) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				wfd_ie = ie;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				break;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			}
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (wfd_ie)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		extra = wpabuf_len(wfd_ie);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_WIFI_DISPLAY */
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	buf = wpabuf_alloc(100 + extra);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (buf == NULL)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return NULL;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* WPS IE with Config Methods attribute */
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	p2p_build_wps_ie_config_methods(buf, config_methods);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef CONFIG_WIFI_DISPLAY
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (wfd_ie)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpabuf_put_buf(buf, wfd_ie);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* CONFIG_WIFI_DISPLAY */
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return buf;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       const u8 *data, size_t len, int rx_freq)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct p2p_message msg;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct p2p_device *dev;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int freq;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	int reject = 1;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct wpabuf *resp;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (p2p_parse(data, len, &msg))
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		return;
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		"P2P: Received Provision Discovery Request from " MACSTR
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		" with config methods 0x%x (freq=%d)",
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		MAC2STR(sa), msg.wps_config_methods, rx_freq);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dev = p2p_get_device(p2p, sa);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"P2P: Provision Discovery Request from "
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"unknown peer " MACSTR, MAC2STR(sa));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   0)) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			        "P2P: Provision Discovery Request add device "
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				"failed " MACSTR, MAC2STR(sa));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)	} else if (msg.wfd_subelems) {
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)		wpabuf_free(dev->info.wfd_subelems);
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)		dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)	}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!(msg.wps_config_methods &
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	      (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD |
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	       WPS_CONFIG_PUSHBUTTON))) {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unsupported "
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			"Config Methods in Provision Discovery Request");
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		goto out;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (msg.group_id) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		size_t i;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		for (i = 0; i < p2p->num_groups; i++) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			if (p2p_group_is_group_id_match(p2p->groups[i],
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)							msg.group_id,
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)							msg.group_id_len))
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				break;
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		}
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		if (i == p2p->num_groups) {
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: PD "
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				"request for unknown P2P Group ID - reject");
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			goto out;
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		}
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	}
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (dev)
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)		dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)				P2P_DEV_PD_PEER_KEYPAD);
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			" requested us to show a PIN on display", MAC2STR(sa));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (dev)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			" requested us to write its PIN using keypad",
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			MAC2STR(sa));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (dev)
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	reject = 0;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out:
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	resp = p2p_build_prov_disc_resp(p2p, msg.dialog_token,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					reject ? 0 : msg.wps_config_methods,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					msg.group_id, msg.group_id_len);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (resp == NULL) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		p2p_parse_free(&msg);
2138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		return;
2148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	}
2158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"P2P: Sending Provision Discovery Response");
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rx_freq > 0)
2188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		freq = rx_freq;
2198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	else
2208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		freq = p2p_channel_to_freq(p2p->cfg->country,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   p2p->cfg->reg_class,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   p2p->cfg->channel);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (freq < 0) {
2248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)			"P2P: Unknown regulatory class/channel");
2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		wpabuf_free(resp);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		p2p_parse_free(&msg);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
2318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
2328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)			    p2p->cfg->dev_addr,
2338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
2348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)			"P2P: Failed to send Action frame");
2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	}
2378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpabuf_free(resp);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	if (!reject && p2p->cfg->prov_disc_req) {
2418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		const u8 *dev_addr = sa;
2428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		if (msg.p2p_device_addr)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			dev_addr = msg.p2p_device_addr;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					msg.wps_config_methods,
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)					dev_addr, msg.pri_dev_type,
2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)					msg.device_name, msg.config_methods,
2488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)					msg.capability ? msg.capability[0] : 0,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					msg.capability ? msg.capability[1] :
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					0,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					msg.group_id, msg.group_id_len);
2528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	}
2538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	p2p_parse_free(&msg);
2548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
2588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)				const u8 *data, size_t len)
2598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles){
2608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	struct p2p_message msg;
2618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	struct p2p_device *dev;
2628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	u16 report_config_methods = 0, req_config_methods;
2638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)	int success = 0;
2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (p2p_parse(data, len, &msg))
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		"P2P: Received Provision Discovery Response from " MACSTR
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		" with config methods 0x%x",
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		MAC2STR(sa), msg.wps_config_methods);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dev = p2p_get_device(p2p, sa);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dev == NULL || !dev->req_config_methods) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"P2P: Ignore Provision Discovery Response from "
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			MACSTR " with no pending request", MAC2STR(sa));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		p2p_parse_free(&msg);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	}
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (dev->dialog_token != msg.dialog_token) {
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			"P2P: Ignore Provision Discovery Response with "
28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			"unexpected Dialog Token %u (expected %u)",
28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)			msg.dialog_token, dev->dialog_token);
28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		p2p_parse_free(&msg);
28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		return;
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch	if (p2p->pending_action_state == P2P_PENDING_PD) {
2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch	}
2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch	/*
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * Use a local copy of the requested config methods since
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * p2p_reset_pending_pd() can clear this in the peer entry.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	req_config_methods = dev->req_config_methods;
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	/*
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * If the response is from the peer to whom a user initiated request
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * was sent earlier, we reset that state info here.
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 */
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (p2p->user_initiated_pd &&
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	    os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0)
3088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)		p2p_reset_pending_pd(p2p);
3098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (msg.wps_config_methods != req_config_methods) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer rejected "
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"our Provision Discovery Request (received "
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			"config_methods 0x%x expected 0x%x",
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			msg.wps_config_methods, req_config_methods);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (p2p->cfg->prov_disc_fail)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						 P2P_PROV_DISC_REJECTED);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		p2p_parse_free(&msg);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto out;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	report_config_methods = req_config_methods;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			P2P_DEV_PD_PEER_KEYPAD);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (req_config_methods & WPS_CONFIG_DISPLAY) {
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			" accepted to show a PIN on display", MAC2STR(sa));
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " MACSTR
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			" accepted to write our PIN using keypad",
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			MAC2STR(sa));
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* Store the provisioning info */
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	dev->wps_prov_info = msg.wps_config_methods;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	p2p_parse_free(&msg);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	success = 1;
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out:
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dev->req_config_methods = 0;
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			"P2P: Start GO Neg after the PD-before-GO-Neg "
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			"workaround with " MACSTR,
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)			MAC2STR(dev->info.p2p_device_addr));
350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)		dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		p2p_connect_send(p2p, dev);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		return;
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch	}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (success && p2p->cfg->prov_disc_resp)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 report_config_methods);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (p2p->state == P2P_PD_DURING_FIND) {
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		p2p_clear_timeout(p2p);
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		p2p_continue_find(p2p);
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   int join, int force_freq)
367{
368	struct wpabuf *req;
369	int freq;
370
371	if (force_freq > 0)
372		freq = force_freq;
373	else
374		freq = dev->listen_freq > 0 ? dev->listen_freq :
375			dev->oper_freq;
376	if (freq <= 0) {
377		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
378			"P2P: No Listen/Operating frequency known for the "
379			"peer " MACSTR " to send Provision Discovery Request",
380			MAC2STR(dev->info.p2p_device_addr));
381		return -1;
382	}
383
384	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
385		if (!(dev->info.dev_capab &
386		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
387			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
388				"P2P: Cannot use PD with P2P Device " MACSTR
389				" that is in a group and is not discoverable",
390				MAC2STR(dev->info.p2p_device_addr));
391			return -1;
392		}
393		/* TODO: use device discoverability request through GO */
394	}
395
396	req = p2p_build_prov_disc_req(p2p, dev->dialog_token,
397				      dev->req_config_methods,
398				      join ? dev : NULL);
399	if (req == NULL)
400		return -1;
401
402	if (p2p->state != P2P_IDLE)
403		p2p_stop_listen_for_freq(p2p, freq);
404	p2p->pending_action_state = P2P_PENDING_PD;
405	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
406			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,
407			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
408		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
409			"P2P: Failed to send Action frame");
410		wpabuf_free(req);
411		return -1;
412	}
413
414	os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN);
415
416	wpabuf_free(req);
417	return 0;
418}
419
420
421int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
422		      u16 config_methods, int join, int force_freq,
423		      int user_initiated_pd)
424{
425	struct p2p_device *dev;
426
427	dev = p2p_get_device(p2p, peer_addr);
428	if (dev == NULL)
429		dev = p2p_get_device_interface(p2p, peer_addr);
430	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
431		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision "
432			"Discovery Request destination " MACSTR
433			" not yet known", MAC2STR(peer_addr));
434		return -1;
435	}
436
437	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Provision Discovery "
438		"Request with " MACSTR " (config methods 0x%x)",
439		MAC2STR(peer_addr), config_methods);
440	if (config_methods == 0)
441		return -1;
442
443	/* Reset provisioning info */
444	dev->wps_prov_info = 0;
445
446	dev->req_config_methods = config_methods;
447	if (join)
448		dev->flags |= P2P_DEV_PD_FOR_JOIN;
449	else
450		dev->flags &= ~P2P_DEV_PD_FOR_JOIN;
451
452	if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH &&
453	    p2p->state != P2P_LISTEN_ONLY) {
454		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Busy with other "
455			"operations; postpone Provision Discovery Request "
456			"with " MACSTR " (config methods 0x%x)",
457			MAC2STR(peer_addr), config_methods);
458		return 0;
459	}
460
461	p2p->user_initiated_pd = user_initiated_pd;
462
463	if (p2p->user_initiated_pd)
464		p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;
465
466	/*
467	 * Assign dialog token here to use the same value in each retry within
468	 * the same PD exchange.
469	 */
470	dev->dialog_token++;
471	if (dev->dialog_token == 0)
472		dev->dialog_token = 1;
473
474	return p2p_send_prov_disc_req(p2p, dev, join, force_freq);
475}
476
477
478void p2p_reset_pending_pd(struct p2p_data *p2p)
479{
480	struct p2p_device *dev;
481
482	dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
483		if (os_memcmp(p2p->pending_pd_devaddr,
484			      dev->info.p2p_device_addr, ETH_ALEN))
485			continue;
486		if (!dev->req_config_methods)
487			continue;
488		if (dev->flags & P2P_DEV_PD_FOR_JOIN)
489			continue;
490		/* Reset the config methods of the device */
491		dev->req_config_methods = 0;
492	}
493
494	p2p->user_initiated_pd = 0;
495	os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
496	p2p->pd_retries = 0;
497}
498