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 431 : static void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
27 : u16 config_methods)
28 : {
29 : u8 *len;
30 431 : wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
31 431 : len = wpabuf_put(buf, 1);
32 431 : wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
33 :
34 : /* Config Methods */
35 431 : wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
36 431 : wpabuf_put_be16(buf, 2);
37 431 : wpabuf_put_be16(buf, config_methods);
38 :
39 431 : p2p_buf_update_ie_hdr(buf, len);
40 431 : }
41 :
42 :
43 75 : static void p2ps_add_new_group_info(struct p2p_data *p2p,
44 : struct p2p_device *dev,
45 : struct wpabuf *buf)
46 : {
47 : int found;
48 : u8 intended_addr[ETH_ALEN];
49 : u8 ssid[SSID_MAX_LEN];
50 : size_t ssid_len;
51 : int group_iface;
52 : unsigned int force_freq;
53 :
54 75 : if (!p2p->cfg->get_go_info)
55 75 : return;
56 :
57 150 : found = p2p->cfg->get_go_info(
58 75 : p2p->cfg->cb_ctx, intended_addr, ssid,
59 : &ssid_len, &group_iface, &force_freq);
60 75 : if (found) {
61 5 : if (force_freq > 0) {
62 5 : p2p->p2ps_prov->force_freq = force_freq;
63 5 : p2p->p2ps_prov->pref_freq = 0;
64 :
65 5 : if (dev)
66 5 : p2p_prepare_channel(p2p, dev, force_freq, 0, 0);
67 : }
68 5 : p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
69 : ssid, ssid_len);
70 :
71 5 : if (group_iface)
72 0 : p2p_buf_add_intended_addr(buf, p2p->intended_addr);
73 : else
74 5 : p2p_buf_add_intended_addr(buf, intended_addr);
75 : } else {
76 70 : if (!p2p->ssid_set) {
77 52 : p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len);
78 52 : p2p->ssid_set = 1;
79 : }
80 :
81 : /* Add pre-composed P2P Group ID */
82 140 : p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
83 70 : p2p->ssid, p2p->ssid_len);
84 :
85 70 : if (group_iface)
86 19 : p2p_buf_add_intended_addr(
87 19 : buf, p2p->intended_addr);
88 : else
89 51 : p2p_buf_add_intended_addr(
90 51 : buf, p2p->cfg->dev_addr);
91 : }
92 : }
93 :
94 :
95 72 : static void p2ps_add_pd_req_attrs(struct p2p_data *p2p, struct p2p_device *dev,
96 : struct wpabuf *buf, u16 config_methods)
97 : {
98 72 : struct p2ps_provision *prov = p2p->p2ps_prov;
99 72 : struct p2ps_feature_capab fcap = { prov->cpt_mask, 0 };
100 72 : int shared_group = 0;
101 : u8 ssid[SSID_MAX_LEN];
102 : size_t ssid_len;
103 : u8 go_dev_addr[ETH_ALEN];
104 : u8 intended_addr[ETH_ALEN];
105 104 : int follow_on_req_fail = prov->status >= 0 &&
106 32 : prov->status != P2P_SC_SUCCESS_DEFERRED;
107 :
108 : /* If we might be explicite group owner, add GO details */
109 141 : if (!follow_on_req_fail &&
110 69 : (prov->conncap & (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW)))
111 68 : p2ps_add_new_group_info(p2p, dev, buf);
112 :
113 72 : if (prov->status >= 0)
114 32 : p2p_buf_add_status(buf, (u8) prov->status);
115 : else
116 40 : prov->method = config_methods;
117 :
118 72 : if (!follow_on_req_fail) {
119 69 : if (p2p->cfg->get_persistent_group) {
120 138 : shared_group = p2p->cfg->get_persistent_group(
121 69 : p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
122 : NULL, 0, go_dev_addr, ssid, &ssid_len,
123 : intended_addr);
124 : }
125 :
126 136 : if (shared_group ||
127 67 : (prov->conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_NEW)))
128 68 : p2p_buf_add_channel_list(buf, p2p->cfg->country,
129 : &p2p->channels);
130 :
131 138 : if ((shared_group && !is_zero_ether_addr(intended_addr)) ||
132 69 : (prov->conncap & (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW)))
133 136 : p2p_buf_add_operating_channel(buf, p2p->cfg->country,
134 68 : p2p->op_reg_class,
135 68 : p2p->op_channel);
136 : }
137 :
138 72 : if (prov->status < 0 && prov->info[0])
139 0 : p2p_buf_add_session_info(buf, prov->info);
140 :
141 72 : if (!follow_on_req_fail)
142 69 : p2p_buf_add_connection_capability(buf, prov->conncap);
143 :
144 72 : p2p_buf_add_advertisement_id(buf, prov->adv_id, prov->adv_mac);
145 :
146 72 : if (!follow_on_req_fail) {
147 71 : if (shared_group || prov->conncap == P2PS_SETUP_NEW ||
148 2 : prov->conncap ==
149 2 : (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW) ||
150 2 : prov->conncap ==
151 : (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT)) {
152 : /* Add Config Timeout */
153 67 : p2p_buf_add_config_timeout(buf, p2p->go_timeout,
154 67 : p2p->client_timeout);
155 : }
156 :
157 138 : p2p_buf_add_listen_channel(buf, p2p->cfg->country,
158 69 : p2p->cfg->reg_class,
159 69 : p2p->cfg->channel);
160 : }
161 :
162 72 : p2p_buf_add_session_id(buf, prov->session_id, prov->session_mac);
163 :
164 72 : p2p_buf_add_feature_capability(buf, sizeof(fcap), (const u8 *) &fcap);
165 :
166 72 : if (shared_group) {
167 2 : p2p_buf_add_persistent_group_info(buf, go_dev_addr,
168 : ssid, ssid_len);
169 : /* Add intended interface address if it is not added yet */
170 4 : if ((prov->conncap == P2PS_SETUP_NONE ||
171 2 : prov->conncap == P2PS_SETUP_CLIENT) &&
172 0 : !is_zero_ether_addr(intended_addr))
173 0 : p2p_buf_add_intended_addr(buf, intended_addr);
174 : }
175 72 : }
176 :
177 :
178 290 : static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
179 : struct p2p_device *dev,
180 : int join)
181 : {
182 : struct wpabuf *buf;
183 : u8 *len;
184 290 : size_t extra = 0;
185 290 : u8 dialog_token = dev->dialog_token;
186 290 : u16 config_methods = dev->req_config_methods;
187 290 : struct p2p_device *go = join ? dev : NULL;
188 : u8 group_capab;
189 :
190 : #ifdef CONFIG_WIFI_DISPLAY
191 290 : if (p2p->wfd_ie_prov_disc_req)
192 3 : extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
193 : #endif /* CONFIG_WIFI_DISPLAY */
194 :
195 290 : if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
196 1 : extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
197 :
198 290 : if (p2p->p2ps_prov)
199 72 : extra += os_strlen(p2p->p2ps_prov->info) + 1 +
200 : sizeof(struct p2ps_provision);
201 :
202 290 : buf = wpabuf_alloc(1000 + extra);
203 290 : if (buf == NULL)
204 0 : return NULL;
205 :
206 290 : p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token);
207 :
208 290 : len = p2p_buf_add_ie_hdr(buf);
209 :
210 290 : group_capab = 0;
211 290 : if (p2p->p2ps_prov) {
212 72 : group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
213 72 : group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
214 72 : if (p2p->cross_connect)
215 0 : group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
216 72 : if (p2p->cfg->p2p_intra_bss)
217 72 : group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
218 : }
219 290 : p2p_buf_add_capability(buf, p2p->dev_capab &
220 : ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
221 : group_capab);
222 290 : p2p_buf_add_device_info(buf, p2p, NULL);
223 290 : if (p2p->p2ps_prov) {
224 72 : p2ps_add_pd_req_attrs(p2p, dev, buf, config_methods);
225 218 : } else if (go) {
226 152 : p2p_buf_add_group_id(buf, go->info.p2p_device_addr,
227 76 : go->oper_ssid, go->oper_ssid_len);
228 : }
229 290 : p2p_buf_update_ie_hdr(buf, len);
230 :
231 : /* WPS IE with Config Methods attribute */
232 290 : p2p_build_wps_ie_config_methods(buf, config_methods);
233 :
234 : #ifdef CONFIG_WIFI_DISPLAY
235 290 : if (p2p->wfd_ie_prov_disc_req)
236 3 : wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
237 : #endif /* CONFIG_WIFI_DISPLAY */
238 :
239 290 : if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
240 1 : wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
241 :
242 290 : return buf;
243 : }
244 :
245 :
246 141 : static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
247 : struct p2p_device *dev,
248 : u8 dialog_token,
249 : enum p2p_status_code status,
250 : u16 config_methods,
251 : u32 adv_id,
252 : const u8 *group_id,
253 : size_t group_id_len,
254 : const u8 *persist_ssid,
255 : size_t persist_ssid_len,
256 : const u8 *fcap,
257 : u16 fcap_len)
258 : {
259 : struct wpabuf *buf;
260 141 : size_t extra = 0;
261 141 : int persist = 0;
262 :
263 : #ifdef CONFIG_WIFI_DISPLAY
264 141 : struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
265 141 : if (wfd_ie && group_id) {
266 : size_t i;
267 5 : for (i = 0; i < p2p->num_groups; i++) {
268 5 : struct p2p_group *g = p2p->groups[i];
269 : struct wpabuf *ie;
270 5 : if (!p2p_group_is_group_id_match(g, group_id,
271 : group_id_len))
272 0 : continue;
273 5 : ie = p2p_group_get_wfd_ie(g);
274 5 : if (ie) {
275 5 : wfd_ie = ie;
276 5 : break;
277 : }
278 : }
279 : }
280 141 : if (wfd_ie)
281 6 : extra = wpabuf_len(wfd_ie);
282 : #endif /* CONFIG_WIFI_DISPLAY */
283 :
284 141 : if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
285 1 : extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
286 :
287 141 : buf = wpabuf_alloc(1000 + extra);
288 141 : if (buf == NULL)
289 0 : return NULL;
290 :
291 141 : p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token);
292 :
293 : /* Add P2P IE for P2PS */
294 192 : if (p2p->p2ps_prov && p2p->p2ps_prov->adv_id == adv_id) {
295 51 : u8 *len = p2p_buf_add_ie_hdr(buf);
296 51 : struct p2ps_provision *prov = p2p->p2ps_prov;
297 : u8 group_capab;
298 51 : u8 conncap = 0;
299 :
300 51 : if (status == P2P_SC_SUCCESS ||
301 : status == P2P_SC_SUCCESS_DEFERRED)
302 39 : conncap = prov->conncap;
303 :
304 51 : if (!status && prov->status != -1)
305 39 : status = prov->status;
306 :
307 51 : p2p_buf_add_status(buf, status);
308 51 : group_capab = P2P_GROUP_CAPAB_PERSISTENT_GROUP |
309 : P2P_GROUP_CAPAB_PERSISTENT_RECONN;
310 51 : if (p2p->cross_connect)
311 0 : group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
312 51 : if (p2p->cfg->p2p_intra_bss)
313 51 : group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
314 51 : p2p_buf_add_capability(buf, p2p->dev_capab &
315 : ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
316 : group_capab);
317 51 : p2p_buf_add_device_info(buf, p2p, NULL);
318 :
319 51 : if (persist_ssid && p2p->cfg->get_persistent_group && dev &&
320 0 : (status == P2P_SC_SUCCESS ||
321 : status == P2P_SC_SUCCESS_DEFERRED)) {
322 : u8 ssid[SSID_MAX_LEN];
323 : size_t ssid_len;
324 : u8 go_dev_addr[ETH_ALEN];
325 : u8 intended_addr[ETH_ALEN];
326 :
327 4 : persist = p2p->cfg->get_persistent_group(
328 2 : p2p->cfg->cb_ctx,
329 2 : dev->info.p2p_device_addr,
330 : persist_ssid, persist_ssid_len, go_dev_addr,
331 : ssid, &ssid_len, intended_addr);
332 2 : if (persist) {
333 2 : p2p_buf_add_persistent_group_info(
334 : buf, go_dev_addr, ssid, ssid_len);
335 2 : if (!is_zero_ether_addr(intended_addr))
336 2 : p2p_buf_add_intended_addr(
337 : buf, intended_addr);
338 : }
339 : }
340 :
341 51 : if (!persist && (conncap & P2PS_SETUP_GROUP_OWNER))
342 7 : p2ps_add_new_group_info(p2p, dev, buf);
343 :
344 : /* Add Operating Channel if conncap indicates GO */
345 51 : if (persist || (conncap & P2PS_SETUP_GROUP_OWNER)) {
346 9 : if (p2p->op_reg_class && p2p->op_channel)
347 27 : p2p_buf_add_operating_channel(
348 9 : buf, p2p->cfg->country,
349 9 : p2p->op_reg_class,
350 9 : p2p->op_channel);
351 : else
352 0 : p2p_buf_add_operating_channel(
353 0 : buf, p2p->cfg->country,
354 0 : p2p->cfg->op_reg_class,
355 0 : p2p->cfg->op_channel);
356 : }
357 :
358 100 : if (persist ||
359 49 : (conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER)))
360 23 : p2p_buf_add_channel_list(buf, p2p->cfg->country,
361 : &p2p->channels);
362 :
363 51 : if (!persist && conncap)
364 37 : p2p_buf_add_connection_capability(buf, conncap);
365 :
366 51 : p2p_buf_add_advertisement_id(buf, adv_id, prov->adv_mac);
367 :
368 100 : if (persist ||
369 49 : (conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER)))
370 23 : p2p_buf_add_config_timeout(buf, p2p->go_timeout,
371 23 : p2p->client_timeout);
372 :
373 51 : p2p_buf_add_session_id(buf, prov->session_id,
374 51 : prov->session_mac);
375 :
376 51 : p2p_buf_add_feature_capability(buf, fcap_len, fcap);
377 51 : p2p_buf_update_ie_hdr(buf, len);
378 90 : } else if (status != P2P_SC_SUCCESS || adv_id) {
379 2 : u8 *len = p2p_buf_add_ie_hdr(buf);
380 :
381 2 : p2p_buf_add_status(buf, status);
382 :
383 2 : if (p2p->p2ps_prov)
384 0 : p2p_buf_add_advertisement_id(buf, adv_id,
385 0 : p2p->p2ps_prov->adv_mac);
386 :
387 2 : p2p_buf_update_ie_hdr(buf, len);
388 : }
389 :
390 : /* WPS IE with Config Methods attribute */
391 141 : p2p_build_wps_ie_config_methods(buf, config_methods);
392 :
393 : #ifdef CONFIG_WIFI_DISPLAY
394 141 : if (wfd_ie)
395 6 : wpabuf_put_buf(buf, wfd_ie);
396 : #endif /* CONFIG_WIFI_DISPLAY */
397 :
398 141 : if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
399 1 : wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
400 :
401 141 : return buf;
402 : }
403 :
404 :
405 40 : static int p2ps_setup_p2ps_prov(struct p2p_data *p2p, u32 adv_id,
406 : u32 session_id, u16 method,
407 : const u8 *session_mac, const u8 *adv_mac)
408 : {
409 : struct p2ps_provision *tmp;
410 :
411 40 : if (!p2p->p2ps_prov) {
412 19 : p2p->p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + 1);
413 19 : if (!p2p->p2ps_prov)
414 0 : return -1;
415 : } else {
416 21 : os_memset(p2p->p2ps_prov, 0, sizeof(struct p2ps_provision) + 1);
417 : }
418 :
419 40 : tmp = p2p->p2ps_prov;
420 40 : tmp->adv_id = adv_id;
421 40 : tmp->session_id = session_id;
422 40 : tmp->method = method;
423 40 : os_memcpy(tmp->session_mac, session_mac, ETH_ALEN);
424 40 : os_memcpy(tmp->adv_mac, adv_mac, ETH_ALEN);
425 40 : tmp->info[0] = '\0';
426 :
427 40 : return 0;
428 : }
429 :
430 :
431 51 : static u8 p2ps_own_preferred_cpt(const u8 *cpt_priority, u8 req_cpt_mask)
432 : {
433 : int i;
434 :
435 52 : for (i = 0; cpt_priority[i]; i++)
436 52 : if (req_cpt_mask & cpt_priority[i])
437 51 : return cpt_priority[i];
438 :
439 0 : return 0;
440 : }
441 :
442 :
443 : /* Check if the message contains a valid P2PS PD Request */
444 52 : static int p2ps_validate_pd_req(struct p2p_data *p2p, struct p2p_message *msg,
445 : const u8 *addr)
446 : {
447 52 : u8 group_id = 0;
448 52 : u8 intended_addr = 0;
449 52 : u8 operating_channel = 0;
450 52 : u8 channel_list = 0;
451 52 : u8 config_timeout = 0;
452 52 : u8 listen_channel = 0;
453 :
454 : #define P2PS_PD_REQ_CHECK(_val, _attr) \
455 : do { \
456 : if ((_val) && !msg->_attr) { \
457 : p2p_dbg(p2p, "Not P2PS PD Request. Missing %s", #_attr); \
458 : return -1; \
459 : } \
460 : } while (0)
461 :
462 52 : P2PS_PD_REQ_CHECK(1, adv_id);
463 52 : P2PS_PD_REQ_CHECK(1, session_id);
464 52 : P2PS_PD_REQ_CHECK(1, session_mac);
465 52 : P2PS_PD_REQ_CHECK(1, adv_mac);
466 52 : P2PS_PD_REQ_CHECK(1, capability);
467 52 : P2PS_PD_REQ_CHECK(1, p2p_device_info);
468 52 : P2PS_PD_REQ_CHECK(1, feature_cap);
469 :
470 : /*
471 : * We don't need to check Connection Capability, Persistent Group,
472 : * and related attributes for follow-on PD Request with a status
473 : * other than SUCCESS_DEFERRED.
474 : */
475 52 : if (msg->status && *msg->status != P2P_SC_SUCCESS_DEFERRED)
476 1 : return 0;
477 :
478 51 : P2PS_PD_REQ_CHECK(1, conn_cap);
479 :
480 : /*
481 : * Note 1: A feature capability attribute structure can be changed
482 : * in the future. The assumption is that such modifications are
483 : * backward compatible, therefore we allow processing of msg.feature_cap
484 : * exceeding the size of the p2ps_feature_capab structure.
485 : * Note 2: Verification of msg.feature_cap_len below has to be changed
486 : * to allow 2 byte feature capability processing if
487 : * struct p2ps_feature_capab is extended to include additional fields
488 : * and it affects the structure size.
489 : */
490 51 : if (msg->feature_cap_len < sizeof(struct p2ps_feature_capab)) {
491 0 : p2p_dbg(p2p, "P2PS: Invalid feature capability len");
492 0 : return -1;
493 : }
494 :
495 51 : switch (*msg->conn_cap) {
496 : case P2PS_SETUP_NEW:
497 49 : group_id = 1;
498 49 : intended_addr = 1;
499 49 : operating_channel = 1;
500 49 : channel_list = 1;
501 49 : config_timeout = 1;
502 49 : listen_channel = 1;
503 49 : break;
504 : case P2PS_SETUP_CLIENT:
505 1 : channel_list = 1;
506 1 : listen_channel = 1;
507 1 : break;
508 : case P2PS_SETUP_GROUP_OWNER:
509 1 : group_id = 1;
510 1 : intended_addr = 1;
511 1 : operating_channel = 1;
512 1 : break;
513 : case P2PS_SETUP_NEW | P2PS_SETUP_GROUP_OWNER:
514 0 : group_id = 1;
515 0 : operating_channel = 1;
516 0 : intended_addr = 1;
517 0 : channel_list = 1;
518 0 : config_timeout = 1;
519 0 : break;
520 : case P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER:
521 0 : group_id = 1;
522 0 : intended_addr = 1;
523 0 : operating_channel = 1;
524 0 : channel_list = 1;
525 0 : config_timeout = 1;
526 0 : break;
527 : default:
528 0 : p2p_dbg(p2p, "Invalid P2PS PD connection capability");
529 0 : return -1;
530 : }
531 :
532 51 : if (msg->persistent_dev) {
533 2 : channel_list = 1;
534 2 : config_timeout = 1;
535 2 : if (os_memcmp(msg->persistent_dev, addr, ETH_ALEN) == 0) {
536 0 : intended_addr = 1;
537 0 : operating_channel = 1;
538 : }
539 : }
540 :
541 51 : P2PS_PD_REQ_CHECK(group_id, group_id);
542 51 : P2PS_PD_REQ_CHECK(intended_addr, intended_addr);
543 51 : P2PS_PD_REQ_CHECK(operating_channel, operating_channel);
544 51 : P2PS_PD_REQ_CHECK(channel_list, channel_list);
545 51 : P2PS_PD_REQ_CHECK(config_timeout, config_timeout);
546 51 : P2PS_PD_REQ_CHECK(listen_channel, listen_channel);
547 :
548 : #undef P2PS_PD_REQ_CHECK
549 :
550 51 : return 0;
551 : }
552 :
553 :
554 143 : void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
555 : const u8 *data, size_t len, int rx_freq)
556 : {
557 : struct p2p_message msg;
558 : struct p2p_device *dev;
559 : int freq;
560 143 : enum p2p_status_code reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
561 : struct wpabuf *resp;
562 143 : u32 adv_id = 0;
563 143 : struct p2ps_advertisement *p2ps_adv = NULL;
564 143 : u8 conncap = P2PS_SETUP_NEW;
565 143 : u8 auto_accept = 0;
566 143 : u32 session_id = 0;
567 143 : u8 session_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
568 143 : u8 adv_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
569 : const u8 *group_mac;
570 143 : int passwd_id = DEV_PW_DEFAULT;
571 : u16 config_methods;
572 143 : u16 allowed_config_methods = WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
573 143 : struct p2ps_feature_capab resp_fcap = { 0, 0 };
574 143 : struct p2ps_feature_capab *req_fcap = NULL;
575 : u8 remote_conncap;
576 : u16 method;
577 :
578 143 : if (p2p_parse(data, len, &msg))
579 3 : return;
580 :
581 994 : p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR
582 : " with config methods 0x%x (freq=%d)",
583 994 : MAC2STR(sa), msg.wps_config_methods, rx_freq);
584 142 : group_mac = msg.intended_addr;
585 :
586 142 : dev = p2p_get_device(p2p, sa);
587 142 : if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
588 708 : p2p_dbg(p2p, "Provision Discovery Request from unknown peer "
589 708 : MACSTR, MAC2STR(sa));
590 :
591 118 : if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
592 : 0)) {
593 6 : p2p_dbg(p2p, "Provision Discovery Request add device failed "
594 6 : MACSTR, MAC2STR(sa));
595 1 : goto out;
596 : }
597 :
598 234 : if (!dev) {
599 3 : dev = p2p_get_device(p2p, sa);
600 3 : if (!dev) {
601 0 : p2p_dbg(p2p,
602 : "Provision Discovery device not found "
603 0 : MACSTR, MAC2STR(sa));
604 0 : goto out;
605 : }
606 : }
607 24 : } else if (msg.wfd_subelems) {
608 1 : wpabuf_free(dev->info.wfd_subelems);
609 1 : dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
610 : }
611 :
612 141 : if (!msg.adv_id) {
613 89 : allowed_config_methods |= WPS_CONFIG_PUSHBUTTON;
614 89 : if (!(msg.wps_config_methods & allowed_config_methods)) {
615 0 : p2p_dbg(p2p,
616 : "Unsupported Config Methods in Provision Discovery Request");
617 0 : goto out;
618 : }
619 :
620 : /* Legacy (non-P2PS) - Unknown groups allowed for P2PS */
621 89 : if (msg.group_id) {
622 : size_t i;
623 :
624 75 : for (i = 0; i < p2p->num_groups; i++) {
625 148 : if (p2p_group_is_group_id_match(
626 74 : p2p->groups[i],
627 : msg.group_id, msg.group_id_len))
628 74 : break;
629 : }
630 75 : if (i == p2p->num_groups) {
631 1 : p2p_dbg(p2p,
632 : "PD request for unknown P2P Group ID - reject");
633 1 : goto out;
634 : }
635 : }
636 : } else {
637 52 : allowed_config_methods |= WPS_CONFIG_P2PS;
638 :
639 : /*
640 : * Set adv_id here, so in case of an error, a P2PS PD Response
641 : * will be sent.
642 : */
643 52 : adv_id = WPA_GET_LE32(msg.adv_id);
644 52 : if (p2ps_validate_pd_req(p2p, &msg, sa) < 0) {
645 0 : reject = P2P_SC_FAIL_INVALID_PARAMS;
646 0 : goto out;
647 : }
648 :
649 52 : req_fcap = (struct p2ps_feature_capab *) msg.feature_cap;
650 :
651 52 : os_memcpy(session_mac, msg.session_mac, ETH_ALEN);
652 52 : os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
653 :
654 52 : session_id = WPA_GET_LE32(msg.session_id);
655 :
656 52 : if (msg.conn_cap)
657 51 : conncap = *msg.conn_cap;
658 :
659 : /*
660 : * We need to verify a P2PS config methog in an initial PD
661 : * request or in a follow-on PD request with the status
662 : * SUCCESS_DEFERRED.
663 : */
664 103 : if ((!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) &&
665 51 : !(msg.wps_config_methods & allowed_config_methods)) {
666 0 : p2p_dbg(p2p,
667 : "Unsupported Config Methods in Provision Discovery Request");
668 0 : goto out;
669 : }
670 :
671 : /*
672 : * TODO: since we don't support multiple PD, reject PD request
673 : * if we are in the middle of P2PS PD with some other peer
674 : */
675 : }
676 :
677 140 : dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
678 : P2P_DEV_PD_PEER_KEYPAD |
679 : P2P_DEV_PD_PEER_P2PS);
680 :
681 140 : if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
682 534 : p2p_dbg(p2p, "Peer " MACSTR
683 534 : " requested us to show a PIN on display", MAC2STR(sa));
684 89 : dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
685 89 : passwd_id = DEV_PW_USER_SPECIFIED;
686 51 : } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
687 54 : p2p_dbg(p2p, "Peer " MACSTR
688 : " requested us to write its PIN using keypad",
689 54 : MAC2STR(sa));
690 9 : dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
691 9 : passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
692 42 : } else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
693 198 : p2p_dbg(p2p, "Peer " MACSTR " requesting P2PS PIN",
694 198 : MAC2STR(sa));
695 33 : dev->flags |= P2P_DEV_PD_PEER_P2PS;
696 33 : passwd_id = DEV_PW_P2PS_DEFAULT;
697 : }
698 :
699 : /* Remove stale persistent groups */
700 140 : if (p2p->cfg->remove_stale_groups) {
701 280 : p2p->cfg->remove_stale_groups(
702 140 : p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
703 : msg.persistent_dev,
704 : msg.persistent_ssid, msg.persistent_ssid_len);
705 : }
706 :
707 140 : reject = P2P_SC_SUCCESS;
708 :
709 : /*
710 : * End of a legacy P2P PD Request processing, from this point continue
711 : * with P2PS one.
712 : */
713 140 : if (!msg.adv_id)
714 88 : goto out;
715 :
716 52 : remote_conncap = conncap;
717 :
718 52 : if (!msg.status) {
719 : unsigned int forced_freq, pref_freq;
720 :
721 40 : if (os_memcmp(p2p->cfg->dev_addr, msg.adv_mac, ETH_ALEN)) {
722 0 : p2p_dbg(p2p,
723 : "P2PS PD adv mac does not match the local one");
724 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
725 0 : goto out;
726 : }
727 :
728 40 : p2ps_adv = p2p_service_p2ps_id(p2p, adv_id);
729 40 : if (!p2ps_adv) {
730 0 : p2p_dbg(p2p, "P2PS PD invalid adv_id=0x%X", adv_id);
731 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
732 0 : goto out;
733 : }
734 40 : p2p_dbg(p2p, "adv_id: 0x%X, p2ps_adv: %p", adv_id, p2ps_adv);
735 :
736 40 : auto_accept = p2ps_adv->auto_accept;
737 40 : conncap = p2p->cfg->p2ps_group_capability(p2p->cfg->cb_ctx,
738 : conncap, auto_accept,
739 : &forced_freq,
740 : &pref_freq);
741 :
742 40 : p2p_dbg(p2p, "Conncap: local:%d remote:%d result:%d",
743 : auto_accept, remote_conncap, conncap);
744 :
745 40 : p2p_prepare_channel(p2p, dev, forced_freq, pref_freq, 0);
746 :
747 40 : resp_fcap.cpt = p2ps_own_preferred_cpt(p2ps_adv->cpt_priority,
748 40 : req_fcap->cpt);
749 :
750 120 : p2p_dbg(p2p, "cpt: service:0x%x remote:0x%x result:0x%x",
751 120 : p2ps_adv->cpt_mask, req_fcap->cpt, resp_fcap.cpt);
752 :
753 40 : if (!resp_fcap.cpt) {
754 0 : p2p_dbg(p2p,
755 : "Incompatible P2PS feature capability CPT bitmask");
756 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
757 80 : } else if (p2ps_adv->config_methods &&
758 80 : !(msg.wps_config_methods &
759 40 : p2ps_adv->config_methods)) {
760 0 : p2p_dbg(p2p,
761 : "Unsupported config methods in Provision Discovery Request (own=0x%x peer=0x%x)",
762 0 : p2ps_adv->config_methods,
763 0 : msg.wps_config_methods);
764 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
765 40 : } else if (!p2ps_adv->state) {
766 0 : p2p_dbg(p2p, "P2PS state unavailable");
767 0 : reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
768 40 : } else if (!conncap) {
769 0 : p2p_dbg(p2p, "Conncap resolution failed");
770 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
771 : }
772 :
773 40 : if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
774 2 : p2p_dbg(p2p, "Keypad - always defer");
775 2 : auto_accept = 0;
776 : }
777 :
778 41 : if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
779 65 : msg.persistent_dev) && conncap != P2PS_SETUP_NEW &&
780 75 : msg.channel_list && msg.channel_list_len &&
781 25 : p2p_peer_channels_check(p2p, &p2p->channels, dev,
782 : msg.channel_list,
783 25 : msg.channel_list_len) < 0) {
784 3 : p2p_dbg(p2p,
785 : "No common channels - force deferred flow");
786 3 : auto_accept = 0;
787 : }
788 :
789 79 : if (((remote_conncap & P2PS_SETUP_GROUP_OWNER) ||
790 42 : msg.persistent_dev) && msg.operating_channel) {
791 : struct p2p_channels intersect;
792 :
793 : /*
794 : * There are cases where only the operating channel is
795 : * provided. This requires saving the channel as the
796 : * supported channel list, and verifying that it is
797 : * supported.
798 : */
799 5 : if (dev->channels.reg_classes == 0 ||
800 4 : !p2p_channels_includes(&dev->channels,
801 2 : msg.operating_channel[3],
802 2 : msg.operating_channel[4])) {
803 1 : struct p2p_channels *ch = &dev->channels;
804 :
805 1 : os_memset(ch, 0, sizeof(*ch));
806 1 : ch->reg_class[0].reg_class =
807 1 : msg.operating_channel[3];
808 1 : ch->reg_class[0].channel[0] =
809 1 : msg.operating_channel[4];
810 1 : ch->reg_class[0].channels = 1;
811 1 : ch->reg_classes = 1;
812 : }
813 :
814 3 : p2p_channels_intersect(&p2p->channels, &dev->channels,
815 : &intersect);
816 :
817 3 : if (intersect.reg_classes == 0) {
818 1 : p2p_dbg(p2p,
819 : "No common channels - force deferred flow");
820 1 : auto_accept = 0;
821 : }
822 : }
823 :
824 40 : if (auto_accept || reject != P2P_SC_SUCCESS) {
825 : struct p2ps_provision *tmp;
826 :
827 28 : if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
828 28 : msg.wps_config_methods,
829 : session_mac, adv_mac) < 0) {
830 0 : reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
831 0 : goto out;
832 : }
833 :
834 28 : tmp = p2p->p2ps_prov;
835 28 : tmp->force_freq = forced_freq;
836 28 : tmp->pref_freq = pref_freq;
837 28 : if (conncap) {
838 28 : tmp->conncap = conncap;
839 28 : tmp->status = P2P_SC_SUCCESS;
840 : } else {
841 0 : tmp->conncap = auto_accept;
842 0 : tmp->status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
843 : }
844 :
845 28 : if (reject != P2P_SC_SUCCESS)
846 0 : goto out;
847 : }
848 : }
849 :
850 64 : if (!msg.status && !auto_accept &&
851 20 : (!p2p->p2ps_prov || p2p->p2ps_prov->adv_id != adv_id)) {
852 : struct p2ps_provision *tmp;
853 :
854 12 : if (!conncap) {
855 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
856 0 : goto out;
857 : }
858 :
859 12 : if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
860 12 : msg.wps_config_methods,
861 : session_mac, adv_mac) < 0) {
862 0 : reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
863 0 : goto out;
864 : }
865 12 : tmp = p2p->p2ps_prov;
866 12 : reject = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
867 12 : tmp->status = reject;
868 : }
869 :
870 : /* Not a P2PS Follow-on PD */
871 52 : if (!msg.status)
872 40 : goto out;
873 :
874 12 : if (*msg.status && *msg.status != P2P_SC_SUCCESS_DEFERRED) {
875 1 : reject = *msg.status;
876 1 : goto out;
877 : }
878 :
879 11 : if (*msg.status != P2P_SC_SUCCESS_DEFERRED || !p2p->p2ps_prov)
880 : goto out;
881 :
882 22 : if (p2p->p2ps_prov->adv_id != adv_id ||
883 11 : os_memcmp(p2p->p2ps_prov->adv_mac, msg.adv_mac, ETH_ALEN)) {
884 0 : p2p_dbg(p2p,
885 : "P2PS Follow-on PD with mismatch Advertisement ID/MAC");
886 0 : goto out;
887 : }
888 :
889 22 : if (p2p->p2ps_prov->session_id != session_id ||
890 11 : os_memcmp(p2p->p2ps_prov->session_mac, msg.session_mac, ETH_ALEN)) {
891 0 : p2p_dbg(p2p, "P2PS Follow-on PD with mismatch Session ID/MAC");
892 0 : goto out;
893 : }
894 :
895 11 : method = p2p->p2ps_prov->method;
896 :
897 44 : conncap = p2p->cfg->p2ps_group_capability(p2p->cfg->cb_ctx,
898 : remote_conncap,
899 11 : p2p->p2ps_prov->conncap,
900 11 : &p2p->p2ps_prov->force_freq,
901 11 : &p2p->p2ps_prov->pref_freq);
902 :
903 11 : resp_fcap.cpt = p2ps_own_preferred_cpt(p2p->p2ps_prov->cpt_priority,
904 11 : req_fcap->cpt);
905 :
906 33 : p2p_dbg(p2p, "cpt: local:0x%x remote:0x%x result:0x%x",
907 33 : p2p->p2ps_prov->cpt_mask, req_fcap->cpt, resp_fcap.cpt);
908 :
909 11 : p2p_prepare_channel(p2p, dev, p2p->p2ps_prov->force_freq,
910 11 : p2p->p2ps_prov->pref_freq, 0);
911 :
912 : /*
913 : * Ensure that if we asked for PIN originally, our method is consistent
914 : * with original request.
915 : */
916 11 : if (method & WPS_CONFIG_DISPLAY)
917 4 : method = WPS_CONFIG_KEYPAD;
918 7 : else if (method & WPS_CONFIG_KEYPAD)
919 2 : method = WPS_CONFIG_DISPLAY;
920 :
921 11 : if (!conncap || !(msg.wps_config_methods & method)) {
922 : /*
923 : * Reject this "Deferred Accept*
924 : * if incompatible conncap or method
925 : */
926 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
927 11 : } else if (!resp_fcap.cpt) {
928 0 : p2p_dbg(p2p,
929 : "Incompatible P2PS feature capability CPT bitmask");
930 0 : reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
931 11 : } else if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
932 12 : msg.persistent_dev) && conncap != P2PS_SETUP_NEW &&
933 3 : msg.channel_list && msg.channel_list_len &&
934 1 : p2p_peer_channels_check(p2p, &p2p->channels, dev,
935 : msg.channel_list,
936 1 : msg.channel_list_len) < 0) {
937 0 : p2p_dbg(p2p,
938 : "No common channels in Follow-On Provision Discovery Request");
939 0 : reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
940 : } else {
941 11 : reject = P2P_SC_SUCCESS;
942 : }
943 :
944 11 : dev->oper_freq = 0;
945 11 : if (reject == P2P_SC_SUCCESS || reject == P2P_SC_SUCCESS_DEFERRED) {
946 : u8 tmp;
947 :
948 11 : if (msg.operating_channel)
949 10 : dev->oper_freq =
950 10 : p2p_channel_to_freq(msg.operating_channel[3],
951 10 : msg.operating_channel[4]);
952 :
953 12 : if ((conncap & P2PS_SETUP_GROUP_OWNER) &&
954 1 : p2p_go_select_channel(p2p, dev, &tmp) < 0)
955 0 : reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
956 : }
957 :
958 11 : p2p->p2ps_prov->status = reject;
959 11 : p2p->p2ps_prov->conncap = conncap;
960 :
961 : out:
962 142 : if (reject == P2P_SC_SUCCESS ||
963 : reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
964 139 : config_methods = msg.wps_config_methods;
965 : else
966 3 : config_methods = 0;
967 :
968 : /*
969 : * Send PD Response for an initial PD Request or for follow-on
970 : * PD Request with P2P_SC_SUCCESS_DEFERRED status.
971 : */
972 142 : if (!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) {
973 141 : resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token,
974 : reject, config_methods, adv_id,
975 : msg.group_id, msg.group_id_len,
976 : msg.persistent_ssid,
977 : msg.persistent_ssid_len,
978 : (const u8 *) &resp_fcap,
979 : sizeof(resp_fcap));
980 141 : if (!resp) {
981 0 : p2p_parse_free(&msg);
982 0 : return;
983 : }
984 141 : p2p_dbg(p2p, "Sending Provision Discovery Response");
985 141 : if (rx_freq > 0)
986 141 : freq = rx_freq;
987 : else
988 0 : freq = p2p_channel_to_freq(p2p->cfg->reg_class,
989 0 : p2p->cfg->channel);
990 141 : if (freq < 0) {
991 0 : p2p_dbg(p2p, "Unknown regulatory class/channel");
992 0 : wpabuf_free(resp);
993 0 : p2p_parse_free(&msg);
994 0 : return;
995 : }
996 141 : p2p->pending_action_state = P2P_PENDING_PD_RESPONSE;
997 282 : if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
998 141 : p2p->cfg->dev_addr,
999 141 : wpabuf_head(resp), wpabuf_len(resp),
1000 : 50) < 0)
1001 0 : p2p_dbg(p2p, "Failed to send Action frame");
1002 : else
1003 141 : p2p->send_action_in_progress = 1;
1004 :
1005 141 : wpabuf_free(resp);
1006 : }
1007 :
1008 142 : if (!dev) {
1009 1 : p2p_parse_free(&msg);
1010 1 : return;
1011 : }
1012 :
1013 141 : freq = 0;
1014 141 : if (reject == P2P_SC_SUCCESS && conncap == P2PS_SETUP_GROUP_OWNER) {
1015 9 : freq = p2p_channel_to_freq(p2p->op_reg_class,
1016 9 : p2p->op_channel);
1017 9 : if (freq < 0)
1018 0 : freq = 0;
1019 : }
1020 :
1021 141 : if (!p2p->cfg->p2ps_prov_complete) {
1022 : /* Don't emit anything */
1023 153 : } else if (msg.status && *msg.status != P2P_SC_SUCCESS &&
1024 12 : *msg.status != P2P_SC_SUCCESS_DEFERRED) {
1025 1 : reject = *msg.status;
1026 1 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
1027 : sa, adv_mac, session_mac,
1028 : NULL, adv_id, session_id,
1029 : 0, 0, msg.persistent_ssid,
1030 : msg.persistent_ssid_len,
1031 : 0, 0, NULL, NULL, 0, freq,
1032 : NULL, 0);
1033 151 : } else if (msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
1034 11 : p2p->p2ps_prov) {
1035 11 : p2p->p2ps_prov->status = reject;
1036 11 : p2p->p2ps_prov->conncap = conncap;
1037 :
1038 22 : if (reject != P2P_SC_SUCCESS)
1039 0 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
1040 : sa, adv_mac, session_mac,
1041 : NULL, adv_id,
1042 : session_id, conncap, 0,
1043 : msg.persistent_ssid,
1044 : msg.persistent_ssid_len, 0,
1045 : 0, NULL, NULL, 0, freq,
1046 : NULL, 0);
1047 : else
1048 22 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx,
1049 11 : *msg.status,
1050 : sa, adv_mac, session_mac,
1051 : group_mac, adv_id,
1052 : session_id, conncap,
1053 : passwd_id,
1054 : msg.persistent_ssid,
1055 : msg.persistent_ssid_len, 0,
1056 : 0, NULL,
1057 : (const u8 *) &resp_fcap,
1058 : sizeof(resp_fcap), freq,
1059 : NULL, 0);
1060 129 : } else if (msg.status && p2p->p2ps_prov) {
1061 0 : p2p->p2ps_prov->status = P2P_SC_SUCCESS;
1062 0 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, *msg.status, sa,
1063 : adv_mac, session_mac, group_mac,
1064 : adv_id, session_id, conncap,
1065 : passwd_id,
1066 : msg.persistent_ssid,
1067 : msg.persistent_ssid_len,
1068 : 0, 0, NULL,
1069 : (const u8 *) &resp_fcap,
1070 : sizeof(resp_fcap), freq, NULL, 0);
1071 129 : } else if (msg.status) {
1072 129 : } else if (auto_accept && reject == P2P_SC_SUCCESS) {
1073 140 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
1074 : sa, adv_mac, session_mac,
1075 : group_mac, adv_id, session_id,
1076 : conncap, passwd_id,
1077 : msg.persistent_ssid,
1078 : msg.persistent_ssid_len,
1079 : 0, 0, NULL,
1080 : (const u8 *) &resp_fcap,
1081 : sizeof(resp_fcap), freq,
1082 28 : msg.group_id ?
1083 28 : msg.group_id + ETH_ALEN : NULL,
1084 28 : msg.group_id ?
1085 28 : msg.group_id_len - ETH_ALEN : 0);
1086 113 : } else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
1087 12 : (!msg.session_info || !msg.session_info_len)) {
1088 12 : p2p->p2ps_prov->method = msg.wps_config_methods;
1089 :
1090 12 : p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
1091 : sa, adv_mac, session_mac,
1092 : group_mac, adv_id, session_id,
1093 : conncap, passwd_id,
1094 : msg.persistent_ssid,
1095 : msg.persistent_ssid_len,
1096 : 0, 1, NULL,
1097 : (const u8 *) &resp_fcap,
1098 : sizeof(resp_fcap), freq, NULL, 0);
1099 89 : } else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
1100 0 : size_t buf_len = msg.session_info_len;
1101 0 : char *buf = os_malloc(2 * buf_len + 1);
1102 :
1103 0 : if (buf) {
1104 0 : p2p->p2ps_prov->method = msg.wps_config_methods;
1105 :
1106 0 : utf8_escape((char *) msg.session_info, buf_len,
1107 0 : buf, 2 * buf_len + 1);
1108 :
1109 0 : p2p->cfg->p2ps_prov_complete(
1110 0 : p2p->cfg->cb_ctx, P2P_SC_SUCCESS, sa,
1111 : adv_mac, session_mac, group_mac, adv_id,
1112 : session_id, conncap, passwd_id,
1113 : msg.persistent_ssid, msg.persistent_ssid_len,
1114 : 0, 1, buf,
1115 : (const u8 *) &resp_fcap, sizeof(resp_fcap),
1116 : freq, NULL, 0);
1117 :
1118 0 : os_free(buf);
1119 : }
1120 : }
1121 :
1122 : /*
1123 : * prov_disc_req callback is used to generate P2P-PROV-DISC-ENTER-PIN,
1124 : * P2P-PROV-DISC-SHOW-PIN, and P2P-PROV-DISC-PBC-REQ events.
1125 : * Call it either on legacy P2P PD or on P2PS PD only if we need to
1126 : * enter/show PIN.
1127 : *
1128 : * The callback is called in the following cases:
1129 : * 1. Legacy P2P PD request, response status SUCCESS
1130 : * 2. P2PS advertiser, method: DISPLAY, autoaccept: TRUE,
1131 : * response status: SUCCESS
1132 : * 3. P2PS advertiser, method DISPLAY, autoaccept: FALSE,
1133 : * response status: INFO_CURRENTLY_UNAVAILABLE
1134 : * 4. P2PS advertiser, method: KEYPAD, autoaccept==any,
1135 : * response status: INFO_CURRENTLY_UNAVAILABLE
1136 : * 5. P2PS follow-on with SUCCESS_DEFERRED,
1137 : * advertiser role: DISPLAY, autoaccept: FALSE,
1138 : * seeker: KEYPAD, response status: SUCCESS
1139 : */
1140 141 : if (p2p->cfg->prov_disc_req &&
1141 180 : ((reject == P2P_SC_SUCCESS && !msg.adv_id) ||
1142 94 : (!msg.status &&
1143 13 : (reject == P2P_SC_SUCCESS ||
1144 40 : reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) &&
1145 42 : passwd_id == DEV_PW_USER_SPECIFIED) ||
1146 72 : (!msg.status &&
1147 8 : reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
1148 40 : passwd_id == DEV_PW_REGISTRAR_SPECIFIED) ||
1149 32 : (reject == P2P_SC_SUCCESS &&
1150 43 : msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
1151 : passwd_id == DEV_PW_REGISTRAR_SPECIFIED))) {
1152 105 : const u8 *dev_addr = sa;
1153 :
1154 105 : if (msg.p2p_device_addr)
1155 105 : dev_addr = msg.p2p_device_addr;
1156 735 : p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa,
1157 105 : msg.wps_config_methods,
1158 : dev_addr, msg.pri_dev_type,
1159 105 : msg.device_name, msg.config_methods,
1160 210 : msg.capability ? msg.capability[0] : 0,
1161 210 : msg.capability ? msg.capability[1] :
1162 : 0,
1163 : msg.group_id, msg.group_id_len);
1164 : }
1165 :
1166 141 : if (reject == P2P_SC_SUCCESS) {
1167 127 : switch (config_methods) {
1168 : case WPS_CONFIG_DISPLAY:
1169 83 : dev->wps_prov_info = WPS_CONFIG_KEYPAD;
1170 83 : break;
1171 : case WPS_CONFIG_KEYPAD:
1172 7 : dev->wps_prov_info = WPS_CONFIG_DISPLAY;
1173 7 : break;
1174 : case WPS_CONFIG_PUSHBUTTON:
1175 9 : dev->wps_prov_info = WPS_CONFIG_PUSHBUTTON;
1176 9 : break;
1177 : case WPS_CONFIG_P2PS:
1178 26 : dev->wps_prov_info = WPS_CONFIG_P2PS;
1179 26 : break;
1180 : default:
1181 2 : dev->wps_prov_info = 0;
1182 2 : break;
1183 : }
1184 :
1185 127 : if (msg.intended_addr)
1186 38 : os_memcpy(dev->interface_addr, msg.intended_addr,
1187 : ETH_ALEN);
1188 : }
1189 141 : p2p_parse_free(&msg);
1190 : }
1191 :
1192 :
1193 51 : static int p2p_validate_p2ps_pd_resp(struct p2p_data *p2p,
1194 : struct p2p_message *msg)
1195 : {
1196 51 : u8 conn_cap_go = 0;
1197 51 : u8 conn_cap_cli = 0;
1198 : u32 session_id;
1199 : u32 adv_id;
1200 :
1201 : #define P2PS_PD_RESP_CHECK(_val, _attr) \
1202 : do { \
1203 : if ((_val) && !msg->_attr) { \
1204 : p2p_dbg(p2p, "P2PS PD Response missing " #_attr); \
1205 : return -1; \
1206 : } \
1207 : } while (0)
1208 :
1209 51 : P2PS_PD_RESP_CHECK(1, status);
1210 51 : P2PS_PD_RESP_CHECK(1, adv_id);
1211 51 : P2PS_PD_RESP_CHECK(1, adv_mac);
1212 51 : P2PS_PD_RESP_CHECK(1, capability);
1213 51 : P2PS_PD_RESP_CHECK(1, p2p_device_info);
1214 51 : P2PS_PD_RESP_CHECK(1, session_id);
1215 51 : P2PS_PD_RESP_CHECK(1, session_mac);
1216 51 : P2PS_PD_RESP_CHECK(1, feature_cap);
1217 :
1218 51 : session_id = WPA_GET_LE32(msg->session_id);
1219 51 : adv_id = WPA_GET_LE32(msg->adv_id);
1220 :
1221 51 : if (p2p->p2ps_prov->session_id != session_id) {
1222 0 : p2p_dbg(p2p,
1223 : "Ignore PD Response with unexpected Session ID");
1224 0 : return -1;
1225 : }
1226 :
1227 51 : if (os_memcmp(p2p->p2ps_prov->session_mac, msg->session_mac,
1228 : ETH_ALEN)) {
1229 0 : p2p_dbg(p2p,
1230 : "Ignore PD Response with unexpected Session MAC");
1231 0 : return -1;
1232 : }
1233 :
1234 51 : if (p2p->p2ps_prov->adv_id != adv_id) {
1235 0 : p2p_dbg(p2p,
1236 : "Ignore PD Response with unexpected Advertisement ID");
1237 0 : return -1;
1238 : }
1239 :
1240 51 : if (os_memcmp(p2p->p2ps_prov->adv_mac, msg->adv_mac, ETH_ALEN) != 0) {
1241 0 : p2p_dbg(p2p,
1242 : "Ignore PD Response with unexpected Advertisement MAC");
1243 0 : return -1;
1244 : }
1245 :
1246 51 : if (msg->listen_channel) {
1247 0 : p2p_dbg(p2p,
1248 : "Ignore malformed PD Response - unexpected Listen Channel");
1249 0 : return -1;
1250 : }
1251 :
1252 90 : if (*msg->status == P2P_SC_SUCCESS &&
1253 39 : !(!!msg->conn_cap ^ !!msg->persistent_dev)) {
1254 0 : p2p_dbg(p2p,
1255 : "Ignore malformed PD Response - either conn_cap or persistent group should be present");
1256 0 : return -1;
1257 : }
1258 :
1259 51 : if (msg->persistent_dev && *msg->status != P2P_SC_SUCCESS) {
1260 0 : p2p_dbg(p2p,
1261 : "Ignore malformed PD Response - persistent group is present, but the status isn't success");
1262 0 : return -1;
1263 : }
1264 :
1265 51 : if (msg->conn_cap) {
1266 37 : conn_cap_go = *msg->conn_cap == P2PS_SETUP_GROUP_OWNER;
1267 37 : conn_cap_cli = *msg->conn_cap == P2PS_SETUP_CLIENT;
1268 : }
1269 :
1270 51 : P2PS_PD_RESP_CHECK(msg->persistent_dev || conn_cap_go || conn_cap_cli,
1271 : channel_list);
1272 51 : P2PS_PD_RESP_CHECK(msg->persistent_dev || conn_cap_go || conn_cap_cli,
1273 : config_timeout);
1274 :
1275 51 : P2PS_PD_RESP_CHECK(conn_cap_go, group_id);
1276 51 : P2PS_PD_RESP_CHECK(conn_cap_go, intended_addr);
1277 51 : P2PS_PD_RESP_CHECK(conn_cap_go, operating_channel);
1278 : /*
1279 : * TODO: Also validate that operating channel is present if the device
1280 : * is a GO in a persistent group. We can't do it here since we don't
1281 : * know what is the role of the peer. It should be probably done in
1282 : * p2ps_prov_complete callback, but currently operating channel isn't
1283 : * passed to it.
1284 : */
1285 :
1286 : #undef P2PS_PD_RESP_CHECK
1287 :
1288 51 : return 0;
1289 : }
1290 :
1291 :
1292 140 : void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
1293 : const u8 *data, size_t len)
1294 : {
1295 : struct p2p_message msg;
1296 : struct p2p_device *dev;
1297 140 : u16 report_config_methods = 0, req_config_methods;
1298 140 : u8 status = P2P_SC_SUCCESS;
1299 140 : u32 adv_id = 0;
1300 140 : u8 conncap = P2PS_SETUP_NEW;
1301 : u8 adv_mac[ETH_ALEN];
1302 : const u8 *group_mac;
1303 140 : int passwd_id = DEV_PW_DEFAULT;
1304 : int p2ps_seeker;
1305 :
1306 140 : if (p2p_parse(data, len, &msg))
1307 4 : return;
1308 :
1309 140 : if (p2p->p2ps_prov && p2p_validate_p2ps_pd_resp(p2p, &msg)) {
1310 0 : p2p_parse_free(&msg);
1311 0 : return;
1312 : }
1313 :
1314 : /* Parse the P2PS members present */
1315 140 : if (msg.status)
1316 51 : status = *msg.status;
1317 :
1318 140 : group_mac = msg.intended_addr;
1319 :
1320 140 : if (msg.adv_mac)
1321 51 : os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
1322 : else
1323 89 : os_memset(adv_mac, 0, ETH_ALEN);
1324 :
1325 140 : if (msg.adv_id)
1326 51 : adv_id = WPA_GET_LE32(msg.adv_id);
1327 :
1328 140 : if (msg.conn_cap) {
1329 37 : conncap = *msg.conn_cap;
1330 :
1331 : /* Switch bits to local relative */
1332 37 : switch (conncap) {
1333 : case P2PS_SETUP_GROUP_OWNER:
1334 7 : conncap = P2PS_SETUP_CLIENT;
1335 7 : break;
1336 : case P2PS_SETUP_CLIENT:
1337 14 : conncap = P2PS_SETUP_GROUP_OWNER;
1338 14 : break;
1339 : }
1340 : }
1341 :
1342 980 : p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR
1343 : " with config methods 0x%x",
1344 980 : MAC2STR(sa), msg.wps_config_methods);
1345 :
1346 140 : dev = p2p_get_device(p2p, sa);
1347 140 : if (dev == NULL || !dev->req_config_methods) {
1348 6 : p2p_dbg(p2p, "Ignore Provision Discovery Response from " MACSTR
1349 6 : " with no pending request", MAC2STR(sa));
1350 1 : p2p_parse_free(&msg);
1351 1 : return;
1352 139 : } else if (msg.wfd_subelems) {
1353 6 : wpabuf_free(dev->info.wfd_subelems);
1354 6 : dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
1355 : }
1356 :
1357 139 : if (dev->dialog_token != msg.dialog_token) {
1358 2 : p2p_dbg(p2p, "Ignore Provision Discovery Response with unexpected Dialog Token %u (expected %u)",
1359 2 : msg.dialog_token, dev->dialog_token);
1360 1 : p2p_parse_free(&msg);
1361 1 : return;
1362 : }
1363 :
1364 138 : if (p2p->pending_action_state == P2P_PENDING_PD) {
1365 133 : os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
1366 133 : p2p->pending_action_state = P2P_NO_PENDING_ACTION;
1367 : }
1368 :
1369 138 : p2ps_seeker = p2p->p2ps_prov && p2p->p2ps_prov->pd_seeker;
1370 :
1371 : /*
1372 : * Use a local copy of the requested config methods since
1373 : * p2p_reset_pending_pd() can clear this in the peer entry.
1374 : */
1375 138 : req_config_methods = dev->req_config_methods;
1376 :
1377 : /*
1378 : * If the response is from the peer to whom a user initiated request
1379 : * was sent earlier, we reset that state info here.
1380 : */
1381 271 : if (p2p->user_initiated_pd &&
1382 133 : os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0)
1383 0 : p2p_reset_pending_pd(p2p);
1384 :
1385 138 : if (msg.wps_config_methods != req_config_methods) {
1386 2 : p2p_dbg(p2p, "Peer rejected our Provision Discovery Request (received config_methods 0x%x expected 0x%x",
1387 1 : msg.wps_config_methods, req_config_methods);
1388 1 : if (p2p->cfg->prov_disc_fail)
1389 1 : p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
1390 : P2P_PROV_DISC_REJECTED,
1391 : adv_id, adv_mac, NULL);
1392 1 : p2p_parse_free(&msg);
1393 1 : p2ps_prov_free(p2p);
1394 1 : goto out;
1395 : }
1396 :
1397 137 : report_config_methods = req_config_methods;
1398 137 : dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
1399 : P2P_DEV_PD_PEER_KEYPAD |
1400 : P2P_DEV_PD_PEER_P2PS);
1401 137 : if (req_config_methods & WPS_CONFIG_DISPLAY) {
1402 522 : p2p_dbg(p2p, "Peer " MACSTR
1403 522 : " accepted to show a PIN on display", MAC2STR(sa));
1404 87 : dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
1405 87 : passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
1406 50 : } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
1407 54 : p2p_dbg(p2p, "Peer " MACSTR
1408 : " accepted to write our PIN using keypad",
1409 54 : MAC2STR(sa));
1410 9 : dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
1411 9 : passwd_id = DEV_PW_USER_SPECIFIED;
1412 41 : } else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
1413 192 : p2p_dbg(p2p, "Peer " MACSTR " accepted P2PS PIN",
1414 192 : MAC2STR(sa));
1415 32 : dev->flags |= P2P_DEV_PD_PEER_P2PS;
1416 32 : passwd_id = DEV_PW_P2PS_DEFAULT;
1417 : }
1418 :
1419 262 : if ((status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
1420 125 : p2p->p2ps_prov) {
1421 39 : dev->oper_freq = 0;
1422 :
1423 : /*
1424 : * Save the reported channel list and operating frequency.
1425 : * Note that the specification mandates that the responder
1426 : * should include in the channel list only channels reported by
1427 : * the initiator, so this is only a sanity check, and if this
1428 : * fails the flow would continue, although it would probably
1429 : * fail. Same is true for the operating channel.
1430 : */
1431 62 : if (msg.channel_list && msg.channel_list_len &&
1432 23 : p2p_peer_channels_check(p2p, &p2p->channels, dev,
1433 : msg.channel_list,
1434 23 : msg.channel_list_len) < 0)
1435 0 : p2p_dbg(p2p, "P2PS PD Response - no common channels");
1436 :
1437 39 : if (msg.operating_channel) {
1438 18 : if (p2p_channels_includes(&p2p->channels,
1439 9 : msg.operating_channel[3],
1440 18 : msg.operating_channel[4]) &&
1441 18 : p2p_channels_includes(&dev->channels,
1442 9 : msg.operating_channel[3],
1443 9 : msg.operating_channel[4])) {
1444 9 : dev->oper_freq =
1445 18 : p2p_channel_to_freq(
1446 9 : msg.operating_channel[3],
1447 9 : msg.operating_channel[4]);
1448 : } else {
1449 0 : p2p_dbg(p2p,
1450 : "P2PS PD Response - invalid operating channel");
1451 : }
1452 : }
1453 :
1454 39 : if (p2p->cfg->p2ps_prov_complete) {
1455 39 : int freq = 0;
1456 :
1457 39 : if (conncap == P2PS_SETUP_GROUP_OWNER) {
1458 : u8 tmp;
1459 :
1460 : /*
1461 : * Re-select the operating channel as it is
1462 : * possible that original channel is no longer
1463 : * valid. This should not really fail.
1464 : */
1465 14 : if (p2p_go_select_channel(p2p, dev, &tmp) < 0)
1466 0 : p2p_dbg(p2p,
1467 : "P2PS PD channel selection failed");
1468 :
1469 14 : freq = p2p_channel_to_freq(p2p->op_reg_class,
1470 14 : p2p->op_channel);
1471 14 : if (freq < 0)
1472 0 : freq = 0;
1473 : }
1474 :
1475 248 : p2p->cfg->p2ps_prov_complete(
1476 39 : p2p->cfg->cb_ctx, status, sa, adv_mac,
1477 39 : p2p->p2ps_prov->session_mac,
1478 39 : group_mac, adv_id, p2p->p2ps_prov->session_id,
1479 : conncap, passwd_id, msg.persistent_ssid,
1480 : msg.persistent_ssid_len, 1, 0, NULL,
1481 : msg.feature_cap, msg.feature_cap_len, freq,
1482 46 : msg.group_id ? msg.group_id + ETH_ALEN : NULL,
1483 46 : msg.group_id ? msg.group_id_len - ETH_ALEN : 0);
1484 : }
1485 39 : p2ps_prov_free(p2p);
1486 98 : } else if (status != P2P_SC_SUCCESS &&
1487 0 : status != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
1488 0 : status != P2P_SC_SUCCESS_DEFERRED && p2p->p2ps_prov) {
1489 0 : if (p2p->cfg->p2ps_prov_complete)
1490 0 : p2p->cfg->p2ps_prov_complete(
1491 0 : p2p->cfg->cb_ctx, status, sa, adv_mac,
1492 0 : p2p->p2ps_prov->session_mac,
1493 0 : group_mac, adv_id, p2p->p2ps_prov->session_id,
1494 : 0, 0, NULL, 0, 1, 0, NULL, NULL, 0, 0, NULL, 0);
1495 0 : p2ps_prov_free(p2p);
1496 : }
1497 :
1498 137 : if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
1499 12 : if (p2p->cfg->remove_stale_groups) {
1500 24 : p2p->cfg->remove_stale_groups(p2p->cfg->cb_ctx,
1501 12 : dev->info.p2p_device_addr,
1502 : NULL, NULL, 0);
1503 : }
1504 :
1505 12 : if (msg.session_info && msg.session_info_len) {
1506 0 : size_t info_len = msg.session_info_len;
1507 0 : char *deferred_sess_resp = os_malloc(2 * info_len + 1);
1508 :
1509 0 : if (!deferred_sess_resp) {
1510 0 : p2p_parse_free(&msg);
1511 0 : p2ps_prov_free(p2p);
1512 0 : goto out;
1513 : }
1514 0 : utf8_escape((char *) msg.session_info, info_len,
1515 0 : deferred_sess_resp, 2 * info_len + 1);
1516 :
1517 0 : if (p2p->cfg->prov_disc_fail)
1518 0 : p2p->cfg->prov_disc_fail(
1519 0 : p2p->cfg->cb_ctx, sa,
1520 : P2P_PROV_DISC_INFO_UNAVAILABLE,
1521 : adv_id, adv_mac,
1522 : deferred_sess_resp);
1523 0 : os_free(deferred_sess_resp);
1524 : } else
1525 12 : if (p2p->cfg->prov_disc_fail)
1526 24 : p2p->cfg->prov_disc_fail(
1527 12 : p2p->cfg->cb_ctx, sa,
1528 : P2P_PROV_DISC_INFO_UNAVAILABLE,
1529 : adv_id, adv_mac, NULL);
1530 125 : } else if (status != P2P_SC_SUCCESS) {
1531 0 : p2p_dbg(p2p, "Peer rejected our Provision Discovery Request");
1532 0 : if (p2p->cfg->prov_disc_fail)
1533 0 : p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
1534 : P2P_PROV_DISC_REJECTED,
1535 : adv_id, adv_mac, NULL);
1536 0 : p2p_parse_free(&msg);
1537 0 : p2ps_prov_free(p2p);
1538 0 : goto out;
1539 : }
1540 :
1541 : /* Store the provisioning info */
1542 137 : dev->wps_prov_info = msg.wps_config_methods;
1543 137 : if (msg.intended_addr)
1544 9 : os_memcpy(dev->interface_addr, msg.intended_addr, ETH_ALEN);
1545 :
1546 137 : p2p_parse_free(&msg);
1547 :
1548 : out:
1549 138 : dev->req_config_methods = 0;
1550 138 : p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
1551 138 : if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
1552 12 : p2p_dbg(p2p, "Start GO Neg after the PD-before-GO-Neg workaround with "
1553 12 : MACSTR, MAC2STR(dev->info.p2p_device_addr));
1554 2 : dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
1555 2 : p2p_connect_send(p2p, dev);
1556 2 : return;
1557 : }
1558 :
1559 : /*
1560 : * prov_disc_resp callback is used to generate P2P-PROV-DISC-ENTER-PIN,
1561 : * P2P-PROV-DISC-SHOW-PIN, and P2P-PROV-DISC-PBC-REQ events.
1562 : * Call it only for a legacy P2P PD or for P2PS PD scenarios where
1563 : * show/enter PIN events are needed.
1564 : *
1565 : * The callback is called in the following cases:
1566 : * 1. Legacy P2P PD response with a status SUCCESS
1567 : * 2. P2PS, advertiser method: DISPLAY, autoaccept: true,
1568 : * response status: SUCCESS, local method KEYPAD
1569 : * 3. P2PS, advertiser method: KEYPAD,Seeker side,
1570 : * response status: INFO_CURRENTLY_UNAVAILABLE,
1571 : * local method: DISPLAY
1572 : */
1573 136 : if (p2p->cfg->prov_disc_resp &&
1574 124 : ((status == P2P_SC_SUCCESS && !adv_id) ||
1575 40 : (p2ps_seeker && status == P2P_SC_SUCCESS &&
1576 44 : passwd_id == DEV_PW_REGISTRAR_SPECIFIED) ||
1577 33 : (p2ps_seeker &&
1578 12 : status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
1579 : passwd_id == DEV_PW_USER_SPECIFIED)))
1580 94 : p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
1581 : report_config_methods);
1582 :
1583 136 : if (p2p->state == P2P_PD_DURING_FIND) {
1584 4 : p2p_clear_timeout(p2p);
1585 4 : p2p_continue_find(p2p);
1586 : }
1587 : }
1588 :
1589 :
1590 291 : int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
1591 : int join, int force_freq)
1592 : {
1593 : struct wpabuf *req;
1594 : int freq;
1595 :
1596 291 : if (force_freq > 0)
1597 74 : freq = force_freq;
1598 : else
1599 217 : freq = dev->listen_freq > 0 ? dev->listen_freq :
1600 : dev->oper_freq;
1601 291 : if (freq <= 0) {
1602 6 : p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
1603 : MACSTR " to send Provision Discovery Request",
1604 6 : MAC2STR(dev->info.p2p_device_addr));
1605 1 : return -1;
1606 : }
1607 :
1608 290 : if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
1609 0 : if (!(dev->info.dev_capab &
1610 : P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
1611 0 : p2p_dbg(p2p, "Cannot use PD with P2P Device " MACSTR
1612 : " that is in a group and is not discoverable",
1613 0 : MAC2STR(dev->info.p2p_device_addr));
1614 0 : return -1;
1615 : }
1616 : /* TODO: use device discoverability request through GO */
1617 : }
1618 :
1619 290 : if (p2p->p2ps_prov) {
1620 72 : if (p2p->p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED) {
1621 29 : if (p2p->p2ps_prov->method == WPS_CONFIG_DISPLAY)
1622 12 : dev->req_config_methods = WPS_CONFIG_KEYPAD;
1623 17 : else if (p2p->p2ps_prov->method == WPS_CONFIG_KEYPAD)
1624 6 : dev->req_config_methods = WPS_CONFIG_DISPLAY;
1625 : else
1626 11 : dev->req_config_methods = WPS_CONFIG_P2PS;
1627 : } else {
1628 : /* Order of preference, based on peer's capabilities */
1629 43 : if (p2p->p2ps_prov->method)
1630 40 : dev->req_config_methods =
1631 40 : p2p->p2ps_prov->method;
1632 3 : else if (dev->info.config_methods & WPS_CONFIG_P2PS)
1633 3 : dev->req_config_methods = WPS_CONFIG_P2PS;
1634 0 : else if (dev->info.config_methods & WPS_CONFIG_DISPLAY)
1635 0 : dev->req_config_methods = WPS_CONFIG_DISPLAY;
1636 : else
1637 0 : dev->req_config_methods = WPS_CONFIG_KEYPAD;
1638 : }
1639 216 : p2p_dbg(p2p,
1640 : "Building PD Request based on P2PS config method 0x%x status %d --> req_config_methods 0x%x",
1641 144 : p2p->p2ps_prov->method, p2p->p2ps_prov->status,
1642 72 : dev->req_config_methods);
1643 :
1644 72 : if (p2p_prepare_channel(p2p, dev, p2p->p2ps_prov->force_freq,
1645 72 : p2p->p2ps_prov->pref_freq, 1) < 0)
1646 0 : return -1;
1647 : }
1648 :
1649 290 : req = p2p_build_prov_disc_req(p2p, dev, join);
1650 290 : if (req == NULL)
1651 0 : return -1;
1652 :
1653 290 : if (p2p->state != P2P_IDLE)
1654 13 : p2p_stop_listen_for_freq(p2p, freq);
1655 290 : p2p->pending_action_state = P2P_PENDING_PD;
1656 580 : if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
1657 290 : p2p->cfg->dev_addr, dev->info.p2p_device_addr,
1658 290 : wpabuf_head(req), wpabuf_len(req), 200) < 0) {
1659 0 : p2p_dbg(p2p, "Failed to send Action frame");
1660 0 : wpabuf_free(req);
1661 0 : return -1;
1662 : }
1663 :
1664 290 : os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN);
1665 :
1666 290 : wpabuf_free(req);
1667 290 : return 0;
1668 : }
1669 :
1670 :
1671 150 : int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
1672 : struct p2ps_provision *p2ps_prov,
1673 : u16 config_methods, int join, int force_freq,
1674 : int user_initiated_pd)
1675 : {
1676 : struct p2p_device *dev;
1677 :
1678 150 : dev = p2p_get_device(p2p, peer_addr);
1679 150 : if (dev == NULL)
1680 6 : dev = p2p_get_device_interface(p2p, peer_addr);
1681 150 : if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
1682 36 : p2p_dbg(p2p, "Provision Discovery Request destination " MACSTR
1683 36 : " not yet known", MAC2STR(peer_addr));
1684 6 : os_free(p2ps_prov);
1685 6 : return -1;
1686 : }
1687 :
1688 1008 : p2p_dbg(p2p, "Provision Discovery Request with " MACSTR
1689 : " (config methods 0x%x)",
1690 864 : MAC2STR(peer_addr), config_methods);
1691 144 : if (config_methods == 0 && !p2ps_prov) {
1692 0 : os_free(p2ps_prov);
1693 0 : return -1;
1694 : }
1695 :
1696 155 : if (p2ps_prov && p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED &&
1697 11 : p2p->p2ps_prov) {
1698 : /* Use cached method from deferred provisioning */
1699 11 : p2ps_prov->method = p2p->p2ps_prov->method;
1700 : }
1701 :
1702 : /* Reset provisioning info */
1703 144 : dev->wps_prov_info = 0;
1704 144 : p2ps_prov_free(p2p);
1705 144 : p2p->p2ps_prov = p2ps_prov;
1706 :
1707 144 : dev->req_config_methods = config_methods;
1708 144 : if (join)
1709 76 : dev->flags |= P2P_DEV_PD_FOR_JOIN;
1710 : else
1711 68 : dev->flags &= ~P2P_DEV_PD_FOR_JOIN;
1712 :
1713 148 : if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH &&
1714 4 : p2p->state != P2P_LISTEN_ONLY) {
1715 0 : p2p_dbg(p2p, "Busy with other operations; postpone Provision Discovery Request with "
1716 : MACSTR " (config methods 0x%x)",
1717 0 : MAC2STR(peer_addr), config_methods);
1718 0 : return 0;
1719 : }
1720 :
1721 144 : p2p->user_initiated_pd = user_initiated_pd;
1722 144 : p2p->pd_force_freq = force_freq;
1723 :
1724 144 : if (p2p->user_initiated_pd)
1725 139 : p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;
1726 :
1727 : /*
1728 : * Assign dialog token here to use the same value in each retry within
1729 : * the same PD exchange.
1730 : */
1731 144 : dev->dialog_token++;
1732 144 : if (dev->dialog_token == 0)
1733 0 : dev->dialog_token = 1;
1734 :
1735 144 : return p2p_send_prov_disc_req(p2p, dev, join, force_freq);
1736 : }
1737 :
1738 :
1739 2 : void p2p_reset_pending_pd(struct p2p_data *p2p)
1740 : {
1741 : struct p2p_device *dev;
1742 :
1743 4 : dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
1744 2 : if (os_memcmp(p2p->pending_pd_devaddr,
1745 : dev->info.p2p_device_addr, ETH_ALEN))
1746 0 : continue;
1747 2 : if (!dev->req_config_methods)
1748 0 : continue;
1749 2 : if (dev->flags & P2P_DEV_PD_FOR_JOIN)
1750 0 : continue;
1751 : /* Reset the config methods of the device */
1752 2 : dev->req_config_methods = 0;
1753 : }
1754 :
1755 2 : p2p->user_initiated_pd = 0;
1756 2 : os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
1757 2 : p2p->pd_retries = 0;
1758 2 : p2p->pd_force_freq = 0;
1759 2 : }
1760 :
1761 :
1762 474 : void p2ps_prov_free(struct p2p_data *p2p)
1763 : {
1764 474 : os_free(p2p->p2ps_prov);
1765 474 : p2p->p2ps_prov = NULL;
1766 474 : }
|