p2p_invitation.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
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
23static 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
67static 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
100void 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)) {
131			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
132				"P2P: Invitation Request add device failed "
133				MACSTR, MAC2STR(sa));
134			status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
135			goto fail;
136		}
137
138		dev = p2p_get_device(p2p, sa);
139		if (dev == NULL) {
140			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
141				"P2P: Reject Invitation Request from unknown "
142				"peer " MACSTR, MAC2STR(sa));
143			status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
144			goto fail;
145		}
146	}
147
148	if (!msg.group_id || !msg.channel_list) {
149		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
150			"P2P: Mandatory attribute missing in Invitation "
151			"Request from " MACSTR, MAC2STR(sa));
152		status = P2P_SC_FAIL_INVALID_PARAMS;
153		goto fail;
154	}
155
156	if (msg.invitation_flags)
157		persistent = *msg.invitation_flags & P2P_INVITATION_FLAGS_TYPE;
158	else {
159		/* Invitation Flags is a mandatory attribute starting from P2P
160		 * spec 1.06. As a backwards compatibility mechanism, assume
161		 * the request was for a persistent group if the attribute is
162		 * missing.
163		 */
164		wpa_printf(MSG_DEBUG, "P2P: Mandatory Invitation Flags "
165			   "attribute missing from Invitation Request");
166		persistent = 1;
167	}
168
169	if (p2p_peer_channels_check(p2p, &p2p->cfg->channels, dev,
170				    msg.channel_list, msg.channel_list_len) <
171	    0) {
172		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
173			"P2P: No common channels found");
174		status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
175		goto fail;
176	}
177
178	if (p2p->cfg->invitation_process) {
179		status = p2p->cfg->invitation_process(
180			p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id,
181			msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
182			&go, group_bssid, &op_freq, persistent);
183	}
184
185	if (op_freq) {
186		if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
187					&reg_class, &channel) < 0) {
188			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
189				"P2P: Unknown forced freq %d MHz from "
190				"invitation_process()", op_freq);
191			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
192			goto fail;
193		}
194
195		p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
196				       &intersection);
197		if (!p2p_channels_includes(&intersection, reg_class, channel))
198		{
199			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
200				"P2P: forced freq %d MHz not in the supported "
201				"channels interaction", op_freq);
202			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
203			goto fail;
204		}
205
206		if (status == P2P_SC_SUCCESS)
207			channels = &intersection;
208	} else {
209		op_freq = p2p_channel_to_freq(p2p->cfg->country,
210					      p2p->cfg->op_reg_class,
211					      p2p->cfg->op_channel);
212		if (op_freq < 0) {
213			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
214				"P2P: Unknown operational channel "
215				"(country=%c%c reg_class=%u channel=%u)",
216				p2p->cfg->country[0], p2p->cfg->country[1],
217				p2p->cfg->op_reg_class, p2p->cfg->op_channel);
218			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
219			goto fail;
220		}
221
222		p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
223				       &intersection);
224		if (status == P2P_SC_SUCCESS) {
225			reg_class = p2p->cfg->op_reg_class;
226			channel = p2p->cfg->op_channel;
227			channels = &intersection;
228		}
229	}
230
231fail:
232	if (go && status == P2P_SC_SUCCESS && !is_zero_ether_addr(group_bssid))
233		bssid = group_bssid;
234	else
235		bssid = NULL;
236	resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
237					 bssid, reg_class, channel, channels);
238
239	if (resp == NULL)
240		goto out;
241
242	if (rx_freq > 0)
243		freq = rx_freq;
244	else
245		freq = p2p_channel_to_freq(p2p->cfg->country,
246					   p2p->cfg->reg_class,
247					   p2p->cfg->channel);
248	if (freq < 0) {
249		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
250			"P2P: Unknown regulatory class/channel");
251		goto out;
252	}
253
254	/*
255	 * Store copy of invitation data to be used when processing TX status
256	 * callback for the Acton frame.
257	 */
258	os_memcpy(p2p->inv_sa, sa, ETH_ALEN);
259	if (msg.group_bssid) {
260		os_memcpy(p2p->inv_group_bssid, msg.group_bssid, ETH_ALEN);
261		p2p->inv_group_bssid_ptr = p2p->inv_group_bssid;
262	} else
263		p2p->inv_group_bssid_ptr = NULL;
264	if (msg.group_id_len - ETH_ALEN <= 32) {
265		os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN,
266			  msg.group_id_len - ETH_ALEN);
267		p2p->inv_ssid_len = msg.group_id_len - ETH_ALEN;
268	}
269	os_memcpy(p2p->inv_go_dev_addr, msg.group_id, ETH_ALEN);
270	p2p->inv_status = status;
271	p2p->inv_op_freq = op_freq;
272
273	p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
274	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
275			    p2p->cfg->dev_addr,
276			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
277		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
278			"P2P: Failed to send Action frame");
279	}
280
281out:
282	wpabuf_free(resp);
283	p2p_parse_free(&msg);
284}
285
286
287void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
288				 const u8 *data, size_t len)
289{
290	struct p2p_device *dev;
291	struct p2p_message msg;
292
293	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
294		"P2P: Received Invitation Response from " MACSTR,
295		MAC2STR(sa));
296
297	dev = p2p_get_device(p2p, sa);
298	if (dev == NULL) {
299		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
300			"P2P: Ignore Invitation Response from unknown peer "
301			MACSTR, MAC2STR(sa));
302		return;
303	}
304
305	if (dev != p2p->invite_peer) {
306		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
307			"P2P: Ignore unexpected Invitation Response from peer "
308			MACSTR, MAC2STR(sa));
309		return;
310	}
311
312	if (p2p_parse(data, len, &msg))
313		return;
314
315	if (!msg.status) {
316		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
317			"P2P: Mandatory Status attribute missing in "
318			"Invitation Response from " MACSTR, MAC2STR(sa));
319		p2p_parse_free(&msg);
320		return;
321	}
322
323	if (p2p->cfg->invitation_result)
324		p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
325					    msg.group_bssid);
326
327	p2p_parse_free(&msg);
328
329	p2p_clear_timeout(p2p);
330	p2p_set_state(p2p, P2P_IDLE);
331	p2p->invite_peer = NULL;
332}
333
334
335int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
336		    const u8 *go_dev_addr)
337{
338	struct wpabuf *req;
339	int freq;
340
341	freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
342	if (freq <= 0) {
343		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
344			"P2P: No Listen/Operating frequency known for the "
345			"peer " MACSTR " to send Invitation Request",
346			MAC2STR(dev->info.p2p_device_addr));
347		return -1;
348	}
349
350	req = p2p_build_invitation_req(p2p, dev, go_dev_addr);
351	if (req == NULL)
352		return -1;
353	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
354		"P2P: Sending Invitation Request");
355	p2p_set_state(p2p, P2P_INVITE);
356	p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
357	p2p->invite_peer = dev;
358	dev->invitation_reqs++;
359	if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
360			    p2p->cfg->dev_addr, dev->info.p2p_device_addr,
361			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
362		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
363			"P2P: Failed to send Action frame");
364		/* Use P2P find to recover and retry */
365		p2p_set_timeout(p2p, 0, 0);
366	}
367
368	wpabuf_free(req);
369
370	return 0;
371}
372
373
374void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
375{
376	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
377		"P2P: Invitation Request TX callback: success=%d", success);
378
379	if (p2p->invite_peer == NULL) {
380		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
381			"P2P: No pending Invite");
382		return;
383	}
384
385	/*
386	 * Use P2P find, if needed, to find the other device from its listen
387	 * channel.
388	 */
389	p2p_set_state(p2p, P2P_INVITE);
390	p2p_set_timeout(p2p, 0, 100000);
391}
392
393
394void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
395{
396	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
397		"P2P: Invitation Response TX callback: success=%d", success);
398	p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
399
400	if (success && p2p->cfg->invitation_received) {
401		p2p->cfg->invitation_received(p2p->cfg->cb_ctx,
402					      p2p->inv_sa,
403					      p2p->inv_group_bssid_ptr,
404					      p2p->inv_ssid, p2p->inv_ssid_len,
405					      p2p->inv_go_dev_addr,
406					      p2p->inv_status,
407					      p2p->inv_op_freq);
408	}
409}
410
411
412int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
413	       const u8 *bssid, const u8 *ssid, size_t ssid_len,
414	       unsigned int force_freq, const u8 *go_dev_addr,
415	       int persistent_group)
416{
417	struct p2p_device *dev;
418
419	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
420		"P2P: Request to invite peer " MACSTR " role=%d persistent=%d "
421		"force_freq=%u",
422		MAC2STR(peer), role, persistent_group, force_freq);
423	if (bssid)
424		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
425			"P2P: Invitation for BSSID " MACSTR, MAC2STR(bssid));
426	if (go_dev_addr) {
427		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
428			"P2P: Invitation for GO Device Address " MACSTR,
429			MAC2STR(go_dev_addr));
430		os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN);
431		p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf;
432	} else
433		p2p->invite_go_dev_addr = NULL;
434	wpa_hexdump_ascii(MSG_DEBUG, "P2P: Invitation for SSID",
435			  ssid, ssid_len);
436
437	dev = p2p_get_device(p2p, peer);
438	if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) {
439		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
440			"P2P: Cannot invite unknown P2P Device " MACSTR,
441			MAC2STR(peer));
442		return -1;
443	}
444
445	if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
446		if (!(dev->info.dev_capab &
447		      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
448			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
449				"P2P: Cannot invite a P2P Device " MACSTR
450				" that is in a group and is not discoverable",
451				MAC2STR(peer));
452		}
453		/* TODO: use device discoverability request through GO */
454	}
455
456	dev->invitation_reqs = 0;
457
458	if (force_freq) {
459		if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
460					&p2p->op_reg_class, &p2p->op_channel) <
461		    0) {
462			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
463				"P2P: Unsupported frequency %u MHz",
464				force_freq);
465			return -1;
466		}
467		p2p->channels.reg_classes = 1;
468		p2p->channels.reg_class[0].channels = 1;
469		p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
470		p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
471	} else {
472		p2p->op_reg_class = p2p->cfg->op_reg_class;
473		p2p->op_channel = p2p->cfg->op_channel;
474		os_memcpy(&p2p->channels, &p2p->cfg->channels,
475			  sizeof(struct p2p_channels));
476	}
477
478	if (p2p->state != P2P_IDLE)
479		p2p_stop_find(p2p);
480
481	p2p->inv_role = role;
482	p2p->inv_bssid_set = bssid != NULL;
483	if (bssid)
484		os_memcpy(p2p->inv_bssid, bssid, ETH_ALEN);
485	os_memcpy(p2p->inv_ssid, ssid, ssid_len);
486	p2p->inv_ssid_len = ssid_len;
487	p2p->inv_persistent = persistent_group;
488	return p2p_invite_send(p2p, dev, go_dev_addr);
489}
490