blob: 1a78e14ef1a39c35efabcfe06900ac5ac593b519 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Wi-Fi Direct - P2P provision discovery
3 * Copyright (c) 2009-2010, Atheros Communications
4 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "common/ieee802_11_defs.h"
Dmitry Shmidt2e67f062014-07-16 09:55:28 -070013#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#include "wps/wps_defs.h"
15#include "p2p_i.h"
16#include "p2p.h"
17
18
Jouni Malinen75ecf522011-06-27 15:19:46 -070019/*
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070020 * Number of retries to attempt for provision discovery requests
21 * in case the peer is not listening.
Jouni Malinen75ecf522011-06-27 15:19:46 -070022 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080023#define MAX_PROV_DISC_REQ_RETRIES 120
Jouni Malinen75ecf522011-06-27 15:19:46 -070024
25
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026static void p2p_build_wps_ie_config_methods(struct wpabuf *buf,
27 u16 config_methods)
28{
29 u8 *len;
30 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
31 len = wpabuf_put(buf, 1);
32 wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
33
34 /* Config Methods */
35 wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
36 wpabuf_put_be16(buf, 2);
37 wpabuf_put_be16(buf, config_methods);
38
39 p2p_buf_update_ie_hdr(buf, len);
40}
41
42
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080043static void p2ps_add_new_group_info(struct p2p_data *p2p,
44 struct p2p_device *dev,
45 struct wpabuf *buf)
Dmitry Shmidt216983b2015-02-06 10:50:36 -080046{
47 int found;
48 u8 intended_addr[ETH_ALEN];
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -070049 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt216983b2015-02-06 10:50:36 -080050 size_t ssid_len;
51 int group_iface;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080052 unsigned int force_freq;
Dmitry Shmidt216983b2015-02-06 10:50:36 -080053
54 if (!p2p->cfg->get_go_info)
55 return;
56
57 found = p2p->cfg->get_go_info(
58 p2p->cfg->cb_ctx, intended_addr, ssid,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080059 &ssid_len, &group_iface, &force_freq);
Dmitry Shmidt216983b2015-02-06 10:50:36 -080060 if (found) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080061 if (force_freq > 0) {
62 p2p->p2ps_prov->force_freq = force_freq;
63 p2p->p2ps_prov->pref_freq = 0;
64
65 if (dev)
66 p2p_prepare_channel(p2p, dev, force_freq, 0, 0);
67 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -080068 p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
69 ssid, ssid_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080070
71 if (group_iface)
72 p2p_buf_add_intended_addr(buf, p2p->intended_addr);
73 else
74 p2p_buf_add_intended_addr(buf, intended_addr);
Dmitry Shmidt216983b2015-02-06 10:50:36 -080075 } else {
76 if (!p2p->ssid_set) {
77 p2p_build_ssid(p2p, p2p->ssid, &p2p->ssid_len);
78 p2p->ssid_set = 1;
79 }
80
81 /* Add pre-composed P2P Group ID */
82 p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
83 p2p->ssid, p2p->ssid_len);
84
85 if (group_iface)
86 p2p_buf_add_intended_addr(
87 buf, p2p->intended_addr);
88 else
89 p2p_buf_add_intended_addr(
90 buf, p2p->cfg->dev_addr);
91 }
92}
93
94
95static void p2ps_add_pd_req_attrs(struct p2p_data *p2p, struct p2p_device *dev,
96 struct wpabuf *buf, u16 config_methods)
97{
98 struct p2ps_provision *prov = p2p->p2ps_prov;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080099 struct p2ps_feature_capab fcap = { prov->cpt_mask, 0 };
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800100 int shared_group = 0;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700101 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800102 size_t ssid_len;
103 u8 go_dev_addr[ETH_ALEN];
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800104 u8 intended_addr[ETH_ALEN];
105 int follow_on_req_fail = prov->status >= 0 &&
106 prov->status != P2P_SC_SUCCESS_DEFERRED;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800107
108 /* If we might be explicite group owner, add GO details */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800109 if (!follow_on_req_fail &&
110 (prov->conncap & (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW)))
111 p2ps_add_new_group_info(p2p, dev, buf);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800112
113 if (prov->status >= 0)
114 p2p_buf_add_status(buf, (u8) prov->status);
115 else
116 prov->method = config_methods;
117
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800118 if (!follow_on_req_fail) {
119 if (p2p->cfg->get_persistent_group) {
120 shared_group = p2p->cfg->get_persistent_group(
121 p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
122 NULL, 0, go_dev_addr, ssid, &ssid_len,
123 intended_addr);
124 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800125
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800126 if (shared_group ||
Sunil8cd6f4d2022-06-28 18:40:46 +0000127 (prov->conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_NEW))) {
128 bool is_6ghz_capab;
129
130 is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
131 p2p_is_peer_6ghz_capab(
132 p2p, dev->info.p2p_device_addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800133 p2p_buf_add_channel_list(buf, p2p->cfg->country,
Sunil8cd6f4d2022-06-28 18:40:46 +0000134 &p2p->channels, is_6ghz_capab);
135 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800136
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800137 if ((shared_group && !is_zero_ether_addr(intended_addr)) ||
138 (prov->conncap & (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW)))
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800139 p2p_buf_add_operating_channel(buf, p2p->cfg->country,
140 p2p->op_reg_class,
141 p2p->op_channel);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800142 }
143
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800144 if (prov->status < 0 && prov->info[0])
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800145 p2p_buf_add_session_info(buf, prov->info);
146
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800147 if (!follow_on_req_fail)
148 p2p_buf_add_connection_capability(buf, prov->conncap);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800149
150 p2p_buf_add_advertisement_id(buf, prov->adv_id, prov->adv_mac);
151
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800152 if (!follow_on_req_fail) {
153 if (shared_group || prov->conncap == P2PS_SETUP_NEW ||
154 prov->conncap ==
155 (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW) ||
156 prov->conncap ==
157 (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT)) {
158 /* Add Config Timeout */
159 p2p_buf_add_config_timeout(buf, p2p->go_timeout,
160 p2p->client_timeout);
161 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800162
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800163 p2p_buf_add_listen_channel(buf, p2p->cfg->country,
164 p2p->cfg->reg_class,
165 p2p->cfg->channel);
166 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800167
168 p2p_buf_add_session_id(buf, prov->session_id, prov->session_mac);
169
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800170 p2p_buf_add_feature_capability(buf, sizeof(fcap), (const u8 *) &fcap);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800171
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800172 if (shared_group) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800173 p2p_buf_add_persistent_group_info(buf, go_dev_addr,
174 ssid, ssid_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800175 /* Add intended interface address if it is not added yet */
176 if ((prov->conncap == P2PS_SETUP_NONE ||
177 prov->conncap == P2PS_SETUP_CLIENT) &&
178 !is_zero_ether_addr(intended_addr))
179 p2p_buf_add_intended_addr(buf, intended_addr);
180 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800181}
182
183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700184static struct wpabuf * p2p_build_prov_disc_req(struct p2p_data *p2p,
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800185 struct p2p_device *dev,
186 int join)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700187{
188 struct wpabuf *buf;
189 u8 *len;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700190 size_t extra = 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800191 u8 dialog_token = dev->dialog_token;
192 u16 config_methods = dev->req_config_methods;
193 struct p2p_device *go = join ? dev : NULL;
194 u8 group_capab;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700195
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700196#ifdef CONFIG_WIFI_DISPLAY
197 if (p2p->wfd_ie_prov_disc_req)
198 extra = wpabuf_len(p2p->wfd_ie_prov_disc_req);
199#endif /* CONFIG_WIFI_DISPLAY */
200
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700201 if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
202 extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
203
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800204 if (p2p->p2ps_prov)
205 extra += os_strlen(p2p->p2ps_prov->info) + 1 +
206 sizeof(struct p2ps_provision);
207
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700208 buf = wpabuf_alloc(1000 + extra);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700209 if (buf == NULL)
210 return NULL;
211
212 p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_REQ, dialog_token);
213
214 len = p2p_buf_add_ie_hdr(buf);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800215
216 group_capab = 0;
217 if (p2p->p2ps_prov) {
218 group_capab |= P2P_GROUP_CAPAB_PERSISTENT_GROUP;
219 group_capab |= P2P_GROUP_CAPAB_PERSISTENT_RECONN;
220 if (p2p->cross_connect)
221 group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
222 if (p2p->cfg->p2p_intra_bss)
223 group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
224 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700225 p2p_buf_add_capability(buf, p2p->dev_capab &
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800226 ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
227 group_capab);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228 p2p_buf_add_device_info(buf, p2p, NULL);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800229 if (p2p->p2ps_prov) {
230 p2ps_add_pd_req_attrs(p2p, dev, buf, config_methods);
231 } else if (go) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700232 p2p_buf_add_group_id(buf, go->info.p2p_device_addr,
233 go->oper_ssid, go->oper_ssid_len);
234 }
235 p2p_buf_update_ie_hdr(buf, len);
236
237 /* WPS IE with Config Methods attribute */
238 p2p_build_wps_ie_config_methods(buf, config_methods);
239
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700240#ifdef CONFIG_WIFI_DISPLAY
241 if (p2p->wfd_ie_prov_disc_req)
242 wpabuf_put_buf(buf, p2p->wfd_ie_prov_disc_req);
243#endif /* CONFIG_WIFI_DISPLAY */
244
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700245 if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ])
246 wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_REQ]);
247
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700248 return buf;
249}
250
251
252static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800253 struct p2p_device *dev,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254 u8 dialog_token,
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800255 enum p2p_status_code status,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700256 u16 config_methods,
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800257 u32 adv_id,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700258 const u8 *group_id,
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800259 size_t group_id_len,
260 const u8 *persist_ssid,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800261 size_t persist_ssid_len,
262 const u8 *fcap,
263 u16 fcap_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700264{
265 struct wpabuf *buf;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700266 size_t extra = 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800267 int persist = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700268
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700269#ifdef CONFIG_WIFI_DISPLAY
270 struct wpabuf *wfd_ie = p2p->wfd_ie_prov_disc_resp;
271 if (wfd_ie && group_id) {
272 size_t i;
273 for (i = 0; i < p2p->num_groups; i++) {
274 struct p2p_group *g = p2p->groups[i];
275 struct wpabuf *ie;
276 if (!p2p_group_is_group_id_match(g, group_id,
277 group_id_len))
278 continue;
279 ie = p2p_group_get_wfd_ie(g);
280 if (ie) {
281 wfd_ie = ie;
282 break;
283 }
284 }
285 }
286 if (wfd_ie)
287 extra = wpabuf_len(wfd_ie);
288#endif /* CONFIG_WIFI_DISPLAY */
289
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700290 if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
291 extra += wpabuf_len(p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
292
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800293 buf = wpabuf_alloc(1000 + extra);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700294 if (buf == NULL)
295 return NULL;
296
297 p2p_buf_add_public_action_hdr(buf, P2P_PROV_DISC_RESP, dialog_token);
298
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800299 /* Add P2P IE for P2PS */
300 if (p2p->p2ps_prov && p2p->p2ps_prov->adv_id == adv_id) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800301 u8 *len = p2p_buf_add_ie_hdr(buf);
302 struct p2ps_provision *prov = p2p->p2ps_prov;
303 u8 group_capab;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800304 u8 conncap = 0;
305
306 if (status == P2P_SC_SUCCESS ||
307 status == P2P_SC_SUCCESS_DEFERRED)
308 conncap = prov->conncap;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800309
310 if (!status && prov->status != -1)
311 status = prov->status;
312
313 p2p_buf_add_status(buf, status);
314 group_capab = P2P_GROUP_CAPAB_PERSISTENT_GROUP |
315 P2P_GROUP_CAPAB_PERSISTENT_RECONN;
316 if (p2p->cross_connect)
317 group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
318 if (p2p->cfg->p2p_intra_bss)
319 group_capab |= P2P_GROUP_CAPAB_INTRA_BSS_DIST;
320 p2p_buf_add_capability(buf, p2p->dev_capab &
321 ~P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY,
322 group_capab);
323 p2p_buf_add_device_info(buf, p2p, NULL);
324
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800325 if (persist_ssid && p2p->cfg->get_persistent_group && dev &&
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800326 (status == P2P_SC_SUCCESS ||
327 status == P2P_SC_SUCCESS_DEFERRED)) {
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700328 u8 ssid[SSID_MAX_LEN];
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800329 size_t ssid_len;
330 u8 go_dev_addr[ETH_ALEN];
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800331 u8 intended_addr[ETH_ALEN];
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800332
333 persist = p2p->cfg->get_persistent_group(
334 p2p->cfg->cb_ctx,
335 dev->info.p2p_device_addr,
336 persist_ssid, persist_ssid_len, go_dev_addr,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800337 ssid, &ssid_len, intended_addr);
338 if (persist) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800339 p2p_buf_add_persistent_group_info(
340 buf, go_dev_addr, ssid, ssid_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800341 if (!is_zero_ether_addr(intended_addr))
342 p2p_buf_add_intended_addr(
343 buf, intended_addr);
344 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800345 }
346
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800347 if (!persist && (conncap & P2PS_SETUP_GROUP_OWNER))
348 p2ps_add_new_group_info(p2p, dev, buf);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800349
350 /* Add Operating Channel if conncap indicates GO */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800351 if (persist || (conncap & P2PS_SETUP_GROUP_OWNER)) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800352 if (p2p->op_reg_class && p2p->op_channel)
353 p2p_buf_add_operating_channel(
354 buf, p2p->cfg->country,
355 p2p->op_reg_class,
356 p2p->op_channel);
357 else
358 p2p_buf_add_operating_channel(
359 buf, p2p->cfg->country,
360 p2p->cfg->op_reg_class,
361 p2p->cfg->op_channel);
362 }
363
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800364 if (persist ||
Sunil8cd6f4d2022-06-28 18:40:46 +0000365 (conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER))) {
366 bool is_6ghz_capab;
367
368 is_6ghz_capab = is_p2p_6ghz_capable(p2p) &&
369 p2p_is_peer_6ghz_capab(
370 p2p, dev->info.p2p_device_addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800371 p2p_buf_add_channel_list(buf, p2p->cfg->country,
Sunil8cd6f4d2022-06-28 18:40:46 +0000372 &p2p->channels, is_6ghz_capab);
373 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800374
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800375 if (!persist && conncap)
376 p2p_buf_add_connection_capability(buf, conncap);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800377
378 p2p_buf_add_advertisement_id(buf, adv_id, prov->adv_mac);
379
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800380 if (persist ||
381 (conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER)))
382 p2p_buf_add_config_timeout(buf, p2p->go_timeout,
383 p2p->client_timeout);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800384
385 p2p_buf_add_session_id(buf, prov->session_id,
386 prov->session_mac);
387
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800388 p2p_buf_add_feature_capability(buf, fcap_len, fcap);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800389 p2p_buf_update_ie_hdr(buf, len);
390 } else if (status != P2P_SC_SUCCESS || adv_id) {
391 u8 *len = p2p_buf_add_ie_hdr(buf);
392
393 p2p_buf_add_status(buf, status);
394
395 if (p2p->p2ps_prov)
396 p2p_buf_add_advertisement_id(buf, adv_id,
397 p2p->p2ps_prov->adv_mac);
398
399 p2p_buf_update_ie_hdr(buf, len);
400 }
401
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 /* WPS IE with Config Methods attribute */
403 p2p_build_wps_ie_config_methods(buf, config_methods);
404
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700405#ifdef CONFIG_WIFI_DISPLAY
406 if (wfd_ie)
407 wpabuf_put_buf(buf, wfd_ie);
408#endif /* CONFIG_WIFI_DISPLAY */
409
Dmitry Shmidt2e67f062014-07-16 09:55:28 -0700410 if (p2p->vendor_elem && p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP])
411 wpabuf_put_buf(buf, p2p->vendor_elem[VENDOR_ELEM_P2P_PD_RESP]);
412
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700413 return buf;
414}
415
416
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800417static int p2ps_setup_p2ps_prov(struct p2p_data *p2p, u32 adv_id,
418 u32 session_id, u16 method,
419 const u8 *session_mac, const u8 *adv_mac)
420{
421 struct p2ps_provision *tmp;
422
423 if (!p2p->p2ps_prov) {
424 p2p->p2ps_prov = os_zalloc(sizeof(struct p2ps_provision) + 1);
425 if (!p2p->p2ps_prov)
426 return -1;
427 } else {
428 os_memset(p2p->p2ps_prov, 0, sizeof(struct p2ps_provision) + 1);
429 }
430
431 tmp = p2p->p2ps_prov;
432 tmp->adv_id = adv_id;
433 tmp->session_id = session_id;
434 tmp->method = method;
435 os_memcpy(tmp->session_mac, session_mac, ETH_ALEN);
436 os_memcpy(tmp->adv_mac, adv_mac, ETH_ALEN);
437 tmp->info[0] = '\0';
438
439 return 0;
440}
441
442
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800443static u8 p2ps_own_preferred_cpt(const u8 *cpt_priority, u8 req_cpt_mask)
444{
445 int i;
446
447 for (i = 0; cpt_priority[i]; i++)
448 if (req_cpt_mask & cpt_priority[i])
449 return cpt_priority[i];
450
451 return 0;
452}
453
454
455/* Check if the message contains a valid P2PS PD Request */
456static int p2ps_validate_pd_req(struct p2p_data *p2p, struct p2p_message *msg,
457 const u8 *addr)
458{
459 u8 group_id = 0;
460 u8 intended_addr = 0;
461 u8 operating_channel = 0;
462 u8 channel_list = 0;
463 u8 config_timeout = 0;
464 u8 listen_channel = 0;
465
466#define P2PS_PD_REQ_CHECK(_val, _attr) \
467do { \
468 if ((_val) && !msg->_attr) { \
469 p2p_dbg(p2p, "Not P2PS PD Request. Missing %s", #_attr); \
470 return -1; \
471 } \
472} while (0)
473
474 P2PS_PD_REQ_CHECK(1, adv_id);
475 P2PS_PD_REQ_CHECK(1, session_id);
476 P2PS_PD_REQ_CHECK(1, session_mac);
477 P2PS_PD_REQ_CHECK(1, adv_mac);
478 P2PS_PD_REQ_CHECK(1, capability);
479 P2PS_PD_REQ_CHECK(1, p2p_device_info);
480 P2PS_PD_REQ_CHECK(1, feature_cap);
481
482 /*
483 * We don't need to check Connection Capability, Persistent Group,
484 * and related attributes for follow-on PD Request with a status
485 * other than SUCCESS_DEFERRED.
486 */
487 if (msg->status && *msg->status != P2P_SC_SUCCESS_DEFERRED)
488 return 0;
489
490 P2PS_PD_REQ_CHECK(1, conn_cap);
491
492 /*
493 * Note 1: A feature capability attribute structure can be changed
494 * in the future. The assumption is that such modifications are
495 * backward compatible, therefore we allow processing of msg.feature_cap
496 * exceeding the size of the p2ps_feature_capab structure.
497 * Note 2: Verification of msg.feature_cap_len below has to be changed
498 * to allow 2 byte feature capability processing if
499 * struct p2ps_feature_capab is extended to include additional fields
500 * and it affects the structure size.
501 */
502 if (msg->feature_cap_len < sizeof(struct p2ps_feature_capab)) {
503 p2p_dbg(p2p, "P2PS: Invalid feature capability len");
504 return -1;
505 }
506
507 switch (*msg->conn_cap) {
508 case P2PS_SETUP_NEW:
509 group_id = 1;
510 intended_addr = 1;
511 operating_channel = 1;
512 channel_list = 1;
513 config_timeout = 1;
514 listen_channel = 1;
515 break;
516 case P2PS_SETUP_CLIENT:
517 channel_list = 1;
518 listen_channel = 1;
519 break;
520 case P2PS_SETUP_GROUP_OWNER:
521 group_id = 1;
522 intended_addr = 1;
523 operating_channel = 1;
524 break;
525 case P2PS_SETUP_NEW | P2PS_SETUP_GROUP_OWNER:
526 group_id = 1;
527 operating_channel = 1;
528 intended_addr = 1;
529 channel_list = 1;
530 config_timeout = 1;
531 break;
532 case P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER:
533 group_id = 1;
534 intended_addr = 1;
535 operating_channel = 1;
536 channel_list = 1;
537 config_timeout = 1;
538 break;
539 default:
540 p2p_dbg(p2p, "Invalid P2PS PD connection capability");
541 return -1;
542 }
543
544 if (msg->persistent_dev) {
545 channel_list = 1;
546 config_timeout = 1;
547 if (os_memcmp(msg->persistent_dev, addr, ETH_ALEN) == 0) {
548 intended_addr = 1;
549 operating_channel = 1;
550 }
551 }
552
553 P2PS_PD_REQ_CHECK(group_id, group_id);
554 P2PS_PD_REQ_CHECK(intended_addr, intended_addr);
555 P2PS_PD_REQ_CHECK(operating_channel, operating_channel);
556 P2PS_PD_REQ_CHECK(channel_list, channel_list);
557 P2PS_PD_REQ_CHECK(config_timeout, config_timeout);
558 P2PS_PD_REQ_CHECK(listen_channel, listen_channel);
559
560#undef P2PS_PD_REQ_CHECK
561
562 return 0;
563}
564
565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
567 const u8 *data, size_t len, int rx_freq)
568{
569 struct p2p_message msg;
570 struct p2p_device *dev;
571 int freq;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800572 enum p2p_status_code reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 struct wpabuf *resp;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800574 u32 adv_id = 0;
575 struct p2ps_advertisement *p2ps_adv = NULL;
576 u8 conncap = P2PS_SETUP_NEW;
577 u8 auto_accept = 0;
578 u32 session_id = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800579 u8 session_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
580 u8 adv_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
581 const u8 *group_mac;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800582 int passwd_id = DEV_PW_DEFAULT;
583 u16 config_methods;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800584 u16 allowed_config_methods = WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
585 struct p2ps_feature_capab resp_fcap = { 0, 0 };
586 struct p2ps_feature_capab *req_fcap = NULL;
587 u8 remote_conncap;
588 u16 method;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700589
590 if (p2p_parse(data, len, &msg))
591 return;
592
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700593 p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700594 " with config methods 0x%x (freq=%d)",
595 MAC2STR(sa), msg.wps_config_methods, rx_freq);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800596 group_mac = msg.intended_addr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597
598 dev = p2p_get_device(p2p, sa);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800599 if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700600 p2p_dbg(p2p, "Provision Discovery Request from unknown peer "
601 MACSTR, MAC2STR(sa));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800602
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800603 if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800604 0)) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700605 p2p_dbg(p2p, "Provision Discovery Request add device failed "
606 MACSTR, MAC2STR(sa));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800607 goto out;
608 }
609
Hai Shalomc09ec812021-03-01 08:11:54 -0800610 dev = p2p_get_device(p2p, sa);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800611 if (!dev) {
Hai Shalomc09ec812021-03-01 08:11:54 -0800612 p2p_dbg(p2p,
613 "Provision Discovery device not found "
614 MACSTR, MAC2STR(sa));
615 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700616 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700617 } else if (msg.wfd_subelems) {
618 wpabuf_free(dev->info.wfd_subelems);
619 dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700620 }
621
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800622 if (!msg.adv_id) {
623 allowed_config_methods |= WPS_CONFIG_PUSHBUTTON;
624 if (!(msg.wps_config_methods & allowed_config_methods)) {
625 p2p_dbg(p2p,
626 "Unsupported Config Methods in Provision Discovery Request");
Dmitry Shmidt04949592012-07-19 12:16:46 -0700627 goto out;
628 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700629
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800630 /* Legacy (non-P2PS) - Unknown groups allowed for P2PS */
631 if (msg.group_id) {
632 size_t i;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800633
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800634 for (i = 0; i < p2p->num_groups; i++) {
635 if (p2p_group_is_group_id_match(
636 p2p->groups[i],
637 msg.group_id, msg.group_id_len))
638 break;
639 }
640 if (i == p2p->num_groups) {
641 p2p_dbg(p2p,
642 "PD request for unknown P2P Group ID - reject");
643 goto out;
644 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800645 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800646 } else {
647 allowed_config_methods |= WPS_CONFIG_P2PS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700648
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800649 /*
650 * Set adv_id here, so in case of an error, a P2PS PD Response
651 * will be sent.
652 */
653 adv_id = WPA_GET_LE32(msg.adv_id);
654 if (p2ps_validate_pd_req(p2p, &msg, sa) < 0) {
655 reject = P2P_SC_FAIL_INVALID_PARAMS;
656 goto out;
657 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800658
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800659 req_fcap = (struct p2ps_feature_capab *) msg.feature_cap;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800660
661 os_memcpy(session_mac, msg.session_mac, ETH_ALEN);
662 os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
663
664 session_id = WPA_GET_LE32(msg.session_id);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800665
666 if (msg.conn_cap)
667 conncap = *msg.conn_cap;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800668
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800669 /*
670 * We need to verify a P2PS config methog in an initial PD
671 * request or in a follow-on PD request with the status
672 * SUCCESS_DEFERRED.
673 */
674 if ((!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) &&
675 !(msg.wps_config_methods & allowed_config_methods)) {
676 p2p_dbg(p2p,
677 "Unsupported Config Methods in Provision Discovery Request");
678 goto out;
679 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800680
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800681 /*
682 * TODO: since we don't support multiple PD, reject PD request
683 * if we are in the middle of P2PS PD with some other peer
684 */
685 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800686
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800687 dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
688 P2P_DEV_PD_PEER_KEYPAD |
689 P2P_DEV_PD_PEER_P2PS);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800690
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800691 if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
692 p2p_dbg(p2p, "Peer " MACSTR
693 " requested us to show a PIN on display", MAC2STR(sa));
694 dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
695 passwd_id = DEV_PW_USER_SPECIFIED;
696 } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
697 p2p_dbg(p2p, "Peer " MACSTR
698 " requested us to write its PIN using keypad",
699 MAC2STR(sa));
700 dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
701 passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
702 } else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
703 p2p_dbg(p2p, "Peer " MACSTR " requesting P2PS PIN",
704 MAC2STR(sa));
705 dev->flags |= P2P_DEV_PD_PEER_P2PS;
706 passwd_id = DEV_PW_P2PS_DEFAULT;
707 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800708
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800709 /* Remove stale persistent groups */
710 if (p2p->cfg->remove_stale_groups) {
711 p2p->cfg->remove_stale_groups(
712 p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
713 msg.persistent_dev,
714 msg.persistent_ssid, msg.persistent_ssid_len);
715 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800716
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800717 reject = P2P_SC_SUCCESS;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800718
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800719 /*
720 * End of a legacy P2P PD Request processing, from this point continue
721 * with P2PS one.
722 */
723 if (!msg.adv_id)
724 goto out;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800725
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800726 remote_conncap = conncap;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800727
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800728 if (!msg.status) {
729 unsigned int forced_freq, pref_freq;
730
731 if (os_memcmp(p2p->cfg->dev_addr, msg.adv_mac, ETH_ALEN)) {
732 p2p_dbg(p2p,
733 "P2PS PD adv mac does not match the local one");
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800734 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
735 goto out;
736 }
737
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800738 p2ps_adv = p2p_service_p2ps_id(p2p, adv_id);
739 if (!p2ps_adv) {
740 p2p_dbg(p2p, "P2PS PD invalid adv_id=0x%X", adv_id);
741 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
742 goto out;
743 }
744 p2p_dbg(p2p, "adv_id: 0x%X, p2ps_adv: %p", adv_id, p2ps_adv);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800745
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800746 auto_accept = p2ps_adv->auto_accept;
747 conncap = p2p->cfg->p2ps_group_capability(p2p->cfg->cb_ctx,
748 conncap, auto_accept,
749 &forced_freq,
750 &pref_freq);
751
752 p2p_dbg(p2p, "Conncap: local:%d remote:%d result:%d",
753 auto_accept, remote_conncap, conncap);
754
755 p2p_prepare_channel(p2p, dev, forced_freq, pref_freq, 0);
756
757 resp_fcap.cpt = p2ps_own_preferred_cpt(p2ps_adv->cpt_priority,
758 req_fcap->cpt);
759
760 p2p_dbg(p2p, "cpt: service:0x%x remote:0x%x result:0x%x",
761 p2ps_adv->cpt_mask, req_fcap->cpt, resp_fcap.cpt);
762
763 if (!resp_fcap.cpt) {
764 p2p_dbg(p2p,
765 "Incompatible P2PS feature capability CPT bitmask");
766 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
767 } else if (p2ps_adv->config_methods &&
768 !(msg.wps_config_methods &
769 p2ps_adv->config_methods)) {
770 p2p_dbg(p2p,
771 "Unsupported config methods in Provision Discovery Request (own=0x%x peer=0x%x)",
772 p2ps_adv->config_methods,
773 msg.wps_config_methods);
774 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
775 } else if (!p2ps_adv->state) {
776 p2p_dbg(p2p, "P2PS state unavailable");
777 reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
778 } else if (!conncap) {
779 p2p_dbg(p2p, "Conncap resolution failed");
780 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
781 }
782
783 if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
784 p2p_dbg(p2p, "Keypad - always defer");
785 auto_accept = 0;
786 }
787
788 if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
789 msg.persistent_dev) && conncap != P2PS_SETUP_NEW &&
790 msg.channel_list && msg.channel_list_len &&
791 p2p_peer_channels_check(p2p, &p2p->channels, dev,
792 msg.channel_list,
793 msg.channel_list_len) < 0) {
794 p2p_dbg(p2p,
795 "No common channels - force deferred flow");
796 auto_accept = 0;
797 }
798
799 if (((remote_conncap & P2PS_SETUP_GROUP_OWNER) ||
800 msg.persistent_dev) && msg.operating_channel) {
801 struct p2p_channels intersect;
802
803 /*
804 * There are cases where only the operating channel is
805 * provided. This requires saving the channel as the
806 * supported channel list, and verifying that it is
807 * supported.
808 */
809 if (dev->channels.reg_classes == 0 ||
810 !p2p_channels_includes(&dev->channels,
811 msg.operating_channel[3],
812 msg.operating_channel[4])) {
813 struct p2p_channels *ch = &dev->channels;
814
815 os_memset(ch, 0, sizeof(*ch));
816 ch->reg_class[0].reg_class =
817 msg.operating_channel[3];
818 ch->reg_class[0].channel[0] =
819 msg.operating_channel[4];
820 ch->reg_class[0].channels = 1;
821 ch->reg_classes = 1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800822 }
823
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800824 p2p_channels_intersect(&p2p->channels, &dev->channels,
825 &intersect);
826
827 if (intersect.reg_classes == 0) {
828 p2p_dbg(p2p,
829 "No common channels - force deferred flow");
830 auto_accept = 0;
831 }
832 }
833
834 if (auto_accept || reject != P2P_SC_SUCCESS) {
835 struct p2ps_provision *tmp;
836
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800837 if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
838 msg.wps_config_methods,
839 session_mac, adv_mac) < 0) {
840 reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
841 goto out;
842 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800843
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800844 tmp = p2p->p2ps_prov;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800845 tmp->force_freq = forced_freq;
846 tmp->pref_freq = pref_freq;
847 if (conncap) {
848 tmp->conncap = conncap;
849 tmp->status = P2P_SC_SUCCESS;
850 } else {
851 tmp->conncap = auto_accept;
852 tmp->status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800853 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800854
855 if (reject != P2P_SC_SUCCESS)
856 goto out;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800857 }
858 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700859
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800860 if (!msg.status && !auto_accept &&
861 (!p2p->p2ps_prov || p2p->p2ps_prov->adv_id != adv_id)) {
862 struct p2ps_provision *tmp;
863
864 if (!conncap) {
865 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
866 goto out;
867 }
868
869 if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
870 msg.wps_config_methods,
871 session_mac, adv_mac) < 0) {
872 reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
873 goto out;
874 }
875 tmp = p2p->p2ps_prov;
876 reject = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
877 tmp->status = reject;
878 }
879
880 /* Not a P2PS Follow-on PD */
881 if (!msg.status)
882 goto out;
883
884 if (*msg.status && *msg.status != P2P_SC_SUCCESS_DEFERRED) {
885 reject = *msg.status;
886 goto out;
887 }
888
889 if (*msg.status != P2P_SC_SUCCESS_DEFERRED || !p2p->p2ps_prov)
890 goto out;
891
892 if (p2p->p2ps_prov->adv_id != adv_id ||
893 os_memcmp(p2p->p2ps_prov->adv_mac, msg.adv_mac, ETH_ALEN)) {
894 p2p_dbg(p2p,
895 "P2PS Follow-on PD with mismatch Advertisement ID/MAC");
896 goto out;
897 }
898
899 if (p2p->p2ps_prov->session_id != session_id ||
900 os_memcmp(p2p->p2ps_prov->session_mac, msg.session_mac, ETH_ALEN)) {
901 p2p_dbg(p2p, "P2PS Follow-on PD with mismatch Session ID/MAC");
902 goto out;
903 }
904
905 method = p2p->p2ps_prov->method;
906
907 conncap = p2p->cfg->p2ps_group_capability(p2p->cfg->cb_ctx,
908 remote_conncap,
909 p2p->p2ps_prov->conncap,
910 &p2p->p2ps_prov->force_freq,
911 &p2p->p2ps_prov->pref_freq);
912
913 resp_fcap.cpt = p2ps_own_preferred_cpt(p2p->p2ps_prov->cpt_priority,
914 req_fcap->cpt);
915
916 p2p_dbg(p2p, "cpt: local:0x%x remote:0x%x result:0x%x",
917 p2p->p2ps_prov->cpt_mask, req_fcap->cpt, resp_fcap.cpt);
918
919 p2p_prepare_channel(p2p, dev, p2p->p2ps_prov->force_freq,
920 p2p->p2ps_prov->pref_freq, 0);
921
922 /*
923 * Ensure that if we asked for PIN originally, our method is consistent
924 * with original request.
925 */
926 if (method & WPS_CONFIG_DISPLAY)
927 method = WPS_CONFIG_KEYPAD;
928 else if (method & WPS_CONFIG_KEYPAD)
929 method = WPS_CONFIG_DISPLAY;
930
931 if (!conncap || !(msg.wps_config_methods & method)) {
932 /*
933 * Reject this "Deferred Accept*
934 * if incompatible conncap or method
935 */
936 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
937 } else if (!resp_fcap.cpt) {
938 p2p_dbg(p2p,
939 "Incompatible P2PS feature capability CPT bitmask");
940 reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
941 } else if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
942 msg.persistent_dev) && conncap != P2PS_SETUP_NEW &&
943 msg.channel_list && msg.channel_list_len &&
944 p2p_peer_channels_check(p2p, &p2p->channels, dev,
945 msg.channel_list,
946 msg.channel_list_len) < 0) {
947 p2p_dbg(p2p,
948 "No common channels in Follow-On Provision Discovery Request");
949 reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
950 } else {
951 reject = P2P_SC_SUCCESS;
952 }
953
954 dev->oper_freq = 0;
955 if (reject == P2P_SC_SUCCESS || reject == P2P_SC_SUCCESS_DEFERRED) {
956 u8 tmp;
957
958 if (msg.operating_channel)
959 dev->oper_freq =
960 p2p_channel_to_freq(msg.operating_channel[3],
961 msg.operating_channel[4]);
962
963 if ((conncap & P2PS_SETUP_GROUP_OWNER) &&
964 p2p_go_select_channel(p2p, dev, &tmp) < 0)
965 reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
966 }
967
968 p2p->p2ps_prov->status = reject;
969 p2p->p2ps_prov->conncap = conncap;
970
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700971out:
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800972 if (reject == P2P_SC_SUCCESS ||
973 reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
974 config_methods = msg.wps_config_methods;
975 else
976 config_methods = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700977
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800978 /*
979 * Send PD Response for an initial PD Request or for follow-on
980 * PD Request with P2P_SC_SUCCESS_DEFERRED status.
981 */
982 if (!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) {
983 resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token,
984 reject, config_methods, adv_id,
985 msg.group_id, msg.group_id_len,
986 msg.persistent_ssid,
987 msg.persistent_ssid_len,
988 (const u8 *) &resp_fcap,
989 sizeof(resp_fcap));
990 if (!resp) {
991 p2p_parse_free(&msg);
992 return;
993 }
994 p2p_dbg(p2p, "Sending Provision Discovery Response");
995 if (rx_freq > 0)
996 freq = rx_freq;
997 else
998 freq = p2p_channel_to_freq(p2p->cfg->reg_class,
999 p2p->cfg->channel);
1000 if (freq < 0) {
1001 p2p_dbg(p2p, "Unknown regulatory class/channel");
1002 wpabuf_free(resp);
1003 p2p_parse_free(&msg);
1004 return;
1005 }
1006 p2p->pending_action_state = P2P_PENDING_PD_RESPONSE;
1007 if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
1008 p2p->cfg->dev_addr,
1009 wpabuf_head(resp), wpabuf_len(resp),
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08001010 50) < 0)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001011 p2p_dbg(p2p, "Failed to send Action frame");
1012 else
1013 p2p->send_action_in_progress = 1;
1014
1015 wpabuf_free(resp);
1016 }
1017
1018 if (!dev) {
1019 p2p_parse_free(&msg);
1020 return;
1021 }
1022
1023 freq = 0;
1024 if (reject == P2P_SC_SUCCESS && conncap == P2PS_SETUP_GROUP_OWNER) {
1025 freq = p2p_channel_to_freq(p2p->op_reg_class,
1026 p2p->op_channel);
1027 if (freq < 0)
1028 freq = 0;
1029 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001031 if (!p2p->cfg->p2ps_prov_complete) {
1032 /* Don't emit anything */
1033 } else if (msg.status && *msg.status != P2P_SC_SUCCESS &&
1034 *msg.status != P2P_SC_SUCCESS_DEFERRED) {
1035 reject = *msg.status;
1036 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
1037 sa, adv_mac, session_mac,
1038 NULL, adv_id, session_id,
1039 0, 0, msg.persistent_ssid,
1040 msg.persistent_ssid_len,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001041 0, 0, NULL, NULL, 0, freq,
1042 NULL, 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001043 } else if (msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
1044 p2p->p2ps_prov) {
1045 p2p->p2ps_prov->status = reject;
1046 p2p->p2ps_prov->conncap = conncap;
1047
1048 if (reject != P2P_SC_SUCCESS)
1049 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, reject,
1050 sa, adv_mac, session_mac,
1051 NULL, adv_id,
1052 session_id, conncap, 0,
1053 msg.persistent_ssid,
1054 msg.persistent_ssid_len, 0,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001055 0, NULL, NULL, 0, freq,
1056 NULL, 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001057 else
1058 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx,
1059 *msg.status,
1060 sa, adv_mac, session_mac,
1061 group_mac, adv_id,
1062 session_id, conncap,
1063 passwd_id,
1064 msg.persistent_ssid,
1065 msg.persistent_ssid_len, 0,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001066 0, NULL,
1067 (const u8 *) &resp_fcap,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001068 sizeof(resp_fcap), freq,
1069 NULL, 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001070 } else if (msg.status && p2p->p2ps_prov) {
1071 p2p->p2ps_prov->status = P2P_SC_SUCCESS;
1072 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, *msg.status, sa,
1073 adv_mac, session_mac, group_mac,
1074 adv_id, session_id, conncap,
1075 passwd_id,
1076 msg.persistent_ssid,
1077 msg.persistent_ssid_len,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001078 0, 0, NULL,
1079 (const u8 *) &resp_fcap,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001080 sizeof(resp_fcap), freq, NULL, 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001081 } else if (msg.status) {
1082 } else if (auto_accept && reject == P2P_SC_SUCCESS) {
1083 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
1084 sa, adv_mac, session_mac,
1085 group_mac, adv_id, session_id,
1086 conncap, passwd_id,
1087 msg.persistent_ssid,
1088 msg.persistent_ssid_len,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001089 0, 0, NULL,
1090 (const u8 *) &resp_fcap,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001091 sizeof(resp_fcap), freq,
1092 msg.group_id ?
1093 msg.group_id + ETH_ALEN : NULL,
1094 msg.group_id ?
1095 msg.group_id_len - ETH_ALEN : 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001096 } else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
1097 (!msg.session_info || !msg.session_info_len)) {
1098 p2p->p2ps_prov->method = msg.wps_config_methods;
1099
1100 p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
1101 sa, adv_mac, session_mac,
1102 group_mac, adv_id, session_id,
1103 conncap, passwd_id,
1104 msg.persistent_ssid,
1105 msg.persistent_ssid_len,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001106 0, 1, NULL,
1107 (const u8 *) &resp_fcap,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001108 sizeof(resp_fcap), freq, NULL, 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001109 } else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
1110 size_t buf_len = msg.session_info_len;
1111 char *buf = os_malloc(2 * buf_len + 1);
1112
1113 if (buf) {
1114 p2p->p2ps_prov->method = msg.wps_config_methods;
1115
1116 utf8_escape((char *) msg.session_info, buf_len,
1117 buf, 2 * buf_len + 1);
1118
1119 p2p->cfg->p2ps_prov_complete(
1120 p2p->cfg->cb_ctx, P2P_SC_SUCCESS, sa,
1121 adv_mac, session_mac, group_mac, adv_id,
1122 session_id, conncap, passwd_id,
1123 msg.persistent_ssid, msg.persistent_ssid_len,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001124 0, 1, buf,
1125 (const u8 *) &resp_fcap, sizeof(resp_fcap),
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001126 freq, NULL, 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001127
1128 os_free(buf);
1129 }
1130 }
1131
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001132 /*
1133 * prov_disc_req callback is used to generate P2P-PROV-DISC-ENTER-PIN,
1134 * P2P-PROV-DISC-SHOW-PIN, and P2P-PROV-DISC-PBC-REQ events.
1135 * Call it either on legacy P2P PD or on P2PS PD only if we need to
1136 * enter/show PIN.
1137 *
1138 * The callback is called in the following cases:
1139 * 1. Legacy P2P PD request, response status SUCCESS
1140 * 2. P2PS advertiser, method: DISPLAY, autoaccept: TRUE,
1141 * response status: SUCCESS
1142 * 3. P2PS advertiser, method DISPLAY, autoaccept: FALSE,
1143 * response status: INFO_CURRENTLY_UNAVAILABLE
1144 * 4. P2PS advertiser, method: KEYPAD, autoaccept==any,
1145 * response status: INFO_CURRENTLY_UNAVAILABLE
1146 * 5. P2PS follow-on with SUCCESS_DEFERRED,
1147 * advertiser role: DISPLAY, autoaccept: FALSE,
1148 * seeker: KEYPAD, response status: SUCCESS
1149 */
1150 if (p2p->cfg->prov_disc_req &&
1151 ((reject == P2P_SC_SUCCESS && !msg.adv_id) ||
1152 (!msg.status &&
1153 (reject == P2P_SC_SUCCESS ||
1154 reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) &&
1155 passwd_id == DEV_PW_USER_SPECIFIED) ||
1156 (!msg.status &&
1157 reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
1158 passwd_id == DEV_PW_REGISTRAR_SPECIFIED) ||
1159 (reject == P2P_SC_SUCCESS &&
1160 msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
1161 passwd_id == DEV_PW_REGISTRAR_SPECIFIED))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001162 const u8 *dev_addr = sa;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001163
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001164 if (msg.p2p_device_addr)
1165 dev_addr = msg.p2p_device_addr;
1166 p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa,
1167 msg.wps_config_methods,
1168 dev_addr, msg.pri_dev_type,
1169 msg.device_name, msg.config_methods,
1170 msg.capability ? msg.capability[0] : 0,
1171 msg.capability ? msg.capability[1] :
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001172 0,
1173 msg.group_id, msg.group_id_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001175
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001176 if (reject != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
1177 p2ps_prov_free(p2p);
1178
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001179 if (reject == P2P_SC_SUCCESS) {
1180 switch (config_methods) {
1181 case WPS_CONFIG_DISPLAY:
1182 dev->wps_prov_info = WPS_CONFIG_KEYPAD;
1183 break;
1184 case WPS_CONFIG_KEYPAD:
1185 dev->wps_prov_info = WPS_CONFIG_DISPLAY;
1186 break;
1187 case WPS_CONFIG_PUSHBUTTON:
1188 dev->wps_prov_info = WPS_CONFIG_PUSHBUTTON;
1189 break;
1190 case WPS_CONFIG_P2PS:
1191 dev->wps_prov_info = WPS_CONFIG_P2PS;
1192 break;
1193 default:
1194 dev->wps_prov_info = 0;
1195 break;
1196 }
1197
1198 if (msg.intended_addr)
1199 os_memcpy(dev->interface_addr, msg.intended_addr,
1200 ETH_ALEN);
1201 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001202 p2p_parse_free(&msg);
1203}
1204
1205
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001206static int p2p_validate_p2ps_pd_resp(struct p2p_data *p2p,
1207 struct p2p_message *msg)
1208{
1209 u8 conn_cap_go = 0;
1210 u8 conn_cap_cli = 0;
1211 u32 session_id;
1212 u32 adv_id;
1213
1214#define P2PS_PD_RESP_CHECK(_val, _attr) \
1215 do { \
1216 if ((_val) && !msg->_attr) { \
1217 p2p_dbg(p2p, "P2PS PD Response missing " #_attr); \
1218 return -1; \
1219 } \
1220 } while (0)
1221
1222 P2PS_PD_RESP_CHECK(1, status);
1223 P2PS_PD_RESP_CHECK(1, adv_id);
1224 P2PS_PD_RESP_CHECK(1, adv_mac);
1225 P2PS_PD_RESP_CHECK(1, capability);
1226 P2PS_PD_RESP_CHECK(1, p2p_device_info);
1227 P2PS_PD_RESP_CHECK(1, session_id);
1228 P2PS_PD_RESP_CHECK(1, session_mac);
1229 P2PS_PD_RESP_CHECK(1, feature_cap);
1230
1231 session_id = WPA_GET_LE32(msg->session_id);
1232 adv_id = WPA_GET_LE32(msg->adv_id);
1233
1234 if (p2p->p2ps_prov->session_id != session_id) {
1235 p2p_dbg(p2p,
1236 "Ignore PD Response with unexpected Session ID");
1237 return -1;
1238 }
1239
1240 if (os_memcmp(p2p->p2ps_prov->session_mac, msg->session_mac,
1241 ETH_ALEN)) {
1242 p2p_dbg(p2p,
1243 "Ignore PD Response with unexpected Session MAC");
1244 return -1;
1245 }
1246
1247 if (p2p->p2ps_prov->adv_id != adv_id) {
1248 p2p_dbg(p2p,
1249 "Ignore PD Response with unexpected Advertisement ID");
1250 return -1;
1251 }
1252
1253 if (os_memcmp(p2p->p2ps_prov->adv_mac, msg->adv_mac, ETH_ALEN) != 0) {
1254 p2p_dbg(p2p,
1255 "Ignore PD Response with unexpected Advertisement MAC");
1256 return -1;
1257 }
1258
1259 if (msg->listen_channel) {
1260 p2p_dbg(p2p,
1261 "Ignore malformed PD Response - unexpected Listen Channel");
1262 return -1;
1263 }
1264
1265 if (*msg->status == P2P_SC_SUCCESS &&
1266 !(!!msg->conn_cap ^ !!msg->persistent_dev)) {
1267 p2p_dbg(p2p,
1268 "Ignore malformed PD Response - either conn_cap or persistent group should be present");
1269 return -1;
1270 }
1271
1272 if (msg->persistent_dev && *msg->status != P2P_SC_SUCCESS) {
1273 p2p_dbg(p2p,
1274 "Ignore malformed PD Response - persistent group is present, but the status isn't success");
1275 return -1;
1276 }
1277
1278 if (msg->conn_cap) {
1279 conn_cap_go = *msg->conn_cap == P2PS_SETUP_GROUP_OWNER;
1280 conn_cap_cli = *msg->conn_cap == P2PS_SETUP_CLIENT;
1281 }
1282
1283 P2PS_PD_RESP_CHECK(msg->persistent_dev || conn_cap_go || conn_cap_cli,
1284 channel_list);
1285 P2PS_PD_RESP_CHECK(msg->persistent_dev || conn_cap_go || conn_cap_cli,
1286 config_timeout);
1287
1288 P2PS_PD_RESP_CHECK(conn_cap_go, group_id);
1289 P2PS_PD_RESP_CHECK(conn_cap_go, intended_addr);
1290 P2PS_PD_RESP_CHECK(conn_cap_go, operating_channel);
1291 /*
1292 * TODO: Also validate that operating channel is present if the device
1293 * is a GO in a persistent group. We can't do it here since we don't
1294 * know what is the role of the peer. It should be probably done in
1295 * p2ps_prov_complete callback, but currently operating channel isn't
1296 * passed to it.
1297 */
1298
1299#undef P2PS_PD_RESP_CHECK
1300
1301 return 0;
1302}
1303
1304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305void p2p_process_prov_disc_resp(struct p2p_data *p2p, const u8 *sa,
1306 const u8 *data, size_t len)
1307{
1308 struct p2p_message msg;
1309 struct p2p_device *dev;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001310 u16 report_config_methods = 0, req_config_methods;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001311 u8 status = P2P_SC_SUCCESS;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001312 u32 adv_id = 0;
1313 u8 conncap = P2PS_SETUP_NEW;
1314 u8 adv_mac[ETH_ALEN];
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001315 const u8 *group_mac;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001316 int passwd_id = DEV_PW_DEFAULT;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001317 int p2ps_seeker;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001318
1319 if (p2p_parse(data, len, &msg))
1320 return;
1321
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001322 if (p2p->p2ps_prov && p2p_validate_p2ps_pd_resp(p2p, &msg)) {
1323 p2p_parse_free(&msg);
1324 return;
1325 }
1326
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001327 /* Parse the P2PS members present */
1328 if (msg.status)
1329 status = *msg.status;
1330
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001331 group_mac = msg.intended_addr;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001332
1333 if (msg.adv_mac)
1334 os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
1335 else
1336 os_memset(adv_mac, 0, ETH_ALEN);
1337
1338 if (msg.adv_id)
1339 adv_id = WPA_GET_LE32(msg.adv_id);
1340
1341 if (msg.conn_cap) {
1342 conncap = *msg.conn_cap;
1343
1344 /* Switch bits to local relative */
1345 switch (conncap) {
1346 case P2PS_SETUP_GROUP_OWNER:
1347 conncap = P2PS_SETUP_CLIENT;
1348 break;
1349 case P2PS_SETUP_CLIENT:
1350 conncap = P2PS_SETUP_GROUP_OWNER;
1351 break;
1352 }
1353 }
1354
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001355 p2p_dbg(p2p, "Received Provision Discovery Response from " MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001356 " with config methods 0x%x",
1357 MAC2STR(sa), msg.wps_config_methods);
1358
1359 dev = p2p_get_device(p2p, sa);
1360 if (dev == NULL || !dev->req_config_methods) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001361 p2p_dbg(p2p, "Ignore Provision Discovery Response from " MACSTR
1362 " with no pending request", MAC2STR(sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363 p2p_parse_free(&msg);
1364 return;
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08001365 } else if (msg.wfd_subelems) {
1366 wpabuf_free(dev->info.wfd_subelems);
1367 dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001368 }
1369
1370 if (dev->dialog_token != msg.dialog_token) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001371 p2p_dbg(p2p, "Ignore Provision Discovery Response with unexpected Dialog Token %u (expected %u)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001372 msg.dialog_token, dev->dialog_token);
1373 p2p_parse_free(&msg);
1374 return;
1375 }
1376
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -07001377 if (p2p->pending_action_state == P2P_PENDING_PD) {
1378 os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
1379 p2p->pending_action_state = P2P_NO_PENDING_ACTION;
1380 }
1381
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001382 p2ps_seeker = p2p->p2ps_prov && p2p->p2ps_prov->pd_seeker;
1383
Jouni Malinen75ecf522011-06-27 15:19:46 -07001384 /*
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001385 * Use a local copy of the requested config methods since
1386 * p2p_reset_pending_pd() can clear this in the peer entry.
1387 */
1388 req_config_methods = dev->req_config_methods;
1389
1390 /*
Jouni Malinen75ecf522011-06-27 15:19:46 -07001391 * If the response is from the peer to whom a user initiated request
1392 * was sent earlier, we reset that state info here.
1393 */
1394 if (p2p->user_initiated_pd &&
1395 os_memcmp(p2p->pending_pd_devaddr, sa, ETH_ALEN) == 0)
1396 p2p_reset_pending_pd(p2p);
1397
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001398 if (msg.wps_config_methods != req_config_methods) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001399 p2p_dbg(p2p, "Peer rejected our Provision Discovery Request (received config_methods 0x%x expected 0x%x",
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001400 msg.wps_config_methods, req_config_methods);
Jouni Malinen75ecf522011-06-27 15:19:46 -07001401 if (p2p->cfg->prov_disc_fail)
1402 p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001403 P2P_PROV_DISC_REJECTED,
1404 adv_id, adv_mac, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405 p2p_parse_free(&msg);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001406 p2ps_prov_free(p2p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001407 goto out;
1408 }
1409
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001410 report_config_methods = req_config_methods;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001411 dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001412 P2P_DEV_PD_PEER_KEYPAD |
1413 P2P_DEV_PD_PEER_P2PS);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001414 if (req_config_methods & WPS_CONFIG_DISPLAY) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001415 p2p_dbg(p2p, "Peer " MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416 " accepted to show a PIN on display", MAC2STR(sa));
1417 dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001418 passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001419 } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001420 p2p_dbg(p2p, "Peer " MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001421 " accepted to write our PIN using keypad",
1422 MAC2STR(sa));
1423 dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001424 passwd_id = DEV_PW_USER_SPECIFIED;
1425 } else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
1426 p2p_dbg(p2p, "Peer " MACSTR " accepted P2PS PIN",
1427 MAC2STR(sa));
1428 dev->flags |= P2P_DEV_PD_PEER_P2PS;
1429 passwd_id = DEV_PW_P2PS_DEFAULT;
1430 }
1431
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001432 if ((status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001433 p2p->p2ps_prov) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001434 dev->oper_freq = 0;
1435
1436 /*
1437 * Save the reported channel list and operating frequency.
1438 * Note that the specification mandates that the responder
1439 * should include in the channel list only channels reported by
Hai Shaloma20dcd72022-02-04 13:43:00 -08001440 * the initiator, so this is only a validity check, and if this
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001441 * fails the flow would continue, although it would probably
1442 * fail. Same is true for the operating channel.
1443 */
1444 if (msg.channel_list && msg.channel_list_len &&
1445 p2p_peer_channels_check(p2p, &p2p->channels, dev,
1446 msg.channel_list,
1447 msg.channel_list_len) < 0)
1448 p2p_dbg(p2p, "P2PS PD Response - no common channels");
1449
1450 if (msg.operating_channel) {
1451 if (p2p_channels_includes(&p2p->channels,
1452 msg.operating_channel[3],
1453 msg.operating_channel[4]) &&
1454 p2p_channels_includes(&dev->channels,
1455 msg.operating_channel[3],
1456 msg.operating_channel[4])) {
1457 dev->oper_freq =
1458 p2p_channel_to_freq(
1459 msg.operating_channel[3],
1460 msg.operating_channel[4]);
1461 } else {
1462 p2p_dbg(p2p,
1463 "P2PS PD Response - invalid operating channel");
1464 }
1465 }
1466
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001467 if (p2p->cfg->p2ps_prov_complete) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001468 int freq = 0;
1469
1470 if (conncap == P2PS_SETUP_GROUP_OWNER) {
1471 u8 tmp;
1472
1473 /*
1474 * Re-select the operating channel as it is
1475 * possible that original channel is no longer
1476 * valid. This should not really fail.
1477 */
1478 if (p2p_go_select_channel(p2p, dev, &tmp) < 0)
1479 p2p_dbg(p2p,
1480 "P2PS PD channel selection failed");
1481
1482 freq = p2p_channel_to_freq(p2p->op_reg_class,
1483 p2p->op_channel);
1484 if (freq < 0)
1485 freq = 0;
1486 }
1487
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001488 p2p->cfg->p2ps_prov_complete(
1489 p2p->cfg->cb_ctx, status, sa, adv_mac,
1490 p2p->p2ps_prov->session_mac,
1491 group_mac, adv_id, p2p->p2ps_prov->session_id,
1492 conncap, passwd_id, msg.persistent_ssid,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001493 msg.persistent_ssid_len, 1, 0, NULL,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001494 msg.feature_cap, msg.feature_cap_len, freq,
1495 msg.group_id ? msg.group_id + ETH_ALEN : NULL,
1496 msg.group_id ? msg.group_id_len - ETH_ALEN : 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001497 }
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001498 p2ps_prov_free(p2p);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001499 } else if (status != P2P_SC_SUCCESS &&
1500 status != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
1501 status != P2P_SC_SUCCESS_DEFERRED && p2p->p2ps_prov) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001502 if (p2p->cfg->p2ps_prov_complete)
1503 p2p->cfg->p2ps_prov_complete(
1504 p2p->cfg->cb_ctx, status, sa, adv_mac,
1505 p2p->p2ps_prov->session_mac,
1506 group_mac, adv_id, p2p->p2ps_prov->session_id,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08001507 0, 0, NULL, 0, 1, 0, NULL, NULL, 0, 0, NULL, 0);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001508 p2ps_prov_free(p2p);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001509 }
1510
1511 if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
1512 if (p2p->cfg->remove_stale_groups) {
1513 p2p->cfg->remove_stale_groups(p2p->cfg->cb_ctx,
1514 dev->info.p2p_device_addr,
1515 NULL, NULL, 0);
1516 }
1517
1518 if (msg.session_info && msg.session_info_len) {
1519 size_t info_len = msg.session_info_len;
1520 char *deferred_sess_resp = os_malloc(2 * info_len + 1);
1521
1522 if (!deferred_sess_resp) {
1523 p2p_parse_free(&msg);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001524 p2ps_prov_free(p2p);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001525 goto out;
1526 }
1527 utf8_escape((char *) msg.session_info, info_len,
1528 deferred_sess_resp, 2 * info_len + 1);
1529
1530 if (p2p->cfg->prov_disc_fail)
1531 p2p->cfg->prov_disc_fail(
1532 p2p->cfg->cb_ctx, sa,
1533 P2P_PROV_DISC_INFO_UNAVAILABLE,
1534 adv_id, adv_mac,
1535 deferred_sess_resp);
1536 os_free(deferred_sess_resp);
1537 } else
1538 if (p2p->cfg->prov_disc_fail)
1539 p2p->cfg->prov_disc_fail(
1540 p2p->cfg->cb_ctx, sa,
1541 P2P_PROV_DISC_INFO_UNAVAILABLE,
1542 adv_id, adv_mac, NULL);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001543 } else if (status != P2P_SC_SUCCESS) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001544 p2p_dbg(p2p, "Peer rejected our Provision Discovery Request");
1545 if (p2p->cfg->prov_disc_fail)
1546 p2p->cfg->prov_disc_fail(p2p->cfg->cb_ctx, sa,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001547 P2P_PROV_DISC_REJECTED,
1548 adv_id, adv_mac, NULL);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001549 p2p_parse_free(&msg);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001550 p2ps_prov_free(p2p);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001551 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001553
1554 /* Store the provisioning info */
1555 dev->wps_prov_info = msg.wps_config_methods;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001556 if (msg.intended_addr)
1557 os_memcpy(dev->interface_addr, msg.intended_addr, ETH_ALEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001558
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001559 p2p_parse_free(&msg);
1560
1561out:
1562 dev->req_config_methods = 0;
1563 p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001564 if (dev->flags & P2P_DEV_PD_BEFORE_GO_NEG) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001565 p2p_dbg(p2p, "Start GO Neg after the PD-before-GO-Neg workaround with "
1566 MACSTR, MAC2STR(dev->info.p2p_device_addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -07001567 dev->flags &= ~P2P_DEV_PD_BEFORE_GO_NEG;
1568 p2p_connect_send(p2p, dev);
1569 return;
1570 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001571
1572 /*
1573 * prov_disc_resp callback is used to generate P2P-PROV-DISC-ENTER-PIN,
1574 * P2P-PROV-DISC-SHOW-PIN, and P2P-PROV-DISC-PBC-REQ events.
1575 * Call it only for a legacy P2P PD or for P2PS PD scenarios where
1576 * show/enter PIN events are needed.
1577 *
1578 * The callback is called in the following cases:
1579 * 1. Legacy P2P PD response with a status SUCCESS
1580 * 2. P2PS, advertiser method: DISPLAY, autoaccept: true,
1581 * response status: SUCCESS, local method KEYPAD
1582 * 3. P2PS, advertiser method: KEYPAD,Seeker side,
1583 * response status: INFO_CURRENTLY_UNAVAILABLE,
1584 * local method: DISPLAY
1585 */
1586 if (p2p->cfg->prov_disc_resp &&
1587 ((status == P2P_SC_SUCCESS && !adv_id) ||
1588 (p2ps_seeker && status == P2P_SC_SUCCESS &&
1589 passwd_id == DEV_PW_REGISTRAR_SPECIFIED) ||
1590 (p2ps_seeker &&
1591 status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
1592 passwd_id == DEV_PW_USER_SPECIFIED)))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001593 p2p->cfg->prov_disc_resp(p2p->cfg->cb_ctx, sa,
1594 report_config_methods);
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001595
1596 if (p2p->state == P2P_PD_DURING_FIND) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001597 p2p_stop_listen_for_freq(p2p, 0);
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001598 p2p_continue_find(p2p);
1599 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001600}
1601
1602
1603int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001604 int join, int force_freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605{
1606 struct wpabuf *req;
1607 int freq;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001608
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001609 if (force_freq > 0)
1610 freq = force_freq;
1611 else
1612 freq = dev->listen_freq > 0 ? dev->listen_freq :
1613 dev->oper_freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614 if (freq <= 0) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001615 p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
1616 MACSTR " to send Provision Discovery Request",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001617 MAC2STR(dev->info.p2p_device_addr));
1618 return -1;
1619 }
1620
1621 if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
1622 if (!(dev->info.dev_capab &
1623 P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001624 p2p_dbg(p2p, "Cannot use PD with P2P Device " MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001625 " that is in a group and is not discoverable",
1626 MAC2STR(dev->info.p2p_device_addr));
1627 return -1;
1628 }
1629 /* TODO: use device discoverability request through GO */
1630 }
1631
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001632 if (p2p->p2ps_prov) {
1633 if (p2p->p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED) {
1634 if (p2p->p2ps_prov->method == WPS_CONFIG_DISPLAY)
1635 dev->req_config_methods = WPS_CONFIG_KEYPAD;
1636 else if (p2p->p2ps_prov->method == WPS_CONFIG_KEYPAD)
1637 dev->req_config_methods = WPS_CONFIG_DISPLAY;
1638 else
1639 dev->req_config_methods = WPS_CONFIG_P2PS;
1640 } else {
1641 /* Order of preference, based on peer's capabilities */
1642 if (p2p->p2ps_prov->method)
1643 dev->req_config_methods =
1644 p2p->p2ps_prov->method;
1645 else if (dev->info.config_methods & WPS_CONFIG_P2PS)
1646 dev->req_config_methods = WPS_CONFIG_P2PS;
1647 else if (dev->info.config_methods & WPS_CONFIG_DISPLAY)
1648 dev->req_config_methods = WPS_CONFIG_DISPLAY;
1649 else
1650 dev->req_config_methods = WPS_CONFIG_KEYPAD;
1651 }
1652 p2p_dbg(p2p,
1653 "Building PD Request based on P2PS config method 0x%x status %d --> req_config_methods 0x%x",
1654 p2p->p2ps_prov->method, p2p->p2ps_prov->status,
1655 dev->req_config_methods);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001656
1657 if (p2p_prepare_channel(p2p, dev, p2p->p2ps_prov->force_freq,
1658 p2p->p2ps_prov->pref_freq, 1) < 0)
1659 return -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001660 }
1661
1662 req = p2p_build_prov_disc_req(p2p, dev, join);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001663 if (req == NULL)
1664 return -1;
1665
Dmitry Shmidt04949592012-07-19 12:16:46 -07001666 if (p2p->state != P2P_IDLE)
1667 p2p_stop_listen_for_freq(p2p, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001668 p2p->pending_action_state = P2P_PENDING_PD;
1669 if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
1670 p2p->cfg->dev_addr, dev->info.p2p_device_addr,
1671 wpabuf_head(req), wpabuf_len(req), 200) < 0) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001672 p2p_dbg(p2p, "Failed to send Action frame");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001673 wpabuf_free(req);
1674 return -1;
1675 }
1676
Jouni Malinen75ecf522011-06-27 15:19:46 -07001677 os_memcpy(p2p->pending_pd_devaddr, dev->info.p2p_device_addr, ETH_ALEN);
1678
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001679 wpabuf_free(req);
1680 return 0;
1681}
1682
1683
1684int p2p_prov_disc_req(struct p2p_data *p2p, const u8 *peer_addr,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001685 struct p2ps_provision *p2ps_prov,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001686 u16 config_methods, int join, int force_freq,
1687 int user_initiated_pd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001688{
1689 struct p2p_device *dev;
1690
1691 dev = p2p_get_device(p2p, peer_addr);
1692 if (dev == NULL)
1693 dev = p2p_get_device_interface(p2p, peer_addr);
1694 if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001695 p2p_dbg(p2p, "Provision Discovery Request destination " MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001696 " not yet known", MAC2STR(peer_addr));
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001697 os_free(p2ps_prov);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001698 return -1;
1699 }
1700
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001701 p2p_dbg(p2p, "Provision Discovery Request with " MACSTR
1702 " (config methods 0x%x)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001703 MAC2STR(peer_addr), config_methods);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001704 if (config_methods == 0 && !p2ps_prov) {
1705 os_free(p2ps_prov);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001706 return -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001707 }
1708
1709 if (p2ps_prov && p2ps_prov->status == P2P_SC_SUCCESS_DEFERRED &&
1710 p2p->p2ps_prov) {
1711 /* Use cached method from deferred provisioning */
1712 p2ps_prov->method = p2p->p2ps_prov->method;
1713 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001714
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001715 /* Reset provisioning info */
1716 dev->wps_prov_info = 0;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001717 p2ps_prov_free(p2p);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001718 p2p->p2ps_prov = p2ps_prov;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001719
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720 dev->req_config_methods = config_methods;
1721 if (join)
1722 dev->flags |= P2P_DEV_PD_FOR_JOIN;
1723 else
1724 dev->flags &= ~P2P_DEV_PD_FOR_JOIN;
1725
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001726 if (p2p->state != P2P_IDLE && p2p->state != P2P_SEARCH &&
1727 p2p->state != P2P_LISTEN_ONLY) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001728 p2p_dbg(p2p, "Busy with other operations; postpone Provision Discovery Request with "
1729 MACSTR " (config methods 0x%x)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730 MAC2STR(peer_addr), config_methods);
1731 return 0;
1732 }
1733
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001734 p2p->user_initiated_pd = user_initiated_pd;
Dmitry Shmidt051af732013-10-22 13:52:46 -07001735 p2p->pd_force_freq = force_freq;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001736
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001737 if (p2p->user_initiated_pd)
Jouni Malinen75ecf522011-06-27 15:19:46 -07001738 p2p->pd_retries = MAX_PROV_DISC_REQ_RETRIES;
1739
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001740 /*
1741 * Assign dialog token here to use the same value in each retry within
1742 * the same PD exchange.
1743 */
1744 dev->dialog_token++;
1745 if (dev->dialog_token == 0)
1746 dev->dialog_token = 1;
1747
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001748 return p2p_send_prov_disc_req(p2p, dev, join, force_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001749}
Jouni Malinen75ecf522011-06-27 15:19:46 -07001750
1751
1752void p2p_reset_pending_pd(struct p2p_data *p2p)
1753{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001754 struct p2p_device *dev;
1755
1756 dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
1757 if (os_memcmp(p2p->pending_pd_devaddr,
1758 dev->info.p2p_device_addr, ETH_ALEN))
1759 continue;
1760 if (!dev->req_config_methods)
1761 continue;
1762 if (dev->flags & P2P_DEV_PD_FOR_JOIN)
1763 continue;
1764 /* Reset the config methods of the device */
1765 dev->req_config_methods = 0;
1766 }
1767
Jouni Malinen75ecf522011-06-27 15:19:46 -07001768 p2p->user_initiated_pd = 0;
1769 os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
1770 p2p->pd_retries = 0;
Dmitry Shmidt051af732013-10-22 13:52:46 -07001771 p2p->pd_force_freq = 0;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001772}
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001773
1774
1775void p2ps_prov_free(struct p2p_data *p2p)
1776{
1777 os_free(p2p->p2ps_prov);
1778 p2p->p2ps_prov = NULL;
1779}