1/*
2 * WPA Supplicant - Basic mesh mode routines
3 * Copyright (c) 2013-2014, cozybit, Inc.  All rights reserved.
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "utils/eloop.h"
13#include "utils/uuid.h"
14#include "common/ieee802_11_defs.h"
15#include "common/wpa_ctrl.h"
16#include "common/hw_features_common.h"
17#include "ap/sta_info.h"
18#include "ap/hostapd.h"
19#include "ap/ieee802_11.h"
20#include "config_ssid.h"
21#include "config.h"
22#include "wpa_supplicant_i.h"
23#include "driver_i.h"
24#include "notify.h"
25#include "ap.h"
26#include "mesh_mpm.h"
27#include "mesh_rsn.h"
28#include "mesh.h"
29
30
31static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s,
32				       bool also_clear_hostapd)
33{
34	wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh,
35					 also_clear_hostapd);
36
37	if (also_clear_hostapd) {
38		wpa_s->ifmsh = NULL;
39		wpa_s->current_ssid = NULL;
40		os_free(wpa_s->mesh_params);
41		wpa_s->mesh_params = NULL;
42	}
43
44	os_free(wpa_s->mesh_rsn);
45	wpa_s->mesh_rsn = NULL;
46
47	if (!also_clear_hostapd)
48		wpa_supplicant_leave_mesh(wpa_s, false);
49}
50
51
52void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
53				      struct hostapd_iface *ifmsh,
54				      bool also_clear_hostapd)
55{
56	if (!ifmsh)
57		return;
58
59	if (ifmsh->mconf) {
60		mesh_mpm_deinit(wpa_s, ifmsh);
61		if (ifmsh->mconf->rsn_ie) {
62			ifmsh->mconf->rsn_ie = NULL;
63			/* We cannot free this struct
64			 * because wpa_authenticator on
65			 * hostapd side is also using it
66			 * for now just set to NULL and
67			 * let hostapd code free it.
68			 */
69		}
70		os_free(ifmsh->mconf);
71		ifmsh->mconf = NULL;
72	}
73
74	/* take care of shared data */
75	if (also_clear_hostapd) {
76		hostapd_interface_deinit(ifmsh);
77		hostapd_interface_free(ifmsh);
78	}
79}
80
81
82static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s,
83					     struct wpa_ssid *ssid)
84{
85	struct mesh_conf *conf;
86	int cipher;
87
88	conf = os_zalloc(sizeof(struct mesh_conf));
89	if (!conf)
90		return NULL;
91
92	os_memcpy(conf->meshid, ssid->ssid, ssid->ssid_len);
93	conf->meshid_len = ssid->ssid_len;
94
95	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE)
96		conf->security |= MESH_CONF_SEC_AUTH |
97			MESH_CONF_SEC_AMPE;
98	else
99		conf->security |= MESH_CONF_SEC_NONE;
100	conf->ieee80211w = ssid->ieee80211w;
101	if (conf->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
102		if (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)
103			conf->ieee80211w = wpa_s->conf->pmf;
104		else
105			conf->ieee80211w = NO_MGMT_FRAME_PROTECTION;
106	}
107#ifdef CONFIG_OCV
108	conf->ocv = ssid->ocv;
109#endif /* CONFIG_OCV */
110
111	cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 0);
112	if (cipher < 0 || cipher == WPA_CIPHER_TKIP) {
113		wpa_msg(wpa_s, MSG_INFO, "mesh: Invalid pairwise cipher");
114		os_free(conf);
115		return NULL;
116	}
117	conf->pairwise_cipher = cipher;
118
119	cipher = wpa_pick_group_cipher(ssid->group_cipher);
120	if (cipher < 0 || cipher == WPA_CIPHER_TKIP ||
121	    cipher == WPA_CIPHER_GTK_NOT_USED) {
122		wpa_msg(wpa_s, MSG_INFO, "mesh: Invalid group cipher");
123		os_free(conf);
124		return NULL;
125	}
126
127	conf->group_cipher = cipher;
128	if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
129		if (ssid->group_mgmt_cipher == WPA_CIPHER_BIP_GMAC_128 ||
130		    ssid->group_mgmt_cipher == WPA_CIPHER_BIP_GMAC_256 ||
131		    ssid->group_mgmt_cipher == WPA_CIPHER_BIP_CMAC_256)
132			conf->mgmt_group_cipher = ssid->group_mgmt_cipher;
133		else
134			conf->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
135	}
136
137	/* defaults */
138	conf->mesh_pp_id = MESH_PATH_PROTOCOL_HWMP;
139	conf->mesh_pm_id = MESH_PATH_METRIC_AIRTIME;
140	conf->mesh_cc_id = 0;
141	conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET;
142	conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0;
143	conf->mesh_fwding = ssid->mesh_fwding;
144	conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries;
145	conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout;
146	conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout;
147	conf->dot11MeshHoldingTimeout = ssid->dot11MeshHoldingTimeout;
148
149	return conf;
150}
151
152
153static void wpas_mesh_copy_groups(struct hostapd_data *bss,
154				  struct wpa_supplicant *wpa_s)
155{
156	int num_groups;
157	size_t groups_size;
158
159	for (num_groups = 0; wpa_s->conf->sae_groups[num_groups] > 0;
160	     num_groups++)
161		;
162
163	groups_size = (num_groups + 1) * sizeof(wpa_s->conf->sae_groups[0]);
164	bss->conf->sae_groups = os_malloc(groups_size);
165	if (bss->conf->sae_groups)
166		os_memcpy(bss->conf->sae_groups, wpa_s->conf->sae_groups,
167			  groups_size);
168}
169
170
171static int wpas_mesh_init_rsn(struct wpa_supplicant *wpa_s)
172{
173	struct hostapd_iface *ifmsh = wpa_s->ifmsh;
174	struct wpa_ssid *ssid = wpa_s->current_ssid;
175	struct hostapd_data *bss = ifmsh->bss[0];
176	static int default_groups[] = { 19, 20, 21, 25, 26, -1 };
177	const char *password;
178	size_t len;
179
180	password = ssid->sae_password;
181	if (!password)
182		password = ssid->passphrase;
183	if (!password) {
184		wpa_printf(MSG_ERROR,
185			   "mesh: Passphrase for SAE not configured");
186		return -1;
187	}
188
189	bss->conf->wpa = ssid->proto;
190	bss->conf->wpa_key_mgmt = ssid->key_mgmt;
191
192	if (wpa_s->conf->sae_groups && wpa_s->conf->sae_groups[0] > 0) {
193		wpas_mesh_copy_groups(bss, wpa_s);
194	} else {
195		bss->conf->sae_groups = os_memdup(default_groups,
196						  sizeof(default_groups));
197		if (!bss->conf->sae_groups)
198			return -1;
199	}
200
201	len = os_strlen(password);
202	bss->conf->ssid.wpa_passphrase = dup_binstr(password, len);
203
204	wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, ifmsh->mconf);
205	return !wpa_s->mesh_rsn ? -1 : 0;
206}
207
208
209static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s)
210{
211	struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
212	struct hostapd_iface *ifmsh = wpa_s->ifmsh;
213	struct he_capabilities *he_capab = NULL;
214
215	if (ifmsh->current_mode)
216		he_capab = &ifmsh->current_mode->he_capab[IEEE80211_MODE_MESH];
217
218	if (hostapd_set_freq_params(
219		    &params->freq,
220		    ifmsh->conf->hw_mode,
221		    ifmsh->freq,
222		    ifmsh->conf->channel,
223		    ifmsh->conf->enable_edmg,
224		    ifmsh->conf->edmg_channel,
225		    ifmsh->conf->ieee80211n,
226		    ifmsh->conf->ieee80211ac,
227		    ifmsh->conf->ieee80211ax,
228		    ifmsh->conf->secondary_channel,
229		    hostapd_get_oper_chwidth(ifmsh->conf),
230		    hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
231		    hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
232		    ifmsh->conf->vht_capab,
233		    he_capab)) {
234		wpa_printf(MSG_ERROR, "Error updating mesh frequency params");
235		wpa_supplicant_mesh_deinit(wpa_s, true);
236		return -1;
237	}
238
239	return 0;
240}
241
242
243static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
244{
245	struct hostapd_iface *ifmsh = wpa_s->ifmsh;
246	struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
247	struct wpa_ssid *ssid = wpa_s->current_ssid;
248	int ret;
249
250	if (!params || !ssid || !ifmsh) {
251		wpa_printf(MSG_ERROR, "mesh: %s called without active mesh",
252			   __func__);
253		return -1;
254	}
255
256	/*
257	 * Update channel configuration if the channel has changed since the
258	 * initial setting, i.e., due to DFS radar detection during CAC.
259	 */
260	if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) {
261		wpa_s->assoc_freq = ifmsh->freq;
262		ssid->frequency = ifmsh->freq;
263		if (wpas_mesh_update_freq_params(wpa_s) < 0)
264			return -1;
265	}
266
267	if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
268	    wpas_mesh_init_rsn(wpa_s)) {
269		wpa_printf(MSG_ERROR,
270			   "mesh: RSN initialization failed - deinit mesh");
271		wpa_supplicant_mesh_deinit(wpa_s, false);
272		return -1;
273	}
274
275	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
276		wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
277		wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
278		wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
279	}
280
281	params->ies = ifmsh->mconf->rsn_ie;
282	params->ie_len = ifmsh->mconf->rsn_ie_len;
283	params->basic_rates = ifmsh->basic_rates;
284	params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
285	params->conf.ht_opmode = ifmsh->bss[0]->iface->ht_op_mode;
286
287	wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
288		wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
289	ret = wpa_drv_join_mesh(wpa_s, params);
290	if (ret)
291		wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
292
293	/* hostapd sets the interface down until we associate */
294	wpa_drv_set_operstate(wpa_s, 1);
295
296	if (!ret) {
297		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
298
299		wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
300			wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
301			ssid->id);
302		wpas_notify_mesh_group_started(wpa_s, ssid);
303	}
304
305	return ret;
306}
307
308
309static void wpas_mesh_complete_cb(void *arg)
310{
311	struct wpa_supplicant *wpa_s = arg;
312
313	wpas_mesh_complete(wpa_s);
314}
315
316
317static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
318{
319	struct wpa_supplicant *wpa_s = ifmsh->owner;
320	struct hostapd_data *bss;
321
322	ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);
323
324	bss = ifmsh->bss[0];
325	bss->msg_ctx = wpa_s;
326	os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
327	bss->driver = wpa_s->driver;
328	bss->drv_priv = wpa_s->drv_priv;
329	bss->iface = ifmsh;
330	bss->mesh_sta_free_cb = mesh_mpm_free_sta;
331	bss->setup_complete_cb = wpas_mesh_complete_cb;
332	bss->setup_complete_cb_ctx = wpa_s;
333
334	bss->conf->start_disabled = 1;
335	bss->conf->mesh = MESH_ENABLED;
336	bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
337
338	if (wpa_drv_init_mesh(wpa_s)) {
339		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
340		return -1;
341	}
342
343	if (hostapd_setup_interface(ifmsh)) {
344		wpa_printf(MSG_ERROR,
345			   "Failed to initialize hostapd interface for mesh");
346		return -1;
347	}
348
349	return 0;
350}
351
352
353static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh)
354{
355	struct wpa_supplicant *wpa_s = ifmsh->owner;
356	size_t j;
357
358	wpa_supplicant_mesh_deinit(wpa_s, false);
359
360#ifdef NEED_AP_MLME
361	for (j = 0; j < ifmsh->num_bss; j++)
362		hostapd_cleanup_cs_params(ifmsh->bss[j]);
363#endif /* NEED_AP_MLME */
364
365	/* Same as hostapd_interface_deinit() without deinitializing control
366	 * interface */
367	for (j = 0; j < ifmsh->num_bss; j++) {
368		struct hostapd_data *hapd = ifmsh->bss[j];
369
370		hostapd_bss_deinit_no_free(hapd);
371		hostapd_free_hapd_data(hapd);
372	}
373
374	hostapd_cleanup_iface_partial(ifmsh);
375
376	return 0;
377}
378
379
380static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
381				    struct wpa_ssid *ssid,
382				    struct hostapd_freq_params *freq)
383{
384	struct hostapd_iface *ifmsh;
385	struct hostapd_data *bss;
386	struct hostapd_config *conf;
387	struct mesh_conf *mconf;
388	int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
389	int rate_len;
390	int frequency;
391
392	if (!wpa_s->conf->user_mpm) {
393		/* not much for us to do here */
394		wpa_msg(wpa_s, MSG_WARNING,
395			"user_mpm is not enabled in configuration");
396		return 0;
397	}
398
399	wpa_s->ifmsh = ifmsh = hostapd_alloc_iface();
400	if (!ifmsh)
401		return -ENOMEM;
402
403	ifmsh->owner = wpa_s;
404	ifmsh->drv_flags = wpa_s->drv_flags;
405	ifmsh->drv_flags2 = wpa_s->drv_flags2;
406	ifmsh->num_bss = 1;
407	ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb;
408	ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb;
409	ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
410			       sizeof(struct hostapd_data *));
411	if (!ifmsh->bss)
412		goto out_free;
413
414	ifmsh->bss[0] = bss = hostapd_alloc_bss_data(NULL, NULL, NULL);
415	if (!bss)
416		goto out_free;
417
418	ifmsh->bss[0]->msg_ctx = wpa_s;
419	os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
420	bss->driver = wpa_s->driver;
421	bss->drv_priv = wpa_s->drv_priv;
422	bss->iface = ifmsh;
423	bss->mesh_sta_free_cb = mesh_mpm_free_sta;
424	bss->setup_complete_cb = wpas_mesh_complete_cb;
425	bss->setup_complete_cb_ctx = wpa_s;
426	frequency = ssid->frequency;
427	if (frequency != freq->freq &&
428	    frequency == freq->freq + freq->sec_channel_offset * 20) {
429		wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched");
430		frequency = freq->freq;
431		ssid->frequency = frequency;
432	}
433	wpa_s->assoc_freq = frequency;
434	wpa_s->current_ssid = ssid;
435
436	/* setup an AP config for auth processing */
437	conf = hostapd_config_defaults();
438	if (!conf)
439		goto out_free;
440
441	if (is_6ghz_freq(freq->freq)) {
442		/*
443		 * IEEE Std 802.11ax-2021, 12.12.2:
444		 * The STA shall use management frame protection (MFPR=1) when
445		 * using RSN.
446		 */
447		ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
448
449		/* Set mandatory op_class parameter for setting up BSS */
450		switch (freq->bandwidth) {
451		case 20:
452			if (freq->freq == 5935)
453				conf->op_class = 136;
454			else
455				conf->op_class = 131;
456			break;
457		case 40:
458			conf->op_class = 132;
459			break;
460		case 80:
461			conf->op_class = 133;
462			break;
463		case 160:
464			conf->op_class = 134;
465			break;
466		default:
467			conf->op_class = 131;
468			break;
469		}
470	}
471
472	bss->conf = *conf->bss;
473	bss->conf->start_disabled = 1;
474	bss->conf->mesh = MESH_ENABLED;
475	bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
476	bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding;
477
478	if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
479			     wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
480		conf->ieee80211h = 1;
481		conf->ieee80211d = 1;
482		conf->country[0] = wpa_s->conf->country[0];
483		conf->country[1] = wpa_s->conf->country[1];
484		conf->country[2] = ' ';
485		wpa_s->mesh_params->handle_dfs = true;
486	}
487
488	bss->iconf = conf;
489	ifmsh->conf = conf;
490
491	ifmsh->bss[0]->max_plinks = wpa_s->conf->max_peer_links;
492	ifmsh->bss[0]->dot11RSNASAERetransPeriod =
493		wpa_s->conf->dot11RSNASAERetransPeriod;
494	os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface));
495
496	mconf = mesh_config_create(wpa_s, ssid);
497	if (!mconf)
498		goto out_free;
499	ifmsh->mconf = mconf;
500
501	/* need conf->hw_mode for supported rates. */
502	conf->hw_mode = ieee80211_freq_to_chan(frequency, &conf->channel);
503	if (conf->hw_mode == NUM_HOSTAPD_MODES) {
504		wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz",
505			   frequency);
506		goto out_free;
507	}
508
509	if (ssid->mesh_basic_rates == NULL) {
510		/*
511		 * XXX: Hack! This is so an MPM which correctly sets the ERP
512		 * mandatory rates as BSSBasicRateSet doesn't reject us. We
513		 * could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but
514		 * this is way easier. This also makes our BSSBasicRateSet
515		 * advertised in beacons match the one in peering frames, sigh.
516		 */
517		if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
518			conf->basic_rates = os_memdup(basic_rates_erp,
519						      sizeof(basic_rates_erp));
520			if (!conf->basic_rates)
521				goto out_free;
522		}
523	} else {
524		rate_len = 0;
525		while (1) {
526			if (ssid->mesh_basic_rates[rate_len] < 1)
527				break;
528			rate_len++;
529		}
530		conf->basic_rates = os_calloc(rate_len + 1, sizeof(int));
531		if (conf->basic_rates == NULL)
532			goto out_free;
533		os_memcpy(conf->basic_rates, ssid->mesh_basic_rates,
534			  rate_len * sizeof(int));
535		conf->basic_rates[rate_len] = -1;
536	}
537
538	/* While it can enhance performance to switch the primary channel, which
539	 * is also the secondary channel of another network at the same time),
540	 * to the other primary channel, problems exist with this in mesh
541	 * networks.
542	 *
543	 * Example with problems:
544	 *     - 3 mesh nodes M1-M3, freq (5200, 5180)
545	 *     - other node O1, e.g. AP mode, freq (5180, 5200),
546	 * Locations: O1 M1      M2      M3
547	 *
548	 * M3 can only send frames to M1 over M2, no direct connection is
549	 * possible
550	 * Start O1, M1 and M3 first, M1 or O1 will switch channels to align
551	 * with* each other. M3 does not swap, because M1 or O1 cannot be
552	 * reached. M2 is started afterwards and can either connect to M3 or M1
553	 * because of this primary secondary channel switch.
554	 *
555	 * Solutions: (1) central coordination -> not always possible
556	 *            (2) disable pri/sec channel switch in mesh networks
557	 *
558	 * In AP mode, when all nodes can work independently, this poses of
559	 * course no problem, therefore disable it only in mesh mode. */
560	conf->no_pri_sec_switch = 1;
561	wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
562
563	if (wpa_drv_init_mesh(wpa_s)) {
564		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
565		return -1;
566	}
567
568	if (hostapd_setup_interface(ifmsh)) {
569		wpa_printf(MSG_ERROR,
570			   "Failed to initialize hostapd interface for mesh");
571		return -1;
572	}
573
574	return 0;
575out_free:
576	wpa_supplicant_mesh_deinit(wpa_s, true);
577	return -ENOMEM;
578}
579
580
581void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
582			  const u8 *ies, size_t ie_len)
583{
584	struct ieee802_11_elems elems;
585
586	wpa_msg(wpa_s, MSG_INFO,
587		"new peer notification for " MACSTR, MAC2STR(addr));
588
589	if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed) {
590		wpa_msg(wpa_s, MSG_INFO, "Could not parse beacon from " MACSTR,
591			MAC2STR(addr));
592		return;
593	}
594	wpa_mesh_new_mesh_peer(wpa_s, addr, &elems);
595}
596
597
598void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s,
599				     struct wpabuf **extra_ie)
600{
601	/* EID + 0-length (wildcard) mesh-id */
602	size_t ielen = 2;
603
604	if (wpabuf_resize(extra_ie, ielen) == 0) {
605		wpabuf_put_u8(*extra_ie, WLAN_EID_MESH_ID);
606		wpabuf_put_u8(*extra_ie, 0);
607	}
608}
609
610
611int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
612			     struct wpa_ssid *ssid)
613{
614	struct wpa_driver_mesh_join_params *params = os_zalloc(sizeof(*params));
615	int ret = 0;
616
617	if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency ||
618	    !params) {
619		ret = -ENOENT;
620		os_free(params);
621		goto out;
622	}
623
624	wpa_supplicant_mesh_deinit(wpa_s, true);
625
626	wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
627	wpa_s->group_cipher = WPA_CIPHER_NONE;
628	wpa_s->mgmt_group_cipher = 0;
629
630	params->meshid = ssid->ssid;
631	params->meshid_len = ssid->ssid_len;
632	ibss_mesh_setup_freq(wpa_s, ssid, &params->freq);
633	wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
634	wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
635	wpa_s->mesh_he_enabled = !!params->freq.he_enabled;
636	if (params->freq.ht_enabled && params->freq.sec_channel_offset)
637		ssid->ht40 = params->freq.sec_channel_offset;
638
639	if (wpa_s->mesh_vht_enabled) {
640		ssid->vht = 1;
641		ssid->vht_center_freq1 = params->freq.center_freq1;
642		switch (params->freq.bandwidth) {
643		case 80:
644			if (params->freq.center_freq2) {
645				ssid->max_oper_chwidth = CHANWIDTH_80P80MHZ;
646				ssid->vht_center_freq2 =
647					params->freq.center_freq2;
648			} else {
649				ssid->max_oper_chwidth = CHANWIDTH_80MHZ;
650			}
651			break;
652		case 160:
653			ssid->max_oper_chwidth = CHANWIDTH_160MHZ;
654			break;
655		default:
656			ssid->max_oper_chwidth = CHANWIDTH_USE_HT;
657			break;
658		}
659	}
660	if (wpa_s->mesh_he_enabled)
661		ssid->he = 1;
662	if (ssid->beacon_int > 0)
663		params->beacon_int = ssid->beacon_int;
664	else if (wpa_s->conf->beacon_int > 0)
665		params->beacon_int = wpa_s->conf->beacon_int;
666	if (ssid->dtim_period > 0)
667		params->dtim_period = ssid->dtim_period;
668	else if (wpa_s->conf->dtim_period > 0)
669		params->dtim_period = wpa_s->conf->dtim_period;
670	params->conf.max_peer_links = wpa_s->conf->max_peer_links;
671	if (ssid->mesh_rssi_threshold < DEFAULT_MESH_RSSI_THRESHOLD) {
672		params->conf.rssi_threshold = ssid->mesh_rssi_threshold;
673		params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD;
674	}
675
676	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
677		params->flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
678		params->flags |= WPA_DRIVER_MESH_FLAG_AMPE;
679		wpa_s->conf->user_mpm = 1;
680	}
681
682	if (wpa_s->conf->user_mpm) {
683		params->flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
684		params->conf.auto_plinks = 0;
685	} else {
686		params->flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
687		params->conf.auto_plinks = 1;
688	}
689	params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
690
691	/* Always explicitely set forwarding to on or off for now */
692	params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_FORWARDING;
693	params->conf.forwarding = ssid->mesh_fwding;
694
695	os_free(wpa_s->mesh_params);
696	wpa_s->mesh_params = params;
697	if (wpa_supplicant_mesh_init(wpa_s, ssid, &params->freq)) {
698		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
699		wpa_supplicant_leave_mesh(wpa_s, true);
700		ret = -1;
701		goto out;
702	}
703
704out:
705	return ret;
706}
707
708
709int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, bool need_deinit)
710{
711	int ret = 0;
712
713	wpa_msg(wpa_s, MSG_INFO, "leaving mesh");
714
715	/* Need to send peering close messages first */
716	if (need_deinit)
717		wpa_supplicant_mesh_deinit(wpa_s, true);
718
719	ret = wpa_drv_leave_mesh(wpa_s);
720	if (ret)
721		wpa_msg(wpa_s, MSG_ERROR, "mesh leave error=%d", ret);
722
723	wpa_drv_set_operstate(wpa_s, 1);
724
725	return ret;
726}
727
728
729static int mesh_attr_text(const u8 *ies, size_t ies_len, char *buf, char *end)
730{
731	struct ieee802_11_elems elems;
732	char *mesh_id, *pos = buf;
733	u8 *bss_basic_rate_set;
734	int bss_basic_rate_set_len, ret, i;
735
736	if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed)
737		return -1;
738
739	if (elems.mesh_id_len < 1)
740		return 0;
741
742	mesh_id = os_malloc(elems.mesh_id_len + 1);
743	if (mesh_id == NULL)
744		return -1;
745
746	os_memcpy(mesh_id, elems.mesh_id, elems.mesh_id_len);
747	mesh_id[elems.mesh_id_len] = '\0';
748	ret = os_snprintf(pos, end - pos, "mesh_id=%s\n", mesh_id);
749	os_free(mesh_id);
750	if (os_snprintf_error(end - pos, ret))
751		return pos - buf;
752	pos += ret;
753
754	if (elems.mesh_config_len > 6) {
755		ret = os_snprintf(pos, end - pos,
756				  "active_path_selection_protocol_id=0x%02x\n"
757				  "active_path_selection_metric_id=0x%02x\n"
758				  "congestion_control_mode_id=0x%02x\n"
759				  "synchronization_method_id=0x%02x\n"
760				  "authentication_protocol_id=0x%02x\n"
761				  "mesh_formation_info=0x%02x\n"
762				  "mesh_capability=0x%02x\n",
763				  elems.mesh_config[0], elems.mesh_config[1],
764				  elems.mesh_config[2], elems.mesh_config[3],
765				  elems.mesh_config[4], elems.mesh_config[5],
766				  elems.mesh_config[6]);
767		if (os_snprintf_error(end - pos, ret))
768			return pos - buf;
769		pos += ret;
770	}
771
772	bss_basic_rate_set = os_malloc(elems.supp_rates_len +
773		elems.ext_supp_rates_len);
774	if (bss_basic_rate_set == NULL)
775		return -1;
776
777	bss_basic_rate_set_len = 0;
778	for (i = 0; i < elems.supp_rates_len; i++) {
779		if (elems.supp_rates[i] & 0x80) {
780			bss_basic_rate_set[bss_basic_rate_set_len++] =
781				(elems.supp_rates[i] & 0x7f) * 5;
782		}
783	}
784	for (i = 0; i < elems.ext_supp_rates_len; i++) {
785		if (elems.ext_supp_rates[i] & 0x80) {
786			bss_basic_rate_set[bss_basic_rate_set_len++] =
787				(elems.ext_supp_rates[i] & 0x7f) * 5;
788		}
789	}
790	if (bss_basic_rate_set_len > 0) {
791		ret = os_snprintf(pos, end - pos, "bss_basic_rate_set=%d",
792				  bss_basic_rate_set[0]);
793		if (os_snprintf_error(end - pos, ret))
794			goto fail;
795		pos += ret;
796
797		for (i = 1; i < bss_basic_rate_set_len; i++) {
798			ret = os_snprintf(pos, end - pos, " %d",
799					  bss_basic_rate_set[i]);
800			if (os_snprintf_error(end - pos, ret))
801				goto fail;
802			pos += ret;
803		}
804
805		ret = os_snprintf(pos, end - pos, "\n");
806		if (os_snprintf_error(end - pos, ret))
807			goto fail;
808		pos += ret;
809	}
810fail:
811	os_free(bss_basic_rate_set);
812
813	return pos - buf;
814}
815
816
817int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
818			       char *end)
819{
820	return mesh_attr_text(ies, ies_len, buf, end);
821}
822
823
824static int wpas_mesh_get_ifname(struct wpa_supplicant *wpa_s, char *ifname,
825				size_t len)
826{
827	char *ifname_ptr = wpa_s->ifname;
828	int res;
829
830	res = os_snprintf(ifname, len, "mesh-%s-%d", ifname_ptr,
831			  wpa_s->mesh_if_idx);
832	if (os_snprintf_error(len, res) ||
833	    (os_strlen(ifname) >= IFNAMSIZ &&
834	     os_strlen(wpa_s->ifname) < IFNAMSIZ)) {
835		/* Try to avoid going over the IFNAMSIZ length limit */
836		res = os_snprintf(ifname, len, "mesh-%d", wpa_s->mesh_if_idx);
837		if (os_snprintf_error(len, res))
838			return -1;
839	}
840	wpa_s->mesh_if_idx++;
841	return 0;
842}
843
844
845int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
846			    size_t len)
847{
848	struct wpa_interface iface;
849	struct wpa_supplicant *mesh_wpa_s;
850	u8 addr[ETH_ALEN];
851
852	if (ifname[0] == '\0' && wpas_mesh_get_ifname(wpa_s, ifname, len) < 0)
853		return -1;
854
855	if (wpa_drv_if_add(wpa_s, WPA_IF_MESH, ifname, NULL, NULL, NULL, addr,
856			   NULL) < 0) {
857		wpa_printf(MSG_ERROR,
858			   "mesh: Failed to create new mesh interface");
859		return -1;
860	}
861	wpa_printf(MSG_INFO, "mesh: Created virtual interface %s addr "
862		   MACSTR, ifname, MAC2STR(addr));
863
864	os_memset(&iface, 0, sizeof(iface));
865	iface.ifname = ifname;
866	iface.driver = wpa_s->driver->name;
867	iface.driver_param = wpa_s->conf->driver_param;
868	iface.ctrl_interface = wpa_s->conf->ctrl_interface;
869
870	mesh_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s);
871	if (!mesh_wpa_s) {
872		wpa_printf(MSG_ERROR,
873			   "mesh: Failed to create new wpa_supplicant interface");
874		wpa_drv_if_remove(wpa_s, WPA_IF_MESH, ifname);
875		return -1;
876	}
877	mesh_wpa_s->mesh_if_created = 1;
878	return 0;
879}
880
881
882int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr)
883{
884	return mesh_mpm_close_peer(wpa_s, addr);
885}
886
887
888int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr,
889		       int duration)
890{
891	return mesh_mpm_connect_peer(wpa_s, addr, duration);
892}
893