blob: 926ba7a9fe60fc20a836da5f8b6060e72b13e6a3 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * wpa_supplicant - P2P
3 * Copyright (c) 2009-2010, Atheros Communications
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004 * Copyright (c) 2010-2014, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008 */
9
10#include "includes.h"
11
12#include "common.h"
13#include "eloop.h"
14#include "common/ieee802_11_common.h"
15#include "common/ieee802_11_defs.h"
16#include "common/wpa_ctrl.h"
17#include "wps/wps_i.h"
18#include "p2p/p2p.h"
19#include "ap/hostapd.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080020#include "ap/ap_config.h"
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070021#include "ap/sta_info.h"
22#include "ap/ap_drv_ops.h"
Dmitry Shmidtcf32e602014-01-28 10:57:39 -080023#include "ap/wps_hostapd.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#include "ap/p2p_hostapd.h"
Dmitry Shmidt203eadb2015-03-05 14:16:04 -080025#include "ap/dfs.h"
Jouni Malinen75ecf522011-06-27 15:19:46 -070026#include "eapol_supp/eapol_supp_sm.h"
27#include "rsn_supp/wpa.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070028#include "wpa_supplicant_i.h"
29#include "driver_i.h"
30#include "ap.h"
31#include "config_ssid.h"
32#include "config.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070033#include "notify.h"
34#include "scan.h"
35#include "bss.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080036#include "offchannel.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037#include "wps_supplicant.h"
38#include "p2p_supplicant.h"
Dmitry Shmidt04f534e2013-12-09 15:50:16 -080039#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040
41
42/*
43 * How many times to try to scan to find the GO before giving up on join
44 * request.
45 */
46#define P2P_MAX_JOIN_SCAN_ATTEMPTS 10
47
Dmitry Shmidt04949592012-07-19 12:16:46 -070048#define P2P_AUTO_PD_SCAN_ATTEMPTS 5
49
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080050/**
51 * Defines time interval in seconds when a GO needs to evacuate a frequency that
52 * it is currently using, but is no longer valid for P2P use cases.
53 */
54#define P2P_GO_FREQ_CHANGE_TIME 5
55
56/**
57 * Defines CSA parameters which are used when GO evacuates the no longer valid
58 * channel (and if the driver supports channel switch).
59 */
60#define P2P_GO_CSA_COUNT 7
61#define P2P_GO_CSA_BLOCK_TX 0
62
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080063#ifndef P2P_MAX_CLIENT_IDLE
64/*
65 * How many seconds to try to reconnect to the GO when connection in P2P client
66 * role has been lost.
67 */
68#define P2P_MAX_CLIENT_IDLE 10
69#endif /* P2P_MAX_CLIENT_IDLE */
70
Dmitry Shmidt04949592012-07-19 12:16:46 -070071#ifndef P2P_MAX_INITIAL_CONN_WAIT
72/*
73 * How many seconds to wait for initial 4-way handshake to get completed after
Dmitry Shmidt15907092014-03-25 10:42:57 -070074 * WPS provisioning step or after the re-invocation of a persistent group on a
75 * P2P Client.
Dmitry Shmidt04949592012-07-19 12:16:46 -070076 */
77#define P2P_MAX_INITIAL_CONN_WAIT 10
78#endif /* P2P_MAX_INITIAL_CONN_WAIT */
79
Dmitry Shmidt92c368d2013-08-29 12:37:21 -070080#ifndef P2P_MAX_INITIAL_CONN_WAIT_GO
81/*
82 * How many seconds to wait for initial 4-way handshake to get completed after
83 * WPS provisioning step on the GO. This controls the extra time the P2P
84 * operation is considered to be in progress (e.g., to delay other scans) after
85 * WPS provisioning has been completed on the GO during group formation.
86 */
87#define P2P_MAX_INITIAL_CONN_WAIT_GO 10
88#endif /* P2P_MAX_INITIAL_CONN_WAIT_GO */
89
Dmitry Shmidt56052862013-10-04 10:23:25 -070090#ifndef P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE
91/*
92 * How many seconds to wait for initial 4-way handshake to get completed after
93 * re-invocation of a persistent group on the GO when the client is expected
94 * to connect automatically (no user interaction).
95 */
96#define P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE 15
97#endif /* P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE */
98
Dmitry Shmidt34af3062013-07-11 10:46:32 -070099#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
100
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800101/*
102 * How many seconds to wait to re-attempt to move GOs, in case previous attempt
103 * was not possible.
104 */
105#define P2P_RECONSIDER_GO_MOVE_DELAY 30
106
Vinayak Yadawad8db34572021-08-30 21:28:05 +0530107/* Check if frequency is 2GHz */
108#define IS_2GHZ(n) (n >= 2412 && n <= 2484)
109
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700110enum p2p_group_removal_reason {
111 P2P_GROUP_REMOVAL_UNKNOWN,
112 P2P_GROUP_REMOVAL_SILENT,
113 P2P_GROUP_REMOVAL_FORMATION_FAILED,
114 P2P_GROUP_REMOVAL_REQUESTED,
115 P2P_GROUP_REMOVAL_IDLE_TIMEOUT,
116 P2P_GROUP_REMOVAL_UNAVAILABLE,
117 P2P_GROUP_REMOVAL_GO_ENDING_SESSION,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800118 P2P_GROUP_REMOVAL_PSK_FAILURE,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800119 P2P_GROUP_REMOVAL_FREQ_CONFLICT,
120 P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700121};
122
Jouni Malinendc7b7132012-09-14 12:53:47 -0700123
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700124static void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx);
125static struct wpa_supplicant *
126wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
127 int go);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800128static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
129 const u8 *ssid, size_t ssid_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800130static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
131 int *force_freq, int *pref_freq, int go,
Sunil8cd6f4d2022-06-28 18:40:46 +0000132 struct weighted_pcl *pref_freq_list,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800133 unsigned int *num_pref_freq);
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800134static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
135 const u8 *ssid, size_t ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700136static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
137static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -0700138 const u8 *dev_addr, enum p2p_wps_method wps_method,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800139 int auto_join, int freq,
140 const u8 *ssid, size_t ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700141static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s);
142static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s);
143static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
144static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800145static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
146 void *timeout_ctx);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800147static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800148static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
149 int group_added);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800150static void wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s);
Dmitry Shmidtbd14a572014-02-18 10:33:49 -0800151static void wpas_stop_listen(void *ctx);
Dmitry Shmidt684785c2014-05-12 13:34:29 -0700152static void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700153static void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800154static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s,
155 enum wpa_driver_if_type type);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -0700156static void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s,
157 int already_deleted);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800158static void wpas_p2p_optimize_listen_channel(struct wpa_supplicant *wpa_s,
159 struct wpa_used_freq_data *freqs,
160 unsigned int num);
161static void wpas_p2p_move_go(void *eloop_ctx, void *timeout_ctx);
162static int wpas_p2p_go_is_peer_freq(struct wpa_supplicant *wpa_s, int freq);
163static void
164wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s,
165 struct wpa_used_freq_data *freqs, unsigned int num,
166 enum wpas_p2p_channel_update_trig trig);
167static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700168
169
Hai Shalomc1a21442022-02-04 13:43:00 -0800170static int wpas_get_6ghz_he_chwidth_capab(struct hostapd_hw_modes *mode)
171{
172 int he_capab = 0;
173
174 if (mode)
175 he_capab = mode->he_capab[WPAS_MODE_INFRA].phy_cap[
176 HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
177 return he_capab;
178}
179
180
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700181/*
182 * Get the number of concurrent channels that the HW can operate, but that are
183 * currently not in use by any of the wpa_supplicant interfaces.
184 */
185static int wpas_p2p_num_unused_channels(struct wpa_supplicant *wpa_s)
186{
187 int *freqs;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800188 int num, unused;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700189
190 freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
191 if (!freqs)
192 return -1;
193
194 num = get_shared_radio_freqs(wpa_s, freqs,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000195 wpa_s->num_multichan_concurrent, false);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700196 os_free(freqs);
197
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800198 unused = wpa_s->num_multichan_concurrent - num;
199 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: num_unused_channels: %d", unused);
200 return unused;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700201}
202
203
204/*
205 * Get the frequencies that are currently in use by one or more of the virtual
206 * interfaces, and that are also valid for P2P operation.
207 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700208static unsigned int
209wpas_p2p_valid_oper_freqs(struct wpa_supplicant *wpa_s,
210 struct wpa_used_freq_data *p2p_freqs,
211 unsigned int len)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700212{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700213 struct wpa_used_freq_data *freqs;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700214 unsigned int num, i, j;
215
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700216 freqs = os_calloc(wpa_s->num_multichan_concurrent,
217 sizeof(struct wpa_used_freq_data));
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700218 if (!freqs)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700219 return 0;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700220
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700221 num = get_shared_radio_freqs_data(wpa_s, freqs,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000222 wpa_s->num_multichan_concurrent,
223 false);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700224
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700225 os_memset(p2p_freqs, 0, sizeof(struct wpa_used_freq_data) * len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700226
227 for (i = 0, j = 0; i < num && j < len; i++) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700228 if (p2p_supported_freq(wpa_s->global->p2p, freqs[i].freq))
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700229 p2p_freqs[j++] = freqs[i];
230 }
231
232 os_free(freqs);
233
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700234 dump_freq_data(wpa_s, "valid for P2P", p2p_freqs, j);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800235
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700236 return j;
237}
238
239
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700240static void wpas_p2p_set_own_freq_preference(struct wpa_supplicant *wpa_s,
241 int freq)
242{
243 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
244 return;
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -0700245
246 /* Use the wpa_s used to control the P2P Device operation */
247 wpa_s = wpa_s->global->p2p_init_wpa_s;
248
249 if (wpa_s->conf->p2p_ignore_shared_freq &&
Dmitry Shmidta0d265f2013-11-19 13:13:41 -0800250 freq > 0 && wpa_s->num_multichan_concurrent > 1 &&
251 wpas_p2p_num_unused_channels(wpa_s) > 0) {
252 wpa_printf(MSG_DEBUG, "P2P: Ignore own channel preference %d MHz due to p2p_ignore_shared_freq=1 configuration",
253 freq);
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700254 freq = 0;
Dmitry Shmidta0d265f2013-11-19 13:13:41 -0800255 }
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700256 p2p_set_own_freq_preference(wpa_s->global->p2p, freq);
257}
258
259
Hai Shalom60840252021-02-19 19:02:11 -0800260static void wpas_p2p_scan_res_handled(struct wpa_supplicant *wpa_s)
261{
262 unsigned int delay = wpas_p2p_search_delay(wpa_s);
263
264 /* In case of concurrent P2P and external scans, delay P2P search. */
265 if (external_scan_running(wpa_s->radio)) {
266 delay = wpa_s->conf->p2p_search_delay;
267 wpa_printf(MSG_DEBUG,
268 "P2P: Delay next P2P search by %d ms to let externally triggered scan complete",
269 delay);
270 }
271
272 p2p_scan_res_handled(wpa_s->global->p2p, delay);
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
277 struct wpa_scan_results *scan_res)
278{
279 size_t i;
280
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800281 if (wpa_s->p2p_scan_work) {
282 struct wpa_radio_work *work = wpa_s->p2p_scan_work;
283 wpa_s->p2p_scan_work = NULL;
284 radio_work_done(work);
285 }
286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700287 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
288 return;
289
290 wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS)",
291 (int) scan_res->num);
292
293 for (i = 0; i < scan_res->num; i++) {
294 struct wpa_scan_res *bss = scan_res->res[i];
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800295 struct os_reltime time_tmp_age, entry_ts;
Dmitry Shmidt96571392013-10-14 12:54:46 -0700296 const u8 *ies;
297 size_t ies_len;
298
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800299 time_tmp_age.sec = bss->age / 1000;
300 time_tmp_age.usec = (bss->age % 1000) * 1000;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800301 os_reltime_sub(&scan_res->fetch_time, &time_tmp_age, &entry_ts);
Dmitry Shmidt96571392013-10-14 12:54:46 -0700302
303 ies = (const u8 *) (bss + 1);
304 ies_len = bss->ie_len;
305 if (bss->beacon_ie_len > 0 &&
306 !wpa_scan_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
307 wpa_scan_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
308 wpa_printf(MSG_DEBUG, "P2P: Use P2P IE(s) from Beacon frame since no P2P IE(s) in Probe Response frames received for "
309 MACSTR, MAC2STR(bss->bssid));
310 ies = ies + ies_len;
311 ies_len = bss->beacon_ie_len;
312 }
313
314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700315 if (p2p_scan_res_handler(wpa_s->global->p2p, bss->bssid,
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800316 bss->freq, &entry_ts, bss->level,
Dmitry Shmidt96571392013-10-14 12:54:46 -0700317 ies, ies_len) > 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700318 break;
319 }
320
Hai Shalom60840252021-02-19 19:02:11 -0800321 wpas_p2p_scan_res_handled(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700322}
323
324
Hai Shalom60840252021-02-19 19:02:11 -0800325static void wpas_p2p_scan_res_fail_handler(struct wpa_supplicant *wpa_s)
Hai Shalom899fcc72020-10-19 14:38:18 -0700326{
Hai Shalom60840252021-02-19 19:02:11 -0800327 if (wpa_s->p2p_scan_work) {
328 struct wpa_radio_work *work = wpa_s->p2p_scan_work;
Hai Shalom899fcc72020-10-19 14:38:18 -0700329
Hai Shalom60840252021-02-19 19:02:11 -0800330 wpa_s->p2p_scan_work = NULL;
331 radio_work_done(work);
Hai Shalom899fcc72020-10-19 14:38:18 -0700332 }
333
Hai Shalom60840252021-02-19 19:02:11 -0800334 if (wpa_s->global->p2p_disabled || !wpa_s->global->p2p)
335 return;
Hai Shalom899fcc72020-10-19 14:38:18 -0700336
Hai Shalom60840252021-02-19 19:02:11 -0800337 wpa_dbg(wpa_s, MSG_DEBUG,
338 "P2P: Failed to get scan results - try to continue");
339 wpas_p2p_scan_res_handled(wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -0700340}
341
342
Sunil Ravi77d572f2023-01-17 23:58:31 +0000343void wpas_p2p_scan_freqs(struct wpa_supplicant *wpa_s,
344 struct wpa_driver_scan_params *params,
345 bool include_6ghz)
346{
347 wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
348 params, false, false, false);
349 wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
350 params, false, false, false);
351 wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211AD,
352 params, false, false, false);
353 if (!wpa_s->conf->p2p_6ghz_disable &&
354 is_p2p_allow_6ghz(wpa_s->global->p2p) && include_6ghz)
355 wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
356 params, true, true, false);
357}
358
359
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800360static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
361{
362 struct wpa_supplicant *wpa_s = work->wpa_s;
363 struct wpa_driver_scan_params *params = work->ctx;
364 int ret;
365
366 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -0800367 if (!work->started) {
368 wpa_scan_free_params(params);
369 return;
370 }
371
372 wpa_s->p2p_scan_work = NULL;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800373 return;
374 }
375
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800376 if (wpa_s->clear_driver_scan_cache) {
377 wpa_printf(MSG_DEBUG,
378 "Request driver to clear scan cache due to local BSS flush");
379 params->only_new_results = 1;
380 }
Hai Shalom899fcc72020-10-19 14:38:18 -0700381
Sunil Ravi77d572f2023-01-17 23:58:31 +0000382 if (!params->freqs)
383 wpas_p2p_scan_freqs(wpa_s, params, params->p2p_include_6ghz);
384
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800385 ret = wpa_drv_scan(wpa_s, params);
Dmitry Shmidtabb90a32016-12-05 15:34:39 -0800386 if (ret == 0)
387 wpa_s->curr_scan_cookie = params->scan_cookie;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800388 wpa_scan_free_params(params);
389 work->ctx = NULL;
390 if (ret) {
391 radio_work_done(work);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800392 p2p_notify_scan_trigger_status(wpa_s->global->p2p, ret);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800393 return;
394 }
395
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800396 p2p_notify_scan_trigger_status(wpa_s->global->p2p, ret);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800397 os_get_reltime(&wpa_s->scan_trigger_time);
398 wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
Hai Shalom60840252021-02-19 19:02:11 -0800399 wpa_s->scan_res_fail_handler = wpas_p2p_scan_res_fail_handler;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800400 wpa_s->own_scan_requested = 1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800401 wpa_s->clear_driver_scan_cache = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800402 wpa_s->p2p_scan_work = work;
403}
404
405
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800406static int wpas_p2p_search_social_channel(struct wpa_supplicant *wpa_s,
407 int freq)
408{
409 if (wpa_s->global->p2p_24ghz_social_channels &&
410 (freq == 2412 || freq == 2437 || freq == 2462)) {
411 /*
412 * Search all social channels regardless of whether these have
413 * been disabled for P2P operating channel use to avoid missing
414 * peers.
415 */
416 return 1;
417 }
418 return p2p_supported_freq(wpa_s->global->p2p, freq);
419}
420
421
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700422static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
423 unsigned int num_req_dev_types,
Hai Shalomc1a21442022-02-04 13:43:00 -0800424 const u8 *req_dev_types, const u8 *dev_id, u16 pw_id,
425 bool include_6ghz)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700426{
427 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800428 struct wpa_driver_scan_params *params = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700429 struct wpabuf *wps_ie, *ies;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700430 unsigned int num_channels = 0;
431 int social_channels_freq[] = { 2412, 2437, 2462, 60480 };
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800432 size_t ielen;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700433 u8 *n, i;
Dmitry Shmidt9c175262016-03-03 10:20:07 -0800434 unsigned int bands;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700435
436 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
437 return -1;
438
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800439 if (wpa_s->p2p_scan_work) {
440 wpa_dbg(wpa_s, MSG_INFO, "P2P: Reject scan trigger since one is already pending");
441 return -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700442 }
443
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800444 params = os_zalloc(sizeof(*params));
445 if (params == NULL)
446 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700447
448 /* P2P Wildcard SSID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800449 params->num_ssids = 1;
450 n = os_malloc(P2P_WILDCARD_SSID_LEN);
451 if (n == NULL)
452 goto fail;
453 os_memcpy(n, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
454 params->ssids[0].ssid = n;
455 params->ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700456
457 wpa_s->wps->dev.p2p = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700458 wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev,
459 wpa_s->wps->uuid, WPS_REQ_ENROLLEE,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700460 num_req_dev_types, req_dev_types);
461 if (wps_ie == NULL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800462 goto fail;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000463
464 /*
465 * In case 6 GHz channels are requested as part of the P2P scan, only
466 * the PSCs would be included as P2P GOs are not expected to be
467 * collocated, i.e., they would not be announced in the RNR element of
468 * other APs.
469 */
Hai Shalomc1a21442022-02-04 13:43:00 -0800470 if (!wpa_s->conf->p2p_6ghz_disable)
471 params->p2p_include_6ghz = include_6ghz;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700472 switch (type) {
473 case P2P_SCAN_SOCIAL:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700474 params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1,
475 sizeof(int));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800476 if (params->freqs == NULL)
477 goto fail;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700478 for (i = 0; i < ARRAY_SIZE(social_channels_freq); i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800479 if (wpas_p2p_search_social_channel(
480 wpa_s, social_channels_freq[i]))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700481 params->freqs[num_channels++] =
482 social_channels_freq[i];
483 }
484 params->freqs[num_channels++] = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700485 break;
486 case P2P_SCAN_FULL:
487 break;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -0800488 case P2P_SCAN_SPECIFIC:
489 params->freqs = os_calloc(2, sizeof(int));
490 if (params->freqs == NULL)
491 goto fail;
492 params->freqs[0] = freq;
493 params->freqs[1] = 0;
494 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700495 case P2P_SCAN_SOCIAL_PLUS_ONE:
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700496 params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 2,
497 sizeof(int));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800498 if (params->freqs == NULL)
499 goto fail;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700500 for (i = 0; i < ARRAY_SIZE(social_channels_freq); i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800501 if (wpas_p2p_search_social_channel(
502 wpa_s, social_channels_freq[i]))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700503 params->freqs[num_channels++] =
504 social_channels_freq[i];
505 }
506 if (p2p_supported_freq(wpa_s->global->p2p, freq))
507 params->freqs[num_channels++] = freq;
508 params->freqs[num_channels++] = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700509 break;
510 }
511
Dmitry Shmidt9c175262016-03-03 10:20:07 -0800512 ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
513 ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
514 if (ies == NULL) {
515 wpabuf_free(wps_ie);
516 goto fail;
517 }
518 wpabuf_put_buf(ies, wps_ie);
519 wpabuf_free(wps_ie);
520
521 bands = wpas_get_bands(wpa_s, params->freqs);
522 p2p_scan_ie(wpa_s->global->p2p, ies, dev_id, bands);
523
524 params->p2p_probe = 1;
525 n = os_malloc(wpabuf_len(ies));
526 if (n == NULL) {
527 wpabuf_free(ies);
528 goto fail;
529 }
530 os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies));
531 params->extra_ies = n;
532 params->extra_ies_len = wpabuf_len(ies);
533 wpabuf_free(ies);
534
Dmitry Shmidtbd14a572014-02-18 10:33:49 -0800535 radio_remove_works(wpa_s, "p2p-scan", 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800536 if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb,
537 params) < 0)
538 goto fail;
539 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700540
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800541fail:
542 wpa_scan_free_params(params);
543 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700544}
545
546
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700547static enum wpa_driver_if_type wpas_p2p_if_type(int p2p_group_interface)
548{
549 switch (p2p_group_interface) {
550 case P2P_GROUP_INTERFACE_PENDING:
551 return WPA_IF_P2P_GROUP;
552 case P2P_GROUP_INTERFACE_GO:
553 return WPA_IF_P2P_GO;
554 case P2P_GROUP_INTERFACE_CLIENT:
555 return WPA_IF_P2P_CLIENT;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000556 default:
557 return WPA_IF_P2P_GROUP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700558 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700559}
560
561
562static struct wpa_supplicant * wpas_get_p2p_group(struct wpa_supplicant *wpa_s,
563 const u8 *ssid,
564 size_t ssid_len, int *go)
565{
566 struct wpa_ssid *s;
567
568 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
569 for (s = wpa_s->conf->ssid; s; s = s->next) {
570 if (s->disabled != 0 || !s->p2p_group ||
571 s->ssid_len != ssid_len ||
572 os_memcmp(ssid, s->ssid, ssid_len) != 0)
573 continue;
574 if (s->mode == WPAS_MODE_P2P_GO &&
575 s != wpa_s->current_ssid)
576 continue;
577 if (go)
578 *go = s->mode == WPAS_MODE_P2P_GO;
579 return wpa_s;
580 }
581 }
582
583 return NULL;
584}
585
586
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800587static void run_wpas_p2p_disconnect(void *eloop_ctx, void *timeout_ctx)
588{
589 struct wpa_supplicant *wpa_s = eloop_ctx;
590 wpa_printf(MSG_DEBUG,
591 "P2P: Complete previously requested removal of %s",
592 wpa_s->ifname);
593 wpas_p2p_disconnect(wpa_s);
594}
595
596
597static int wpas_p2p_disconnect_safely(struct wpa_supplicant *wpa_s,
598 struct wpa_supplicant *calling_wpa_s)
599{
600 if (calling_wpa_s == wpa_s && wpa_s &&
601 wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
602 /*
603 * The calling wpa_s instance is going to be removed. Do that
604 * from an eloop callback to keep the instance available until
Hai Shalom899fcc72020-10-19 14:38:18 -0700605 * the caller has returned. This may be needed, e.g., to provide
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800606 * control interface responses on the per-interface socket.
607 */
608 if (eloop_register_timeout(0, 0, run_wpas_p2p_disconnect,
609 wpa_s, NULL) < 0)
610 return -1;
611 return 0;
612 }
613
614 return wpas_p2p_disconnect(wpa_s);
615}
616
617
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800618/* Determine total number of clients in active groups where we are the GO */
619static unsigned int p2p_group_go_member_count(struct wpa_supplicant *wpa_s)
620{
621 unsigned int count = 0;
622 struct wpa_ssid *s;
623
624 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
625 for (s = wpa_s->conf->ssid; s; s = s->next) {
626 wpa_printf(MSG_DEBUG,
627 "P2P: sup:%p ssid:%p disabled:%d p2p:%d mode:%d",
628 wpa_s, s, s->disabled, s->p2p_group,
629 s->mode);
630 if (!s->disabled && s->p2p_group &&
631 s->mode == WPAS_MODE_P2P_GO) {
632 count += p2p_get_group_num_members(
633 wpa_s->p2p_group);
634 }
635 }
636 }
637
638 return count;
639}
640
641
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800642static unsigned int p2p_is_active_persistent_group(struct wpa_supplicant *wpa_s)
643{
644 return !wpa_s->p2p_mgmt && wpa_s->current_ssid &&
645 !wpa_s->current_ssid->disabled &&
646 wpa_s->current_ssid->p2p_group &&
647 wpa_s->current_ssid->p2p_persistent_group;
648}
649
650
651static unsigned int p2p_is_active_persistent_go(struct wpa_supplicant *wpa_s)
652{
653 return p2p_is_active_persistent_group(wpa_s) &&
654 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO;
655}
656
657
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800658/* Find an interface for a P2P group where we are the GO */
659static struct wpa_supplicant *
660wpas_p2p_get_go_group(struct wpa_supplicant *wpa_s)
661{
662 struct wpa_supplicant *save = NULL;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800663
664 if (!wpa_s)
665 return NULL;
666
667 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800668 if (!p2p_is_active_persistent_go(wpa_s))
669 continue;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800670
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800671 /* Prefer a group with connected clients */
672 if (p2p_get_group_num_members(wpa_s->p2p_group))
673 return wpa_s;
674 save = wpa_s;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800675 }
676
677 /* No group with connected clients, so pick the one without (if any) */
678 return save;
679}
680
681
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800682static unsigned int p2p_is_active_persistent_cli(struct wpa_supplicant *wpa_s)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800683{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800684 return p2p_is_active_persistent_group(wpa_s) &&
685 wpa_s->current_ssid->mode == WPAS_MODE_INFRA;
686}
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800687
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800688
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800689/* Find an interface for a P2P group where we are the P2P Client */
690static struct wpa_supplicant *
691wpas_p2p_get_cli_group(struct wpa_supplicant *wpa_s)
692{
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800693 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800694 if (p2p_is_active_persistent_cli(wpa_s))
695 return wpa_s;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800696 }
697
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800698 return NULL;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800699}
700
701
702/* Find a persistent group where we are the GO */
703static struct wpa_ssid *
704wpas_p2p_get_persistent_go(struct wpa_supplicant *wpa_s)
705{
706 struct wpa_ssid *s;
707
708 for (s = wpa_s->conf->ssid; s; s = s->next) {
709 if (s->disabled == 2 && s->mode == WPAS_MODE_P2P_GO)
710 return s;
711 }
712
713 return NULL;
714}
715
716
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800717static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role,
718 unsigned int *force_freq,
719 unsigned int *pref_freq)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800720{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800721 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800722 struct wpa_ssid *s;
723 u8 conncap = P2PS_SETUP_NONE;
724 unsigned int owned_members = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800725 struct wpa_supplicant *go_wpa_s, *cli_wpa_s;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800726 struct wpa_ssid *persistent_go;
727 int p2p_no_group_iface;
Sunil8cd6f4d2022-06-28 18:40:46 +0000728 struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
729 unsigned int size;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800730
731 wpa_printf(MSG_DEBUG, "P2P: Conncap - in:%d role:%d", incoming, role);
732
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800733 if (force_freq)
734 *force_freq = 0;
735 if (pref_freq)
736 *pref_freq = 0;
737
738 size = P2P_MAX_PREF_CHANNELS;
739 if (force_freq && pref_freq &&
740 !wpas_p2p_setup_freqs(wpa_s, 0, (int *) force_freq,
741 (int *) pref_freq, 0, pref_freq_list, &size))
742 wpas_p2p_set_own_freq_preference(wpa_s,
743 *force_freq ? *force_freq :
744 *pref_freq);
745
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800746 /*
747 * For non-concurrent capable devices:
748 * If persistent_go, then no new.
749 * If GO, then no client.
750 * If client, then no GO.
751 */
752 go_wpa_s = wpas_p2p_get_go_group(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800753 if (go_wpa_s)
754 owned_members = p2p_get_group_num_members(go_wpa_s->p2p_group);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800755 persistent_go = wpas_p2p_get_persistent_go(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800756 p2p_no_group_iface = !wpas_p2p_create_iface(wpa_s);
757 cli_wpa_s = wpas_p2p_get_cli_group(wpa_s);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800758
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800759 wpa_printf(MSG_DEBUG,
760 "P2P: GO(iface)=%p members=%u CLI(iface)=%p persistent(ssid)=%p",
761 go_wpa_s, owned_members, cli_wpa_s, persistent_go);
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800762
763 /* If not concurrent, restrict our choices */
764 if (p2p_no_group_iface) {
765 wpa_printf(MSG_DEBUG, "P2P: p2p_no_group_iface");
766
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800767 if (cli_wpa_s)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800768 return P2PS_SETUP_NONE;
769
770 if (go_wpa_s) {
771 if (role == P2PS_SETUP_CLIENT ||
772 incoming == P2PS_SETUP_GROUP_OWNER ||
773 p2p_client_limit_reached(go_wpa_s->p2p_group))
774 return P2PS_SETUP_NONE;
775
776 return P2PS_SETUP_GROUP_OWNER;
777 }
778
779 if (persistent_go) {
780 if (role == P2PS_SETUP_NONE || role == P2PS_SETUP_NEW) {
781 if (!incoming)
782 return P2PS_SETUP_GROUP_OWNER |
783 P2PS_SETUP_CLIENT;
784 if (incoming == P2PS_SETUP_NEW) {
785 u8 r;
786
787 if (os_get_random(&r, sizeof(r)) < 0 ||
788 (r & 1))
789 return P2PS_SETUP_CLIENT;
790 return P2PS_SETUP_GROUP_OWNER;
791 }
792 }
793 }
794 }
795
796 /* If a required role has been specified, handle it here */
797 if (role && role != P2PS_SETUP_NEW) {
798 switch (incoming) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800799 case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
800 case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
801 /*
802 * Peer has an active GO, so if the role allows it and
803 * we do not have any active roles, become client.
804 */
805 if ((role & P2PS_SETUP_CLIENT) && !go_wpa_s &&
806 !cli_wpa_s)
807 return P2PS_SETUP_CLIENT;
808
809 /* fall through */
810
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800811 case P2PS_SETUP_NONE:
812 case P2PS_SETUP_NEW:
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800813 conncap = role;
814 goto grp_owner;
815
816 case P2PS_SETUP_GROUP_OWNER:
817 /*
818 * Must be a complimentary role - cannot be a client to
819 * more than one peer.
820 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800821 if (incoming == role || cli_wpa_s)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800822 return P2PS_SETUP_NONE;
823
824 return P2PS_SETUP_CLIENT;
825
826 case P2PS_SETUP_CLIENT:
827 /* Must be a complimentary role */
828 if (incoming != role) {
829 conncap = P2PS_SETUP_GROUP_OWNER;
830 goto grp_owner;
831 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700832 /* fall through */
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800833
834 default:
835 return P2PS_SETUP_NONE;
836 }
837 }
838
839 /*
840 * For now, we only will support ownership of one group, and being a
841 * client of one group. Therefore, if we have either an existing GO
842 * group, or an existing client group, we will not do a new GO
843 * negotiation, but rather try to re-use the existing groups.
844 */
845 switch (incoming) {
846 case P2PS_SETUP_NONE:
847 case P2PS_SETUP_NEW:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800848 if (cli_wpa_s)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800849 conncap = P2PS_SETUP_GROUP_OWNER;
850 else if (!owned_members)
851 conncap = P2PS_SETUP_NEW;
852 else if (incoming == P2PS_SETUP_NONE)
853 conncap = P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT;
854 else
855 conncap = P2PS_SETUP_CLIENT;
856 break;
857
858 case P2PS_SETUP_CLIENT:
859 conncap = P2PS_SETUP_GROUP_OWNER;
860 break;
861
862 case P2PS_SETUP_GROUP_OWNER:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800863 if (!cli_wpa_s)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800864 conncap = P2PS_SETUP_CLIENT;
865 break;
866
867 case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
868 case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800869 if (cli_wpa_s)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800870 conncap = P2PS_SETUP_GROUP_OWNER;
871 else {
872 u8 r;
873
874 if (os_get_random(&r, sizeof(r)) < 0 ||
875 (r & 1))
876 conncap = P2PS_SETUP_CLIENT;
877 else
878 conncap = P2PS_SETUP_GROUP_OWNER;
879 }
880 break;
881
882 default:
883 return P2PS_SETUP_NONE;
884 }
885
886grp_owner:
887 if ((conncap & P2PS_SETUP_GROUP_OWNER) ||
888 (!incoming && (conncap & P2PS_SETUP_NEW))) {
889 if (go_wpa_s && p2p_client_limit_reached(go_wpa_s->p2p_group))
890 conncap &= ~P2PS_SETUP_GROUP_OWNER;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800891
892 s = wpas_p2p_get_persistent_go(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800893 if (!s && !go_wpa_s && p2p_no_group_iface) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800894 p2p_set_intended_addr(wpa_s->global->p2p,
Dmitry Shmidt9c175262016-03-03 10:20:07 -0800895 wpa_s->p2p_mgmt ?
896 wpa_s->parent->own_addr :
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800897 wpa_s->own_addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800898 } else if (!s && !go_wpa_s) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800899 if (wpas_p2p_add_group_interface(wpa_s,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800900 WPA_IF_P2P_GROUP) < 0) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800901 wpa_printf(MSG_ERROR,
902 "P2P: Failed to allocate a new interface for the group");
903 return P2PS_SETUP_NONE;
904 }
905 wpa_s->global->pending_group_iface_for_p2ps = 1;
906 p2p_set_intended_addr(wpa_s->global->p2p,
907 wpa_s->pending_interface_addr);
908 }
909 }
910
911 return conncap;
912}
913
914
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700915static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
916 enum p2p_group_removal_reason removal_reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917{
918 struct wpa_ssid *ssid;
919 char *gtype;
920 const char *reason;
921
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700922 ssid = wpa_s->current_ssid;
923 if (ssid == NULL) {
924 /*
925 * The current SSID was not known, but there may still be a
Dmitry Shmidtaa532512012-09-24 10:35:31 -0700926 * pending P2P group interface waiting for provisioning or a
927 * P2P group that is trying to reconnect.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700928 */
929 ssid = wpa_s->conf->ssid;
930 while (ssid) {
Jouni Malinen9d712832012-10-05 11:01:57 -0700931 if (ssid->p2p_group && ssid->disabled != 2)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700932 break;
933 ssid = ssid->next;
934 }
Jouni Malinen5c44edb2012-08-31 21:35:32 +0300935 if (ssid == NULL &&
936 wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE)
937 {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700938 wpa_printf(MSG_ERROR, "P2P: P2P group interface "
939 "not found");
940 return -1;
941 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942 }
943 if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_GO)
944 gtype = "GO";
945 else if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT ||
946 (ssid && ssid->mode == WPAS_MODE_INFRA)) {
947 wpa_s->reassociate = 0;
948 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700949 gtype = "client";
950 } else
951 gtype = "GO";
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700952
953 if (removal_reason != P2P_GROUP_REMOVAL_SILENT && ssid)
954 wpas_notify_p2p_group_removed(wpa_s, ssid, gtype);
955
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800956 if (os_strcmp(gtype, "client") == 0) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700957 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800958 if (eloop_is_timeout_registered(wpas_p2p_psk_failure_removal,
959 wpa_s, NULL)) {
960 wpa_printf(MSG_DEBUG,
961 "P2P: PSK failure removal was scheduled, so use PSK failure as reason for group removal");
962 removal_reason = P2P_GROUP_REMOVAL_PSK_FAILURE;
963 eloop_cancel_timeout(wpas_p2p_psk_failure_removal,
964 wpa_s, NULL);
965 }
966 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700968 if (wpa_s->cross_connect_in_use) {
969 wpa_s->cross_connect_in_use = 0;
Dmitry Shmidt9c175262016-03-03 10:20:07 -0800970 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -0700971 P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
972 wpa_s->ifname, wpa_s->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700974 switch (removal_reason) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700975 case P2P_GROUP_REMOVAL_REQUESTED:
976 reason = " reason=REQUESTED";
977 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700978 case P2P_GROUP_REMOVAL_FORMATION_FAILED:
979 reason = " reason=FORMATION_FAILED";
980 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700981 case P2P_GROUP_REMOVAL_IDLE_TIMEOUT:
982 reason = " reason=IDLE";
983 break;
984 case P2P_GROUP_REMOVAL_UNAVAILABLE:
985 reason = " reason=UNAVAILABLE";
986 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700987 case P2P_GROUP_REMOVAL_GO_ENDING_SESSION:
988 reason = " reason=GO_ENDING_SESSION";
989 break;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -0700990 case P2P_GROUP_REMOVAL_PSK_FAILURE:
991 reason = " reason=PSK_FAILURE";
992 break;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800993 case P2P_GROUP_REMOVAL_FREQ_CONFLICT:
994 reason = " reason=FREQ_CONFLICT";
995 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996 default:
997 reason = "";
998 break;
999 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001000 if (removal_reason != P2P_GROUP_REMOVAL_SILENT) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001001 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001002 P2P_EVENT_GROUP_REMOVED "%s %s%s",
1003 wpa_s->ifname, gtype, reason);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001004 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001005
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001006 if (eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL) > 0)
1007 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group freq_conflict timeout");
Dmitry Shmidt04949592012-07-19 12:16:46 -07001008 if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
1009 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001010 if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001011 wpa_s->p2pdev, NULL) > 0) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001012 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group formation "
1013 "timeout");
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001014 wpa_s->p2p_in_provisioning = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001015 wpas_p2p_group_formation_failed(wpa_s, 1);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001016 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001017
Dmitry Shmidt15907092014-03-25 10:42:57 -07001018 wpa_s->p2p_in_invitation = 0;
Matthew Wang06b42472022-11-10 06:56:31 +00001019 wpa_s->p2p_retry_limit = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001020 eloop_cancel_timeout(wpas_p2p_move_go, wpa_s, NULL);
1021 eloop_cancel_timeout(wpas_p2p_reconsider_moving_go, wpa_s, NULL);
Dmitry Shmidt15907092014-03-25 10:42:57 -07001022
Dmitry Shmidt96571392013-10-14 12:54:46 -07001023 /*
1024 * Make sure wait for the first client does not remain active after the
1025 * group has been removed.
1026 */
1027 wpa_s->global->p2p_go_wait_client.sec = 0;
1028
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001029 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
1030 struct wpa_global *global;
1031 char *ifname;
1032 enum wpa_driver_if_type type;
1033 wpa_printf(MSG_DEBUG, "P2P: Remove group interface %s",
1034 wpa_s->ifname);
1035 global = wpa_s->global;
1036 ifname = os_strdup(wpa_s->ifname);
1037 type = wpas_p2p_if_type(wpa_s->p2p_group_interface);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001038 eloop_cancel_timeout(run_wpas_p2p_disconnect, wpa_s, NULL);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07001039 wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001040 wpa_s = global->ifaces;
1041 if (wpa_s && ifname)
1042 wpa_drv_if_remove(wpa_s, type, ifname);
1043 os_free(ifname);
Jouni Malinen2b89da82012-08-31 22:04:41 +03001044 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045 }
1046
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001047 /*
1048 * The primary interface was used for P2P group operations, so
1049 * need to reset its p2pdev.
1050 */
1051 wpa_s->p2pdev = wpa_s->parent;
1052
Dmitry Shmidt96571392013-10-14 12:54:46 -07001053 if (!wpa_s->p2p_go_group_formation_completed) {
1054 wpa_s->global->p2p_group_formation = NULL;
1055 wpa_s->p2p_in_provisioning = 0;
1056 }
1057
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001058 wpa_s->show_group_started = 0;
1059 os_free(wpa_s->go_params);
1060 wpa_s->go_params = NULL;
1061
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001062 os_free(wpa_s->p2p_group_common_freqs);
1063 wpa_s->p2p_group_common_freqs = NULL;
1064 wpa_s->p2p_group_common_freqs_num = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001065 wpa_s->p2p_go_do_acs = 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08001066 wpa_s->p2p_go_allow_dfs = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001067
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001068 wpa_s->waiting_presence_resp = 0;
1069
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001070 wpa_printf(MSG_DEBUG, "P2P: Remove temporary group network");
1071 if (ssid && (ssid->p2p_group ||
1072 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION ||
1073 (ssid->key_mgmt & WPA_KEY_MGMT_WPS))) {
1074 int id = ssid->id;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001075 if (ssid == wpa_s->current_ssid) {
1076 wpa_sm_set_config(wpa_s->wpa, NULL);
1077 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078 wpa_s->current_ssid = NULL;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001079 }
1080 /*
1081 * Networks objects created during any P2P activities are not
1082 * exposed out as they might/will confuse certain non-P2P aware
1083 * applications since these network objects won't behave like
1084 * regular ones.
1085 *
1086 * Likewise, we don't send out network removed signals for such
1087 * network objects.
1088 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089 wpa_config_remove_network(wpa_s->conf, id);
1090 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001091 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001092 } else {
1093 wpa_printf(MSG_DEBUG, "P2P: Temporary group network not "
1094 "found");
1095 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001096 if (wpa_s->ap_iface)
1097 wpa_supplicant_ap_deinit(wpa_s);
1098 else
1099 wpa_drv_deinit_p2p_cli(wpa_s);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001100
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001101 os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
1102
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001103 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104}
1105
1106
1107static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s,
1108 u8 *go_dev_addr,
1109 const u8 *ssid, size_t ssid_len)
1110{
1111 struct wpa_bss *bss;
1112 const u8 *bssid;
1113 struct wpabuf *p2p;
1114 u8 group_capab;
1115 const u8 *addr;
1116
1117 if (wpa_s->go_params)
1118 bssid = wpa_s->go_params->peer_interface_addr;
1119 else
1120 bssid = wpa_s->bssid;
1121
1122 bss = wpa_bss_get(wpa_s, bssid, ssid, ssid_len);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001123 if (bss == NULL && wpa_s->go_params &&
1124 !is_zero_ether_addr(wpa_s->go_params->peer_device_addr))
1125 bss = wpa_bss_get_p2p_dev_addr(
1126 wpa_s, wpa_s->go_params->peer_device_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001127 if (bss == NULL) {
1128 u8 iface_addr[ETH_ALEN];
1129 if (p2p_get_interface_addr(wpa_s->global->p2p, bssid,
1130 iface_addr) == 0)
1131 bss = wpa_bss_get(wpa_s, iface_addr, ssid, ssid_len);
1132 }
1133 if (bss == NULL) {
1134 wpa_printf(MSG_DEBUG, "P2P: Could not figure out whether "
1135 "group is persistent - BSS " MACSTR " not found",
1136 MAC2STR(bssid));
1137 return 0;
1138 }
1139
1140 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
Dmitry Shmidt96571392013-10-14 12:54:46 -07001141 if (p2p == NULL)
1142 p2p = wpa_bss_get_vendor_ie_multi_beacon(bss,
1143 P2P_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001144 if (p2p == NULL) {
1145 wpa_printf(MSG_DEBUG, "P2P: Could not figure out whether "
1146 "group is persistent - BSS " MACSTR
1147 " did not include P2P IE", MAC2STR(bssid));
1148 wpa_hexdump(MSG_DEBUG, "P2P: Probe Response IEs",
Hai Shalom60840252021-02-19 19:02:11 -08001149 wpa_bss_ie_ptr(bss), bss->ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001150 wpa_hexdump(MSG_DEBUG, "P2P: Beacon IEs",
Hai Shalom60840252021-02-19 19:02:11 -08001151 wpa_bss_ie_ptr(bss) + bss->ie_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001152 bss->beacon_ie_len);
1153 return 0;
1154 }
1155
1156 group_capab = p2p_get_group_capab(p2p);
1157 addr = p2p_get_go_dev_addr(p2p);
1158 wpa_printf(MSG_DEBUG, "P2P: Checking whether group is persistent: "
1159 "group_capab=0x%x", group_capab);
1160 if (addr) {
1161 os_memcpy(go_dev_addr, addr, ETH_ALEN);
1162 wpa_printf(MSG_DEBUG, "P2P: GO Device Address " MACSTR,
1163 MAC2STR(addr));
1164 } else
1165 os_memset(go_dev_addr, 0, ETH_ALEN);
1166 wpabuf_free(p2p);
1167
1168 wpa_printf(MSG_DEBUG, "P2P: BSS " MACSTR " group_capab=0x%x "
1169 "go_dev_addr=" MACSTR,
1170 MAC2STR(bssid), group_capab, MAC2STR(go_dev_addr));
1171
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07001172 return !!(group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001173}
1174
1175
Jouni Malinen75ecf522011-06-27 15:19:46 -07001176static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s,
1177 struct wpa_ssid *ssid,
1178 const u8 *go_dev_addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001179{
1180 struct wpa_ssid *s;
1181 int changed = 0;
1182
1183 wpa_printf(MSG_DEBUG, "P2P: Storing credentials for a persistent "
1184 "group (GO Dev Addr " MACSTR ")", MAC2STR(go_dev_addr));
1185 for (s = wpa_s->conf->ssid; s; s = s->next) {
1186 if (s->disabled == 2 &&
1187 os_memcmp(go_dev_addr, s->bssid, ETH_ALEN) == 0 &&
1188 s->ssid_len == ssid->ssid_len &&
1189 os_memcmp(ssid->ssid, s->ssid, ssid->ssid_len) == 0)
1190 break;
1191 }
1192
1193 if (s) {
1194 wpa_printf(MSG_DEBUG, "P2P: Update existing persistent group "
1195 "entry");
1196 if (ssid->passphrase && !s->passphrase)
1197 changed = 1;
1198 else if (ssid->passphrase && s->passphrase &&
1199 os_strcmp(ssid->passphrase, s->passphrase) != 0)
1200 changed = 1;
1201 } else {
1202 wpa_printf(MSG_DEBUG, "P2P: Create a new persistent group "
1203 "entry");
1204 changed = 1;
1205 s = wpa_config_add_network(wpa_s->conf);
1206 if (s == NULL)
Jouni Malinen75ecf522011-06-27 15:19:46 -07001207 return -1;
1208
1209 /*
1210 * Instead of network_added we emit persistent_group_added
1211 * notification. Also to keep the defense checks in
1212 * persistent_group obj registration method, we set the
1213 * relevant flags in s to designate it as a persistent group.
1214 */
1215 s->p2p_group = 1;
1216 s->p2p_persistent_group = 1;
1217 wpas_notify_persistent_group_added(wpa_s, s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001218 wpa_config_set_network_defaults(s);
1219 }
1220
1221 s->p2p_group = 1;
1222 s->p2p_persistent_group = 1;
1223 s->disabled = 2;
1224 s->bssid_set = 1;
1225 os_memcpy(s->bssid, go_dev_addr, ETH_ALEN);
1226 s->mode = ssid->mode;
1227 s->auth_alg = WPA_AUTH_ALG_OPEN;
1228 s->key_mgmt = WPA_KEY_MGMT_PSK;
1229 s->proto = WPA_PROTO_RSN;
Dmitry Shmidte4663042016-04-04 10:07:49 -07001230 s->pbss = ssid->pbss;
1231 s->pairwise_cipher = ssid->pbss ? WPA_CIPHER_GCMP : WPA_CIPHER_CCMP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001232 s->export_keys = 1;
1233 if (ssid->passphrase) {
1234 os_free(s->passphrase);
1235 s->passphrase = os_strdup(ssid->passphrase);
1236 }
1237 if (ssid->psk_set) {
1238 s->psk_set = 1;
1239 os_memcpy(s->psk, ssid->psk, 32);
1240 }
1241 if (s->passphrase && !s->psk_set)
1242 wpa_config_update_psk(s);
1243 if (s->ssid == NULL || s->ssid_len < ssid->ssid_len) {
1244 os_free(s->ssid);
1245 s->ssid = os_malloc(ssid->ssid_len);
1246 }
1247 if (s->ssid) {
1248 s->ssid_len = ssid->ssid_len;
1249 os_memcpy(s->ssid, ssid->ssid, s->ssid_len);
1250 }
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001251 if (ssid->mode == WPAS_MODE_P2P_GO && wpa_s->global->add_psk) {
1252 dl_list_add(&s->psk_list, &wpa_s->global->add_psk->list);
1253 wpa_s->global->add_psk = NULL;
1254 changed = 1;
1255 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001257 if (changed && wpa_s->conf->update_config &&
1258 wpa_config_write(wpa_s->confname, wpa_s->conf)) {
1259 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
1260 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07001261
1262 return s->id;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001263}
1264
1265
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001266static void wpas_p2p_add_persistent_group_client(struct wpa_supplicant *wpa_s,
1267 const u8 *addr)
1268{
1269 struct wpa_ssid *ssid, *s;
1270 u8 *n;
1271 size_t i;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001272 int found = 0;
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07001273 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001274
1275 ssid = wpa_s->current_ssid;
1276 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
1277 !ssid->p2p_persistent_group)
1278 return;
1279
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07001280 for (s = p2p_wpa_s->conf->ssid; s; s = s->next) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001281 if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
1282 continue;
1283
1284 if (s->ssid_len == ssid->ssid_len &&
1285 os_memcmp(s->ssid, ssid->ssid, s->ssid_len) == 0)
1286 break;
1287 }
1288
1289 if (s == NULL)
1290 return;
1291
1292 for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001293 if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN, addr,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001294 ETH_ALEN) != 0)
1295 continue;
1296
1297 if (i == s->num_p2p_clients - 1)
1298 return; /* already the most recent entry */
1299
1300 /* move the entry to mark it most recent */
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001301 os_memmove(s->p2p_client_list + i * 2 * ETH_ALEN,
1302 s->p2p_client_list + (i + 1) * 2 * ETH_ALEN,
1303 (s->num_p2p_clients - i - 1) * 2 * ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001304 os_memcpy(s->p2p_client_list +
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001305 (s->num_p2p_clients - 1) * 2 * ETH_ALEN, addr,
1306 ETH_ALEN);
1307 os_memset(s->p2p_client_list +
1308 (s->num_p2p_clients - 1) * 2 * ETH_ALEN + ETH_ALEN,
1309 0xff, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001310 found = 1;
1311 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001312 }
1313
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001314 if (!found && s->num_p2p_clients < P2P_MAX_STORED_CLIENTS) {
1315 n = os_realloc_array(s->p2p_client_list,
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001316 s->num_p2p_clients + 1, 2 * ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001317 if (n == NULL)
1318 return;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001319 os_memcpy(n + s->num_p2p_clients * 2 * ETH_ALEN, addr,
1320 ETH_ALEN);
1321 os_memset(n + s->num_p2p_clients * 2 * ETH_ALEN + ETH_ALEN,
1322 0xff, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001323 s->p2p_client_list = n;
1324 s->num_p2p_clients++;
Dmitry Shmidt6aa8ae42014-07-07 09:31:33 -07001325 } else if (!found && s->p2p_client_list) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001326 /* Not enough room for an additional entry - drop the oldest
1327 * entry */
1328 os_memmove(s->p2p_client_list,
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001329 s->p2p_client_list + 2 * ETH_ALEN,
1330 (s->num_p2p_clients - 1) * 2 * ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001331 os_memcpy(s->p2p_client_list +
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001332 (s->num_p2p_clients - 1) * 2 * ETH_ALEN,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001333 addr, ETH_ALEN);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001334 os_memset(s->p2p_client_list +
1335 (s->num_p2p_clients - 1) * 2 * ETH_ALEN + ETH_ALEN,
1336 0xff, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001337 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001338
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07001339 if (p2p_wpa_s->conf->update_config &&
1340 wpa_config_write(p2p_wpa_s->confname, p2p_wpa_s->conf))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001341 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001342}
1343
1344
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07001345static void wpas_p2p_group_started(struct wpa_supplicant *wpa_s,
1346 int go, struct wpa_ssid *ssid, int freq,
1347 const u8 *psk, const char *passphrase,
1348 const u8 *go_dev_addr, int persistent,
1349 const char *extra)
1350{
1351 const char *ssid_txt;
1352 char psk_txt[65];
1353
1354 if (psk)
1355 wpa_snprintf_hex(psk_txt, sizeof(psk_txt), psk, 32);
1356 else
1357 psk_txt[0] = '\0';
1358
1359 if (ssid)
1360 ssid_txt = wpa_ssid_txt(ssid->ssid, ssid->ssid_len);
1361 else
1362 ssid_txt = "";
1363
1364 if (passphrase && passphrase[0] == '\0')
1365 passphrase = NULL;
1366
1367 /*
1368 * Include PSK/passphrase only in the control interface message and
1369 * leave it out from the debug log entry.
1370 */
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001371 wpa_msg_global_ctrl(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07001372 P2P_EVENT_GROUP_STARTED
1373 "%s %s ssid=\"%s\" freq=%d%s%s%s%s%s go_dev_addr="
1374 MACSTR "%s%s",
1375 wpa_s->ifname, go ? "GO" : "client", ssid_txt, freq,
1376 psk ? " psk=" : "", psk_txt,
1377 passphrase ? " passphrase=\"" : "",
1378 passphrase ? passphrase : "",
1379 passphrase ? "\"" : "",
1380 MAC2STR(go_dev_addr),
1381 persistent ? " [PERSISTENT]" : "", extra);
1382 wpa_printf(MSG_INFO, P2P_EVENT_GROUP_STARTED
1383 "%s %s ssid=\"%s\" freq=%d go_dev_addr=" MACSTR "%s%s",
1384 wpa_s->ifname, go ? "GO" : "client", ssid_txt, freq,
1385 MAC2STR(go_dev_addr), persistent ? " [PERSISTENT]" : "",
1386 extra);
1387}
1388
1389
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001390static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001391 int success, int already_deleted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392{
1393 struct wpa_ssid *ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001394 int client;
1395 int persistent;
1396 u8 go_dev_addr[ETH_ALEN];
1397
1398 /*
1399 * This callback is likely called for the main interface. Update wpa_s
1400 * to use the group interface if a new interface was created for the
1401 * group.
1402 */
1403 if (wpa_s->global->p2p_group_formation)
1404 wpa_s = wpa_s->global->p2p_group_formation;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001405 if (wpa_s->p2p_go_group_formation_completed) {
1406 wpa_s->global->p2p_group_formation = NULL;
1407 wpa_s->p2p_in_provisioning = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001408 } else if (wpa_s->p2p_in_provisioning && !success) {
1409 wpa_msg(wpa_s, MSG_DEBUG,
1410 "P2P: Stop provisioning state due to failure");
1411 wpa_s->p2p_in_provisioning = 0;
Dmitry Shmidt56052862013-10-04 10:23:25 -07001412 }
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001413 wpa_s->p2p_in_invitation = 0;
Matthew Wang06b42472022-11-10 06:56:31 +00001414 wpa_s->p2p_retry_limit = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001415 wpa_s->group_formation_reported = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416
1417 if (!success) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001418 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001419 P2P_EVENT_GROUP_FORMATION_FAILURE);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001420 wpas_notify_p2p_group_formation_failure(wpa_s, "");
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07001421 if (already_deleted)
1422 return;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001423 wpas_p2p_group_delete(wpa_s,
1424 P2P_GROUP_REMOVAL_FORMATION_FAILED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001425 return;
1426 }
1427
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001428 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07001429 P2P_EVENT_GROUP_FORMATION_SUCCESS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001430
1431 ssid = wpa_s->current_ssid;
1432 if (ssid && ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1433 ssid->mode = WPAS_MODE_P2P_GO;
1434 p2p_group_notif_formation_done(wpa_s->p2p_group);
1435 wpa_supplicant_ap_mac_addr_filter(wpa_s, NULL);
1436 }
1437
1438 persistent = 0;
1439 if (ssid) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001440 client = ssid->mode == WPAS_MODE_INFRA;
1441 if (ssid->mode == WPAS_MODE_P2P_GO) {
1442 persistent = ssid->p2p_persistent_group;
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001443 os_memcpy(go_dev_addr, wpa_s->global->p2p_dev_addr,
1444 ETH_ALEN);
George Burgess IV0d2d1bf2021-11-01 03:08:33 -07001445 } else {
1446 os_memset(go_dev_addr, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001447 persistent = wpas_p2p_persistent_group(wpa_s,
1448 go_dev_addr,
1449 ssid->ssid,
1450 ssid->ssid_len);
George Burgess IV0d2d1bf2021-11-01 03:08:33 -07001451 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001453 client = wpa_s->p2p_group_interface ==
1454 P2P_GROUP_INTERFACE_CLIENT;
1455 os_memset(go_dev_addr, 0, ETH_ALEN);
1456 }
1457
1458 wpa_s->show_group_started = 0;
1459 if (client) {
1460 /*
1461 * Indicate event only after successfully completed 4-way
1462 * handshake, i.e., when the interface is ready for data
1463 * packets.
1464 */
1465 wpa_s->show_group_started = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466 } else {
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07001467 wpas_p2p_group_started(wpa_s, 1, ssid,
1468 ssid ? ssid->frequency : 0,
1469 ssid && ssid->passphrase == NULL &&
1470 ssid->psk_set ? ssid->psk : NULL,
1471 ssid ? ssid->passphrase : NULL,
1472 go_dev_addr, persistent, "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001473 wpas_p2p_cross_connect_setup(wpa_s);
1474 wpas_p2p_set_group_idle_timeout(wpa_s);
1475 }
1476
1477 if (persistent)
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001478 wpas_p2p_store_persistent_group(wpa_s->p2pdev,
1479 ssid, go_dev_addr);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001480 else {
1481 os_free(wpa_s->global->add_psk);
1482 wpa_s->global->add_psk = NULL;
1483 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001484
Dmitry Shmidt92c368d2013-08-29 12:37:21 -07001485 if (!client) {
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08001486 wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 0, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001487 os_get_reltime(&wpa_s->global->p2p_go_wait_client);
Dmitry Shmidt92c368d2013-08-29 12:37:21 -07001488 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489}
1490
1491
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001492struct send_action_work {
1493 unsigned int freq;
1494 u8 dst[ETH_ALEN];
1495 u8 src[ETH_ALEN];
1496 u8 bssid[ETH_ALEN];
1497 size_t len;
1498 unsigned int wait_time;
1499 u8 buf[0];
1500};
1501
1502
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001503static void wpas_p2p_free_send_action_work(struct wpa_supplicant *wpa_s)
1504{
1505 struct send_action_work *awork = wpa_s->p2p_send_action_work->ctx;
1506
1507 wpa_printf(MSG_DEBUG,
1508 "P2P: Free Action frame radio work @%p (freq=%u dst="
1509 MACSTR " src=" MACSTR " bssid=" MACSTR " wait_time=%u)",
1510 wpa_s->p2p_send_action_work, awork->freq,
1511 MAC2STR(awork->dst), MAC2STR(awork->src),
1512 MAC2STR(awork->bssid), awork->wait_time);
1513 wpa_hexdump(MSG_DEBUG, "P2P: Freeing pending Action frame",
1514 awork->buf, awork->len);
1515 os_free(awork);
1516 wpa_s->p2p_send_action_work->ctx = NULL;
1517 radio_work_done(wpa_s->p2p_send_action_work);
1518 wpa_s->p2p_send_action_work = NULL;
1519}
1520
1521
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001522static void wpas_p2p_send_action_work_timeout(void *eloop_ctx,
1523 void *timeout_ctx)
1524{
1525 struct wpa_supplicant *wpa_s = eloop_ctx;
1526
1527 if (!wpa_s->p2p_send_action_work)
1528 return;
1529
1530 wpa_printf(MSG_DEBUG, "P2P: Send Action frame radio work timed out");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001531 wpas_p2p_free_send_action_work(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001532}
1533
1534
Dmitry Shmidt03658832014-08-13 11:03:49 -07001535static void wpas_p2p_action_tx_clear(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001536{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001537 if (wpa_s->p2p_send_action_work) {
1538 struct send_action_work *awork;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001539
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001540 awork = wpa_s->p2p_send_action_work->ctx;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001541 wpa_printf(MSG_DEBUG,
1542 "P2P: Clear Action TX work @%p (wait_time=%u)",
1543 wpa_s->p2p_send_action_work, awork->wait_time);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001544 if (awork->wait_time == 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001545 wpas_p2p_free_send_action_work(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001546 } else {
1547 /*
1548 * In theory, this should not be needed, but number of
1549 * places in the P2P code is still using non-zero wait
1550 * time for the last Action frame in the sequence and
1551 * some of these do not call send_action_done().
1552 */
1553 eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
1554 wpa_s, NULL);
1555 eloop_register_timeout(
1556 0, awork->wait_time * 1000,
1557 wpas_p2p_send_action_work_timeout,
1558 wpa_s, NULL);
1559 }
1560 }
Dmitry Shmidt03658832014-08-13 11:03:49 -07001561}
1562
1563
1564static void wpas_p2p_send_action_tx_status(struct wpa_supplicant *wpa_s,
1565 unsigned int freq,
1566 const u8 *dst, const u8 *src,
1567 const u8 *bssid,
1568 const u8 *data, size_t data_len,
1569 enum offchannel_send_action_result
1570 result)
1571{
1572 enum p2p_send_action_result res = P2P_SEND_ACTION_SUCCESS;
1573
1574 wpas_p2p_action_tx_clear(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001575
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001576 if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled)
1577 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001578
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001579 switch (result) {
1580 case OFFCHANNEL_SEND_ACTION_SUCCESS:
1581 res = P2P_SEND_ACTION_SUCCESS;
1582 break;
1583 case OFFCHANNEL_SEND_ACTION_NO_ACK:
1584 res = P2P_SEND_ACTION_NO_ACK;
1585 break;
1586 case OFFCHANNEL_SEND_ACTION_FAILED:
1587 res = P2P_SEND_ACTION_FAILED;
1588 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001589 }
1590
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001591 p2p_send_action_cb(wpa_s->global->p2p, freq, dst, src, bssid, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001592
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001593 if (result != OFFCHANNEL_SEND_ACTION_SUCCESS &&
1594 wpa_s->pending_pd_before_join &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001595 (os_memcmp(dst, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001596 os_memcmp(dst, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0) &&
1597 wpa_s->p2p_fallback_to_go_neg) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001598 wpa_s->pending_pd_before_join = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001599 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
1600 "during p2p_connect-auto");
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001601 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001602 P2P_EVENT_FALLBACK_TO_GO_NEG
1603 "reason=no-ACK-to-PD-Req");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001604 wpas_p2p_fallback_to_go_neg(wpa_s, 0);
1605 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001606 }
1607}
1608
1609
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001610static void wpas_send_action_cb(struct wpa_radio_work *work, int deinit)
1611{
1612 struct wpa_supplicant *wpa_s = work->wpa_s;
1613 struct send_action_work *awork = work->ctx;
1614
1615 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001616 if (work->started) {
1617 eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
1618 wpa_s, NULL);
1619 wpa_s->p2p_send_action_work = NULL;
1620 offchannel_send_action_done(wpa_s);
1621 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001622 os_free(awork);
1623 return;
1624 }
1625
1626 if (offchannel_send_action(wpa_s, awork->freq, awork->dst, awork->src,
1627 awork->bssid, awork->buf, awork->len,
1628 awork->wait_time,
1629 wpas_p2p_send_action_tx_status, 1) < 0) {
1630 os_free(awork);
1631 radio_work_done(work);
1632 return;
1633 }
1634 wpa_s->p2p_send_action_work = work;
1635}
1636
1637
1638static int wpas_send_action_work(struct wpa_supplicant *wpa_s,
1639 unsigned int freq, const u8 *dst,
1640 const u8 *src, const u8 *bssid, const u8 *buf,
1641 size_t len, unsigned int wait_time)
1642{
1643 struct send_action_work *awork;
1644
Hai Shalom81f62d82019-07-22 12:10:00 -07001645 if (radio_work_pending(wpa_s, "p2p-send-action")) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001646 wpa_printf(MSG_DEBUG, "P2P: Cannot schedule new p2p-send-action work since one is already pending");
1647 return -1;
1648 }
1649
1650 awork = os_zalloc(sizeof(*awork) + len);
1651 if (awork == NULL)
1652 return -1;
1653
1654 awork->freq = freq;
1655 os_memcpy(awork->dst, dst, ETH_ALEN);
1656 os_memcpy(awork->src, src, ETH_ALEN);
1657 os_memcpy(awork->bssid, bssid, ETH_ALEN);
1658 awork->len = len;
1659 awork->wait_time = wait_time;
1660 os_memcpy(awork->buf, buf, len);
1661
Hai Shalom81f62d82019-07-22 12:10:00 -07001662 if (radio_add_work(wpa_s, freq, "p2p-send-action", 1,
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001663 wpas_send_action_cb, awork) < 0) {
1664 os_free(awork);
1665 return -1;
1666 }
1667
1668 return 0;
1669}
1670
1671
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001672static int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst,
1673 const u8 *src, const u8 *bssid, const u8 *buf,
Hai Shalom021b0b52019-04-10 11:17:58 -07001674 size_t len, unsigned int wait_time, int *scheduled)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001675{
1676 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001677 int listen_freq = -1, send_freq = -1;
1678
Hai Shalom021b0b52019-04-10 11:17:58 -07001679 if (scheduled)
1680 *scheduled = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001681 if (wpa_s->p2p_listen_work)
1682 listen_freq = wpa_s->p2p_listen_work->freq;
1683 if (wpa_s->p2p_send_action_work)
1684 send_freq = wpa_s->p2p_send_action_work->freq;
1685 if (listen_freq != (int) freq && send_freq != (int) freq) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001686 int res;
1687
1688 wpa_printf(MSG_DEBUG, "P2P: Schedule new radio work for Action frame TX (listen_freq=%d send_freq=%d freq=%u)",
1689 listen_freq, send_freq, freq);
1690 res = wpas_send_action_work(wpa_s, freq, dst, src, bssid, buf,
1691 len, wait_time);
1692 if (res == 0 && scheduled)
1693 *scheduled = 1;
1694 return res;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001695 }
1696
1697 wpa_printf(MSG_DEBUG, "P2P: Use ongoing radio work for Action frame TX");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001698 return offchannel_send_action(wpa_s, freq, dst, src, bssid, buf, len,
1699 wait_time,
1700 wpas_p2p_send_action_tx_status, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001701}
1702
1703
1704static void wpas_send_action_done(void *ctx)
1705{
1706 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001707
1708 if (wpa_s->p2p_send_action_work) {
1709 eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
1710 wpa_s, NULL);
1711 os_free(wpa_s->p2p_send_action_work->ctx);
1712 radio_work_done(wpa_s->p2p_send_action_work);
1713 wpa_s->p2p_send_action_work = NULL;
1714 }
1715
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001716 offchannel_send_action_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001717}
1718
1719
1720static int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s,
1721 struct p2p_go_neg_results *params)
1722{
1723 if (wpa_s->go_params == NULL) {
1724 wpa_s->go_params = os_malloc(sizeof(*params));
1725 if (wpa_s->go_params == NULL)
1726 return -1;
1727 }
1728 os_memcpy(wpa_s->go_params, params, sizeof(*params));
1729 return 0;
1730}
1731
1732
1733static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
1734 struct p2p_go_neg_results *res)
1735{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001736 wpa_s->group_formation_reported = 0;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001737 wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR
1738 " dev_addr " MACSTR " wps_method %d",
1739 MAC2STR(res->peer_interface_addr),
1740 MAC2STR(res->peer_device_addr), res->wps_method);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001741 wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start WPS Enrollee for SSID",
1742 res->ssid, res->ssid_len);
1743 wpa_supplicant_ap_deinit(wpa_s);
1744 wpas_copy_go_neg_results(wpa_s, res);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001745 if (res->wps_method == WPS_PBC) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001746 wpas_wps_start_pbc(wpa_s, res->peer_interface_addr, 1, 0);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001747#ifdef CONFIG_WPS_NFC
1748 } else if (res->wps_method == WPS_NFC) {
1749 wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
1750 res->peer_interface_addr,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001751 wpa_s->p2pdev->p2p_oob_dev_pw,
1752 wpa_s->p2pdev->p2p_oob_dev_pw_id, 1,
1753 wpa_s->p2pdev->p2p_oob_dev_pw_id ==
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001754 DEV_PW_NFC_CONNECTION_HANDOVER ?
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001755 wpa_s->p2pdev->p2p_peer_oob_pubkey_hash :
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001756 NULL,
1757 NULL, 0, 0);
1758#endif /* CONFIG_WPS_NFC */
1759 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760 u16 dev_pw_id = DEV_PW_DEFAULT;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001761 if (wpa_s->p2p_wps_method == WPS_P2PS)
1762 dev_pw_id = DEV_PW_P2PS_DEFAULT;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001763 if (wpa_s->p2p_wps_method == WPS_PIN_KEYPAD)
1764 dev_pw_id = DEV_PW_REGISTRAR_SPECIFIED;
1765 wpas_wps_start_pin(wpa_s, res->peer_interface_addr,
1766 wpa_s->p2p_pin, 1, dev_pw_id);
1767 }
1768}
1769
1770
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001771static void wpas_p2p_add_psk_list(struct wpa_supplicant *wpa_s,
1772 struct wpa_ssid *ssid)
1773{
1774 struct wpa_ssid *persistent;
1775 struct psk_list_entry *psk;
1776 struct hostapd_data *hapd;
1777
1778 if (!wpa_s->ap_iface)
1779 return;
1780
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001781 persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001782 ssid->ssid_len);
1783 if (persistent == NULL)
1784 return;
1785
1786 hapd = wpa_s->ap_iface->bss[0];
1787
1788 dl_list_for_each(psk, &persistent->psk_list, struct psk_list_entry,
1789 list) {
1790 struct hostapd_wpa_psk *hpsk;
1791
1792 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add persistent group PSK entry for "
1793 MACSTR " psk=%d",
1794 MAC2STR(psk->addr), psk->p2p);
1795 hpsk = os_zalloc(sizeof(*hpsk));
1796 if (hpsk == NULL)
1797 break;
1798 os_memcpy(hpsk->psk, psk->psk, PMK_LEN);
1799 if (psk->p2p)
1800 os_memcpy(hpsk->p2p_dev_addr, psk->addr, ETH_ALEN);
1801 else
1802 os_memcpy(hpsk->addr, psk->addr, ETH_ALEN);
1803 hpsk->next = hapd->conf->ssid.wpa_psk;
1804 hapd->conf->ssid.wpa_psk = hpsk;
1805 }
1806}
1807
1808
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001809static void p2p_go_dump_common_freqs(struct wpa_supplicant *wpa_s)
1810{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001811 char buf[20 + P2P_MAX_CHANNELS * 6];
1812 char *pos, *end;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001813 unsigned int i;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001814 int res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001815
Roshan Pius3a1667e2018-07-03 15:17:14 -07001816 pos = buf;
1817 end = pos + sizeof(buf);
1818 for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
1819 res = os_snprintf(pos, end - pos, " %d",
1820 wpa_s->p2p_group_common_freqs[i]);
1821 if (os_snprintf_error(end - pos, res))
1822 break;
1823 pos += res;
1824 }
1825 *pos = '\0';
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001826
Roshan Pius3a1667e2018-07-03 15:17:14 -07001827 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Common group frequencies:%s", buf);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001828}
1829
1830
1831static void p2p_go_save_group_common_freqs(struct wpa_supplicant *wpa_s,
1832 struct p2p_go_neg_results *params)
1833{
1834 unsigned int i, len = int_array_len(wpa_s->go_params->freq_list);
1835
1836 wpa_s->p2p_group_common_freqs_num = 0;
1837 os_free(wpa_s->p2p_group_common_freqs);
1838 wpa_s->p2p_group_common_freqs = os_calloc(len, sizeof(int));
1839 if (!wpa_s->p2p_group_common_freqs)
1840 return;
1841
1842 for (i = 0; i < len; i++) {
1843 if (!wpa_s->go_params->freq_list[i])
1844 break;
1845 wpa_s->p2p_group_common_freqs[i] =
1846 wpa_s->go_params->freq_list[i];
1847 }
1848 wpa_s->p2p_group_common_freqs_num = i;
1849}
1850
1851
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001852static void p2p_config_write(struct wpa_supplicant *wpa_s)
1853{
1854#ifndef CONFIG_NO_CONFIG_WRITE
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001855 if (wpa_s->p2pdev->conf->update_config &&
1856 wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf))
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001857 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
1858#endif /* CONFIG_NO_CONFIG_WRITE */
1859}
1860
1861
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001862static void p2p_go_configured(void *ctx, void *data)
1863{
1864 struct wpa_supplicant *wpa_s = ctx;
1865 struct p2p_go_neg_results *params = data;
1866 struct wpa_ssid *ssid;
1867
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001868 wpa_s->ap_configured_cb = NULL;
1869 wpa_s->ap_configured_cb_ctx = NULL;
1870 wpa_s->ap_configured_cb_data = NULL;
1871 if (!wpa_s->go_params) {
1872 wpa_printf(MSG_ERROR,
1873 "P2P: p2p_go_configured() called with wpa_s->go_params == NULL");
1874 return;
1875 }
1876
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001877 p2p_go_save_group_common_freqs(wpa_s, params);
1878 p2p_go_dump_common_freqs(wpa_s);
1879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001880 ssid = wpa_s->current_ssid;
1881 if (ssid && ssid->mode == WPAS_MODE_P2P_GO) {
1882 wpa_printf(MSG_DEBUG, "P2P: Group setup without provisioning");
1883 if (wpa_s->global->p2p_group_formation == wpa_s)
1884 wpa_s->global->p2p_group_formation = NULL;
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07001885 wpas_p2p_group_started(wpa_s, 1, ssid, ssid->frequency,
1886 params->passphrase[0] == '\0' ?
1887 params->psk : NULL,
1888 params->passphrase,
1889 wpa_s->global->p2p_dev_addr,
1890 params->persistent_group, "");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001891 wpa_s->group_formation_reported = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001892
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001893 if (wpa_s->p2pdev->p2ps_method_config_any) {
1894 if (is_zero_ether_addr(wpa_s->p2pdev->p2ps_join_addr)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001895 wpa_dbg(wpa_s, MSG_DEBUG,
1896 "P2PS: Setting default PIN for ANY");
1897 wpa_supplicant_ap_wps_pin(wpa_s, NULL,
1898 "12345670", NULL, 0,
1899 0);
1900 } else {
1901 wpa_dbg(wpa_s, MSG_DEBUG,
1902 "P2PS: Setting default PIN for " MACSTR,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001903 MAC2STR(wpa_s->p2pdev->p2ps_join_addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001904 wpa_supplicant_ap_wps_pin(
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001905 wpa_s, wpa_s->p2pdev->p2ps_join_addr,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001906 "12345670", NULL, 0, 0);
1907 }
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001908 wpa_s->p2pdev->p2ps_method_config_any = 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001909 }
1910
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001911 os_get_reltime(&wpa_s->global->p2p_go_wait_client);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001912 if (params->persistent_group) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001913 wpas_p2p_store_persistent_group(
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001914 wpa_s->p2pdev, ssid,
Dmitry Shmidt497c1d52011-07-21 15:19:46 -07001915 wpa_s->global->p2p_dev_addr);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001916 wpas_p2p_add_psk_list(wpa_s, ssid);
1917 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001918
1919 wpas_notify_p2p_group_started(wpa_s, ssid,
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08001920 params->persistent_group, 0,
1921 NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922 wpas_p2p_cross_connect_setup(wpa_s);
1923 wpas_p2p_set_group_idle_timeout(wpa_s);
Dmitry Shmidt56052862013-10-04 10:23:25 -07001924
1925 if (wpa_s->p2p_first_connection_timeout) {
1926 wpa_dbg(wpa_s, MSG_DEBUG,
1927 "P2P: Start group formation timeout of %d seconds until first data connection on GO",
1928 wpa_s->p2p_first_connection_timeout);
1929 wpa_s->p2p_go_group_formation_completed = 0;
1930 wpa_s->global->p2p_group_formation = wpa_s;
1931 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001932 wpa_s->p2pdev, NULL);
Dmitry Shmidt56052862013-10-04 10:23:25 -07001933 eloop_register_timeout(
1934 wpa_s->p2p_first_connection_timeout, 0,
1935 wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001936 wpa_s->p2pdev, NULL);
Dmitry Shmidt56052862013-10-04 10:23:25 -07001937 }
1938
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939 return;
1940 }
1941
1942 wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning");
1943 if (wpa_supplicant_ap_mac_addr_filter(wpa_s,
1944 params->peer_interface_addr)) {
1945 wpa_printf(MSG_DEBUG, "P2P: Failed to setup MAC address "
1946 "filtering");
1947 return;
1948 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001949 if (params->wps_method == WPS_PBC) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001950 wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001951 params->peer_device_addr);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001952#ifdef CONFIG_WPS_NFC
1953 } else if (params->wps_method == WPS_NFC) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001954 if (wpa_s->p2pdev->p2p_oob_dev_pw_id !=
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001955 DEV_PW_NFC_CONNECTION_HANDOVER &&
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001956 !wpa_s->p2pdev->p2p_oob_dev_pw) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001957 wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
1958 return;
1959 }
1960 wpas_ap_wps_add_nfc_pw(
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001961 wpa_s, wpa_s->p2pdev->p2p_oob_dev_pw_id,
1962 wpa_s->p2pdev->p2p_oob_dev_pw,
1963 wpa_s->p2pdev->p2p_peer_oob_pk_hash_known ?
1964 wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001965#endif /* CONFIG_WPS_NFC */
1966 } else if (wpa_s->p2p_pin[0])
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001967 wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001968 wpa_s->p2p_pin, NULL, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969 os_free(wpa_s->go_params);
1970 wpa_s->go_params = NULL;
1971}
1972
1973
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001974/**
1975 * wpas_p2p_freq_to_edmg_channel - Convert frequency into EDMG channel
1976 * @freq: Frequency (MHz) to convert
1977 * @op_class: Buffer for returning operating class
1978 * @op_edmg_channel: Buffer for returning channel number
1979 * Returns: 0 on success, -1 on failure
1980 *
1981 * This can be used to find the highest channel bonding which includes the
1982 * specified frequency.
1983 */
1984static int wpas_p2p_freq_to_edmg_channel(struct wpa_supplicant *wpa_s,
1985 unsigned int freq,
1986 u8 *op_class, u8 *op_edmg_channel)
1987{
1988 struct hostapd_hw_modes *hwmode;
1989 struct ieee80211_edmg_config edmg;
1990 unsigned int i;
1991 enum chan_width chanwidth[] = {
1992 CHAN_WIDTH_8640,
1993 CHAN_WIDTH_6480,
1994 CHAN_WIDTH_4320,
1995 };
1996
1997 if (!wpa_s->hw.modes)
1998 return -1;
1999
2000 hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08002001 HOSTAPD_MODE_IEEE80211AD, false);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002002 if (!hwmode) {
2003 wpa_printf(MSG_ERROR,
2004 "Unsupported AP mode: HOSTAPD_MODE_IEEE80211AD");
2005 return -1;
2006 }
2007
2008 /* Find the highest EDMG channel bandwidth to start the P2P GO */
2009 for (i = 0; i < ARRAY_SIZE(chanwidth); i++) {
2010 if (ieee80211_chaninfo_to_channel(freq, chanwidth[i], 0,
2011 op_class,
2012 op_edmg_channel) < 0)
2013 continue;
2014
2015 hostapd_encode_edmg_chan(1, *op_edmg_channel, 0, &edmg);
2016 if (edmg.channels &&
2017 ieee802_edmg_is_allowed(hwmode->edmg, edmg)) {
2018 wpa_printf(MSG_DEBUG,
2019 "Freq %u to EDMG channel %u at opclass %u",
2020 freq, *op_edmg_channel, *op_class);
2021 return 0;
2022 }
2023 }
2024
2025 return -1;
2026}
2027
2028
2029int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s,
2030 struct p2p_go_neg_results *params)
2031{
2032 u8 op_channel, op_class;
2033 int freq;
2034
2035 /* Try social channel as primary channel frequency */
2036 freq = (!params->freq) ? 58320 + 1 * 2160 : params->freq;
2037
2038 if (wpas_p2p_freq_to_edmg_channel(wpa_s, freq, &op_class,
2039 &op_channel) == 0) {
2040 wpa_printf(MSG_DEBUG,
2041 "Freq %d will be used to set an EDMG connection (channel=%u opclass=%u)",
2042 freq, op_channel, op_class);
2043 params->freq = freq;
2044 return 0;
2045 }
2046
2047 return -1;
2048}
2049
2050
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002051static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
2052 struct p2p_go_neg_results *params,
2053 int group_formation)
2054{
2055 struct wpa_ssid *ssid;
2056
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002057 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Starting GO");
2058 if (wpas_copy_go_neg_results(wpa_s, params) < 0) {
2059 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not copy GO Negotiation "
2060 "results");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061 return;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002062 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002063
2064 ssid = wpa_config_add_network(wpa_s->conf);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002065 if (ssid == NULL) {
2066 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not add network for GO");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002067 return;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002068 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002070 wpa_s->show_group_started = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002071 wpa_s->p2p_go_group_formation_completed = 0;
2072 wpa_s->group_formation_reported = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002073 os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002074
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075 wpa_config_set_network_defaults(ssid);
2076 ssid->temporary = 1;
2077 ssid->p2p_group = 1;
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002078 ssid->p2p_persistent_group = !!params->persistent_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002079 ssid->mode = group_formation ? WPAS_MODE_P2P_GROUP_FORMATION :
2080 WPAS_MODE_P2P_GO;
2081 ssid->frequency = params->freq;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002082 ssid->ht40 = params->ht40;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002083 ssid->vht = params->vht;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002084 ssid->max_oper_chwidth = params->max_oper_chwidth;
2085 ssid->vht_center_freq2 = params->vht_center_freq2;
Hai Shalom74f70d42019-02-11 14:42:39 -08002086 ssid->he = params->he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002087 if (params->edmg) {
2088 u8 op_channel, op_class;
2089
2090 if (!wpas_p2p_freq_to_edmg_channel(wpa_s, params->freq,
2091 &op_class, &op_channel)) {
2092 ssid->edmg_channel = op_channel;
2093 ssid->enable_edmg = params->edmg;
2094 } else {
2095 wpa_dbg(wpa_s, MSG_DEBUG,
2096 "P2P: Could not match EDMG channel, freq %d, for GO",
2097 params->freq);
2098 }
2099 }
2100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002101 ssid->ssid = os_zalloc(params->ssid_len + 1);
2102 if (ssid->ssid) {
2103 os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
2104 ssid->ssid_len = params->ssid_len;
2105 }
2106 ssid->auth_alg = WPA_AUTH_ALG_OPEN;
2107 ssid->key_mgmt = WPA_KEY_MGMT_PSK;
Hai Shalomc1a21442022-02-04 13:43:00 -08002108 if (is_6ghz_freq(ssid->frequency) &&
2109 is_p2p_6ghz_capable(wpa_s->global->p2p)) {
2110 ssid->auth_alg |= WPA_AUTH_ALG_SAE;
2111 ssid->key_mgmt = WPA_KEY_MGMT_SAE;
2112 ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002113 ssid->sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
Hai Shalomc1a21442022-02-04 13:43:00 -08002114 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use SAE auth_alg and key_mgmt");
2115 } else {
2116 p2p_set_6ghz_dev_capab(wpa_s->global->p2p, false);
2117 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002118 ssid->proto = WPA_PROTO_RSN;
2119 ssid->pairwise_cipher = WPA_CIPHER_CCMP;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002120 ssid->group_cipher = WPA_CIPHER_CCMP;
2121 if (params->freq > 56160) {
2122 /*
2123 * Enable GCMP instead of CCMP as pairwise_cipher and
2124 * group_cipher in 60 GHz.
2125 */
2126 ssid->pairwise_cipher = WPA_CIPHER_GCMP;
2127 ssid->group_cipher = WPA_CIPHER_GCMP;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002128 /* P2P GO in 60 GHz is always a PCP (PBSS) */
2129 ssid->pbss = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002130 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002131 if (os_strlen(params->passphrase) > 0) {
2132 ssid->passphrase = os_strdup(params->passphrase);
2133 if (ssid->passphrase == NULL) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002134 wpa_msg_global(wpa_s, MSG_ERROR,
2135 "P2P: Failed to copy passphrase for GO");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002136 wpa_config_remove_network(wpa_s->conf, ssid->id);
2137 return;
2138 }
2139 } else
2140 ssid->passphrase = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002141 ssid->psk_set = params->psk_set;
2142 if (ssid->psk_set)
2143 os_memcpy(ssid->psk, params->psk, sizeof(ssid->psk));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002144 else if (ssid->passphrase)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002145 wpa_config_update_psk(ssid);
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002146 ssid->ap_max_inactivity = wpa_s->p2pdev->conf->p2p_go_max_inactivity;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002147
2148 wpa_s->ap_configured_cb = p2p_go_configured;
2149 wpa_s->ap_configured_cb_ctx = wpa_s;
2150 wpa_s->ap_configured_cb_data = wpa_s->go_params;
Dmitry Shmidt6dc03bd2014-05-16 10:40:13 -07002151 wpa_s->scan_req = NORMAL_SCAN_REQ;
Jouni Malinen75ecf522011-06-27 15:19:46 -07002152 wpa_s->connect_without_scan = ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153 wpa_s->reassociate = 1;
2154 wpa_s->disconnected = 0;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07002155 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Request scan (that will be skipped) to "
2156 "start GO)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002157 wpa_supplicant_req_scan(wpa_s, 0, 0);
2158}
2159
2160
2161static void wpas_p2p_clone_config(struct wpa_supplicant *dst,
2162 const struct wpa_supplicant *src)
2163{
2164 struct wpa_config *d;
2165 const struct wpa_config *s;
2166
2167 d = dst->conf;
2168 s = src->conf;
2169
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002170#define C(n) \
2171do { \
2172 if (s->n && !d->n) \
2173 d->n = os_strdup(s->n); \
2174} while (0)
2175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176 C(device_name);
2177 C(manufacturer);
2178 C(model_name);
2179 C(model_number);
2180 C(serial_number);
2181 C(config_methods);
2182#undef C
2183
2184 os_memcpy(d->device_type, s->device_type, WPS_DEV_TYPE_LEN);
2185 os_memcpy(d->sec_device_type, s->sec_device_type,
2186 sizeof(d->sec_device_type));
2187 d->num_sec_device_types = s->num_sec_device_types;
2188
2189 d->p2p_group_idle = s->p2p_group_idle;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002190 d->p2p_go_freq_change_policy = s->p2p_go_freq_change_policy;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002191 d->p2p_intra_bss = s->p2p_intra_bss;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002192 d->persistent_reconnect = s->persistent_reconnect;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002193 d->max_num_sta = s->max_num_sta;
2194 d->pbc_in_m1 = s->pbc_in_m1;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002195 d->ignore_old_scan_res = s->ignore_old_scan_res;
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002196 d->beacon_int = s->beacon_int;
Dmitry Shmidt18463232014-01-24 12:29:41 -08002197 d->dtim_period = s->dtim_period;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002198 d->p2p_go_ctwindow = s->p2p_go_ctwindow;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002199 d->disassoc_low_ack = s->disassoc_low_ack;
Dmitry Shmidt96571392013-10-14 12:54:46 -07002200 d->disable_scan_offload = s->disable_scan_offload;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002201 d->passive_scan = s->passive_scan;
Hai Shalomc1a21442022-02-04 13:43:00 -08002202 d->pmf = s->pmf;
2203 d->p2p_6ghz_disable = s->p2p_6ghz_disable;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002204 d->sae_pwe = s->sae_pwe;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002205
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002206 if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey &&
2207 !d->wps_nfc_pw_from_config) {
2208 wpabuf_free(d->wps_nfc_dh_privkey);
2209 wpabuf_free(d->wps_nfc_dh_pubkey);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002210 d->wps_nfc_dh_privkey = wpabuf_dup(s->wps_nfc_dh_privkey);
2211 d->wps_nfc_dh_pubkey = wpabuf_dup(s->wps_nfc_dh_pubkey);
2212 }
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07002213 d->p2p_cli_probe = s->p2p_cli_probe;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002214 d->go_interworking = s->go_interworking;
2215 d->go_access_network_type = s->go_access_network_type;
2216 d->go_internet = s->go_internet;
2217 d->go_venue_group = s->go_venue_group;
2218 d->go_venue_type = s->go_venue_type;
Hai Shalom60840252021-02-19 19:02:11 -08002219 d->p2p_add_cli_chan = s->p2p_add_cli_chan;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220}
2221
2222
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002223static void wpas_p2p_get_group_ifname(struct wpa_supplicant *wpa_s,
2224 char *ifname, size_t len)
2225{
2226 char *ifname_ptr = wpa_s->ifname;
2227
2228 if (os_strncmp(wpa_s->ifname, P2P_MGMT_DEVICE_PREFIX,
2229 os_strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
2230 ifname_ptr = os_strrchr(wpa_s->ifname, '-') + 1;
2231 }
2232
2233 os_snprintf(ifname, len, "p2p-%s-%d", ifname_ptr, wpa_s->p2p_group_idx);
2234 if (os_strlen(ifname) >= IFNAMSIZ &&
2235 os_strlen(wpa_s->ifname) < IFNAMSIZ) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002236 int res;
2237
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002238 /* Try to avoid going over the IFNAMSIZ length limit */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002239 res = os_snprintf(ifname, len, "p2p-%d", wpa_s->p2p_group_idx);
2240 if (os_snprintf_error(len, res) && len)
2241 ifname[len - 1] = '\0';
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002242 }
2243}
2244
2245
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s,
2247 enum wpa_driver_if_type type)
2248{
2249 char ifname[120], force_ifname[120];
2250
2251 if (wpa_s->pending_interface_name[0]) {
2252 wpa_printf(MSG_DEBUG, "P2P: Pending virtual interface exists "
2253 "- skip creation of a new one");
2254 if (is_zero_ether_addr(wpa_s->pending_interface_addr)) {
2255 wpa_printf(MSG_DEBUG, "P2P: Pending virtual address "
2256 "unknown?! ifname='%s'",
2257 wpa_s->pending_interface_name);
2258 return -1;
2259 }
2260 return 0;
2261 }
2262
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002263 wpas_p2p_get_group_ifname(wpa_s, ifname, sizeof(ifname));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002264 force_ifname[0] = '\0';
2265
2266 wpa_printf(MSG_DEBUG, "P2P: Create a new interface %s for the group",
2267 ifname);
2268 wpa_s->p2p_group_idx++;
2269
2270 wpa_s->pending_interface_type = type;
2271 if (wpa_drv_if_add(wpa_s, type, ifname, NULL, NULL, force_ifname,
2272 wpa_s->pending_interface_addr, NULL) < 0) {
2273 wpa_printf(MSG_ERROR, "P2P: Failed to create new group "
2274 "interface");
2275 return -1;
2276 }
2277
Jimmy Chen36c21992018-11-29 16:46:43 +08002278 if (wpa_s->conf->p2p_interface_random_mac_addr) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002279 random_mac_addr(wpa_s->pending_interface_addr);
2280 wpa_printf(MSG_DEBUG, "P2P: Generate random MAC address " MACSTR
2281 " for the group",
2282 MAC2STR(wpa_s->pending_interface_addr));
Jimmy Chen36c21992018-11-29 16:46:43 +08002283 }
2284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002285 if (force_ifname[0]) {
2286 wpa_printf(MSG_DEBUG, "P2P: Driver forced interface name %s",
2287 force_ifname);
2288 os_strlcpy(wpa_s->pending_interface_name, force_ifname,
2289 sizeof(wpa_s->pending_interface_name));
2290 } else
2291 os_strlcpy(wpa_s->pending_interface_name, ifname,
2292 sizeof(wpa_s->pending_interface_name));
2293 wpa_printf(MSG_DEBUG, "P2P: Created pending virtual interface %s addr "
2294 MACSTR, wpa_s->pending_interface_name,
2295 MAC2STR(wpa_s->pending_interface_addr));
2296
2297 return 0;
2298}
2299
2300
2301static void wpas_p2p_remove_pending_group_interface(
2302 struct wpa_supplicant *wpa_s)
2303{
2304 if (!wpa_s->pending_interface_name[0] ||
2305 is_zero_ether_addr(wpa_s->pending_interface_addr))
2306 return; /* No pending virtual interface */
2307
2308 wpa_printf(MSG_DEBUG, "P2P: Removing pending group interface %s",
2309 wpa_s->pending_interface_name);
2310 wpa_drv_if_remove(wpa_s, wpa_s->pending_interface_type,
2311 wpa_s->pending_interface_name);
2312 os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
2313 wpa_s->pending_interface_name[0] = '\0';
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002314 wpa_s->global->pending_group_iface_for_p2ps = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002315}
2316
2317
2318static struct wpa_supplicant *
2319wpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go)
2320{
2321 struct wpa_interface iface;
2322 struct wpa_supplicant *group_wpa_s;
2323
2324 if (!wpa_s->pending_interface_name[0]) {
2325 wpa_printf(MSG_ERROR, "P2P: No pending group interface");
2326 if (!wpas_p2p_create_iface(wpa_s))
2327 return NULL;
2328 /*
2329 * Something has forced us to remove the pending interface; try
2330 * to create a new one and hope for the best that we will get
2331 * the same local address.
2332 */
2333 if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
2334 WPA_IF_P2P_CLIENT) < 0)
2335 return NULL;
2336 }
2337
2338 os_memset(&iface, 0, sizeof(iface));
2339 iface.ifname = wpa_s->pending_interface_name;
2340 iface.driver = wpa_s->driver->name;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002341 if (wpa_s->conf->ctrl_interface == NULL &&
2342 wpa_s->parent != wpa_s &&
2343 wpa_s->p2p_mgmt &&
2344 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE))
2345 iface.ctrl_interface = wpa_s->parent->conf->ctrl_interface;
2346 else
2347 iface.ctrl_interface = wpa_s->conf->ctrl_interface;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348 iface.driver_param = wpa_s->conf->driver_param;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08002349 group_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002350 if (group_wpa_s == NULL) {
2351 wpa_printf(MSG_ERROR, "P2P: Failed to create new "
2352 "wpa_supplicant interface");
2353 return NULL;
2354 }
2355 wpa_s->pending_interface_name[0] = '\0';
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356 group_wpa_s->p2p_group_interface = go ? P2P_GROUP_INTERFACE_GO :
2357 P2P_GROUP_INTERFACE_CLIENT;
2358 wpa_s->global->p2p_group_formation = group_wpa_s;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002359 wpa_s->global->pending_group_iface_for_p2ps = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002360
2361 wpas_p2p_clone_config(group_wpa_s, wpa_s);
2362
Jimmy Chen36c21992018-11-29 16:46:43 +08002363 if (wpa_s->conf->p2p_interface_random_mac_addr) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002364 if (wpa_drv_set_mac_addr(group_wpa_s,
2365 wpa_s->pending_interface_addr) < 0) {
Jimmy Chen36c21992018-11-29 16:46:43 +08002366 wpa_msg(group_wpa_s, MSG_INFO,
2367 "Failed to set random MAC address");
Hai Shalom74f70d42019-02-11 14:42:39 -08002368 wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s,
2369 0);
Jimmy Chen36c21992018-11-29 16:46:43 +08002370 return NULL;
2371 }
2372
2373 if (wpa_supplicant_update_mac_addr(group_wpa_s) < 0) {
2374 wpa_msg(group_wpa_s, MSG_INFO,
2375 "Could not update MAC address information");
Hai Shalom74f70d42019-02-11 14:42:39 -08002376 wpa_supplicant_remove_iface(wpa_s->global, group_wpa_s,
2377 0);
Jimmy Chen36c21992018-11-29 16:46:43 +08002378 return NULL;
2379 }
2380
Hai Shalom74f70d42019-02-11 14:42:39 -08002381 wpa_printf(MSG_DEBUG, "P2P: Using random MAC address " MACSTR
2382 " for the group",
2383 MAC2STR(wpa_s->pending_interface_addr));
Jimmy Chen36c21992018-11-29 16:46:43 +08002384 }
2385
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002386 return group_wpa_s;
2387}
2388
2389
2390static void wpas_p2p_group_formation_timeout(void *eloop_ctx,
2391 void *timeout_ctx)
2392{
2393 struct wpa_supplicant *wpa_s = eloop_ctx;
2394 wpa_printf(MSG_DEBUG, "P2P: Group Formation timed out");
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07002395 wpas_p2p_group_formation_failed(wpa_s, 0);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002396}
2397
2398
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07002399static void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s,
2400 int already_deleted)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002401{
2402 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002403 wpa_s->p2pdev, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002404 if (wpa_s->global->p2p)
2405 p2p_group_formation_failed(wpa_s->global->p2p);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07002406 wpas_group_formation_completed(wpa_s, 0, already_deleted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407}
2408
2409
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002410static void wpas_p2p_grpform_fail_after_wps(struct wpa_supplicant *wpa_s)
2411{
2412 wpa_printf(MSG_DEBUG, "P2P: Reject group formation due to WPS provisioning failure");
2413 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002414 wpa_s->p2pdev, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002415 eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002416 wpa_s->p2pdev, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002417 wpa_s->global->p2p_fail_on_wps_complete = 0;
2418}
2419
2420
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002421void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s)
2422{
2423 if (wpa_s->global->p2p_group_formation != wpa_s)
2424 return;
2425 /* Speed up group formation timeout since this cannot succeed */
2426 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002427 wpa_s->p2pdev, NULL);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002428 eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002429 wpa_s->p2pdev, NULL);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002430}
2431
2432
Matthew Wang06b42472022-11-10 06:56:31 +00002433bool wpas_p2p_retry_limit_exceeded(struct wpa_supplicant *wpa_s)
2434{
2435 if (!wpa_s->p2p_in_invitation || !wpa_s->p2p_retry_limit ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00002436 wpa_s->p2p_in_invitation <= wpa_s->p2p_retry_limit)
Matthew Wang06b42472022-11-10 06:56:31 +00002437 return false;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002438
Matthew Wang06b42472022-11-10 06:56:31 +00002439 wpa_printf(MSG_DEBUG, "P2P: Group join retry limit exceeded");
2440 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
2441 wpa_s->p2pdev, NULL);
2442 eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
2443 wpa_s->p2pdev, NULL);
2444 return true;
2445}
2446
2447
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002448static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449{
2450 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002451 struct wpa_supplicant *group_wpa_s;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002452
2453 if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
2454 wpa_drv_cancel_remain_on_channel(wpa_s);
2455 wpa_s->off_channel_freq = 0;
2456 wpa_s->roc_waiting_drv_freq = 0;
2457 }
2458
2459 if (res->status) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002460 wpa_msg_global(wpa_s, MSG_INFO,
2461 P2P_EVENT_GO_NEG_FAILURE "status=%d",
2462 res->status);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002463 wpas_notify_p2p_go_neg_completed(wpa_s, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464 wpas_p2p_remove_pending_group_interface(wpa_s);
2465 return;
2466 }
2467
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002468 if (!res->role_go) {
2469 /* Inform driver of the operating channel of GO. */
2470 wpa_drv_set_prob_oper_freq(wpa_s, res->freq);
2471 }
2472
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 if (wpa_s->p2p_go_ht40)
2474 res->ht40 = 1;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002475 if (wpa_s->p2p_go_vht)
2476 res->vht = 1;
Hai Shalomc3565922019-10-28 11:58:20 -07002477 if (wpa_s->p2p_go_he)
2478 res->he = 1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002479 if (wpa_s->p2p_go_edmg)
2480 res->edmg = 1;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002481 res->max_oper_chwidth = wpa_s->p2p_go_max_oper_chwidth;
2482 res->vht_center_freq2 = wpa_s->p2p_go_vht_center_freq2;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002483
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002484 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS "role=%s "
2485 "freq=%d ht40=%d peer_dev=" MACSTR " peer_iface=" MACSTR
2486 " wps_method=%s",
2487 res->role_go ? "GO" : "client", res->freq, res->ht40,
2488 MAC2STR(res->peer_device_addr),
2489 MAC2STR(res->peer_interface_addr),
2490 p2p_wps_method_text(res->wps_method));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002491 wpas_notify_p2p_go_neg_completed(wpa_s, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492
Dmitry Shmidt04949592012-07-19 12:16:46 -07002493 if (res->role_go && wpa_s->p2p_persistent_id >= 0) {
2494 struct wpa_ssid *ssid;
2495 ssid = wpa_config_get_network(wpa_s->conf,
2496 wpa_s->p2p_persistent_id);
2497 if (ssid && ssid->disabled == 2 &&
2498 ssid->mode == WPAS_MODE_P2P_GO && ssid->passphrase) {
2499 size_t len = os_strlen(ssid->passphrase);
2500 wpa_printf(MSG_DEBUG, "P2P: Override passphrase based "
2501 "on requested persistent group");
2502 os_memcpy(res->passphrase, ssid->passphrase, len);
2503 res->passphrase[len] = '\0';
2504 }
2505 }
2506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 if (wpa_s->create_p2p_iface) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002508 group_wpa_s =
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 wpas_p2p_init_group_interface(wpa_s, res->role_go);
2510 if (group_wpa_s == NULL) {
2511 wpas_p2p_remove_pending_group_interface(wpa_s);
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002512 eloop_cancel_timeout(wpas_p2p_long_listen_timeout,
2513 wpa_s, NULL);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07002514 wpas_p2p_group_formation_failed(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 return;
2516 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
2518 wpa_s->pending_interface_name[0] = '\0';
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002519 } else {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002520 group_wpa_s = wpa_s->parent;
2521 wpa_s->global->p2p_group_formation = group_wpa_s;
2522 if (group_wpa_s != wpa_s)
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002523 wpas_p2p_clone_config(group_wpa_s, wpa_s);
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002524 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002525
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002526 group_wpa_s->p2p_in_provisioning = 1;
2527 group_wpa_s->p2pdev = wpa_s;
2528 if (group_wpa_s != wpa_s) {
2529 os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
2530 sizeof(group_wpa_s->p2p_pin));
2531 group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
2532 }
2533 if (res->role_go) {
2534 wpas_start_wps_go(group_wpa_s, res, 1);
2535 } else {
2536 os_get_reltime(&group_wpa_s->scan_min_time);
2537 wpas_start_wps_enrollee(group_wpa_s, res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 }
2539
Hai Shalomfdcde762020-04-02 11:19:20 -07002540 wpa_s->global->p2p_long_listen = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
2542
2543 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
2544 eloop_register_timeout(15 + res->peer_config_timeout / 100,
2545 (res->peer_config_timeout % 100) * 10000,
2546 wpas_p2p_group_formation_timeout, wpa_s, NULL);
2547}
2548
2549
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002550static void wpas_go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id,
2551 u8 go_intent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552{
2553 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002554 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_REQUEST MACSTR
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002555 " dev_passwd_id=%u go_intent=%u", MAC2STR(src),
2556 dev_passwd_id, go_intent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557
Dmitry Shmidt7a53dbb2015-06-11 13:13:53 -07002558 wpas_notify_p2p_go_neg_req(wpa_s, src, dev_passwd_id, go_intent);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559}
2560
2561
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002562static void wpas_dev_found(void *ctx, const u8 *addr,
2563 const struct p2p_peer_info *info,
2564 int new_device)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565{
Roshan Piusfd2fd662017-01-23 13:41:57 -08002566 u8 *wfd_dev_info = NULL;
2567 u8 wfd_dev_info_len = 0;
Jimmy Chen0133fc12021-03-04 13:56:11 +08002568 u8 *wfd_r2_dev_info = NULL;
Jimmy Chen57e19f52021-03-04 14:19:52 +08002569 u8 wfd_r2_dev_info_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002570#ifndef CONFIG_NO_STDOUT_DEBUG
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002571 struct wpa_supplicant *wpa_s = ctx;
2572 char devtype[WPS_DEV_TYPE_BUFSIZE];
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002573 char *wfd_dev_info_hex = NULL;
Jimmy Chen0133fc12021-03-04 13:56:11 +08002574 char *wfd_r2_dev_info_hex = NULL;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002575
Irfan Sheriff8367dc92012-09-09 17:08:19 -07002576#ifdef CONFIG_WIFI_DISPLAY
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002577 wfd_dev_info_hex = wifi_display_subelem_hex(info->wfd_subelems,
2578 WFD_SUBELEM_DEVICE_INFO);
Roshan Piusfd2fd662017-01-23 13:41:57 -08002579 if (wfd_dev_info_hex) {
2580 wfd_dev_info_len = strlen(wfd_dev_info_hex) / 2;
2581 wfd_dev_info = os_zalloc(wfd_dev_info_len);
2582 // Only used for notification, so not handling error.
2583 hexstr2bin(wfd_dev_info_hex, wfd_dev_info, wfd_dev_info_len);
2584 }
Jimmy Chen0133fc12021-03-04 13:56:11 +08002585
2586 wfd_r2_dev_info_hex = wifi_display_subelem_hex(info->wfd_subelems,
2587 WFD_SUBELEM_R2_DEVICE_INFO);
2588 if (wfd_r2_dev_info_hex) {
2589 wfd_r2_dev_info_len = strlen(wfd_r2_dev_info_hex) / 2;
2590 wfd_r2_dev_info = os_zalloc(wfd_r2_dev_info_len);
2591 // Only used for notification, so not handling error.
2592 hexstr2bin(wfd_r2_dev_info_hex, wfd_r2_dev_info, wfd_r2_dev_info_len);
2593 }
Irfan Sheriff8367dc92012-09-09 17:08:19 -07002594#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002595
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002596 if (info->p2ps_instance) {
2597 char str[256];
2598 const u8 *buf = wpabuf_head(info->p2ps_instance);
2599 size_t len = wpabuf_len(info->p2ps_instance);
2600
2601 while (len) {
2602 u32 id;
2603 u16 methods;
2604 u8 str_len;
2605
2606 if (len < 4 + 2 + 1)
2607 break;
2608 id = WPA_GET_LE32(buf);
2609 buf += sizeof(u32);
2610 methods = WPA_GET_BE16(buf);
2611 buf += sizeof(u16);
2612 str_len = *buf++;
2613 if (str_len > len - 4 - 2 - 1)
2614 break;
2615 os_memcpy(str, buf, str_len);
2616 str[str_len] = '\0';
2617 buf += str_len;
2618 len -= str_len + sizeof(u32) + sizeof(u16) + sizeof(u8);
2619
2620 wpa_msg_global(wpa_s, MSG_INFO,
2621 P2P_EVENT_DEVICE_FOUND MACSTR
2622 " p2p_dev_addr=" MACSTR
2623 " pri_dev_type=%s name='%s'"
2624 " config_methods=0x%x"
2625 " dev_capab=0x%x"
2626 " group_capab=0x%x"
2627 " adv_id=%x asp_svc=%s%s",
2628 MAC2STR(addr),
2629 MAC2STR(info->p2p_device_addr),
2630 wps_dev_type_bin2str(
2631 info->pri_dev_type,
2632 devtype, sizeof(devtype)),
2633 info->device_name, methods,
2634 info->dev_capab, info->group_capab,
2635 id, str,
2636 info->vendor_elems ?
2637 " vendor_elems=1" : "");
2638 }
2639 goto done;
2640 }
2641
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002642 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
2643 " p2p_dev_addr=" MACSTR
2644 " pri_dev_type=%s name='%s' config_methods=0x%x "
Jimmy Chen0133fc12021-03-04 13:56:11 +08002645 "dev_capab=0x%x group_capab=0x%x%s%s%s%s%s new=%d",
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002646 MAC2STR(addr), MAC2STR(info->p2p_device_addr),
2647 wps_dev_type_bin2str(info->pri_dev_type, devtype,
2648 sizeof(devtype)),
2649 info->device_name, info->config_methods,
2650 info->dev_capab, info->group_capab,
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002651 wfd_dev_info_hex ? " wfd_dev_info=0x" : "",
Dmitry Shmidt2e67f062014-07-16 09:55:28 -07002652 wfd_dev_info_hex ? wfd_dev_info_hex : "",
Jimmy Chen0133fc12021-03-04 13:56:11 +08002653 wfd_r2_dev_info_hex ? " wfd_r2_dev_info=0x" : "",
2654 wfd_r2_dev_info_hex ? wfd_r2_dev_info_hex : "",
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002655 info->vendor_elems ? " vendor_elems=1" : "",
2656 new_device);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002658done:
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002659 os_free(wfd_dev_info_hex);
Jimmy Chen0133fc12021-03-04 13:56:11 +08002660 os_free(wfd_r2_dev_info_hex);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002661#endif /* CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08002662
Roshan Piusfd2fd662017-01-23 13:41:57 -08002663 wpas_notify_p2p_device_found(ctx, addr, info, wfd_dev_info,
Jimmy Chen0133fc12021-03-04 13:56:11 +08002664 wfd_dev_info_len, wfd_r2_dev_info,
2665 wfd_r2_dev_info_len, new_device);
Roshan Piusfd2fd662017-01-23 13:41:57 -08002666 os_free(wfd_dev_info);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667}
2668
2669
2670static void wpas_dev_lost(void *ctx, const u8 *dev_addr)
2671{
2672 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002673
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002674 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_LOST
2675 "p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002676
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 wpas_notify_p2p_device_lost(wpa_s, dev_addr);
2678}
2679
2680
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002681static void wpas_find_stopped(void *ctx)
2682{
2683 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002684
2685 if (wpa_s->p2p_scan_work && wpas_abort_ongoing_scan(wpa_s) < 0)
2686 wpa_printf(MSG_DEBUG, "P2P: Abort ongoing scan failed");
2687
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002688 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED);
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07002689 wpas_notify_p2p_find_stopped(wpa_s);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002690}
2691
2692
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002693struct wpas_p2p_listen_work {
2694 unsigned int freq;
2695 unsigned int duration;
2696 struct wpabuf *probe_resp_ie;
2697};
2698
2699
2700static void wpas_p2p_listen_work_free(struct wpas_p2p_listen_work *lwork)
2701{
2702 if (lwork == NULL)
2703 return;
2704 wpabuf_free(lwork->probe_resp_ie);
2705 os_free(lwork);
2706}
2707
2708
2709static void wpas_p2p_listen_work_done(struct wpa_supplicant *wpa_s)
2710{
2711 struct wpas_p2p_listen_work *lwork;
2712
2713 if (!wpa_s->p2p_listen_work)
2714 return;
2715
2716 lwork = wpa_s->p2p_listen_work->ctx;
2717 wpas_p2p_listen_work_free(lwork);
2718 radio_work_done(wpa_s->p2p_listen_work);
2719 wpa_s->p2p_listen_work = NULL;
2720}
2721
2722
2723static void wpas_start_listen_cb(struct wpa_radio_work *work, int deinit)
2724{
2725 struct wpa_supplicant *wpa_s = work->wpa_s;
2726 struct wpas_p2p_listen_work *lwork = work->ctx;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002727 unsigned int duration;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002728
2729 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002730 if (work->started) {
2731 wpa_s->p2p_listen_work = NULL;
2732 wpas_stop_listen(wpa_s);
2733 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002734 wpas_p2p_listen_work_free(lwork);
2735 return;
2736 }
2737
2738 wpa_s->p2p_listen_work = work;
2739
2740 wpa_drv_set_ap_wps_ie(wpa_s, NULL, lwork->probe_resp_ie, NULL);
2741
2742 if (wpa_drv_probe_req_report(wpa_s, 1) < 0) {
2743 wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver to "
2744 "report received Probe Request frames");
2745 wpas_p2p_listen_work_done(wpa_s);
2746 return;
2747 }
2748
2749 wpa_s->pending_listen_freq = lwork->freq;
2750 wpa_s->pending_listen_duration = lwork->duration;
2751
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002752 duration = lwork->duration;
2753#ifdef CONFIG_TESTING_OPTIONS
2754 if (wpa_s->extra_roc_dur) {
2755 wpa_printf(MSG_DEBUG, "TESTING: Increase ROC duration %u -> %u",
2756 duration, duration + wpa_s->extra_roc_dur);
2757 duration += wpa_s->extra_roc_dur;
2758 }
2759#endif /* CONFIG_TESTING_OPTIONS */
2760
2761 if (wpa_drv_remain_on_channel(wpa_s, lwork->freq, duration) < 0) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002762 wpa_printf(MSG_DEBUG, "P2P: Failed to request the driver "
2763 "to remain on channel (%u MHz) for Listen "
2764 "state", lwork->freq);
2765 wpas_p2p_listen_work_done(wpa_s);
2766 wpa_s->pending_listen_freq = 0;
2767 return;
2768 }
2769 wpa_s->off_channel_freq = 0;
2770 wpa_s->roc_waiting_drv_freq = lwork->freq;
2771}
2772
2773
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002774static int wpas_start_listen(void *ctx, unsigned int freq,
2775 unsigned int duration,
2776 const struct wpabuf *probe_resp_ie)
2777{
2778 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002779 struct wpas_p2p_listen_work *lwork;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002781 if (wpa_s->p2p_listen_work) {
2782 wpa_printf(MSG_DEBUG, "P2P: Reject start_listen since p2p_listen_work already exists");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 return -1;
2784 }
2785
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002786 lwork = os_zalloc(sizeof(*lwork));
2787 if (lwork == NULL)
2788 return -1;
2789 lwork->freq = freq;
2790 lwork->duration = duration;
2791 if (probe_resp_ie) {
2792 lwork->probe_resp_ie = wpabuf_dup(probe_resp_ie);
2793 if (lwork->probe_resp_ie == NULL) {
2794 wpas_p2p_listen_work_free(lwork);
2795 return -1;
2796 }
2797 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002798
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002799 if (radio_add_work(wpa_s, freq, "p2p-listen", 0, wpas_start_listen_cb,
2800 lwork) < 0) {
2801 wpas_p2p_listen_work_free(lwork);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002802 return -1;
2803 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002804
2805 return 0;
2806}
2807
2808
2809static void wpas_stop_listen(void *ctx)
2810{
2811 struct wpa_supplicant *wpa_s = ctx;
2812 if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
2813 wpa_drv_cancel_remain_on_channel(wpa_s);
2814 wpa_s->off_channel_freq = 0;
2815 wpa_s->roc_waiting_drv_freq = 0;
2816 }
2817 wpa_drv_set_ap_wps_ie(wpa_s, NULL, NULL, NULL);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07002818
2819 /*
2820 * Don't cancel Probe Request RX reporting for a connected P2P Client
2821 * handling Probe Request frames.
2822 */
2823 if (!wpa_s->p2p_cli_probe)
2824 wpa_drv_probe_req_report(wpa_s, 0);
2825
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002826 wpas_p2p_listen_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002827}
2828
2829
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07002830static int wpas_send_probe_resp(void *ctx, const struct wpabuf *buf,
2831 unsigned int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832{
2833 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07002834 return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
Hai Shalomfdcde762020-04-02 11:19:20 -07002835 freq, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002836}
2837
2838
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002839static void wpas_prov_disc_local_display(struct wpa_supplicant *wpa_s,
2840 const u8 *peer, const char *params,
2841 unsigned int generated_pin)
2842{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002843 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_SHOW_PIN MACSTR
2844 " %08d%s", MAC2STR(peer), generated_pin, params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002845}
2846
2847
2848static void wpas_prov_disc_local_keypad(struct wpa_supplicant *wpa_s,
2849 const u8 *peer, const char *params)
2850{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002851 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_ENTER_PIN MACSTR
2852 "%s", MAC2STR(peer), params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002853}
2854
2855
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002856static void wpas_prov_disc_req(void *ctx, const u8 *peer, u16 config_methods,
2857 const u8 *dev_addr, const u8 *pri_dev_type,
2858 const char *dev_name, u16 supp_config_methods,
2859 u8 dev_capab, u8 group_capab, const u8 *group_id,
2860 size_t group_id_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002861{
2862 struct wpa_supplicant *wpa_s = ctx;
2863 char devtype[WPS_DEV_TYPE_BUFSIZE];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002864 char params[300];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865 u8 empty_dev_type[8];
2866 unsigned int generated_pin = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002867 struct wpa_supplicant *group = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002868 int res;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002869
2870 if (group_id) {
2871 for (group = wpa_s->global->ifaces; group; group = group->next)
2872 {
2873 struct wpa_ssid *s = group->current_ssid;
2874 if (s != NULL &&
2875 s->mode == WPAS_MODE_P2P_GO &&
2876 group_id_len - ETH_ALEN == s->ssid_len &&
2877 os_memcmp(group_id + ETH_ALEN, s->ssid,
2878 s->ssid_len) == 0)
2879 break;
2880 }
2881 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002882
2883 if (pri_dev_type == NULL) {
2884 os_memset(empty_dev_type, 0, sizeof(empty_dev_type));
2885 pri_dev_type = empty_dev_type;
2886 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002887 res = os_snprintf(params, sizeof(params), " p2p_dev_addr=" MACSTR
2888 " pri_dev_type=%s name='%s' config_methods=0x%x "
2889 "dev_capab=0x%x group_capab=0x%x%s%s",
2890 MAC2STR(dev_addr),
2891 wps_dev_type_bin2str(pri_dev_type, devtype,
2892 sizeof(devtype)),
2893 dev_name, supp_config_methods, dev_capab, group_capab,
2894 group ? " group=" : "",
2895 group ? group->ifname : "");
2896 if (os_snprintf_error(sizeof(params), res))
2897 wpa_printf(MSG_DEBUG, "P2P: PD Request event truncated");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002898 params[sizeof(params) - 1] = '\0';
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002899
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002900 if (config_methods & WPS_CONFIG_DISPLAY) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002901 if (wps_generate_pin(&generated_pin) < 0) {
2902 wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
2903 wpas_notify_p2p_provision_discovery(
2904 wpa_s, peer, 0 /* response */,
2905 P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
2906 return;
2907 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 wpas_prov_disc_local_display(wpa_s, peer, params,
2909 generated_pin);
2910 } else if (config_methods & WPS_CONFIG_KEYPAD)
2911 wpas_prov_disc_local_keypad(wpa_s, peer, params);
2912 else if (config_methods & WPS_CONFIG_PUSHBUTTON)
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002913 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_REQ
2914 MACSTR "%s", MAC2STR(peer), params);
Jouni Malinen75ecf522011-06-27 15:19:46 -07002915
2916 wpas_notify_p2p_provision_discovery(wpa_s, peer, 1 /* request */,
2917 P2P_PROV_DISC_SUCCESS,
2918 config_methods, generated_pin);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919}
2920
2921
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002922static void wpas_prov_disc_resp(void *ctx, const u8 *peer, u16 config_methods)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002923{
2924 struct wpa_supplicant *wpa_s = ctx;
2925 unsigned int generated_pin = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002926 char params[20];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002927
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002928 if (wpa_s->pending_pd_before_join &&
2929 (os_memcmp(peer, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0 ||
2930 os_memcmp(peer, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0)) {
2931 wpa_s->pending_pd_before_join = 0;
2932 wpa_printf(MSG_DEBUG, "P2P: Starting pending "
2933 "join-existing-group operation");
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002934 wpas_p2p_join_start(wpa_s, 0, NULL, 0);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002935 return;
2936 }
2937
Dmitry Shmidt04949592012-07-19 12:16:46 -07002938 if (wpa_s->pending_pd_use == AUTO_PD_JOIN ||
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002939 wpa_s->pending_pd_use == AUTO_PD_GO_NEG) {
2940 int res;
2941
2942 res = os_snprintf(params, sizeof(params), " peer_go=%d",
2943 wpa_s->pending_pd_use == AUTO_PD_JOIN);
2944 if (os_snprintf_error(sizeof(params), res))
2945 params[sizeof(params) - 1] = '\0';
2946 } else
Dmitry Shmidt04949592012-07-19 12:16:46 -07002947 params[0] = '\0';
2948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 if (config_methods & WPS_CONFIG_DISPLAY)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002950 wpas_prov_disc_local_keypad(wpa_s, peer, params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002951 else if (config_methods & WPS_CONFIG_KEYPAD) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002952 if (wps_generate_pin(&generated_pin) < 0) {
2953 wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
2954 wpas_notify_p2p_provision_discovery(
2955 wpa_s, peer, 0 /* response */,
2956 P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
2957 return;
2958 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002959 wpas_prov_disc_local_display(wpa_s, peer, params,
2960 generated_pin);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002961 } else if (config_methods & WPS_CONFIG_PUSHBUTTON)
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07002962 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_PBC_RESP
2963 MACSTR "%s", MAC2STR(peer), params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964
Jouni Malinen75ecf522011-06-27 15:19:46 -07002965 wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
2966 P2P_PROV_DISC_SUCCESS,
2967 config_methods, generated_pin);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002968}
2969
2970
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002971static void wpas_prov_disc_fail(void *ctx, const u8 *peer,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002972 enum p2p_prov_disc_status status,
2973 u32 adv_id, const u8 *adv_mac,
2974 const char *deferred_session_resp)
Jouni Malinen75ecf522011-06-27 15:19:46 -07002975{
2976 struct wpa_supplicant *wpa_s = ctx;
2977
Dmitry Shmidt04949592012-07-19 12:16:46 -07002978 if (wpa_s->p2p_fallback_to_go_neg) {
2979 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: PD for p2p_connect-auto "
2980 "failed - fall back to GO Negotiation");
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002981 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002982 P2P_EVENT_FALLBACK_TO_GO_NEG
2983 "reason=PD-failed");
Dmitry Shmidt04949592012-07-19 12:16:46 -07002984 wpas_p2p_fallback_to_go_neg(wpa_s, 0);
2985 return;
2986 }
2987
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002988 if (status == P2P_PROV_DISC_TIMEOUT_JOIN) {
Dmitry Shmidt2b380482012-09-13 10:52:13 -07002989 wpa_s->pending_pd_before_join = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002990 wpa_printf(MSG_DEBUG, "P2P: Starting pending "
2991 "join-existing-group operation (no ACK for PD "
2992 "Req attempts)");
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002993 wpas_p2p_join_start(wpa_s, 0, NULL, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002994 return;
Dmitry Shmidt2b380482012-09-13 10:52:13 -07002995 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002996
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002997 if (adv_id && adv_mac && deferred_session_resp) {
2998 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
2999 " p2p_dev_addr=" MACSTR " status=%d adv_id=%x"
3000 " deferred_session_resp='%s'",
3001 MAC2STR(peer), status, adv_id,
3002 deferred_session_resp);
3003 } else if (adv_id && adv_mac) {
3004 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
3005 " p2p_dev_addr=" MACSTR " status=%d adv_id=%x",
3006 MAC2STR(peer), status, adv_id);
3007 } else {
3008 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_PROV_DISC_FAILURE
3009 " p2p_dev_addr=" MACSTR " status=%d",
3010 MAC2STR(peer), status);
3011 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07003012
Jouni Malinen75ecf522011-06-27 15:19:46 -07003013 wpas_notify_p2p_provision_discovery(wpa_s, peer, 0 /* response */,
3014 status, 0, 0);
3015}
3016
3017
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003018static int freq_included(struct wpa_supplicant *wpa_s,
3019 const struct p2p_channels *channels,
3020 unsigned int freq)
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003021{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003022 if ((channels == NULL || p2p_channels_includes_freq(channels, freq)) &&
3023 wpas_p2p_go_is_peer_freq(wpa_s, freq))
3024 return 1;
3025 return 0;
3026}
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003027
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003028
3029static void wpas_p2p_go_update_common_freqs(struct wpa_supplicant *wpa_s)
3030{
3031 unsigned int num = P2P_MAX_CHANNELS;
3032 int *common_freqs;
3033 int ret;
3034
3035 p2p_go_dump_common_freqs(wpa_s);
3036 common_freqs = os_calloc(num, sizeof(int));
3037 if (!common_freqs)
3038 return;
3039
3040 ret = p2p_group_get_common_freqs(wpa_s->p2p_group, common_freqs, &num);
3041 if (ret < 0) {
3042 wpa_dbg(wpa_s, MSG_DEBUG,
3043 "P2P: Failed to get group common freqs");
3044 os_free(common_freqs);
3045 return;
3046 }
3047
3048 os_free(wpa_s->p2p_group_common_freqs);
3049 wpa_s->p2p_group_common_freqs = common_freqs;
3050 wpa_s->p2p_group_common_freqs_num = num;
3051 p2p_go_dump_common_freqs(wpa_s);
3052}
3053
3054
3055/*
3056 * Check if the given frequency is one of the possible operating frequencies
3057 * set after the completion of the GO Negotiation.
3058 */
3059static int wpas_p2p_go_is_peer_freq(struct wpa_supplicant *wpa_s, int freq)
3060{
3061 unsigned int i;
3062
3063 p2p_go_dump_common_freqs(wpa_s);
3064
3065 /* assume no restrictions */
3066 if (!wpa_s->p2p_group_common_freqs_num)
3067 return 1;
3068
3069 for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
3070 if (wpa_s->p2p_group_common_freqs[i] == freq)
3071 return 1;
3072 }
3073 return 0;
3074}
3075
3076
3077static int wpas_sta_check_ecsa(struct hostapd_data *hapd,
3078 struct sta_info *sta, void *ctx)
3079{
3080 int *ecsa_support = ctx;
3081
3082 *ecsa_support &= sta->ecsa_supported;
3083
3084 return 0;
3085}
3086
3087
3088/* Check if all the peers support eCSA */
3089static int wpas_p2p_go_clients_support_ecsa(struct wpa_supplicant *wpa_s)
3090{
3091 int ecsa_support = 1;
3092
3093 ap_for_each_sta(wpa_s->ap_iface->bss[0], wpas_sta_check_ecsa,
3094 &ecsa_support);
3095
3096 return ecsa_support;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003097}
3098
3099
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003100/**
3101 * Pick the best frequency to use from all the currently used frequencies.
3102 */
3103static int wpas_p2p_pick_best_used_freq(struct wpa_supplicant *wpa_s,
3104 struct wpa_used_freq_data *freqs,
3105 unsigned int num)
3106{
3107 unsigned int i, c;
3108
3109 /* find a candidate freq that is supported by P2P */
3110 for (c = 0; c < num; c++)
3111 if (p2p_supported_freq(wpa_s->global->p2p, freqs[c].freq))
3112 break;
3113
3114 if (c == num)
3115 return 0;
3116
3117 /* once we have a candidate, try to find a 'better' one */
3118 for (i = c + 1; i < num; i++) {
3119 if (!p2p_supported_freq(wpa_s->global->p2p, freqs[i].freq))
3120 continue;
3121
3122 /*
3123 * 1. Infrastructure station interfaces have higher preference.
3124 * 2. P2P Clients have higher preference.
3125 * 3. All others.
3126 */
3127 if (freqs[i].flags & WPA_FREQ_USED_BY_INFRA_STATION) {
3128 c = i;
3129 break;
3130 }
3131
3132 if ((freqs[i].flags & WPA_FREQ_USED_BY_P2P_CLIENT))
3133 c = i;
3134 }
3135 return freqs[c].freq;
3136}
3137
3138
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003139static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
3140 const u8 *go_dev_addr, const u8 *ssid,
3141 size_t ssid_len, int *go, u8 *group_bssid,
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003142 int *force_freq, int persistent_group,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003143 const struct p2p_channels *channels,
3144 int dev_pw_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003145{
3146 struct wpa_supplicant *wpa_s = ctx;
3147 struct wpa_ssid *s;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003148 struct wpa_used_freq_data *freqs;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003149 struct wpa_supplicant *grp;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003150 int best_freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003151
3152 if (!persistent_group) {
3153 wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003154 " to join an active group (SSID: %s)",
3155 MAC2STR(sa), wpa_ssid_txt(ssid, ssid_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003156 if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
3157 (os_memcmp(go_dev_addr, wpa_s->p2p_auth_invite, ETH_ALEN)
3158 == 0 ||
3159 os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0)) {
3160 wpa_printf(MSG_DEBUG, "P2P: Accept previously "
3161 "authorized invitation");
3162 goto accept_inv;
3163 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003164
3165#ifdef CONFIG_WPS_NFC
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003166 if (dev_pw_id >= 0 && wpa_s->p2p_nfc_tag_enabled &&
3167 dev_pw_id == wpa_s->p2p_oob_dev_pw_id) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003168 wpa_printf(MSG_DEBUG, "P2P: Accept invitation based on local enabled NFC Tag");
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003169 wpa_s->p2p_wps_method = WPS_NFC;
3170 wpa_s->pending_join_wps_method = WPS_NFC;
3171 os_memcpy(wpa_s->pending_join_dev_addr,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003172 go_dev_addr, ETH_ALEN);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003173 os_memcpy(wpa_s->pending_join_iface_addr,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003174 bssid, ETH_ALEN);
3175 goto accept_inv;
3176 }
3177#endif /* CONFIG_WPS_NFC */
3178
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003179 /*
3180 * Do not accept the invitation automatically; notify user and
3181 * request approval.
3182 */
3183 return P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
3184 }
3185
3186 grp = wpas_get_p2p_group(wpa_s, ssid, ssid_len, go);
3187 if (grp) {
3188 wpa_printf(MSG_DEBUG, "P2P: Accept invitation to already "
3189 "running persistent group");
3190 if (*go)
3191 os_memcpy(group_bssid, grp->own_addr, ETH_ALEN);
3192 goto accept_inv;
3193 }
3194
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08003195 if (!is_zero_ether_addr(wpa_s->p2p_auth_invite) &&
3196 os_memcmp(sa, wpa_s->p2p_auth_invite, ETH_ALEN) == 0) {
3197 wpa_printf(MSG_DEBUG, "P2P: Accept previously initiated "
3198 "invitation to re-invoke a persistent group");
Dmitry Shmidt76cd2cc2014-05-27 12:56:04 -07003199 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08003200 } else if (!wpa_s->conf->persistent_reconnect)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003201 return P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
3202
3203 for (s = wpa_s->conf->ssid; s; s = s->next) {
3204 if (s->disabled == 2 &&
3205 os_memcmp(s->bssid, go_dev_addr, ETH_ALEN) == 0 &&
3206 s->ssid_len == ssid_len &&
3207 os_memcmp(ssid, s->ssid, ssid_len) == 0)
3208 break;
3209 }
3210
3211 if (!s) {
3212 wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
3213 " requested reinvocation of an unknown group",
3214 MAC2STR(sa));
3215 return P2P_SC_FAIL_UNKNOWN_GROUP;
3216 }
3217
3218 if (s->mode == WPAS_MODE_P2P_GO && !wpas_p2p_create_iface(wpa_s)) {
3219 *go = 1;
3220 if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
3221 wpa_printf(MSG_DEBUG, "P2P: The only available "
3222 "interface is already in use - reject "
3223 "invitation");
3224 return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
3225 }
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003226 if (wpa_s->p2p_mgmt)
3227 os_memcpy(group_bssid, wpa_s->parent->own_addr,
3228 ETH_ALEN);
3229 else
3230 os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003231 } else if (s->mode == WPAS_MODE_P2P_GO) {
3232 *go = 1;
3233 if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO) < 0)
3234 {
3235 wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new "
3236 "interface address for the group");
3237 return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
3238 }
3239 os_memcpy(group_bssid, wpa_s->pending_interface_addr,
3240 ETH_ALEN);
3241 }
3242
3243accept_inv:
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003244 wpas_p2p_set_own_freq_preference(wpa_s, 0);
3245
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003246 best_freq = 0;
3247 freqs = os_calloc(wpa_s->num_multichan_concurrent,
3248 sizeof(struct wpa_used_freq_data));
3249 if (freqs) {
3250 int num_channels = wpa_s->num_multichan_concurrent;
3251 int num = wpas_p2p_valid_oper_freqs(wpa_s, freqs, num_channels);
3252 best_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
3253 os_free(freqs);
3254 }
3255
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003256 /* Get one of the frequencies currently in use */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003257 if (best_freq > 0) {
Dmitry Shmidta0d265f2013-11-19 13:13:41 -08003258 wpa_printf(MSG_DEBUG, "P2P: Trying to prefer a channel already used by one of the interfaces");
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003259 wpas_p2p_set_own_freq_preference(wpa_s, best_freq);
Dmitry Shmidta0d265f2013-11-19 13:13:41 -08003260
3261 if (wpa_s->num_multichan_concurrent < 2 ||
3262 wpas_p2p_num_unused_channels(wpa_s) < 1) {
3263 wpa_printf(MSG_DEBUG, "P2P: No extra channels available - trying to force channel to match a channel already used by one of the interfaces");
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003264 *force_freq = best_freq;
Dmitry Shmidta0d265f2013-11-19 13:13:41 -08003265 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003266 }
3267
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003268 if (*force_freq > 0 && wpa_s->num_multichan_concurrent > 1 &&
3269 wpas_p2p_num_unused_channels(wpa_s) > 0) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003270 if (*go == 0) {
3271 /* We are the client */
3272 wpa_printf(MSG_DEBUG, "P2P: Peer was found to be "
3273 "running a GO but we are capable of MCC, "
3274 "figure out the best channel to use");
3275 *force_freq = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003276 } else if (!freq_included(wpa_s, channels, *force_freq)) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003277 /* We are the GO, and *force_freq is not in the
3278 * intersection */
3279 wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
3280 "in intersection but we are capable of MCC, "
3281 "figure out the best channel to use",
3282 *force_freq);
3283 *force_freq = 0;
3284 }
3285 }
3286
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003287 return P2P_SC_SUCCESS;
3288}
3289
3290
3291static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
3292 const u8 *ssid, size_t ssid_len,
3293 const u8 *go_dev_addr, u8 status,
3294 int op_freq)
3295{
3296 struct wpa_supplicant *wpa_s = ctx;
3297 struct wpa_ssid *s;
3298
3299 for (s = wpa_s->conf->ssid; s; s = s->next) {
3300 if (s->disabled == 2 &&
3301 s->ssid_len == ssid_len &&
3302 os_memcmp(ssid, s->ssid, ssid_len) == 0)
3303 break;
3304 }
3305
3306 if (status == P2P_SC_SUCCESS) {
3307 wpa_printf(MSG_DEBUG, "P2P: Invitation from peer " MACSTR
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003308 " was accepted; op_freq=%d MHz, SSID=%s",
3309 MAC2STR(sa), op_freq, wpa_ssid_txt(ssid, ssid_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003310 if (s) {
Dmitry Shmidt91c40cd2012-09-25 14:23:53 -07003311 int go = s->mode == WPAS_MODE_P2P_GO;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003312 if (go) {
3313 wpa_msg_global(wpa_s, MSG_INFO,
3314 P2P_EVENT_INVITATION_ACCEPTED
3315 "sa=" MACSTR
3316 " persistent=%d freq=%d",
3317 MAC2STR(sa), s->id, op_freq);
3318 } else {
3319 wpa_msg_global(wpa_s, MSG_INFO,
3320 P2P_EVENT_INVITATION_ACCEPTED
3321 "sa=" MACSTR
3322 " persistent=%d",
3323 MAC2STR(sa), s->id);
3324 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003325 wpas_p2p_group_add_persistent(
Hai Shalomb755a2a2020-04-23 21:49:02 -07003326 wpa_s, s, go, 0, op_freq, 0,
3327 wpa_s->conf->p2p_go_ht40,
3328 wpa_s->conf->p2p_go_vht,
3329 0,
3330 wpa_s->conf->p2p_go_he,
3331 wpa_s->conf->p2p_go_edmg, NULL,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003332 go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
Matthew Wang124e5f42022-12-29 07:23:06 +00003333 1, is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
3334 false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003335 } else if (bssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003336 wpa_s->user_initiated_pd = 0;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003337 wpa_msg_global(wpa_s, MSG_INFO,
3338 P2P_EVENT_INVITATION_ACCEPTED
3339 "sa=" MACSTR " go_dev_addr=" MACSTR
3340 " bssid=" MACSTR " unknown-network",
3341 MAC2STR(sa), MAC2STR(go_dev_addr),
3342 MAC2STR(bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003343 wpas_p2p_join(wpa_s, bssid, go_dev_addr,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003344 wpa_s->p2p_wps_method, 0, op_freq,
Dmitry Shmidt344abd32014-01-14 13:17:00 -08003345 ssid, ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003346 }
3347 return;
3348 }
3349
3350 if (status != P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
3351 wpa_printf(MSG_DEBUG, "P2P: Invitation from peer " MACSTR
3352 " was rejected (status %u)", MAC2STR(sa), status);
3353 return;
3354 }
3355
3356 if (!s) {
3357 if (bssid) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003358 wpa_msg_global(wpa_s, MSG_INFO,
3359 P2P_EVENT_INVITATION_RECEIVED
3360 "sa=" MACSTR " go_dev_addr=" MACSTR
3361 " bssid=" MACSTR " unknown-network",
3362 MAC2STR(sa), MAC2STR(go_dev_addr),
3363 MAC2STR(bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003364 } else {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003365 wpa_msg_global(wpa_s, MSG_INFO,
3366 P2P_EVENT_INVITATION_RECEIVED
3367 "sa=" MACSTR " go_dev_addr=" MACSTR
3368 " unknown-network",
3369 MAC2STR(sa), MAC2STR(go_dev_addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003370 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003371 wpas_notify_p2p_invitation_received(wpa_s, sa, go_dev_addr,
3372 bssid, 0, op_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003373 return;
3374 }
3375
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08003376 if (s->mode == WPAS_MODE_P2P_GO && op_freq) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003377 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
3378 "sa=" MACSTR " persistent=%d freq=%d",
3379 MAC2STR(sa), s->id, op_freq);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08003380 } else {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003381 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RECEIVED
3382 "sa=" MACSTR " persistent=%d",
3383 MAC2STR(sa), s->id);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08003384 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003385 wpas_notify_p2p_invitation_received(wpa_s, sa, go_dev_addr, bssid,
3386 s->id, op_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003387}
3388
3389
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003390static void wpas_remove_persistent_peer(struct wpa_supplicant *wpa_s,
3391 struct wpa_ssid *ssid,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003392 const u8 *peer, int inv)
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003393{
3394 size_t i;
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003395 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003396
3397 if (ssid == NULL)
3398 return;
3399
3400 for (i = 0; ssid->p2p_client_list && i < ssid->num_p2p_clients; i++) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003401 if (os_memcmp(ssid->p2p_client_list + i * 2 * ETH_ALEN, peer,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003402 ETH_ALEN) == 0)
3403 break;
3404 }
Dmitry Shmidt6aa8ae42014-07-07 09:31:33 -07003405 if (i >= ssid->num_p2p_clients || !ssid->p2p_client_list) {
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003406 if (ssid->mode != WPAS_MODE_P2P_GO &&
3407 os_memcmp(ssid->bssid, peer, ETH_ALEN) == 0) {
3408 wpa_printf(MSG_DEBUG, "P2P: Remove persistent group %d "
3409 "due to invitation result", ssid->id);
3410 wpas_notify_network_removed(wpa_s, ssid);
3411 wpa_config_remove_network(wpa_s->conf, ssid->id);
3412 return;
3413 }
3414 return; /* Peer not found in client list */
3415 }
3416
3417 wpa_printf(MSG_DEBUG, "P2P: Remove peer " MACSTR " from persistent "
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003418 "group %d client list%s",
3419 MAC2STR(peer), ssid->id,
3420 inv ? " due to invitation result" : "");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003421 os_memmove(ssid->p2p_client_list + i * 2 * ETH_ALEN,
3422 ssid->p2p_client_list + (i + 1) * 2 * ETH_ALEN,
3423 (ssid->num_p2p_clients - i - 1) * 2 * ETH_ALEN);
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003424 ssid->num_p2p_clients--;
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07003425 if (p2p_wpa_s->conf->update_config &&
3426 wpa_config_write(p2p_wpa_s->confname, p2p_wpa_s->conf))
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003427 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003428}
3429
3430
3431static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
3432 const u8 *peer)
3433{
3434 struct wpa_ssid *ssid;
3435
3436 wpa_s = wpa_s->global->p2p_invite_group;
3437 if (wpa_s == NULL)
3438 return; /* No known invitation group */
3439 ssid = wpa_s->current_ssid;
3440 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
3441 !ssid->p2p_persistent_group)
3442 return; /* Not operating as a GO in persistent group */
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003443 ssid = wpas_p2p_get_persistent(wpa_s->p2pdev, peer,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003444 ssid->ssid, ssid->ssid_len);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003445 wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003446}
3447
3448
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08003449static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003450 const struct p2p_channels *channels,
Dmitry Shmidt15907092014-03-25 10:42:57 -07003451 const u8 *peer, int neg_freq,
3452 int peer_oper_freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003453{
3454 struct wpa_supplicant *wpa_s = ctx;
3455 struct wpa_ssid *ssid;
Dmitry Shmidt15907092014-03-25 10:42:57 -07003456 int freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003457
3458 if (bssid) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003459 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
3460 "status=%d " MACSTR,
3461 status, MAC2STR(bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003462 } else {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003463 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
3464 "status=%d ", status);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003465 }
3466 wpas_notify_p2p_invitation_result(wpa_s, status, bssid);
3467
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003468 wpa_printf(MSG_DEBUG, "P2P: Invitation result - status=%d peer=" MACSTR,
3469 status, MAC2STR(peer));
3470 if (wpa_s->pending_invite_ssid_id == -1) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003471 struct wpa_supplicant *group_if =
3472 wpa_s->global->p2p_invite_group;
3473
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003474 if (status == P2P_SC_FAIL_UNKNOWN_GROUP)
3475 wpas_remove_persistent_client(wpa_s, peer);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003476
3477 /*
3478 * Invitation to an active group. If this is successful and we
3479 * are the GO, set the client wait to postpone some concurrent
3480 * operations and to allow provisioning and connection to happen
3481 * more quickly.
3482 */
3483 if (status == P2P_SC_SUCCESS &&
3484 group_if && group_if->current_ssid &&
3485 group_if->current_ssid->mode == WPAS_MODE_P2P_GO) {
3486 os_get_reltime(&wpa_s->global->p2p_go_wait_client);
3487#ifdef CONFIG_TESTING_OPTIONS
3488 if (group_if->p2p_go_csa_on_inv) {
3489 wpa_printf(MSG_DEBUG,
3490 "Testing: force P2P GO CSA after invitation");
3491 eloop_cancel_timeout(
3492 wpas_p2p_reconsider_moving_go,
3493 wpa_s, NULL);
3494 eloop_register_timeout(
3495 0, 50000,
3496 wpas_p2p_reconsider_moving_go,
3497 wpa_s, NULL);
3498 }
3499#endif /* CONFIG_TESTING_OPTIONS */
3500 }
3501 return;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003502 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003503
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08003504 if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
3505 wpa_printf(MSG_DEBUG, "P2P: Waiting for peer to start another "
3506 "invitation exchange to indicate readiness for "
3507 "re-invocation");
3508 }
3509
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003510 if (status != P2P_SC_SUCCESS) {
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003511 if (status == P2P_SC_FAIL_UNKNOWN_GROUP) {
3512 ssid = wpa_config_get_network(
3513 wpa_s->conf, wpa_s->pending_invite_ssid_id);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003514 wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003515 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003516 wpas_p2p_remove_pending_group_interface(wpa_s);
3517 return;
3518 }
3519
3520 ssid = wpa_config_get_network(wpa_s->conf,
3521 wpa_s->pending_invite_ssid_id);
3522 if (ssid == NULL) {
3523 wpa_printf(MSG_ERROR, "P2P: Could not find persistent group "
3524 "data matching with invitation");
3525 return;
3526 }
3527
Jouni Malinen2c5b17d2012-10-13 21:52:46 -07003528 /*
3529 * The peer could have missed our ctrl::ack frame for Invitation
3530 * Response and continue retransmitting the frame. To reduce the
3531 * likelihood of the peer not getting successful TX status for the
3532 * Invitation Response frame, wait a short time here before starting
3533 * the persistent group so that we will remain on the current channel to
3534 * acknowledge any possible retransmission from the peer.
3535 */
3536 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: 50 ms wait on current channel before "
3537 "starting persistent group");
3538 os_sleep(0, 50000);
3539
Dmitry Shmidt15907092014-03-25 10:42:57 -07003540 if (neg_freq > 0 && ssid->mode == WPAS_MODE_P2P_GO &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003541 freq_included(wpa_s, channels, neg_freq))
Dmitry Shmidt15907092014-03-25 10:42:57 -07003542 freq = neg_freq;
3543 else if (peer_oper_freq > 0 && ssid->mode != WPAS_MODE_P2P_GO &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003544 freq_included(wpa_s, channels, peer_oper_freq))
Dmitry Shmidt15907092014-03-25 10:42:57 -07003545 freq = peer_oper_freq;
3546 else
3547 freq = 0;
3548
3549 wpa_printf(MSG_DEBUG, "P2P: Persistent group invitation success - op_freq=%d MHz SSID=%s",
3550 freq, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003551 wpas_p2p_group_add_persistent(wpa_s, ssid,
Jouni Malinen31be0a42012-08-31 21:20:51 +03003552 ssid->mode == WPAS_MODE_P2P_GO,
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003553 wpa_s->p2p_persistent_go_freq,
Dmitry Shmidt15907092014-03-25 10:42:57 -07003554 freq,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003555 wpa_s->p2p_go_vht_center_freq2,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003556 wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003557 wpa_s->p2p_go_max_oper_chwidth,
Hai Shalom74f70d42019-02-11 14:42:39 -08003558 wpa_s->p2p_go_he,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003559 wpa_s->p2p_go_edmg,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003560 channels,
Dmitry Shmidt56052862013-10-04 10:23:25 -07003561 ssid->mode == WPAS_MODE_P2P_GO ?
3562 P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
Hai Shalomc1a21442022-02-04 13:43:00 -08003563 0, 1,
Matthew Wang124e5f42022-12-29 07:23:06 +00003564 is_p2p_allow_6ghz(wpa_s->global->p2p), 0,
3565 false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003566}
3567
3568
Dmitry Shmidt04949592012-07-19 12:16:46 -07003569static int wpas_p2p_disallowed_freq(struct wpa_global *global,
3570 unsigned int freq)
3571{
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003572 if (freq_range_list_includes(&global->p2p_go_avoid_freq, freq))
3573 return 1;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003574 return freq_range_list_includes(&global->p2p_disallow_freq, freq);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003575}
3576
3577
3578static void wpas_p2p_add_chan(struct p2p_reg_class *reg, u8 chan)
3579{
3580 reg->channel[reg->channels] = chan;
3581 reg->channels++;
3582}
3583
3584
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003585static int wpas_p2p_default_channels(struct wpa_supplicant *wpa_s,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003586 struct p2p_channels *chan,
3587 struct p2p_channels *cli_chan)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003588{
3589 int i, cla = 0;
3590
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003591 wpa_s->global->p2p_24ghz_social_channels = 1;
3592
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003593 os_memset(cli_chan, 0, sizeof(*cli_chan));
3594
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003595 wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for 2.4 GHz "
3596 "band");
3597
3598 /* Operating class 81 - 2.4 GHz band channels 1..13 */
3599 chan->reg_class[cla].reg_class = 81;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003600 chan->reg_class[cla].channels = 0;
3601 for (i = 0; i < 11; i++) {
3602 if (!wpas_p2p_disallowed_freq(wpa_s->global, 2412 + i * 5))
3603 wpas_p2p_add_chan(&chan->reg_class[cla], i + 1);
3604 }
3605 if (chan->reg_class[cla].channels)
3606 cla++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003607
3608 wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for lower 5 GHz "
3609 "band");
3610
3611 /* Operating class 115 - 5 GHz, channels 36-48 */
3612 chan->reg_class[cla].reg_class = 115;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003613 chan->reg_class[cla].channels = 0;
3614 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 36 * 5))
3615 wpas_p2p_add_chan(&chan->reg_class[cla], 36);
3616 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 40 * 5))
3617 wpas_p2p_add_chan(&chan->reg_class[cla], 40);
3618 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 44 * 5))
3619 wpas_p2p_add_chan(&chan->reg_class[cla], 44);
3620 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 48 * 5))
3621 wpas_p2p_add_chan(&chan->reg_class[cla], 48);
3622 if (chan->reg_class[cla].channels)
3623 cla++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003624
3625 wpa_printf(MSG_DEBUG, "P2P: Enable operating classes for higher 5 GHz "
3626 "band");
3627
3628 /* Operating class 124 - 5 GHz, channels 149,153,157,161 */
3629 chan->reg_class[cla].reg_class = 124;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003630 chan->reg_class[cla].channels = 0;
3631 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 149 * 5))
3632 wpas_p2p_add_chan(&chan->reg_class[cla], 149);
3633 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 153 * 5))
3634 wpas_p2p_add_chan(&chan->reg_class[cla], 153);
3635 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 156 * 5))
3636 wpas_p2p_add_chan(&chan->reg_class[cla], 157);
3637 if (!wpas_p2p_disallowed_freq(wpa_s->global, 5000 + 161 * 5))
3638 wpas_p2p_add_chan(&chan->reg_class[cla], 161);
3639 if (chan->reg_class[cla].channels)
3640 cla++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003641
3642 chan->reg_classes = cla;
3643 return 0;
3644}
3645
3646
Hai Shalomc1a21442022-02-04 13:43:00 -08003647static enum chan_allowed has_channel(struct wpa_global *global,
3648 struct hostapd_hw_modes *mode, u8 op_class,
3649 u8 chan, int *flags)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650{
3651 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003652 unsigned int freq;
3653
Hai Shalomc1a21442022-02-04 13:43:00 -08003654 freq = ieee80211_chan_to_freq(NULL, op_class, chan);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003655 if (wpas_p2p_disallowed_freq(global, freq))
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003656 return NOT_ALLOWED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003657
3658 for (i = 0; i < mode->num_channels; i++) {
Hai Shalomc1a21442022-02-04 13:43:00 -08003659 if ((unsigned int) mode->channels[i].freq == freq) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003660 if (flags)
3661 *flags = mode->channels[i].flag;
Hai Shalomc1a21442022-02-04 13:43:00 -08003662 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003663 return NOT_ALLOWED;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003664 if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR)
3665 return NO_IR;
Hai Shalomc1a21442022-02-04 13:43:00 -08003666 if (mode->channels[i].flag & HOSTAPD_CHAN_RADAR)
3667 return RADAR;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003668 return ALLOWED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669 }
3670 }
3671
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003672 return NOT_ALLOWED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003673}
3674
3675
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003676static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
3677 struct hostapd_hw_modes *mode,
Hai Shalomc1a21442022-02-04 13:43:00 -08003678 u8 channel, const u8 *center_channels,
3679 size_t num_chan)
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003680{
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003681 size_t i;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003682
3683 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
3684 return 0;
3685
Hai Shalomc1a21442022-02-04 13:43:00 -08003686 for (i = 0; i < num_chan; i++)
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003687 /*
3688 * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
3689 * so the center channel is 6 channels away from the start/end.
3690 */
3691 if (channel >= center_channels[i] - 6 &&
3692 channel <= center_channels[i] + 6)
3693 return center_channels[i];
3694
3695 return 0;
3696}
3697
3698
Hai Shalomc1a21442022-02-04 13:43:00 -08003699static const u8 center_channels_5ghz_80mhz[] = { 42, 58, 106, 122, 138,
3700 155, 171 };
3701static const u8 center_channels_6ghz_80mhz[] = { 7, 23, 39, 55, 71, 87, 103,
3702 119, 135, 151, 167, 183, 199,
3703 215 };
3704
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003705static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
3706 struct hostapd_hw_modes *mode,
Hai Shalomc1a21442022-02-04 13:43:00 -08003707 u8 op_class, u8 channel, u8 bw)
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003708{
3709 u8 center_chan;
3710 int i, flags;
3711 enum chan_allowed res, ret = ALLOWED;
Hai Shalomc1a21442022-02-04 13:43:00 -08003712 const u8 *chans;
3713 size_t num_chans;
3714 bool is_6ghz = is_6ghz_op_class(op_class);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003715
Hai Shalomc1a21442022-02-04 13:43:00 -08003716 if (is_6ghz) {
3717 chans = center_channels_6ghz_80mhz;
3718 num_chans = ARRAY_SIZE(center_channels_6ghz_80mhz);
3719 } else {
3720 chans = center_channels_5ghz_80mhz;
3721 num_chans = ARRAY_SIZE(center_channels_5ghz_80mhz);
3722 }
3723 center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel,
3724 chans, num_chans);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003725 if (!center_chan)
3726 return NOT_ALLOWED;
Hai Shalomc1a21442022-02-04 13:43:00 -08003727 if (!wpa_s->p2p_go_allow_dfs &&
3728 !is_6ghz && center_chan >= 58 && center_chan <= 138)
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003729 return NOT_ALLOWED; /* Do not allow DFS channels for P2P */
3730
3731 /* check all the channels are available */
3732 for (i = 0; i < 4; i++) {
3733 int adj_chan = center_chan - 6 + i * 4;
3734
Hai Shalomc1a21442022-02-04 13:43:00 -08003735 res = has_channel(wpa_s->global, mode, op_class, adj_chan,
3736 &flags);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003737 if (res == NOT_ALLOWED)
3738 return NOT_ALLOWED;
Hai Shalomc1a21442022-02-04 13:43:00 -08003739 if (res == RADAR)
3740 ret = RADAR;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003741 if (res == NO_IR)
3742 ret = NO_IR;
Hai Shalomc1a21442022-02-04 13:43:00 -08003743 if (!is_6ghz) {
3744 if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
3745 return NOT_ALLOWED;
3746 if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
3747 return NOT_ALLOWED;
3748 if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30))
3749 return NOT_ALLOWED;
3750 if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
3751 return NOT_ALLOWED;
3752 } else if (is_6ghz &&
3753 (!(wpas_get_6ghz_he_chwidth_capab(mode) &
3754 HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003755 return NOT_ALLOWED;
Hai Shalomc1a21442022-02-04 13:43:00 -08003756 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003757 }
3758
3759 return ret;
3760}
3761
3762
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003763static int wpas_p2p_get_center_160mhz(struct wpa_supplicant *wpa_s,
3764 struct hostapd_hw_modes *mode,
Hai Shalomc1a21442022-02-04 13:43:00 -08003765 u8 channel, const u8 *center_channels,
3766 size_t num_chan)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003767{
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003768 unsigned int i;
3769
3770 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
3771 return 0;
3772
Hai Shalomc1a21442022-02-04 13:43:00 -08003773 for (i = 0; i < num_chan; i++)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003774 /*
3775 * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
3776 * so the center channel is 14 channels away from the start/end.
3777 */
3778 if (channel >= center_channels[i] - 14 &&
3779 channel <= center_channels[i] + 14)
3780 return center_channels[i];
3781
3782 return 0;
3783}
3784
3785
Hai Shalomc1a21442022-02-04 13:43:00 -08003786static const u8 center_channels_5ghz_160mhz[] = { 50, 114, 163 };
3787static const u8 center_channels_6ghz_160mhz[] = { 15, 47, 79, 111, 143, 175,
3788 207 };
3789
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003790static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
3791 struct hostapd_hw_modes *mode,
Hai Shalomc1a21442022-02-04 13:43:00 -08003792 u8 op_class, u8 channel, u8 bw)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003793{
3794 u8 center_chan;
3795 int i, flags;
3796 enum chan_allowed res, ret = ALLOWED;
Hai Shalomc1a21442022-02-04 13:43:00 -08003797 const u8 *chans;
3798 size_t num_chans;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003799
Hai Shalomc1a21442022-02-04 13:43:00 -08003800 if (is_6ghz_op_class(op_class)) {
3801 chans = center_channels_6ghz_160mhz;
3802 num_chans = ARRAY_SIZE(center_channels_6ghz_160mhz);
3803 } else {
3804 chans = center_channels_5ghz_160mhz;
3805 num_chans = ARRAY_SIZE(center_channels_5ghz_160mhz);
3806 }
3807 center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel,
3808 chans, num_chans);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003809 if (!center_chan)
3810 return NOT_ALLOWED;
3811 /* VHT 160 MHz uses DFS channels in most countries. */
3812
3813 /* Check all the channels are available */
3814 for (i = 0; i < 8; i++) {
3815 int adj_chan = center_chan - 14 + i * 4;
3816
Hai Shalomc1a21442022-02-04 13:43:00 -08003817 res = has_channel(wpa_s->global, mode, op_class, adj_chan,
3818 &flags);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003819 if (res == NOT_ALLOWED)
3820 return NOT_ALLOWED;
3821
Hai Shalomc1a21442022-02-04 13:43:00 -08003822 if (res == RADAR)
3823 ret = RADAR;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003824 if (res == NO_IR)
3825 ret = NO_IR;
3826
Hai Shalomc1a21442022-02-04 13:43:00 -08003827 if (!is_6ghz_op_class(op_class)) {
3828 if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
3829 return NOT_ALLOWED;
3830 if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
3831 return NOT_ALLOWED;
3832 if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110))
3833 return NOT_ALLOWED;
3834 if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90))
3835 return NOT_ALLOWED;
3836 if (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70))
3837 return NOT_ALLOWED;
3838 if (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50))
3839 return NOT_ALLOWED;
3840 if (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30))
3841 return NOT_ALLOWED;
3842 if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
3843 return NOT_ALLOWED;
3844 } else if (is_6ghz_op_class(op_class) &&
3845 (!(wpas_get_6ghz_he_chwidth_capab(mode) &
3846 HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G))) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003847 return NOT_ALLOWED;
Hai Shalomc1a21442022-02-04 13:43:00 -08003848 }
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003849 }
3850
3851 return ret;
3852}
3853
3854
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003855static enum chan_allowed wpas_p2p_verify_edmg(struct wpa_supplicant *wpa_s,
3856 struct hostapd_hw_modes *mode,
3857 u8 channel)
3858{
3859 struct ieee80211_edmg_config edmg;
3860
3861 hostapd_encode_edmg_chan(1, channel, 0, &edmg);
3862 if (edmg.channels && ieee802_edmg_is_allowed(mode->edmg, edmg))
3863 return ALLOWED;
3864
3865 return NOT_ALLOWED;
3866}
3867
3868
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003869static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
3870 struct hostapd_hw_modes *mode,
Hai Shalomc1a21442022-02-04 13:43:00 -08003871 u8 op_class, u8 channel, u8 bw)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003872{
Dmitry Shmidt96be6222014-02-13 10:16:51 -08003873 int flag = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003874 enum chan_allowed res, res2;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003875
Sunil Ravi89eba102022-09-13 21:04:37 -07003876 if (is_6ghz_op_class(op_class) && !is_6ghz_psc_frequency(
3877 p2p_channel_to_freq(op_class, channel)))
3878 return NOT_ALLOWED;
3879
Hai Shalomc1a21442022-02-04 13:43:00 -08003880 res2 = res = has_channel(wpa_s->global, mode, op_class, channel, &flag);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003881 if (bw == BW40MINUS) {
3882 if (!(flag & HOSTAPD_CHAN_HT40MINUS))
3883 return NOT_ALLOWED;
Hai Shalomc1a21442022-02-04 13:43:00 -08003884 res2 = has_channel(wpa_s->global, mode, op_class, channel - 4,
3885 NULL);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003886 } else if (bw == BW40PLUS) {
3887 if (!(flag & HOSTAPD_CHAN_HT40PLUS))
3888 return NOT_ALLOWED;
Hai Shalomc1a21442022-02-04 13:43:00 -08003889 res2 = has_channel(wpa_s->global, mode, op_class, channel + 4,
3890 NULL);
3891 } else if (is_6ghz_op_class(op_class) && bw == BW40) {
3892 if (mode->mode != HOSTAPD_MODE_IEEE80211A)
3893 return NOT_ALLOWED;
3894 if (get_6ghz_sec_channel(channel) < 0)
3895 res2 = has_channel(wpa_s->global, mode, op_class,
3896 channel - 4, NULL);
3897 else
3898 res2 = has_channel(wpa_s->global, mode, op_class,
3899 channel + 4, NULL);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003900 } else if (bw == BW80) {
Hai Shalomc1a21442022-02-04 13:43:00 -08003901 res2 = wpas_p2p_verify_80mhz(wpa_s, mode, op_class, channel,
3902 bw);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003903 } else if (bw == BW160) {
Hai Shalomc1a21442022-02-04 13:43:00 -08003904 res2 = wpas_p2p_verify_160mhz(wpa_s, mode, op_class, channel,
3905 bw);
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003906 } else if (bw == BW4320 || bw == BW6480 || bw == BW8640) {
3907 return wpas_p2p_verify_edmg(wpa_s, mode, channel);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003908 }
3909
3910 if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
3911 return NOT_ALLOWED;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003912 if (res == NO_IR || res2 == NO_IR)
3913 return NO_IR;
Hai Shalomc1a21442022-02-04 13:43:00 -08003914 if (res == RADAR || res2 == RADAR)
3915 return RADAR;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003916 return res;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003917}
3918
3919
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003920static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003921 struct p2p_channels *chan,
Hai Shalom60840252021-02-19 19:02:11 -08003922 struct p2p_channels *cli_chan,
3923 bool p2p_disable_6ghz)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003924{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003925 struct hostapd_hw_modes *mode;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003926 int cla, op, cli_cla;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003927
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003928 if (wpa_s->hw.modes == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929 wpa_printf(MSG_DEBUG, "P2P: Driver did not support fetching "
3930 "of all supported channels; assume dualband "
3931 "support");
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003932 return wpas_p2p_default_channels(wpa_s, chan, cli_chan);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003933 }
3934
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003935 cla = cli_cla = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003936
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003937 for (op = 0; global_op_class[op].op_class; op++) {
3938 const struct oper_class_map *o = &global_op_class[op];
Hai Shalomc1a21442022-02-04 13:43:00 -08003939 unsigned int ch;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003940 struct p2p_reg_class *reg = NULL, *cli_reg = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003941
Hai Shalom899fcc72020-10-19 14:38:18 -07003942 if (o->p2p == NO_P2P_SUPP ||
Hai Shalom60840252021-02-19 19:02:11 -08003943 (is_6ghz_op_class(o->op_class) && p2p_disable_6ghz))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003944 continue;
3945
Hai Shalomfdcde762020-04-02 11:19:20 -07003946 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode,
3947 is_6ghz_op_class(o->op_class));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003948 if (mode == NULL)
3949 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003950 if (mode->mode == HOSTAPD_MODE_IEEE80211G)
3951 wpa_s->global->p2p_24ghz_social_channels = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003952 for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003953 enum chan_allowed res;
Hai Shalom899fcc72020-10-19 14:38:18 -07003954
3955 /* Check for non-continuous jump in channel index
3956 * incrementation */
Hai Shalom60840252021-02-19 19:02:11 -08003957 if ((o->op_class >= 128 && o->op_class <= 130) &&
Hai Shalom899fcc72020-10-19 14:38:18 -07003958 ch < 149 && ch + o->inc > 149)
3959 ch = 149;
3960
Hai Shalomc1a21442022-02-04 13:43:00 -08003961 res = wpas_p2p_verify_channel(wpa_s, mode, o->op_class,
3962 ch, o->bw);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003963 if (res == ALLOWED) {
3964 if (reg == NULL) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003965 if (cla == P2P_MAX_REG_CLASSES)
3966 continue;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003967 wpa_printf(MSG_DEBUG, "P2P: Add operating class %u",
3968 o->op_class);
3969 reg = &chan->reg_class[cla];
3970 cla++;
3971 reg->reg_class = o->op_class;
3972 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003973 if (reg->channels == P2P_MAX_REG_CLASS_CHANNELS)
3974 continue;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003975 reg->channel[reg->channels] = ch;
3976 reg->channels++;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003977 } else if (res == NO_IR &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003978 wpa_s->conf->p2p_add_cli_chan) {
3979 if (cli_reg == NULL) {
Hai Shalomfdcde762020-04-02 11:19:20 -07003980 if (cli_cla == P2P_MAX_REG_CLASSES)
3981 continue;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003982 wpa_printf(MSG_DEBUG, "P2P: Add operating class %u (client only)",
3983 o->op_class);
3984 cli_reg = &cli_chan->reg_class[cli_cla];
3985 cli_cla++;
3986 cli_reg->reg_class = o->op_class;
3987 }
Hai Shalomfdcde762020-04-02 11:19:20 -07003988 if (cli_reg->channels ==
3989 P2P_MAX_REG_CLASS_CHANNELS)
3990 continue;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003991 cli_reg->channel[cli_reg->channels] = ch;
3992 cli_reg->channels++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003993 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003994 }
3995 if (reg) {
3996 wpa_hexdump(MSG_DEBUG, "P2P: Channels",
3997 reg->channel, reg->channels);
3998 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003999 if (cli_reg) {
4000 wpa_hexdump(MSG_DEBUG, "P2P: Channels (client only)",
4001 cli_reg->channel, cli_reg->channels);
4002 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004003 }
4004
4005 chan->reg_classes = cla;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004006 cli_chan->reg_classes = cli_cla;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004007
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004008 return 0;
4009}
4010
4011
Hai Shalomc1a21442022-02-04 13:43:00 -08004012int wpas_p2p_get_sec_channel_offset_40mhz(struct wpa_supplicant *wpa_s,
4013 struct hostapd_hw_modes *mode,
4014 u8 channel)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004015{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004016 int op;
4017 enum chan_allowed ret;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004018
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004019 for (op = 0; global_op_class[op].op_class; op++) {
4020 const struct oper_class_map *o = &global_op_class[op];
Sunil Ravi77d572f2023-01-17 23:58:31 +00004021 u16 ch = 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004022
Hai Shalomc1a21442022-02-04 13:43:00 -08004023 /* Allow DFS channels marked as NO_P2P_SUPP to be used with
4024 * driver offloaded DFS. */
4025 if ((o->p2p == NO_P2P_SUPP &&
4026 (!is_dfs_global_op_class(o->op_class) ||
4027 !wpa_s->p2p_go_allow_dfs)) ||
Hai Shalom899fcc72020-10-19 14:38:18 -07004028 (is_6ghz_op_class(o->op_class) &&
4029 wpa_s->conf->p2p_6ghz_disable))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004030 continue;
4031
Sunil Ravi77d572f2023-01-17 23:58:31 +00004032 /* IEEE Std 802.11ax-2021 26.17.2.3.2: "A 6 GHz-only AP should
4033 * set up the BSS with a primary 20 MHz channel that coincides
4034 * with a preferred scanning channel (PSC)."
4035 * 6 GHz BW40 operation class 132 in wpa_supplicant uses the
4036 * lowest 20 MHz channel for simplicity, so increase ch by 4 to
4037 * match the PSC.
4038 */
Hai Shalomc1a21442022-02-04 13:43:00 -08004039 if (is_6ghz_op_class(o->op_class) && o->bw == BW40 &&
4040 get_6ghz_sec_channel(channel) < 0)
Sunil Ravi77d572f2023-01-17 23:58:31 +00004041 ch = 4;
Hai Shalomc1a21442022-02-04 13:43:00 -08004042
Sunil Ravi77d572f2023-01-17 23:58:31 +00004043 for (ch += o->min_chan; ch <= o->max_chan; ch += o->inc) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004044 if (o->mode != HOSTAPD_MODE_IEEE80211A ||
Hai Shalomc1a21442022-02-04 13:43:00 -08004045 (o->bw != BW40PLUS && o->bw != BW40MINUS &&
4046 o->bw != BW40) ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00004047 ch != channel)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004048 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08004049 ret = wpas_p2p_verify_channel(wpa_s, mode, o->op_class,
4050 ch, o->bw);
4051 if (ret == ALLOWED) {
4052 if (is_6ghz_op_class(o->op_class) &&
4053 o->bw == BW40)
4054 return get_6ghz_sec_channel(channel);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004055 return (o->bw == BW40MINUS) ? -1 : 1;
Hai Shalomc1a21442022-02-04 13:43:00 -08004056 }
4057 if (ret == RADAR && wpa_s->p2p_go_allow_dfs) {
4058 /* Allow RADAR channels used for driver
4059 * offloaded DFS */
4060 return (o->bw == BW40MINUS) ? -1 : 1;
4061 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004062 }
4063 }
4064 return 0;
4065}
4066
4067
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004068int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
Hai Shalomc1a21442022-02-04 13:43:00 -08004069 struct hostapd_hw_modes *mode, u8 channel,
4070 u8 op_class)
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004071{
Hai Shalomc1a21442022-02-04 13:43:00 -08004072 const u8 *chans;
4073 size_t num_chans;
4074 enum chan_allowed ret;
4075
4076 ret = wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW80);
4077 if (!(ret == ALLOWED || (ret == RADAR && wpa_s->p2p_go_allow_dfs)))
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004078 return 0;
4079
Hai Shalomc1a21442022-02-04 13:43:00 -08004080 if (is_6ghz_op_class(op_class)) {
4081 chans = center_channels_6ghz_80mhz;
4082 num_chans = ARRAY_SIZE(center_channels_6ghz_80mhz);
4083 } else {
4084 chans = center_channels_5ghz_80mhz;
4085 num_chans = ARRAY_SIZE(center_channels_5ghz_80mhz);
4086 }
4087 return wpas_p2p_get_center_80mhz(wpa_s, mode, channel,
4088 chans, num_chans);
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07004089}
4090
4091
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004092int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
Hai Shalomc1a21442022-02-04 13:43:00 -08004093 struct hostapd_hw_modes *mode, u8 channel,
4094 u8 op_class)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004095{
Hai Shalomc1a21442022-02-04 13:43:00 -08004096 const u8 *chans;
4097 size_t num_chans;
4098 enum chan_allowed ret;
4099
4100 ret = wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW160);
4101 if (!(ret == ALLOWED || (ret == RADAR && wpa_s->p2p_go_allow_dfs)))
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004102 return 0;
Hai Shalomc1a21442022-02-04 13:43:00 -08004103 if (is_6ghz_op_class(op_class)) {
4104 chans = center_channels_6ghz_160mhz;
4105 num_chans = ARRAY_SIZE(center_channels_6ghz_160mhz);
4106 } else {
4107 chans = center_channels_5ghz_160mhz;
4108 num_chans = ARRAY_SIZE(center_channels_5ghz_160mhz);
4109 }
4110 return wpas_p2p_get_center_160mhz(wpa_s, mode, channel,
4111 chans, num_chans);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004112}
4113
4114
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004115static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf,
4116 size_t buf_len)
4117{
4118 struct wpa_supplicant *wpa_s = ctx;
4119
4120 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4121 if (os_memcmp(wpa_s->own_addr, interface_addr, ETH_ALEN) == 0)
4122 break;
4123 }
4124 if (wpa_s == NULL)
4125 return -1;
4126
4127 return wpa_drv_get_noa(wpa_s, buf, buf_len);
4128}
4129
4130
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004131struct wpa_supplicant * wpas_get_p2p_go_iface(struct wpa_supplicant *wpa_s,
4132 const u8 *ssid, size_t ssid_len)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004133{
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004134 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4135 struct wpa_ssid *s = wpa_s->current_ssid;
4136 if (s == NULL)
4137 continue;
4138 if (s->mode != WPAS_MODE_P2P_GO &&
4139 s->mode != WPAS_MODE_AP &&
4140 s->mode != WPAS_MODE_P2P_GROUP_FORMATION)
4141 continue;
4142 if (s->ssid_len != ssid_len ||
Dmitry Shmidt03658832014-08-13 11:03:49 -07004143 os_memcmp(ssid, s->ssid, ssid_len) != 0)
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004144 continue;
4145 return wpa_s;
4146 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004147
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004148 return NULL;
4149
4150}
4151
4152
4153struct wpa_supplicant * wpas_get_p2p_client_iface(struct wpa_supplicant *wpa_s,
4154 const u8 *peer_dev_addr)
4155{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004156 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4157 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004158 if (ssid && (ssid->mode != WPAS_MODE_INFRA || !ssid->p2p_group))
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004159 continue;
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004160 if (os_memcmp(wpa_s->go_dev_addr, peer_dev_addr, ETH_ALEN) == 0)
4161 return wpa_s;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004162 }
4163
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07004164 return NULL;
4165}
4166
4167
4168static int wpas_go_connected(void *ctx, const u8 *dev_addr)
4169{
4170 struct wpa_supplicant *wpa_s = ctx;
4171
4172 return wpas_get_p2p_client_iface(wpa_s, dev_addr) != NULL;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004173}
4174
4175
Dmitry Shmidt18463232014-01-24 12:29:41 -08004176static int wpas_is_concurrent_session_active(void *ctx)
4177{
4178 struct wpa_supplicant *wpa_s = ctx;
4179 struct wpa_supplicant *ifs;
4180
4181 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
4182 if (ifs == wpa_s)
4183 continue;
4184 if (ifs->wpa_state > WPA_ASSOCIATED)
4185 return 1;
4186 }
4187 return 0;
4188}
4189
4190
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004191static void wpas_p2p_debug_print(void *ctx, int level, const char *msg)
4192{
4193 struct wpa_supplicant *wpa_s = ctx;
4194 wpa_msg_global(wpa_s, level, "P2P: %s", msg);
4195}
4196
4197
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004198int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s,
4199 const char *conf_p2p_dev)
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004200{
4201 struct wpa_interface iface;
4202 struct wpa_supplicant *p2pdev_wpa_s;
4203 char ifname[100];
4204 char force_name[100];
4205 int ret;
Hai Shalom60840252021-02-19 19:02:11 -08004206 const u8 *if_addr = NULL;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004207
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004208 ret = os_snprintf(ifname, sizeof(ifname), P2P_MGMT_DEVICE_PREFIX "%s",
4209 wpa_s->ifname);
4210 if (os_snprintf_error(sizeof(ifname), ret))
4211 return -1;
Hai Shalom899fcc72020-10-19 14:38:18 -07004212 /* Cut length at the maximum size. Note that we don't need to ensure
4213 * collision free names here as the created interface is not a netdev.
4214 */
4215 ifname[IFNAMSIZ - 1] = '\0';
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004216 force_name[0] = '\0';
4217 wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE;
Hai Shalom60840252021-02-19 19:02:11 -08004218
4219 if (wpa_s->conf->p2p_device_random_mac_addr == 2 &&
4220 !is_zero_ether_addr(wpa_s->conf->p2p_device_persistent_mac_addr))
4221 if_addr = wpa_s->conf->p2p_device_persistent_mac_addr;
4222
4223 ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, if_addr, NULL,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004224 force_name, wpa_s->pending_interface_addr, NULL);
4225 if (ret < 0) {
4226 wpa_printf(MSG_DEBUG, "P2P: Failed to create P2P Device interface");
4227 return ret;
4228 }
4229 os_strlcpy(wpa_s->pending_interface_name, ifname,
4230 sizeof(wpa_s->pending_interface_name));
4231
4232 os_memset(&iface, 0, sizeof(iface));
4233 iface.p2p_mgmt = 1;
4234 iface.ifname = wpa_s->pending_interface_name;
4235 iface.driver = wpa_s->driver->name;
4236 iface.driver_param = wpa_s->conf->driver_param;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004237
4238 /*
4239 * If a P2P Device configuration file was given, use it as the interface
4240 * configuration file (instead of using parent's configuration file.
4241 */
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07004242 if (conf_p2p_dev) {
4243 iface.confname = conf_p2p_dev;
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004244 iface.ctrl_interface = NULL;
4245 } else {
4246 iface.confname = wpa_s->confname;
4247 iface.ctrl_interface = wpa_s->conf->ctrl_interface;
4248 }
Dmitry Shmidt2ac5f602014-03-07 10:08:21 -08004249
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08004250 p2pdev_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004251 if (!p2pdev_wpa_s) {
4252 wpa_printf(MSG_DEBUG, "P2P: Failed to add P2P Device interface");
4253 return -1;
4254 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004255
Dmitry Shmidt9c175262016-03-03 10:20:07 -08004256 p2pdev_wpa_s->p2pdev = p2pdev_wpa_s;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004257 wpa_s->pending_interface_name[0] = '\0';
4258 return 0;
4259}
4260
4261
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004262static void wpas_presence_resp(void *ctx, const u8 *src, u8 status,
4263 const u8 *noa, size_t noa_len)
4264{
4265 struct wpa_supplicant *wpa_s, *intf = ctx;
4266 char hex[100];
4267
4268 for (wpa_s = intf->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
4269 if (wpa_s->waiting_presence_resp)
4270 break;
4271 }
4272 if (!wpa_s) {
4273 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No group interface was waiting for presence response");
4274 return;
4275 }
4276 wpa_s->waiting_presence_resp = 0;
4277
4278 wpa_snprintf_hex(hex, sizeof(hex), noa, noa_len);
4279 wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_PRESENCE_RESPONSE "src=" MACSTR
4280 " status=%u noa=%s", MAC2STR(src), status, hex);
4281}
4282
4283
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004284static int wpas_get_persistent_group(void *ctx, const u8 *addr, const u8 *ssid,
4285 size_t ssid_len, u8 *go_dev_addr,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004286 u8 *ret_ssid, size_t *ret_ssid_len,
4287 u8 *intended_iface_addr)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004288{
4289 struct wpa_supplicant *wpa_s = ctx;
4290 struct wpa_ssid *s;
4291
4292 s = wpas_p2p_get_persistent(wpa_s, addr, ssid, ssid_len);
4293 if (s) {
4294 os_memcpy(ret_ssid, s->ssid, s->ssid_len);
4295 *ret_ssid_len = s->ssid_len;
4296 os_memcpy(go_dev_addr, s->bssid, ETH_ALEN);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004297
4298 if (s->mode != WPAS_MODE_P2P_GO) {
4299 os_memset(intended_iface_addr, 0, ETH_ALEN);
4300 } else if (wpas_p2p_create_iface(wpa_s)) {
4301 if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO))
4302 return 0;
4303
4304 os_memcpy(intended_iface_addr,
4305 wpa_s->pending_interface_addr, ETH_ALEN);
4306 } else {
4307 os_memcpy(intended_iface_addr, wpa_s->own_addr,
4308 ETH_ALEN);
4309 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004310 return 1;
4311 }
4312
4313 return 0;
4314}
4315
4316
4317static int wpas_get_go_info(void *ctx, u8 *intended_addr,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004318 u8 *ssid, size_t *ssid_len, int *group_iface,
4319 unsigned int *freq)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004320{
4321 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004322 struct wpa_supplicant *go;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004323 struct wpa_ssid *s;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004324
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004325 /*
4326 * group_iface will be set to 1 only if a dedicated interface for P2P
4327 * role is required. First, we try to reuse an active GO. However,
4328 * if it is not present, we will try to reactivate an existing
4329 * persistent group and set group_iface to 1, so the caller will know
4330 * that the pending interface should be used.
4331 */
4332 *group_iface = 0;
4333
4334 if (freq)
4335 *freq = 0;
4336
4337 go = wpas_p2p_get_go_group(wpa_s);
4338 if (!go) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004339 s = wpas_p2p_get_persistent_go(wpa_s);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004340 *group_iface = wpas_p2p_create_iface(wpa_s);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004341 if (s)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004342 os_memcpy(intended_addr, s->bssid, ETH_ALEN);
4343 else
4344 return 0;
4345 } else {
4346 s = go->current_ssid;
4347 os_memcpy(intended_addr, go->own_addr, ETH_ALEN);
4348 if (freq)
4349 *freq = go->assoc_freq;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004350 }
4351
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004352 os_memcpy(ssid, s->ssid, s->ssid_len);
4353 *ssid_len = s->ssid_len;
4354
4355 return 1;
4356}
4357
4358
4359static int wpas_remove_stale_groups(void *ctx, const u8 *peer, const u8 *go,
4360 const u8 *ssid, size_t ssid_len)
4361{
4362 struct wpa_supplicant *wpa_s = ctx;
4363 struct wpa_ssid *s;
4364 int save_config = 0;
4365 size_t i;
4366
4367 /* Start with our first choice of Persistent Groups */
4368 while ((s = wpas_p2p_get_persistent(wpa_s, peer, NULL, 0))) {
4369 if (go && ssid && ssid_len &&
4370 s->ssid_len == ssid_len &&
4371 os_memcmp(go, s->bssid, ETH_ALEN) == 0 &&
4372 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4373 break;
4374
4375 /* Remove stale persistent group */
4376 if (s->mode != WPAS_MODE_P2P_GO || s->num_p2p_clients <= 1) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004377 wpa_dbg(wpa_s, MSG_DEBUG,
4378 "P2P: Remove stale persistent group id=%d",
4379 s->id);
4380 wpas_notify_persistent_group_removed(wpa_s, s);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004381 wpa_config_remove_network(wpa_s->conf, s->id);
4382 save_config = 1;
4383 continue;
4384 }
4385
4386 for (i = 0; i < s->num_p2p_clients; i++) {
4387 if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN,
4388 peer, ETH_ALEN) != 0)
4389 continue;
4390
4391 os_memmove(s->p2p_client_list + i * 2 * ETH_ALEN,
4392 s->p2p_client_list + (i + 1) * 2 * ETH_ALEN,
4393 (s->num_p2p_clients - i - 1) * 2 * ETH_ALEN);
4394 break;
4395 }
4396 s->num_p2p_clients--;
4397 save_config = 1;
4398 }
4399
4400 if (save_config)
4401 p2p_config_write(wpa_s);
4402
4403 /* Return TRUE if valid SSID remains */
4404 return s != NULL;
4405}
4406
4407
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004408static void wpas_p2ps_get_feat_cap_str(char *buf, size_t buf_len,
4409 const u8 *feat_cap, size_t feat_cap_len)
4410{
4411 static const char pref[] = " feature_cap=";
4412 int ret;
4413
4414 buf[0] = '\0';
4415
4416 /*
4417 * We expect a feature capability to contain at least one byte to be
4418 * reported. The string buffer provided by the caller function is
4419 * expected to be big enough to contain all bytes of the attribute for
4420 * known specifications. This function truncates the reported bytes if
4421 * the feature capability data exceeds the string buffer size.
4422 */
4423 if (!feat_cap || !feat_cap_len || buf_len < sizeof(pref) + 2)
4424 return;
4425
4426 os_memcpy(buf, pref, sizeof(pref));
4427 ret = wpa_snprintf_hex(&buf[sizeof(pref) - 1],
4428 buf_len - sizeof(pref) + 1,
4429 feat_cap, feat_cap_len);
4430
4431 if (ret != (2 * (int) feat_cap_len))
4432 wpa_printf(MSG_WARNING, "P2PS feature_cap bytes truncated");
4433}
4434
4435
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004436static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
4437 const u8 *adv_mac, const u8 *ses_mac,
4438 const u8 *grp_mac, u32 adv_id, u32 ses_id,
4439 u8 conncap, int passwd_id,
4440 const u8 *persist_ssid,
4441 size_t persist_ssid_size, int response_done,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004442 int prov_start, const char *session_info,
4443 const u8 *feat_cap, size_t feat_cap_len,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004444 unsigned int freq,
4445 const u8 *group_ssid, size_t group_ssid_len)
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004446{
4447 struct wpa_supplicant *wpa_s = ctx;
4448 u8 mac[ETH_ALEN];
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004449 struct wpa_ssid *persistent_go, *stale, *s = NULL;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004450 int save_config = 0;
4451 struct wpa_supplicant *go_wpa_s;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004452 char feat_cap_str[256];
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004453
4454 if (!dev)
4455 return;
4456
4457 os_memset(mac, 0, ETH_ALEN);
4458 if (!adv_mac)
4459 adv_mac = mac;
4460 if (!ses_mac)
4461 ses_mac = mac;
4462 if (!grp_mac)
4463 grp_mac = mac;
4464
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004465 wpas_p2ps_get_feat_cap_str(feat_cap_str, sizeof(feat_cap_str),
4466 feat_cap, feat_cap_len);
4467
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004468 if (prov_start) {
4469 if (session_info == NULL) {
4470 wpa_msg_global(wpa_s, MSG_INFO,
4471 P2P_EVENT_P2PS_PROVISION_START MACSTR
4472 " adv_id=%x conncap=%x"
4473 " adv_mac=" MACSTR
4474 " session=%x mac=" MACSTR
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004475 " dev_passwd_id=%d%s",
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004476 MAC2STR(dev), adv_id, conncap,
4477 MAC2STR(adv_mac),
4478 ses_id, MAC2STR(ses_mac),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004479 passwd_id, feat_cap_str);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004480 } else {
4481 wpa_msg_global(wpa_s, MSG_INFO,
4482 P2P_EVENT_P2PS_PROVISION_START MACSTR
4483 " adv_id=%x conncap=%x"
4484 " adv_mac=" MACSTR
4485 " session=%x mac=" MACSTR
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004486 " dev_passwd_id=%d info='%s'%s",
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004487 MAC2STR(dev), adv_id, conncap,
4488 MAC2STR(adv_mac),
4489 ses_id, MAC2STR(ses_mac),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004490 passwd_id, session_info, feat_cap_str);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004491 }
4492 return;
4493 }
4494
4495 go_wpa_s = wpas_p2p_get_go_group(wpa_s);
4496 persistent_go = wpas_p2p_get_persistent_go(wpa_s);
4497
4498 if (status && status != P2P_SC_SUCCESS_DEFERRED) {
4499 if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
4500 wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
4501
4502 if (persistent_go && !persistent_go->num_p2p_clients) {
4503 /* remove empty persistent GO */
Hai Shalom74f70d42019-02-11 14:42:39 -08004504 wpa_dbg(wpa_s, MSG_DEBUG,
4505 "P2P: Remove empty persistent group id=%d",
4506 persistent_go->id);
4507 wpas_notify_persistent_group_removed(wpa_s,
4508 persistent_go);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004509 wpa_config_remove_network(wpa_s->conf,
4510 persistent_go->id);
4511 }
4512
4513 wpa_msg_global(wpa_s, MSG_INFO,
4514 P2P_EVENT_P2PS_PROVISION_DONE MACSTR
4515 " status=%d"
4516 " adv_id=%x adv_mac=" MACSTR
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004517 " session=%x mac=" MACSTR "%s",
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004518 MAC2STR(dev), status,
4519 adv_id, MAC2STR(adv_mac),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004520 ses_id, MAC2STR(ses_mac), feat_cap_str);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004521 return;
4522 }
4523
4524 /* Clean up stale persistent groups with this device */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004525 if (persist_ssid && persist_ssid_size)
4526 s = wpas_p2p_get_persistent(wpa_s, dev, persist_ssid,
4527 persist_ssid_size);
4528
4529 if (persist_ssid && s && s->mode != WPAS_MODE_P2P_GO &&
4530 is_zero_ether_addr(grp_mac)) {
4531 wpa_dbg(wpa_s, MSG_ERROR,
4532 "P2P: Peer device is a GO in a persistent group, but it did not provide the intended MAC address");
4533 return;
4534 }
4535
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004536 for (;;) {
4537 stale = wpas_p2p_get_persistent(wpa_s, dev, NULL, 0);
4538 if (!stale)
4539 break;
4540
4541 if (s && s->ssid_len == stale->ssid_len &&
4542 os_memcmp(stale->bssid, s->bssid, ETH_ALEN) == 0 &&
4543 os_memcmp(stale->ssid, s->ssid, s->ssid_len) == 0)
4544 break;
4545
4546 /* Remove stale persistent group */
4547 if (stale->mode != WPAS_MODE_P2P_GO ||
4548 stale->num_p2p_clients <= 1) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004549 wpa_dbg(wpa_s, MSG_DEBUG,
4550 "P2P: Remove stale persistent group id=%d",
4551 stale->id);
4552 wpas_notify_persistent_group_removed(wpa_s, stale);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004553 wpa_config_remove_network(wpa_s->conf, stale->id);
4554 } else {
4555 size_t i;
4556
4557 for (i = 0; i < stale->num_p2p_clients; i++) {
4558 if (os_memcmp(stale->p2p_client_list +
4559 i * ETH_ALEN,
4560 dev, ETH_ALEN) == 0) {
4561 os_memmove(stale->p2p_client_list +
4562 i * ETH_ALEN,
4563 stale->p2p_client_list +
4564 (i + 1) * ETH_ALEN,
4565 (stale->num_p2p_clients -
4566 i - 1) * ETH_ALEN);
4567 break;
4568 }
4569 }
4570 stale->num_p2p_clients--;
4571 }
4572 save_config = 1;
4573 }
4574
4575 if (save_config)
4576 p2p_config_write(wpa_s);
4577
4578 if (s) {
4579 if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
4580 wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
4581
4582 if (persistent_go && s != persistent_go &&
4583 !persistent_go->num_p2p_clients) {
4584 /* remove empty persistent GO */
Hai Shalom74f70d42019-02-11 14:42:39 -08004585 wpa_dbg(wpa_s, MSG_DEBUG,
4586 "P2P: Remove empty persistent group id=%d",
4587 persistent_go->id);
4588 wpas_notify_persistent_group_removed(wpa_s,
4589 persistent_go);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004590 wpa_config_remove_network(wpa_s->conf,
4591 persistent_go->id);
4592 /* Save config */
4593 }
4594
4595 wpa_msg_global(wpa_s, MSG_INFO,
4596 P2P_EVENT_P2PS_PROVISION_DONE MACSTR
4597 " status=%d"
4598 " adv_id=%x adv_mac=" MACSTR
4599 " session=%x mac=" MACSTR
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004600 " persist=%d%s",
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004601 MAC2STR(dev), status,
4602 adv_id, MAC2STR(adv_mac),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004603 ses_id, MAC2STR(ses_mac), s->id, feat_cap_str);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004604 return;
4605 }
4606
Hai Shalom5f92bc92019-04-18 11:54:11 -07004607 wpa_s->global->pending_p2ps_group = 0;
4608 wpa_s->global->pending_p2ps_group_freq = 0;
4609
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004610 if (conncap == P2PS_SETUP_GROUP_OWNER) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004611 /*
4612 * We need to copy the interface name. Simply saving a
4613 * pointer isn't enough, since if we use pending_interface_name
4614 * it will be overwritten when the group is added.
4615 */
4616 char go_ifname[100];
4617
4618 go_ifname[0] = '\0';
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004619 if (!go_wpa_s) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07004620 if (!response_done) {
4621 wpa_s->global->pending_p2ps_group = 1;
4622 wpa_s->global->pending_p2ps_group_freq = freq;
4623 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004624
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004625 if (!wpas_p2p_create_iface(wpa_s))
4626 os_memcpy(go_ifname, wpa_s->ifname,
4627 sizeof(go_ifname));
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004628 else if (wpa_s->pending_interface_name[0])
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004629 os_memcpy(go_ifname,
4630 wpa_s->pending_interface_name,
4631 sizeof(go_ifname));
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004632
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004633 if (!go_ifname[0]) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004634 wpas_p2ps_prov_complete(
4635 wpa_s, P2P_SC_FAIL_UNKNOWN_GROUP,
4636 dev, adv_mac, ses_mac,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004637 grp_mac, adv_id, ses_id, 0, 0,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004638 NULL, 0, 0, 0, NULL, NULL, 0, 0,
4639 NULL, 0);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004640 return;
4641 }
4642
4643 /* If PD Resp complete, start up the GO */
4644 if (response_done && persistent_go) {
4645 wpas_p2p_group_add_persistent(
4646 wpa_s, persistent_go,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004647 0, 0, freq, 0, 0, 0, 0, 0, 0, NULL,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004648 persistent_go->mode ==
4649 WPAS_MODE_P2P_GO ?
4650 P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
Matthew Wang124e5f42022-12-29 07:23:06 +00004651 0, 0, false, 0, false);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004652 } else if (response_done) {
Hai Shalom74f70d42019-02-11 14:42:39 -08004653 wpas_p2p_group_add(wpa_s, 1, freq,
Hai Shalomc1a21442022-02-04 13:43:00 -08004654 0, 0, 0, 0, 0, 0, false);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004655 }
4656
4657 if (passwd_id == DEV_PW_P2PS_DEFAULT) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004658 os_memcpy(wpa_s->p2ps_join_addr, grp_mac,
4659 ETH_ALEN);
4660 wpa_s->p2ps_method_config_any = 1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004661 }
4662 } else if (passwd_id == DEV_PW_P2PS_DEFAULT) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004663 os_memcpy(go_ifname, go_wpa_s->ifname,
4664 sizeof(go_ifname));
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004665
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004666 if (is_zero_ether_addr(grp_mac)) {
4667 wpa_dbg(go_wpa_s, MSG_DEBUG,
4668 "P2P: Setting PIN-1 for ANY");
4669 wpa_supplicant_ap_wps_pin(go_wpa_s, NULL,
4670 "12345670", NULL, 0,
4671 0);
4672 } else {
4673 wpa_dbg(go_wpa_s, MSG_DEBUG,
4674 "P2P: Setting PIN-1 for " MACSTR,
4675 MAC2STR(grp_mac));
4676 wpa_supplicant_ap_wps_pin(go_wpa_s, grp_mac,
4677 "12345670", NULL, 0,
4678 0);
4679 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004680
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004681 os_memcpy(wpa_s->p2ps_join_addr, grp_mac, ETH_ALEN);
4682 wpa_s->p2ps_method_config_any = 1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004683 }
4684
4685 wpa_msg_global(wpa_s, MSG_INFO,
4686 P2P_EVENT_P2PS_PROVISION_DONE MACSTR
4687 " status=%d conncap=%x"
4688 " adv_id=%x adv_mac=" MACSTR
4689 " session=%x mac=" MACSTR
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004690 " dev_passwd_id=%d go=%s%s",
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004691 MAC2STR(dev), status, conncap,
4692 adv_id, MAC2STR(adv_mac),
4693 ses_id, MAC2STR(ses_mac),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004694 passwd_id, go_ifname, feat_cap_str);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004695 return;
4696 }
4697
4698 if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
4699 wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
4700
4701 if (persistent_go && !persistent_go->num_p2p_clients) {
4702 /* remove empty persistent GO */
Hai Shalom74f70d42019-02-11 14:42:39 -08004703 wpa_dbg(wpa_s, MSG_DEBUG,
4704 "P2P: Remove empty persistent group id=%d",
4705 persistent_go->id);
4706 wpas_notify_persistent_group_removed(wpa_s, persistent_go);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004707 wpa_config_remove_network(wpa_s->conf, persistent_go->id);
4708 }
4709
4710 if (conncap == P2PS_SETUP_CLIENT) {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004711 char ssid_hex[32 * 2 + 1];
4712
4713 if (group_ssid)
4714 wpa_snprintf_hex(ssid_hex, sizeof(ssid_hex),
4715 group_ssid, group_ssid_len);
4716 else
4717 ssid_hex[0] = '\0';
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004718 wpa_msg_global(wpa_s, MSG_INFO,
4719 P2P_EVENT_P2PS_PROVISION_DONE MACSTR
4720 " status=%d conncap=%x"
4721 " adv_id=%x adv_mac=" MACSTR
4722 " session=%x mac=" MACSTR
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004723 " dev_passwd_id=%d join=" MACSTR "%s%s%s",
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004724 MAC2STR(dev), status, conncap,
4725 adv_id, MAC2STR(adv_mac),
4726 ses_id, MAC2STR(ses_mac),
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004727 passwd_id, MAC2STR(grp_mac), feat_cap_str,
4728 group_ssid ? " group_ssid=" : "", ssid_hex);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004729 } else {
4730 wpa_msg_global(wpa_s, MSG_INFO,
4731 P2P_EVENT_P2PS_PROVISION_DONE MACSTR
4732 " status=%d conncap=%x"
4733 " adv_id=%x adv_mac=" MACSTR
4734 " session=%x mac=" MACSTR
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004735 " dev_passwd_id=%d%s",
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004736 MAC2STR(dev), status, conncap,
4737 adv_id, MAC2STR(adv_mac),
4738 ses_id, MAC2STR(ses_mac),
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004739 passwd_id, feat_cap_str);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004740 }
4741}
4742
4743
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -07004744static int _wpas_p2p_in_progress(void *ctx)
4745{
4746 struct wpa_supplicant *wpa_s = ctx;
4747 return wpas_p2p_in_progress(wpa_s);
4748}
4749
4750
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004751static int wpas_prov_disc_resp_cb(void *ctx)
4752{
4753 struct wpa_supplicant *wpa_s = ctx;
4754 struct wpa_ssid *persistent_go;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004755 unsigned int freq;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004756
4757 if (!wpa_s->global->pending_p2ps_group)
4758 return 0;
4759
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004760 freq = wpa_s->global->pending_p2ps_group_freq;
4761 wpa_s->global->pending_p2ps_group_freq = 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004762 wpa_s->global->pending_p2ps_group = 0;
4763
4764 if (wpas_p2p_get_go_group(wpa_s))
4765 return 0;
4766 persistent_go = wpas_p2p_get_persistent_go(wpa_s);
4767
4768 if (persistent_go) {
4769 wpas_p2p_group_add_persistent(
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004770 wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4771 NULL,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004772 persistent_go->mode == WPAS_MODE_P2P_GO ?
Hai Shalomc1a21442022-02-04 13:43:00 -08004773 P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0,
Matthew Wang124e5f42022-12-29 07:23:06 +00004774 is_p2p_allow_6ghz(wpa_s->global->p2p), 0, false);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004775 } else {
Hai Shalomc1a21442022-02-04 13:43:00 -08004776 wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0, 0, 0,
4777 is_p2p_allow_6ghz(wpa_s->global->p2p));
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004778 }
4779
4780 return 1;
4781}
4782
4783
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004784static int wpas_p2p_get_pref_freq_list(void *ctx, int go,
4785 unsigned int *len,
Sunil8cd6f4d2022-06-28 18:40:46 +00004786 struct weighted_pcl *freq_list)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004787{
4788 struct wpa_supplicant *wpa_s = ctx;
4789
4790 return wpa_drv_get_pref_freq_list(wpa_s, go ? WPA_IF_P2P_GO :
4791 WPA_IF_P2P_CLIENT, len, freq_list);
4792}
4793
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004794int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
4795{
JaeMan Park9de97322022-07-11 15:36:43 +09004796 int ret = 0;
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004797 u8 addr[ETH_ALEN] = {0};
4798
4799 if (wpa_s->conf->p2p_device_random_mac_addr == 0)
4800 return 0;
4801
Hai Shalom60840252021-02-19 19:02:11 -08004802 if (wpa_s->conf->p2p_device_random_mac_addr == 2) {
4803 if (is_zero_ether_addr(
4804 wpa_s->conf->p2p_device_persistent_mac_addr) &&
4805 !is_zero_ether_addr(wpa_s->own_addr)) {
4806 os_memcpy(wpa_s->conf->p2p_device_persistent_mac_addr,
4807 wpa_s->own_addr, ETH_ALEN);
4808 }
4809 return 0;
4810 }
4811
4812 if (!wpa_s->conf->ssid) {
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004813 if (random_mac_addr(addr) < 0) {
4814 wpa_msg(wpa_s, MSG_INFO,
4815 "Failed to generate random MAC address");
4816 return -EINVAL;
4817 }
4818
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004819 /* Store generated MAC address. */
4820 os_memcpy(wpa_s->conf->p2p_device_persistent_mac_addr, addr,
4821 ETH_ALEN);
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004822 } else {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004823 /* If there are existing saved groups, restore last MAC address.
4824 * if there is no last used MAC address, the last one is
4825 * factory MAC. */
4826 if (is_zero_ether_addr(
4827 wpa_s->conf->p2p_device_persistent_mac_addr))
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004828 return 0;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004829 os_memcpy(addr, wpa_s->conf->p2p_device_persistent_mac_addr,
4830 ETH_ALEN);
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004831 wpa_msg(wpa_s, MSG_DEBUG, "Restore last used MAC address.");
4832 }
4833
JaeMan Park9de97322022-07-11 15:36:43 +09004834 ret = wpa_drv_set_mac_addr(wpa_s, addr);
4835
4836 if (ret < 0) {
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004837 wpa_msg(wpa_s, MSG_INFO,
4838 "Failed to set random MAC address");
JaeMan Park9de97322022-07-11 15:36:43 +09004839 return ret;
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004840 }
4841
JaeMan Park9de97322022-07-11 15:36:43 +09004842 ret = wpa_supplicant_update_mac_addr(wpa_s);
4843
4844 if (ret < 0) {
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004845 wpa_msg(wpa_s, MSG_INFO,
4846 "Could not update MAC address information");
JaeMan Park9de97322022-07-11 15:36:43 +09004847 return ret;
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004848 }
4849
4850 wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR,
4851 MAC2STR(addr));
4852
4853 return 0;
4854}
4855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004856/**
4857 * wpas_p2p_init - Initialize P2P module for %wpa_supplicant
4858 * @global: Pointer to global data from wpa_supplicant_init()
4859 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
4860 * Returns: 0 on success, -1 on failure
4861 */
4862int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
4863{
4864 struct p2p_config p2p;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004865 int i;
4866
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004867 if (wpa_s->conf->p2p_disabled)
4868 return 0;
4869
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004870 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE))
4871 return 0;
4872
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004873 if (global->p2p)
4874 return 0;
4875
Jimmy Chenf887c7b2018-11-13 15:19:57 +08004876 if (wpas_p2p_mac_setup(wpa_s) < 0) {
4877 wpa_msg(wpa_s, MSG_ERROR,
4878 "Failed to initialize P2P random MAC address.");
4879 return -1;
4880 }
4881
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004882 os_memset(&p2p, 0, sizeof(p2p));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004883 p2p.cb_ctx = wpa_s;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004884 p2p.debug_print = wpas_p2p_debug_print;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004885 p2p.p2p_scan = wpas_p2p_scan;
4886 p2p.send_action = wpas_send_action;
4887 p2p.send_action_done = wpas_send_action_done;
4888 p2p.go_neg_completed = wpas_go_neg_completed;
4889 p2p.go_neg_req_rx = wpas_go_neg_req_rx;
4890 p2p.dev_found = wpas_dev_found;
4891 p2p.dev_lost = wpas_dev_lost;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004892 p2p.find_stopped = wpas_find_stopped;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004893 p2p.start_listen = wpas_start_listen;
4894 p2p.stop_listen = wpas_stop_listen;
4895 p2p.send_probe_resp = wpas_send_probe_resp;
4896 p2p.sd_request = wpas_sd_request;
4897 p2p.sd_response = wpas_sd_response;
4898 p2p.prov_disc_req = wpas_prov_disc_req;
4899 p2p.prov_disc_resp = wpas_prov_disc_resp;
Jouni Malinen75ecf522011-06-27 15:19:46 -07004900 p2p.prov_disc_fail = wpas_prov_disc_fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004901 p2p.invitation_process = wpas_invitation_process;
4902 p2p.invitation_received = wpas_invitation_received;
4903 p2p.invitation_result = wpas_invitation_result;
4904 p2p.get_noa = wpas_get_noa;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004905 p2p.go_connected = wpas_go_connected;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004906 p2p.presence_resp = wpas_presence_resp;
Dmitry Shmidt18463232014-01-24 12:29:41 -08004907 p2p.is_concurrent_session_active = wpas_is_concurrent_session_active;
Dmitry Shmidt5a1480c2014-05-12 09:46:02 -07004908 p2p.is_p2p_in_progress = _wpas_p2p_in_progress;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004909 p2p.get_persistent_group = wpas_get_persistent_group;
4910 p2p.get_go_info = wpas_get_go_info;
4911 p2p.remove_stale_groups = wpas_remove_stale_groups;
4912 p2p.p2ps_prov_complete = wpas_p2ps_prov_complete;
4913 p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb;
4914 p2p.p2ps_group_capability = p2ps_group_capability;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004915 p2p.get_pref_freq_list = wpas_p2p_get_pref_freq_list;
Hai Shalom60840252021-02-19 19:02:11 -08004916 p2p.p2p_6ghz_disable = wpa_s->conf->p2p_6ghz_disable;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004917
4918 os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004919 os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004920 p2p.dev_name = wpa_s->conf->device_name;
4921 p2p.manufacturer = wpa_s->conf->manufacturer;
4922 p2p.model_name = wpa_s->conf->model_name;
4923 p2p.model_number = wpa_s->conf->model_number;
4924 p2p.serial_number = wpa_s->conf->serial_number;
4925 if (wpa_s->wps) {
4926 os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16);
4927 p2p.config_methods = wpa_s->wps->config_methods;
4928 }
4929
Hai Shalom60840252021-02-19 19:02:11 -08004930 if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels,
4931 p2p.p2p_6ghz_disable)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004932 wpa_printf(MSG_ERROR,
4933 "P2P: Failed to configure supported channel list");
4934 return -1;
4935 }
4936
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004937 if (wpa_s->conf->p2p_listen_reg_class &&
4938 wpa_s->conf->p2p_listen_channel) {
4939 p2p.reg_class = wpa_s->conf->p2p_listen_reg_class;
4940 p2p.channel = wpa_s->conf->p2p_listen_channel;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004941 p2p.channel_forced = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004942 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004943 /*
4944 * Pick one of the social channels randomly as the listen
4945 * channel.
4946 */
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004947 if (p2p_config_get_random_social(&p2p, &p2p.reg_class,
Hai Shalom74f70d42019-02-11 14:42:39 -08004948 &p2p.channel,
4949 &global->p2p_go_avoid_freq,
4950 &global->p2p_disallow_freq) !=
4951 0) {
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07004952 wpa_printf(MSG_INFO,
4953 "P2P: No social channels supported by the driver - do not enable P2P");
4954 return 0;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004955 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07004956 p2p.channel_forced = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004957 }
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004958 wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d:%d",
4959 p2p.reg_class, p2p.channel);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004960
4961 if (wpa_s->conf->p2p_oper_reg_class &&
4962 wpa_s->conf->p2p_oper_channel) {
4963 p2p.op_reg_class = wpa_s->conf->p2p_oper_reg_class;
4964 p2p.op_channel = wpa_s->conf->p2p_oper_channel;
4965 p2p.cfg_op_channel = 1;
4966 wpa_printf(MSG_DEBUG, "P2P: Configured operating channel: "
4967 "%d:%d", p2p.op_reg_class, p2p.op_channel);
4968
4969 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004970 /*
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004971 * Use random operation channel from 2.4 GHz band social
4972 * channels (1, 6, 11) or band 60 GHz social channel (2) if no
4973 * other preference is indicated.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004974 */
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004975 if (p2p_config_get_random_social(&p2p, &p2p.op_reg_class,
Hai Shalom74f70d42019-02-11 14:42:39 -08004976 &p2p.op_channel, NULL,
4977 NULL) != 0) {
4978 wpa_printf(MSG_INFO,
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004979 "P2P: Failed to select random social channel as operation channel");
Hai Shalom74f70d42019-02-11 14:42:39 -08004980 p2p.op_reg_class = 0;
4981 p2p.op_channel = 0;
4982 /* This will be overridden during group setup in
4983 * p2p_prepare_channel(), so allow setup to continue. */
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07004984 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004985 p2p.cfg_op_channel = 0;
4986 wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "
4987 "%d:%d", p2p.op_reg_class, p2p.op_channel);
4988 }
Dmitry Shmidt44c95782013-05-17 09:51:35 -07004989
4990 if (wpa_s->conf->p2p_pref_chan && wpa_s->conf->num_p2p_pref_chan) {
4991 p2p.pref_chan = wpa_s->conf->p2p_pref_chan;
4992 p2p.num_pref_chan = wpa_s->conf->num_p2p_pref_chan;
4993 }
4994
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004995 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4996 os_memcpy(p2p.country, wpa_s->conf->country, 2);
4997 p2p.country[2] = 0x04;
4998 } else
4999 os_memcpy(p2p.country, "XX\x04", 3);
5000
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005001 os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type,
5002 WPS_DEV_TYPE_LEN);
5003
5004 p2p.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
5005 os_memcpy(p2p.sec_dev_type, wpa_s->conf->sec_device_type,
5006 p2p.num_sec_dev_types * WPS_DEV_TYPE_LEN);
5007
5008 p2p.concurrent_operations = !!(wpa_s->drv_flags &
5009 WPA_DRIVER_FLAGS_P2P_CONCURRENT);
5010
5011 p2p.max_peers = 100;
5012
5013 if (wpa_s->conf->p2p_ssid_postfix) {
5014 p2p.ssid_postfix_len =
5015 os_strlen(wpa_s->conf->p2p_ssid_postfix);
5016 if (p2p.ssid_postfix_len > sizeof(p2p.ssid_postfix))
5017 p2p.ssid_postfix_len = sizeof(p2p.ssid_postfix);
5018 os_memcpy(p2p.ssid_postfix, wpa_s->conf->p2p_ssid_postfix,
5019 p2p.ssid_postfix_len);
5020 }
5021
5022 p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
5023
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005024 p2p.max_listen = wpa_s->max_remain_on_chan;
5025
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07005026 if (wpa_s->conf->p2p_passphrase_len >= 8 &&
5027 wpa_s->conf->p2p_passphrase_len <= 63)
5028 p2p.passphrase_len = wpa_s->conf->p2p_passphrase_len;
5029 else
5030 p2p.passphrase_len = 8;
5031
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005032 global->p2p = p2p_init(&p2p);
5033 if (global->p2p == NULL)
5034 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005035 global->p2p_init_wpa_s = wpa_s;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005036
5037 for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {
5038 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
5039 continue;
5040 p2p_add_wps_vendor_extension(
5041 global->p2p, wpa_s->conf->wps_vendor_ext[i]);
5042 }
5043
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005044 p2p_set_no_go_freq(global->p2p, &wpa_s->conf->p2p_no_go_freq);
5045
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005046 return 0;
5047}
5048
5049
5050/**
5051 * wpas_p2p_deinit - Deinitialize per-interface P2P data
5052 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
5053 *
5054 * This function deinitialize per-interface P2P data.
5055 */
5056void wpas_p2p_deinit(struct wpa_supplicant *wpa_s)
5057{
5058 if (wpa_s->driver && wpa_s->drv_priv)
5059 wpa_drv_probe_req_report(wpa_s, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005060
5061 if (wpa_s->go_params) {
5062 /* Clear any stored provisioning info */
5063 p2p_clear_provisioning_info(
5064 wpa_s->global->p2p,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005065 wpa_s->go_params->peer_device_addr);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005066 }
5067
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005068 os_free(wpa_s->go_params);
5069 wpa_s->go_params = NULL;
Dmitry Shmidt684785c2014-05-12 13:34:29 -07005070 eloop_cancel_timeout(wpas_p2p_psk_failure_removal, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005071 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
5072 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07005073 wpa_s->global->p2p_long_listen = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005074 eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
5075 eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
5076 wpas_p2p_remove_pending_group_interface(wpa_s);
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08005077 eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -07005078 eloop_cancel_timeout(wpas_p2p_reconsider_moving_go, wpa_s, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005079 wpas_p2p_listen_work_done(wpa_s);
5080 if (wpa_s->p2p_send_action_work) {
5081 os_free(wpa_s->p2p_send_action_work->ctx);
5082 radio_work_done(wpa_s->p2p_send_action_work);
5083 wpa_s->p2p_send_action_work = NULL;
5084 }
5085 eloop_cancel_timeout(wpas_p2p_send_action_work_timeout, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005086
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005087 wpabuf_free(wpa_s->p2p_oob_dev_pw);
5088 wpa_s->p2p_oob_dev_pw = NULL;
5089
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005090 os_free(wpa_s->p2p_group_common_freqs);
5091 wpa_s->p2p_group_common_freqs = NULL;
5092 wpa_s->p2p_group_common_freqs_num = 0;
5093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005094 /* TODO: remove group interface from the driver if this wpa_s instance
5095 * is on top of a P2P group interface */
5096}
5097
5098
5099/**
5100 * wpas_p2p_deinit_global - Deinitialize global P2P module
5101 * @global: Pointer to global data from wpa_supplicant_init()
5102 *
5103 * This function deinitializes the global (per device) P2P module.
5104 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005105static void wpas_p2p_deinit_global(struct wpa_global *global)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005106{
5107 struct wpa_supplicant *wpa_s, *tmp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005108
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005109 wpa_s = global->ifaces;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005110
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005111 wpas_p2p_service_flush(global->p2p_init_wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005112
5113 /* Remove remaining P2P group interfaces */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005114 while (wpa_s && wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
5115 wpa_s = wpa_s->next;
5116 while (wpa_s) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005117 tmp = global->ifaces;
5118 while (tmp &&
5119 (tmp == wpa_s ||
5120 tmp->p2p_group_interface == NOT_P2P_GROUP_INTERFACE)) {
5121 tmp = tmp->next;
5122 }
5123 if (tmp == NULL)
5124 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005125 /* Disconnect from the P2P group and deinit the interface */
5126 wpas_p2p_disconnect(tmp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005127 }
5128
5129 /*
5130 * Deinit GO data on any possibly remaining interface (if main
5131 * interface is used as GO).
5132 */
5133 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
5134 if (wpa_s->ap_iface)
5135 wpas_p2p_group_deinit(wpa_s);
5136 }
5137
5138 p2p_deinit(global->p2p);
5139 global->p2p = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005140 global->p2p_init_wpa_s = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005141}
5142
5143
5144static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s)
5145{
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005146 if (wpa_s->conf->p2p_no_group_iface)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005147 return 0; /* separate interface disabled per configuration */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005148 if (wpa_s->drv_flags &
5149 (WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE |
5150 WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P))
5151 return 1; /* P2P group requires a new interface in every case
5152 */
5153 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CONCURRENT))
5154 return 0; /* driver does not support concurrent operations */
5155 if (wpa_s->global->ifaces->next)
5156 return 1; /* more that one interface already in use */
5157 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
5158 return 1; /* this interface is already in use */
5159 return 0;
5160}
5161
5162
5163static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s,
5164 const u8 *peer_addr,
5165 enum p2p_wps_method wps_method,
5166 int go_intent, const u8 *own_interface_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005167 unsigned int force_freq, int persistent_group,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005168 struct wpa_ssid *ssid, unsigned int pref_freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005169{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005170 if (persistent_group && wpa_s->conf->persistent_reconnect)
5171 persistent_group = 2;
5172
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005173 /*
5174 * Increase GO config timeout if HT40 is used since it takes some time
5175 * to scan channels for coex purposes before the BSS can be started.
5176 */
5177 p2p_set_config_timeout(wpa_s->global->p2p,
5178 wpa_s->p2p_go_ht40 ? 255 : 100, 20);
5179
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005180 return p2p_connect(wpa_s->global->p2p, peer_addr, wps_method,
5181 go_intent, own_interface_addr, force_freq,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005182 persistent_group, ssid ? ssid->ssid : NULL,
5183 ssid ? ssid->ssid_len : 0,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005184 wpa_s->p2p_pd_before_go_neg, pref_freq,
5185 wps_method == WPS_NFC ? wpa_s->p2p_oob_dev_pw_id :
5186 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005187}
5188
5189
5190static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s,
5191 const u8 *peer_addr,
5192 enum p2p_wps_method wps_method,
5193 int go_intent, const u8 *own_interface_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005194 unsigned int force_freq, int persistent_group,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005195 struct wpa_ssid *ssid, unsigned int pref_freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005196{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005197 if (persistent_group && wpa_s->conf->persistent_reconnect)
5198 persistent_group = 2;
5199
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005200 return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method,
5201 go_intent, own_interface_addr, force_freq,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005202 persistent_group, ssid ? ssid->ssid : NULL,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005203 ssid ? ssid->ssid_len : 0, pref_freq,
5204 wps_method == WPS_NFC ? wpa_s->p2p_oob_dev_pw_id :
5205 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005206}
5207
5208
5209static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s)
5210{
5211 wpa_s->p2p_join_scan_count++;
5212 wpa_printf(MSG_DEBUG, "P2P: Join scan attempt %d",
5213 wpa_s->p2p_join_scan_count);
5214 if (wpa_s->p2p_join_scan_count > P2P_MAX_JOIN_SCAN_ATTEMPTS) {
5215 wpa_printf(MSG_DEBUG, "P2P: Failed to find GO " MACSTR
5216 " for join operationg - stop join attempt",
5217 MAC2STR(wpa_s->pending_join_iface_addr));
5218 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005219 if (wpa_s->p2p_auto_pd) {
5220 wpa_s->p2p_auto_pd = 0;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005221 wpa_msg_global(wpa_s, MSG_INFO,
5222 P2P_EVENT_PROV_DISC_FAILURE
5223 " p2p_dev_addr=" MACSTR " status=N/A",
5224 MAC2STR(wpa_s->pending_join_dev_addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -07005225 return;
5226 }
Jimmy Chenb7b3f4d2020-09-02 16:50:11 +08005227 if (wpa_s->p2p_fallback_to_go_neg) {
5228 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Join operating "
5229 "failed - fall back to GO Negotiation");
5230 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
5231 P2P_EVENT_FALLBACK_TO_GO_NEG
5232 "reason=join-failed");
5233 wpas_p2p_fallback_to_go_neg(wpa_s, 0);
5234 return;
5235 }
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005236 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005237 P2P_EVENT_GROUP_FORMATION_FAILURE);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005238 wpas_notify_p2p_group_formation_failure(wpa_s, "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005239 }
5240}
5241
5242
Dmitry Shmidt04949592012-07-19 12:16:46 -07005243static int wpas_check_freq_conflict(struct wpa_supplicant *wpa_s, int freq)
5244{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005245 int res;
5246 unsigned int num, i;
5247 struct wpa_used_freq_data *freqs;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005248
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005249 if (wpas_p2p_num_unused_channels(wpa_s) > 0) {
5250 /* Multiple channels are supported and not all are in use */
Dmitry Shmidt04949592012-07-19 12:16:46 -07005251 return 0;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005252 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005253
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005254 freqs = os_calloc(wpa_s->num_multichan_concurrent,
5255 sizeof(struct wpa_used_freq_data));
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005256 if (!freqs)
5257 return 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005258
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005259 num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
5260 wpa_s->num_multichan_concurrent);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005261
5262 for (i = 0; i < num; i++) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005263 if (freqs[i].freq == freq) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005264 wpa_printf(MSG_DEBUG, "P2P: Frequency %d MHz in use by another virtual interface and can be used",
5265 freq);
5266 res = 0;
5267 goto exit_free;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005268 }
5269 }
5270
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005271 wpa_printf(MSG_DEBUG, "P2P: No valid operating frequencies");
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005272 res = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005273
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005274exit_free:
5275 os_free(freqs);
5276 return res;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005277}
5278
5279
5280static int wpas_p2p_peer_go(struct wpa_supplicant *wpa_s,
5281 const u8 *peer_dev_addr)
5282{
5283 struct wpa_bss *bss;
5284 int updated;
5285
5286 bss = wpa_bss_get_p2p_dev_addr(wpa_s, peer_dev_addr);
5287 if (bss == NULL)
5288 return -1;
5289 if (bss->last_update_idx < wpa_s->bss_update_idx) {
5290 wpa_printf(MSG_DEBUG, "P2P: Peer BSS entry not updated in the "
5291 "last scan");
5292 return 0;
5293 }
5294
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005295 updated = os_reltime_before(&wpa_s->p2p_auto_started,
5296 &bss->last_update);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005297 wpa_printf(MSG_DEBUG, "P2P: Current BSS entry for peer updated at "
5298 "%ld.%06ld (%supdated in last scan)",
5299 bss->last_update.sec, bss->last_update.usec,
5300 updated ? "": "not ");
5301
5302 return updated;
5303}
5304
5305
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005306static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
5307 struct wpa_scan_results *scan_res)
5308{
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005309 struct wpa_bss *bss = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005310 int freq;
5311 u8 iface_addr[ETH_ALEN];
Dmitry Shmidt04949592012-07-19 12:16:46 -07005312
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005313 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
5314
5315 if (wpa_s->global->p2p_disabled)
5316 return;
5317
Dmitry Shmidt04949592012-07-19 12:16:46 -07005318 wpa_printf(MSG_DEBUG, "P2P: Scan results received (%d BSS) for %sjoin",
5319 scan_res ? (int) scan_res->num : -1,
5320 wpa_s->p2p_auto_join ? "auto_" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005321
5322 if (scan_res)
5323 wpas_p2p_scan_res_handler(wpa_s, scan_res);
5324
Dmitry Shmidt04949592012-07-19 12:16:46 -07005325 if (wpa_s->p2p_auto_pd) {
5326 int join = wpas_p2p_peer_go(wpa_s,
5327 wpa_s->pending_join_dev_addr);
5328 if (join == 0 &&
5329 wpa_s->auto_pd_scan_retry < P2P_AUTO_PD_SCAN_ATTEMPTS) {
5330 wpa_s->auto_pd_scan_retry++;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005331 bss = wpa_bss_get_bssid_latest(
5332 wpa_s, wpa_s->pending_join_dev_addr);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005333 if (bss) {
5334 freq = bss->freq;
5335 wpa_printf(MSG_DEBUG, "P2P: Scan retry %d for "
5336 "the peer " MACSTR " at %d MHz",
5337 wpa_s->auto_pd_scan_retry,
5338 MAC2STR(wpa_s->
5339 pending_join_dev_addr),
5340 freq);
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005341 wpas_p2p_join_scan_req(wpa_s, freq, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005342 return;
5343 }
5344 }
5345
5346 if (join < 0)
5347 join = 0;
5348
5349 wpa_s->p2p_auto_pd = 0;
5350 wpa_s->pending_pd_use = join ? AUTO_PD_JOIN : AUTO_PD_GO_NEG;
5351 wpa_printf(MSG_DEBUG, "P2P: Auto PD with " MACSTR " join=%d",
5352 MAC2STR(wpa_s->pending_join_dev_addr), join);
5353 if (p2p_prov_disc_req(wpa_s->global->p2p,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005354 wpa_s->pending_join_dev_addr, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005355 wpa_s->pending_pd_config_methods, join,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005356 0, wpa_s->user_initiated_pd) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07005357 wpa_s->p2p_auto_pd = 0;
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005358 wpa_msg_global(wpa_s, MSG_INFO,
5359 P2P_EVENT_PROV_DISC_FAILURE
5360 " p2p_dev_addr=" MACSTR " status=N/A",
5361 MAC2STR(wpa_s->pending_join_dev_addr));
Dmitry Shmidt04949592012-07-19 12:16:46 -07005362 }
5363 return;
5364 }
5365
5366 if (wpa_s->p2p_auto_join) {
5367 int join = wpas_p2p_peer_go(wpa_s,
5368 wpa_s->pending_join_dev_addr);
5369 if (join < 0) {
5370 wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
5371 "running a GO -> use GO Negotiation");
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005372 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005373 P2P_EVENT_FALLBACK_TO_GO_NEG
5374 "reason=peer-not-running-GO");
Dmitry Shmidt04949592012-07-19 12:16:46 -07005375 wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
5376 wpa_s->p2p_pin, wpa_s->p2p_wps_method,
5377 wpa_s->p2p_persistent_group, 0, 0, 0,
5378 wpa_s->p2p_go_intent,
5379 wpa_s->p2p_connect_freq,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005380 wpa_s->p2p_go_vht_center_freq2,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005381 wpa_s->p2p_persistent_id,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005382 wpa_s->p2p_pd_before_go_neg,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005383 wpa_s->p2p_go_ht40,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005384 wpa_s->p2p_go_vht,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08005385 wpa_s->p2p_go_max_oper_chwidth,
Hai Shalom74f70d42019-02-11 14:42:39 -08005386 wpa_s->p2p_go_he,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08005387 wpa_s->p2p_go_edmg,
Hai Shalomc1a21442022-02-04 13:43:00 -08005388 NULL, 0,
5389 is_p2p_allow_6ghz(wpa_s->global->p2p));
Dmitry Shmidt04949592012-07-19 12:16:46 -07005390 return;
5391 }
5392
5393 wpa_printf(MSG_DEBUG, "P2P: Peer was found running GO%s -> "
5394 "try to join the group", join ? "" :
5395 " in older scan");
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005396 if (!join) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005397 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005398 P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005399 wpa_s->p2p_fallback_to_go_neg = 1;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08005400 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005401 }
5402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005403 freq = p2p_get_oper_freq(wpa_s->global->p2p,
5404 wpa_s->pending_join_iface_addr);
5405 if (freq < 0 &&
5406 p2p_get_interface_addr(wpa_s->global->p2p,
5407 wpa_s->pending_join_dev_addr,
5408 iface_addr) == 0 &&
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07005409 os_memcmp(iface_addr, wpa_s->pending_join_dev_addr, ETH_ALEN) != 0
5410 && !wpa_bss_get_bssid(wpa_s, wpa_s->pending_join_iface_addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005411 wpa_printf(MSG_DEBUG, "P2P: Overwrite pending interface "
5412 "address for join from " MACSTR " to " MACSTR
5413 " based on newly discovered P2P peer entry",
5414 MAC2STR(wpa_s->pending_join_iface_addr),
5415 MAC2STR(iface_addr));
5416 os_memcpy(wpa_s->pending_join_iface_addr, iface_addr,
5417 ETH_ALEN);
5418
5419 freq = p2p_get_oper_freq(wpa_s->global->p2p,
5420 wpa_s->pending_join_iface_addr);
5421 }
5422 if (freq >= 0) {
5423 wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
5424 "from P2P peer table: %d MHz", freq);
5425 }
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005426 if (wpa_s->p2p_join_ssid_len) {
5427 wpa_printf(MSG_DEBUG, "P2P: Trying to find target GO BSS entry based on BSSID "
5428 MACSTR " and SSID %s",
5429 MAC2STR(wpa_s->pending_join_iface_addr),
5430 wpa_ssid_txt(wpa_s->p2p_join_ssid,
5431 wpa_s->p2p_join_ssid_len));
5432 bss = wpa_bss_get(wpa_s, wpa_s->pending_join_iface_addr,
5433 wpa_s->p2p_join_ssid,
5434 wpa_s->p2p_join_ssid_len);
Dmitry Shmidtde47be72016-01-07 12:52:55 -08005435 } else if (!bss) {
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005436 wpa_printf(MSG_DEBUG, "P2P: Trying to find target GO BSS entry based on BSSID "
5437 MACSTR, MAC2STR(wpa_s->pending_join_iface_addr));
5438 bss = wpa_bss_get_bssid_latest(wpa_s,
5439 wpa_s->pending_join_iface_addr);
5440 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005441 if (bss) {
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005442 u8 dev_addr[ETH_ALEN];
5443
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005444 freq = bss->freq;
5445 wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency "
Dmitry Shmidt051af732013-10-22 13:52:46 -07005446 "from BSS table: %d MHz (SSID %s)", freq,
5447 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Hai Shalom60840252021-02-19 19:02:11 -08005448 if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len,
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07005449 dev_addr) == 0 &&
5450 os_memcmp(wpa_s->pending_join_dev_addr,
5451 wpa_s->pending_join_iface_addr, ETH_ALEN) == 0 &&
5452 os_memcmp(dev_addr, wpa_s->pending_join_dev_addr,
5453 ETH_ALEN) != 0) {
5454 wpa_printf(MSG_DEBUG,
5455 "P2P: Update target GO device address based on BSS entry: " MACSTR " (was " MACSTR ")",
5456 MAC2STR(dev_addr),
5457 MAC2STR(wpa_s->pending_join_dev_addr));
5458 os_memcpy(wpa_s->pending_join_dev_addr, dev_addr,
5459 ETH_ALEN);
5460 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005461 }
5462 if (freq > 0) {
5463 u16 method;
5464
Dmitry Shmidt04949592012-07-19 12:16:46 -07005465 if (wpas_check_freq_conflict(wpa_s, freq) > 0) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005466 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07005467 P2P_EVENT_GROUP_FORMATION_FAILURE
5468 "reason=FREQ_CONFLICT");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005469 wpas_notify_p2p_group_formation_failure(
5470 wpa_s, "FREQ_CONFLICT");
Dmitry Shmidt04949592012-07-19 12:16:46 -07005471 return;
5472 }
5473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005474 wpa_printf(MSG_DEBUG, "P2P: Send Provision Discovery Request "
5475 "prior to joining an existing group (GO " MACSTR
5476 " freq=%u MHz)",
5477 MAC2STR(wpa_s->pending_join_dev_addr), freq);
5478 wpa_s->pending_pd_before_join = 1;
5479
5480 switch (wpa_s->pending_join_wps_method) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005481 case WPS_PIN_DISPLAY:
5482 method = WPS_CONFIG_KEYPAD;
5483 break;
5484 case WPS_PIN_KEYPAD:
5485 method = WPS_CONFIG_DISPLAY;
5486 break;
5487 case WPS_PBC:
5488 method = WPS_CONFIG_PUSHBUTTON;
5489 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005490 case WPS_P2PS:
5491 method = WPS_CONFIG_P2PS;
5492 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005493 default:
5494 method = 0;
5495 break;
5496 }
5497
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005498 if ((p2p_get_provisioning_info(wpa_s->global->p2p,
5499 wpa_s->pending_join_dev_addr) ==
5500 method)) {
5501 /*
5502 * We have already performed provision discovery for
5503 * joining the group. Proceed directly to join
5504 * operation without duplicated provision discovery. */
5505 wpa_printf(MSG_DEBUG, "P2P: Provision discovery "
5506 "with " MACSTR " already done - proceed to "
5507 "join",
5508 MAC2STR(wpa_s->pending_join_dev_addr));
5509 wpa_s->pending_pd_before_join = 0;
5510 goto start;
5511 }
5512
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005513 if (p2p_prov_disc_req(wpa_s->global->p2p,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08005514 wpa_s->pending_join_dev_addr,
5515 NULL, method, 1,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08005516 freq, wpa_s->user_initiated_pd) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005517 wpa_printf(MSG_DEBUG, "P2P: Failed to send Provision "
5518 "Discovery Request before joining an "
5519 "existing group");
5520 wpa_s->pending_pd_before_join = 0;
5521 goto start;
5522 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005523 return;
5524 }
5525
5526 wpa_printf(MSG_DEBUG, "P2P: Failed to find BSS/GO - try again later");
5527 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
5528 eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL);
5529 wpas_p2p_check_join_scan_limit(wpa_s);
5530 return;
5531
5532start:
5533 /* Start join operation immediately */
Dmitry Shmidtde47be72016-01-07 12:52:55 -08005534 wpas_p2p_join_start(wpa_s, 0, wpa_s->p2p_join_ssid,
5535 wpa_s->p2p_join_ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005536}
5537
5538
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005539static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
5540 const u8 *ssid, size_t ssid_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005541{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005542 int ret;
5543 struct wpa_driver_scan_params params;
5544 struct wpabuf *wps_ie, *ies;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005545 size_t ielen;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005546 int freqs[2] = { 0, 0 };
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005547 unsigned int bands;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005548
5549 os_memset(&params, 0, sizeof(params));
5550
5551 /* P2P Wildcard SSID */
5552 params.num_ssids = 1;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005553 if (ssid && ssid_len) {
5554 params.ssids[0].ssid = ssid;
5555 params.ssids[0].ssid_len = ssid_len;
5556 os_memcpy(wpa_s->p2p_join_ssid, ssid, ssid_len);
5557 wpa_s->p2p_join_ssid_len = ssid_len;
5558 } else {
5559 params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID;
5560 params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN;
5561 wpa_s->p2p_join_ssid_len = 0;
5562 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005563
5564 wpa_s->wps->dev.p2p = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005565 wps_ie = wps_build_probe_req_ie(DEV_PW_DEFAULT, &wpa_s->wps->dev,
5566 wpa_s->wps->uuid, WPS_REQ_ENROLLEE, 0,
5567 NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005568 if (wps_ie == NULL) {
5569 wpas_p2p_scan_res_join(wpa_s, NULL);
5570 return;
5571 }
5572
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08005573 if (!freq) {
5574 int oper_freq;
5575 /*
5576 * If freq is not provided, check the operating freq of the GO
5577 * and use a single channel scan on if possible.
5578 */
5579 oper_freq = p2p_get_oper_freq(wpa_s->global->p2p,
5580 wpa_s->pending_join_iface_addr);
5581 if (oper_freq > 0)
5582 freq = oper_freq;
5583 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005584 if (freq > 0) {
5585 freqs[0] = freq;
5586 params.freqs = freqs;
Sunil Ravi77d572f2023-01-17 23:58:31 +00005587 } else {
5588 wpas_p2p_scan_freqs(wpa_s, &params, true);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005589 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005590
Dmitry Shmidt9c175262016-03-03 10:20:07 -08005591 ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
5592 ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
5593 if (ies == NULL) {
5594 wpabuf_free(wps_ie);
5595 wpas_p2p_scan_res_join(wpa_s, NULL);
5596 return;
5597 }
5598 wpabuf_put_buf(ies, wps_ie);
5599 wpabuf_free(wps_ie);
5600
5601 bands = wpas_get_bands(wpa_s, freqs);
5602 p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
5603
5604 params.p2p_probe = 1;
5605 params.extra_ies = wpabuf_head(ies);
5606 params.extra_ies_len = wpabuf_len(ies);
5607
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005608 if (wpa_s->clear_driver_scan_cache) {
5609 wpa_printf(MSG_DEBUG,
5610 "Request driver to clear scan cache due to local BSS flush");
5611 params.only_new_results = 1;
5612 }
5613
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005614 /*
5615 * Run a scan to update BSS table and start Provision Discovery once
5616 * the new scan results become available.
5617 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005618 ret = wpa_drv_scan(wpa_s, &params);
Hai Shalomc1a21442022-02-04 13:43:00 -08005619 if (params.freqs != freqs)
Hai Shalom899fcc72020-10-19 14:38:18 -07005620 os_free(params.freqs);
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005621 if (!ret) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005622 os_get_reltime(&wpa_s->scan_trigger_time);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005623 wpa_s->scan_res_handler = wpas_p2p_scan_res_join;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005624 wpa_s->own_scan_requested = 1;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005625 wpa_s->clear_driver_scan_cache = 0;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07005626 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005627
5628 wpabuf_free(ies);
5629
5630 if (ret) {
5631 wpa_printf(MSG_DEBUG, "P2P: Failed to start scan for join - "
5632 "try again later");
5633 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
5634 eloop_register_timeout(1, 0, wpas_p2p_join_scan, wpa_s, NULL);
5635 wpas_p2p_check_join_scan_limit(wpa_s);
5636 }
5637}
5638
5639
Dmitry Shmidt04949592012-07-19 12:16:46 -07005640static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx)
5641{
5642 struct wpa_supplicant *wpa_s = eloop_ctx;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005643 wpas_p2p_join_scan_req(wpa_s, 0, NULL, 0);
Dmitry Shmidt04949592012-07-19 12:16:46 -07005644}
5645
5646
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005647static int wpas_p2p_join(struct wpa_supplicant *wpa_s, const u8 *iface_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005648 const u8 *dev_addr, enum p2p_wps_method wps_method,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005649 int auto_join, int op_freq,
5650 const u8 *ssid, size_t ssid_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005651{
5652 wpa_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005653 MACSTR " dev " MACSTR " op_freq=%d)%s",
5654 MAC2STR(iface_addr), MAC2STR(dev_addr), op_freq,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005655 auto_join ? " (auto_join)" : "");
Dmitry Shmidt344abd32014-01-14 13:17:00 -08005656 if (ssid && ssid_len) {
5657 wpa_printf(MSG_DEBUG, "P2P: Group SSID specified: %s",
5658 wpa_ssid_txt(ssid, ssid_len));
5659 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005660
Dmitry Shmidt04949592012-07-19 12:16:46 -07005661 wpa_s->p2p_auto_pd = 0;
5662 wpa_s->p2p_auto_join = !!auto_join;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005663 os_memcpy(wpa_s->pending_join_iface_addr, iface_addr, ETH_ALEN);
5664 os_memcpy(wpa_s->pending_join_dev_addr, dev_addr, ETH_ALEN);
5665 wpa_s->pending_join_wps_method = wps_method;
5666
5667 /* Make sure we are not running find during connection establishment */
5668 wpas_p2p_stop_find(wpa_s);
5669
5670 wpa_s->p2p_join_scan_count = 0;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005671 wpas_p2p_join_scan_req(wpa_s, op_freq, ssid, ssid_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005672 return 0;
5673}
5674
5675
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005676static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
5677 const u8 *ssid, size_t ssid_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005678{
5679 struct wpa_supplicant *group;
5680 struct p2p_go_neg_results res;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005681 struct wpa_bss *bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005682
5683 group = wpas_p2p_get_group_iface(wpa_s, 0, 0);
5684 if (group == NULL)
5685 return -1;
5686 if (group != wpa_s) {
5687 os_memcpy(group->p2p_pin, wpa_s->p2p_pin,
5688 sizeof(group->p2p_pin));
5689 group->p2p_wps_method = wpa_s->p2p_wps_method;
5690 }
5691
Hai Shalom74f70d42019-02-11 14:42:39 -08005692 /*
5693 * Need to mark the current interface for p2p_group_formation
5694 * when a separate group interface is not used. This is needed
5695 * to allow p2p_cancel stop a pending p2p_connect-join.
5696 * wpas_p2p_init_group_interface() addresses this for the case
5697 * where a separate group interface is used.
5698 */
5699 if (group == wpa_s->parent)
5700 wpa_s->global->p2p_group_formation = group;
5701
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005702 group->p2p_in_provisioning = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07005703 group->p2p_fallback_to_go_neg = wpa_s->p2p_fallback_to_go_neg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005704
5705 os_memset(&res, 0, sizeof(res));
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005706 os_memcpy(res.peer_device_addr, wpa_s->pending_join_dev_addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005707 os_memcpy(res.peer_interface_addr, wpa_s->pending_join_iface_addr,
5708 ETH_ALEN);
5709 res.wps_method = wpa_s->pending_join_wps_method;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005710 if (freq && ssid && ssid_len) {
5711 res.freq = freq;
5712 res.ssid_len = ssid_len;
5713 os_memcpy(res.ssid, ssid, ssid_len);
5714 } else {
Dmitry Shmidtde47be72016-01-07 12:52:55 -08005715 if (ssid && ssid_len) {
5716 bss = wpa_bss_get(wpa_s, wpa_s->pending_join_iface_addr,
5717 ssid, ssid_len);
5718 } else {
5719 bss = wpa_bss_get_bssid_latest(
5720 wpa_s, wpa_s->pending_join_iface_addr);
5721 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005722 if (bss) {
5723 res.freq = bss->freq;
5724 res.ssid_len = bss->ssid_len;
5725 os_memcpy(res.ssid, bss->ssid, bss->ssid_len);
5726 wpa_printf(MSG_DEBUG, "P2P: Join target GO operating frequency from BSS table: %d MHz (SSID %s)",
5727 bss->freq,
5728 wpa_ssid_txt(bss->ssid, bss->ssid_len));
Dmitry Shmidtde47be72016-01-07 12:52:55 -08005729 } else if (ssid && ssid_len) {
5730 res.ssid_len = ssid_len;
5731 os_memcpy(res.ssid, ssid, ssid_len);
5732 wpa_printf(MSG_DEBUG, "P2P: Join target GO (SSID %s)",
5733 wpa_ssid_txt(ssid, ssid_len));
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005734 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07005735 }
5736
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005737 if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
5738 wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel prior to "
5739 "starting client");
5740 wpa_drv_cancel_remain_on_channel(wpa_s);
5741 wpa_s->off_channel_freq = 0;
5742 wpa_s->roc_waiting_drv_freq = 0;
5743 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005744 wpas_start_wps_enrollee(group, &res);
5745
5746 /*
5747 * Allow a longer timeout for join-a-running-group than normal 15
5748 * second group formation timeout since the GO may not have authorized
5749 * our connection yet.
5750 */
5751 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s, NULL);
5752 eloop_register_timeout(60, 0, wpas_p2p_group_formation_timeout,
5753 wpa_s, NULL);
5754
5755 return 0;
5756}
5757
5758
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005759static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005760 int *force_freq, int *pref_freq, int go,
Sunil8cd6f4d2022-06-28 18:40:46 +00005761 struct weighted_pcl *pref_freq_list,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005762 unsigned int *num_pref_freq)
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005763{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005764 struct wpa_used_freq_data *freqs;
5765 int res, best_freq, num_unused;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005766 unsigned int freq_in_use = 0, num, i, max_pref_freq;
Vinayak Yadawad8db34572021-08-30 21:28:05 +05305767 int p2p_pref_freq;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005768
5769 max_pref_freq = *num_pref_freq;
5770 *num_pref_freq = 0;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005771
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005772 freqs = os_calloc(wpa_s->num_multichan_concurrent,
5773 sizeof(struct wpa_used_freq_data));
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005774 if (!freqs)
5775 return -1;
5776
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005777 num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
5778 wpa_s->num_multichan_concurrent);
5779
5780 /*
5781 * It is possible that the total number of used frequencies is bigger
5782 * than the number of frequencies used for P2P, so get the system wide
5783 * number of unused frequencies.
5784 */
5785 num_unused = wpas_p2p_num_unused_channels(wpa_s);
5786
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07005787 wpa_printf(MSG_DEBUG,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005788 "P2P: Setup freqs: freq=%d num_MCC=%d shared_freqs=%u num_unused=%d",
5789 freq, wpa_s->num_multichan_concurrent, num, num_unused);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005790
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005791 if (freq > 0) {
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005792 int ret;
5793 if (go)
5794 ret = p2p_supported_freq(wpa_s->global->p2p, freq);
5795 else
5796 ret = p2p_supported_freq_cli(wpa_s->global->p2p, freq);
5797 if (!ret) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005798 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07005799 ieee80211_is_dfs(freq, wpa_s->hw.modes,
5800 wpa_s->hw.num_modes)) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08005801 /*
5802 * If freq is a DFS channel and DFS is offloaded
5803 * to the driver, allow P2P GO to use it.
5804 */
5805 wpa_printf(MSG_DEBUG,
5806 "P2P: The forced channel for GO (%u MHz) is DFS, and DFS is offloaded to the driver",
5807 freq);
5808 } else {
5809 wpa_printf(MSG_DEBUG,
5810 "P2P: The forced channel (%u MHz) is not supported for P2P uses",
5811 freq);
5812 res = -3;
5813 goto exit_free;
5814 }
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005815 }
5816
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005817 for (i = 0; i < num; i++) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005818 if (freqs[i].freq == freq)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005819 freq_in_use = 1;
5820 }
5821
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005822 if (num_unused <= 0 && !freq_in_use) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005823 wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group on %u MHz as there are no available channels",
5824 freq);
5825 res = -2;
5826 goto exit_free;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005827 }
5828 wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the "
5829 "requested channel (%u MHz)", freq);
5830 *force_freq = freq;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005831 goto exit_ok;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005832 }
5833
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005834 best_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005835
Vinayak Yadawad8db34572021-08-30 21:28:05 +05305836 if (*pref_freq == 0) {
5837 if (wpa_s->conf->num_p2p_pref_chan && IS_2GHZ(best_freq)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005838 i = 0;
Vinayak Yadawad8db34572021-08-30 21:28:05 +05305839 while (i < wpa_s->conf->num_p2p_pref_chan) {
5840 p2p_pref_freq = ieee80211_chan_to_freq(NULL,
5841 wpa_s->conf->p2p_pref_chan[i].op_class,
5842 wpa_s->conf->p2p_pref_chan[i].chan);
5843
5844 if (p2p_supported_freq(wpa_s->global->p2p, p2p_pref_freq) &&
5845 !wpas_p2p_disallowed_freq(wpa_s->global, p2p_pref_freq)) {
5846 best_freq = p2p_pref_freq;
5847 wpa_printf(MSG_DEBUG, "P2P: Using frequency (%u MHz) "
5848 "from P2P preferred channel list", best_freq);
5849 break;
5850 } else {
5851 wpa_printf(MSG_MSGDUMP, "P2P: Skipping preferred "
5852 "frequency (%u MHz) ", p2p_pref_freq);
5853 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005854 i++;
5855 }
Sreeramya Soratkalf928e8f2022-03-22 17:33:31 +05305856 } else if (!wpa_s->conf->num_p2p_pref_chan) {
Vinayak Yadawad8db34572021-08-30 21:28:05 +05305857 enum wpa_driver_if_type iface_type;
5858
5859 if (go)
5860 iface_type = WPA_IF_P2P_GO;
5861 else
5862 iface_type = WPA_IF_P2P_CLIENT;
5863
5864 wpa_printf(MSG_DEBUG, "P2P: best_freq=%d, go=%d",
5865 best_freq, go);
5866
5867 res = wpa_drv_get_pref_freq_list(wpa_s, iface_type,
5868 &max_pref_freq,
5869 pref_freq_list);
5870 if (!res && max_pref_freq > 0) {
5871 *num_pref_freq = max_pref_freq;
5872 i = 0;
5873 while (i < *num_pref_freq &&
5874 (!p2p_supported_freq(wpa_s->global->p2p,
Sunil8cd6f4d2022-06-28 18:40:46 +00005875 pref_freq_list[i].freq) ||
5876 wpas_p2p_disallowed_freq(
5877 wpa_s->global,
5878 pref_freq_list[i].freq) ||
5879 !p2p_pref_freq_allowed(&pref_freq_list[i],
5880 go))) {
Vinayak Yadawad8db34572021-08-30 21:28:05 +05305881 wpa_printf(MSG_DEBUG,
5882 "P2P: preferred_freq_list[%d]=%d is disallowed",
Sunil8cd6f4d2022-06-28 18:40:46 +00005883 i, pref_freq_list[i].freq);
Vinayak Yadawad8db34572021-08-30 21:28:05 +05305884 i++;
5885 }
5886 if (i != *num_pref_freq) {
Sunil8cd6f4d2022-06-28 18:40:46 +00005887 best_freq = pref_freq_list[i].freq;
Vinayak Yadawad8db34572021-08-30 21:28:05 +05305888 wpa_printf(MSG_DEBUG,
5889 "P2P: Using preferred_freq_list[%d]=%d",
5890 i, best_freq);
5891 } else {
5892 wpa_printf(MSG_DEBUG,
5893 "P2P: All driver preferred frequencies are "
5894 "disallowed for P2P use");
5895 *num_pref_freq = 0;
5896 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005897 } else {
5898 wpa_printf(MSG_DEBUG,
Vinayak Yadawad8db34572021-08-30 21:28:05 +05305899 "P2P: No preferred frequency list available");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005900 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005901 }
5902 }
5903
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005904 /* We have a candidate frequency to use */
5905 if (best_freq > 0) {
5906 if (*pref_freq == 0 && num_unused > 0) {
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08005907 wpa_printf(MSG_DEBUG, "P2P: Try to prefer a frequency (%u MHz) we are already using",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005908 best_freq);
5909 *pref_freq = best_freq;
Dmitry Shmidt51a47d52013-09-10 10:52:57 -07005910 } else {
5911 wpa_printf(MSG_DEBUG, "P2P: Try to force us to use frequency (%u MHz) which is already in use",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005912 best_freq);
5913 *force_freq = best_freq;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005914 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07005915 } else if (num_unused > 0) {
5916 wpa_printf(MSG_DEBUG,
5917 "P2P: Current operating channels are not available for P2P. Try to use another channel");
5918 *force_freq = 0;
5919 } else {
5920 wpa_printf(MSG_DEBUG,
5921 "P2P: All channels are in use and none of them are P2P enabled. Cannot start P2P group");
5922 res = -2;
5923 goto exit_free;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005924 }
5925
5926exit_ok:
5927 res = 0;
5928exit_free:
5929 os_free(freqs);
5930 return res;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08005931}
5932
5933
Hai Shalomc1a21442022-02-04 13:43:00 -08005934static bool is_p2p_6ghz_supported(struct wpa_supplicant *wpa_s,
5935 const u8 *peer_addr)
5936{
5937 if (wpa_s->conf->p2p_6ghz_disable ||
5938 !get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
5939 HOSTAPD_MODE_IEEE80211A, true))
5940 return false;
5941
5942 if (!p2p_wfd_enabled(wpa_s->global->p2p))
5943 return false;
5944 if (peer_addr && !p2p_peer_wfd_enabled(wpa_s->global->p2p, peer_addr))
5945 return false;
5946
5947 return true;
5948}
5949
5950
5951static int wpas_p2p_check_6ghz(struct wpa_supplicant *wpa_s,
5952 const u8 *peer_addr, bool allow_6ghz, int freq)
5953{
5954 if (allow_6ghz && is_p2p_6ghz_supported(wpa_s, peer_addr)) {
5955 wpa_printf(MSG_DEBUG,
5956 "P2P: Allow connection on 6 GHz channels");
5957 p2p_set_6ghz_dev_capab(wpa_s->global->p2p, true);
5958 } else {
5959 if (is_6ghz_freq(freq))
5960 return -2;
5961 p2p_set_6ghz_dev_capab(wpa_s->global->p2p, false);
5962 }
5963
5964 return 0;
5965}
5966
5967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005968/**
5969 * wpas_p2p_connect - Request P2P Group Formation to be started
5970 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
5971 * @peer_addr: Address of the peer P2P Device
5972 * @pin: PIN to use during provisioning or %NULL to indicate PBC mode
5973 * @persistent_group: Whether to create a persistent group
Dmitry Shmidt04949592012-07-19 12:16:46 -07005974 * @auto_join: Whether to select join vs. GO Negotiation automatically
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005975 * @join: Whether to join an existing group (as a client) instead of starting
5976 * Group Owner negotiation; @peer_addr is BSSID in that case
5977 * @auth: Whether to only authorize the connection instead of doing that and
5978 * initiating Group Owner negotiation
5979 * @go_intent: GO Intent or -1 to use default
5980 * @freq: Frequency for the group or 0 for auto-selection
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005981 * @freq2: Center frequency of segment 1 for the GO operating in VHT 80P80 mode
Dmitry Shmidt04949592012-07-19 12:16:46 -07005982 * @persistent_id: Persistent group credentials to use for forcing GO
5983 * parameters or -1 to generate new values (SSID/passphrase)
5984 * @pd: Whether to send Provision Discovery prior to GO Negotiation as an
5985 * interoperability workaround when initiating group formation
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005986 * @ht40: Start GO with 40 MHz channel width
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07005987 * @vht: Start GO with VHT support
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005988 * @vht_chwidth: Channel width supported by GO operating with VHT support
Hai Shalom81f62d82019-07-22 12:10:00 -07005989 * (CHANWIDTH_*).
Dmitry Shmidtde47be72016-01-07 12:52:55 -08005990 * @group_ssid: Specific Group SSID for join or %NULL if not set
5991 * @group_ssid_len: Length of @group_ssid in octets
Hai Shalomc1a21442022-02-04 13:43:00 -08005992 * @allow_6ghz: Allow P2P connection on 6 GHz channels
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005993 * Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
5994 * failure, -2 on failure due to channel not currently available,
5995 * -3 if forced channel is not supported
5996 */
5997int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
5998 const char *pin, enum p2p_wps_method wps_method,
Dmitry Shmidt04949592012-07-19 12:16:46 -07005999 int persistent_group, int auto_join, int join, int auth,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006000 int go_intent, int freq, unsigned int vht_center_freq2,
6001 int persistent_id, int pd, int ht40, int vht,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006002 unsigned int vht_chwidth, int he, int edmg,
Hai Shalomc1a21442022-02-04 13:43:00 -08006003 const u8 *group_ssid, size_t group_ssid_len,
6004 bool allow_6ghz)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006005{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006006 int force_freq = 0, pref_freq = 0;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08006007 int ret = 0, res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006008 enum wpa_driver_if_type iftype;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006009 const u8 *if_addr;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006010 struct wpa_ssid *ssid = NULL;
Sunil8cd6f4d2022-06-28 18:40:46 +00006011 struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
6012 unsigned int size;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006013
6014 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
6015 return -1;
6016
Dmitry Shmidt04949592012-07-19 12:16:46 -07006017 if (persistent_id >= 0) {
6018 ssid = wpa_config_get_network(wpa_s->conf, persistent_id);
6019 if (ssid == NULL || ssid->disabled != 2 ||
6020 ssid->mode != WPAS_MODE_P2P_GO)
6021 return -1;
6022 }
6023
Hai Shalomc1a21442022-02-04 13:43:00 -08006024 if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq))
Hai Shalom899fcc72020-10-19 14:38:18 -07006025 return -2;
6026
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006027 os_free(wpa_s->global->add_psk);
6028 wpa_s->global->add_psk = NULL;
6029
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006030 wpa_s->global->p2p_fail_on_wps_complete = 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006031 wpa_s->global->pending_p2ps_group = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006032 wpa_s->global->pending_p2ps_group_freq = 0;
6033 wpa_s->p2ps_method_config_any = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006034
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006035 if (go_intent < 0)
6036 go_intent = wpa_s->conf->p2p_go_intent;
6037
6038 if (!auth)
Hai Shalomfdcde762020-04-02 11:19:20 -07006039 wpa_s->global->p2p_long_listen = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006040
6041 wpa_s->p2p_wps_method = wps_method;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006042 wpa_s->p2p_persistent_group = !!persistent_group;
6043 wpa_s->p2p_persistent_id = persistent_id;
6044 wpa_s->p2p_go_intent = go_intent;
6045 wpa_s->p2p_connect_freq = freq;
6046 wpa_s->p2p_fallback_to_go_neg = 0;
6047 wpa_s->p2p_pd_before_go_neg = !!pd;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006048 wpa_s->p2p_go_ht40 = !!ht40;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006049 wpa_s->p2p_go_vht = !!vht;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006050 wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
6051 wpa_s->p2p_go_max_oper_chwidth = vht_chwidth;
Hai Shalom74f70d42019-02-11 14:42:39 -08006052 wpa_s->p2p_go_he = !!he;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006053 wpa_s->p2p_go_edmg = !!edmg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006054
6055 if (pin)
6056 os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
6057 else if (wps_method == WPS_PIN_DISPLAY) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08006058 if (wps_generate_pin((unsigned int *) &ret) < 0)
6059 return -1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006060 res = os_snprintf(wpa_s->p2p_pin, sizeof(wpa_s->p2p_pin),
6061 "%08d", ret);
6062 if (os_snprintf_error(sizeof(wpa_s->p2p_pin), res))
6063 wpa_s->p2p_pin[sizeof(wpa_s->p2p_pin) - 1] = '\0';
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006064 wpa_printf(MSG_DEBUG, "P2P: Randomly generated PIN: %s",
6065 wpa_s->p2p_pin);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006066 } else if (wps_method == WPS_P2PS) {
6067 /* Force the P2Ps default PIN to be used */
6068 os_strlcpy(wpa_s->p2p_pin, "12345670", sizeof(wpa_s->p2p_pin));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006069 } else
6070 wpa_s->p2p_pin[0] = '\0';
6071
Dmitry Shmidt04949592012-07-19 12:16:46 -07006072 if (join || auto_join) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006073 u8 iface_addr[ETH_ALEN], dev_addr[ETH_ALEN];
6074 if (auth) {
6075 wpa_printf(MSG_DEBUG, "P2P: Authorize invitation to "
6076 "connect a running group from " MACSTR,
6077 MAC2STR(peer_addr));
6078 os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
6079 return ret;
6080 }
6081 os_memcpy(dev_addr, peer_addr, ETH_ALEN);
6082 if (p2p_get_interface_addr(wpa_s->global->p2p, peer_addr,
6083 iface_addr) < 0) {
6084 os_memcpy(iface_addr, peer_addr, ETH_ALEN);
6085 p2p_get_dev_addr(wpa_s->global->p2p, peer_addr,
6086 dev_addr);
6087 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07006088 if (auto_join) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006089 os_get_reltime(&wpa_s->p2p_auto_started);
Dmitry Shmidt04949592012-07-19 12:16:46 -07006090 wpa_printf(MSG_DEBUG, "P2P: Auto join started at "
6091 "%ld.%06ld",
6092 wpa_s->p2p_auto_started.sec,
6093 wpa_s->p2p_auto_started.usec);
6094 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006095 wpa_s->user_initiated_pd = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07006096 if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08006097 auto_join, freq,
6098 group_ssid, group_ssid_len) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006099 return -1;
6100 return ret;
6101 }
6102
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006103 size = P2P_MAX_PREF_CHANNELS;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006104 res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006105 go_intent == 15, pref_freq_list, &size);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08006106 if (res)
6107 return res;
Dmitry Shmidta0d265f2013-11-19 13:13:41 -08006108 wpas_p2p_set_own_freq_preference(wpa_s,
6109 force_freq ? force_freq : pref_freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006110
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006111 p2p_set_own_pref_freq_list(wpa_s->global->p2p, pref_freq_list, size);
6112
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006113 wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
6114
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006115 if (wpa_s->create_p2p_iface) {
6116 /* Prepare to add a new interface for the group */
6117 iftype = WPA_IF_P2P_GROUP;
6118 if (go_intent == 15)
6119 iftype = WPA_IF_P2P_GO;
6120 if (wpas_p2p_add_group_interface(wpa_s, iftype) < 0) {
6121 wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new "
6122 "interface for the group");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006123 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006124 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006125
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006126 if_addr = wpa_s->pending_interface_addr;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006127 } else {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006128 if (wpa_s->p2p_mgmt)
6129 if_addr = wpa_s->parent->own_addr;
6130 else
6131 if_addr = wpa_s->own_addr;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006132 os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
6133 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006134
6135 if (auth) {
6136 if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006137 go_intent, if_addr,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006138 force_freq, persistent_group, ssid,
6139 pref_freq) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006140 return -1;
6141 return ret;
6142 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006143
6144 if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method,
6145 go_intent, if_addr, force_freq,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006146 persistent_group, ssid, pref_freq) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006147 if (wpa_s->create_p2p_iface)
6148 wpas_p2p_remove_pending_group_interface(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006149 return -1;
6150 }
6151 return ret;
6152}
6153
6154
6155/**
6156 * wpas_p2p_remain_on_channel_cb - Indication of remain-on-channel start
6157 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
6158 * @freq: Frequency of the channel in MHz
6159 * @duration: Duration of the stay on the channel in milliseconds
6160 *
6161 * This callback is called when the driver indicates that it has started the
6162 * requested remain-on-channel duration.
6163 */
6164void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
6165 unsigned int freq, unsigned int duration)
6166{
6167 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
6168 return;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08006169 wpa_printf(MSG_DEBUG, "P2P: remain-on-channel callback (off_channel_freq=%u pending_listen_freq=%d roc_waiting_drv_freq=%d freq=%u duration=%u)",
6170 wpa_s->off_channel_freq, wpa_s->pending_listen_freq,
6171 wpa_s->roc_waiting_drv_freq, freq, duration);
6172 if (wpa_s->off_channel_freq &&
6173 wpa_s->off_channel_freq == wpa_s->pending_listen_freq) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006174 p2p_listen_cb(wpa_s->global->p2p, wpa_s->pending_listen_freq,
6175 wpa_s->pending_listen_duration);
6176 wpa_s->pending_listen_freq = 0;
Dmitry Shmidt7f93d6f2014-02-21 11:22:49 -08006177 } else {
6178 wpa_printf(MSG_DEBUG, "P2P: Ignore remain-on-channel callback (off_channel_freq=%u pending_listen_freq=%d freq=%u duration=%u)",
6179 wpa_s->off_channel_freq, wpa_s->pending_listen_freq,
6180 freq, duration);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006181 }
6182}
6183
6184
Jithu Jance57cea1a2014-08-20 10:22:04 -07006185int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s, unsigned int timeout)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006186{
6187 /* Limit maximum Listen state time based on driver limitation. */
6188 if (timeout > wpa_s->max_remain_on_chan)
6189 timeout = wpa_s->max_remain_on_chan;
6190
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006191 return p2p_listen(wpa_s->global->p2p, timeout);
6192}
6193
6194
6195/**
6196 * wpas_p2p_cancel_remain_on_channel_cb - Remain-on-channel timeout
6197 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
6198 * @freq: Frequency of the channel in MHz
6199 *
6200 * This callback is called when the driver indicates that a remain-on-channel
6201 * operation has been completed, i.e., the duration on the requested channel
6202 * has timed out.
6203 */
6204void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
6205 unsigned int freq)
6206{
6207 wpa_printf(MSG_DEBUG, "P2P: Cancel remain-on-channel callback "
6208 "(p2p_long_listen=%d ms pending_action_tx=%p)",
Hai Shalomfdcde762020-04-02 11:19:20 -07006209 wpa_s->global->p2p_long_listen,
6210 offchannel_pending_action_tx(wpa_s));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08006211 wpas_p2p_listen_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006212 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
6213 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07006214 if (wpa_s->global->p2p_long_listen > 0)
6215 wpa_s->global->p2p_long_listen -= wpa_s->max_remain_on_chan;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006216 if (p2p_listen_end(wpa_s->global->p2p, freq) > 0)
6217 return; /* P2P module started a new operation */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08006218 if (offchannel_pending_action_tx(wpa_s))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006219 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07006220 if (wpa_s->global->p2p_long_listen > 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006221 wpa_printf(MSG_DEBUG, "P2P: Continuing long Listen state");
Hai Shalomfdcde762020-04-02 11:19:20 -07006222 wpas_p2p_listen_start(wpa_s, wpa_s->global->p2p_long_listen);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006223 } else {
6224 /*
6225 * When listen duration is over, stop listen & update p2p_state
6226 * to IDLE.
6227 */
6228 p2p_stop_listen(wpa_s->global->p2p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006229 }
6230}
6231
6232
6233/**
6234 * wpas_p2p_group_remove - Remove a P2P group
6235 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
6236 * @ifname: Network interface name of the group interface or "*" to remove all
6237 * groups
6238 * Returns: 0 on success, -1 on failure
6239 *
6240 * This function is used to remove a P2P group. This can be used to disconnect
6241 * from a group in which the local end is a P2P Client or to end a P2P Group in
6242 * case the local end is the Group Owner. If a virtual network interface was
6243 * created for this group, that interface will be removed. Otherwise, only the
6244 * configured P2P group network will be removed from the interface.
6245 */
6246int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname)
6247{
6248 struct wpa_global *global = wpa_s->global;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006249 struct wpa_supplicant *calling_wpa_s = wpa_s;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006250
6251 if (os_strcmp(ifname, "*") == 0) {
6252 struct wpa_supplicant *prev;
Hai Shalom899fcc72020-10-19 14:38:18 -07006253 bool calling_wpa_s_group_removed = false;
6254
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006255 wpa_s = global->ifaces;
6256 while (wpa_s) {
6257 prev = wpa_s;
6258 wpa_s = wpa_s->next;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07006259 if (prev->p2p_group_interface !=
6260 NOT_P2P_GROUP_INTERFACE ||
6261 (prev->current_ssid &&
Hai Shalom899fcc72020-10-19 14:38:18 -07006262 prev->current_ssid->p2p_group)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006263 wpas_p2p_disconnect_safely(prev, calling_wpa_s);
Hai Shalom899fcc72020-10-19 14:38:18 -07006264 if (prev == calling_wpa_s)
6265 calling_wpa_s_group_removed = true;
6266 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006267 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006268
6269 if (!calling_wpa_s_group_removed &&
6270 (calling_wpa_s->p2p_group_interface !=
6271 NOT_P2P_GROUP_INTERFACE ||
6272 (calling_wpa_s->current_ssid &&
6273 calling_wpa_s->current_ssid->p2p_group))) {
6274 wpa_printf(MSG_DEBUG, "Remove calling_wpa_s P2P group");
6275 wpas_p2p_disconnect_safely(calling_wpa_s,
6276 calling_wpa_s);
6277 }
6278
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006279 return 0;
6280 }
6281
6282 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
6283 if (os_strcmp(wpa_s->ifname, ifname) == 0)
6284 break;
6285 }
6286
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08006287 return wpas_p2p_disconnect_safely(wpa_s, calling_wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006288}
6289
6290
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006291static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
6292{
6293 unsigned int r;
6294
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006295 if (!wpa_s->conf->num_p2p_pref_chan && !freq) {
6296 unsigned int i, size = P2P_MAX_PREF_CHANNELS;
Sunil8cd6f4d2022-06-28 18:40:46 +00006297 struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006298 int res;
6299
6300 res = wpa_drv_get_pref_freq_list(wpa_s, WPA_IF_P2P_GO,
6301 &size, pref_freq_list);
Hai Shalomc1a21442022-02-04 13:43:00 -08006302 if (!is_p2p_allow_6ghz(wpa_s->global->p2p))
6303 size = p2p_remove_6ghz_channels(pref_freq_list, size);
6304
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006305 if (!res && size > 0) {
6306 i = 0;
Dmitry Shmidt29333592017-01-09 12:27:11 -08006307 while (i < size &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006308 (!p2p_supported_freq(wpa_s->global->p2p,
Sunil8cd6f4d2022-06-28 18:40:46 +00006309 pref_freq_list[i].freq) ||
6310 wpas_p2p_disallowed_freq(
6311 wpa_s->global,
6312 pref_freq_list[i].freq) ||
6313 !p2p_pref_freq_allowed(&pref_freq_list[i],
6314 true))) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006315 wpa_printf(MSG_DEBUG,
6316 "P2P: preferred_freq_list[%d]=%d is disallowed",
Sunil8cd6f4d2022-06-28 18:40:46 +00006317 i, pref_freq_list[i].freq);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006318 i++;
6319 }
6320 if (i != size) {
Sunil8cd6f4d2022-06-28 18:40:46 +00006321 freq = pref_freq_list[i].freq;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006322 wpa_printf(MSG_DEBUG,
6323 "P2P: Using preferred_freq_list[%d]=%d",
6324 i, freq);
6325 } else {
6326 wpa_printf(MSG_DEBUG,
6327 "P2P: All driver preferred frequencies are disallowed for P2P use");
6328 }
6329 } else {
6330 wpa_printf(MSG_DEBUG,
6331 "P2P: No preferred frequency list available");
6332 }
6333 }
6334
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006335 if (freq == 2) {
6336 wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 2.4 GHz "
6337 "band");
6338 if (wpa_s->best_24_freq > 0 &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006339 p2p_supported_freq_go(wpa_s->global->p2p,
6340 wpa_s->best_24_freq)) {
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006341 freq = wpa_s->best_24_freq;
6342 wpa_printf(MSG_DEBUG, "P2P: Use best 2.4 GHz band "
6343 "channel: %d MHz", freq);
6344 } else {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006345 if (os_get_random((u8 *) &r, sizeof(r)) < 0)
6346 return -1;
Jimmy Chen801bf462021-11-09 23:08:48 +08006347 int possible_2g_freqs[] = {
6348 /* operating class 81 */
6349 2412, 2437, 2462,
6350 };
6351 int possible_2g_freqs_num =
6352 sizeof(possible_2g_freqs)/sizeof(possible_2g_freqs[0]);
6353 int i;
6354 for (i = 0; i < possible_2g_freqs_num; i++, r++) {
6355 freq = possible_2g_freqs[r % possible_2g_freqs_num];
6356 if (p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
6357 break;
6358 }
6359 }
6360
6361 if (i >= possible_2g_freqs_num) {
6362 wpa_printf(MSG_DEBUG, "P2P: Could not select "
6363 "2.4 GHz channel for P2P group");
6364 return -1;
6365 }
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006366 wpa_printf(MSG_DEBUG, "P2P: Use random 2.4 GHz band "
6367 "channel: %d MHz", freq);
6368 }
6369 }
6370
6371 if (freq == 5) {
6372 wpa_printf(MSG_DEBUG, "P2P: Request to start GO on 5 GHz "
6373 "band");
6374 if (wpa_s->best_5_freq > 0 &&
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006375 p2p_supported_freq_go(wpa_s->global->p2p,
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006376 wpa_s->best_5_freq)) {
6377 freq = wpa_s->best_5_freq;
6378 wpa_printf(MSG_DEBUG, "P2P: Use best 5 GHz band "
6379 "channel: %d MHz", freq);
6380 } else {
Hai Shalomc1a21442022-02-04 13:43:00 -08006381 const int freqs[] = {
6382 /* operating class 115 */
6383 5180, 5200, 5220, 5240,
6384 /* operating class 124 */
6385 5745, 5765, 5785, 5805,
6386 };
6387 unsigned int i, num_freqs = ARRAY_SIZE(freqs);
6388
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006389 if (os_get_random((u8 *) &r, sizeof(r)) < 0)
6390 return -1;
Jimmy Chen64b90632020-09-29 17:27:34 +08006391
6392 /*
6393 * most of 5G channels are DFS, only operating class 115 and 124
6394 * are available possibly, randomly pick a start to check them.
6395 */
6396 int possible_5g_freqs[] = {
6397 /* operating class 115 */
6398 5180, 5200, 5220, 5240,
6399 /* operating class 124 */
6400 5745, 5765, 5785, 5805,
6401 };
6402 int possible_5g_freqs_num =
6403 sizeof(possible_5g_freqs)/sizeof(possible_5g_freqs[0]);
6404
Jimmy Chen64b90632020-09-29 17:27:34 +08006405 for (i = 0; i < possible_5g_freqs_num; i++, r++) {
6406 if (p2p_supported_freq_go(
6407 wpa_s->global->p2p,
6408 possible_5g_freqs[r % possible_5g_freqs_num])) {
6409 freq = possible_5g_freqs[r % possible_5g_freqs_num];
6410 break;
6411 }
6412 }
6413
6414 if (i >= possible_5g_freqs_num) {
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006415 wpa_printf(MSG_DEBUG, "P2P: Could not select "
6416 "5 GHz channel for P2P group");
6417 return -1;
6418 }
6419 wpa_printf(MSG_DEBUG, "P2P: Use random 5 GHz band "
6420 "channel: %d MHz", freq);
6421 }
6422 }
6423
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006424 if (freq > 0 && !p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006425 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07006426 ieee80211_is_dfs(freq, wpa_s->hw.modes,
6427 wpa_s->hw.num_modes)) {
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006428 /*
6429 * If freq is a DFS channel and DFS is offloaded to the
6430 * driver, allow P2P GO to use it.
6431 */
6432 wpa_printf(MSG_DEBUG, "P2P: "
6433 "%s: The forced channel for GO (%u MHz) is DFS, and DFS is offloaded",
6434 __func__, freq);
6435 return freq;
6436 }
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07006437 wpa_printf(MSG_DEBUG, "P2P: The forced channel for GO "
6438 "(%u MHz) is not supported for P2P uses",
6439 freq);
6440 return -1;
6441 }
6442
6443 return freq;
6444}
6445
6446
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006447static int wpas_p2p_supported_freq_go(struct wpa_supplicant *wpa_s,
6448 const struct p2p_channels *channels,
6449 int freq)
6450{
6451 if (!wpas_p2p_disallowed_freq(wpa_s->global, freq) &&
6452 p2p_supported_freq_go(wpa_s->global->p2p, freq) &&
6453 freq_included(wpa_s, channels, freq))
6454 return 1;
6455 return 0;
6456}
6457
6458
6459static void wpas_p2p_select_go_freq_no_pref(struct wpa_supplicant *wpa_s,
6460 struct p2p_go_neg_results *params,
6461 const struct p2p_channels *channels)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006462{
6463 unsigned int i, r;
6464
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006465 /* try all channels in operating class 115 */
6466 for (i = 0; i < 4; i++) {
6467 params->freq = 5180 + i * 20;
Hai Shalomc1a21442022-02-04 13:43:00 -08006468 if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006469 goto out;
6470 }
6471
6472 /* try all channels in operating class 124 */
6473 for (i = 0; i < 4; i++) {
6474 params->freq = 5745 + i * 20;
Hai Shalomc1a21442022-02-04 13:43:00 -08006475 if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006476 goto out;
6477 }
6478
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006479 /* try social channel class 180 channel 2 */
6480 params->freq = 58320 + 1 * 2160;
Hai Shalomc1a21442022-02-04 13:43:00 -08006481 if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006482 goto out;
6483
6484 /* try all channels in reg. class 180 */
6485 for (i = 0; i < 4; i++) {
6486 params->freq = 58320 + i * 2160;
Hai Shalomc1a21442022-02-04 13:43:00 -08006487 if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07006488 goto out;
6489 }
6490
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006491 /* try some random selection of the social channels */
6492 if (os_get_random((u8 *) &r, sizeof(r)) < 0)
6493 return;
6494
6495 for (i = 0; i < 3; i++) {
6496 params->freq = 2412 + ((r + i) % 3) * 25;
6497 if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
6498 goto out;
6499 }
6500
6501 /* try all other channels in operating class 81 */
6502 for (i = 0; i < 11; i++) {
6503 params->freq = 2412 + i * 5;
6504
6505 /* skip social channels; covered in the previous loop */
6506 if (params->freq == 2412 ||
6507 params->freq == 2437 ||
6508 params->freq == 2462)
6509 continue;
6510
6511 if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
6512 goto out;
6513 }
6514
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006515 params->freq = 0;
Dmitry Shmidt203eadb2015-03-05 14:16:04 -08006516 wpa_printf(MSG_DEBUG, "P2P: No 2.4, 5, or 60 GHz channel allowed");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006517 return;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006518out:
6519 wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference known)",
6520 params->freq);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006521}
6522
6523
Roshan Pius3a1667e2018-07-03 15:17:14 -07006524static int wpas_same_band(int freq1, int freq2)
6525{
6526 enum hostapd_hw_mode mode1, mode2;
6527 u8 chan1, chan2;
6528
6529 mode1 = ieee80211_freq_to_chan(freq1, &chan1);
6530 mode2 = ieee80211_freq_to_chan(freq2, &chan2);
6531 if (mode1 == NUM_HOSTAPD_MODES)
6532 return 0;
6533 return mode1 == mode2;
6534}
6535
6536
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006537static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
6538 struct p2p_go_neg_results *params,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006539 int freq, int vht_center_freq2, int ht40,
Hai Shalom74f70d42019-02-11 14:42:39 -08006540 int vht, int max_oper_chwidth, int he,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006541 int edmg,
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08006542 const struct p2p_channels *channels)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006543{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006544 struct wpa_used_freq_data *freqs;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006545 unsigned int cand;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006546 unsigned int num, i;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006547 int ignore_no_freqs = 0;
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08006548 int unused_channels = wpas_p2p_num_unused_channels(wpa_s) > 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006549
6550 os_memset(params, 0, sizeof(*params));
6551 params->role_go = 1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07006552 params->ht40 = ht40;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006553 params->vht = vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08006554 params->he = he;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006555 params->max_oper_chwidth = max_oper_chwidth;
6556 params->vht_center_freq2 = vht_center_freq2;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006557 params->edmg = edmg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006558
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006559 freqs = os_calloc(wpa_s->num_multichan_concurrent,
6560 sizeof(struct wpa_used_freq_data));
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006561 if (!freqs)
6562 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006563
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006564 num = get_shared_radio_freqs_data(wpa_s, freqs,
Sunil Ravi77d572f2023-01-17 23:58:31 +00006565 wpa_s->num_multichan_concurrent,
6566 false);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006567
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006568 if (wpa_s->current_ssid &&
6569 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO &&
6570 wpa_s->wpa_state == WPA_COMPLETED) {
6571 wpa_printf(MSG_DEBUG, "P2P: %s called for an active GO",
6572 __func__);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006573
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006574 /*
6575 * If the frequency selection is done for an active P2P GO that
6576 * is not sharing a frequency, allow to select a new frequency
6577 * even if there are no unused frequencies as we are about to
6578 * move the P2P GO so its frequency can be re-used.
6579 */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006580 for (i = 0; i < num; i++) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006581 if (freqs[i].freq == wpa_s->current_ssid->frequency &&
6582 freqs[i].flags == 0) {
6583 ignore_no_freqs = 1;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07006584 break;
6585 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006586 }
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08006587 }
6588
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006589 /* Try to use EDMG channel */
6590 if (params->edmg) {
6591 if (wpas_p2p_try_edmg_channel(wpa_s, params) == 0)
6592 goto success;
6593 params->edmg = 0;
6594 }
6595
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006596 /* try using the forced freq */
6597 if (freq) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006598 if (wpas_p2p_disallowed_freq(wpa_s->global, freq) ||
6599 !freq_included(wpa_s, channels, freq)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006600 wpa_printf(MSG_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006601 "P2P: Forced GO freq %d MHz disallowed",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006602 freq);
6603 goto fail;
6604 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006605 if (!p2p_supported_freq_go(wpa_s->global->p2p, freq)) {
6606 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07006607 ieee80211_is_dfs(freq, wpa_s->hw.modes,
6608 wpa_s->hw.num_modes)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006609 /*
6610 * If freq is a DFS channel and DFS is offloaded
6611 * to the driver, allow P2P GO to use it.
6612 */
6613 wpa_printf(MSG_DEBUG,
6614 "P2P: %s: The forced channel for GO (%u MHz) requires DFS and DFS is offloaded",
6615 __func__, freq);
6616 } else {
6617 wpa_printf(MSG_DEBUG,
6618 "P2P: The forced channel for GO (%u MHz) is not supported for P2P uses",
6619 freq);
6620 goto fail;
6621 }
6622 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006623
6624 for (i = 0; i < num; i++) {
6625 if (freqs[i].freq == freq) {
6626 wpa_printf(MSG_DEBUG,
6627 "P2P: forced freq (%d MHz) is also shared",
6628 freq);
6629 params->freq = freq;
6630 goto success;
6631 }
6632 }
6633
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08006634 if (!ignore_no_freqs && !unused_channels) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006635 wpa_printf(MSG_DEBUG,
6636 "P2P: Cannot force GO on freq (%d MHz) as all the channels are in use",
6637 freq);
6638 goto fail;
6639 }
6640
6641 wpa_printf(MSG_DEBUG,
6642 "P2P: force GO freq (%d MHz) on a free channel",
6643 freq);
6644 params->freq = freq;
6645 goto success;
6646 }
6647
6648 /* consider using one of the shared frequencies */
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08006649 if (num &&
6650 (!wpa_s->conf->p2p_ignore_shared_freq || !unused_channels)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006651 cand = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
6652 if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
6653 wpa_printf(MSG_DEBUG,
6654 "P2P: Use shared freq (%d MHz) for GO",
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08006655 cand);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006656 params->freq = cand;
6657 goto success;
6658 }
6659
6660 /* try using one of the shared freqs */
6661 for (i = 0; i < num; i++) {
6662 if (wpas_p2p_supported_freq_go(wpa_s, channels,
6663 freqs[i].freq)) {
6664 wpa_printf(MSG_DEBUG,
6665 "P2P: Use shared freq (%d MHz) for GO",
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08006666 freqs[i].freq);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006667 params->freq = freqs[i].freq;
6668 goto success;
6669 }
6670 }
6671 }
6672
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08006673 if (!ignore_no_freqs && !unused_channels) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006674 wpa_printf(MSG_DEBUG,
6675 "P2P: Cannot force GO on any of the channels we are already using");
6676 goto fail;
6677 }
6678
6679 /* try using the setting from the configuration file */
6680 if (wpa_s->conf->p2p_oper_reg_class == 81 &&
6681 wpa_s->conf->p2p_oper_channel >= 1 &&
6682 wpa_s->conf->p2p_oper_channel <= 11 &&
6683 wpas_p2p_supported_freq_go(
6684 wpa_s, channels,
6685 2407 + 5 * wpa_s->conf->p2p_oper_channel)) {
6686 params->freq = 2407 + 5 * wpa_s->conf->p2p_oper_channel;
6687 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
6688 "frequency %d MHz", params->freq);
6689 goto success;
6690 }
6691
6692 if ((wpa_s->conf->p2p_oper_reg_class == 115 ||
6693 wpa_s->conf->p2p_oper_reg_class == 116 ||
6694 wpa_s->conf->p2p_oper_reg_class == 117 ||
6695 wpa_s->conf->p2p_oper_reg_class == 124 ||
6696 wpa_s->conf->p2p_oper_reg_class == 125 ||
6697 wpa_s->conf->p2p_oper_reg_class == 126 ||
6698 wpa_s->conf->p2p_oper_reg_class == 127) &&
6699 wpas_p2p_supported_freq_go(wpa_s, channels,
6700 5000 +
6701 5 * wpa_s->conf->p2p_oper_channel)) {
6702 params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel;
6703 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured "
6704 "frequency %d MHz", params->freq);
6705 goto success;
6706 }
6707
6708 /* Try using best channels */
6709 if (wpa_s->conf->p2p_oper_channel == 0 &&
6710 wpa_s->best_overall_freq > 0 &&
6711 wpas_p2p_supported_freq_go(wpa_s, channels,
6712 wpa_s->best_overall_freq)) {
6713 params->freq = wpa_s->best_overall_freq;
6714 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best overall "
6715 "channel %d MHz", params->freq);
6716 goto success;
6717 }
6718
6719 if (wpa_s->conf->p2p_oper_channel == 0 &&
6720 wpa_s->best_24_freq > 0 &&
6721 wpas_p2p_supported_freq_go(wpa_s, channels,
6722 wpa_s->best_24_freq)) {
6723 params->freq = wpa_s->best_24_freq;
6724 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 2.4 GHz "
6725 "channel %d MHz", params->freq);
6726 goto success;
6727 }
6728
6729 if (wpa_s->conf->p2p_oper_channel == 0 &&
6730 wpa_s->best_5_freq > 0 &&
6731 wpas_p2p_supported_freq_go(wpa_s, channels,
6732 wpa_s->best_5_freq)) {
6733 params->freq = wpa_s->best_5_freq;
6734 wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz "
6735 "channel %d MHz", params->freq);
6736 goto success;
6737 }
6738
6739 /* try using preferred channels */
6740 cand = p2p_get_pref_freq(wpa_s->global->p2p, channels);
6741 if (cand && wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
6742 params->freq = cand;
6743 wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred "
6744 "channels", params->freq);
6745 goto success;
6746 }
6747
Roshan Pius3a1667e2018-07-03 15:17:14 -07006748 /* Try using a channel that allows VHT to be used with 80 MHz */
6749 if (wpa_s->hw.modes && wpa_s->p2p_group_common_freqs) {
6750 for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
6751 enum hostapd_hw_mode mode;
6752 struct hostapd_hw_modes *hwmode;
6753 u8 chan;
Hai Shalomc1a21442022-02-04 13:43:00 -08006754 u8 op_class;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006755
6756 cand = wpa_s->p2p_group_common_freqs[i];
Hai Shalomc1a21442022-02-04 13:43:00 -08006757 op_class = is_6ghz_freq(cand) ? 133 : 128;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006758 mode = ieee80211_freq_to_chan(cand, &chan);
6759 hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalomfdcde762020-04-02 11:19:20 -07006760 mode, is_6ghz_freq(cand));
Roshan Pius3a1667e2018-07-03 15:17:14 -07006761 if (!hwmode ||
Hai Shalomc1a21442022-02-04 13:43:00 -08006762 wpas_p2p_verify_channel(wpa_s, hwmode, op_class,
6763 chan, BW80) != ALLOWED)
Roshan Pius3a1667e2018-07-03 15:17:14 -07006764 continue;
6765 if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
6766 params->freq = cand;
6767 wpa_printf(MSG_DEBUG,
6768 "P2P: Use freq %d MHz common with the peer and allowing VHT80",
6769 params->freq);
6770 goto success;
6771 }
6772 }
6773 }
6774
6775 /* Try using a channel that allows HT to be used with 40 MHz on the same
6776 * band so that CSA can be used */
6777 if (wpa_s->current_ssid && wpa_s->hw.modes &&
6778 wpa_s->p2p_group_common_freqs) {
6779 for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
6780 enum hostapd_hw_mode mode;
6781 struct hostapd_hw_modes *hwmode;
Hai Shalomc1a21442022-02-04 13:43:00 -08006782 u8 chan, op_class;
6783 bool is_6ghz, supported = false;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006784
Hai Shalomc1a21442022-02-04 13:43:00 -08006785 is_6ghz = is_6ghz_freq(cand);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006786 cand = wpa_s->p2p_group_common_freqs[i];
6787 mode = ieee80211_freq_to_chan(cand, &chan);
6788 hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalomc1a21442022-02-04 13:43:00 -08006789 mode, is_6ghz);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006790 if (!wpas_same_band(wpa_s->current_ssid->frequency,
6791 cand) ||
Hai Shalomc1a21442022-02-04 13:43:00 -08006792 !hwmode)
Roshan Pius3a1667e2018-07-03 15:17:14 -07006793 continue;
Hai Shalomc1a21442022-02-04 13:43:00 -08006794 if (is_6ghz &&
6795 wpas_p2p_verify_channel(wpa_s, hwmode, 132, chan,
6796 BW40) == ALLOWED)
6797 supported = true;
6798
6799 if (!is_6ghz &&
6800 ieee80211_freq_to_channel_ext(
Sunil8cd6f4d2022-06-28 18:40:46 +00006801 cand, -1, CONF_OPER_CHWIDTH_USE_HT,
6802 &op_class, &chan) != NUM_HOSTAPD_MODES &&
Hai Shalomc1a21442022-02-04 13:43:00 -08006803 wpas_p2p_verify_channel(
6804 wpa_s, hwmode, op_class, chan,
6805 BW40MINUS) == ALLOWED)
6806 supported = true;
6807
6808 if (!supported && !is_6ghz &&
6809 ieee80211_freq_to_channel_ext(
Sunil8cd6f4d2022-06-28 18:40:46 +00006810 cand, 1, CONF_OPER_CHWIDTH_USE_HT,
6811 &op_class, &chan) != NUM_HOSTAPD_MODES &&
Hai Shalomc1a21442022-02-04 13:43:00 -08006812 wpas_p2p_verify_channel(
6813 wpa_s, hwmode, op_class, chan,
6814 BW40PLUS) == ALLOWED)
6815 supported = true;
6816
6817 if (!supported)
6818 continue;
6819
Roshan Pius3a1667e2018-07-03 15:17:14 -07006820 if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
6821 params->freq = cand;
6822 wpa_printf(MSG_DEBUG,
6823 "P2P: Use freq %d MHz common with the peer, allowing HT40, and maintaining same band",
6824 params->freq);
6825 goto success;
6826 }
6827 }
6828 }
6829
6830 /* Try using one of the group common freqs on the same band so that CSA
6831 * can be used */
6832 if (wpa_s->current_ssid && wpa_s->p2p_group_common_freqs) {
6833 for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
6834 cand = wpa_s->p2p_group_common_freqs[i];
6835 if (!wpas_same_band(wpa_s->current_ssid->frequency,
6836 cand))
6837 continue;
6838 if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
6839 params->freq = cand;
6840 wpa_printf(MSG_DEBUG,
6841 "P2P: Use freq %d MHz common with the peer and maintaining same band",
6842 params->freq);
6843 goto success;
6844 }
6845 }
6846 }
6847
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006848 /* Try using one of the group common freqs */
6849 if (wpa_s->p2p_group_common_freqs) {
6850 for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
6851 cand = wpa_s->p2p_group_common_freqs[i];
6852 if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
6853 params->freq = cand;
6854 wpa_printf(MSG_DEBUG,
6855 "P2P: Use freq %d MHz common with the peer",
6856 params->freq);
6857 goto success;
6858 }
6859 }
6860 }
6861
6862 /* no preference, select some channel */
6863 wpas_p2p_select_go_freq_no_pref(wpa_s, params, channels);
6864
6865 if (params->freq == 0) {
6866 wpa_printf(MSG_DEBUG, "P2P: did not find a freq for GO use");
6867 goto fail;
6868 }
6869
6870success:
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07006871 os_free(freqs);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006872 return 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08006873fail:
6874 os_free(freqs);
6875 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006876}
6877
6878
6879static struct wpa_supplicant *
6880wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
6881 int go)
6882{
6883 struct wpa_supplicant *group_wpa_s;
6884
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006885 if (!wpas_p2p_create_iface(wpa_s)) {
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006886 if (wpa_s->p2p_mgmt) {
6887 /*
6888 * We may be called on the p2p_dev interface which
6889 * cannot be used for group operations, so always use
6890 * the primary interface.
6891 */
6892 wpa_s->parent->p2pdev = wpa_s;
6893 wpa_s = wpa_s->parent;
6894 }
6895 wpa_dbg(wpa_s, MSG_DEBUG,
6896 "P2P: Use primary interface for group operations");
Dmitry Shmidt56052862013-10-04 10:23:25 -07006897 wpa_s->p2p_first_connection_timeout = 0;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08006898 if (wpa_s != wpa_s->p2pdev)
Dmitry Shmidt849734c2016-05-27 09:59:01 -07006899 wpas_p2p_clone_config(wpa_s, wpa_s->p2pdev);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006900 return wpa_s;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006901 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006902
6903 if (wpas_p2p_add_group_interface(wpa_s, go ? WPA_IF_P2P_GO :
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006904 WPA_IF_P2P_CLIENT) < 0) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006905 wpa_msg_global(wpa_s, MSG_ERROR,
6906 "P2P: Failed to add group interface");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006907 return NULL;
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006908 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006909 group_wpa_s = wpas_p2p_init_group_interface(wpa_s, go);
6910 if (group_wpa_s == NULL) {
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07006911 wpa_msg_global(wpa_s, MSG_ERROR,
6912 "P2P: Failed to initialize group interface");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006913 wpas_p2p_remove_pending_group_interface(wpa_s);
6914 return NULL;
6915 }
6916
Roshan Pius3a1667e2018-07-03 15:17:14 -07006917 if (go && wpa_s->p2p_go_do_acs) {
6918 group_wpa_s->p2p_go_do_acs = wpa_s->p2p_go_do_acs;
6919 group_wpa_s->p2p_go_acs_band = wpa_s->p2p_go_acs_band;
6920 wpa_s->p2p_go_do_acs = 0;
6921 }
6922
Hai Shalomc1a21442022-02-04 13:43:00 -08006923 if (go && wpa_s->p2p_go_allow_dfs) {
6924 group_wpa_s->p2p_go_allow_dfs = wpa_s->p2p_go_allow_dfs;
6925 wpa_s->p2p_go_allow_dfs = 0;
6926 }
6927
Dmitry Shmidtaa532512012-09-24 10:35:31 -07006928 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use separate group interface %s",
6929 group_wpa_s->ifname);
Dmitry Shmidt56052862013-10-04 10:23:25 -07006930 group_wpa_s->p2p_first_connection_timeout = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006931 return group_wpa_s;
6932}
6933
6934
6935/**
6936 * wpas_p2p_group_add - Add a new P2P group with local end as Group Owner
6937 * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
6938 * @persistent_group: Whether to create a persistent group
6939 * @freq: Frequency for the group or 0 to indicate no hardcoding
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006940 * @vht_center_freq2: segment_1 center frequency for GO operating in VHT 80P80
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07006941 * @ht40: Start GO with 40 MHz channel width
6942 * @vht: Start GO with VHT support
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006943 * @vht_chwidth: channel bandwidth for GO operating with VHT support
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006944 * @edmg: Start GO with EDMG support
Hai Shalomc1a21442022-02-04 13:43:00 -08006945 * @allow_6ghz: Allow P2P group creation on a 6 GHz channel
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006946 * Returns: 0 on success, -1 on failure
6947 *
6948 * This function creates a new P2P group with the local end as the Group Owner,
6949 * i.e., without using Group Owner Negotiation.
6950 */
6951int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08006952 int freq, int vht_center_freq2, int ht40, int vht,
Hai Shalomc1a21442022-02-04 13:43:00 -08006953 int max_oper_chwidth, int he, int edmg,
6954 bool allow_6ghz)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006955{
6956 struct p2p_go_neg_results params;
Sunil Ravi77a0f092022-10-03 00:53:41 +00006957 int selected_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006958
6959 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
6960 return -1;
Hai Shalomc1a21442022-02-04 13:43:00 -08006961 if (wpas_p2p_check_6ghz(wpa_s, NULL, allow_6ghz, freq))
6962 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006963
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07006964 os_free(wpa_s->global->add_psk);
6965 wpa_s->global->add_psk = NULL;
6966
Dmitry Shmidtdca39792011-09-06 11:17:33 -07006967 /* Make sure we are not running find during connection establishment */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006968 wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08006969 wpas_p2p_stop_find_oper(wpa_s);
Dmitry Shmidtdca39792011-09-06 11:17:33 -07006970
Roshan Pius3a1667e2018-07-03 15:17:14 -07006971 if (!wpa_s->p2p_go_do_acs) {
Sunil Ravi77a0f092022-10-03 00:53:41 +00006972 selected_freq = wpas_p2p_select_go_freq(wpa_s, freq);
6973 if (selected_freq < 0)
Roshan Pius3a1667e2018-07-03 15:17:14 -07006974 return -1;
6975 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006976
Sunil Ravi77a0f092022-10-03 00:53:41 +00006977 if (wpas_p2p_init_go_params(wpa_s, &params, selected_freq, vht_center_freq2,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08006978 ht40, vht, max_oper_chwidth, he, edmg,
6979 NULL))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08006980 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006982 p2p_go_params(wpa_s->global->p2p, &params);
6983 params.persistent_group = persistent_group;
6984
6985 wpa_s = wpas_p2p_get_group_iface(wpa_s, 0, 1);
6986 if (wpa_s == NULL)
6987 return -1;
Sunil Ravi77a0f092022-10-03 00:53:41 +00006988 if (freq > 0)
6989 wpa_s->p2p_go_no_pri_sec_switch = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07006990 wpas_start_wps_go(wpa_s, &params, 0);
6991
6992 return 0;
6993}
6994
6995
6996static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
Dmitry Shmidt15907092014-03-25 10:42:57 -07006997 struct wpa_ssid *params, int addr_allocated,
Matthew Wang124e5f42022-12-29 07:23:06 +00006998 int freq, int force_scan, int retry_limit,
6999 bool force_go_bssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007000{
7001 struct wpa_ssid *ssid;
Matthew Wang9ae940b2022-09-14 21:25:34 -07007002 int other_iface_found = 0;
7003 struct wpa_supplicant *ifs;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007004
7005 wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 0);
7006 if (wpa_s == NULL)
7007 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007008 if (force_scan)
7009 os_get_reltime(&wpa_s->scan_min_time);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007010 wpa_s->p2p_last_4way_hs_fail = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007011
7012 wpa_supplicant_ap_deinit(wpa_s);
7013
7014 ssid = wpa_config_add_network(wpa_s->conf);
7015 if (ssid == NULL)
7016 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007017 os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007018 wpa_config_set_network_defaults(ssid);
7019 ssid->temporary = 1;
7020 ssid->proto = WPA_PROTO_RSN;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007021 ssid->pbss = params->pbss;
7022 ssid->pairwise_cipher = params->pbss ? WPA_CIPHER_GCMP :
7023 WPA_CIPHER_CCMP;
7024 ssid->group_cipher = params->pbss ? WPA_CIPHER_GCMP : WPA_CIPHER_CCMP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007025 ssid->key_mgmt = WPA_KEY_MGMT_PSK;
7026 ssid->ssid = os_malloc(params->ssid_len);
7027 if (ssid->ssid == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007028 wpa_config_remove_network(wpa_s->conf, ssid->id);
7029 return -1;
7030 }
7031 os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
7032 ssid->ssid_len = params->ssid_len;
7033 ssid->p2p_group = 1;
7034 ssid->export_keys = 1;
7035 if (params->psk_set) {
7036 os_memcpy(ssid->psk, params->psk, 32);
7037 ssid->psk_set = 1;
7038 }
7039 if (params->passphrase)
7040 ssid->passphrase = os_strdup(params->passphrase);
7041
Matthew Wang124e5f42022-12-29 07:23:06 +00007042 if (force_go_bssid && params->bssid_set) {
Matthew Wangdcf19452022-11-07 20:42:52 -08007043 ssid->bssid_set = 1;
7044 os_memcpy(ssid->bssid, params->bssid, ETH_ALEN);
7045 }
7046
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007047 wpa_s->show_group_started = 1;
Dmitry Shmidt15907092014-03-25 10:42:57 -07007048 wpa_s->p2p_in_invitation = 1;
Matthew Wang06b42472022-11-10 06:56:31 +00007049 wpa_s->p2p_retry_limit = retry_limit;
Dmitry Shmidt15907092014-03-25 10:42:57 -07007050 wpa_s->p2p_invite_go_freq = freq;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007051 wpa_s->p2p_go_group_formation_completed = 0;
7052 wpa_s->global->p2p_group_formation = wpa_s;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007053
Matthew Wang9ae940b2022-09-14 21:25:34 -07007054 /*
7055 * Get latest scan results from driver in case cached scan results from
7056 * interfaces on the same wiphy allow us to skip the next scan by fast
7057 * associating. Also update the scan time to the most recent scan result
7058 * fetch time on the same radio so it reflects the actual time the last
7059 * scan result event occurred.
7060 */
7061 wpa_supplicant_update_scan_results(wpa_s);
7062 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
7063 radio_list) {
7064 if (ifs == wpa_s)
7065 continue;
7066 if (!other_iface_found || os_reltime_before(&wpa_s->last_scan,
7067 &ifs->last_scan)) {
7068 other_iface_found = 1;
7069 wpa_s->last_scan.sec = ifs->last_scan.sec;
7070 wpa_s->last_scan.usec = ifs->last_scan.usec;
7071 }
7072 }
7073
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007074 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev,
Dmitry Shmidt15907092014-03-25 10:42:57 -07007075 NULL);
7076 eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
7077 wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007078 wpa_s->p2pdev, NULL);
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08007079 wpa_supplicant_select_network(wpa_s, ssid);
7080
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007081 return 0;
7082}
7083
7084
7085int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
7086 struct wpa_ssid *ssid, int addr_allocated,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007087 int force_freq, int neg_freq,
7088 int vht_center_freq2, int ht40,
Hai Shalom74f70d42019-02-11 14:42:39 -08007089 int vht, int max_oper_chwidth, int he,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007090 int edmg,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007091 const struct p2p_channels *channels,
Hai Shalomc1a21442022-02-04 13:43:00 -08007092 int connection_timeout, int force_scan,
Matthew Wang124e5f42022-12-29 07:23:06 +00007093 bool allow_6ghz, int retry_limit,
7094 bool force_go_bssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007095{
7096 struct p2p_go_neg_results params;
Dmitry Shmidt96be6222014-02-13 10:16:51 -08007097 int go = 0, freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007098
7099 if (ssid->disabled != 2 || ssid->ssid == NULL)
7100 return -1;
7101
7102 if (wpas_get_p2p_group(wpa_s, ssid->ssid, ssid->ssid_len, &go) &&
7103 go == (ssid->mode == WPAS_MODE_P2P_GO)) {
7104 wpa_printf(MSG_DEBUG, "P2P: Requested persistent group is "
7105 "already running");
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07007106 if (go == 0 &&
7107 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007108 wpa_s->p2pdev, NULL)) {
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07007109 /*
7110 * This can happen if Invitation Response frame was lost
7111 * and the peer (GO of a persistent group) tries to
7112 * invite us again. Reschedule the timeout to avoid
7113 * terminating the wait for the connection too early
7114 * since we now know that the peer is still trying to
7115 * invite us instead of having already started the GO.
7116 */
7117 wpa_printf(MSG_DEBUG,
7118 "P2P: Reschedule group formation timeout since peer is still trying to invite us");
7119 eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
7120 wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007121 wpa_s->p2pdev, NULL);
Dmitry Shmidtb1e52102015-05-29 12:36:29 -07007122 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007123 return 0;
7124 }
7125
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07007126 os_free(wpa_s->global->add_psk);
7127 wpa_s->global->add_psk = NULL;
7128
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007129 /* Make sure we are not running find during connection establishment */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007130 wpas_p2p_stop_find_oper(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007131
Dmitry Shmidt04949592012-07-19 12:16:46 -07007132 wpa_s->p2p_fallback_to_go_neg = 0;
7133
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007134 if (ssid->mode == WPAS_MODE_P2P_GO) {
7135 if (force_freq > 0) {
7136 freq = wpas_p2p_select_go_freq(wpa_s, force_freq);
7137 if (freq < 0)
7138 return -1;
Sunil Ravi77a0f092022-10-03 00:53:41 +00007139 wpa_s->p2p_go_no_pri_sec_switch = 1;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007140 } else {
7141 freq = wpas_p2p_select_go_freq(wpa_s, neg_freq);
7142 if (freq < 0 ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007143 (freq > 0 && !freq_included(wpa_s, channels, freq)))
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007144 freq = 0;
7145 }
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007146 } else if (ssid->mode == WPAS_MODE_INFRA) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007147 freq = neg_freq;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007148 if (freq <= 0 || !freq_included(wpa_s, channels, freq)) {
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007149 struct os_reltime now;
7150 struct wpa_bss *bss =
7151 wpa_bss_get_p2p_dev_addr(wpa_s, ssid->bssid);
Dmitry Shmidt8bae4132013-06-06 11:25:10 -07007152
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007153 os_get_reltime(&now);
7154 if (bss &&
7155 !os_reltime_expired(&now, &bss->last_update, 5) &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007156 freq_included(wpa_s, channels, bss->freq))
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007157 freq = bss->freq;
7158 else
7159 freq = 0;
7160 }
7161
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007162 return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq,
Matthew Wang124e5f42022-12-29 07:23:06 +00007163 force_scan, retry_limit,
7164 force_go_bssid);
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007165 } else {
Dmitry Shmidt15907092014-03-25 10:42:57 -07007166 return -1;
Dmitry Shmidt912c6ec2015-03-30 13:16:51 -07007167 }
Dmitry Shmidt15907092014-03-25 10:42:57 -07007168
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007169 if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007170 ht40, vht, max_oper_chwidth, he, edmg,
7171 channels))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007172 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007173
7174 params.role_go = 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007175 params.psk_set = ssid->psk_set;
7176 if (params.psk_set)
7177 os_memcpy(params.psk, ssid->psk, sizeof(params.psk));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007178 if (ssid->passphrase) {
7179 if (os_strlen(ssid->passphrase) >= sizeof(params.passphrase)) {
7180 wpa_printf(MSG_ERROR, "P2P: Invalid passphrase in "
7181 "persistent group");
7182 return -1;
7183 }
7184 os_strlcpy(params.passphrase, ssid->passphrase,
7185 sizeof(params.passphrase));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007186 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007187 os_memcpy(params.ssid, ssid->ssid, ssid->ssid_len);
7188 params.ssid_len = ssid->ssid_len;
7189 params.persistent_group = 1;
7190
7191 wpa_s = wpas_p2p_get_group_iface(wpa_s, addr_allocated, 1);
7192 if (wpa_s == NULL)
7193 return -1;
7194
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007195 p2p_channels_to_freqs(channels, params.freq_list, P2P_MAX_CHANNELS);
7196
Dmitry Shmidt56052862013-10-04 10:23:25 -07007197 wpa_s->p2p_first_connection_timeout = connection_timeout;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007198 wpas_start_wps_go(wpa_s, &params, 0);
7199
7200 return 0;
7201}
7202
7203
7204static void wpas_p2p_ie_update(void *ctx, struct wpabuf *beacon_ies,
7205 struct wpabuf *proberesp_ies)
7206{
7207 struct wpa_supplicant *wpa_s = ctx;
7208 if (wpa_s->ap_iface) {
7209 struct hostapd_data *hapd = wpa_s->ap_iface->bss[0];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007210 if (!(hapd->conf->p2p & P2P_GROUP_OWNER)) {
7211 wpabuf_free(beacon_ies);
7212 wpabuf_free(proberesp_ies);
7213 return;
7214 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007215 if (beacon_ies) {
7216 wpabuf_free(hapd->p2p_beacon_ie);
7217 hapd->p2p_beacon_ie = beacon_ies;
7218 }
7219 wpabuf_free(hapd->p2p_probe_resp_ie);
7220 hapd->p2p_probe_resp_ie = proberesp_ies;
7221 } else {
7222 wpabuf_free(beacon_ies);
7223 wpabuf_free(proberesp_ies);
7224 }
7225 wpa_supplicant_ap_update_beacon(wpa_s);
7226}
7227
7228
7229static void wpas_p2p_idle_update(void *ctx, int idle)
7230{
7231 struct wpa_supplicant *wpa_s = ctx;
7232 if (!wpa_s->ap_iface)
7233 return;
7234 wpa_printf(MSG_DEBUG, "P2P: GO - group %sidle", idle ? "" : "not ");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007235 if (idle) {
7236 if (wpa_s->global->p2p_fail_on_wps_complete &&
7237 wpa_s->p2p_in_provisioning) {
7238 wpas_p2p_grpform_fail_after_wps(wpa_s);
7239 return;
7240 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007241 wpas_p2p_set_group_idle_timeout(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007242 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007243 eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL);
7244}
7245
7246
7247struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
Dmitry Shmidt04949592012-07-19 12:16:46 -07007248 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007249{
7250 struct p2p_group *group;
7251 struct p2p_group_config *cfg;
7252
Dmitry Shmidt849734c2016-05-27 09:59:01 -07007253 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
7254 !ssid->p2p_group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007255 return NULL;
7256
7257 cfg = os_zalloc(sizeof(*cfg));
7258 if (cfg == NULL)
7259 return NULL;
7260
Dmitry Shmidt04949592012-07-19 12:16:46 -07007261 if (ssid->p2p_persistent_group && wpa_s->conf->persistent_reconnect)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007262 cfg->persistent_group = 2;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007263 else if (ssid->p2p_persistent_group)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007264 cfg->persistent_group = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007265 os_memcpy(cfg->interface_addr, wpa_s->own_addr, ETH_ALEN);
7266 if (wpa_s->max_stations &&
7267 wpa_s->max_stations < wpa_s->conf->max_num_sta)
7268 cfg->max_clients = wpa_s->max_stations;
7269 else
7270 cfg->max_clients = wpa_s->conf->max_num_sta;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007271 os_memcpy(cfg->ssid, ssid->ssid, ssid->ssid_len);
7272 cfg->ssid_len = ssid->ssid_len;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007273 cfg->freq = ssid->frequency;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007274 cfg->cb_ctx = wpa_s;
7275 cfg->ie_update = wpas_p2p_ie_update;
7276 cfg->idle_update = wpas_p2p_idle_update;
Dmitry Shmidte4663042016-04-04 10:07:49 -07007277 cfg->ip_addr_alloc = WPA_GET_BE32(wpa_s->p2pdev->conf->ip_addr_start)
7278 != 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007279
7280 group = p2p_group_init(wpa_s->global->p2p, cfg);
7281 if (group == NULL)
7282 os_free(cfg);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007283 if (ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007284 p2p_group_notif_formation_done(group);
7285 wpa_s->p2p_group = group;
7286 return group;
7287}
7288
7289
7290void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
7291 int registrar)
7292{
Dmitry Shmidt04949592012-07-19 12:16:46 -07007293 struct wpa_ssid *ssid = wpa_s->current_ssid;
7294
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007295 if (!wpa_s->p2p_in_provisioning) {
7296 wpa_printf(MSG_DEBUG, "P2P: Ignore WPS success event - P2P "
7297 "provisioning not in progress");
7298 return;
7299 }
7300
Dmitry Shmidt04949592012-07-19 12:16:46 -07007301 if (ssid && ssid->mode == WPAS_MODE_INFRA) {
7302 u8 go_dev_addr[ETH_ALEN];
7303 os_memcpy(go_dev_addr, wpa_s->bssid, ETH_ALEN);
7304 wpas_p2p_persistent_group(wpa_s, go_dev_addr, ssid->ssid,
7305 ssid->ssid_len);
7306 /* Clear any stored provisioning info */
7307 p2p_clear_provisioning_info(wpa_s->global->p2p, go_dev_addr);
7308 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007309
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007310 eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007311 NULL);
Dmitry Shmidt56052862013-10-04 10:23:25 -07007312 wpa_s->p2p_go_group_formation_completed = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007313 if (ssid && ssid->mode == WPAS_MODE_INFRA) {
7314 /*
7315 * Use a separate timeout for initial data connection to
7316 * complete to allow the group to be removed automatically if
7317 * something goes wrong in this step before the P2P group idle
7318 * timeout mechanism is taken into use.
7319 */
Dmitry Shmidt56052862013-10-04 10:23:25 -07007320 wpa_dbg(wpa_s, MSG_DEBUG,
7321 "P2P: Re-start group formation timeout (%d seconds) as client for initial connection",
7322 P2P_MAX_INITIAL_CONN_WAIT);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007323 eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
7324 wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007325 wpa_s->p2pdev, NULL);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007326 /* Complete group formation on successful data connection. */
7327 wpa_s->p2p_go_group_formation_completed = 0;
Dmitry Shmidt56052862013-10-04 10:23:25 -07007328 } else if (ssid) {
7329 /*
7330 * Use a separate timeout for initial data connection to
7331 * complete to allow the group to be removed automatically if
7332 * the client does not complete data connection successfully.
7333 */
7334 wpa_dbg(wpa_s, MSG_DEBUG,
7335 "P2P: Re-start group formation timeout (%d seconds) as GO for initial connection",
7336 P2P_MAX_INITIAL_CONN_WAIT_GO);
7337 eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT_GO, 0,
7338 wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007339 wpa_s->p2pdev, NULL);
Dmitry Shmidt56052862013-10-04 10:23:25 -07007340 /*
7341 * Complete group formation on first successful data connection
7342 */
7343 wpa_s->p2p_go_group_formation_completed = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007344 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007345 if (wpa_s->global->p2p)
7346 p2p_wps_success_cb(wpa_s->global->p2p, peer_addr);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007347 wpas_group_formation_completed(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007348}
7349
7350
Jouni Malinen75ecf522011-06-27 15:19:46 -07007351void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
7352 struct wps_event_fail *fail)
7353{
7354 if (!wpa_s->p2p_in_provisioning) {
7355 wpa_printf(MSG_DEBUG, "P2P: Ignore WPS fail event - P2P "
7356 "provisioning not in progress");
7357 return;
7358 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007359
7360 if (wpa_s->go_params) {
7361 p2p_clear_provisioning_info(
7362 wpa_s->global->p2p,
Dmitry Shmidt04949592012-07-19 12:16:46 -07007363 wpa_s->go_params->peer_device_addr);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007364 }
7365
Jouni Malinen75ecf522011-06-27 15:19:46 -07007366 wpas_notify_p2p_wps_failed(wpa_s, fail);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007367
7368 if (wpa_s == wpa_s->global->p2p_group_formation) {
7369 /*
7370 * Allow some time for the failed WPS negotiation exchange to
7371 * complete, but remove the group since group formation cannot
7372 * succeed after provisioning failure.
7373 */
7374 wpa_printf(MSG_DEBUG, "P2P: WPS step failed during group formation - reject connection from timeout");
7375 wpa_s->global->p2p_fail_on_wps_complete = 1;
7376 eloop_deplete_timeout(0, 50000,
7377 wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007378 wpa_s->p2pdev, NULL);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007379 }
7380}
7381
7382
7383int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s)
7384{
7385 if (!wpa_s->global->p2p_fail_on_wps_complete ||
7386 !wpa_s->p2p_in_provisioning)
7387 return 0;
7388
7389 wpas_p2p_grpform_fail_after_wps(wpa_s);
7390
7391 return 1;
Jouni Malinen75ecf522011-06-27 15:19:46 -07007392}
7393
7394
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007395int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
Dmitry Shmidt04949592012-07-19 12:16:46 -07007396 const char *config_method,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007397 enum wpas_p2p_prov_disc_use use,
7398 struct p2ps_provision *p2ps_prov)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007399{
7400 u16 config_methods;
7401
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007402 wpa_s->global->pending_p2ps_group = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007403 wpa_s->global->pending_p2ps_group_freq = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07007404 wpa_s->p2p_fallback_to_go_neg = 0;
7405 wpa_s->pending_pd_use = NORMAL_PD;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007406 if (p2ps_prov && use == WPAS_P2P_PD_FOR_ASP) {
7407 p2ps_prov->conncap = p2ps_group_capability(
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007408 wpa_s, P2PS_SETUP_NONE, p2ps_prov->role,
7409 &p2ps_prov->force_freq, &p2ps_prov->pref_freq);
7410
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007411 wpa_printf(MSG_DEBUG,
7412 "P2P: %s conncap: %d - ASP parsed: %x %x %d %s",
7413 __func__, p2ps_prov->conncap,
7414 p2ps_prov->adv_id, p2ps_prov->conncap,
7415 p2ps_prov->status, p2ps_prov->info);
7416
7417 config_methods = 0;
7418 } else if (os_strncmp(config_method, "display", 7) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007419 config_methods = WPS_CONFIG_DISPLAY;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007420 else if (os_strncmp(config_method, "keypad", 6) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007421 config_methods = WPS_CONFIG_KEYPAD;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007422 else if (os_strncmp(config_method, "pbc", 3) == 0 ||
7423 os_strncmp(config_method, "pushbutton", 10) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007424 config_methods = WPS_CONFIG_PUSHBUTTON;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007425 else {
7426 wpa_printf(MSG_DEBUG, "P2P: Unknown config method");
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007427 os_free(p2ps_prov);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007428 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007429 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007430
Dmitry Shmidt04949592012-07-19 12:16:46 -07007431 if (use == WPAS_P2P_PD_AUTO) {
7432 os_memcpy(wpa_s->pending_join_dev_addr, peer_addr, ETH_ALEN);
7433 wpa_s->pending_pd_config_methods = config_methods;
7434 wpa_s->p2p_auto_pd = 1;
7435 wpa_s->p2p_auto_join = 0;
7436 wpa_s->pending_pd_before_join = 0;
7437 wpa_s->auto_pd_scan_retry = 0;
7438 wpas_p2p_stop_find(wpa_s);
7439 wpa_s->p2p_join_scan_count = 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007440 os_get_reltime(&wpa_s->p2p_auto_started);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007441 wpa_printf(MSG_DEBUG, "P2P: Auto PD started at %ld.%06ld",
7442 wpa_s->p2p_auto_started.sec,
7443 wpa_s->p2p_auto_started.usec);
7444 wpas_p2p_join_scan(wpa_s, NULL);
7445 return 0;
7446 }
7447
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007448 if (wpa_s->global->p2p == NULL || wpa_s->global->p2p_disabled) {
7449 os_free(p2ps_prov);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007450 return -1;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007451 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007452
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007453 return p2p_prov_disc_req(wpa_s->global->p2p, peer_addr, p2ps_prov,
Dmitry Shmidt04949592012-07-19 12:16:46 -07007454 config_methods, use == WPAS_P2P_PD_FOR_JOIN,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007455 0, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007456}
7457
7458
7459int wpas_p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
7460 char *end)
7461{
7462 return p2p_scan_result_text(ies, ies_len, buf, end);
7463}
7464
7465
7466static void wpas_p2p_clear_pending_action_tx(struct wpa_supplicant *wpa_s)
7467{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007468 if (!offchannel_pending_action_tx(wpa_s))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007469 return;
7470
Dmitry Shmidtde47be72016-01-07 12:52:55 -08007471 if (wpa_s->p2p_send_action_work) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007472 wpas_p2p_free_send_action_work(wpa_s);
Dmitry Shmidtde47be72016-01-07 12:52:55 -08007473 eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
7474 wpa_s, NULL);
7475 offchannel_send_action_done(wpa_s);
7476 }
Dmitry Shmidt03658832014-08-13 11:03:49 -07007477
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007478 wpa_printf(MSG_DEBUG, "P2P: Drop pending Action TX due to new "
7479 "operation request");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08007480 offchannel_clear_pending_action_tx(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007481}
7482
7483
7484int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout,
7485 enum p2p_discovery_type type,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007486 unsigned int num_req_dev_types, const u8 *req_dev_types,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007487 const u8 *dev_id, unsigned int search_delay,
Hai Shalomc1a21442022-02-04 13:43:00 -08007488 u8 seek_cnt, const char **seek_string, int freq,
7489 bool include_6ghz)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007490{
7491 wpas_p2p_clear_pending_action_tx(wpa_s);
Hai Shalomfdcde762020-04-02 11:19:20 -07007492 wpa_s->global->p2p_long_listen = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007493
Dmitry Shmidt04949592012-07-19 12:16:46 -07007494 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007495 wpa_s->p2p_in_provisioning) {
7496 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Reject p2p_find operation%s%s",
7497 (wpa_s->global->p2p_disabled || !wpa_s->global->p2p) ?
7498 " (P2P disabled)" : "",
7499 wpa_s->p2p_in_provisioning ?
7500 " (p2p_in_provisioning)" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007501 return -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07007502 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007503
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007504 wpa_supplicant_cancel_sched_scan(wpa_s);
7505
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007506 return p2p_find(wpa_s->global->p2p, timeout, type,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07007507 num_req_dev_types, req_dev_types, dev_id,
Hai Shalomc1a21442022-02-04 13:43:00 -08007508 search_delay, seek_cnt, seek_string, freq,
7509 include_6ghz);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007510}
7511
7512
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007513static void wpas_p2p_scan_res_ignore_search(struct wpa_supplicant *wpa_s,
7514 struct wpa_scan_results *scan_res)
7515{
7516 wpa_printf(MSG_DEBUG, "P2P: Ignore scan results");
7517
7518 if (wpa_s->p2p_scan_work) {
7519 struct wpa_radio_work *work = wpa_s->p2p_scan_work;
7520 wpa_s->p2p_scan_work = NULL;
7521 radio_work_done(work);
7522 }
7523
7524 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
7525 return;
7526
7527 /*
7528 * Indicate that results have been processed so that the P2P module can
7529 * continue pending tasks.
7530 */
Hai Shalom60840252021-02-19 19:02:11 -08007531 wpas_p2p_scan_res_handled(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007532}
7533
7534
7535static void wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007536{
7537 wpas_p2p_clear_pending_action_tx(wpa_s);
Hai Shalomfdcde762020-04-02 11:19:20 -07007538 wpa_s->global->p2p_long_listen = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007539 eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
7540 eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007541
7542 if (wpa_s->global->p2p)
7543 p2p_stop_find(wpa_s->global->p2p);
7544
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007545 if (wpa_s->scan_res_handler == wpas_p2p_scan_res_handler) {
7546 wpa_printf(MSG_DEBUG,
7547 "P2P: Do not consider the scan results after stop_find");
7548 wpa_s->scan_res_handler = wpas_p2p_scan_res_ignore_search;
7549 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08007550}
7551
7552
7553void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s)
7554{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007555 wpas_p2p_stop_find_oper(wpa_s);
Dmitry Shmidt216983b2015-02-06 10:50:36 -08007556 if (!wpa_s->global->pending_group_iface_for_p2ps)
7557 wpas_p2p_remove_pending_group_interface(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007558}
7559
7560
7561static void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx)
7562{
7563 struct wpa_supplicant *wpa_s = eloop_ctx;
Hai Shalomfdcde762020-04-02 11:19:20 -07007564 wpa_s->global->p2p_long_listen = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007565}
7566
7567
7568int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout)
7569{
7570 int res;
7571
7572 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
7573 return -1;
7574
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07007575 if (wpa_s->p2p_lo_started) {
7576 wpa_printf(MSG_DEBUG,
7577 "P2P: Cannot start P2P listen, it is offloaded");
7578 return -1;
7579 }
7580
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007581 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007582 wpas_p2p_clear_pending_action_tx(wpa_s);
7583
7584 if (timeout == 0) {
7585 /*
7586 * This is a request for unlimited Listen state. However, at
7587 * least for now, this is mapped to a Listen state for one
7588 * hour.
7589 */
7590 timeout = 3600;
7591 }
7592 eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07007593 wpa_s->global->p2p_long_listen = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007594
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007595 /*
7596 * Stop previous find/listen operation to avoid trying to request a new
7597 * remain-on-channel operation while the driver is still running the
7598 * previous one.
7599 */
7600 if (wpa_s->global->p2p)
7601 p2p_stop_find(wpa_s->global->p2p);
7602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007603 res = wpas_p2p_listen_start(wpa_s, timeout * 1000);
7604 if (res == 0 && timeout * 1000 > wpa_s->max_remain_on_chan) {
Hai Shalomfdcde762020-04-02 11:19:20 -07007605 wpa_s->global->p2p_long_listen = timeout * 1000;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007606 eloop_register_timeout(timeout, 0,
7607 wpas_p2p_long_listen_timeout,
7608 wpa_s, NULL);
7609 }
7610
7611 return res;
7612}
7613
7614
7615int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
7616 u8 *buf, size_t len, int p2p_group)
7617{
7618 struct wpabuf *p2p_ie;
7619 int ret;
7620
7621 if (wpa_s->global->p2p_disabled)
7622 return -1;
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07007623 /*
7624 * Advertize mandatory cross connection capability even on
7625 * p2p_disabled=1 interface when associating with a P2P Manager WLAN AP.
7626 */
7627 if (wpa_s->conf->p2p_disabled && p2p_group)
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07007628 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007629 if (wpa_s->global->p2p == NULL)
7630 return -1;
7631 if (bss == NULL)
7632 return -1;
7633
7634 p2p_ie = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
7635 ret = p2p_assoc_req_ie(wpa_s->global->p2p, bss->bssid, buf, len,
7636 p2p_group, p2p_ie);
7637 wpabuf_free(p2p_ie);
7638
7639 return ret;
7640}
7641
7642
7643int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007644 const u8 *dst, const u8 *bssid,
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07007645 const u8 *ie, size_t ie_len,
7646 unsigned int rx_freq, int ssi_signal)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007647{
7648 if (wpa_s->global->p2p_disabled)
7649 return 0;
7650 if (wpa_s->global->p2p == NULL)
7651 return 0;
7652
Dmitry Shmidt04949592012-07-19 12:16:46 -07007653 switch (p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid,
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07007654 ie, ie_len, rx_freq, wpa_s->p2p_lo_started)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07007655 case P2P_PREQ_NOT_P2P:
7656 wpas_notify_preq(wpa_s, addr, dst, bssid, ie, ie_len,
7657 ssi_signal);
7658 /* fall through */
7659 case P2P_PREQ_MALFORMED:
7660 case P2P_PREQ_NOT_LISTEN:
7661 case P2P_PREQ_NOT_PROCESSED:
7662 default: /* make gcc happy */
7663 return 0;
7664 case P2P_PREQ_PROCESSED:
7665 return 1;
7666 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007667}
7668
7669
7670void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
7671 const u8 *sa, const u8 *bssid,
7672 u8 category, const u8 *data, size_t len, int freq)
7673{
7674 if (wpa_s->global->p2p_disabled)
7675 return;
7676 if (wpa_s->global->p2p == NULL)
7677 return;
7678
7679 p2p_rx_action(wpa_s->global->p2p, da, sa, bssid, category, data, len,
7680 freq);
7681}
7682
7683
7684void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies)
7685{
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007686 unsigned int bands;
7687
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007688 if (wpa_s->global->p2p_disabled)
7689 return;
7690 if (wpa_s->global->p2p == NULL)
7691 return;
7692
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007693 bands = wpas_get_bands(wpa_s, NULL);
7694 p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007695}
7696
7697
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07007698static void wpas_p2p_group_deinit(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007699{
7700 p2p_group_deinit(wpa_s->p2p_group);
7701 wpa_s->p2p_group = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007702
7703 wpa_s->ap_configured_cb = NULL;
7704 wpa_s->ap_configured_cb_ctx = NULL;
7705 wpa_s->ap_configured_cb_data = NULL;
7706 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007707}
7708
7709
7710int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
7711{
Hai Shalomfdcde762020-04-02 11:19:20 -07007712 wpa_s->global->p2p_long_listen = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007713
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007714 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
7715 return -1;
7716
7717 return p2p_reject(wpa_s->global->p2p, addr);
7718}
7719
7720
7721/* Invite to reinvoke a persistent group */
7722int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
Jouni Malinen31be0a42012-08-31 21:20:51 +03007723 struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007724 int vht_center_freq2, int ht40, int vht, int max_chwidth,
Hai Shalomc1a21442022-02-04 13:43:00 -08007725 int pref_freq, int he, int edmg, bool allow_6ghz)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007726{
7727 enum p2p_invite_role role;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007728 u8 *bssid = NULL;
7729 int force_freq = 0;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007730 int res;
Dmitry Shmidta0d265f2013-11-19 13:13:41 -08007731 int no_pref_freq_given = pref_freq == 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00007732 struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
7733 unsigned int size;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007734
Hai Shalomc1a21442022-02-04 13:43:00 -08007735 if (wpas_p2p_check_6ghz(wpa_s, NULL, allow_6ghz, freq))
7736 return -1;
7737
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007738 wpa_s->global->p2p_invite_group = NULL;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007739 if (peer_addr)
7740 os_memcpy(wpa_s->p2p_auth_invite, peer_addr, ETH_ALEN);
7741 else
7742 os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007743
Jouni Malinen31be0a42012-08-31 21:20:51 +03007744 wpa_s->p2p_persistent_go_freq = freq;
7745 wpa_s->p2p_go_ht40 = !!ht40;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007746 wpa_s->p2p_go_vht = !!vht;
Hai Shalom74f70d42019-02-11 14:42:39 -08007747 wpa_s->p2p_go_he = !!he;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007748 wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
7749 wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007750 wpa_s->p2p_go_edmg = !!edmg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007751 if (ssid->mode == WPAS_MODE_P2P_GO) {
7752 role = P2P_INVITE_ROLE_GO;
7753 if (peer_addr == NULL) {
7754 wpa_printf(MSG_DEBUG, "P2P: Missing peer "
7755 "address in invitation command");
7756 return -1;
7757 }
7758 if (wpas_p2p_create_iface(wpa_s)) {
7759 if (wpas_p2p_add_group_interface(wpa_s,
7760 WPA_IF_P2P_GO) < 0) {
7761 wpa_printf(MSG_ERROR, "P2P: Failed to "
7762 "allocate a new interface for the "
7763 "group");
7764 return -1;
7765 }
7766 bssid = wpa_s->pending_interface_addr;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007767 } else if (wpa_s->p2p_mgmt)
7768 bssid = wpa_s->parent->own_addr;
7769 else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007770 bssid = wpa_s->own_addr;
7771 } else {
7772 role = P2P_INVITE_ROLE_CLIENT;
7773 peer_addr = ssid->bssid;
7774 }
7775 wpa_s->pending_invite_ssid_id = ssid->id;
7776
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007777 size = P2P_MAX_PREF_CHANNELS;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007778 res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007779 role == P2P_INVITE_ROLE_GO,
7780 pref_freq_list, &size);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007781 if (res)
7782 return res;
Irfan Sheriffaf84a572012-09-22 16:59:30 -07007783
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007784 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
7785 return -1;
7786
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08007787 p2p_set_own_pref_freq_list(wpa_s->global->p2p, pref_freq_list, size);
7788
Dmitry Shmidta0d265f2013-11-19 13:13:41 -08007789 if (wpa_s->parent->conf->p2p_ignore_shared_freq &&
7790 no_pref_freq_given && pref_freq > 0 &&
7791 wpa_s->num_multichan_concurrent > 1 &&
7792 wpas_p2p_num_unused_channels(wpa_s) > 0) {
7793 wpa_printf(MSG_DEBUG, "P2P: Ignore own channel preference %d MHz for invitation due to p2p_ignore_shared_freq=1 configuration",
7794 pref_freq);
7795 pref_freq = 0;
7796 }
7797
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08007798 /*
7799 * Stop any find/listen operations before invitation and possibly
7800 * connection establishment.
7801 */
7802 wpas_p2p_stop_find_oper(wpa_s);
7803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007804 return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007805 ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007806 1, pref_freq, -1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007807}
7808
7809
7810/* Invite to join an active group */
7811int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
Hai Shalomc1a21442022-02-04 13:43:00 -08007812 const u8 *peer_addr, const u8 *go_dev_addr,
7813 bool allow_6ghz)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007814{
7815 struct wpa_global *global = wpa_s->global;
7816 enum p2p_invite_role role;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007817 u8 *bssid = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007818 struct wpa_ssid *ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007819 int persistent;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007820 int freq = 0, force_freq = 0, pref_freq = 0;
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007821 int res;
Sunil8cd6f4d2022-06-28 18:40:46 +00007822 struct weighted_pcl pref_freq_list[P2P_MAX_PREF_CHANNELS];
7823 unsigned int size;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007824
Jouni Malinen31be0a42012-08-31 21:20:51 +03007825 wpa_s->p2p_persistent_go_freq = 0;
7826 wpa_s->p2p_go_ht40 = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007827 wpa_s->p2p_go_vht = 0;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007828 wpa_s->p2p_go_vht_center_freq2 = 0;
7829 wpa_s->p2p_go_max_oper_chwidth = 0;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08007830 wpa_s->p2p_go_edmg = 0;
Jouni Malinen31be0a42012-08-31 21:20:51 +03007831
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007832 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
7833 if (os_strcmp(wpa_s->ifname, ifname) == 0)
7834 break;
7835 }
7836 if (wpa_s == NULL) {
7837 wpa_printf(MSG_DEBUG, "P2P: Interface '%s' not found", ifname);
7838 return -1;
7839 }
7840
7841 ssid = wpa_s->current_ssid;
7842 if (ssid == NULL) {
7843 wpa_printf(MSG_DEBUG, "P2P: No current SSID to use for "
7844 "invitation");
7845 return -1;
7846 }
7847
Dmitry Shmidt700a1372013-03-15 14:14:44 -07007848 wpa_s->global->p2p_invite_group = wpa_s;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007849 persistent = ssid->p2p_persistent_group &&
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007850 wpas_p2p_get_persistent(wpa_s->p2pdev, peer_addr,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08007851 ssid->ssid, ssid->ssid_len);
7852
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007853 if (ssid->mode == WPAS_MODE_P2P_GO) {
7854 role = P2P_INVITE_ROLE_ACTIVE_GO;
7855 bssid = wpa_s->own_addr;
7856 if (go_dev_addr == NULL)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007857 go_dev_addr = wpa_s->global->p2p_dev_addr;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007858 freq = ssid->frequency;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007859 } else {
7860 role = P2P_INVITE_ROLE_CLIENT;
7861 if (wpa_s->wpa_state < WPA_ASSOCIATED) {
7862 wpa_printf(MSG_DEBUG, "P2P: Not associated - cannot "
7863 "invite to current group");
7864 return -1;
7865 }
7866 bssid = wpa_s->bssid;
7867 if (go_dev_addr == NULL &&
7868 !is_zero_ether_addr(wpa_s->go_dev_addr))
7869 go_dev_addr = wpa_s->go_dev_addr;
Dmitry Shmidt051af732013-10-22 13:52:46 -07007870 freq = wpa_s->current_bss ? wpa_s->current_bss->freq :
7871 (int) wpa_s->assoc_freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007872 }
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007873 wpa_s->p2pdev->pending_invite_ssid_id = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007874
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007875 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
7876 return -1;
Hai Shalomc1a21442022-02-04 13:43:00 -08007877 if (wpas_p2p_check_6ghz(wpa_s, peer_addr, allow_6ghz, freq))
7878 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007879
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007880 size = P2P_MAX_PREF_CHANNELS;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07007881 res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08007882 role == P2P_INVITE_ROLE_ACTIVE_GO,
7883 pref_freq_list, &size);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007884 if (res)
7885 return res;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07007886 wpas_p2p_set_own_freq_preference(wpa_s, force_freq);
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007888 return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
Dmitry Shmidt7a5e50a2013-03-05 12:37:16 -08007889 ssid->ssid, ssid->ssid_len, force_freq,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007890 go_dev_addr, persistent, pref_freq, -1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007891}
7892
7893
7894void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
7895{
7896 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007897 u8 go_dev_addr[ETH_ALEN];
7898 int persistent;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007899 int freq;
Hai Shalom5f92bc92019-04-18 11:54:11 -07007900 u8 ip[3 * 4], *ip_ptr = NULL;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007901 char ip_addr[100];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007902
Dmitry Shmidt04949592012-07-19 12:16:46 -07007903 if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) {
7904 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08007905 wpa_s->p2pdev, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07007906 }
7907
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007908 if (!wpa_s->show_group_started || !ssid)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007909 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007910
7911 wpa_s->show_group_started = 0;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007912 if (!wpa_s->p2p_go_group_formation_completed &&
7913 wpa_s->global->p2p_group_formation == wpa_s) {
7914 wpa_dbg(wpa_s, MSG_DEBUG,
7915 "P2P: Marking group formation completed on client on data connection");
7916 wpa_s->p2p_go_group_formation_completed = 1;
7917 wpa_s->global->p2p_group_formation = NULL;
7918 wpa_s->p2p_in_provisioning = 0;
7919 wpa_s->p2p_in_invitation = 0;
Matthew Wang06b42472022-11-10 06:56:31 +00007920 wpa_s->p2p_retry_limit = 0;
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08007921 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007922
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007923 os_memset(go_dev_addr, 0, ETH_ALEN);
7924 if (ssid->bssid_set)
7925 os_memcpy(go_dev_addr, ssid->bssid, ETH_ALEN);
7926 persistent = wpas_p2p_persistent_group(wpa_s, go_dev_addr, ssid->ssid,
7927 ssid->ssid_len);
7928 os_memcpy(wpa_s->go_dev_addr, go_dev_addr, ETH_ALEN);
7929
7930 if (wpa_s->global->p2p_group_formation == wpa_s)
7931 wpa_s->global->p2p_group_formation = NULL;
7932
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007933 freq = wpa_s->current_bss ? wpa_s->current_bss->freq :
7934 (int) wpa_s->assoc_freq;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007935
7936 ip_addr[0] = '\0';
7937 if (wpa_sm_get_p2p_ip_addr(wpa_s->wpa, ip) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08007938 int res;
7939
7940 res = os_snprintf(ip_addr, sizeof(ip_addr),
7941 " ip_addr=%u.%u.%u.%u "
7942 "ip_mask=%u.%u.%u.%u go_ip_addr=%u.%u.%u.%u",
7943 ip[0], ip[1], ip[2], ip[3],
7944 ip[4], ip[5], ip[6], ip[7],
7945 ip[8], ip[9], ip[10], ip[11]);
7946 if (os_snprintf_error(sizeof(ip_addr), res))
7947 ip_addr[0] = '\0';
Hai Shalom5f92bc92019-04-18 11:54:11 -07007948 ip_ptr = ip;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08007949 }
7950
Dmitry Shmidt7f0b69e2014-07-28 10:35:20 -07007951 wpas_p2p_group_started(wpa_s, 0, ssid, freq,
7952 ssid->passphrase == NULL && ssid->psk_set ?
7953 ssid->psk : NULL,
7954 ssid->passphrase, go_dev_addr, persistent,
7955 ip_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007956
7957 if (persistent)
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07007958 wpas_p2p_store_persistent_group(wpa_s->p2pdev,
7959 ssid, go_dev_addr);
7960
Hai Shalom5f92bc92019-04-18 11:54:11 -07007961 wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1, ip_ptr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007962}
7963
7964
7965int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
7966 u32 interval1, u32 duration2, u32 interval2)
7967{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007968 int ret;
7969
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007970 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
7971 return -1;
7972
7973 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
7974 wpa_s->current_ssid == NULL ||
7975 wpa_s->current_ssid->mode != WPAS_MODE_INFRA)
7976 return -1;
7977
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08007978 ret = p2p_presence_req(wpa_s->global->p2p, wpa_s->bssid,
7979 wpa_s->own_addr, wpa_s->assoc_freq,
7980 duration1, interval1, duration2, interval2);
7981 if (ret == 0)
7982 wpa_s->waiting_presence_resp = 1;
7983
7984 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007985}
7986
7987
7988int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period,
7989 unsigned int interval)
7990{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007991 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
7992 return -1;
7993
7994 return p2p_ext_listen(wpa_s->global->p2p, period, interval);
7995}
7996
7997
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08007998static int wpas_p2p_is_client(struct wpa_supplicant *wpa_s)
7999{
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08008000 if (wpa_s->current_ssid == NULL) {
8001 /*
8002 * current_ssid can be cleared when P2P client interface gets
8003 * disconnected, so assume this interface was used as P2P
8004 * client.
8005 */
8006 return 1;
8007 }
8008 return wpa_s->current_ssid->p2p_group &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008009 wpa_s->current_ssid->mode == WPAS_MODE_INFRA;
8010}
8011
8012
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008013static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx)
8014{
8015 struct wpa_supplicant *wpa_s = eloop_ctx;
8016
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008017 if (wpa_s->conf->p2p_group_idle == 0 && !wpas_p2p_is_client(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008018 wpa_printf(MSG_DEBUG, "P2P: Ignore group idle timeout - "
8019 "disabled");
8020 return;
8021 }
8022
Dmitry Shmidt04949592012-07-19 12:16:46 -07008023 wpa_printf(MSG_DEBUG, "P2P: Group idle timeout reached - terminate "
8024 "group");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008025 wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_IDLE_TIMEOUT);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008026}
8027
8028
8029static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s)
8030{
Dmitry Shmidt04949592012-07-19 12:16:46 -07008031 int timeout;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008032
Dmitry Shmidt04949592012-07-19 12:16:46 -07008033 if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
8034 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
8035
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008036 if (wpa_s->current_ssid == NULL || !wpa_s->current_ssid->p2p_group)
8037 return;
8038
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008039 timeout = wpa_s->conf->p2p_group_idle;
8040 if (wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
8041 (timeout == 0 || timeout > P2P_MAX_CLIENT_IDLE))
8042 timeout = P2P_MAX_CLIENT_IDLE;
8043
8044 if (timeout == 0)
8045 return;
8046
Dmitry Shmidt04949592012-07-19 12:16:46 -07008047 if (timeout < 0) {
8048 if (wpa_s->current_ssid->mode == WPAS_MODE_INFRA)
8049 timeout = 0; /* special client mode no-timeout */
8050 else
8051 return;
8052 }
8053
8054 if (wpa_s->p2p_in_provisioning) {
8055 /*
8056 * Use the normal group formation timeout during the
8057 * provisioning phase to avoid terminating this process too
8058 * early due to group idle timeout.
8059 */
8060 wpa_printf(MSG_DEBUG, "P2P: Do not use P2P group idle timeout "
8061 "during provisioning");
8062 return;
8063 }
Deepthi Gowri9e4e8ac2013-04-16 11:57:05 +05308064
Dmitry Shmidt04949592012-07-19 12:16:46 -07008065 if (wpa_s->show_group_started) {
8066 /*
8067 * Use the normal group formation timeout between the end of
8068 * the provisioning phase and completion of 4-way handshake to
8069 * avoid terminating this process too early due to group idle
8070 * timeout.
8071 */
8072 wpa_printf(MSG_DEBUG, "P2P: Do not use P2P group idle timeout "
8073 "while waiting for initial 4-way handshake to "
8074 "complete");
8075 return;
8076 }
8077
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008078 wpa_printf(MSG_DEBUG, "P2P: Set P2P group idle timeout to %u seconds",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008079 timeout);
8080 eloop_register_timeout(timeout, 0, wpas_p2p_group_idle_timeout,
8081 wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008082}
8083
8084
Jouni Malinen2b89da82012-08-31 22:04:41 +03008085/* Returns 1 if the interface was removed */
8086int wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
8087 u16 reason_code, const u8 *ie, size_t ie_len,
8088 int locally_generated)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008089{
8090 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
Jouni Malinen2b89da82012-08-31 22:04:41 +03008091 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008092
Dmitry Shmidt04949592012-07-19 12:16:46 -07008093 if (!locally_generated)
8094 p2p_deauth_notif(wpa_s->global->p2p, bssid, reason_code, ie,
8095 ie_len);
8096
8097 if (reason_code == WLAN_REASON_DEAUTH_LEAVING && !locally_generated &&
8098 wpa_s->current_ssid &&
8099 wpa_s->current_ssid->p2p_group &&
8100 wpa_s->current_ssid->mode == WPAS_MODE_INFRA) {
8101 wpa_printf(MSG_DEBUG, "P2P: GO indicated that the P2P Group "
8102 "session is ending");
Jouni Malinen2b89da82012-08-31 22:04:41 +03008103 if (wpas_p2p_group_delete(wpa_s,
8104 P2P_GROUP_REMOVAL_GO_ENDING_SESSION)
8105 > 0)
8106 return 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008107 }
Jouni Malinen2b89da82012-08-31 22:04:41 +03008108
8109 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008110}
8111
8112
8113void wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid,
Dmitry Shmidt04949592012-07-19 12:16:46 -07008114 u16 reason_code, const u8 *ie, size_t ie_len,
8115 int locally_generated)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008116{
8117 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
8118 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008119
Dmitry Shmidt04949592012-07-19 12:16:46 -07008120 if (!locally_generated)
8121 p2p_disassoc_notif(wpa_s->global->p2p, bssid, reason_code, ie,
8122 ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008123}
8124
8125
8126void wpas_p2p_update_config(struct wpa_supplicant *wpa_s)
8127{
8128 struct p2p_data *p2p = wpa_s->global->p2p;
8129
8130 if (p2p == NULL)
8131 return;
8132
8133 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE))
8134 return;
8135
8136 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_NAME)
8137 p2p_set_dev_name(p2p, wpa_s->conf->device_name);
8138
8139 if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_TYPE)
8140 p2p_set_pri_dev_type(p2p, wpa_s->conf->device_type);
8141
8142 if (wpa_s->wps &&
8143 (wpa_s->conf->changed_parameters & CFG_CHANGED_CONFIG_METHODS))
8144 p2p_set_config_methods(p2p, wpa_s->wps->config_methods);
8145
8146 if (wpa_s->wps && (wpa_s->conf->changed_parameters & CFG_CHANGED_UUID))
8147 p2p_set_uuid(p2p, wpa_s->wps->uuid);
8148
8149 if (wpa_s->conf->changed_parameters & CFG_CHANGED_WPS_STRING) {
8150 p2p_set_manufacturer(p2p, wpa_s->conf->manufacturer);
8151 p2p_set_model_name(p2p, wpa_s->conf->model_name);
8152 p2p_set_model_number(p2p, wpa_s->conf->model_number);
8153 p2p_set_serial_number(p2p, wpa_s->conf->serial_number);
8154 }
8155
8156 if (wpa_s->conf->changed_parameters & CFG_CHANGED_SEC_DEVICE_TYPE)
8157 p2p_set_sec_dev_types(p2p,
8158 (void *) wpa_s->conf->sec_device_type,
8159 wpa_s->conf->num_sec_device_types);
8160
8161 if (wpa_s->conf->changed_parameters & CFG_CHANGED_VENDOR_EXTENSION) {
8162 int i;
8163 p2p_remove_wps_vendor_extensions(p2p);
8164 for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {
8165 if (wpa_s->conf->wps_vendor_ext[i] == NULL)
8166 continue;
8167 p2p_add_wps_vendor_extension(
8168 p2p, wpa_s->conf->wps_vendor_ext[i]);
8169 }
8170 }
8171
8172 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
8173 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
8174 char country[3];
8175 country[0] = wpa_s->conf->country[0];
8176 country[1] = wpa_s->conf->country[1];
8177 country[2] = 0x04;
8178 p2p_set_country(p2p, country);
8179 }
8180
8181 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_SSID_POSTFIX) {
8182 p2p_set_ssid_postfix(p2p, (u8 *) wpa_s->conf->p2p_ssid_postfix,
8183 wpa_s->conf->p2p_ssid_postfix ?
8184 os_strlen(wpa_s->conf->p2p_ssid_postfix) :
8185 0);
8186 }
8187
8188 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_INTRA_BSS)
8189 p2p_set_intra_bss_dist(p2p, wpa_s->conf->p2p_intra_bss);
Jouni Malinen75ecf522011-06-27 15:19:46 -07008190
8191 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_LISTEN_CHANNEL) {
8192 u8 reg_class, channel;
8193 int ret;
8194 unsigned int r;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008195 u8 channel_forced;
8196
Jouni Malinen75ecf522011-06-27 15:19:46 -07008197 if (wpa_s->conf->p2p_listen_reg_class &&
8198 wpa_s->conf->p2p_listen_channel) {
8199 reg_class = wpa_s->conf->p2p_listen_reg_class;
8200 channel = wpa_s->conf->p2p_listen_channel;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008201 channel_forced = 1;
Jouni Malinen75ecf522011-06-27 15:19:46 -07008202 } else {
8203 reg_class = 81;
8204 /*
8205 * Pick one of the social channels randomly as the
8206 * listen channel.
8207 */
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008208 if (os_get_random((u8 *) &r, sizeof(r)) < 0)
8209 channel = 1;
8210 else
8211 channel = 1 + (r % 3) * 5;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008212 channel_forced = 0;
Jouni Malinen75ecf522011-06-27 15:19:46 -07008213 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07008214 ret = p2p_set_listen_channel(p2p, reg_class, channel,
8215 channel_forced);
Jouni Malinen75ecf522011-06-27 15:19:46 -07008216 if (ret)
8217 wpa_printf(MSG_ERROR, "P2P: Own listen channel update "
8218 "failed: %d", ret);
8219 }
8220 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_OPER_CHANNEL) {
8221 u8 op_reg_class, op_channel, cfg_op_channel;
8222 int ret = 0;
8223 unsigned int r;
8224 if (wpa_s->conf->p2p_oper_reg_class &&
8225 wpa_s->conf->p2p_oper_channel) {
8226 op_reg_class = wpa_s->conf->p2p_oper_reg_class;
8227 op_channel = wpa_s->conf->p2p_oper_channel;
8228 cfg_op_channel = 1;
8229 } else {
8230 op_reg_class = 81;
8231 /*
8232 * Use random operation channel from (1, 6, 11)
8233 *if no other preference is indicated.
8234 */
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07008235 if (os_get_random((u8 *) &r, sizeof(r)) < 0)
8236 op_channel = 1;
8237 else
8238 op_channel = 1 + (r % 3) * 5;
Jouni Malinen75ecf522011-06-27 15:19:46 -07008239 cfg_op_channel = 0;
8240 }
8241 ret = p2p_set_oper_channel(p2p, op_reg_class, op_channel,
8242 cfg_op_channel);
8243 if (ret)
8244 wpa_printf(MSG_ERROR, "P2P: Own oper channel update "
8245 "failed: %d", ret);
8246 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008247
8248 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_PREF_CHAN) {
8249 if (p2p_set_pref_chan(p2p, wpa_s->conf->num_p2p_pref_chan,
8250 wpa_s->conf->p2p_pref_chan) < 0) {
8251 wpa_printf(MSG_ERROR, "P2P: Preferred channel list "
8252 "update failed");
8253 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008254
8255 if (p2p_set_no_go_freq(p2p, &wpa_s->conf->p2p_no_go_freq) < 0) {
8256 wpa_printf(MSG_ERROR, "P2P: No GO channel list "
8257 "update failed");
8258 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07008259 }
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07008260
8261 if (wpa_s->conf->changed_parameters & CFG_CHANGED_P2P_PASSPHRASE_LEN)
8262 p2p_set_passphrase_len(p2p, wpa_s->conf->p2p_passphrase_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008263}
8264
8265
8266int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start,
8267 int duration)
8268{
8269 if (!wpa_s->ap_iface)
8270 return -1;
8271 return hostapd_p2p_set_noa(wpa_s->ap_iface->bss[0], count, start,
8272 duration);
8273}
8274
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008275
8276int wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled)
8277{
8278 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
8279 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008280
8281 wpa_s->global->cross_connection = enabled;
8282 p2p_set_cross_connect(wpa_s->global->p2p, enabled);
8283
8284 if (!enabled) {
8285 struct wpa_supplicant *iface;
8286
8287 for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
8288 {
8289 if (iface->cross_connect_enabled == 0)
8290 continue;
8291
8292 iface->cross_connect_enabled = 0;
8293 iface->cross_connect_in_use = 0;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008294 wpa_msg_global(iface->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008295 P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
8296 iface->ifname,
8297 iface->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008298 }
8299 }
8300
8301 return 0;
8302}
8303
8304
8305static void wpas_p2p_enable_cross_connect(struct wpa_supplicant *uplink)
8306{
8307 struct wpa_supplicant *iface;
8308
8309 if (!uplink->global->cross_connection)
8310 return;
8311
8312 for (iface = uplink->global->ifaces; iface; iface = iface->next) {
8313 if (!iface->cross_connect_enabled)
8314 continue;
8315 if (os_strcmp(uplink->ifname, iface->cross_connect_uplink) !=
8316 0)
8317 continue;
8318 if (iface->ap_iface == NULL)
8319 continue;
8320 if (iface->cross_connect_in_use)
8321 continue;
8322
8323 iface->cross_connect_in_use = 1;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008324 wpa_msg_global(iface->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008325 P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
8326 iface->ifname, iface->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008327 }
8328}
8329
8330
8331static void wpas_p2p_disable_cross_connect(struct wpa_supplicant *uplink)
8332{
8333 struct wpa_supplicant *iface;
8334
8335 for (iface = uplink->global->ifaces; iface; iface = iface->next) {
8336 if (!iface->cross_connect_enabled)
8337 continue;
8338 if (os_strcmp(uplink->ifname, iface->cross_connect_uplink) !=
8339 0)
8340 continue;
8341 if (!iface->cross_connect_in_use)
8342 continue;
8343
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008344 wpa_msg_global(iface->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008345 P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
8346 iface->ifname, iface->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008347 iface->cross_connect_in_use = 0;
8348 }
8349}
8350
8351
8352void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s)
8353{
8354 if (wpa_s->ap_iface || wpa_s->current_ssid == NULL ||
8355 wpa_s->current_ssid->mode != WPAS_MODE_INFRA ||
8356 wpa_s->cross_connect_disallowed)
8357 wpas_p2p_disable_cross_connect(wpa_s);
8358 else
8359 wpas_p2p_enable_cross_connect(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008360 if (!wpa_s->ap_iface &&
8361 eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
8362 wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008363}
8364
8365
8366void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s)
8367{
8368 wpas_p2p_disable_cross_connect(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008369 if (!wpa_s->ap_iface &&
8370 !eloop_is_timeout_registered(wpas_p2p_group_idle_timeout,
8371 wpa_s, NULL))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008372 wpas_p2p_set_group_idle_timeout(wpa_s);
8373}
8374
8375
8376static void wpas_p2p_cross_connect_setup(struct wpa_supplicant *wpa_s)
8377{
8378 struct wpa_supplicant *iface;
8379
8380 if (!wpa_s->global->cross_connection)
8381 return;
8382
8383 for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
8384 if (iface == wpa_s)
8385 continue;
8386 if (iface->drv_flags &
8387 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)
8388 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008389 if ((iface->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
8390 iface != wpa_s->parent)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008391 continue;
8392
8393 wpa_s->cross_connect_enabled = 1;
8394 os_strlcpy(wpa_s->cross_connect_uplink, iface->ifname,
8395 sizeof(wpa_s->cross_connect_uplink));
8396 wpa_printf(MSG_DEBUG, "P2P: Enable cross connection from "
8397 "%s to %s whenever uplink is available",
8398 wpa_s->ifname, wpa_s->cross_connect_uplink);
8399
8400 if (iface->ap_iface || iface->current_ssid == NULL ||
8401 iface->current_ssid->mode != WPAS_MODE_INFRA ||
8402 iface->cross_connect_disallowed ||
8403 iface->wpa_state != WPA_COMPLETED)
8404 break;
8405
8406 wpa_s->cross_connect_in_use = 1;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008407 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07008408 P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
8409 wpa_s->ifname, wpa_s->cross_connect_uplink);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008410 break;
8411 }
8412}
8413
8414
8415int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s)
8416{
8417 if (wpa_s->p2p_group_interface != P2P_GROUP_INTERFACE_CLIENT &&
8418 !wpa_s->p2p_in_provisioning)
8419 return 0; /* not P2P client operation */
8420
8421 wpa_printf(MSG_DEBUG, "P2P: Terminate connection due to WPS PBC "
8422 "session overlap");
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008423 if (wpa_s != wpa_s->p2pdev)
8424 wpa_msg_ctrl(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_OVERLAP);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07008425 wpas_p2p_group_formation_failed(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008426 return 1;
8427}
8428
8429
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07008430void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx)
8431{
8432 struct wpa_supplicant *wpa_s = eloop_ctx;
8433 wpas_p2p_notif_pbc_overlap(wpa_s);
8434}
8435
8436
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008437void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s,
8438 enum wpas_p2p_channel_update_trig trig)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008439{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008440 struct p2p_channels chan, cli_chan;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008441 struct wpa_used_freq_data *freqs = NULL;
8442 unsigned int num = wpa_s->num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008443
8444 if (wpa_s->global == NULL || wpa_s->global->p2p == NULL)
8445 return;
8446
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008447 freqs = os_calloc(num, sizeof(struct wpa_used_freq_data));
8448 if (!freqs)
8449 return;
8450
Sunil Ravi77d572f2023-01-17 23:58:31 +00008451 num = get_shared_radio_freqs_data(wpa_s, freqs, num, false);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008452
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008453 os_memset(&chan, 0, sizeof(chan));
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008454 os_memset(&cli_chan, 0, sizeof(cli_chan));
Hai Shalom60840252021-02-19 19:02:11 -08008455 if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan,
8456 is_p2p_6ghz_disabled(wpa_s->global->p2p))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008457 wpa_printf(MSG_ERROR, "P2P: Failed to update supported "
8458 "channel list");
8459 return;
8460 }
8461
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008462 p2p_update_channel_list(wpa_s->global->p2p, &chan, &cli_chan);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07008463
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008464 wpas_p2p_optimize_listen_channel(wpa_s, freqs, num);
Dmitry Shmidt684785c2014-05-12 13:34:29 -07008465
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08008466 /*
8467 * The used frequencies map changed, so it is possible that a GO is
8468 * using a channel that is no longer valid for P2P use. It is also
8469 * possible that due to policy consideration, it would be preferable to
8470 * move it to a frequency already used by other station interfaces.
8471 */
8472 wpas_p2p_consider_moving_gos(wpa_s, freqs, num, trig);
8473
8474 os_free(freqs);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008475}
8476
8477
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008478static void wpas_p2p_scan_res_ignore(struct wpa_supplicant *wpa_s,
8479 struct wpa_scan_results *scan_res)
8480{
8481 wpa_printf(MSG_DEBUG, "P2P: Ignore scan results");
8482}
8483
8484
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008485int wpas_p2p_cancel(struct wpa_supplicant *wpa_s)
8486{
8487 struct wpa_global *global = wpa_s->global;
8488 int found = 0;
8489 const u8 *peer;
8490
8491 if (global->p2p == NULL)
8492 return -1;
8493
8494 wpa_printf(MSG_DEBUG, "P2P: Request to cancel group formation");
8495
8496 if (wpa_s->pending_interface_name[0] &&
8497 !is_zero_ether_addr(wpa_s->pending_interface_addr))
8498 found = 1;
8499
8500 peer = p2p_get_go_neg_peer(global->p2p);
8501 if (peer) {
8502 wpa_printf(MSG_DEBUG, "P2P: Unauthorize pending GO Neg peer "
8503 MACSTR, MAC2STR(peer));
8504 p2p_unauthorize(global->p2p, peer);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008505 found = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008506 }
8507
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08008508 if (wpa_s->scan_res_handler == wpas_p2p_scan_res_join) {
8509 wpa_printf(MSG_DEBUG, "P2P: Stop pending scan for join");
8510 wpa_s->scan_res_handler = wpas_p2p_scan_res_ignore;
8511 found = 1;
8512 }
8513
8514 if (wpa_s->pending_pd_before_join) {
8515 wpa_printf(MSG_DEBUG, "P2P: Stop pending PD before join");
8516 wpa_s->pending_pd_before_join = 0;
8517 found = 1;
8518 }
8519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008520 wpas_p2p_stop_find(wpa_s);
8521
8522 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
8523 if (wpa_s == global->p2p_group_formation &&
8524 (wpa_s->p2p_in_provisioning ||
8525 wpa_s->parent->pending_interface_type ==
8526 WPA_IF_P2P_CLIENT)) {
8527 wpa_printf(MSG_DEBUG, "P2P: Interface %s in group "
8528 "formation found - cancelling",
8529 wpa_s->ifname);
8530 found = 1;
8531 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008532 wpa_s->p2pdev, NULL);
Jouni Malinenadddfc42012-10-03 14:31:41 -07008533 if (wpa_s->p2p_in_provisioning) {
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07008534 wpas_group_formation_completed(wpa_s, 0, 0);
Jouni Malinenadddfc42012-10-03 14:31:41 -07008535 break;
8536 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008537 wpas_p2p_group_delete(wpa_s,
8538 P2P_GROUP_REMOVAL_REQUESTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008539 break;
Dmitry Shmidt21de2142014-04-08 10:50:52 -07008540 } else if (wpa_s->p2p_in_invitation) {
8541 wpa_printf(MSG_DEBUG, "P2P: Interface %s in invitation found - cancelling",
8542 wpa_s->ifname);
8543 found = 1;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07008544 wpas_p2p_group_formation_failed(wpa_s, 0);
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008545 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008546 }
8547 }
8548
8549 if (!found) {
8550 wpa_printf(MSG_DEBUG, "P2P: No ongoing group formation found");
8551 return -1;
8552 }
8553
8554 return 0;
8555}
8556
8557
8558void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s)
8559{
8560 if (wpa_s->current_ssid == NULL || !wpa_s->current_ssid->p2p_group)
8561 return;
8562
8563 wpa_printf(MSG_DEBUG, "P2P: Remove group due to driver resource not "
8564 "being available anymore");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008565 wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_UNAVAILABLE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008566}
8567
8568
8569void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s,
8570 int freq_24, int freq_5, int freq_overall)
8571{
8572 struct p2p_data *p2p = wpa_s->global->p2p;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008573 if (p2p == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008574 return;
8575 p2p_set_best_channels(p2p, freq_24, freq_5, freq_overall);
8576}
8577
8578
8579int wpas_p2p_unauthorize(struct wpa_supplicant *wpa_s, const char *addr)
8580{
8581 u8 peer[ETH_ALEN];
8582 struct p2p_data *p2p = wpa_s->global->p2p;
8583
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008584 if (p2p == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008585 return -1;
8586
8587 if (hwaddr_aton(addr, peer))
8588 return -1;
8589
8590 return p2p_unauthorize(p2p, peer);
8591}
8592
8593
8594/**
8595 * wpas_p2p_disconnect - Disconnect from a P2P Group
8596 * @wpa_s: Pointer to wpa_supplicant data
8597 * Returns: 0 on success, -1 on failure
8598 *
8599 * This can be used to disconnect from a group in which the local end is a P2P
8600 * Client or to end a P2P Group in case the local end is the Group Owner. If a
8601 * virtual network interface was created for this group, that interface will be
8602 * removed. Otherwise, only the configured P2P group network will be removed
8603 * from the interface.
8604 */
8605int wpas_p2p_disconnect(struct wpa_supplicant *wpa_s)
8606{
8607
8608 if (wpa_s == NULL)
8609 return -1;
8610
Jouni Malinen2b89da82012-08-31 22:04:41 +03008611 return wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_REQUESTED) < 0 ?
8612 -1 : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008613}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008614
8615
8616int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s)
8617{
Dmitry Shmidtf8623282013-02-20 14:34:59 -08008618 int ret;
8619
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008620 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
8621 return 0;
8622
Dmitry Shmidtf8623282013-02-20 14:34:59 -08008623 ret = p2p_in_progress(wpa_s->global->p2p);
8624 if (ret == 0) {
8625 /*
8626 * Check whether there is an ongoing WPS provisioning step (or
8627 * other parts of group formation) on another interface since
8628 * p2p_in_progress() does not report this to avoid issues for
8629 * scans during such provisioning step.
8630 */
8631 if (wpa_s->global->p2p_group_formation &&
8632 wpa_s->global->p2p_group_formation != wpa_s) {
8633 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Another interface (%s) "
8634 "in group formation",
8635 wpa_s->global->p2p_group_formation->ifname);
8636 ret = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00008637 } else if (wpa_s->global->p2p_group_formation == wpa_s) {
8638 wpa_dbg(wpa_s, MSG_DEBUG,
8639 "P2P: Skip Extended Listen timeout and allow scans on current interface for group formation");
8640 ret = 2;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08008641 }
8642 }
8643
Dmitry Shmidt92c368d2013-08-29 12:37:21 -07008644 if (!ret && wpa_s->global->p2p_go_wait_client.sec) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08008645 struct os_reltime now;
8646 os_get_reltime(&now);
8647 if (os_reltime_expired(&now, &wpa_s->global->p2p_go_wait_client,
8648 P2P_MAX_INITIAL_CONN_WAIT_GO)) {
Dmitry Shmidt92c368d2013-08-29 12:37:21 -07008649 /* Wait for the first client has expired */
8650 wpa_s->global->p2p_go_wait_client.sec = 0;
8651 } else {
8652 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Waiting for initial client connection during group formation");
8653 ret = 1;
8654 }
8655 }
8656
Dmitry Shmidtf8623282013-02-20 14:34:59 -08008657 return ret;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008658}
8659
8660
8661void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s,
8662 struct wpa_ssid *ssid)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008663{
8664 if (wpa_s->p2p_in_provisioning && ssid->p2p_group &&
8665 eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008666 wpa_s->p2pdev, NULL) > 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07008667 /**
8668 * Remove the network by scheduling the group formation
8669 * timeout to happen immediately. The teardown code
8670 * needs to be scheduled to run asynch later so that we
8671 * don't delete data from under ourselves unexpectedly.
8672 * Calling wpas_p2p_group_formation_timeout directly
8673 * causes a series of crashes in WPS failure scenarios.
8674 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008675 wpa_printf(MSG_DEBUG, "P2P: Canceled group formation due to "
8676 "P2P group network getting removed");
Dmitry Shmidt04949592012-07-19 12:16:46 -07008677 eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008678 wpa_s->p2pdev, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008679 }
8680}
8681
8682
8683struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008684 const u8 *addr, const u8 *ssid,
8685 size_t ssid_len)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008686{
8687 struct wpa_ssid *s;
8688 size_t i;
8689
8690 for (s = wpa_s->conf->ssid; s; s = s->next) {
8691 if (s->disabled != 2)
8692 continue;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008693 if (ssid &&
8694 (ssid_len != s->ssid_len ||
8695 os_memcmp(ssid, s->ssid, ssid_len) != 0))
8696 continue;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008697 if (addr == NULL) {
8698 if (s->mode == WPAS_MODE_P2P_GO)
8699 return s;
8700 continue;
8701 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008702 if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0)
8703 return s; /* peer is GO in the persistent group */
8704 if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL)
8705 continue;
8706 for (i = 0; i < s->num_p2p_clients; i++) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08008707 if (os_memcmp(s->p2p_client_list + i * 2 * ETH_ALEN,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008708 addr, ETH_ALEN) == 0)
8709 return s; /* peer is P2P client in persistent
8710 * group */
8711 }
8712 }
8713
8714 return NULL;
8715}
8716
8717
8718void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
8719 const u8 *addr)
8720{
Dmitry Shmidt56052862013-10-04 10:23:25 -07008721 if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008722 wpa_s->p2pdev, NULL) > 0) {
Dmitry Shmidt56052862013-10-04 10:23:25 -07008723 /*
8724 * This can happen if WPS provisioning step is not terminated
8725 * cleanly (e.g., P2P Client does not send WSC_Done). Since the
8726 * peer was able to connect, there is no need to time out group
8727 * formation after this, though. In addition, this is used with
8728 * the initial connection wait on the GO as a separate formation
8729 * timeout and as such, expected to be hit after the initial WPS
8730 * provisioning step.
8731 */
8732 wpa_printf(MSG_DEBUG, "P2P: Canceled P2P group formation timeout on data connection");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008733
8734 if (!wpa_s->p2p_go_group_formation_completed &&
8735 !wpa_s->group_formation_reported) {
8736 /*
8737 * GO has not yet notified group formation success since
8738 * the WPS step was not completed cleanly. Do that
8739 * notification now since the P2P Client was able to
8740 * connect and as such, must have received the
8741 * credential from the WPS step.
8742 */
8743 if (wpa_s->global->p2p)
8744 p2p_wps_success_cb(wpa_s->global->p2p, addr);
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07008745 wpas_group_formation_completed(wpa_s, 1, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08008746 }
Dmitry Shmidt56052862013-10-04 10:23:25 -07008747 }
8748 if (!wpa_s->p2p_go_group_formation_completed) {
8749 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Marking group formation completed on GO on first data connection");
8750 wpa_s->p2p_go_group_formation_completed = 1;
8751 wpa_s->global->p2p_group_formation = NULL;
8752 wpa_s->p2p_in_provisioning = 0;
Dmitry Shmidt21de2142014-04-08 10:50:52 -07008753 wpa_s->p2p_in_invitation = 0;
Matthew Wang06b42472022-11-10 06:56:31 +00008754 wpa_s->p2p_retry_limit = 0;
Dmitry Shmidt56052862013-10-04 10:23:25 -07008755 }
Dmitry Shmidt92c368d2013-08-29 12:37:21 -07008756 wpa_s->global->p2p_go_wait_client.sec = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08008757 if (addr == NULL)
8758 return;
8759 wpas_p2p_add_persistent_group_client(wpa_s, addr);
8760}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08008761
Dmitry Shmidt04949592012-07-19 12:16:46 -07008762
Dmitry Shmidt7f656022015-02-25 14:36:37 -08008763static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
8764 int group_added)
Dmitry Shmidt04949592012-07-19 12:16:46 -07008765{
8766 struct wpa_supplicant *group = wpa_s;
Dmitry Shmidt7f656022015-02-25 14:36:37 -08008767 int ret = 0;
8768
Dmitry Shmidt04949592012-07-19 12:16:46 -07008769 if (wpa_s->global->p2p_group_formation)
8770 group = wpa_s->global->p2p_group_formation;
Dmitry Shmidta3dc3092015-06-23 11:21:28 -07008771 wpa_s = wpa_s->global->p2p_init_wpa_s;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008772 offchannel_send_action_done(wpa_s);
8773 if (group_added)
Dmitry Shmidt7f656022015-02-25 14:36:37 -08008774 ret = wpas_p2p_group_delete(group, P2P_GROUP_REMOVAL_SILENT);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008775 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Fall back to GO Negotiation");
8776 wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin,
8777 wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
8778 0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008779 wpa_s->p2p_go_vht_center_freq2,
Dmitry Shmidt04949592012-07-19 12:16:46 -07008780 wpa_s->p2p_persistent_id,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008781 wpa_s->p2p_pd_before_go_neg,
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07008782 wpa_s->p2p_go_ht40,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08008783 wpa_s->p2p_go_vht,
Hai Shalom74f70d42019-02-11 14:42:39 -08008784 wpa_s->p2p_go_max_oper_chwidth,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08008785 wpa_s->p2p_go_he,
8786 wpa_s->p2p_go_edmg,
Hai Shalomc1a21442022-02-04 13:43:00 -08008787 NULL, 0, is_p2p_allow_6ghz(wpa_s->global->p2p));
Dmitry Shmidt7f656022015-02-25 14:36:37 -08008788 return ret;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008789}
8790
8791
8792int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s)
8793{
Dmitry Shmidt7f656022015-02-25 14:36:37 -08008794 int res;
8795
Dmitry Shmidt04949592012-07-19 12:16:46 -07008796 if (!wpa_s->p2p_fallback_to_go_neg ||
8797 wpa_s->p2p_in_provisioning <= 5)
8798 return 0;
8799
8800 if (wpas_p2p_peer_go(wpa_s, wpa_s->pending_join_dev_addr) > 0)
8801 return 0; /* peer operating as a GO */
8802
8803 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - "
8804 "fallback to GO Negotiation");
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008805 wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG
Dmitry Shmidt7f656022015-02-25 14:36:37 -08008806 "reason=GO-not-found");
8807 res = wpas_p2p_fallback_to_go_neg(wpa_s, 1);
Dmitry Shmidt04949592012-07-19 12:16:46 -07008808
Dmitry Shmidt7f656022015-02-25 14:36:37 -08008809 return res == 1 ? 2 : 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07008810}
8811
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008812
8813unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s)
8814{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008815 struct wpa_supplicant *ifs;
8816
8817 if (wpa_s->wpa_state > WPA_SCANNING) {
8818 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search delay due to "
8819 "concurrent operation",
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07008820 wpa_s->conf->p2p_search_delay);
8821 return wpa_s->conf->p2p_search_delay;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008822 }
8823
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08008824 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
8825 radio_list) {
8826 if (ifs != wpa_s && ifs->wpa_state > WPA_SCANNING) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008827 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use %u ms search "
8828 "delay due to concurrent operation on "
8829 "interface %s",
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07008830 wpa_s->conf->p2p_search_delay,
8831 ifs->ifname);
8832 return wpa_s->conf->p2p_search_delay;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07008833 }
8834 }
8835
8836 return 0;
8837}
8838
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07008839
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008840static int wpas_p2p_remove_psk_entry(struct wpa_supplicant *wpa_s,
8841 struct wpa_ssid *s, const u8 *addr,
8842 int iface_addr)
8843{
8844 struct psk_list_entry *psk, *tmp;
8845 int changed = 0;
8846
8847 dl_list_for_each_safe(psk, tmp, &s->psk_list, struct psk_list_entry,
8848 list) {
8849 if ((iface_addr && !psk->p2p &&
8850 os_memcmp(addr, psk->addr, ETH_ALEN) == 0) ||
8851 (!iface_addr && psk->p2p &&
8852 os_memcmp(addr, psk->addr, ETH_ALEN) == 0)) {
8853 wpa_dbg(wpa_s, MSG_DEBUG,
8854 "P2P: Remove persistent group PSK list entry for "
8855 MACSTR " p2p=%u",
8856 MAC2STR(psk->addr), psk->p2p);
8857 dl_list_del(&psk->list);
8858 os_free(psk);
8859 changed++;
8860 }
8861 }
8862
8863 return changed;
8864}
8865
8866
8867void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
8868 const u8 *p2p_dev_addr,
8869 const u8 *psk, size_t psk_len)
8870{
8871 struct wpa_ssid *ssid = wpa_s->current_ssid;
8872 struct wpa_ssid *persistent;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07008873 struct psk_list_entry *p, *last;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008874
8875 if (psk_len != sizeof(p->psk))
8876 return;
8877
8878 if (p2p_dev_addr) {
8879 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New PSK for addr=" MACSTR
8880 " p2p_dev_addr=" MACSTR,
8881 MAC2STR(mac_addr), MAC2STR(p2p_dev_addr));
8882 if (is_zero_ether_addr(p2p_dev_addr))
8883 p2p_dev_addr = NULL;
8884 } else {
8885 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New PSK for addr=" MACSTR,
8886 MAC2STR(mac_addr));
8887 }
8888
8889 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
8890 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: new_psk_cb during group formation");
8891 /* To be added to persistent group once created */
8892 if (wpa_s->global->add_psk == NULL) {
8893 wpa_s->global->add_psk = os_zalloc(sizeof(*p));
8894 if (wpa_s->global->add_psk == NULL)
8895 return;
8896 }
8897 p = wpa_s->global->add_psk;
8898 if (p2p_dev_addr) {
8899 p->p2p = 1;
8900 os_memcpy(p->addr, p2p_dev_addr, ETH_ALEN);
8901 } else {
8902 p->p2p = 0;
8903 os_memcpy(p->addr, mac_addr, ETH_ALEN);
8904 }
8905 os_memcpy(p->psk, psk, psk_len);
8906 return;
8907 }
8908
8909 if (ssid->mode != WPAS_MODE_P2P_GO || !ssid->p2p_persistent_group) {
8910 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Ignore new_psk_cb on not-persistent GO");
8911 return;
8912 }
8913
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008914 persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008915 ssid->ssid_len);
8916 if (!persistent) {
8917 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not find persistent group information to store the new PSK");
8918 return;
8919 }
8920
8921 p = os_zalloc(sizeof(*p));
8922 if (p == NULL)
8923 return;
8924 if (p2p_dev_addr) {
8925 p->p2p = 1;
8926 os_memcpy(p->addr, p2p_dev_addr, ETH_ALEN);
8927 } else {
8928 p->p2p = 0;
8929 os_memcpy(p->addr, mac_addr, ETH_ALEN);
8930 }
8931 os_memcpy(p->psk, psk, psk_len);
8932
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07008933 if (dl_list_len(&persistent->psk_list) > P2P_MAX_STORED_CLIENTS &&
8934 (last = dl_list_last(&persistent->psk_list,
8935 struct psk_list_entry, list))) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008936 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove oldest PSK entry for "
8937 MACSTR " (p2p=%u) to make room for a new one",
8938 MAC2STR(last->addr), last->p2p);
8939 dl_list_del(&last->list);
8940 os_free(last);
8941 }
8942
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008943 wpas_p2p_remove_psk_entry(wpa_s->p2pdev, persistent,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008944 p2p_dev_addr ? p2p_dev_addr : mac_addr,
8945 p2p_dev_addr == NULL);
8946 if (p2p_dev_addr) {
8947 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add new PSK for p2p_dev_addr="
8948 MACSTR, MAC2STR(p2p_dev_addr));
8949 } else {
8950 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add new PSK for addr=" MACSTR,
8951 MAC2STR(mac_addr));
8952 }
8953 dl_list_add(&persistent->psk_list, &p->list);
8954
Dmitry Shmidt9c175262016-03-03 10:20:07 -08008955 if (wpa_s->p2pdev->conf->update_config &&
8956 wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf))
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008957 wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008958}
8959
8960
8961static void wpas_p2p_remove_psk(struct wpa_supplicant *wpa_s,
8962 struct wpa_ssid *s, const u8 *addr,
8963 int iface_addr)
8964{
8965 int res;
8966
8967 res = wpas_p2p_remove_psk_entry(wpa_s, s, addr, iface_addr);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08008968 if (res > 0 && wpa_s->conf->update_config &&
8969 wpa_config_write(wpa_s->confname, wpa_s->conf))
8970 wpa_dbg(wpa_s, MSG_DEBUG,
8971 "P2P: Failed to update configuration");
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07008972}
8973
8974
8975static void wpas_p2p_remove_client_go(struct wpa_supplicant *wpa_s,
8976 const u8 *peer, int iface_addr)
8977{
8978 struct hostapd_data *hapd;
8979 struct hostapd_wpa_psk *psk, *prev, *rem;
8980 struct sta_info *sta;
8981
8982 if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL ||
8983 wpa_s->current_ssid->mode != WPAS_MODE_P2P_GO)
8984 return;
8985
8986 /* Remove per-station PSK entry */
8987 hapd = wpa_s->ap_iface->bss[0];
8988 prev = NULL;
8989 psk = hapd->conf->ssid.wpa_psk;
8990 while (psk) {
8991 if ((iface_addr && os_memcmp(peer, psk->addr, ETH_ALEN) == 0) ||
8992 (!iface_addr &&
8993 os_memcmp(peer, psk->p2p_dev_addr, ETH_ALEN) == 0)) {
8994 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove operating group PSK entry for "
8995 MACSTR " iface_addr=%d",
8996 MAC2STR(peer), iface_addr);
8997 if (prev)
8998 prev->next = psk->next;
8999 else
9000 hapd->conf->ssid.wpa_psk = psk->next;
9001 rem = psk;
9002 psk = psk->next;
Sunil Ravia04bd252022-05-02 22:54:18 -07009003 bin_clear_free(rem, sizeof(*rem));
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07009004 } else {
9005 prev = psk;
9006 psk = psk->next;
9007 }
9008 }
9009
9010 /* Disconnect from group */
9011 if (iface_addr)
9012 sta = ap_get_sta(hapd, peer);
9013 else
9014 sta = ap_get_sta_p2p(hapd, peer);
9015 if (sta) {
9016 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disconnect peer " MACSTR
9017 " (iface_addr=%d) from group",
9018 MAC2STR(peer), iface_addr);
9019 hostapd_drv_sta_deauth(hapd, sta->addr,
9020 WLAN_REASON_DEAUTH_LEAVING);
9021 ap_sta_deauthenticate(hapd, sta, WLAN_REASON_DEAUTH_LEAVING);
9022 }
9023}
9024
9025
9026void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer,
9027 int iface_addr)
9028{
9029 struct wpa_ssid *s;
9030 struct wpa_supplicant *w;
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07009031 struct wpa_supplicant *p2p_wpa_s = wpa_s->global->p2p_init_wpa_s;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07009032
9033 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove client " MACSTR, MAC2STR(peer));
9034
9035 /* Remove from any persistent group */
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07009036 for (s = p2p_wpa_s->conf->ssid; s; s = s->next) {
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07009037 if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO)
9038 continue;
9039 if (!iface_addr)
Dmitry Shmidt8bd70b72015-05-26 16:02:19 -07009040 wpas_remove_persistent_peer(p2p_wpa_s, s, peer, 0);
9041 wpas_p2p_remove_psk(p2p_wpa_s, s, peer, iface_addr);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07009042 }
9043
9044 /* Remove from any operating group */
9045 for (w = wpa_s->global->ifaces; w; w = w->next)
9046 wpas_p2p_remove_client_go(w, peer, iface_addr);
9047}
9048
9049
9050static void wpas_p2p_psk_failure_removal(void *eloop_ctx, void *timeout_ctx)
9051{
9052 struct wpa_supplicant *wpa_s = eloop_ctx;
9053 wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_PSK_FAILURE);
9054}
9055
9056
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08009057static void wpas_p2p_group_freq_conflict(void *eloop_ctx, void *timeout_ctx)
9058{
9059 struct wpa_supplicant *wpa_s = eloop_ctx;
9060
9061 wpa_printf(MSG_DEBUG, "P2P: Frequency conflict - terminate group");
9062 wpas_p2p_group_delete(wpa_s, P2P_GROUP_REMOVAL_FREQ_CONFLICT);
9063}
9064
9065
9066int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq,
9067 struct wpa_ssid *ssid)
9068{
9069 struct wpa_supplicant *iface;
9070
9071 for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
9072 if (!iface->current_ssid ||
9073 iface->current_ssid->frequency == freq ||
9074 (iface->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
9075 !iface->current_ssid->p2p_group))
9076 continue;
9077
9078 /* Remove the connection with least priority */
9079 if (!wpas_is_p2p_prioritized(iface)) {
9080 /* STA connection has priority over existing
9081 * P2P connection, so remove the interface. */
9082 wpa_printf(MSG_DEBUG, "P2P: Removing P2P connection due to single channel concurrent mode frequency conflict");
9083 eloop_register_timeout(0, 0,
9084 wpas_p2p_group_freq_conflict,
9085 iface, NULL);
9086 /* If connection in progress is P2P connection, do not
9087 * proceed for the connection. */
9088 if (wpa_s == iface)
9089 return -1;
9090 else
9091 return 0;
9092 } else {
9093 /* P2P connection has priority, disable the STA network
9094 */
9095 wpa_supplicant_disable_network(wpa_s->global->ifaces,
9096 ssid);
9097 wpa_msg(wpa_s->global->ifaces, MSG_INFO,
9098 WPA_EVENT_FREQ_CONFLICT " id=%d", ssid->id);
9099 os_memset(wpa_s->global->ifaces->pending_bssid, 0,
9100 ETH_ALEN);
9101 /* If P2P connection is in progress, continue
9102 * connecting...*/
9103 if (wpa_s == iface)
9104 return 0;
9105 else
9106 return -1;
9107 }
9108 }
9109
9110 return 0;
9111}
9112
9113
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07009114int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s)
9115{
9116 struct wpa_ssid *ssid = wpa_s->current_ssid;
9117
9118 if (ssid == NULL || !ssid->p2p_group)
9119 return 0;
9120
9121 if (wpa_s->p2p_last_4way_hs_fail &&
9122 wpa_s->p2p_last_4way_hs_fail == ssid) {
9123 u8 go_dev_addr[ETH_ALEN];
9124 struct wpa_ssid *persistent;
9125
9126 if (wpas_p2p_persistent_group(wpa_s, go_dev_addr,
9127 ssid->ssid,
9128 ssid->ssid_len) <= 0) {
9129 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not determine whether 4-way handshake failures were for a persistent group");
9130 goto disconnect;
9131 }
9132
9133 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Two 4-way handshake failures for a P2P group - go_dev_addr="
9134 MACSTR, MAC2STR(go_dev_addr));
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009135 persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, go_dev_addr,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07009136 ssid->ssid,
9137 ssid->ssid_len);
9138 if (persistent == NULL || persistent->mode != WPAS_MODE_INFRA) {
9139 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No matching persistent group stored");
9140 goto disconnect;
9141 }
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009142 wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07009143 P2P_EVENT_PERSISTENT_PSK_FAIL "%d",
9144 persistent->id);
9145 disconnect:
9146 wpa_s->p2p_last_4way_hs_fail = NULL;
9147 /*
9148 * Remove the group from a timeout to avoid issues with caller
9149 * continuing to use the interface if this is on a P2P group
9150 * interface.
9151 */
9152 eloop_register_timeout(0, 0, wpas_p2p_psk_failure_removal,
9153 wpa_s, NULL);
9154 return 1;
9155 }
9156
9157 wpa_s->p2p_last_4way_hs_fail = ssid;
9158 return 0;
9159}
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009160
9161
9162#ifdef CONFIG_WPS_NFC
9163
9164static struct wpabuf * wpas_p2p_nfc_handover(int ndef, struct wpabuf *wsc,
9165 struct wpabuf *p2p)
9166{
9167 struct wpabuf *ret;
9168 size_t wsc_len;
9169
9170 if (p2p == NULL) {
9171 wpabuf_free(wsc);
9172 wpa_printf(MSG_DEBUG, "P2P: No p2p buffer for handover");
9173 return NULL;
9174 }
9175
9176 wsc_len = wsc ? wpabuf_len(wsc) : 0;
9177 ret = wpabuf_alloc(2 + wsc_len + 2 + wpabuf_len(p2p));
9178 if (ret == NULL) {
9179 wpabuf_free(wsc);
9180 wpabuf_free(p2p);
9181 return NULL;
9182 }
9183
9184 wpabuf_put_be16(ret, wsc_len);
9185 if (wsc)
9186 wpabuf_put_buf(ret, wsc);
9187 wpabuf_put_be16(ret, wpabuf_len(p2p));
9188 wpabuf_put_buf(ret, p2p);
9189
9190 wpabuf_free(wsc);
9191 wpabuf_free(p2p);
9192 wpa_hexdump_buf(MSG_DEBUG,
9193 "P2P: Generated NFC connection handover message", ret);
9194
9195 if (ndef && ret) {
9196 struct wpabuf *tmp;
9197 tmp = ndef_build_p2p(ret);
9198 wpabuf_free(ret);
9199 if (tmp == NULL) {
9200 wpa_printf(MSG_DEBUG, "P2P: Failed to NDEF encapsulate handover request");
9201 return NULL;
9202 }
9203 ret = tmp;
9204 }
9205
9206 return ret;
9207}
9208
9209
9210static int wpas_p2p_cli_freq(struct wpa_supplicant *wpa_s,
9211 struct wpa_ssid **ssid, u8 *go_dev_addr)
9212{
9213 struct wpa_supplicant *iface;
9214
9215 if (go_dev_addr)
9216 os_memset(go_dev_addr, 0, ETH_ALEN);
9217 if (ssid)
9218 *ssid = NULL;
9219 for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
9220 if (iface->wpa_state < WPA_ASSOCIATING ||
9221 iface->current_ssid == NULL || iface->assoc_freq == 0 ||
9222 !iface->current_ssid->p2p_group ||
9223 iface->current_ssid->mode != WPAS_MODE_INFRA)
9224 continue;
9225 if (ssid)
9226 *ssid = iface->current_ssid;
9227 if (go_dev_addr)
9228 os_memcpy(go_dev_addr, iface->go_dev_addr, ETH_ALEN);
9229 return iface->assoc_freq;
9230 }
9231 return 0;
9232}
9233
9234
9235struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s,
9236 int ndef)
9237{
9238 struct wpabuf *wsc, *p2p;
9239 struct wpa_ssid *ssid;
9240 u8 go_dev_addr[ETH_ALEN];
9241 int cli_freq = wpas_p2p_cli_freq(wpa_s, &ssid, go_dev_addr);
9242
9243 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
9244 wpa_printf(MSG_DEBUG, "P2P: P2P disabled - cannot build handover request");
9245 return NULL;
9246 }
9247
9248 if (wpa_s->conf->wps_nfc_dh_pubkey == NULL &&
9249 wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
9250 &wpa_s->conf->wps_nfc_dh_privkey) < 0) {
9251 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No DH key available for handover request");
9252 return NULL;
9253 }
9254
9255 if (cli_freq == 0) {
9256 wsc = wps_build_nfc_handover_req_p2p(
9257 wpa_s->parent->wps, wpa_s->conf->wps_nfc_dh_pubkey);
9258 } else
9259 wsc = NULL;
9260 p2p = p2p_build_nfc_handover_req(wpa_s->global->p2p, cli_freq,
9261 go_dev_addr, ssid ? ssid->ssid : NULL,
9262 ssid ? ssid->ssid_len : 0);
9263
9264 return wpas_p2p_nfc_handover(ndef, wsc, p2p);
9265}
9266
9267
9268struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s,
9269 int ndef, int tag)
9270{
9271 struct wpabuf *wsc, *p2p;
9272 struct wpa_ssid *ssid;
9273 u8 go_dev_addr[ETH_ALEN];
9274 int cli_freq = wpas_p2p_cli_freq(wpa_s, &ssid, go_dev_addr);
9275
9276 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
9277 return NULL;
9278
9279 if (!tag && wpa_s->conf->wps_nfc_dh_pubkey == NULL &&
9280 wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
9281 &wpa_s->conf->wps_nfc_dh_privkey) < 0)
9282 return NULL;
9283
9284 if (cli_freq == 0) {
9285 wsc = wps_build_nfc_handover_sel_p2p(
9286 wpa_s->parent->wps,
9287 tag ? wpa_s->conf->wps_nfc_dev_pw_id :
9288 DEV_PW_NFC_CONNECTION_HANDOVER,
9289 wpa_s->conf->wps_nfc_dh_pubkey,
9290 tag ? wpa_s->conf->wps_nfc_dev_pw : NULL);
9291 } else
9292 wsc = NULL;
9293 p2p = p2p_build_nfc_handover_sel(wpa_s->global->p2p, cli_freq,
9294 go_dev_addr, ssid ? ssid->ssid : NULL,
9295 ssid ? ssid->ssid_len : 0);
9296
9297 return wpas_p2p_nfc_handover(ndef, wsc, p2p);
9298}
9299
9300
9301static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s,
9302 struct p2p_nfc_params *params)
9303{
9304 wpa_printf(MSG_DEBUG, "P2P: Initiate join-group based on NFC "
9305 "connection handover (freq=%d)",
9306 params->go_freq);
9307
9308 if (params->go_freq && params->go_ssid_len) {
9309 wpa_s->p2p_wps_method = WPS_NFC;
9310 wpa_s->pending_join_wps_method = WPS_NFC;
9311 os_memset(wpa_s->pending_join_iface_addr, 0, ETH_ALEN);
9312 os_memcpy(wpa_s->pending_join_dev_addr, params->go_dev_addr,
9313 ETH_ALEN);
9314 return wpas_p2p_join_start(wpa_s, params->go_freq,
9315 params->go_ssid,
9316 params->go_ssid_len);
9317 }
9318
9319 return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
9320 WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08009321 params->go_freq, wpa_s->p2p_go_vht_center_freq2,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08009322 -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08009323 wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08009324 params->go_ssid_len ? params->go_ssid : NULL,
Hai Shalomc1a21442022-02-04 13:43:00 -08009325 params->go_ssid_len, false);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009326}
9327
9328
9329static int wpas_p2p_nfc_auth_join(struct wpa_supplicant *wpa_s,
9330 struct p2p_nfc_params *params, int tag)
9331{
9332 int res, persistent;
9333 struct wpa_ssid *ssid;
9334
9335 wpa_printf(MSG_DEBUG, "P2P: Authorize join-group based on NFC "
9336 "connection handover");
9337 for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
9338 ssid = wpa_s->current_ssid;
9339 if (ssid == NULL)
9340 continue;
9341 if (ssid->mode != WPAS_MODE_P2P_GO)
9342 continue;
9343 if (wpa_s->ap_iface == NULL)
9344 continue;
9345 break;
9346 }
9347 if (wpa_s == NULL) {
9348 wpa_printf(MSG_DEBUG, "P2P: Could not find GO interface");
9349 return -1;
9350 }
9351
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009352 if (wpa_s->p2pdev->p2p_oob_dev_pw_id !=
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009353 DEV_PW_NFC_CONNECTION_HANDOVER &&
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009354 !wpa_s->p2pdev->p2p_oob_dev_pw) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009355 wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
9356 return -1;
9357 }
9358 res = wpas_ap_wps_add_nfc_pw(
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009359 wpa_s, wpa_s->p2pdev->p2p_oob_dev_pw_id,
9360 wpa_s->p2pdev->p2p_oob_dev_pw,
9361 wpa_s->p2pdev->p2p_peer_oob_pk_hash_known ?
9362 wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009363 if (res)
9364 return res;
9365
9366 if (!tag) {
9367 wpa_printf(MSG_DEBUG, "P2P: Negotiated handover - wait for peer to join without invitation");
9368 return 0;
9369 }
9370
9371 if (!params->peer ||
9372 !(params->peer->dev_capab & P2P_DEV_CAPAB_INVITATION_PROCEDURE))
9373 return 0;
9374
9375 wpa_printf(MSG_DEBUG, "P2P: Static handover - invite peer " MACSTR
9376 " to join", MAC2STR(params->peer->p2p_device_addr));
9377
9378 wpa_s->global->p2p_invite_group = wpa_s;
9379 persistent = ssid->p2p_persistent_group &&
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009380 wpas_p2p_get_persistent(wpa_s->p2pdev,
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009381 params->peer->p2p_device_addr,
9382 ssid->ssid, ssid->ssid_len);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009383 wpa_s->p2pdev->pending_invite_ssid_id = -1;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009384
9385 return p2p_invite(wpa_s->global->p2p, params->peer->p2p_device_addr,
9386 P2P_INVITE_ROLE_ACTIVE_GO, wpa_s->own_addr,
9387 ssid->ssid, ssid->ssid_len, ssid->frequency,
9388 wpa_s->global->p2p_dev_addr, persistent, 0,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07009389 wpa_s->p2pdev->p2p_oob_dev_pw_id);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009390}
9391
9392
9393static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s,
9394 struct p2p_nfc_params *params,
9395 int forced_freq)
9396{
9397 wpa_printf(MSG_DEBUG, "P2P: Initiate GO Negotiation based on NFC "
9398 "connection handover");
9399 return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
9400 WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08009401 forced_freq, wpa_s->p2p_go_vht_center_freq2,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08009402 -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08009403 wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
Hai Shalomc1a21442022-02-04 13:43:00 -08009404 NULL, 0, false);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009405}
9406
9407
9408static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s,
9409 struct p2p_nfc_params *params,
9410 int forced_freq)
9411{
9412 int res;
9413
9414 wpa_printf(MSG_DEBUG, "P2P: Authorize GO Negotiation based on NFC "
9415 "connection handover");
9416 res = wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
9417 WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08009418 forced_freq, wpa_s->p2p_go_vht_center_freq2,
Dmitry Shmidtde47be72016-01-07 12:52:55 -08009419 -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08009420 wpa_s->p2p_go_he, wpa_s->p2p_go_edmg,
Hai Shalomc1a21442022-02-04 13:43:00 -08009421 NULL, 0, false);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009422 if (res)
9423 return res;
9424
9425 res = wpas_p2p_listen(wpa_s, 60);
9426 if (res) {
9427 p2p_unauthorize(wpa_s->global->p2p,
9428 params->peer->p2p_device_addr);
9429 }
9430
9431 return res;
9432}
9433
9434
9435static int wpas_p2p_nfc_connection_handover(struct wpa_supplicant *wpa_s,
9436 const struct wpabuf *data,
9437 int sel, int tag, int forced_freq)
9438{
9439 const u8 *pos, *end;
9440 u16 len, id;
9441 struct p2p_nfc_params params;
9442 int res;
9443
9444 os_memset(&params, 0, sizeof(params));
9445 params.sel = sel;
9446
9447 wpa_hexdump_buf(MSG_DEBUG, "P2P: Received NFC tag payload", data);
9448
9449 pos = wpabuf_head(data);
9450 end = pos + wpabuf_len(data);
9451
9452 if (end - pos < 2) {
9453 wpa_printf(MSG_DEBUG, "P2P: Not enough data for Length of WSC "
9454 "attributes");
9455 return -1;
9456 }
9457 len = WPA_GET_BE16(pos);
9458 pos += 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009459 if (len > end - pos) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009460 wpa_printf(MSG_DEBUG, "P2P: Not enough data for WSC "
9461 "attributes");
9462 return -1;
9463 }
9464 params.wsc_attr = pos;
9465 params.wsc_len = len;
9466 pos += len;
9467
9468 if (end - pos < 2) {
9469 wpa_printf(MSG_DEBUG, "P2P: Not enough data for Length of P2P "
9470 "attributes");
9471 return -1;
9472 }
9473 len = WPA_GET_BE16(pos);
9474 pos += 2;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08009475 if (len > end - pos) {
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009476 wpa_printf(MSG_DEBUG, "P2P: Not enough data for P2P "
9477 "attributes");
9478 return -1;
9479 }
9480 params.p2p_attr = pos;
9481 params.p2p_len = len;
9482 pos += len;
9483
9484 wpa_hexdump(MSG_DEBUG, "P2P: WSC attributes",
9485 params.wsc_attr, params.wsc_len);
9486 wpa_hexdump(MSG_DEBUG, "P2P: P2P attributes",
9487 params.p2p_attr, params.p2p_len);
9488 if (pos < end) {
9489 wpa_hexdump(MSG_DEBUG,
9490 "P2P: Ignored extra data after P2P attributes",
9491 pos, end - pos);
9492 }
9493
9494 res = p2p_process_nfc_connection_handover(wpa_s->global->p2p, &params);
9495 if (res)
9496 return res;
9497
9498 if (params.next_step == NO_ACTION)
9499 return 0;
9500
9501 if (params.next_step == BOTH_GO) {
9502 wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_BOTH_GO "peer=" MACSTR,
9503 MAC2STR(params.peer->p2p_device_addr));
9504 return 0;
9505 }
9506
9507 if (params.next_step == PEER_CLIENT) {
9508 if (!is_zero_ether_addr(params.go_dev_addr)) {
9509 wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_PEER_CLIENT
9510 "peer=" MACSTR " freq=%d go_dev_addr=" MACSTR
9511 " ssid=\"%s\"",
9512 MAC2STR(params.peer->p2p_device_addr),
9513 params.go_freq,
9514 MAC2STR(params.go_dev_addr),
9515 wpa_ssid_txt(params.go_ssid,
9516 params.go_ssid_len));
9517 } else {
9518 wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_PEER_CLIENT
9519 "peer=" MACSTR " freq=%d",
9520 MAC2STR(params.peer->p2p_device_addr),
9521 params.go_freq);
9522 }
9523 return 0;
9524 }
9525
9526 if (wpas_p2p_cli_freq(wpa_s, NULL, NULL)) {
9527 wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_NFC_WHILE_CLIENT "peer="
9528 MACSTR, MAC2STR(params.peer->p2p_device_addr));
9529 return 0;
9530 }
9531
9532 wpabuf_free(wpa_s->p2p_oob_dev_pw);
9533 wpa_s->p2p_oob_dev_pw = NULL;
9534
9535 if (params.oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2) {
9536 wpa_printf(MSG_DEBUG, "P2P: No peer OOB Dev Pw "
9537 "received");
9538 return -1;
9539 }
9540
9541 id = WPA_GET_BE16(params.oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN);
9542 wpa_printf(MSG_DEBUG, "P2P: Peer OOB Dev Pw %u", id);
9543 wpa_hexdump(MSG_DEBUG, "P2P: Peer OOB Public Key hash",
9544 params.oob_dev_pw, WPS_OOB_PUBKEY_HASH_LEN);
9545 os_memcpy(wpa_s->p2p_peer_oob_pubkey_hash,
9546 params.oob_dev_pw, WPS_OOB_PUBKEY_HASH_LEN);
9547 wpa_s->p2p_peer_oob_pk_hash_known = 1;
9548
9549 if (tag) {
9550 if (id < 0x10) {
9551 wpa_printf(MSG_DEBUG, "P2P: Static handover - invalid "
9552 "peer OOB Device Password Id %u", id);
9553 return -1;
9554 }
9555 wpa_printf(MSG_DEBUG, "P2P: Static handover - use peer OOB "
9556 "Device Password Id %u", id);
9557 wpa_hexdump_key(MSG_DEBUG, "P2P: Peer OOB Device Password",
9558 params.oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN + 2,
9559 params.oob_dev_pw_len -
9560 WPS_OOB_PUBKEY_HASH_LEN - 2);
9561 wpa_s->p2p_oob_dev_pw_id = id;
9562 wpa_s->p2p_oob_dev_pw = wpabuf_alloc_copy(
9563 params.oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN + 2,
9564 params.oob_dev_pw_len -
9565 WPS_OOB_PUBKEY_HASH_LEN - 2);
9566 if (wpa_s->p2p_oob_dev_pw == NULL)
9567 return -1;
9568
9569 if (wpa_s->conf->wps_nfc_dh_pubkey == NULL &&
9570 wps_nfc_gen_dh(&wpa_s->conf->wps_nfc_dh_pubkey,
9571 &wpa_s->conf->wps_nfc_dh_privkey) < 0)
9572 return -1;
9573 } else {
9574 wpa_printf(MSG_DEBUG, "P2P: Using abbreviated WPS handshake "
9575 "without Device Password");
9576 wpa_s->p2p_oob_dev_pw_id = DEV_PW_NFC_CONNECTION_HANDOVER;
9577 }
9578
9579 switch (params.next_step) {
9580 case NO_ACTION:
9581 case BOTH_GO:
9582 case PEER_CLIENT:
9583 /* already covered above */
9584 return 0;
9585 case JOIN_GROUP:
9586 return wpas_p2p_nfc_join_group(wpa_s, &params);
9587 case AUTH_JOIN:
9588 return wpas_p2p_nfc_auth_join(wpa_s, &params, tag);
9589 case INIT_GO_NEG:
9590 return wpas_p2p_nfc_init_go_neg(wpa_s, &params, forced_freq);
9591 case RESP_GO_NEG:
9592 /* TODO: use own OOB Dev Pw */
9593 return wpas_p2p_nfc_resp_go_neg(wpa_s, &params, forced_freq);
9594 }
9595
9596 return -1;
9597}
9598
9599
9600int wpas_p2p_nfc_tag_process(struct wpa_supplicant *wpa_s,
9601 const struct wpabuf *data, int forced_freq)
9602{
9603 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
9604 return -1;
9605
9606 return wpas_p2p_nfc_connection_handover(wpa_s, data, 1, 1, forced_freq);
9607}
9608
9609
9610int wpas_p2p_nfc_report_handover(struct wpa_supplicant *wpa_s, int init,
9611 const struct wpabuf *req,
9612 const struct wpabuf *sel, int forced_freq)
9613{
9614 struct wpabuf *tmp;
9615 int ret;
9616
9617 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
9618 return -1;
9619
9620 wpa_printf(MSG_DEBUG, "NFC: P2P connection handover reported");
9621
9622 wpa_hexdump_ascii(MSG_DEBUG, "NFC: Req",
9623 wpabuf_head(req), wpabuf_len(req));
9624 wpa_hexdump_ascii(MSG_DEBUG, "NFC: Sel",
9625 wpabuf_head(sel), wpabuf_len(sel));
9626 if (forced_freq)
9627 wpa_printf(MSG_DEBUG, "NFC: Forced freq %d", forced_freq);
9628 tmp = ndef_parse_p2p(init ? sel : req);
9629 if (tmp == NULL) {
9630 wpa_printf(MSG_DEBUG, "P2P: Could not parse NDEF");
9631 return -1;
9632 }
9633
9634 ret = wpas_p2p_nfc_connection_handover(wpa_s, tmp, init, 0,
9635 forced_freq);
9636 wpabuf_free(tmp);
9637
9638 return ret;
9639}
9640
9641
9642int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled)
9643{
9644 const u8 *if_addr;
9645 int go_intent = wpa_s->conf->p2p_go_intent;
9646 struct wpa_supplicant *iface;
9647
9648 if (wpa_s->global->p2p == NULL)
9649 return -1;
9650
9651 if (!enabled) {
9652 wpa_printf(MSG_DEBUG, "P2P: Disable use of own NFC Tag");
9653 for (iface = wpa_s->global->ifaces; iface; iface = iface->next)
9654 {
9655 if (!iface->ap_iface)
9656 continue;
9657 hostapd_wps_nfc_token_disable(iface->ap_iface->bss[0]);
9658 }
9659 p2p_set_authorized_oob_dev_pw_id(wpa_s->global->p2p, 0,
9660 0, NULL);
9661 if (wpa_s->p2p_nfc_tag_enabled)
9662 wpas_p2p_remove_pending_group_interface(wpa_s);
9663 wpa_s->p2p_nfc_tag_enabled = 0;
9664 return 0;
9665 }
9666
9667 if (wpa_s->global->p2p_disabled)
9668 return -1;
9669
9670 if (wpa_s->conf->wps_nfc_dh_pubkey == NULL ||
9671 wpa_s->conf->wps_nfc_dh_privkey == NULL ||
9672 wpa_s->conf->wps_nfc_dev_pw == NULL ||
9673 wpa_s->conf->wps_nfc_dev_pw_id < 0x10) {
9674 wpa_printf(MSG_DEBUG, "P2P: NFC password token not configured "
9675 "to allow static handover cases");
9676 return -1;
9677 }
9678
9679 wpa_printf(MSG_DEBUG, "P2P: Enable use of own NFC Tag");
9680
9681 wpa_s->p2p_oob_dev_pw_id = wpa_s->conf->wps_nfc_dev_pw_id;
9682 wpabuf_free(wpa_s->p2p_oob_dev_pw);
9683 wpa_s->p2p_oob_dev_pw = wpabuf_dup(wpa_s->conf->wps_nfc_dev_pw);
9684 if (wpa_s->p2p_oob_dev_pw == NULL)
9685 return -1;
9686 wpa_s->p2p_peer_oob_pk_hash_known = 0;
9687
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07009688 if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_GO ||
9689 wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT) {
9690 /*
9691 * P2P Group Interface present and the command came on group
9692 * interface, so enable the token for the current interface.
9693 */
9694 wpa_s->create_p2p_iface = 0;
9695 } else {
9696 wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
9697 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009698
9699 if (wpa_s->create_p2p_iface) {
9700 enum wpa_driver_if_type iftype;
9701 /* Prepare to add a new interface for the group */
9702 iftype = WPA_IF_P2P_GROUP;
9703 if (go_intent == 15)
9704 iftype = WPA_IF_P2P_GO;
9705 if (wpas_p2p_add_group_interface(wpa_s, iftype) < 0) {
9706 wpa_printf(MSG_ERROR, "P2P: Failed to allocate a new "
9707 "interface for the group");
9708 return -1;
9709 }
9710
9711 if_addr = wpa_s->pending_interface_addr;
Dmitry Shmidt9c175262016-03-03 10:20:07 -08009712 } else if (wpa_s->p2p_mgmt)
9713 if_addr = wpa_s->parent->own_addr;
9714 else
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08009715 if_addr = wpa_s->own_addr;
9716
9717 wpa_s->p2p_nfc_tag_enabled = enabled;
9718
9719 for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
9720 struct hostapd_data *hapd;
9721 if (iface->ap_iface == NULL)
9722 continue;
9723 hapd = iface->ap_iface->bss[0];
9724 wpabuf_free(hapd->conf->wps_nfc_dh_pubkey);
9725 hapd->conf->wps_nfc_dh_pubkey =
9726 wpabuf_dup(wpa_s->conf->wps_nfc_dh_pubkey);
9727 wpabuf_free(hapd->conf->wps_nfc_dh_privkey);
9728 hapd->conf->wps_nfc_dh_privkey =
9729 wpabuf_dup(wpa_s->conf->wps_nfc_dh_privkey);
9730 wpabuf_free(hapd->conf->wps_nfc_dev_pw);
9731 hapd->conf->wps_nfc_dev_pw =
9732 wpabuf_dup(wpa_s->conf->wps_nfc_dev_pw);
9733 hapd->conf->wps_nfc_dev_pw_id = wpa_s->conf->wps_nfc_dev_pw_id;
9734
9735 if (hostapd_wps_nfc_token_enable(iface->ap_iface->bss[0]) < 0) {
9736 wpa_dbg(iface, MSG_DEBUG,
9737 "P2P: Failed to enable NFC Tag for GO");
9738 }
9739 }
9740 p2p_set_authorized_oob_dev_pw_id(
9741 wpa_s->global->p2p, wpa_s->conf->wps_nfc_dev_pw_id, go_intent,
9742 if_addr);
9743
9744 return 0;
9745}
9746
9747#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009748
9749
9750static void wpas_p2p_optimize_listen_channel(struct wpa_supplicant *wpa_s,
9751 struct wpa_used_freq_data *freqs,
9752 unsigned int num)
9753{
9754 u8 curr_chan, cand, chan;
9755 unsigned int i;
9756
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009757 /*
9758 * If possible, optimize the Listen channel to be a channel that is
9759 * already used by one of the other interfaces.
9760 */
9761 if (!wpa_s->conf->p2p_optimize_listen_chan)
9762 return;
9763
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009764 curr_chan = p2p_get_listen_channel(wpa_s->global->p2p);
9765 for (i = 0, cand = 0; i < num; i++) {
9766 ieee80211_freq_to_chan(freqs[i].freq, &chan);
9767 if (curr_chan == chan) {
9768 cand = 0;
9769 break;
9770 }
9771
9772 if (chan == 1 || chan == 6 || chan == 11)
9773 cand = chan;
9774 }
9775
9776 if (cand) {
9777 wpa_dbg(wpa_s, MSG_DEBUG,
Dmitry Shmidt216983b2015-02-06 10:50:36 -08009778 "P2P: Update Listen channel to %u based on operating channel",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009779 cand);
9780 p2p_set_listen_channel(wpa_s->global->p2p, 81, cand, 0);
9781 }
9782}
9783
9784
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009785static int wpas_p2p_move_go_csa(struct wpa_supplicant *wpa_s)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009786{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009787 struct hostapd_config *conf;
9788 struct p2p_go_neg_results params;
9789 struct csa_settings csa_settings;
9790 struct wpa_ssid *current_ssid = wpa_s->current_ssid;
9791 int old_freq = current_ssid->frequency;
9792 int ret;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009793
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009794 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) {
9795 wpa_dbg(wpa_s, MSG_DEBUG, "CSA is not enabled");
9796 return -1;
9797 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009798
9799 /*
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009800 * TODO: This function may not always work correctly. For example,
9801 * when we have a running GO and a BSS on a DFS channel.
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009802 */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08009803 if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, 0, 0,
9804 NULL)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009805 wpa_dbg(wpa_s, MSG_DEBUG,
9806 "P2P CSA: Failed to select new frequency for GO");
9807 return -1;
9808 }
9809
9810 if (current_ssid->frequency == params.freq) {
9811 wpa_dbg(wpa_s, MSG_DEBUG,
9812 "P2P CSA: Selected same frequency - not moving GO");
9813 return 0;
9814 }
9815
9816 conf = hostapd_config_defaults();
9817 if (!conf) {
9818 wpa_dbg(wpa_s, MSG_DEBUG,
9819 "P2P CSA: Failed to allocate default config");
9820 return -1;
9821 }
9822
9823 current_ssid->frequency = params.freq;
9824 if (wpa_supplicant_conf_ap_ht(wpa_s, current_ssid, conf)) {
9825 wpa_dbg(wpa_s, MSG_DEBUG,
9826 "P2P CSA: Failed to create new GO config");
9827 ret = -1;
9828 goto out;
9829 }
9830
Sunil4a3f9f52022-07-19 22:04:39 +00009831 if (conf->hw_mode != wpa_s->ap_iface->current_mode->mode &&
9832 (wpa_s->ap_iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A ||
Sunil Ravi89eba102022-09-13 21:04:37 -07009833 is_6ghz_freq(wpa_s->ap_iface->freq) ||
Sunil4a3f9f52022-07-19 22:04:39 +00009834 conf->hw_mode != HOSTAPD_MODE_IEEE80211G)) {
9835 wpa_dbg(wpa_s, MSG_INFO,
Sunil Ravi89eba102022-09-13 21:04:37 -07009836 "P2P CSA: CSA from hardware mode %d%s to %d is not supported",
9837 wpa_s->ap_iface->current_mode->mode,
9838 is_6ghz_freq(wpa_s->ap_iface->freq) ? " (6 GHz)" : "",
9839 conf->hw_mode);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009840 ret = -1;
9841 goto out;
9842 }
9843
9844 os_memset(&csa_settings, 0, sizeof(csa_settings));
9845 csa_settings.cs_count = P2P_GO_CSA_COUNT;
9846 csa_settings.block_tx = P2P_GO_CSA_BLOCK_TX;
9847 csa_settings.freq_params.freq = params.freq;
9848 csa_settings.freq_params.sec_channel_offset = conf->secondary_channel;
9849 csa_settings.freq_params.ht_enabled = conf->ieee80211n;
9850 csa_settings.freq_params.bandwidth = conf->secondary_channel ? 40 : 20;
9851
9852 if (conf->ieee80211ac) {
9853 int freq1 = 0, freq2 = 0;
9854 u8 chan, opclass;
9855
9856 if (ieee80211_freq_to_channel_ext(params.freq,
9857 conf->secondary_channel,
9858 conf->vht_oper_chwidth,
9859 &opclass, &chan) ==
9860 NUM_HOSTAPD_MODES) {
9861 wpa_printf(MSG_ERROR, "P2P CSA: Bad freq");
9862 ret = -1;
9863 goto out;
9864 }
9865
9866 if (conf->vht_oper_centr_freq_seg0_idx)
9867 freq1 = ieee80211_chan_to_freq(
9868 NULL, opclass,
9869 conf->vht_oper_centr_freq_seg0_idx);
9870
9871 if (conf->vht_oper_centr_freq_seg1_idx)
9872 freq2 = ieee80211_chan_to_freq(
9873 NULL, opclass,
9874 conf->vht_oper_centr_freq_seg1_idx);
9875
9876 if (freq1 < 0 || freq2 < 0) {
9877 wpa_dbg(wpa_s, MSG_DEBUG,
9878 "P2P CSA: Selected invalid VHT center freqs");
9879 ret = -1;
9880 goto out;
9881 }
9882
9883 csa_settings.freq_params.vht_enabled = conf->ieee80211ac;
9884 csa_settings.freq_params.center_freq1 = freq1;
9885 csa_settings.freq_params.center_freq2 = freq2;
9886
9887 switch (conf->vht_oper_chwidth) {
Sunil8cd6f4d2022-06-28 18:40:46 +00009888 case CONF_OPER_CHWIDTH_80MHZ:
9889 case CONF_OPER_CHWIDTH_80P80MHZ:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009890 csa_settings.freq_params.bandwidth = 80;
9891 break;
Sunil8cd6f4d2022-06-28 18:40:46 +00009892 case CONF_OPER_CHWIDTH_160MHZ:
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009893 csa_settings.freq_params.bandwidth = 160;
9894 break;
Sunil8cd6f4d2022-06-28 18:40:46 +00009895 default:
9896 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009897 }
9898 }
9899
9900 ret = ap_switch_channel(wpa_s, &csa_settings);
9901out:
9902 current_ssid->frequency = old_freq;
9903 hostapd_config_free(conf);
9904 return ret;
9905}
9906
9907
9908static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s)
9909{
9910 struct p2p_go_neg_results params;
9911 struct wpa_ssid *current_ssid = wpa_s->current_ssid;
Hai Shalom899fcc72020-10-19 14:38:18 -07009912 void (*ap_configured_cb)(void *ctx, void *data);
9913 void *ap_configured_cb_ctx, *ap_configured_cb_data;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009914
9915 wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_REMOVE_AND_REFORM_GROUP);
9916
9917 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Move GO from freq=%d MHz",
9918 current_ssid->frequency);
9919
9920 /* Stop the AP functionality */
9921 /* TODO: Should do this in a way that does not indicated to possible
9922 * P2P Clients in the group that the group is terminated. */
Hai Shalom899fcc72020-10-19 14:38:18 -07009923 /* If this action occurs before a group is started, the callback should
9924 * be preserved, or GROUP-STARTED event would be lost. If this action
9925 * occurs after a group is started, these pointers are all NULL and
9926 * harmless. */
9927 ap_configured_cb = wpa_s->ap_configured_cb;
9928 ap_configured_cb_ctx = wpa_s->ap_configured_cb_ctx;
9929 ap_configured_cb_data = wpa_s->ap_configured_cb_data;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009930 wpa_supplicant_ap_deinit(wpa_s);
9931
9932 /* Reselect the GO frequency */
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08009933 if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, 0, 0,
9934 NULL)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009935 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq");
9936 wpas_p2p_group_delete(wpa_s,
9937 P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL);
9938 return;
9939 }
9940 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New freq selected for the GO (%u MHz)",
9941 params.freq);
9942
9943 if (params.freq &&
9944 !p2p_supported_freq_go(wpa_s->global->p2p, params.freq)) {
9945 wpa_printf(MSG_DEBUG,
9946 "P2P: Selected freq (%u MHz) is not valid for P2P",
9947 params.freq);
9948 wpas_p2p_group_delete(wpa_s,
9949 P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL);
9950 return;
9951 }
9952
Hai Shalom899fcc72020-10-19 14:38:18 -07009953 /* Restore preserved callback parameters */
Jimmy Chen4b2a5022020-08-26 18:55:45 +08009954 wpa_s->ap_configured_cb = ap_configured_cb;
9955 wpa_s->ap_configured_cb_ctx = ap_configured_cb_ctx;
9956 wpa_s->ap_configured_cb_data = ap_configured_cb_data;
Hai Shalom899fcc72020-10-19 14:38:18 -07009957
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009958 /* Update the frequency */
9959 current_ssid->frequency = params.freq;
9960 wpa_s->connect_without_scan = current_ssid;
9961 wpa_s->reassociate = 1;
9962 wpa_s->disconnected = 0;
9963 wpa_supplicant_req_scan(wpa_s, 0, 0);
9964}
9965
9966
9967static void wpas_p2p_move_go(void *eloop_ctx, void *timeout_ctx)
9968{
9969 struct wpa_supplicant *wpa_s = eloop_ctx;
9970
9971 if (!wpa_s->ap_iface || !wpa_s->current_ssid)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009972 return;
9973
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009974 wpas_p2p_go_update_common_freqs(wpa_s);
9975
9976 /* Do not move GO in the middle of a CSA */
9977 if (hostapd_csa_in_progress(wpa_s->ap_iface)) {
9978 wpa_printf(MSG_DEBUG,
9979 "P2P: CSA is in progress - not moving GO");
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009980 return;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08009981 }
9982
9983 /*
9984 * First, try a channel switch flow. If it is not supported or fails,
9985 * take down the GO and bring it up again.
9986 */
9987 if (wpas_p2p_move_go_csa(wpa_s) < 0)
9988 wpas_p2p_move_go_no_csa(wpa_s);
9989}
9990
9991
9992static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx)
9993{
9994 struct wpa_supplicant *wpa_s = eloop_ctx;
9995 struct wpa_used_freq_data *freqs = NULL;
9996 unsigned int num = wpa_s->num_multichan_concurrent;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07009997
9998 freqs = os_calloc(num, sizeof(struct wpa_used_freq_data));
9999 if (!freqs)
10000 return;
10001
Sunil Ravi77d572f2023-01-17 23:58:31 +000010002 num = get_shared_radio_freqs_data(wpa_s, freqs, num, false);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -070010003
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010004 /* Previous attempt to move a GO was not possible -- try again. */
10005 wpas_p2p_consider_moving_gos(wpa_s, freqs, num,
10006 WPAS_P2P_CHANNEL_UPDATE_ANY);
10007
Dmitry Shmidt43cb5782014-06-16 16:23:22 -070010008 os_free(freqs);
10009}
10010
10011
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010012/*
10013 * Consider moving a GO from its currently used frequency:
10014 * 1. It is possible that due to regulatory consideration the frequency
10015 * can no longer be used and there is a need to evacuate the GO.
10016 * 2. It is possible that due to MCC considerations, it would be preferable
10017 * to move the GO to a channel that is currently used by some other
10018 * station interface.
10019 *
10020 * In case a frequency that became invalid is once again valid, cancel a
10021 * previously initiated GO frequency change.
10022 */
10023static void wpas_p2p_consider_moving_one_go(struct wpa_supplicant *wpa_s,
10024 struct wpa_used_freq_data *freqs,
10025 unsigned int num)
10026{
10027 unsigned int i, invalid_freq = 0, policy_move = 0, flags = 0;
10028 unsigned int timeout;
10029 int freq;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010030 int dfs_offload;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010031
10032 wpas_p2p_go_update_common_freqs(wpa_s);
10033
10034 freq = wpa_s->current_ssid->frequency;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010035 dfs_offload = (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
Roshan Pius3a1667e2018-07-03 15:17:14 -070010036 ieee80211_is_dfs(freq, wpa_s->hw.modes, wpa_s->hw.num_modes);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010037 for (i = 0, invalid_freq = 0; i < num; i++) {
10038 if (freqs[i].freq == freq) {
10039 flags = freqs[i].flags;
10040
10041 /* The channel is invalid, must change it */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010042 if (!p2p_supported_freq_go(wpa_s->global->p2p, freq) &&
10043 !dfs_offload) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010044 wpa_dbg(wpa_s, MSG_DEBUG,
10045 "P2P: Freq=%d MHz no longer valid for GO",
10046 freq);
10047 invalid_freq = 1;
10048 }
10049 } else if (freqs[i].flags == 0) {
10050 /* Freq is not used by any other station interface */
10051 continue;
10052 } else if (!p2p_supported_freq(wpa_s->global->p2p,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070010053 freqs[i].freq) && !dfs_offload) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080010054 /* Freq is not valid for P2P use cases */
10055 continue;
10056 } else if (wpa_s->conf->p2p_go_freq_change_policy ==
10057 P2P_GO_FREQ_MOVE_SCM) {
10058 policy_move = 1;
10059 } else if (wpa_s->conf->p2p_go_freq_change_policy ==
10060 P2P_GO_FREQ_MOVE_SCM_PEER_SUPPORTS &&
10061 wpas_p2p_go_is_peer_freq(wpa_s, freqs[i].freq)) {
10062 policy_move = 1;
10063 } else if ((wpa_s->conf->p2p_go_freq_change_policy ==
10064 P2P_GO_FREQ_MOVE_SCM_ECSA) &&
10065 wpas_p2p_go_is_peer_freq(wpa_s, freqs[i].freq)) {
10066 if (!p2p_get_group_num_members(wpa_s->p2p_group)) {
10067 policy_move = 1;
10068 } else if ((wpa_s->drv_flags &
10069 WPA_DRIVER_FLAGS_AP_CSA) &&
10070 wpas_p2p_go_clients_support_ecsa(wpa_s)) {
10071 u8 chan;
10072
10073 /*
10074 * We do not support CSA between bands, so move
10075 * GO only within the same band.
10076 */
10077 if (wpa_s->ap_iface->current_mode->mode ==
10078 ieee80211_freq_to_chan(freqs[i].freq,
10079 &chan))
10080 policy_move = 1;
10081 }
10082 }
10083 }
10084
10085 wpa_dbg(wpa_s, MSG_DEBUG,
10086 "P2P: GO move: invalid_freq=%u, policy_move=%u, flags=0x%X",
10087 invalid_freq, policy_move, flags);
10088
10089 /*
10090 * The channel is valid, or we are going to have a policy move, so
10091 * cancel timeout.
10092 */
10093 if (!invalid_freq || policy_move) {
10094 wpa_dbg(wpa_s, MSG_DEBUG,
10095 "P2P: Cancel a GO move from freq=%d MHz", freq);
10096 eloop_cancel_timeout(wpas_p2p_move_go, wpa_s, NULL);
10097
10098 if (wpas_p2p_in_progress(wpa_s)) {
10099 wpa_dbg(wpa_s, MSG_DEBUG,
10100 "P2P: GO move: policy CS is not allowed - setting timeout to re-consider GO move");
10101 eloop_cancel_timeout(wpas_p2p_reconsider_moving_go,
10102 wpa_s, NULL);
10103 eloop_register_timeout(P2P_RECONSIDER_GO_MOVE_DELAY, 0,
10104 wpas_p2p_reconsider_moving_go,
10105 wpa_s, NULL);
10106 return;
10107 }
10108 }
10109
10110 if (!invalid_freq && (!policy_move || flags != 0)) {
10111 wpa_dbg(wpa_s, MSG_DEBUG,
10112 "P2P: Not initiating a GO frequency change");
10113 return;
10114 }
10115
10116 /*
10117 * Do not consider moving GO if it is in the middle of a CSA. When the
10118 * CSA is finished this flow should be retriggered.
10119 */
10120 if (hostapd_csa_in_progress(wpa_s->ap_iface)) {
10121 wpa_dbg(wpa_s, MSG_DEBUG,
10122 "P2P: Not initiating a GO frequency change - CSA is in progress");
10123 return;
10124 }
10125
10126 if (invalid_freq && !wpas_p2p_disallowed_freq(wpa_s->global, freq))
10127 timeout = P2P_GO_FREQ_CHANGE_TIME;
10128 else
10129 timeout = 0;
10130
10131 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Move GO from freq=%d MHz in %d secs",
10132 freq, timeout);
10133 eloop_cancel_timeout(wpas_p2p_move_go, wpa_s, NULL);
10134 eloop_register_timeout(timeout, 0, wpas_p2p_move_go, wpa_s, NULL);
10135}
10136
10137
10138static void wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s,
10139 struct wpa_used_freq_data *freqs,
10140 unsigned int num,
10141 enum wpas_p2p_channel_update_trig trig)
10142{
10143 struct wpa_supplicant *ifs;
10144
10145 eloop_cancel_timeout(wpas_p2p_reconsider_moving_go, ELOOP_ALL_CTX,
10146 NULL);
10147
10148 /*
10149 * Travers all the radio interfaces, and for each GO interface, check
10150 * if there is a need to move the GO from the frequency it is using,
10151 * or in case the frequency is valid again, cancel the evacuation flow.
10152 */
10153 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
10154 radio_list) {
10155 if (ifs->current_ssid == NULL ||
10156 ifs->current_ssid->mode != WPAS_MODE_P2P_GO)
10157 continue;
10158
10159 /*
10160 * The GO was just started or completed channel switch, no need
10161 * to move it.
10162 */
10163 if (wpa_s == ifs &&
10164 (trig == WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE ||
10165 trig == WPAS_P2P_CHANNEL_UPDATE_CS)) {
10166 wpa_dbg(wpa_s, MSG_DEBUG,
10167 "P2P: GO move - schedule re-consideration");
10168 eloop_register_timeout(P2P_RECONSIDER_GO_MOVE_DELAY, 0,
10169 wpas_p2p_reconsider_moving_go,
10170 wpa_s, NULL);
10171 continue;
10172 }
10173
10174 wpas_p2p_consider_moving_one_go(ifs, freqs, num);
10175 }
10176}
10177
10178
10179void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s)
10180{
10181 if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
10182 return;
10183
10184 wpas_p2p_update_channel_list(wpa_s,
10185 WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE);
10186}
10187
10188
Dmitry Shmidt43cb5782014-06-16 16:23:22 -070010189void wpas_p2p_deinit_iface(struct wpa_supplicant *wpa_s)
10190{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -070010191 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
10192 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
10193 "the management interface is being removed");
10194 wpas_p2p_deinit_global(wpa_s->global);
10195 }
10196}
10197
10198
10199void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s)
10200{
10201 if (wpa_s->ap_iface->bss)
10202 wpa_s->ap_iface->bss[0]->p2p_group = NULL;
10203 wpas_p2p_group_deinit(wpa_s);
10204}
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -070010205
10206
10207int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
10208 unsigned int period, unsigned int interval,
10209 unsigned int count)
10210{
10211 struct p2p_data *p2p = wpa_s->global->p2p;
10212 u8 *device_types;
10213 size_t dev_types_len;
10214 struct wpabuf *buf;
10215 int ret;
10216
10217 if (wpa_s->p2p_lo_started) {
10218 wpa_dbg(wpa_s, MSG_DEBUG,
10219 "P2P Listen offload is already started");
10220 return 0;
10221 }
10222
10223 if (wpa_s->global->p2p == NULL ||
10224 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD)) {
10225 wpa_printf(MSG_DEBUG, "P2P: Listen offload not supported");
10226 return -1;
10227 }
10228
10229 if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
10230 wpa_printf(MSG_ERROR, "P2P: Input channel not supported: %u",
10231 freq);
10232 return -1;
10233 }
10234
10235 /* Get device type */
10236 dev_types_len = (wpa_s->conf->num_sec_device_types + 1) *
10237 WPS_DEV_TYPE_LEN;
10238 device_types = os_malloc(dev_types_len);
10239 if (!device_types)
10240 return -1;
10241 os_memcpy(device_types, wpa_s->conf->device_type, WPS_DEV_TYPE_LEN);
10242 os_memcpy(&device_types[WPS_DEV_TYPE_LEN], wpa_s->conf->sec_device_type,
10243 wpa_s->conf->num_sec_device_types * WPS_DEV_TYPE_LEN);
10244
10245 /* Get Probe Response IE(s) */
10246 buf = p2p_build_probe_resp_template(p2p, freq);
10247 if (!buf) {
10248 os_free(device_types);
10249 return -1;
10250 }
10251
10252 ret = wpa_drv_p2p_lo_start(wpa_s, freq, period, interval, count,
10253 device_types, dev_types_len,
10254 wpabuf_mhead_u8(buf), wpabuf_len(buf));
10255 if (ret < 0)
10256 wpa_dbg(wpa_s, MSG_DEBUG,
10257 "P2P: Failed to start P2P listen offload");
10258
10259 os_free(device_types);
10260 wpabuf_free(buf);
10261
10262 if (ret == 0) {
10263 wpa_s->p2p_lo_started = 1;
10264
10265 /* Stop current P2P listen if any */
10266 wpas_stop_listen(wpa_s);
10267 }
10268
10269 return ret;
10270}
10271
10272
10273int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s)
10274{
10275 int ret;
10276
10277 if (!wpa_s->p2p_lo_started)
10278 return 0;
10279
10280 ret = wpa_drv_p2p_lo_stop(wpa_s);
10281 if (ret < 0)
10282 wpa_dbg(wpa_s, MSG_DEBUG,
10283 "P2P: Failed to stop P2P listen offload");
10284
10285 wpa_s->p2p_lo_started = 0;
10286 return ret;
10287}