blob: 785200cd67b5a160e7f45d685e20c99671c95f90 [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) {
256 if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
257 &reg_class, &channel) < 0) {
258 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
259 "P2P: Unknown forced freq %d MHz from "
260 "invitation_process()", op_freq);
261 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
262 goto fail;
263 }
264
265 p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
266 &intersection);
267 if (!p2p_channels_includes(&intersection, reg_class, channel))
268 {
269 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
270 "P2P: forced freq %d MHz not in the supported "
271 "channels interaction", op_freq);
272 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
273 goto fail;
274 }
275
276 if (status == P2P_SC_SUCCESS)
277 channels = &intersection;
278 } else {
279 op_freq = p2p_channel_to_freq(p2p->cfg->country,
280 p2p->cfg->op_reg_class,
281 p2p->cfg->op_channel);
282 if (op_freq < 0) {
283 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
284 "P2P: Unknown operational channel "
285 "(country=%c%c reg_class=%u channel=%u)",
286 p2p->cfg->country[0], p2p->cfg->country[1],
287 p2p->cfg->op_reg_class, p2p->cfg->op_channel);
288 status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
289 goto fail;
290 }
291
292 p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
293 &intersection);
294 if (status == P2P_SC_SUCCESS) {
295 reg_class = p2p->cfg->op_reg_class;
296 channel = p2p->cfg->op_channel;
297 channels = &intersection;
298 }
299 }
300
301fail:
302 if (go && status == P2P_SC_SUCCESS && !is_zero_ether_addr(group_bssid))
303 bssid = group_bssid;
304 else
305 bssid = NULL;
306 resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
307 bssid, reg_class, channel, channels);
308
309 if (resp == NULL)
310 goto out;
311
312 if (rx_freq > 0)
313 freq = rx_freq;
314 else
315 freq = p2p_channel_to_freq(p2p->cfg->country,
316 p2p->cfg->reg_class,
317 p2p->cfg->channel);
318 if (freq < 0) {
319 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
320 "P2P: Unknown regulatory class/channel");
321 goto out;
322 }
323
324 /*
325 * Store copy of invitation data to be used when processing TX status
326 * callback for the Acton frame.
327 */
328 os_memcpy(p2p->inv_sa, sa, ETH_ALEN);
329 if (msg.group_bssid) {
330 os_memcpy(p2p->inv_group_bssid, msg.group_bssid, ETH_ALEN);
331 p2p->inv_group_bssid_ptr = p2p->inv_group_bssid;
332 } else
333 p2p->inv_group_bssid_ptr = NULL;
334 if (msg.group_id_len - ETH_ALEN <= 32) {
335 os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN,
336 msg.group_id_len - ETH_ALEN);
337 p2p->inv_ssid_len = msg.group_id_len - ETH_ALEN;
338 }
339 os_memcpy(p2p->inv_go_dev_addr, msg.group_id, ETH_ALEN);
340 p2p->inv_status = status;
341 p2p->inv_op_freq = op_freq;
342
343 p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
344 if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
345 p2p->cfg->dev_addr,
346 wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
347 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
348 "P2P: Failed to send Action frame");
349 }
350
351out:
352 wpabuf_free(resp);
353 p2p_parse_free(&msg);
354}
355
356
357void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
358 const u8 *data, size_t len)
359{
360 struct p2p_device *dev;
361 struct p2p_message msg;
362
363 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
364 "P2P: Received Invitation Response from " MACSTR,
365 MAC2STR(sa));
366
367 dev = p2p_get_device(p2p, sa);
368 if (dev == NULL) {
369 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
370 "P2P: Ignore Invitation Response from unknown peer "
371 MACSTR, MAC2STR(sa));
372 return;
373 }
374
375 if (dev != p2p->invite_peer) {
376 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
377 "P2P: Ignore unexpected Invitation Response from peer "
378 MACSTR, MAC2STR(sa));
379 return;
380 }
381
382 if (p2p_parse(data, len, &msg))
383 return;
384
385 if (!msg.status) {
386 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
387 "P2P: Mandatory Status attribute missing in "
388 "Invitation Response from " MACSTR, MAC2STR(sa));
389 p2p_parse_free(&msg);
390 return;
391 }
392
393 if (p2p->cfg->invitation_result)
394 p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
395 msg.group_bssid);
396
397 p2p_parse_free(&msg);
398
399 p2p_clear_timeout(p2p);
400 p2p_set_state(p2p, P2P_IDLE);
401 p2p->invite_peer = NULL;
402}
403
404
405int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
406 const u8 *go_dev_addr)
407{
408 struct wpabuf *req;
409 int freq;
410
411 freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
412 if (freq <= 0) {
413 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
414 "P2P: No Listen/Operating frequency known for the "
415 "peer " MACSTR " to send Invitation Request",
416 MAC2STR(dev->info.p2p_device_addr));
417 return -1;
418 }
419
420 req = p2p_build_invitation_req(p2p, dev, go_dev_addr);
421 if (req == NULL)
422 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700423 if (p2p->state != P2P_IDLE)
424 p2p_stop_listen_for_freq(p2p, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
426 "P2P: Sending Invitation Request");
427 p2p_set_state(p2p, P2P_INVITE);
428 p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
429 p2p->invite_peer = dev;
430 dev->invitation_reqs++;
431 if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
432 p2p->cfg->dev_addr, dev->info.p2p_device_addr,
433 wpabuf_head(req), wpabuf_len(req), 200) < 0) {
434 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
435 "P2P: Failed to send Action frame");
436 /* Use P2P find to recover and retry */
437 p2p_set_timeout(p2p, 0, 0);
438 }
439
440 wpabuf_free(req);
441
442 return 0;
443}
444
445
446void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
447{
448 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
449 "P2P: Invitation Request TX callback: success=%d", success);
450
451 if (p2p->invite_peer == NULL) {
452 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
453 "P2P: No pending Invite");
454 return;
455 }
456
457 /*
458 * Use P2P find, if needed, to find the other device from its listen
459 * channel.
460 */
461 p2p_set_state(p2p, P2P_INVITE);
462 p2p_set_timeout(p2p, 0, 100000);
463}
464
465
466void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
467{
468 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
469 "P2P: Invitation Response TX callback: success=%d", success);
470 p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
471
472 if (success && p2p->cfg->invitation_received) {
473 p2p->cfg->invitation_received(p2p->cfg->cb_ctx,
474 p2p->inv_sa,
475 p2p->inv_group_bssid_ptr,
476 p2p->inv_ssid, p2p->inv_ssid_len,
477 p2p->inv_go_dev_addr,
478 p2p->inv_status,
479 p2p->inv_op_freq);
480 }
481}
482
483
484int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
485 const u8 *bssid, const u8 *ssid, size_t ssid_len,
486 unsigned int force_freq, const u8 *go_dev_addr,
487 int persistent_group)
488{
489 struct p2p_device *dev;
490
491 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
492 "P2P: Request to invite peer " MACSTR " role=%d persistent=%d "
493 "force_freq=%u",
494 MAC2STR(peer), role, persistent_group, force_freq);
495 if (bssid)
496 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
497 "P2P: Invitation for BSSID " MACSTR, MAC2STR(bssid));
498 if (go_dev_addr) {
499 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
500 "P2P: Invitation for GO Device Address " MACSTR,
501 MAC2STR(go_dev_addr));
502 os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN);
503 p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf;
504 } else
505 p2p->invite_go_dev_addr = NULL;
506 wpa_hexdump_ascii(MSG_DEBUG, "P2P: Invitation for SSID",
507 ssid, ssid_len);
508
509 dev = p2p_get_device(p2p, peer);
510 if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) {
511 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
512 "P2P: Cannot invite unknown P2P Device " MACSTR,
513 MAC2STR(peer));
514 return -1;
515 }
516
517 if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
518 if (!(dev->info.dev_capab &
519 P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
520 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
521 "P2P: Cannot invite a P2P Device " MACSTR
522 " that is in a group and is not discoverable",
523 MAC2STR(peer));
524 }
525 /* TODO: use device discoverability request through GO */
526 }
527
528 dev->invitation_reqs = 0;
529
530 if (force_freq) {
531 if (p2p_freq_to_channel(p2p->cfg->country, force_freq,
532 &p2p->op_reg_class, &p2p->op_channel) <
533 0) {
534 wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
535 "P2P: Unsupported frequency %u MHz",
536 force_freq);
537 return -1;
538 }
539 p2p->channels.reg_classes = 1;
540 p2p->channels.reg_class[0].channels = 1;
541 p2p->channels.reg_class[0].reg_class = p2p->op_reg_class;
542 p2p->channels.reg_class[0].channel[0] = p2p->op_channel;
543 } else {
544 p2p->op_reg_class = p2p->cfg->op_reg_class;
545 p2p->op_channel = p2p->cfg->op_channel;
546 os_memcpy(&p2p->channels, &p2p->cfg->channels,
547 sizeof(struct p2p_channels));
548 }
549
550 if (p2p->state != P2P_IDLE)
551 p2p_stop_find(p2p);
552
553 p2p->inv_role = role;
554 p2p->inv_bssid_set = bssid != NULL;
555 if (bssid)
556 os_memcpy(p2p->inv_bssid, bssid, ETH_ALEN);
557 os_memcpy(p2p->inv_ssid, ssid, ssid_len);
558 p2p->inv_ssid_len = ssid_len;
559 p2p->inv_persistent = persistent_group;
560 return p2p_invite_send(p2p, dev, go_dev_addr);
561}