xref: /freebsd/contrib/wpa/src/p2p/p2p_invitation.c (revision 5b9c547c072b84410b50897cc53710c75b2f6b74)
1f05cddf9SRui Paulo /*
2f05cddf9SRui Paulo  * Wi-Fi Direct - P2P Invitation procedure
3f05cddf9SRui Paulo  * Copyright (c) 2010, Atheros Communications
4f05cddf9SRui Paulo  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
7f05cddf9SRui Paulo  */
8f05cddf9SRui Paulo 
9f05cddf9SRui Paulo #include "includes.h"
10f05cddf9SRui Paulo 
11f05cddf9SRui Paulo #include "common.h"
12f05cddf9SRui Paulo #include "common/ieee802_11_defs.h"
13*5b9c547cSRui Paulo #include "common/wpa_ctrl.h"
14f05cddf9SRui Paulo #include "p2p_i.h"
15f05cddf9SRui Paulo #include "p2p.h"
16f05cddf9SRui Paulo 
17f05cddf9SRui Paulo 
18f05cddf9SRui Paulo static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
19f05cddf9SRui Paulo 						struct p2p_device *peer,
20*5b9c547cSRui Paulo 						const u8 *go_dev_addr,
21*5b9c547cSRui Paulo 						int dev_pw_id)
22f05cddf9SRui Paulo {
23f05cddf9SRui Paulo 	struct wpabuf *buf;
24f05cddf9SRui Paulo 	u8 *len;
25f05cddf9SRui Paulo 	const u8 *dev_addr;
26f05cddf9SRui Paulo 	size_t extra = 0;
27f05cddf9SRui Paulo 
28f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY
29f05cddf9SRui Paulo 	struct wpabuf *wfd_ie = p2p->wfd_ie_invitation;
30f05cddf9SRui Paulo 	if (wfd_ie && p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
31f05cddf9SRui Paulo 		size_t i;
32f05cddf9SRui Paulo 		for (i = 0; i < p2p->num_groups; i++) {
33f05cddf9SRui Paulo 			struct p2p_group *g = p2p->groups[i];
34f05cddf9SRui Paulo 			struct wpabuf *ie;
35f05cddf9SRui Paulo 			if (os_memcmp(p2p_group_get_interface_addr(g),
36f05cddf9SRui Paulo 				      p2p->inv_bssid, ETH_ALEN) != 0)
37f05cddf9SRui Paulo 				continue;
38f05cddf9SRui Paulo 			ie = p2p_group_get_wfd_ie(g);
39f05cddf9SRui Paulo 			if (ie) {
40f05cddf9SRui Paulo 				wfd_ie = ie;
41f05cddf9SRui Paulo 				break;
42f05cddf9SRui Paulo 			}
43f05cddf9SRui Paulo 		}
44f05cddf9SRui Paulo 	}
45f05cddf9SRui Paulo 	if (wfd_ie)
46f05cddf9SRui Paulo 		extra = wpabuf_len(wfd_ie);
47f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */
48f05cddf9SRui Paulo 
49*5b9c547cSRui Paulo 	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ])
50*5b9c547cSRui Paulo 		extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ]);
51*5b9c547cSRui Paulo 
52f05cddf9SRui Paulo 	buf = wpabuf_alloc(1000 + extra);
53f05cddf9SRui Paulo 	if (buf == NULL)
54f05cddf9SRui Paulo 		return NULL;
55f05cddf9SRui Paulo 
56f05cddf9SRui Paulo 	peer->dialog_token++;
57f05cddf9SRui Paulo 	if (peer->dialog_token == 0)
58f05cddf9SRui Paulo 		peer->dialog_token = 1;
59f05cddf9SRui Paulo 	p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_REQ,
60f05cddf9SRui Paulo 				      peer->dialog_token);
61f05cddf9SRui Paulo 
62f05cddf9SRui Paulo 	len = p2p_buf_add_ie_hdr(buf);
63f05cddf9SRui Paulo 	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO || !p2p->inv_persistent)
64f05cddf9SRui Paulo 		p2p_buf_add_config_timeout(buf, 0, 0);
65f05cddf9SRui Paulo 	else
66f05cddf9SRui Paulo 		p2p_buf_add_config_timeout(buf, p2p->go_timeout,
67f05cddf9SRui Paulo 					   p2p->client_timeout);
68f05cddf9SRui Paulo 	p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ?
69f05cddf9SRui Paulo 				     P2P_INVITATION_FLAGS_TYPE : 0);
70*5b9c547cSRui Paulo 	if (p2p->inv_role != P2P_INVITE_ROLE_CLIENT ||
71*5b9c547cSRui Paulo 	    !(peer->flags & P2P_DEV_NO_PREF_CHAN))
72f05cddf9SRui Paulo 		p2p_buf_add_operating_channel(buf, p2p->cfg->country,
73*5b9c547cSRui Paulo 					      p2p->op_reg_class,
74*5b9c547cSRui Paulo 					      p2p->op_channel);
75f05cddf9SRui Paulo 	if (p2p->inv_bssid_set)
76f05cddf9SRui Paulo 		p2p_buf_add_group_bssid(buf, p2p->inv_bssid);
77f05cddf9SRui Paulo 	p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
78f05cddf9SRui Paulo 	if (go_dev_addr)
79f05cddf9SRui Paulo 		dev_addr = go_dev_addr;
80f05cddf9SRui Paulo 	else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
81f05cddf9SRui Paulo 		dev_addr = peer->info.p2p_device_addr;
82f05cddf9SRui Paulo 	else
83f05cddf9SRui Paulo 		dev_addr = p2p->cfg->dev_addr;
84f05cddf9SRui Paulo 	p2p_buf_add_group_id(buf, dev_addr, p2p->inv_ssid, p2p->inv_ssid_len);
85f05cddf9SRui Paulo 	p2p_buf_add_device_info(buf, p2p, peer);
86f05cddf9SRui Paulo 	p2p_buf_update_ie_hdr(buf, len);
87f05cddf9SRui Paulo 
88f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY
89f05cddf9SRui Paulo 	if (wfd_ie)
90f05cddf9SRui Paulo 		wpabuf_put_buf(buf, wfd_ie);
91f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */
92f05cddf9SRui Paulo 
93*5b9c547cSRui Paulo 	if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ])
94*5b9c547cSRui Paulo 		wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_INV_REQ]);
95*5b9c547cSRui Paulo 
96*5b9c547cSRui Paulo 	if (dev_pw_id >= 0) {
97*5b9c547cSRui Paulo 		/* WSC IE in Invitation Request for NFC static handover */
98*5b9c547cSRui Paulo 		p2p_build_wps_ie(p2p, buf, dev_pw_id, 0);
99*5b9c547cSRui Paulo 	}
100*5b9c547cSRui Paulo 
101f05cddf9SRui Paulo 	return buf;
102f05cddf9SRui Paulo }
103f05cddf9SRui Paulo 
104f05cddf9SRui Paulo 
105f05cddf9SRui Paulo static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
106f05cddf9SRui Paulo 						 struct p2p_device *peer,
107f05cddf9SRui Paulo 						 u8 dialog_token, u8 status,
108f05cddf9SRui Paulo 						 const u8 *group_bssid,
109f05cddf9SRui Paulo 						 u8 reg_class, u8 channel,
110f05cddf9SRui Paulo 						 struct p2p_channels *channels)
111f05cddf9SRui Paulo {
112f05cddf9SRui Paulo 	struct wpabuf *buf;
113f05cddf9SRui Paulo 	u8 *len;
114f05cddf9SRui Paulo 	size_t extra = 0;
115f05cddf9SRui Paulo 
116f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY
117f05cddf9SRui Paulo 	struct wpabuf *wfd_ie = p2p->wfd_ie_invitation;
118f05cddf9SRui Paulo 	if (wfd_ie && group_bssid) {
119f05cddf9SRui Paulo 		size_t i;
120f05cddf9SRui Paulo 		for (i = 0; i < p2p->num_groups; i++) {
121f05cddf9SRui Paulo 			struct p2p_group *g = p2p->groups[i];
122f05cddf9SRui Paulo 			struct wpabuf *ie;
123f05cddf9SRui Paulo 			if (os_memcmp(p2p_group_get_interface_addr(g),
124f05cddf9SRui Paulo 				      group_bssid, ETH_ALEN) != 0)
125f05cddf9SRui Paulo 				continue;
126f05cddf9SRui Paulo 			ie = p2p_group_get_wfd_ie(g);
127f05cddf9SRui Paulo 			if (ie) {
128f05cddf9SRui Paulo 				wfd_ie = ie;
129f05cddf9SRui Paulo 				break;
130f05cddf9SRui Paulo 			}
131f05cddf9SRui Paulo 		}
132f05cddf9SRui Paulo 	}
133f05cddf9SRui Paulo 	if (wfd_ie)
134f05cddf9SRui Paulo 		extra = wpabuf_len(wfd_ie);
135f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */
136f05cddf9SRui Paulo 
137f05cddf9SRui Paulo 	buf = wpabuf_alloc(1000 + extra);
138f05cddf9SRui Paulo 	if (buf == NULL)
139f05cddf9SRui Paulo 		return NULL;
140f05cddf9SRui Paulo 
141f05cddf9SRui Paulo 	p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_RESP,
142f05cddf9SRui Paulo 				      dialog_token);
143f05cddf9SRui Paulo 
144f05cddf9SRui Paulo 	len = p2p_buf_add_ie_hdr(buf);
145f05cddf9SRui Paulo 	p2p_buf_add_status(buf, status);
146f05cddf9SRui Paulo 	p2p_buf_add_config_timeout(buf, 0, 0); /* FIX */
147f05cddf9SRui Paulo 	if (reg_class && channel)
148f05cddf9SRui Paulo 		p2p_buf_add_operating_channel(buf, p2p->cfg->country,
149f05cddf9SRui Paulo 					      reg_class, channel);
150f05cddf9SRui Paulo 	if (group_bssid)
151f05cddf9SRui Paulo 		p2p_buf_add_group_bssid(buf, group_bssid);
152f05cddf9SRui Paulo 	if (channels)
153f05cddf9SRui Paulo 		p2p_buf_add_channel_list(buf, p2p->cfg->country, channels);
154f05cddf9SRui Paulo 	p2p_buf_update_ie_hdr(buf, len);
155f05cddf9SRui Paulo 
156f05cddf9SRui Paulo #ifdef CONFIG_WIFI_DISPLAY
157f05cddf9SRui Paulo 	if (wfd_ie)
158f05cddf9SRui Paulo 		wpabuf_put_buf(buf, wfd_ie);
159f05cddf9SRui Paulo #endif /* CONFIG_WIFI_DISPLAY */
160f05cddf9SRui Paulo 
161f05cddf9SRui Paulo 	return buf;
162f05cddf9SRui Paulo }
163f05cddf9SRui Paulo 
164f05cddf9SRui Paulo 
165f05cddf9SRui Paulo void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
166f05cddf9SRui Paulo 				const u8 *data, size_t len, int rx_freq)
167f05cddf9SRui Paulo {
168f05cddf9SRui Paulo 	struct p2p_device *dev;
169f05cddf9SRui Paulo 	struct p2p_message msg;
170f05cddf9SRui Paulo 	struct wpabuf *resp = NULL;
171f05cddf9SRui Paulo 	u8 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
172f05cddf9SRui Paulo 	int freq;
173f05cddf9SRui Paulo 	int go = 0;
174f05cddf9SRui Paulo 	u8 group_bssid[ETH_ALEN], *bssid;
175f05cddf9SRui Paulo 	int op_freq = 0;
176f05cddf9SRui Paulo 	u8 reg_class = 0, channel = 0;
177*5b9c547cSRui Paulo 	struct p2p_channels all_channels, intersection, *channels = NULL;
178f05cddf9SRui Paulo 	int persistent;
179f05cddf9SRui Paulo 
180f05cddf9SRui Paulo 	os_memset(group_bssid, 0, sizeof(group_bssid));
181f05cddf9SRui Paulo 
182*5b9c547cSRui Paulo 	p2p_dbg(p2p, "Received Invitation Request from " MACSTR " (freq=%d)",
183f05cddf9SRui Paulo 		MAC2STR(sa), rx_freq);
184f05cddf9SRui Paulo 
185f05cddf9SRui Paulo 	if (p2p_parse(data, len, &msg))
186f05cddf9SRui Paulo 		return;
187f05cddf9SRui Paulo 
188f05cddf9SRui Paulo 	dev = p2p_get_device(p2p, sa);
189f05cddf9SRui Paulo 	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
190*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Invitation Request from unknown peer " MACSTR,
191*5b9c547cSRui Paulo 			MAC2STR(sa));
192f05cddf9SRui Paulo 
193*5b9c547cSRui Paulo 		if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
194f05cddf9SRui Paulo 				   0)) {
195*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Invitation Request add device failed "
196f05cddf9SRui Paulo 				MACSTR, MAC2STR(sa));
197f05cddf9SRui Paulo 			status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
198f05cddf9SRui Paulo 			goto fail;
199f05cddf9SRui Paulo 		}
200f05cddf9SRui Paulo 
201f05cddf9SRui Paulo 		dev = p2p_get_device(p2p, sa);
202f05cddf9SRui Paulo 		if (dev == NULL) {
203*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Reject Invitation Request from unknown peer "
204*5b9c547cSRui Paulo 				MACSTR, MAC2STR(sa));
205f05cddf9SRui Paulo 			status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
206f05cddf9SRui Paulo 			goto fail;
207f05cddf9SRui Paulo 		}
208f05cddf9SRui Paulo 	}
209f05cddf9SRui Paulo 
210f05cddf9SRui Paulo 	if (!msg.group_id || !msg.channel_list) {
211*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Mandatory attribute missing in Invitation Request from "
212*5b9c547cSRui Paulo 			MACSTR, MAC2STR(sa));
213f05cddf9SRui Paulo 		status = P2P_SC_FAIL_INVALID_PARAMS;
214f05cddf9SRui Paulo 		goto fail;
215f05cddf9SRui Paulo 	}
216f05cddf9SRui Paulo 
217f05cddf9SRui Paulo 	if (msg.invitation_flags)
218f05cddf9SRui Paulo 		persistent = *msg.invitation_flags & P2P_INVITATION_FLAGS_TYPE;
219f05cddf9SRui Paulo 	else {
220f05cddf9SRui Paulo 		/* Invitation Flags is a mandatory attribute starting from P2P
221f05cddf9SRui Paulo 		 * spec 1.06. As a backwards compatibility mechanism, assume
222f05cddf9SRui Paulo 		 * the request was for a persistent group if the attribute is
223f05cddf9SRui Paulo 		 * missing.
224f05cddf9SRui Paulo 		 */
225*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Mandatory Invitation Flags attribute missing from Invitation Request");
226f05cddf9SRui Paulo 		persistent = 1;
227f05cddf9SRui Paulo 	}
228f05cddf9SRui Paulo 
229*5b9c547cSRui Paulo 	p2p_channels_union(&p2p->cfg->channels, &p2p->cfg->cli_channels,
230*5b9c547cSRui Paulo 			   &all_channels);
231*5b9c547cSRui Paulo 
232*5b9c547cSRui Paulo 	if (p2p_peer_channels_check(p2p, &all_channels, dev,
233f05cddf9SRui Paulo 				    msg.channel_list, msg.channel_list_len) <
234f05cddf9SRui Paulo 	    0) {
235*5b9c547cSRui Paulo 		p2p_dbg(p2p, "No common channels found");
236f05cddf9SRui Paulo 		status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
237f05cddf9SRui Paulo 		goto fail;
238f05cddf9SRui Paulo 	}
239f05cddf9SRui Paulo 
240*5b9c547cSRui Paulo 	p2p_channels_dump(p2p, "own channels", &p2p->cfg->channels);
241*5b9c547cSRui Paulo 	p2p_channels_dump(p2p, "own client channels", &all_channels);
242*5b9c547cSRui Paulo 	p2p_channels_dump(p2p, "peer channels", &dev->channels);
243*5b9c547cSRui Paulo 	p2p_channels_intersect(&all_channels, &dev->channels,
244*5b9c547cSRui Paulo 			       &intersection);
245*5b9c547cSRui Paulo 	p2p_channels_dump(p2p, "intersection", &intersection);
246*5b9c547cSRui Paulo 
247f05cddf9SRui Paulo 	if (p2p->cfg->invitation_process) {
248f05cddf9SRui Paulo 		status = p2p->cfg->invitation_process(
249f05cddf9SRui Paulo 			p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id,
250f05cddf9SRui Paulo 			msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
251*5b9c547cSRui Paulo 			&go, group_bssid, &op_freq, persistent, &intersection,
252*5b9c547cSRui Paulo 			msg.dev_password_id_present ? msg.dev_password_id : -1);
253*5b9c547cSRui Paulo 	}
254*5b9c547cSRui Paulo 
255*5b9c547cSRui Paulo 	if (go) {
256*5b9c547cSRui Paulo 		p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
257*5b9c547cSRui Paulo 				       &intersection);
258*5b9c547cSRui Paulo 		p2p_channels_dump(p2p, "intersection(GO)", &intersection);
259*5b9c547cSRui Paulo 		if (intersection.reg_classes == 0) {
260*5b9c547cSRui Paulo 			p2p_dbg(p2p, "No common channels found (GO)");
261*5b9c547cSRui Paulo 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
262*5b9c547cSRui Paulo 			goto fail;
263*5b9c547cSRui Paulo 		}
264f05cddf9SRui Paulo 	}
265f05cddf9SRui Paulo 
266f05cddf9SRui Paulo 	if (op_freq) {
267*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Invitation processing forced frequency %d MHz",
268*5b9c547cSRui Paulo 			op_freq);
269*5b9c547cSRui Paulo 		if (p2p_freq_to_channel(op_freq, &reg_class, &channel) < 0) {
270*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Unknown forced freq %d MHz from invitation_process()",
271*5b9c547cSRui Paulo 				op_freq);
272f05cddf9SRui Paulo 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
273f05cddf9SRui Paulo 			goto fail;
274f05cddf9SRui Paulo 		}
275f05cddf9SRui Paulo 
276f05cddf9SRui Paulo 		if (!p2p_channels_includes(&intersection, reg_class, channel))
277f05cddf9SRui Paulo 		{
278*5b9c547cSRui Paulo 			p2p_dbg(p2p, "forced freq %d MHz not in the supported channels interaction",
279*5b9c547cSRui Paulo 				op_freq);
280f05cddf9SRui Paulo 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
281f05cddf9SRui Paulo 			goto fail;
282f05cddf9SRui Paulo 		}
283f05cddf9SRui Paulo 
284f05cddf9SRui Paulo 		if (status == P2P_SC_SUCCESS)
285f05cddf9SRui Paulo 			channels = &intersection;
286f05cddf9SRui Paulo 	} else {
287*5b9c547cSRui Paulo 		p2p_dbg(p2p, "No forced channel from invitation processing - figure out best one to use");
288f05cddf9SRui Paulo 
289f05cddf9SRui Paulo 		/* Default to own configuration as a starting point */
290f05cddf9SRui Paulo 		p2p->op_reg_class = p2p->cfg->op_reg_class;
291f05cddf9SRui Paulo 		p2p->op_channel = p2p->cfg->op_channel;
292*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Own default op_class %d channel %d",
293f05cddf9SRui Paulo 			p2p->op_reg_class, p2p->op_channel);
294f05cddf9SRui Paulo 
295f05cddf9SRui Paulo 		/* Use peer preference if specified and compatible */
296f05cddf9SRui Paulo 		if (msg.operating_channel) {
297f05cddf9SRui Paulo 			int req_freq;
298f05cddf9SRui Paulo 			req_freq = p2p_channel_to_freq(
299f05cddf9SRui Paulo 				msg.operating_channel[3],
300f05cddf9SRui Paulo 				msg.operating_channel[4]);
301*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Peer operating channel preference: %d MHz",
302f05cddf9SRui Paulo 				req_freq);
303f05cddf9SRui Paulo 			if (req_freq > 0 &&
304f05cddf9SRui Paulo 			    p2p_channels_includes(&intersection,
305f05cddf9SRui Paulo 						  msg.operating_channel[3],
306f05cddf9SRui Paulo 						  msg.operating_channel[4])) {
307f05cddf9SRui Paulo 				p2p->op_reg_class = msg.operating_channel[3];
308f05cddf9SRui Paulo 				p2p->op_channel = msg.operating_channel[4];
309*5b9c547cSRui Paulo 				p2p_dbg(p2p, "Use peer preference op_class %d channel %d",
310f05cddf9SRui Paulo 					p2p->op_reg_class, p2p->op_channel);
311f05cddf9SRui Paulo 			} else {
312*5b9c547cSRui Paulo 				p2p_dbg(p2p, "Cannot use peer channel preference");
313f05cddf9SRui Paulo 			}
314f05cddf9SRui Paulo 		}
315f05cddf9SRui Paulo 
316*5b9c547cSRui Paulo 		/* Reselect the channel only for the case of the GO */
317*5b9c547cSRui Paulo 		if (go &&
318*5b9c547cSRui Paulo 		    !p2p_channels_includes(&intersection, p2p->op_reg_class,
319f05cddf9SRui Paulo 					   p2p->op_channel)) {
320*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Initially selected channel (op_class %d channel %d) not in channel intersection - try to reselect",
321f05cddf9SRui Paulo 				p2p->op_reg_class, p2p->op_channel);
322f05cddf9SRui Paulo 			p2p_reselect_channel(p2p, &intersection);
323*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Re-selection result: op_class %d channel %d",
324f05cddf9SRui Paulo 				p2p->op_reg_class, p2p->op_channel);
325f05cddf9SRui Paulo 			if (!p2p_channels_includes(&intersection,
326f05cddf9SRui Paulo 						   p2p->op_reg_class,
327f05cddf9SRui Paulo 						   p2p->op_channel)) {
328*5b9c547cSRui Paulo 				p2p_dbg(p2p, "Peer does not support selected operating channel (reg_class=%u channel=%u)",
329f05cddf9SRui Paulo 					p2p->op_reg_class, p2p->op_channel);
330f05cddf9SRui Paulo 				status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
331f05cddf9SRui Paulo 				goto fail;
332f05cddf9SRui Paulo 			}
333*5b9c547cSRui Paulo 		} else if (go && !(dev->flags & P2P_DEV_FORCE_FREQ) &&
334*5b9c547cSRui Paulo 			   !p2p->cfg->cfg_op_channel) {
335*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Try to reselect channel selection with peer information received; previously selected op_class %u channel %u",
336*5b9c547cSRui Paulo 				p2p->op_reg_class, p2p->op_channel);
337*5b9c547cSRui Paulo 			p2p_reselect_channel(p2p, &intersection);
338f05cddf9SRui Paulo 		}
339f05cddf9SRui Paulo 
340*5b9c547cSRui Paulo 		op_freq = p2p_channel_to_freq(p2p->op_reg_class,
341f05cddf9SRui Paulo 					      p2p->op_channel);
342f05cddf9SRui Paulo 		if (op_freq < 0) {
343*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Unknown operational channel (country=%c%c reg_class=%u channel=%u)",
344f05cddf9SRui Paulo 				p2p->cfg->country[0], p2p->cfg->country[1],
345f05cddf9SRui Paulo 				p2p->op_reg_class, p2p->op_channel);
346f05cddf9SRui Paulo 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
347f05cddf9SRui Paulo 			goto fail;
348f05cddf9SRui Paulo 		}
349*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Selected operating channel - %d MHz", op_freq);
350f05cddf9SRui Paulo 
351f05cddf9SRui Paulo 		if (status == P2P_SC_SUCCESS) {
352f05cddf9SRui Paulo 			reg_class = p2p->op_reg_class;
353f05cddf9SRui Paulo 			channel = p2p->op_channel;
354f05cddf9SRui Paulo 			channels = &intersection;
355f05cddf9SRui Paulo 		}
356f05cddf9SRui Paulo 	}
357f05cddf9SRui Paulo 
358f05cddf9SRui Paulo fail:
359f05cddf9SRui Paulo 	if (go && status == P2P_SC_SUCCESS && !is_zero_ether_addr(group_bssid))
360f05cddf9SRui Paulo 		bssid = group_bssid;
361f05cddf9SRui Paulo 	else
362f05cddf9SRui Paulo 		bssid = NULL;
363f05cddf9SRui Paulo 	resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
364f05cddf9SRui Paulo 					 bssid, reg_class, channel, channels);
365f05cddf9SRui Paulo 
366f05cddf9SRui Paulo 	if (resp == NULL)
367f05cddf9SRui Paulo 		goto out;
368f05cddf9SRui Paulo 
369f05cddf9SRui Paulo 	if (rx_freq > 0)
370f05cddf9SRui Paulo 		freq = rx_freq;
371f05cddf9SRui Paulo 	else
372*5b9c547cSRui Paulo 		freq = p2p_channel_to_freq(p2p->cfg->reg_class,
373f05cddf9SRui Paulo 					   p2p->cfg->channel);
374f05cddf9SRui Paulo 	if (freq < 0) {
375*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Unknown regulatory class/channel");
376f05cddf9SRui Paulo 		goto out;
377f05cddf9SRui Paulo 	}
378f05cddf9SRui Paulo 
379f05cddf9SRui Paulo 	/*
380f05cddf9SRui Paulo 	 * Store copy of invitation data to be used when processing TX status
381f05cddf9SRui Paulo 	 * callback for the Acton frame.
382f05cddf9SRui Paulo 	 */
383f05cddf9SRui Paulo 	os_memcpy(p2p->inv_sa, sa, ETH_ALEN);
384f05cddf9SRui Paulo 	if (msg.group_bssid) {
385f05cddf9SRui Paulo 		os_memcpy(p2p->inv_group_bssid, msg.group_bssid, ETH_ALEN);
386f05cddf9SRui Paulo 		p2p->inv_group_bssid_ptr = p2p->inv_group_bssid;
387f05cddf9SRui Paulo 	} else
388f05cddf9SRui Paulo 		p2p->inv_group_bssid_ptr = NULL;
389*5b9c547cSRui Paulo 	if (msg.group_id) {
390f05cddf9SRui Paulo 		if (msg.group_id_len - ETH_ALEN <= 32) {
391f05cddf9SRui Paulo 			os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN,
392f05cddf9SRui Paulo 				  msg.group_id_len - ETH_ALEN);
393f05cddf9SRui Paulo 			p2p->inv_ssid_len = msg.group_id_len - ETH_ALEN;
394f05cddf9SRui Paulo 		}
395f05cddf9SRui Paulo 		os_memcpy(p2p->inv_go_dev_addr, msg.group_id, ETH_ALEN);
396*5b9c547cSRui Paulo 	} else {
397*5b9c547cSRui Paulo 		p2p->inv_ssid_len = 0;
398*5b9c547cSRui Paulo 		os_memset(p2p->inv_go_dev_addr, 0, ETH_ALEN);
399*5b9c547cSRui Paulo 	}
400f05cddf9SRui Paulo 	p2p->inv_status = status;
401f05cddf9SRui Paulo 	p2p->inv_op_freq = op_freq;
402f05cddf9SRui Paulo 
403f05cddf9SRui Paulo 	p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
404f05cddf9SRui Paulo 	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
405f05cddf9SRui Paulo 			    p2p->cfg->dev_addr,
406f05cddf9SRui Paulo 			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
407*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Failed to send Action frame");
408f05cddf9SRui Paulo 	}
409f05cddf9SRui Paulo 
410f05cddf9SRui Paulo out:
411f05cddf9SRui Paulo 	wpabuf_free(resp);
412f05cddf9SRui Paulo 	p2p_parse_free(&msg);
413f05cddf9SRui Paulo }
414f05cddf9SRui Paulo 
415f05cddf9SRui Paulo 
416f05cddf9SRui Paulo void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
417f05cddf9SRui Paulo 				 const u8 *data, size_t len)
418f05cddf9SRui Paulo {
419f05cddf9SRui Paulo 	struct p2p_device *dev;
420f05cddf9SRui Paulo 	struct p2p_message msg;
421*5b9c547cSRui Paulo 	struct p2p_channels intersection, *channels = NULL;
422f05cddf9SRui Paulo 
423*5b9c547cSRui Paulo 	p2p_dbg(p2p, "Received Invitation Response from " MACSTR,
424f05cddf9SRui Paulo 		MAC2STR(sa));
425f05cddf9SRui Paulo 
426f05cddf9SRui Paulo 	dev = p2p_get_device(p2p, sa);
427f05cddf9SRui Paulo 	if (dev == NULL) {
428*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Ignore Invitation Response from unknown peer "
429f05cddf9SRui Paulo 			MACSTR, MAC2STR(sa));
430*5b9c547cSRui Paulo 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
431f05cddf9SRui Paulo 		return;
432f05cddf9SRui Paulo 	}
433f05cddf9SRui Paulo 
434f05cddf9SRui Paulo 	if (dev != p2p->invite_peer) {
435*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Ignore unexpected Invitation Response from peer "
436f05cddf9SRui Paulo 			MACSTR, MAC2STR(sa));
437*5b9c547cSRui Paulo 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
438f05cddf9SRui Paulo 		return;
439f05cddf9SRui Paulo 	}
440f05cddf9SRui Paulo 
441*5b9c547cSRui Paulo 	if (p2p_parse(data, len, &msg)) {
442*5b9c547cSRui Paulo 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
443f05cddf9SRui Paulo 		return;
444*5b9c547cSRui Paulo 	}
445f05cddf9SRui Paulo 
446f05cddf9SRui Paulo 	if (!msg.status) {
447*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Mandatory Status attribute missing in Invitation Response from "
448*5b9c547cSRui Paulo 			MACSTR, MAC2STR(sa));
449*5b9c547cSRui Paulo 		p2p_parse_free(&msg);
450*5b9c547cSRui Paulo 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
451*5b9c547cSRui Paulo 		return;
452*5b9c547cSRui Paulo 	}
453*5b9c547cSRui Paulo 
454*5b9c547cSRui Paulo 	/*
455*5b9c547cSRui Paulo 	 * We should not really receive a replayed response twice since
456*5b9c547cSRui Paulo 	 * duplicate frames are supposed to be dropped. However, not all drivers
457*5b9c547cSRui Paulo 	 * do that for pre-association frames. We did not use to verify dialog
458*5b9c547cSRui Paulo 	 * token matches for invitation response frames, but that check can be
459*5b9c547cSRui Paulo 	 * safely used to drop a replayed response to the previous Invitation
460*5b9c547cSRui Paulo 	 * Request in case the suggested operating channel was changed. This
461*5b9c547cSRui Paulo 	 * allows a duplicated reject frame to be dropped with the assumption
462*5b9c547cSRui Paulo 	 * that the real response follows after it.
463*5b9c547cSRui Paulo 	 */
464*5b9c547cSRui Paulo 	if (*msg.status == P2P_SC_FAIL_NO_COMMON_CHANNELS &&
465*5b9c547cSRui Paulo 	    p2p->retry_invite_req_sent &&
466*5b9c547cSRui Paulo 	    msg.dialog_token != dev->dialog_token) {
467*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Unexpected Dialog Token %u (expected %u)",
468*5b9c547cSRui Paulo 			msg.dialog_token, dev->dialog_token);
469f05cddf9SRui Paulo 		p2p_parse_free(&msg);
470f05cddf9SRui Paulo 		return;
471f05cddf9SRui Paulo 	}
472f05cddf9SRui Paulo 
473*5b9c547cSRui Paulo 	if (*msg.status == P2P_SC_FAIL_NO_COMMON_CHANNELS &&
474*5b9c547cSRui Paulo 	    p2p->retry_invite_req &&
475*5b9c547cSRui Paulo 	    p2p_channel_random_social(&p2p->cfg->channels, &p2p->op_reg_class,
476*5b9c547cSRui Paulo 				      &p2p->op_channel) == 0) {
477*5b9c547cSRui Paulo 		p2p->retry_invite_req = 0;
478*5b9c547cSRui Paulo 		p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
479*5b9c547cSRui Paulo 		p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
480*5b9c547cSRui Paulo 		p2p_set_state(p2p, P2P_INVITE);
481*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Resend Invitation Request setting op_class %u channel %u as operating channel",
482*5b9c547cSRui Paulo 			p2p->op_reg_class, p2p->op_channel);
483*5b9c547cSRui Paulo 		p2p->retry_invite_req_sent = 1;
484*5b9c547cSRui Paulo 		p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr,
485*5b9c547cSRui Paulo 				p2p->invite_dev_pw_id);
486*5b9c547cSRui Paulo 		p2p_parse_free(&msg);
487*5b9c547cSRui Paulo 		return;
488*5b9c547cSRui Paulo 	}
489*5b9c547cSRui Paulo 	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
490*5b9c547cSRui Paulo 	p2p->retry_invite_req = 0;
491*5b9c547cSRui Paulo 
492*5b9c547cSRui Paulo 	if (!msg.channel_list && *msg.status == P2P_SC_SUCCESS) {
493*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Mandatory Channel List attribute missing in Invitation Response from "
494*5b9c547cSRui Paulo 			MACSTR, MAC2STR(sa));
495*5b9c547cSRui Paulo #ifdef CONFIG_P2P_STRICT
496*5b9c547cSRui Paulo 		p2p_parse_free(&msg);
497*5b9c547cSRui Paulo 		return;
498*5b9c547cSRui Paulo #endif /* CONFIG_P2P_STRICT */
499*5b9c547cSRui Paulo 		/* Try to survive without peer channel list */
500*5b9c547cSRui Paulo 		channels = &p2p->channels;
501*5b9c547cSRui Paulo 	} else if (!msg.channel_list) {
502*5b9c547cSRui Paulo 		/* Non-success cases are not required to include Channel List */
503*5b9c547cSRui Paulo 		channels = &p2p->channels;
504*5b9c547cSRui Paulo 	} else if (p2p_peer_channels_check(p2p, &p2p->channels, dev,
505*5b9c547cSRui Paulo 					   msg.channel_list,
506*5b9c547cSRui Paulo 					   msg.channel_list_len) < 0) {
507*5b9c547cSRui Paulo 		p2p_dbg(p2p, "No common channels found");
508*5b9c547cSRui Paulo 		p2p_parse_free(&msg);
509*5b9c547cSRui Paulo 		return;
510*5b9c547cSRui Paulo 	} else {
511*5b9c547cSRui Paulo 		p2p_channels_intersect(&p2p->channels, &dev->channels,
512*5b9c547cSRui Paulo 				       &intersection);
513*5b9c547cSRui Paulo 		channels = &intersection;
514*5b9c547cSRui Paulo 	}
515*5b9c547cSRui Paulo 
516*5b9c547cSRui Paulo 	if (p2p->cfg->invitation_result) {
517*5b9c547cSRui Paulo 		int peer_oper_freq = 0;
518*5b9c547cSRui Paulo 		int freq = p2p_channel_to_freq(p2p->op_reg_class,
519*5b9c547cSRui Paulo 					       p2p->op_channel);
520*5b9c547cSRui Paulo 		if (freq < 0)
521*5b9c547cSRui Paulo 			freq = 0;
522*5b9c547cSRui Paulo 
523*5b9c547cSRui Paulo 		if (msg.operating_channel) {
524*5b9c547cSRui Paulo 			peer_oper_freq = p2p_channel_to_freq(
525*5b9c547cSRui Paulo 				msg.operating_channel[3],
526*5b9c547cSRui Paulo 				msg.operating_channel[4]);
527*5b9c547cSRui Paulo 			if (peer_oper_freq < 0)
528*5b9c547cSRui Paulo 				peer_oper_freq = 0;
529*5b9c547cSRui Paulo 		}
530*5b9c547cSRui Paulo 
531f05cddf9SRui Paulo 		p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
532*5b9c547cSRui Paulo 					    msg.group_bssid, channels, sa,
533*5b9c547cSRui Paulo 					    freq, peer_oper_freq);
534*5b9c547cSRui Paulo 	}
535f05cddf9SRui Paulo 
536f05cddf9SRui Paulo 	p2p_parse_free(&msg);
537f05cddf9SRui Paulo 
538f05cddf9SRui Paulo 	p2p_clear_timeout(p2p);
539f05cddf9SRui Paulo 	p2p_set_state(p2p, P2P_IDLE);
540f05cddf9SRui Paulo 	p2p->invite_peer = NULL;
541f05cddf9SRui Paulo }
542f05cddf9SRui Paulo 
543f05cddf9SRui Paulo 
544f05cddf9SRui Paulo int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
545*5b9c547cSRui Paulo 		    const u8 *go_dev_addr, int dev_pw_id)
546f05cddf9SRui Paulo {
547f05cddf9SRui Paulo 	struct wpabuf *req;
548f05cddf9SRui Paulo 	int freq;
549f05cddf9SRui Paulo 
550f05cddf9SRui Paulo 	freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
551*5b9c547cSRui Paulo 	if (freq <= 0)
552*5b9c547cSRui Paulo 		freq = dev->oob_go_neg_freq;
553f05cddf9SRui Paulo 	if (freq <= 0) {
554*5b9c547cSRui Paulo 		p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
555*5b9c547cSRui Paulo 			MACSTR " to send Invitation Request",
556f05cddf9SRui Paulo 			MAC2STR(dev->info.p2p_device_addr));
557f05cddf9SRui Paulo 		return -1;
558f05cddf9SRui Paulo 	}
559f05cddf9SRui Paulo 
560*5b9c547cSRui Paulo 	req = p2p_build_invitation_req(p2p, dev, go_dev_addr, dev_pw_id);
561f05cddf9SRui Paulo 	if (req == NULL)
562f05cddf9SRui Paulo 		return -1;
563f05cddf9SRui Paulo 	if (p2p->state != P2P_IDLE)
564f05cddf9SRui Paulo 		p2p_stop_listen_for_freq(p2p, freq);
565*5b9c547cSRui Paulo 	p2p_dbg(p2p, "Sending Invitation Request");
566f05cddf9SRui Paulo 	p2p_set_state(p2p, P2P_INVITE);
567f05cddf9SRui Paulo 	p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
568f05cddf9SRui Paulo 	p2p->invite_peer = dev;
569f05cddf9SRui Paulo 	dev->invitation_reqs++;
570f05cddf9SRui Paulo 	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
571f05cddf9SRui Paulo 			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,
572*5b9c547cSRui Paulo 			    wpabuf_head(req), wpabuf_len(req), 500) < 0) {
573*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Failed to send Action frame");
574f05cddf9SRui Paulo 		/* Use P2P find to recover and retry */
575f05cddf9SRui Paulo 		p2p_set_timeout(p2p, 0, 0);
576*5b9c547cSRui Paulo 	} else {
577*5b9c547cSRui Paulo 		dev->flags |= P2P_DEV_WAIT_INV_REQ_ACK;
578f05cddf9SRui Paulo 	}
579f05cddf9SRui Paulo 
580f05cddf9SRui Paulo 	wpabuf_free(req);
581f05cddf9SRui Paulo 
582f05cddf9SRui Paulo 	return 0;
583f05cddf9SRui Paulo }
584f05cddf9SRui Paulo 
585f05cddf9SRui Paulo 
586f05cddf9SRui Paulo void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
587f05cddf9SRui Paulo {
588*5b9c547cSRui Paulo 	p2p_dbg(p2p, "Invitation Request TX callback: success=%d", success);
589f05cddf9SRui Paulo 
590f05cddf9SRui Paulo 	if (p2p->invite_peer == NULL) {
591*5b9c547cSRui Paulo 		p2p_dbg(p2p, "No pending Invite");
592f05cddf9SRui Paulo 		return;
593f05cddf9SRui Paulo 	}
594f05cddf9SRui Paulo 
595*5b9c547cSRui Paulo 	if (success)
596*5b9c547cSRui Paulo 		p2p->invite_peer->flags &= ~P2P_DEV_WAIT_INV_REQ_ACK;
597*5b9c547cSRui Paulo 
598f05cddf9SRui Paulo 	/*
599f05cddf9SRui Paulo 	 * Use P2P find, if needed, to find the other device from its listen
600f05cddf9SRui Paulo 	 * channel.
601f05cddf9SRui Paulo 	 */
602f05cddf9SRui Paulo 	p2p_set_state(p2p, P2P_INVITE);
603*5b9c547cSRui Paulo 	p2p_set_timeout(p2p, 0, success ? 500000 : 100000);
604f05cddf9SRui Paulo }
605f05cddf9SRui Paulo 
606f05cddf9SRui Paulo 
607f05cddf9SRui Paulo void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
608f05cddf9SRui Paulo {
609*5b9c547cSRui Paulo 	p2p_dbg(p2p, "Invitation Response TX callback: success=%d", success);
610f05cddf9SRui Paulo 	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
611f05cddf9SRui Paulo 
612*5b9c547cSRui Paulo 	if (!success)
613*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Assume Invitation Response was actually received by the peer even though Ack was not reported");
614*5b9c547cSRui Paulo 
615*5b9c547cSRui Paulo 	if (p2p->cfg->invitation_received) {
616f05cddf9SRui Paulo 		p2p->cfg->invitation_received(p2p->cfg->cb_ctx,
617f05cddf9SRui Paulo 					      p2p->inv_sa,
618f05cddf9SRui Paulo 					      p2p->inv_group_bssid_ptr,
619f05cddf9SRui Paulo 					      p2p->inv_ssid, p2p->inv_ssid_len,
620f05cddf9SRui Paulo 					      p2p->inv_go_dev_addr,
621f05cddf9SRui Paulo 					      p2p->inv_status,
622f05cddf9SRui Paulo 					      p2p->inv_op_freq);
623f05cddf9SRui Paulo 	}
624f05cddf9SRui Paulo }
625f05cddf9SRui Paulo 
626f05cddf9SRui Paulo 
627f05cddf9SRui Paulo int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
628f05cddf9SRui Paulo 	       const u8 *bssid, const u8 *ssid, size_t ssid_len,
629f05cddf9SRui Paulo 	       unsigned int force_freq, const u8 *go_dev_addr,
630*5b9c547cSRui Paulo 	       int persistent_group, unsigned int pref_freq, int dev_pw_id)
631f05cddf9SRui Paulo {
632f05cddf9SRui Paulo 	struct p2p_device *dev;
633f05cddf9SRui Paulo 
634*5b9c547cSRui Paulo 	p2p_dbg(p2p, "Request to invite peer " MACSTR " role=%d persistent=%d "
635f05cddf9SRui Paulo 		"force_freq=%u",
636f05cddf9SRui Paulo 		MAC2STR(peer), role, persistent_group, force_freq);
637f05cddf9SRui Paulo 	if (bssid)
638*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Invitation for BSSID " MACSTR, MAC2STR(bssid));
639f05cddf9SRui Paulo 	if (go_dev_addr) {
640*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Invitation for GO Device Address " MACSTR,
641f05cddf9SRui Paulo 			MAC2STR(go_dev_addr));
642f05cddf9SRui Paulo 		os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN);
643f05cddf9SRui Paulo 		p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf;
644f05cddf9SRui Paulo 	} else
645f05cddf9SRui Paulo 		p2p->invite_go_dev_addr = NULL;
646*5b9c547cSRui Paulo 	wpa_hexdump_ascii(MSG_DEBUG, "Invitation for SSID",
647f05cddf9SRui Paulo 			  ssid, ssid_len);
648*5b9c547cSRui Paulo 	if (dev_pw_id >= 0) {
649*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Invitation to use Device Password ID %d",
650*5b9c547cSRui Paulo 			dev_pw_id);
651*5b9c547cSRui Paulo 	}
652*5b9c547cSRui Paulo 	p2p->invite_dev_pw_id = dev_pw_id;
653*5b9c547cSRui Paulo 	p2p->retry_invite_req = role == P2P_INVITE_ROLE_GO &&
654*5b9c547cSRui Paulo 		persistent_group && !force_freq;
655*5b9c547cSRui Paulo 	p2p->retry_invite_req_sent = 0;
656f05cddf9SRui Paulo 
657f05cddf9SRui Paulo 	dev = p2p_get_device(p2p, peer);
658*5b9c547cSRui Paulo 	if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0 &&
659*5b9c547cSRui Paulo 			    dev->oob_go_neg_freq <= 0)) {
660*5b9c547cSRui Paulo 		p2p_dbg(p2p, "Cannot invite unknown P2P Device " MACSTR,
661f05cddf9SRui Paulo 			MAC2STR(peer));
662f05cddf9SRui Paulo 		return -1;
663f05cddf9SRui Paulo 	}
664f05cddf9SRui Paulo 
665*5b9c547cSRui Paulo 	if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq,
666*5b9c547cSRui Paulo 				role != P2P_INVITE_ROLE_CLIENT) < 0)
667*5b9c547cSRui Paulo 		return -1;
668*5b9c547cSRui Paulo 
669*5b9c547cSRui Paulo 	if (persistent_group && role == P2P_INVITE_ROLE_CLIENT && !force_freq &&
670*5b9c547cSRui Paulo 	    !pref_freq)
671*5b9c547cSRui Paulo 		dev->flags |= P2P_DEV_NO_PREF_CHAN;
672*5b9c547cSRui Paulo 	else
673*5b9c547cSRui Paulo 		dev->flags &= ~P2P_DEV_NO_PREF_CHAN;
674*5b9c547cSRui Paulo 
675f05cddf9SRui Paulo 	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
676f05cddf9SRui Paulo 		if (!(dev->info.dev_capab &
677f05cddf9SRui Paulo 		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
678*5b9c547cSRui Paulo 			p2p_dbg(p2p, "Cannot invite a P2P Device " MACSTR
679f05cddf9SRui Paulo 				" that is in a group and is not discoverable",
680f05cddf9SRui Paulo 				MAC2STR(peer));
681f05cddf9SRui Paulo 		}
682f05cddf9SRui Paulo 		/* TODO: use device discoverability request through GO */
683f05cddf9SRui Paulo 	}
684f05cddf9SRui Paulo 
685f05cddf9SRui Paulo 	dev->invitation_reqs = 0;
686f05cddf9SRui Paulo 
687f05cddf9SRui Paulo 	if (p2p->state != P2P_IDLE)
688f05cddf9SRui Paulo 		p2p_stop_find(p2p);
689f05cddf9SRui Paulo 
690f05cddf9SRui Paulo 	p2p->inv_role = role;
691f05cddf9SRui Paulo 	p2p->inv_bssid_set = bssid != NULL;
692f05cddf9SRui Paulo 	if (bssid)
693f05cddf9SRui Paulo 		os_memcpy(p2p->inv_bssid, bssid, ETH_ALEN);
694f05cddf9SRui Paulo 	os_memcpy(p2p->inv_ssid, ssid, ssid_len);
695f05cddf9SRui Paulo 	p2p->inv_ssid_len = ssid_len;
696f05cddf9SRui Paulo 	p2p->inv_persistent = persistent_group;
697*5b9c547cSRui Paulo 	return p2p_invite_send(p2p, dev, go_dev_addr, dev_pw_id);
698f05cddf9SRui Paulo }
699