blob: 7d6dd1110c06f43cc62b1d3f74828e5c56dc4a0c [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Wi-Fi Direct - P2P Invitation procedure
3 * Copyright (c) 2010, Atheros Communications
4 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "common/ieee802_11_defs.h"
13#include "p2p_i.h"
14#include "p2p.h"
15
16
17static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
18 struct p2p_device *peer,
19 const u8 *go_dev_addr)
20{
21 struct wpabuf *buf;
22 u8 *len;
23 const u8 *dev_addr;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070024 size_t extra = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070026#ifdef CONFIG_WIFI_DISPLAY
27 struct wpabuf *wfd_ie = p2p->wfd_ie_invitation;
28 if (wfd_ie && p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) {
29 size_t i;
30 for (i = 0; i < p2p->num_groups; i++) {
31 struct p2p_group *g = p2p->groups[i];
32 struct wpabuf *ie;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -070033 if (os_memcmp(p2p_group_get_interface_addr(g),
34 p2p->inv_bssid, ETH_ALEN) != 0)
35 continue;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070036 ie = p2p_group_get_wfd_ie(g);
37 if (ie) {
38 wfd_ie = ie;
39 break;
40 }
41 }
42 }
43 if (wfd_ie)
44 extra = wpabuf_len(wfd_ie);
45#endif /* CONFIG_WIFI_DISPLAY */
46
47 buf = wpabuf_alloc(1000 + extra);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048 if (buf == NULL)
49 return NULL;
50
51 peer->dialog_token++;
52 if (peer->dialog_token == 0)
53 peer->dialog_token = 1;
54 p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_REQ,
55 peer->dialog_token);
56
57 len = p2p_buf_add_ie_hdr(buf);
58 if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO || !p2p->inv_persistent)
59 p2p_buf_add_config_timeout(buf, 0, 0);
60 else
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070061 p2p_buf_add_config_timeout(buf, p2p->go_timeout,
62 p2p->client_timeout);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070063 p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ?
64 P2P_INVITATION_FLAGS_TYPE : 0);
65 p2p_buf_add_operating_channel(buf, p2p->cfg->country,
66 p2p->op_reg_class, p2p->op_channel);
67 if (p2p->inv_bssid_set)
68 p2p_buf_add_group_bssid(buf, p2p->inv_bssid);
Irfan Sherifff0619662012-09-23 19:11:37 -070069#ifdef ANDROID_P2P
Irfan Sheriffaf84a572012-09-22 16:59:30 -070070 if (p2p->cfg->p2p_concurrency == P2P_SINGLE_CHANNEL_CONCURRENT && p2p->op_channel) {
71 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "Forcing channel list %d", p2p->op_channel);
72 p2p_buf_add_oper_as_channel_list(buf, p2p->cfg->country, p2p->op_reg_class,
73 p2p->op_channel);
74 } else {
Irfan Sherifff0619662012-09-23 19:11:37 -070075#endif
Irfan Sheriffaf84a572012-09-22 16:59:30 -070076 p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
Irfan Sherifff0619662012-09-23 19:11:37 -070077#ifdef ANDROID_P2P
Irfan Sheriffaf84a572012-09-22 16:59:30 -070078 }
Irfan Sherifff0619662012-09-23 19:11:37 -070079#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070080 if (go_dev_addr)
81 dev_addr = go_dev_addr;
82 else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
83 dev_addr = peer->info.p2p_device_addr;
84 else
85 dev_addr = p2p->cfg->dev_addr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070086 p2p_buf_add_group_id(buf, dev_addr, p2p->inv_ssid, p2p->inv_ssid_len);
87 p2p_buf_add_device_info(buf, p2p, peer);
88 p2p_buf_update_ie_hdr(buf, len);
89
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070090#ifdef CONFIG_WIFI_DISPLAY
91 if (wfd_ie)
92 wpabuf_put_buf(buf, wfd_ie);
93#endif /* CONFIG_WIFI_DISPLAY */
94
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070095 return buf;
96}
97
98
99static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
100 struct p2p_device *peer,
101 u8 dialog_token, u8 status,
102 const u8 *group_bssid,
103 u8 reg_class, u8 channel,
104 struct p2p_channels *channels)
105{
106 struct wpabuf *buf;
107 u8 *len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700108 size_t extra = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700109
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700110#ifdef CONFIG_WIFI_DISPLAY
111 struct wpabuf *wfd_ie = p2p->wfd_ie_invitation;
112 if (wfd_ie && group_bssid) {
113 size_t i;
114 for (i = 0; i < p2p->num_groups; i++) {
115 struct p2p_group *g = p2p->groups[i];
116 struct wpabuf *ie;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -0700117 if (os_memcmp(p2p_group_get_interface_addr(g),
118 group_bssid, ETH_ALEN) != 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700119 continue;
120 ie = p2p_group_get_wfd_ie(g);
121 if (ie) {
122 wfd_ie = ie;
123 break;
124 }
125 }
126 }
127 if (wfd_ie)
128 extra = wpabuf_len(wfd_ie);
129#endif /* CONFIG_WIFI_DISPLAY */
130
131 buf = wpabuf_alloc(1000 + extra);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700132 if (buf == NULL)
133 return NULL;
134
135 p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_RESP,
136 dialog_token);
137
138 len = p2p_buf_add_ie_hdr(buf);
139 p2p_buf_add_status(buf, status);
140 p2p_buf_add_config_timeout(buf, 0, 0); /* FIX */
141 if (reg_class && channel)
142 p2p_buf_add_operating_channel(buf, p2p->cfg->country,
143 reg_class, channel);
144 if (group_bssid)
145 p2p_buf_add_group_bssid(buf, group_bssid);
Irfan Sherifff0619662012-09-23 19:11:37 -0700146#ifdef ANDROID_P2P
Irfan Sheriffaf84a572012-09-22 16:59:30 -0700147 if (p2p->cfg->p2p_concurrency == P2P_SINGLE_CHANNEL_CONCURRENT && channel) {
148 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "Forcing channel list %d", channel);
149 p2p_buf_add_oper_as_channel_list(buf, p2p->cfg->country,
150 reg_class, channel);
151 } else {
Irfan Sherifff0619662012-09-23 19:11:37 -0700152#endif
Irfan Sheriffaf84a572012-09-22 16:59:30 -0700153 if (channels)
154 p2p_buf_add_channel_list(buf, p2p->cfg->country, channels);
Irfan Sherifff0619662012-09-23 19:11:37 -0700155#ifdef ANDROID_P2P
Irfan Sheriffaf84a572012-09-22 16:59:30 -0700156 }
Irfan Sherifff0619662012-09-23 19:11:37 -0700157#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700158 p2p_buf_update_ie_hdr(buf, len);
159
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700160#ifdef CONFIG_WIFI_DISPLAY
161 if (wfd_ie)
162 wpabuf_put_buf(buf, wfd_ie);
163#endif /* CONFIG_WIFI_DISPLAY */
164
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700165 return buf;
166}
167
168
169void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
170 const u8 *data, size_t len, int rx_freq)
171{
172 struct p2p_device *dev;
173 struct p2p_message msg;
174 struct wpabuf *resp = NULL;
175 u8 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
176 int freq;
177 int go = 0;
178 u8 group_bssid[ETH_ALEN], *bssid;
179 int op_freq = 0;
180 u8 reg_class = 0, channel = 0;
181 struct p2p_channels intersection, *channels = NULL;
182 int persistent;
183
184 os_memset(group_bssid, 0, sizeof(group_bssid));
185
186 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
187 "P2P: Received Invitation Request from " MACSTR " (freq=%d)",
188 MAC2STR(sa), rx_freq);
189
190 if (p2p_parse(data, len, &msg))
191 return;
192
193 dev = p2p_get_device(p2p, sa);
194 if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
195 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
196 "P2P: Invitation Request from unknown peer "
197 MACSTR, MAC2STR(sa));
198
Dmitry Shmidt04949592012-07-19 12:16:46 -0700199 if (p2p_add_device(p2p, sa, rx_freq, 0, data + 1, len - 1, 0))
200 {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700201 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
202 "P2P: Invitation Request add device failed "
203 MACSTR, MAC2STR(sa));
204 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
205 goto fail;
206 }
207
208 dev = p2p_get_device(p2p, sa);
209 if (dev == NULL) {
210 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
211 "P2P: Reject Invitation Request from unknown "
212 "peer " MACSTR, MAC2STR(sa));
213 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
214 goto fail;
215 }
216 }
217
218 if (!msg.group_id || !msg.channel_list) {
219 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
220 "P2P: Mandatory attribute missing in Invitation "
221 "Request from " MACSTR, MAC2STR(sa));
222 status = P2P_SC_FAIL_INVALID_PARAMS;
223 goto fail;
224 }
225
226 if (msg.invitation_flags)
227 persistent = *msg.invitation_flags & P2P_INVITATION_FLAGS_TYPE;
228 else {
229 /* Invitation Flags is a mandatory attribute starting from P2P
230 * spec 1.06. As a backwards compatibility mechanism, assume
231 * the request was for a persistent group if the attribute is
232 * missing.
233 */
234 wpa_printf(MSG_DEBUG, "P2P: Mandatory Invitation Flags "
235 "attribute missing from Invitation Request");
236 persistent = 1;
237 }
238
239 if (p2p_peer_channels_check(p2p, &p2p->cfg->channels, dev,
240 msg.channel_list, msg.channel_list_len) <
241 0) {
242 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
243 "P2P: No common channels found");
244 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
245 goto fail;
246 }
247
248 if (p2p->cfg->invitation_process) {
249 status = p2p->cfg->invitation_process(
250 p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id,
251 msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
252 &go, group_bssid, &op_freq, persistent);
253 }
254
255 if (op_freq) {
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -0700256 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Invitation "
257 "processing forced frequency %d MHz", op_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700258 if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
259 &reg_class, &channel) < 0) {
260 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
261 "P2P: Unknown forced freq %d MHz from "
262 "invitation_process()", op_freq);
263 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
264 goto fail;
265 }
266
267 p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
268 &intersection);
269 if (!p2p_channels_includes(&intersection, reg_class, channel))
270 {
271 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
272 "P2P: forced freq %d MHz not in the supported "
273 "channels interaction", op_freq);
274 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
275 goto fail;
276 }
277
278 if (status == P2P_SC_SUCCESS)
279 channels = &intersection;
280 } else {
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -0700281 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
282 "P2P: No forced channel from invitation processing - "
283 "figure out best one to use");
284
285 p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
286 &intersection);
287 /* Default to own configuration as a starting point */
288 p2p->op_reg_class = p2p->cfg->op_reg_class;
289 p2p->op_channel = p2p->cfg->op_channel;
290 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own default "
291 "op_class %d channel %d",
292 p2p->op_reg_class, p2p->op_channel);
293
294 /* Use peer preference if specified and compatible */
295 if (msg.operating_channel) {
296 int req_freq;
297 req_freq = p2p_channel_to_freq(
298 (const char *) msg.operating_channel,
299 msg.operating_channel[3],
300 msg.operating_channel[4]);
301 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer "
302 "operating channel preference: %d MHz",
303 req_freq);
304 if (req_freq > 0 &&
305 p2p_channels_includes(&intersection,
306 msg.operating_channel[3],
307 msg.operating_channel[4])) {
308 p2p->op_reg_class = msg.operating_channel[3];
309 p2p->op_channel = msg.operating_channel[4];
310 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
311 "P2P: Use peer preference op_class %d "
312 "channel %d",
313 p2p->op_reg_class, p2p->op_channel);
314 } else {
315 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
316 "P2P: Cannot use peer channel "
317 "preference");
318 }
319 }
320
321 if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
322 p2p->op_channel)) {
323 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
324 "P2P: Initially selected channel (op_class %d "
325 "channel %d) not in channel intersection - try "
326 "to reselect",
327 p2p->op_reg_class, p2p->op_channel);
328 p2p_reselect_channel(p2p, &intersection);
329 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
330 "P2P: Re-selection result: op_class %d "
331 "channel %d",
332 p2p->op_reg_class, p2p->op_channel);
333 if (!p2p_channels_includes(&intersection,
334 p2p->op_reg_class,
335 p2p->op_channel)) {
336 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
337 "P2P: Peer does not support selected "
338 "operating channel (reg_class=%u "
339 "channel=%u)",
340 p2p->op_reg_class, p2p->op_channel);
341 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
342 goto fail;
343 }
344 }
345
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700346 op_freq = p2p_channel_to_freq(p2p->cfg->country,
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -0700347 p2p->op_reg_class,
348 p2p->op_channel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700349 if (op_freq < 0) {
350 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
351 "P2P: Unknown operational channel "
352 "(country=%c%c reg_class=%u channel=%u)",
353 p2p->cfg->country[0], p2p->cfg->country[1],
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -0700354 p2p->op_reg_class, p2p->op_channel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700355 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
356 goto fail;
357 }
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -0700358 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
359 "channel - %d MHz", op_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700360
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700361 if (status == P2P_SC_SUCCESS) {
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -0700362 reg_class = p2p->op_reg_class;
363 channel = p2p->op_channel;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700364 channels = &intersection;
365 }
366 }
367
368fail:
369 if (go && status == P2P_SC_SUCCESS && !is_zero_ether_addr(group_bssid))
370 bssid = group_bssid;
371 else
372 bssid = NULL;
373 resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
374 bssid, reg_class, channel, channels);
375
376 if (resp == NULL)
377 goto out;
378
379 if (rx_freq > 0)
380 freq = rx_freq;
381 else
382 freq = p2p_channel_to_freq(p2p->cfg->country,
383 p2p->cfg->reg_class,
384 p2p->cfg->channel);
385 if (freq < 0) {
386 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
387 "P2P: Unknown regulatory class/channel");
388 goto out;
389 }
390
391 /*
392 * Store copy of invitation data to be used when processing TX status
393 * callback for the Acton frame.
394 */
395 os_memcpy(p2p->inv_sa, sa, ETH_ALEN);
396 if (msg.group_bssid) {
397 os_memcpy(p2p->inv_group_bssid, msg.group_bssid, ETH_ALEN);
398 p2p->inv_group_bssid_ptr = p2p->inv_group_bssid;
399 } else
400 p2p->inv_group_bssid_ptr = NULL;
401 if (msg.group_id_len - ETH_ALEN <= 32) {
402 os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN,
403 msg.group_id_len - ETH_ALEN);
404 p2p->inv_ssid_len = msg.group_id_len - ETH_ALEN;
405 }
406 os_memcpy(p2p->inv_go_dev_addr, msg.group_id, ETH_ALEN);
407 p2p->inv_status = status;
408 p2p->inv_op_freq = op_freq;
409
410 p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
411 if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
412 p2p->cfg->dev_addr,
413 wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
414 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
415 "P2P: Failed to send Action frame");
416 }
417
418out:
419 wpabuf_free(resp);
420 p2p_parse_free(&msg);
421}
422
423
424void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
425 const u8 *data, size_t len)
426{
427 struct p2p_device *dev;
428 struct p2p_message msg;
429
430 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
431 "P2P: Received Invitation Response from " MACSTR,
432 MAC2STR(sa));
433
434 dev = p2p_get_device(p2p, sa);
435 if (dev == NULL) {
436 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
437 "P2P: Ignore Invitation Response from unknown peer "
438 MACSTR, MAC2STR(sa));
439 return;
440 }
441
442 if (dev != p2p->invite_peer) {
443 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
444 "P2P: Ignore unexpected Invitation Response from peer "
445 MACSTR, MAC2STR(sa));
446 return;
447 }
448
449 if (p2p_parse(data, len, &msg))
450 return;
451
452 if (!msg.status) {
453 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
454 "P2P: Mandatory Status attribute missing in "
455 "Invitation Response from " MACSTR, MAC2STR(sa));
456 p2p_parse_free(&msg);
457 return;
458 }
459
460 if (p2p->cfg->invitation_result)
461 p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
462 msg.group_bssid);
463
464 p2p_parse_free(&msg);
465
466 p2p_clear_timeout(p2p);
467 p2p_set_state(p2p, P2P_IDLE);
468 p2p->invite_peer = NULL;
469}
470
471
472int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
473 const u8 *go_dev_addr)
474{
475 struct wpabuf *req;
476 int freq;
477
478 freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
479 if (freq <= 0) {
480 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
481 "P2P: No Listen/Operating frequency known for the "
482 "peer " MACSTR " to send Invitation Request",
483 MAC2STR(dev->info.p2p_device_addr));
484 return -1;
485 }
486
487 req = p2p_build_invitation_req(p2p, dev, go_dev_addr);
488 if (req == NULL)
489 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700490 if (p2p->state != P2P_IDLE)
491 p2p_stop_listen_for_freq(p2p, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700492 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
493 "P2P: Sending Invitation Request");
494 p2p_set_state(p2p, P2P_INVITE);
495 p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
496 p2p->invite_peer = dev;
497 dev->invitation_reqs++;
498 if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
499 p2p->cfg->dev_addr, dev->info.p2p_device_addr,
500 wpabuf_head(req), wpabuf_len(req), 200) < 0) {
501 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
502 "P2P: Failed to send Action frame");
503 /* Use P2P find to recover and retry */
504 p2p_set_timeout(p2p, 0, 0);
505 }
506
507 wpabuf_free(req);
508
509 return 0;
510}
511
512
513void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
514{
515 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
516 "P2P: Invitation Request TX callback: success=%d", success);
517
518 if (p2p->invite_peer == NULL) {
519 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
520 "P2P: No pending Invite");
521 return;
522 }
523
524 /*
525 * Use P2P find, if needed, to find the other device from its listen
526 * channel.
527 */
528 p2p_set_state(p2p, P2P_INVITE);
529 p2p_set_timeout(p2p, 0, 100000);
530}
531
532
533void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
534{
535 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
536 "P2P: Invitation Response TX callback: success=%d", success);
537 p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
538
539 if (success && p2p->cfg->invitation_received) {
540 p2p->cfg->invitation_received(p2p->cfg->cb_ctx,
541 p2p->inv_sa,
542 p2p->inv_group_bssid_ptr,
543 p2p->inv_ssid, p2p->inv_ssid_len,
544 p2p->inv_go_dev_addr,
545 p2p->inv_status,
546 p2p->inv_op_freq);
547 }
548}
549
550
551int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
552 const u8 *bssid, const u8 *ssid, size_t ssid_len,
553 unsigned int force_freq, const u8 *go_dev_addr,
554 int persistent_group)
555{
556 struct p2p_device *dev;
557
558 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
559 "P2P: Request to invite peer " MACSTR " role=%d persistent=%d "
560 "force_freq=%u",
561 MAC2STR(peer), role, persistent_group, force_freq);
562 if (bssid)
563 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
564 "P2P: Invitation for BSSID " MACSTR, MAC2STR(bssid));
565 if (go_dev_addr) {
566 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
567 "P2P: Invitation for GO Device Address " MACSTR,
568 MAC2STR(go_dev_addr));
569 os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN);
570 p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf;
571 } else
572 p2p->invite_go_dev_addr = NULL;
573 wpa_hexdump_ascii(MSG_DEBUG, "P2P: Invitation for SSID",
574 ssid, ssid_len);
575
576 dev = p2p_get_device(p2p, peer);
577 if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) {
578 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
579 "P2P: Cannot invite unknown P2P Device " MACSTR,
580 MAC2STR(peer));
581 return -1;
582 }
583
584 if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
585 if (!(dev->info.dev_capab &
586 P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
587 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
588 "P2P: Cannot invite a P2P Device " MACSTR
589 " that is in a group and is not discoverable",
590 MAC2STR(peer));
591 }
592 /* TODO: use device discoverability request through GO */
593 }
594
595 dev->invitation_reqs = 0;
596
597 if (force_freq) {
598 if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
599 &p2p->op_reg_class, &p2p->op_channel) <
600 0) {
601 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
602 "P2P: Unsupported frequency %u MHz",
603 force_freq);
604 return -1;
605 }
606 p2p->channels.reg_classes = 1;
607 p2p->channels.reg_class[0].channels = 1;
608 p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
609 p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
610 } else {
611 p2p->op_reg_class = p2p->cfg->op_reg_class;
612 p2p->op_channel = p2p->cfg->op_channel;
613 os_memcpy(&p2p->channels, &p2p->cfg->channels,
614 sizeof(struct p2p_channels));
615 }
616
617 if (p2p->state != P2P_IDLE)
618 p2p_stop_find(p2p);
619
620 p2p->inv_role = role;
621 p2p->inv_bssid_set = bssid != NULL;
622 if (bssid)
623 os_memcpy(p2p->inv_bssid, bssid, ETH_ALEN);
624 os_memcpy(p2p->inv_ssid, ssid, ssid_len);
625 p2p->inv_ssid_len = ssid_len;
626 p2p->inv_persistent = persistent_group;
627 return p2p_invite_send(p2p, dev, go_dev_addr);
628}