Line data Source code
1 : /*
2 : * Wi-Fi Direct - P2P provision discovery
3 : * Copyright (c) 2009-2010, Atheros Communications
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 : #include "common/ieee802_11_defs.h"
13 : #include "common/wpa_ctrl.h"
14 : #include "wps/wps_defs.h"
15 : #include "p2p_i.h"
16 : #include "p2p.h"
17 :
18 :
19 : /*
20 : * Number of retries to attempt for provision discovery requests
21 : * in case the peer is not listening.
22 : */
23 : #define MAX_PROV_DISC_REQ_RETRIES 120
24 :
25 :
26 280 : static void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
27 : u16 config_methods)
28 : {
29 : u8 *len;
30 280 : wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
31 280 : len = wpabuf_put(buf, 1);
32 280 : wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
33 :
34 : /* Config Methods */
35 280 : wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
36 280 : wpabuf_put_be16(buf, 2);
37 280 : wpabuf_put_be16(buf, config_methods);
38 :
39 280 : p2p_buf_update_ie_hdr(buf, len);
40 280 : }
41 :
42 :
43 20 : static void p2ps_add_new_group_info(struct p2p_data *p2p, struct wpabuf *buf)
44 : {
45 : int found;
46 : u8 intended_addr[ETH_ALEN];
47 : u8 ssid[32];
48 : size_t ssid_len;
49 : int group_iface;
50 :
51 20 : if (!p2p->cfg->get_go_info)
52 20 : return;
53 :
54 40 : found = p2p->cfg->get_go_info(
55 20 : p2p->cfg->cb_ctx, intended_addr, ssid,
56 : &ssid_len, &group_iface);
57 20 : if (found) {
58 0 : p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
59 : ssid, ssid_len);
60 0 : p2p_buf_add_intended_addr(buf, intended_addr);
61 : } else {
62 20 : if (!p2p->ssid_set) {
63 18 : p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len);
64 18 : p2p->ssid_set = 1;
65 : }
66 :
67 : /* Add pre-composed P2P Group ID */
68 40 : p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
69 20 : p2p->ssid, p2p->ssid_len);
70 :
71 20 : if (group_iface)
72 2 : p2p_buf_add_intended_addr(
73 2 : buf, p2p->intended_addr);
74 : else
75 18 : p2p_buf_add_intended_addr(
76 18 : buf, p2p->cfg->dev_addr);
77 : }
78 : }
79 :
80 :
81 18 : static void p2ps_add_pd_req_attrs(struct p2p_data *p2p, struct p2p_device *dev,
82 : struct wpabuf *buf, u16 config_methods)
83 : {
84 18 : struct p2ps_provision *prov = p2p->p2ps_prov;
85 18 : u8 feat_cap_mask[] = { 1, 0 };
86 18 : int shared_group = 0;
87 : u8 ssid[32];
88 : size_t ssid_len;
89 : u8 go_dev_addr[ETH_ALEN];
90 :
91 : /* If we might be explicite group owner, add GO details */
92 18 : if (prov->conncap & (P2PS_SETUP_GROUP_OWNER |
93 : P2PS_SETUP_NEW))
94 18 : p2ps_add_new_group_info(p2p, buf);
95 :
96 18 : if (prov->status >= 0)
97 3 : p2p_buf_add_status(buf, (u8) prov->status);
98 : else
99 15 : prov->method = config_methods;
100 :
101 18 : if (p2p->cfg->get_persistent_group) {
102 36 : shared_group = p2p->cfg->get_persistent_group(
103 18 : p2p->cfg->cb_ctx, dev->info.p2p_device_addr, NULL, 0,
104 : go_dev_addr, ssid, &ssid_len);
105 : }
106 :
107 : /* Add Operating Channel if conncap includes GO */
108 35 : if (shared_group ||
109 17 : (prov->conncap & (P2PS_SETUP_GROUP_OWNER |
110 : P2PS_SETUP_NEW))) {
111 : u8 tmp;
112 :
113 18 : p2p_go_select_channel(p2p, dev, &tmp);
114 :
115 18 : if (p2p->op_reg_class && p2p->op_channel)
116 36 : p2p_buf_add_operating_channel(buf, p2p->cfg->country,
117 18 : p2p->op_reg_class,
118 18 : p2p->op_channel);
119 : else
120 0 : p2p_buf_add_operating_channel(buf, p2p->cfg->country,
121 0 : p2p->cfg->op_reg_class,
122 0 : p2p->cfg->op_channel);
123 : }
124 :
125 18 : p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->cfg->channels);
126 :
127 18 : if (prov->info[0])
128 4 : p2p_buf_add_session_info(buf, prov->info);
129 :
130 18 : p2p_buf_add_connection_capability(buf, prov->conncap);
131 :
132 18 : p2p_buf_add_advertisement_id(buf, prov->adv_id, prov->adv_mac);
133 :
134 18 : if (shared_group || prov->conncap == P2PS_SETUP_NEW ||
135 0 : prov->conncap ==
136 0 : (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW) ||
137 0 : prov->conncap ==
138 : (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT)) {
139 : /* Add Config Timeout */
140 18 : p2p_buf_add_config_timeout(buf, p2p->go_timeout,
141 18 : p2p->client_timeout);
142 : }
143 :
144 18 : p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class,
145 18 : p2p->cfg->channel);
146 :
147 18 : p2p_buf_add_session_id(buf, prov->session_id, prov->session_mac);
148 :
149 18 : p2p_buf_add_feature_capability(buf, sizeof(feat_cap_mask),
150 : feat_cap_mask);
151 :
152 18 : if (shared_group)
153 1 : p2p_buf_add_persistent_group_info(buf, go_dev_addr,
154 : ssid, ssid_len);
155 18 : }
156 :
157 :
158 199 : static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
159 : struct p2p_device *dev,
160 : int join)
161 : {
162 : struct wpabuf *buf;
163 : u8 *len;
164 199 : size_t extra = 0;
165 199 : u8 dialog_token = dev->dialog_token;
166 199 : u16 config_methods = dev->req_config_methods;
167 199 : struct p2p_device *go = join ? dev : NULL;
168 : u8 group_capab;
169 :
170 : #ifdef CONFIG_WIFI_DISPLAY
171 199 : if (p2p->wfd_ie_prov_disc_req)
172 3 : extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
173 : #endif /* CONFIG_WIFI_DISPLAY */
174 :
175 199 : if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
176 0 : extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
177 :
178 199 : if (p2p->p2ps_prov)
179 18 : extra += os_strlen(p2p->p2ps_prov->info) + 1 +
180 : sizeof(struct p2ps_provision);
181 :
182 199 : buf = wpabuf_alloc(1000 + extra);
183 199 : if (buf == NULL)
184 0 : return NULL;
185 :
186 199 : p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token);
187 :
188 199 : len = p2p_buf_add_ie_hdr(buf);
189 :
190 199 : group_capab = 0;
191 199 : if (p2p->p2ps_prov) {
192 18 : group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
193 18 : group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
194 18 : if (p2p->cross_connect)
195 0 : group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
196 18 : if (p2p->cfg->p2p_intra_bss)
197 18 : group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
198 : }
199 199 : p2p_buf_add_capability(buf, p2p->dev_capab &
200 : ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
201 : group_capab);
202 199 : p2p_buf_add_device_info(buf, p2p, NULL);
203 199 : if (p2p->p2ps_prov) {
204 18 : p2ps_add_pd_req_attrs(p2p, dev, buf, config_methods);
205 181 : } else if (go) {
206 100 : p2p_buf_add_group_id(buf, go->info.p2p_device_addr,
207 50 : go->oper_ssid, go->oper_ssid_len);
208 : }
209 199 : p2p_buf_update_ie_hdr(buf, len);
210 :
211 : /* WPS IE with Config Methods attribute */
212 199 : p2p_build_wps_ie_config_methods(buf, config_methods);
213 :
214 : #ifdef CONFIG_WIFI_DISPLAY
215 199 : if (p2p->wfd_ie_prov_disc_req)
216 3 : wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
217 : #endif /* CONFIG_WIFI_DISPLAY */
218 :
219 199 : if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
220 0 : wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
221 :
222 199 : return buf;
223 : }
224 :
225 :
226 81 : static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
227 : struct p2p_device *dev,
228 : u8 dialog_token,
229 : enum p2p_status_code status,
230 : u16 config_methods,
231 : u32 adv_id,
232 : const u8 *group_id,
233 : size_t group_id_len,
234 : const u8 *persist_ssid,
235 : size_t persist_ssid_len)
236 : {
237 : struct wpabuf *buf;
238 81 : size_t extra = 0;
239 81 : int persist = 0;
240 :
241 : #ifdef CONFIG_WIFI_DISPLAY
242 81 : struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
243 81 : if (wfd_ie && group_id) {
244 : size_t i;
245 3 : for (i = 0; i < p2p->num_groups; i++) {
246 3 : struct p2p_group *g = p2p->groups[i];
247 : struct wpabuf *ie;
248 3 : if (!p2p_group_is_group_id_match(g, group_id,
249 : group_id_len))
250 0 : continue;
251 3 : ie = p2p_group_get_wfd_ie(g);
252 3 : if (ie) {
253 3 : wfd_ie = ie;
254 3 : break;
255 : }
256 : }
257 : }
258 81 : if (wfd_ie)
259 3 : extra = wpabuf_len(wfd_ie);
260 : #endif /* CONFIG_WIFI_DISPLAY */
261 :
262 81 : if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
263 0 : extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
264 :
265 81 : buf = wpabuf_alloc(1000 + extra);
266 81 : if (buf == NULL)
267 0 : return NULL;
268 :
269 81 : p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token);
270 :
271 : /* Add P2P IE for P2PS */
272 99 : if (p2p->p2ps_prov && p2p->p2ps_prov->adv_id == adv_id) {
273 18 : u8 feat_cap_mask[] = { 1, 0 };
274 18 : u8 *len = p2p_buf_add_ie_hdr(buf);
275 18 : struct p2ps_provision *prov = p2p->p2ps_prov;
276 : u8 group_capab;
277 :
278 18 : if (!status && prov->status != -1)
279 14 : status = prov->status;
280 :
281 18 : p2p_buf_add_status(buf, status);
282 18 : group_capab = P2P_GROUP_CAPAB_PERSISTENT_GROUP |
283 : P2P_GROUP_CAPAB_PERSISTENT_RECONN;
284 18 : if (p2p->cross_connect)
285 0 : group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
286 18 : if (p2p->cfg->p2p_intra_bss)
287 18 : group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
288 18 : p2p_buf_add_capability(buf, p2p->dev_capab &
289 : ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
290 : group_capab);
291 18 : p2p_buf_add_device_info(buf, p2p, NULL);
292 :
293 18 : if (persist_ssid && p2p->cfg->get_persistent_group &&
294 0 : (status == P2P_SC_SUCCESS ||
295 : status == P2P_SC_SUCCESS_DEFERRED)) {
296 : u8 ssid[32];
297 : size_t ssid_len;
298 : u8 go_dev_addr[ETH_ALEN];
299 :
300 2 : persist = p2p->cfg->get_persistent_group(
301 1 : p2p->cfg->cb_ctx,
302 1 : dev->info.p2p_device_addr,
303 : persist_ssid, persist_ssid_len, go_dev_addr,
304 : ssid, &ssid_len);
305 1 : if (persist)
306 1 : p2p_buf_add_persistent_group_info(
307 : buf, go_dev_addr, ssid, ssid_len);
308 : }
309 :
310 18 : if (!persist && (prov->conncap & P2PS_SETUP_GROUP_OWNER))
311 2 : p2ps_add_new_group_info(p2p, buf);
312 :
313 : /* Add Operating Channel if conncap indicates GO */
314 18 : if (persist || (prov->conncap & P2PS_SETUP_GROUP_OWNER)) {
315 : u8 tmp;
316 :
317 3 : if (dev)
318 3 : p2p_go_select_channel(p2p, dev, &tmp);
319 :
320 3 : if (p2p->op_reg_class && p2p->op_channel)
321 9 : p2p_buf_add_operating_channel(
322 3 : buf, p2p->cfg->country,
323 3 : p2p->op_reg_class,
324 3 : p2p->op_channel);
325 : else
326 0 : p2p_buf_add_operating_channel(
327 0 : buf, p2p->cfg->country,
328 0 : p2p->cfg->op_reg_class,
329 0 : p2p->cfg->op_channel);
330 : }
331 :
332 18 : p2p_buf_add_channel_list(buf, p2p->cfg->country,
333 18 : &p2p->cfg->channels);
334 :
335 18 : if (!persist && (status == P2P_SC_SUCCESS ||
336 : status == P2P_SC_SUCCESS_DEFERRED))
337 13 : p2p_buf_add_connection_capability(buf, prov->conncap);
338 :
339 18 : p2p_buf_add_advertisement_id(buf, adv_id, prov->adv_mac);
340 :
341 18 : p2p_buf_add_config_timeout(buf, p2p->go_timeout,
342 18 : p2p->client_timeout);
343 :
344 18 : p2p_buf_add_session_id(buf, prov->session_id,
345 18 : prov->session_mac);
346 :
347 18 : p2p_buf_add_feature_capability(buf, sizeof(feat_cap_mask),
348 : feat_cap_mask);
349 18 : p2p_buf_update_ie_hdr(buf, len);
350 63 : } else if (status != P2P_SC_SUCCESS || adv_id) {
351 2 : u8 *len = p2p_buf_add_ie_hdr(buf);
352 :
353 2 : p2p_buf_add_status(buf, status);
354 :
355 2 : if (p2p->p2ps_prov)
356 0 : p2p_buf_add_advertisement_id(buf, adv_id,
357 0 : p2p->p2ps_prov->adv_mac);
358 :
359 2 : p2p_buf_update_ie_hdr(buf, len);
360 : }
361 :
362 : /* WPS IE with Config Methods attribute */
363 81 : p2p_build_wps_ie_config_methods(buf, config_methods);
364 :
365 : #ifdef CONFIG_WIFI_DISPLAY
366 81 : if (wfd_ie)
367 3 : wpabuf_put_buf(buf, wfd_ie);
368 : #endif /* CONFIG_WIFI_DISPLAY */
369 :
370 81 : if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
371 0 : wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
372 :
373 81 : return buf;
374 : }
375 :
376 :
377 15 : static int p2ps_setup_p2ps_prov(struct p2p_data *p2p, u32 adv_id,
378 : u32 session_id, u16 method,
379 : const u8 *session_mac, const u8 *adv_mac)
380 : {
381 : struct p2ps_provision *tmp;
382 :
383 15 : if (!p2p->p2ps_prov) {
384 7 : p2p->p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + 1);
385 7 : if (!p2p->p2ps_prov)
386 0 : return -1;
387 : } else {
388 8 : os_memset(p2p->p2ps_prov, 0, sizeof(struct p2ps_provision) + 1);
389 : }
390 :
391 15 : tmp = p2p->p2ps_prov;
392 15 : tmp->adv_id = adv_id;
393 15 : tmp->session_id = session_id;
394 15 : tmp->method = method;
395 15 : os_memcpy(tmp->session_mac, session_mac, ETH_ALEN);
396 15 : os_memcpy(tmp->adv_mac, adv_mac, ETH_ALEN);
397 15 : tmp->info[0] = '\0';
398 :
399 15 : return 0;
400 : }
401 :
402 :
403 82 : void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
404 : const u8 *data, size_t len, int rx_freq)
405 : {
406 : struct p2p_message msg;
407 : struct p2p_device *dev;
408 : int freq;
409 82 : enum p2p_status_code reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
410 : struct wpabuf *resp;
411 82 : u32 adv_id = 0;
412 82 : struct p2ps_advertisement *p2ps_adv = NULL;
413 82 : u8 conncap = P2PS_SETUP_NEW;
414 82 : u8 auto_accept = 0;
415 82 : u32 session_id = 0;
416 : u8 session_mac[ETH_ALEN];
417 : u8 adv_mac[ETH_ALEN];
418 : u8 group_mac[ETH_ALEN];
419 82 : int passwd_id = DEV_PW_DEFAULT;
420 : u16 config_methods;
421 :
422 82 : if (p2p_parse(data, len, &msg))
423 2 : return;
424 :
425 567 : p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR
426 : " with config methods 0x%x (freq=%d)",
427 567 : MAC2STR(sa), msg.wps_config_methods, rx_freq);
428 :
429 81 : dev = p2p_get_device(p2p, sa);
430 81 : if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
431 402 : p2p_dbg(p2p, "Provision Discovery Request from unknown peer "
432 402 : MACSTR, MAC2STR(sa));
433 :
434 134 : if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
435 : 0)) {
436 6 : p2p_dbg(p2p, "Provision Discovery Request add device failed "
437 6 : MACSTR, MAC2STR(sa));
438 : }
439 14 : } else if (msg.wfd_subelems) {
440 1 : wpabuf_free(dev->info.wfd_subelems);
441 1 : dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
442 : }
443 :
444 81 : if (!(msg.wps_config_methods &
445 : (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD |
446 : WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_P2PS))) {
447 1 : p2p_dbg(p2p, "Unsupported Config Methods in Provision Discovery Request");
448 1 : goto out;
449 : }
450 :
451 : /* Legacy (non-P2PS) - Unknown groups allowed for P2PS */
452 80 : if (!msg.adv_id && msg.group_id) {
453 : size_t i;
454 51 : for (i = 0; i < p2p->num_groups; i++) {
455 50 : if (p2p_group_is_group_id_match(p2p->groups[i],
456 : msg.group_id,
457 : msg.group_id_len))
458 50 : break;
459 : }
460 51 : if (i == p2p->num_groups) {
461 1 : p2p_dbg(p2p, "PD request for unknown P2P Group ID - reject");
462 1 : goto out;
463 : }
464 : }
465 :
466 79 : if (dev) {
467 77 : dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
468 : P2P_DEV_PD_PEER_KEYPAD |
469 : P2P_DEV_PD_PEER_P2PS);
470 :
471 : /* Remove stale persistent groups */
472 77 : if (p2p->cfg->remove_stale_groups) {
473 154 : p2p->cfg->remove_stale_groups(
474 77 : p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
475 : msg.persistent_dev,
476 : msg.persistent_ssid, msg.persistent_ssid_len);
477 : }
478 : }
479 79 : if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
480 336 : p2p_dbg(p2p, "Peer " MACSTR
481 336 : " requested us to show a PIN on display", MAC2STR(sa));
482 56 : if (dev)
483 54 : dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
484 56 : passwd_id = DEV_PW_USER_SPECIFIED;
485 23 : } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
486 42 : p2p_dbg(p2p, "Peer " MACSTR
487 : " requested us to write its PIN using keypad",
488 42 : MAC2STR(sa));
489 7 : if (dev)
490 7 : dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
491 7 : passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
492 16 : } else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
493 60 : p2p_dbg(p2p, "Peer " MACSTR " requesting P2PS PIN",
494 60 : MAC2STR(sa));
495 10 : if (dev)
496 10 : dev->flags |= P2P_DEV_PD_PEER_P2PS;
497 10 : passwd_id = DEV_PW_P2PS_DEFAULT;
498 : }
499 :
500 79 : reject = P2P_SC_SUCCESS;
501 :
502 79 : os_memset(session_mac, 0, ETH_ALEN);
503 79 : os_memset(adv_mac, 0, ETH_ALEN);
504 79 : os_memset(group_mac, 0, ETH_ALEN);
505 :
506 97 : if (msg.adv_id && msg.session_id && msg.session_mac && msg.adv_mac &&
507 33 : (msg.status || msg.conn_cap)) {
508 : u8 remote_conncap;
509 :
510 18 : if (msg.intended_addr)
511 18 : os_memcpy(group_mac, msg.intended_addr, ETH_ALEN);
512 :
513 18 : os_memcpy(session_mac, msg.session_mac, ETH_ALEN);
514 18 : os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
515 :
516 18 : session_id = WPA_GET_LE32(msg.session_id);
517 18 : adv_id = WPA_GET_LE32(msg.adv_id);
518 :
519 18 : if (!msg.status)
520 15 : p2ps_adv = p2p_service_p2ps_id(p2p, adv_id);
521 :
522 18 : p2p_dbg(p2p, "adv_id: %x - p2ps_adv - %p", adv_id, p2ps_adv);
523 :
524 18 : if (msg.conn_cap)
525 18 : conncap = *msg.conn_cap;
526 18 : remote_conncap = conncap;
527 :
528 18 : if (p2ps_adv) {
529 15 : auto_accept = p2ps_adv->auto_accept;
530 30 : conncap = p2p->cfg->p2ps_group_capability(
531 15 : p2p->cfg->cb_ctx, conncap, auto_accept);
532 :
533 15 : p2p_dbg(p2p, "Conncap: local:%d remote:%d result:%d",
534 : auto_accept, remote_conncap, conncap);
535 :
536 30 : if (p2ps_adv->config_methods &&
537 30 : !(msg.wps_config_methods &
538 15 : p2ps_adv->config_methods)) {
539 0 : p2p_dbg(p2p,
540 : "Unsupported config methods in Provision Discovery Request (own=0x%x peer=0x%x)",
541 0 : p2ps_adv->config_methods,
542 0 : msg.wps_config_methods);
543 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
544 15 : } else if (!p2ps_adv->state) {
545 0 : p2p_dbg(p2p, "P2PS state unavailable");
546 0 : reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
547 15 : } else if (!conncap) {
548 0 : p2p_dbg(p2p, "Conncap resolution failed");
549 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
550 : }
551 :
552 15 : if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
553 2 : p2p_dbg(p2p, "Keypad - always defer");
554 2 : auto_accept = 0;
555 : }
556 :
557 15 : if (auto_accept || reject != P2P_SC_SUCCESS) {
558 : struct p2ps_provision *tmp;
559 :
560 11 : if (reject == P2P_SC_SUCCESS && !conncap) {
561 0 : reject =
562 : P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
563 : }
564 :
565 11 : if (p2ps_setup_p2ps_prov(
566 : p2p, adv_id, session_id,
567 11 : msg.wps_config_methods,
568 : session_mac, adv_mac) < 0) {
569 0 : reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
570 0 : goto out;
571 : }
572 :
573 11 : tmp = p2p->p2ps_prov;
574 11 : if (conncap) {
575 11 : tmp->conncap = conncap;
576 11 : tmp->status = P2P_SC_SUCCESS;
577 : } else {
578 0 : tmp->conncap = auto_accept;
579 0 : tmp->status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
580 : }
581 :
582 11 : if (reject != P2P_SC_SUCCESS)
583 0 : goto out;
584 : }
585 3 : } else if (!msg.status) {
586 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
587 0 : goto out;
588 : }
589 :
590 22 : if (!msg.status && !auto_accept &&
591 7 : (!p2p->p2ps_prov || p2p->p2ps_prov->adv_id != adv_id)) {
592 : struct p2ps_provision *tmp;
593 :
594 4 : if (!conncap) {
595 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
596 0 : goto out;
597 : }
598 :
599 4 : if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
600 4 : msg.wps_config_methods,
601 : session_mac, adv_mac) < 0) {
602 0 : reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
603 0 : goto out;
604 : }
605 4 : tmp = p2p->p2ps_prov;
606 4 : reject = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
607 4 : tmp->status = reject;
608 : }
609 :
610 18 : if (msg.status) {
611 6 : if (*msg.status &&
612 3 : *msg.status != P2P_SC_SUCCESS_DEFERRED) {
613 0 : reject = *msg.status;
614 6 : } else if (*msg.status == P2P_SC_SUCCESS_DEFERRED &&
615 3 : p2p->p2ps_prov) {
616 3 : u16 method = p2p->p2ps_prov->method;
617 :
618 9 : conncap = p2p->cfg->p2ps_group_capability(
619 3 : p2p->cfg->cb_ctx, remote_conncap,
620 3 : p2p->p2ps_prov->conncap);
621 :
622 6 : p2p_dbg(p2p,
623 : "Conncap: local:%d remote:%d result:%d",
624 3 : p2p->p2ps_prov->conncap,
625 : remote_conncap, conncap);
626 :
627 : /*
628 : * Ensure that if we asked for PIN originally,
629 : * our method is consistent with original
630 : * request.
631 : */
632 3 : if (method & WPS_CONFIG_DISPLAY)
633 1 : method = WPS_CONFIG_KEYPAD;
634 2 : else if (method & WPS_CONFIG_KEYPAD)
635 1 : method = WPS_CONFIG_DISPLAY;
636 :
637 : /* Reject this "Deferred Accept* if incompatible
638 : * conncap or method */
639 6 : if (!conncap ||
640 3 : !(msg.wps_config_methods & method))
641 0 : reject =
642 : P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
643 : else
644 3 : reject = P2P_SC_SUCCESS;
645 :
646 3 : p2p->p2ps_prov->status = reject;
647 3 : p2p->p2ps_prov->conncap = conncap;
648 : }
649 : }
650 : }
651 :
652 : out:
653 81 : if (reject == P2P_SC_SUCCESS ||
654 : reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
655 79 : config_methods = msg.wps_config_methods;
656 : else
657 2 : config_methods = 0;
658 81 : resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token, reject,
659 : config_methods, adv_id,
660 : msg.group_id, msg.group_id_len,
661 : msg.persistent_ssid,
662 : msg.persistent_ssid_len);
663 81 : if (resp == NULL) {
664 0 : p2p_parse_free(&msg);
665 0 : return;
666 : }
667 81 : p2p_dbg(p2p, "Sending Provision Discovery Response");
668 81 : if (rx_freq > 0)
669 81 : freq = rx_freq;
670 : else
671 0 : freq = p2p_channel_to_freq(p2p->cfg->reg_class,
672 0 : p2p->cfg->channel);
673 81 : if (freq < 0) {
674 0 : p2p_dbg(p2p, "Unknown regulatory class/channel");
675 0 : wpabuf_free(resp);
676 0 : p2p_parse_free(&msg);
677 0 : return;
678 : }
679 81 : p2p->pending_action_state = P2P_PENDING_PD_RESPONSE;
680 162 : if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
681 81 : p2p->cfg->dev_addr,
682 81 : wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
683 0 : p2p_dbg(p2p, "Failed to send Action frame");
684 : } else
685 81 : p2p->send_action_in_progress = 1;
686 :
687 81 : wpabuf_free(resp);
688 :
689 81 : if (!p2p->cfg->p2ps_prov_complete) {
690 : /* Don't emit anything */
691 84 : } else if (msg.status && *msg.status != P2P_SC_SUCCESS &&
692 3 : *msg.status != P2P_SC_SUCCESS_DEFERRED) {
693 0 : reject = *msg.status;
694 0 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
695 : sa, adv_mac, session_mac,
696 : NULL, adv_id, session_id,
697 : 0, 0, msg.persistent_ssid,
698 : msg.persistent_ssid_len,
699 : 0, 0, NULL);
700 84 : } else if (msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
701 3 : p2p->p2ps_prov) {
702 3 : p2p->p2ps_prov->status = reject;
703 3 : p2p->p2ps_prov->conncap = conncap;
704 :
705 6 : if (reject != P2P_SC_SUCCESS)
706 0 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
707 : sa, adv_mac, session_mac,
708 : NULL, adv_id,
709 : session_id, conncap, 0,
710 : msg.persistent_ssid,
711 : msg.persistent_ssid_len, 0,
712 : 0, NULL);
713 : else
714 6 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx,
715 3 : *msg.status,
716 : sa, adv_mac, session_mac,
717 : group_mac, adv_id,
718 : session_id, conncap,
719 : passwd_id,
720 : msg.persistent_ssid,
721 : msg.persistent_ssid_len, 0,
722 : 0, NULL);
723 78 : } else if (msg.status && p2p->p2ps_prov) {
724 0 : p2p->p2ps_prov->status = P2P_SC_SUCCESS;
725 0 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, *msg.status, sa,
726 : adv_mac, session_mac, group_mac,
727 : adv_id, session_id, conncap,
728 : passwd_id,
729 : msg.persistent_ssid,
730 : msg.persistent_ssid_len,
731 : 0, 0, NULL);
732 78 : } else if (msg.status) {
733 78 : } else if (auto_accept && reject == P2P_SC_SUCCESS) {
734 11 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
735 : sa, adv_mac, session_mac,
736 : group_mac, adv_id, session_id,
737 : conncap, passwd_id,
738 : msg.persistent_ssid,
739 : msg.persistent_ssid_len,
740 : 0, 0, NULL);
741 71 : } else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
742 4 : (!msg.session_info || !msg.session_info_len)) {
743 4 : p2p->p2ps_prov->method = msg.wps_config_methods;
744 :
745 4 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
746 : sa, adv_mac, session_mac,
747 : group_mac, adv_id, session_id,
748 : conncap, passwd_id,
749 : msg.persistent_ssid,
750 : msg.persistent_ssid_len,
751 : 0, 1, NULL);
752 63 : } else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
753 0 : size_t buf_len = msg.session_info_len;
754 0 : char *buf = os_malloc(2 * buf_len + 1);
755 :
756 0 : if (buf) {
757 0 : p2p->p2ps_prov->method = msg.wps_config_methods;
758 :
759 0 : utf8_escape((char *) msg.session_info, buf_len,
760 0 : buf, 2 * buf_len + 1);
761 :
762 0 : p2p->cfg->p2ps_prov_complete(
763 0 : p2p->cfg->cb_ctx, P2P_SC_SUCCESS, sa,
764 : adv_mac, session_mac, group_mac, adv_id,
765 : session_id, conncap, passwd_id,
766 : msg.persistent_ssid, msg.persistent_ssid_len,
767 : 0, 1, buf);
768 :
769 0 : os_free(buf);
770 : }
771 : }
772 :
773 81 : if (reject == P2P_SC_SUCCESS && p2p->cfg->prov_disc_req) {
774 75 : const u8 *dev_addr = sa;
775 75 : if (msg.p2p_device_addr)
776 75 : dev_addr = msg.p2p_device_addr;
777 525 : p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa,
778 75 : msg.wps_config_methods,
779 : dev_addr, msg.pri_dev_type,
780 75 : msg.device_name, msg.config_methods,
781 150 : msg.capability ? msg.capability[0] : 0,
782 150 : msg.capability ? msg.capability[1] :
783 : 0,
784 : msg.group_id, msg.group_id_len);
785 : }
786 81 : p2p_parse_free(&msg);
787 : }
788 :
789 :
790 80 : void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
791 : const u8 *data, size_t len)
792 : {
793 : struct p2p_message msg;
794 : struct p2p_device *dev;
795 80 : u16 report_config_methods = 0, req_config_methods;
796 80 : u8 status = P2P_SC_SUCCESS;
797 80 : int success = 0;
798 80 : u32 adv_id = 0;
799 80 : u8 conncap = P2PS_SETUP_NEW;
800 : u8 adv_mac[ETH_ALEN];
801 : u8 group_mac[ETH_ALEN];
802 80 : int passwd_id = DEV_PW_DEFAULT;
803 :
804 80 : if (p2p_parse(data, len, &msg))
805 4 : return;
806 :
807 : /* Parse the P2PS members present */
808 80 : if (msg.status)
809 18 : status = *msg.status;
810 :
811 80 : if (msg.intended_addr)
812 2 : os_memcpy(group_mac, msg.intended_addr, ETH_ALEN);
813 : else
814 78 : os_memset(group_mac, 0, ETH_ALEN);
815 :
816 80 : if (msg.adv_mac)
817 18 : os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
818 : else
819 62 : os_memset(adv_mac, 0, ETH_ALEN);
820 :
821 80 : if (msg.adv_id)
822 18 : adv_id = WPA_GET_LE32(msg.adv_id);
823 :
824 80 : if (msg.conn_cap) {
825 13 : conncap = *msg.conn_cap;
826 :
827 : /* Switch bits to local relative */
828 13 : switch (conncap) {
829 : case P2PS_SETUP_GROUP_OWNER:
830 2 : conncap = P2PS_SETUP_CLIENT;
831 2 : break;
832 : case P2PS_SETUP_CLIENT:
833 6 : conncap = P2PS_SETUP_GROUP_OWNER;
834 6 : break;
835 : }
836 : }
837 :
838 560 : p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR
839 : " with config methods 0x%x",
840 560 : MAC2STR(sa), msg.wps_config_methods);
841 :
842 80 : dev = p2p_get_device(p2p, sa);
843 80 : if (dev == NULL || !dev->req_config_methods) {
844 6 : p2p_dbg(p2p, "Ignore Provision Discovery Response from " MACSTR
845 6 : " with no pending request", MAC2STR(sa));
846 1 : p2p_parse_free(&msg);
847 1 : return;
848 : }
849 :
850 79 : if (dev->dialog_token != msg.dialog_token) {
851 2 : p2p_dbg(p2p, "Ignore Provision Discovery Response with unexpected Dialog Token %u (expected %u)",
852 2 : msg.dialog_token, dev->dialog_token);
853 1 : p2p_parse_free(&msg);
854 1 : return;
855 : }
856 :
857 78 : if (p2p->pending_action_state == P2P_PENDING_PD) {
858 74 : os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
859 74 : p2p->pending_action_state = P2P_NO_PENDING_ACTION;
860 : }
861 :
862 : /*
863 : * Use a local copy of the requested config methods since
864 : * p2p_reset_pending_pd() can clear this in the peer entry.
865 : */
866 78 : req_config_methods = dev->req_config_methods;
867 :
868 : /*
869 : * If the response is from the peer to whom a user initiated request
870 : * was sent earlier, we reset that state info here.
871 : */
872 152 : if (p2p->user_initiated_pd &&
873 74 : os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0)
874 0 : p2p_reset_pending_pd(p2p);
875 :
876 78 : if (msg.wps_config_methods != req_config_methods) {
877 2 : p2p_dbg(p2p, "Peer rejected our Provision Discovery Request (received config_methods 0x%x expected 0x%x",
878 1 : msg.wps_config_methods, req_config_methods);
879 1 : if (p2p->cfg->prov_disc_fail)
880 1 : p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
881 : P2P_PROV_DISC_REJECTED,
882 : adv_id, adv_mac, NULL);
883 1 : p2p_parse_free(&msg);
884 1 : os_free(p2p->p2ps_prov);
885 1 : p2p->p2ps_prov = NULL;
886 1 : goto out;
887 : }
888 :
889 77 : report_config_methods = req_config_methods;
890 77 : dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
891 : P2P_DEV_PD_PEER_KEYPAD |
892 : P2P_DEV_PD_PEER_P2PS);
893 77 : if (req_config_methods & WPS_CONFIG_DISPLAY) {
894 324 : p2p_dbg(p2p, "Peer " MACSTR
895 324 : " accepted to show a PIN on display", MAC2STR(sa));
896 54 : dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
897 54 : passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
898 23 : } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
899 42 : p2p_dbg(p2p, "Peer " MACSTR
900 : " accepted to write our PIN using keypad",
901 42 : MAC2STR(sa));
902 7 : dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
903 7 : passwd_id = DEV_PW_USER_SPECIFIED;
904 16 : } else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
905 60 : p2p_dbg(p2p, "Peer " MACSTR " accepted P2PS PIN",
906 60 : MAC2STR(sa));
907 10 : dev->flags |= P2P_DEV_PD_PEER_P2PS;
908 10 : passwd_id = DEV_PW_P2PS_DEFAULT;
909 : }
910 :
911 91 : if ((msg.conn_cap || msg.persistent_dev) &&
912 28 : msg.adv_id &&
913 14 : (status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
914 14 : p2p->p2ps_prov) {
915 14 : if (p2p->cfg->p2ps_prov_complete) {
916 56 : p2p->cfg->p2ps_prov_complete(
917 14 : p2p->cfg->cb_ctx, status, sa, adv_mac,
918 14 : p2p->p2ps_prov->session_mac,
919 14 : group_mac, adv_id, p2p->p2ps_prov->session_id,
920 : conncap, passwd_id, msg.persistent_ssid,
921 : msg.persistent_ssid_len, 1, 0, NULL);
922 : }
923 14 : os_free(p2p->p2ps_prov);
924 14 : p2p->p2ps_prov = NULL;
925 : }
926 :
927 77 : if (status != P2P_SC_SUCCESS &&
928 0 : status != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
929 0 : status != P2P_SC_SUCCESS_DEFERRED && p2p->p2ps_prov) {
930 0 : if (p2p->cfg->p2ps_prov_complete)
931 0 : p2p->cfg->p2ps_prov_complete(
932 0 : p2p->cfg->cb_ctx, status, sa, adv_mac,
933 0 : p2p->p2ps_prov->session_mac,
934 0 : group_mac, adv_id, p2p->p2ps_prov->session_id,
935 : 0, 0, NULL, 0, 1, 0, NULL);
936 0 : os_free(p2p->p2ps_prov);
937 0 : p2p->p2ps_prov = NULL;
938 : }
939 :
940 77 : if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
941 4 : if (p2p->cfg->remove_stale_groups) {
942 8 : p2p->cfg->remove_stale_groups(p2p->cfg->cb_ctx,
943 4 : dev->info.p2p_device_addr,
944 : NULL, NULL, 0);
945 : }
946 :
947 4 : if (msg.session_info && msg.session_info_len) {
948 0 : size_t info_len = msg.session_info_len;
949 0 : char *deferred_sess_resp = os_malloc(2 * info_len + 1);
950 :
951 0 : if (!deferred_sess_resp) {
952 0 : p2p_parse_free(&msg);
953 0 : os_free(p2p->p2ps_prov);
954 0 : p2p->p2ps_prov = NULL;
955 0 : goto out;
956 : }
957 0 : utf8_escape((char *) msg.session_info, info_len,
958 0 : deferred_sess_resp, 2 * info_len + 1);
959 :
960 0 : if (p2p->cfg->prov_disc_fail)
961 0 : p2p->cfg->prov_disc_fail(
962 0 : p2p->cfg->cb_ctx, sa,
963 : P2P_PROV_DISC_INFO_UNAVAILABLE,
964 : adv_id, adv_mac,
965 : deferred_sess_resp);
966 0 : os_free(deferred_sess_resp);
967 : } else
968 4 : if (p2p->cfg->prov_disc_fail)
969 8 : p2p->cfg->prov_disc_fail(
970 4 : p2p->cfg->cb_ctx, sa,
971 : P2P_PROV_DISC_INFO_UNAVAILABLE,
972 : adv_id, adv_mac, NULL);
973 73 : } else if (msg.wps_config_methods != dev->req_config_methods ||
974 : status != P2P_SC_SUCCESS) {
975 0 : p2p_dbg(p2p, "Peer rejected our Provision Discovery Request");
976 0 : if (p2p->cfg->prov_disc_fail)
977 0 : p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
978 : P2P_PROV_DISC_REJECTED, 0,
979 : NULL, NULL);
980 0 : p2p_parse_free(&msg);
981 0 : os_free(p2p->p2ps_prov);
982 0 : p2p->p2ps_prov = NULL;
983 0 : goto out;
984 : }
985 :
986 : /* Store the provisioning info */
987 77 : dev->wps_prov_info = msg.wps_config_methods;
988 :
989 77 : p2p_parse_free(&msg);
990 77 : success = 1;
991 :
992 : out:
993 78 : dev->req_config_methods = 0;
994 78 : p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
995 78 : if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
996 12 : p2p_dbg(p2p, "Start GO Neg after the PD-before-GO-Neg workaround with "
997 12 : MACSTR, MAC2STR(dev->info.p2p_device_addr));
998 2 : dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
999 2 : p2p_connect_send(p2p, dev);
1000 2 : return;
1001 : }
1002 76 : if (success && p2p->cfg->prov_disc_resp)
1003 75 : p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
1004 : report_config_methods);
1005 :
1006 76 : if (p2p->state == P2P_PD_DURING_FIND) {
1007 13 : p2p_clear_timeout(p2p);
1008 13 : p2p_continue_find(p2p);
1009 : }
1010 : }
1011 :
1012 :
1013 200 : int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
1014 : int join, int force_freq)
1015 : {
1016 : struct wpabuf *req;
1017 : int freq;
1018 :
1019 200 : if (force_freq > 0)
1020 48 : freq = force_freq;
1021 : else
1022 152 : freq = dev->listen_freq > 0 ? dev->listen_freq :
1023 : dev->oper_freq;
1024 200 : if (freq <= 0) {
1025 6 : p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
1026 : MACSTR " to send Provision Discovery Request",
1027 6 : MAC2STR(dev->info.p2p_device_addr));
1028 1 : return -1;
1029 : }
1030 :
1031 199 : if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
1032 0 : if (!(dev->info.dev_capab &
1033 : P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
1034 0 : p2p_dbg(p2p, "Cannot use PD with P2P Device " MACSTR
1035 : " that is in a group and is not discoverable",
1036 0 : MAC2STR(dev->info.p2p_device_addr));
1037 0 : return -1;
1038 : }
1039 : /* TODO: use device discoverability request through GO */
1040 : }
1041 :
1042 199 : if (p2p->p2ps_prov) {
1043 18 : if (p2p->p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED) {
1044 3 : if (p2p->p2ps_prov->method == WPS_CONFIG_DISPLAY)
1045 1 : dev->req_config_methods = WPS_CONFIG_KEYPAD;
1046 2 : else if (p2p->p2ps_prov->method == WPS_CONFIG_KEYPAD)
1047 1 : dev->req_config_methods = WPS_CONFIG_DISPLAY;
1048 : else
1049 1 : dev->req_config_methods = WPS_CONFIG_P2PS;
1050 : } else {
1051 : /* Order of preference, based on peer's capabilities */
1052 15 : if (p2p->p2ps_prov->method)
1053 15 : dev->req_config_methods =
1054 15 : p2p->p2ps_prov->method;
1055 0 : else if (dev->info.config_methods & WPS_CONFIG_P2PS)
1056 0 : dev->req_config_methods = WPS_CONFIG_P2PS;
1057 0 : else if (dev->info.config_methods & WPS_CONFIG_DISPLAY)
1058 0 : dev->req_config_methods = WPS_CONFIG_DISPLAY;
1059 : else
1060 0 : dev->req_config_methods = WPS_CONFIG_KEYPAD;
1061 : }
1062 54 : p2p_dbg(p2p,
1063 : "Building PD Request based on P2PS config method 0x%x status %d --> req_config_methods 0x%x",
1064 36 : p2p->p2ps_prov->method, p2p->p2ps_prov->status,
1065 18 : dev->req_config_methods);
1066 : }
1067 :
1068 199 : req = p2p_build_prov_disc_req(p2p, dev, join);
1069 199 : if (req == NULL)
1070 0 : return -1;
1071 :
1072 199 : if (p2p->state != P2P_IDLE)
1073 24 : p2p_stop_listen_for_freq(p2p, freq);
1074 199 : p2p->pending_action_state = P2P_PENDING_PD;
1075 398 : if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
1076 199 : p2p->cfg->dev_addr, dev->info.p2p_device_addr,
1077 199 : wpabuf_head(req), wpabuf_len(req), 200) < 0) {
1078 0 : p2p_dbg(p2p, "Failed to send Action frame");
1079 0 : wpabuf_free(req);
1080 0 : return -1;
1081 : }
1082 :
1083 199 : os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN);
1084 :
1085 199 : wpabuf_free(req);
1086 199 : return 0;
1087 : }
1088 :
1089 :
1090 88 : int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
1091 : struct p2ps_provision *p2ps_prov,
1092 : u16 config_methods, int join, int force_freq,
1093 : int user_initiated_pd)
1094 : {
1095 : struct p2p_device *dev;
1096 :
1097 88 : dev = p2p_get_device(p2p, peer_addr);
1098 88 : if (dev == NULL)
1099 7 : dev = p2p_get_device_interface(p2p, peer_addr);
1100 88 : if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
1101 42 : p2p_dbg(p2p, "Provision Discovery Request destination " MACSTR
1102 42 : " not yet known", MAC2STR(peer_addr));
1103 7 : os_free(p2ps_prov);
1104 7 : return -1;
1105 : }
1106 :
1107 567 : p2p_dbg(p2p, "Provision Discovery Request with " MACSTR
1108 : " (config methods 0x%x)",
1109 486 : MAC2STR(peer_addr), config_methods);
1110 81 : if (config_methods == 0 && !p2ps_prov) {
1111 1 : os_free(p2ps_prov);
1112 1 : return -1;
1113 : }
1114 :
1115 83 : if (p2ps_prov && p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED &&
1116 3 : p2p->p2ps_prov) {
1117 : /* Use cached method from deferred provisioning */
1118 3 : p2ps_prov->method = p2p->p2ps_prov->method;
1119 : }
1120 :
1121 : /* Reset provisioning info */
1122 80 : dev->wps_prov_info = 0;
1123 80 : os_free(p2p->p2ps_prov);
1124 80 : p2p->p2ps_prov = p2ps_prov;
1125 :
1126 80 : dev->req_config_methods = config_methods;
1127 80 : if (join)
1128 50 : dev->flags |= P2P_DEV_PD_FOR_JOIN;
1129 : else
1130 30 : dev->flags &= ~P2P_DEV_PD_FOR_JOIN;
1131 :
1132 86 : if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH &&
1133 6 : p2p->state != P2P_LISTEN_ONLY) {
1134 0 : p2p_dbg(p2p, "Busy with other operations; postpone Provision Discovery Request with "
1135 : MACSTR " (config methods 0x%x)",
1136 0 : MAC2STR(peer_addr), config_methods);
1137 0 : return 0;
1138 : }
1139 :
1140 80 : p2p->user_initiated_pd = user_initiated_pd;
1141 80 : p2p->pd_force_freq = force_freq;
1142 :
1143 80 : if (p2p->user_initiated_pd)
1144 76 : p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;
1145 :
1146 : /*
1147 : * Assign dialog token here to use the same value in each retry within
1148 : * the same PD exchange.
1149 : */
1150 80 : dev->dialog_token++;
1151 80 : if (dev->dialog_token == 0)
1152 0 : dev->dialog_token = 1;
1153 :
1154 80 : return p2p_send_prov_disc_req(p2p, dev, join, force_freq);
1155 : }
1156 :
1157 :
1158 1 : void p2p_reset_pending_pd(struct p2p_data *p2p)
1159 : {
1160 : struct p2p_device *dev;
1161 :
1162 2 : dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
1163 1 : if (os_memcmp(p2p->pending_pd_devaddr,
1164 : dev->info.p2p_device_addr, ETH_ALEN))
1165 0 : continue;
1166 1 : if (!dev->req_config_methods)
1167 0 : continue;
1168 1 : if (dev->flags & P2P_DEV_PD_FOR_JOIN)
1169 0 : continue;
1170 : /* Reset the config methods of the device */
1171 1 : dev->req_config_methods = 0;
1172 : }
1173 :
1174 1 : p2p->user_initiated_pd = 0;
1175 1 : os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
1176 1 : p2p->pd_retries = 0;
1177 1 : p2p->pd_force_freq = 0;
1178 1 : }
|