xref: /netbsd-src/external/bsd/wpa/dist/src/p2p/p2p_invitation.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*
2  * Wi-Fi Direct - P2P Invitation procedure
3  * Copyright (c) 2010, Atheros Communications
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 #include "common/ieee802_11_defs.h"
19 #include "p2p_i.h"
20 #include "p2p.h"
21 
22 
23 static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
24 						struct p2p_device *peer,
25 						const u8 *go_dev_addr)
26 {
27 	struct wpabuf *buf;
28 	u8 *len;
29 	const u8 *dev_addr;
30 
31 	buf = wpabuf_alloc(1000);
32 	if (buf == NULL)
33 		return NULL;
34 
35 	peer->dialog_token++;
36 	if (peer->dialog_token == 0)
37 		peer->dialog_token = 1;
38 	p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_REQ,
39 				      peer->dialog_token);
40 
41 	len = p2p_buf_add_ie_hdr(buf);
42 	if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO || !p2p->inv_persistent)
43 		p2p_buf_add_config_timeout(buf, 0, 0);
44 	else
45 		p2p_buf_add_config_timeout(buf, 100, 20);
46 	p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ?
47 				     P2P_INVITATION_FLAGS_TYPE : 0);
48 	p2p_buf_add_operating_channel(buf, p2p->cfg->country,
49 				      p2p->op_reg_class, p2p->op_channel);
50 	if (p2p->inv_bssid_set)
51 		p2p_buf_add_group_bssid(buf, p2p->inv_bssid);
52 	p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
53 	if (go_dev_addr)
54 		dev_addr = go_dev_addr;
55 	else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
56 		dev_addr = peer->info.p2p_device_addr;
57 	else
58 		dev_addr = p2p->cfg->dev_addr;
59 	p2p_buf_add_group_id(buf, dev_addr, p2p->inv_ssid, p2p->inv_ssid_len);
60 	p2p_buf_add_device_info(buf, p2p, peer);
61 	p2p_buf_update_ie_hdr(buf, len);
62 
63 	return buf;
64 }
65 
66 
67 static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
68 						 struct p2p_device *peer,
69 						 u8 dialog_token, u8 status,
70 						 const u8 *group_bssid,
71 						 u8 reg_class, u8 channel,
72 						 struct p2p_channels *channels)
73 {
74 	struct wpabuf *buf;
75 	u8 *len;
76 
77 	buf = wpabuf_alloc(1000);
78 	if (buf == NULL)
79 		return NULL;
80 
81 	p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_RESP,
82 				      dialog_token);
83 
84 	len = p2p_buf_add_ie_hdr(buf);
85 	p2p_buf_add_status(buf, status);
86 	p2p_buf_add_config_timeout(buf, 0, 0); /* FIX */
87 	if (reg_class && channel)
88 		p2p_buf_add_operating_channel(buf, p2p->cfg->country,
89 					      reg_class, channel);
90 	if (group_bssid)
91 		p2p_buf_add_group_bssid(buf, group_bssid);
92 	if (channels)
93 		p2p_buf_add_channel_list(buf, p2p->cfg->country, channels);
94 	p2p_buf_update_ie_hdr(buf, len);
95 
96 	return buf;
97 }
98 
99 
100 void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
101 				const u8 *data, size_t len, int rx_freq)
102 {
103 	struct p2p_device *dev;
104 	struct p2p_message msg;
105 	struct wpabuf *resp = NULL;
106 	u8 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
107 	int freq;
108 	int go = 0;
109 	u8 group_bssid[ETH_ALEN], *bssid;
110 	int op_freq = 0;
111 	u8 reg_class = 0, channel = 0;
112 	struct p2p_channels intersection, *channels = NULL;
113 	int persistent;
114 
115 	os_memset(group_bssid, 0, sizeof(group_bssid));
116 
117 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
118 		"P2P: Received Invitation Request from " MACSTR " (freq=%d)",
119 		MAC2STR(sa), rx_freq);
120 
121 	if (p2p_parse(data, len, &msg))
122 		return;
123 
124 	dev = p2p_get_device(p2p, sa);
125 	if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
126 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
127 			"P2P: Invitation Request from unknown peer "
128 			MACSTR, MAC2STR(sa));
129 
130 		if (p2p_add_device(p2p, sa, rx_freq, 0, data + 1, len - 1, 0))
131 		{
132 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
133 				"P2P: Invitation Request add device failed "
134 				MACSTR, MAC2STR(sa));
135 			status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
136 			goto fail;
137 		}
138 
139 		dev = p2p_get_device(p2p, sa);
140 		if (dev == NULL) {
141 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
142 				"P2P: Reject Invitation Request from unknown "
143 				"peer " MACSTR, MAC2STR(sa));
144 			status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
145 			goto fail;
146 		}
147 	}
148 
149 	if (!msg.group_id || !msg.channel_list) {
150 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
151 			"P2P: Mandatory attribute missing in Invitation "
152 			"Request from " MACSTR, MAC2STR(sa));
153 		status = P2P_SC_FAIL_INVALID_PARAMS;
154 		goto fail;
155 	}
156 
157 	if (msg.invitation_flags)
158 		persistent = *msg.invitation_flags & P2P_INVITATION_FLAGS_TYPE;
159 	else {
160 		/* Invitation Flags is a mandatory attribute starting from P2P
161 		 * spec 1.06. As a backwards compatibility mechanism, assume
162 		 * the request was for a persistent group if the attribute is
163 		 * missing.
164 		 */
165 		wpa_printf(MSG_DEBUG, "P2P: Mandatory Invitation Flags "
166 			   "attribute missing from Invitation Request");
167 		persistent = 1;
168 	}
169 
170 	if (p2p_peer_channels_check(p2p, &p2p->cfg->channels, dev,
171 				    msg.channel_list, msg.channel_list_len) <
172 	    0) {
173 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
174 			"P2P: No common channels found");
175 		status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
176 		goto fail;
177 	}
178 
179 	if (p2p->cfg->invitation_process) {
180 		status = p2p->cfg->invitation_process(
181 			p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id,
182 			msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
183 			&go, group_bssid, &op_freq, persistent);
184 	}
185 
186 	if (op_freq) {
187 		if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
188 					&reg_class, &channel) < 0) {
189 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
190 				"P2P: Unknown forced freq %d MHz from "
191 				"invitation_process()", op_freq);
192 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
193 			goto fail;
194 		}
195 
196 		p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
197 				       &intersection);
198 		if (!p2p_channels_includes(&intersection, reg_class, channel))
199 		{
200 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
201 				"P2P: forced freq %d MHz not in the supported "
202 				"channels interaction", op_freq);
203 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
204 			goto fail;
205 		}
206 
207 		if (status == P2P_SC_SUCCESS)
208 			channels = &intersection;
209 	} else {
210 		op_freq = p2p_channel_to_freq(p2p->cfg->country,
211 					      p2p->cfg->op_reg_class,
212 					      p2p->cfg->op_channel);
213 		if (op_freq < 0) {
214 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
215 				"P2P: Unknown operational channel "
216 				"(country=%c%c reg_class=%u channel=%u)",
217 				p2p->cfg->country[0], p2p->cfg->country[1],
218 				p2p->cfg->op_reg_class, p2p->cfg->op_channel);
219 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
220 			goto fail;
221 		}
222 
223 		p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
224 				       &intersection);
225 		if (status == P2P_SC_SUCCESS) {
226 			reg_class = p2p->cfg->op_reg_class;
227 			channel = p2p->cfg->op_channel;
228 			channels = &intersection;
229 		}
230 	}
231 
232 fail:
233 	if (go && status == P2P_SC_SUCCESS && !is_zero_ether_addr(group_bssid))
234 		bssid = group_bssid;
235 	else
236 		bssid = NULL;
237 	resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
238 					 bssid, reg_class, channel, channels);
239 
240 	if (resp == NULL)
241 		goto out;
242 
243 	if (rx_freq > 0)
244 		freq = rx_freq;
245 	else
246 		freq = p2p_channel_to_freq(p2p->cfg->country,
247 					   p2p->cfg->reg_class,
248 					   p2p->cfg->channel);
249 	if (freq < 0) {
250 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
251 			"P2P: Unknown regulatory class/channel");
252 		goto out;
253 	}
254 
255 	/*
256 	 * Store copy of invitation data to be used when processing TX status
257 	 * callback for the Acton frame.
258 	 */
259 	os_memcpy(p2p->inv_sa, sa, ETH_ALEN);
260 	if (msg.group_bssid) {
261 		os_memcpy(p2p->inv_group_bssid, msg.group_bssid, ETH_ALEN);
262 		p2p->inv_group_bssid_ptr = p2p->inv_group_bssid;
263 	} else
264 		p2p->inv_group_bssid_ptr = NULL;
265 	if (msg.group_id_len - ETH_ALEN <= 32) {
266 		os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN,
267 			  msg.group_id_len - ETH_ALEN);
268 		p2p->inv_ssid_len = msg.group_id_len - ETH_ALEN;
269 	}
270 	os_memcpy(p2p->inv_go_dev_addr, msg.group_id, ETH_ALEN);
271 	p2p->inv_status = status;
272 	p2p->inv_op_freq = op_freq;
273 
274 	p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
275 	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
276 			    p2p->cfg->dev_addr,
277 			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
278 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
279 			"P2P: Failed to send Action frame");
280 	}
281 
282 out:
283 	wpabuf_free(resp);
284 	p2p_parse_free(&msg);
285 }
286 
287 
288 void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
289 				 const u8 *data, size_t len)
290 {
291 	struct p2p_device *dev;
292 	struct p2p_message msg;
293 
294 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
295 		"P2P: Received Invitation Response from " MACSTR,
296 		MAC2STR(sa));
297 
298 	dev = p2p_get_device(p2p, sa);
299 	if (dev == NULL) {
300 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
301 			"P2P: Ignore Invitation Response from unknown peer "
302 			MACSTR, MAC2STR(sa));
303 		return;
304 	}
305 
306 	if (dev != p2p->invite_peer) {
307 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
308 			"P2P: Ignore unexpected Invitation Response from peer "
309 			MACSTR, MAC2STR(sa));
310 		return;
311 	}
312 
313 	if (p2p_parse(data, len, &msg))
314 		return;
315 
316 	if (!msg.status) {
317 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
318 			"P2P: Mandatory Status attribute missing in "
319 			"Invitation Response from " MACSTR, MAC2STR(sa));
320 		p2p_parse_free(&msg);
321 		return;
322 	}
323 
324 	if (p2p->cfg->invitation_result)
325 		p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
326 					    msg.group_bssid);
327 
328 	p2p_parse_free(&msg);
329 
330 	p2p_clear_timeout(p2p);
331 	p2p_set_state(p2p, P2P_IDLE);
332 	p2p->invite_peer = NULL;
333 }
334 
335 
336 int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
337 		    const u8 *go_dev_addr)
338 {
339 	struct wpabuf *req;
340 	int freq;
341 
342 	freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
343 	if (freq <= 0) {
344 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
345 			"P2P: No Listen/Operating frequency known for the "
346 			"peer " MACSTR " to send Invitation Request",
347 			MAC2STR(dev->info.p2p_device_addr));
348 		return -1;
349 	}
350 
351 	req = p2p_build_invitation_req(p2p, dev, go_dev_addr);
352 	if (req == NULL)
353 		return -1;
354 	if (p2p->state != P2P_IDLE)
355 		p2p_stop_listen_for_freq(p2p, freq);
356 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
357 		"P2P: Sending Invitation Request");
358 	p2p_set_state(p2p, P2P_INVITE);
359 	p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
360 	p2p->invite_peer = dev;
361 	dev->invitation_reqs++;
362 	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
363 			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,
364 			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
365 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
366 			"P2P: Failed to send Action frame");
367 		/* Use P2P find to recover and retry */
368 		p2p_set_timeout(p2p, 0, 0);
369 	}
370 
371 	wpabuf_free(req);
372 
373 	return 0;
374 }
375 
376 
377 void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
378 {
379 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
380 		"P2P: Invitation Request TX callback: success=%d", success);
381 
382 	if (p2p->invite_peer == NULL) {
383 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
384 			"P2P: No pending Invite");
385 		return;
386 	}
387 
388 	/*
389 	 * Use P2P find, if needed, to find the other device from its listen
390 	 * channel.
391 	 */
392 	p2p_set_state(p2p, P2P_INVITE);
393 	p2p_set_timeout(p2p, 0, 100000);
394 }
395 
396 
397 void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
398 {
399 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
400 		"P2P: Invitation Response TX callback: success=%d", success);
401 	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
402 
403 	if (success && p2p->cfg->invitation_received) {
404 		p2p->cfg->invitation_received(p2p->cfg->cb_ctx,
405 					      p2p->inv_sa,
406 					      p2p->inv_group_bssid_ptr,
407 					      p2p->inv_ssid, p2p->inv_ssid_len,
408 					      p2p->inv_go_dev_addr,
409 					      p2p->inv_status,
410 					      p2p->inv_op_freq);
411 	}
412 }
413 
414 
415 int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
416 	       const u8 *bssid, const u8 *ssid, size_t ssid_len,
417 	       unsigned int force_freq, const u8 *go_dev_addr,
418 	       int persistent_group)
419 {
420 	struct p2p_device *dev;
421 
422 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
423 		"P2P: Request to invite peer " MACSTR " role=%d persistent=%d "
424 		"force_freq=%u",
425 		MAC2STR(peer), role, persistent_group, force_freq);
426 	if (bssid)
427 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
428 			"P2P: Invitation for BSSID " MACSTR, MAC2STR(bssid));
429 	if (go_dev_addr) {
430 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
431 			"P2P: Invitation for GO Device Address " MACSTR,
432 			MAC2STR(go_dev_addr));
433 		os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN);
434 		p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf;
435 	} else
436 		p2p->invite_go_dev_addr = NULL;
437 	wpa_hexdump_ascii(MSG_DEBUG, "P2P: Invitation for SSID",
438 			  ssid, ssid_len);
439 
440 	dev = p2p_get_device(p2p, peer);
441 	if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) {
442 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
443 			"P2P: Cannot invite unknown P2P Device " MACSTR,
444 			MAC2STR(peer));
445 		return -1;
446 	}
447 
448 	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
449 		if (!(dev->info.dev_capab &
450 		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
451 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
452 				"P2P: Cannot invite a P2P Device " MACSTR
453 				" that is in a group and is not discoverable",
454 				MAC2STR(peer));
455 		}
456 		/* TODO: use device discoverability request through GO */
457 	}
458 
459 	dev->invitation_reqs = 0;
460 
461 	if (force_freq) {
462 		if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
463 					&p2p->op_reg_class, &p2p->op_channel) <
464 		    0) {
465 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
466 				"P2P: Unsupported frequency %u MHz",
467 				force_freq);
468 			return -1;
469 		}
470 		p2p->channels.reg_classes = 1;
471 		p2p->channels.reg_class[0].channels = 1;
472 		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
473 		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
474 	} else {
475 		p2p->op_reg_class = p2p->cfg->op_reg_class;
476 		p2p->op_channel = p2p->cfg->op_channel;
477 		os_memcpy(&p2p->channels, &p2p->cfg->channels,
478 			  sizeof(struct p2p_channels));
479 	}
480 
481 	if (p2p->state != P2P_IDLE)
482 		p2p_stop_find(p2p);
483 
484 	p2p->inv_role = role;
485 	p2p->inv_bssid_set = bssid != NULL;
486 	if (bssid)
487 		os_memcpy(p2p->inv_bssid, bssid, ETH_ALEN);
488 	os_memcpy(p2p->inv_ssid, ssid, ssid_len);
489 	p2p->inv_ssid_len = ssid_len;
490 	p2p->inv_persistent = persistent_group;
491 	return p2p_invite_send(p2p, dev, go_dev_addr);
492 }
493