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 
wpa_supplicant_mesh_deinit(struct wpa_supplicant * wpa_s,bool also_clear_hostapd)31 static 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 
wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant * wpa_s,struct hostapd_iface * ifmsh,bool also_clear_hostapd)52 void 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 
mesh_config_create(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)82 static 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 
wpas_mesh_copy_groups(struct hostapd_data * bss,struct wpa_supplicant * wpa_s)153 static 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 
wpas_mesh_init_rsn(struct wpa_supplicant * wpa_s)171 static 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 
wpas_mesh_update_freq_params(struct wpa_supplicant * wpa_s)209 static 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->ieee80211be,
229                         ifmsh->conf->secondary_channel,
230                         hostapd_get_oper_chwidth(ifmsh->conf),
231                         hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
232                         hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
233                         ifmsh->conf->vht_capab,
234                         he_capab, NULL, 0)) {
235                     wpa_printf(MSG_ERROR, "Error updating mesh frequency params");
236                     wpa_supplicant_mesh_deinit(wpa_s, true);
237                     return -1;
238           }
239 
240           return 0;
241 }
242 
243 
wpas_mesh_complete(struct wpa_supplicant * wpa_s)244 static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
245 {
246           struct hostapd_iface *ifmsh = wpa_s->ifmsh;
247           struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
248           struct wpa_ssid *ssid = wpa_s->current_ssid;
249           int ret;
250 
251           if (!params || !ssid || !ifmsh) {
252                     wpa_printf(MSG_ERROR, "mesh: %s called without active mesh",
253                                  __func__);
254                     return -1;
255           }
256 
257           /*
258            * Update channel configuration if the channel has changed since the
259            * initial setting, i.e., due to DFS radar detection during CAC.
260            */
261           if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) {
262                     wpa_s->assoc_freq = ifmsh->freq;
263                     ssid->frequency = ifmsh->freq;
264                     if (wpas_mesh_update_freq_params(wpa_s) < 0)
265                               return -1;
266           }
267 
268           if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
269               wpas_mesh_init_rsn(wpa_s)) {
270                     wpa_printf(MSG_ERROR,
271                                  "mesh: RSN initialization failed - deinit mesh");
272                     wpa_supplicant_mesh_deinit(wpa_s, false);
273                     return -1;
274           }
275 
276           if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
277                     wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
278                     wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
279                     wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
280           }
281 
282           params->ies = ifmsh->mconf->rsn_ie;
283           params->ie_len = ifmsh->mconf->rsn_ie_len;
284           params->basic_rates = ifmsh->basic_rates;
285           params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
286           params->conf.ht_opmode = ifmsh->bss[0]->iface->ht_op_mode;
287 
288           wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
289                     wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
290           ret = wpa_drv_join_mesh(wpa_s, params);
291           if (ret)
292                     wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
293 
294           /* hostapd sets the interface down until we associate */
295           wpa_drv_set_operstate(wpa_s, 1);
296 
297           if (!ret) {
298                     wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
299 
300                     wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
301                               wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
302                               ssid->id);
303                     wpas_notify_mesh_group_started(wpa_s, ssid);
304           }
305 
306           return ret;
307 }
308 
309 
wpas_mesh_complete_cb(void * arg)310 static void wpas_mesh_complete_cb(void *arg)
311 {
312           struct wpa_supplicant *wpa_s = arg;
313 
314           wpas_mesh_complete(wpa_s);
315 }
316 
317 
wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface * ifmsh)318 static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
319 {
320           struct wpa_supplicant *wpa_s = ifmsh->owner;
321           struct hostapd_data *bss;
322 
323           ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);
324 
325           bss = ifmsh->bss[0];
326           bss->msg_ctx = wpa_s;
327           os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
328           bss->driver = wpa_s->driver;
329           bss->drv_priv = wpa_s->drv_priv;
330           bss->iface = ifmsh;
331           bss->mesh_sta_free_cb = mesh_mpm_free_sta;
332           bss->setup_complete_cb = wpas_mesh_complete_cb;
333           bss->setup_complete_cb_ctx = wpa_s;
334 
335           bss->conf->start_disabled = 1;
336           bss->conf->mesh = MESH_ENABLED;
337           bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
338 
339           if (wpa_drv_init_mesh(wpa_s)) {
340                     wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
341                     return -1;
342           }
343 
344           if (hostapd_setup_interface(ifmsh)) {
345                     wpa_printf(MSG_ERROR,
346                                  "Failed to initialize hostapd interface for mesh");
347                     return -1;
348           }
349 
350           return 0;
351 }
352 
353 
wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface * ifmsh)354 static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh)
355 {
356           struct wpa_supplicant *wpa_s = ifmsh->owner;
357           size_t j;
358 
359           wpa_supplicant_mesh_deinit(wpa_s, false);
360 
361 #ifdef NEED_AP_MLME
362           for (j = 0; j < ifmsh->num_bss; j++)
363                     hostapd_cleanup_cs_params(ifmsh->bss[j]);
364 #endif /* NEED_AP_MLME */
365 
366           /* Same as hostapd_interface_deinit() without deinitializing control
367            * interface */
368           for (j = 0; j < ifmsh->num_bss; j++) {
369                     struct hostapd_data *hapd = ifmsh->bss[j];
370 
371                     hostapd_bss_deinit_no_free(hapd);
372                     hostapd_free_hapd_data(hapd);
373           }
374 
375           hostapd_cleanup_iface_partial(ifmsh);
376 
377           return 0;
378 }
379 
380 
wpa_supplicant_mesh_init(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,struct hostapd_freq_params * freq)381 static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
382                                             struct wpa_ssid *ssid,
383                                             struct hostapd_freq_params *freq)
384 {
385           struct hostapd_iface *ifmsh;
386           struct hostapd_data *bss;
387           struct hostapd_config *conf;
388           struct mesh_conf *mconf;
389           int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 };
390           int rate_len;
391           int frequency;
392 
393           if (!wpa_s->conf->user_mpm) {
394                     /* not much for us to do here */
395                     wpa_msg(wpa_s, MSG_WARNING,
396                               "user_mpm is not enabled in configuration");
397                     return 0;
398           }
399 
400           wpa_s->ifmsh = ifmsh = hostapd_alloc_iface();
401           if (!ifmsh)
402                     return -ENOMEM;
403 
404           ifmsh->owner = wpa_s;
405           ifmsh->drv_flags = wpa_s->drv_flags;
406           ifmsh->drv_flags2 = wpa_s->drv_flags2;
407           ifmsh->num_bss = 1;
408           ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb;
409           ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb;
410           ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss,
411                                      sizeof(struct hostapd_data *));
412           if (!ifmsh->bss)
413                     goto out_free;
414 
415           ifmsh->bss[0] = bss = hostapd_alloc_bss_data(NULL, NULL, NULL);
416           if (!bss)
417                     goto out_free;
418 
419           ifmsh->bss[0]->msg_ctx = wpa_s;
420           os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
421           bss->driver = wpa_s->driver;
422           bss->drv_priv = wpa_s->drv_priv;
423           bss->iface = ifmsh;
424           bss->mesh_sta_free_cb = mesh_mpm_free_sta;
425           bss->setup_complete_cb = wpas_mesh_complete_cb;
426           bss->setup_complete_cb_ctx = wpa_s;
427           frequency = ssid->frequency;
428           if (frequency != freq->freq &&
429               frequency == freq->freq + freq->sec_channel_offset * 20) {
430                     wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched");
431                     frequency = freq->freq;
432                     ssid->frequency = frequency;
433           }
434           wpa_s->assoc_freq = frequency;
435           wpa_s->current_ssid = ssid;
436 
437           /* setup an AP config for auth processing */
438           conf = hostapd_config_defaults();
439           if (!conf)
440                     goto out_free;
441 
442           if (is_6ghz_freq(freq->freq)) {
443                     /*
444                      * IEEE Std 802.11ax-2021, 12.12.2:
445                      * The STA shall use management frame protection (MFPR=1) when
446                      * using RSN.
447                      */
448                     ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED;
449 
450                     /* Set mandatory op_class parameter for setting up BSS */
451                     switch (freq->bandwidth) {
452                     case 20:
453                               if (freq->freq == 5935)
454                                         conf->op_class = 136;
455                               else
456                                         conf->op_class = 131;
457                               break;
458                     case 40:
459                               conf->op_class = 132;
460                               break;
461                     case 80:
462                               conf->op_class = 133;
463                               break;
464                     case 160:
465                               conf->op_class = 134;
466                               break;
467                     default:
468                               conf->op_class = 131;
469                               break;
470                     }
471           }
472 
473           bss->conf = *conf->bss;
474           bss->conf->start_disabled = 1;
475           bss->conf->mesh = MESH_ENABLED;
476           bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
477           bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding;
478 
479           if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes,
480                                    wpa_s->hw.num_modes) && wpa_s->conf->country[0]) {
481                     conf->ieee80211h = 1;
482                     conf->ieee80211d = 1;
483                     conf->country[0] = wpa_s->conf->country[0];
484                     conf->country[1] = wpa_s->conf->country[1];
485                     conf->country[2] = ' ';
486                     wpa_s->mesh_params->handle_dfs = true;
487           }
488 
489           bss->iconf = conf;
490           ifmsh->conf = conf;
491 
492           ifmsh->bss[0]->max_plinks = wpa_s->conf->max_peer_links;
493           ifmsh->bss[0]->dot11RSNASAERetransPeriod =
494                     wpa_s->conf->dot11RSNASAERetransPeriod;
495           os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface));
496 
497           mconf = mesh_config_create(wpa_s, ssid);
498           if (!mconf)
499                     goto out_free;
500           ifmsh->mconf = mconf;
501 
502           /* need conf->hw_mode for supported rates. */
503           conf->hw_mode = ieee80211_freq_to_chan(frequency, &conf->channel);
504           if (conf->hw_mode == NUM_HOSTAPD_MODES) {
505                     wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz",
506                                  frequency);
507                     goto out_free;
508           }
509 
510           if (ssid->mesh_basic_rates == NULL) {
511                     /*
512                      * XXX: Hack! This is so an MPM which correctly sets the ERP
513                      * mandatory rates as BSSBasicRateSet doesn't reject us. We
514                      * could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but
515                      * this is way easier. This also makes our BSSBasicRateSet
516                      * advertised in beacons match the one in peering frames, sigh.
517                      */
518                     if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) {
519                               conf->basic_rates = os_memdup(basic_rates_erp,
520                                                                   sizeof(basic_rates_erp));
521                               if (!conf->basic_rates)
522                                         goto out_free;
523                     }
524           } else {
525                     rate_len = 0;
526                     while (1) {
527                               if (ssid->mesh_basic_rates[rate_len] < 1)
528                                         break;
529                               rate_len++;
530                     }
531                     conf->basic_rates = os_calloc(rate_len + 1, sizeof(int));
532                     if (conf->basic_rates == NULL)
533                               goto out_free;
534                     os_memcpy(conf->basic_rates, ssid->mesh_basic_rates,
535                                 rate_len * sizeof(int));
536                     conf->basic_rates[rate_len] = -1;
537           }
538 
539           /* While it can enhance performance to switch the primary channel, which
540            * is also the secondary channel of another network at the same time),
541            * to the other primary channel, problems exist with this in mesh
542            * networks.
543            *
544            * Example with problems:
545            *     - 3 mesh nodes M1-M3, freq (5200, 5180)
546            *     - other node O1, e.g. AP mode, freq (5180, 5200),
547            * Locations: O1 M1      M2      M3
548            *
549            * M3 can only send frames to M1 over M2, no direct connection is
550            * possible
551            * Start O1, M1 and M3 first, M1 or O1 will switch channels to align
552            * with* each other. M3 does not swap, because M1 or O1 cannot be
553            * reached. M2 is started afterwards and can either connect to M3 or M1
554            * because of this primary secondary channel switch.
555            *
556            * Solutions: (1) central coordination -> not always possible
557            *            (2) disable pri/sec channel switch in mesh networks
558            *
559            * In AP mode, when all nodes can work independently, this poses of
560            * course no problem, therefore disable it only in mesh mode. */
561           conf->no_pri_sec_switch = 1;
562           wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
563 
564           if (wpa_drv_init_mesh(wpa_s)) {
565                     wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
566                     return -1;
567           }
568 
569           if (hostapd_setup_interface(ifmsh)) {
570                     wpa_printf(MSG_ERROR,
571                                  "Failed to initialize hostapd interface for mesh");
572                     return -1;
573           }
574 
575           return 0;
576 out_free:
577           wpa_supplicant_mesh_deinit(wpa_s, true);
578           return -ENOMEM;
579 }
580 
581 
wpa_mesh_notify_peer(struct wpa_supplicant * wpa_s,const u8 * addr,const u8 * ies,size_t ie_len)582 void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
583                                 const u8 *ies, size_t ie_len)
584 {
585           struct ieee802_11_elems elems;
586 
587           wpa_msg(wpa_s, MSG_INFO,
588                     "new peer notification for " MACSTR, MAC2STR(addr));
589 
590           if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed) {
591                     wpa_msg(wpa_s, MSG_INFO, "Could not parse beacon from " MACSTR,
592                               MAC2STR(addr));
593                     return;
594           }
595           wpa_mesh_new_mesh_peer(wpa_s, addr, &elems);
596 }
597 
598 
wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant * wpa_s,struct wpabuf ** extra_ie)599 void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s,
600                                              struct wpabuf **extra_ie)
601 {
602           /* EID + 0-length (wildcard) mesh-id */
603           size_t ielen = 2;
604 
605           if (wpabuf_resize(extra_ie, ielen) == 0) {
606                     wpabuf_put_u8(*extra_ie, WLAN_EID_MESH_ID);
607                     wpabuf_put_u8(*extra_ie, 0);
608           }
609 }
610 
611 
wpa_supplicant_join_mesh(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid)612 int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
613                                    struct wpa_ssid *ssid)
614 {
615           struct wpa_driver_mesh_join_params *params = os_zalloc(sizeof(*params));
616           int ret = 0;
617 
618           if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency ||
619               !params) {
620                     ret = -ENOENT;
621                     os_free(params);
622                     goto out;
623           }
624 
625           wpa_supplicant_mesh_deinit(wpa_s, true);
626 
627           wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
628           wpa_s->group_cipher = WPA_CIPHER_NONE;
629           wpa_s->mgmt_group_cipher = 0;
630 
631           params->meshid = ssid->ssid;
632           params->meshid_len = ssid->ssid_len;
633           ibss_mesh_setup_freq(wpa_s, ssid, &params->freq);
634           wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
635           wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
636           wpa_s->mesh_he_enabled = !!params->freq.he_enabled;
637           wpa_s->mesh_eht_enabled = !!params->freq.eht_enabled;
638           if (params->freq.ht_enabled && params->freq.sec_channel_offset)
639                     ssid->ht40 = params->freq.sec_channel_offset;
640 
641           if (wpa_s->mesh_vht_enabled) {
642                     ssid->vht = 1;
643                     ssid->vht_center_freq1 = params->freq.center_freq1;
644                     switch (params->freq.bandwidth) {
645                     case 80:
646                               if (params->freq.center_freq2) {
647                                         ssid->max_oper_chwidth =
648                                                   CONF_OPER_CHWIDTH_80P80MHZ;
649                                         ssid->vht_center_freq2 =
650                                                   params->freq.center_freq2;
651                               } else {
652                                         ssid->max_oper_chwidth =
653                                                   CONF_OPER_CHWIDTH_80MHZ;
654                               }
655                               break;
656                     case 160:
657                               ssid->max_oper_chwidth = CONF_OPER_CHWIDTH_160MHZ;
658                               break;
659                     default:
660                               ssid->max_oper_chwidth = CONF_OPER_CHWIDTH_USE_HT;
661                               break;
662                     }
663           }
664           if (wpa_s->mesh_he_enabled)
665                     ssid->he = 1;
666           if (wpa_s->mesh_eht_enabled)
667                     ssid->eht = 1;
668           if (ssid->beacon_int > 0)
669                     params->beacon_int = ssid->beacon_int;
670           else if (wpa_s->conf->beacon_int > 0)
671                     params->beacon_int = wpa_s->conf->beacon_int;
672           if (ssid->dtim_period > 0)
673                     params->dtim_period = ssid->dtim_period;
674           else if (wpa_s->conf->dtim_period > 0)
675                     params->dtim_period = wpa_s->conf->dtim_period;
676           params->conf.max_peer_links = wpa_s->conf->max_peer_links;
677           if (ssid->mesh_rssi_threshold < DEFAULT_MESH_RSSI_THRESHOLD) {
678                     params->conf.rssi_threshold = ssid->mesh_rssi_threshold;
679                     params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD;
680           }
681 
682           if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
683                     params->flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
684                     params->flags |= WPA_DRIVER_MESH_FLAG_AMPE;
685                     wpa_s->conf->user_mpm = 1;
686           }
687 
688           if (wpa_s->conf->user_mpm) {
689                     params->flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
690                     params->conf.auto_plinks = 0;
691           } else {
692                     params->flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
693                     params->conf.auto_plinks = 1;
694           }
695           params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
696 
697           /* Always explicitely set forwarding to on or off for now */
698           params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_FORWARDING;
699           params->conf.forwarding = ssid->mesh_fwding;
700 
701           os_free(wpa_s->mesh_params);
702           wpa_s->mesh_params = params;
703           if (wpa_supplicant_mesh_init(wpa_s, ssid, &params->freq)) {
704                     wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
705                     wpa_supplicant_leave_mesh(wpa_s, true);
706                     ret = -1;
707                     goto out;
708           }
709 
710 out:
711           return ret;
712 }
713 
714 
wpa_supplicant_leave_mesh(struct wpa_supplicant * wpa_s,bool need_deinit)715 int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, bool need_deinit)
716 {
717           int ret = 0;
718 
719           wpa_msg(wpa_s, MSG_INFO, "leaving mesh");
720 
721           /* Need to send peering close messages first */
722           if (need_deinit)
723                     wpa_supplicant_mesh_deinit(wpa_s, true);
724 
725           ret = wpa_drv_leave_mesh(wpa_s);
726           if (ret)
727                     wpa_msg(wpa_s, MSG_ERROR, "mesh leave error=%d", ret);
728 
729           wpa_drv_set_operstate(wpa_s, 1);
730 
731           return ret;
732 }
733 
734 
mesh_attr_text(const u8 * ies,size_t ies_len,char * buf,char * end)735 static int mesh_attr_text(const u8 *ies, size_t ies_len, char *buf, char *end)
736 {
737           struct ieee802_11_elems elems;
738           char *mesh_id, *pos = buf;
739           u8 *bss_basic_rate_set;
740           int bss_basic_rate_set_len, ret, i;
741 
742           if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed)
743                     return -1;
744 
745           if (elems.mesh_id_len < 1)
746                     return 0;
747 
748           mesh_id = os_malloc(elems.mesh_id_len + 1);
749           if (mesh_id == NULL)
750                     return -1;
751 
752           os_memcpy(mesh_id, elems.mesh_id, elems.mesh_id_len);
753           mesh_id[elems.mesh_id_len] = '\0';
754           ret = os_snprintf(pos, end - pos, "mesh_id=%s\n", mesh_id);
755           os_free(mesh_id);
756           if (os_snprintf_error(end - pos, ret))
757                     return pos - buf;
758           pos += ret;
759 
760           if (elems.mesh_config_len > 6) {
761                     ret = os_snprintf(pos, end - pos,
762                                           "active_path_selection_protocol_id=0x%02x\n"
763                                           "active_path_selection_metric_id=0x%02x\n"
764                                           "congestion_control_mode_id=0x%02x\n"
765                                           "synchronization_method_id=0x%02x\n"
766                                           "authentication_protocol_id=0x%02x\n"
767                                           "mesh_formation_info=0x%02x\n"
768                                           "mesh_capability=0x%02x\n",
769                                           elems.mesh_config[0], elems.mesh_config[1],
770                                           elems.mesh_config[2], elems.mesh_config[3],
771                                           elems.mesh_config[4], elems.mesh_config[5],
772                                           elems.mesh_config[6]);
773                     if (os_snprintf_error(end - pos, ret))
774                               return pos - buf;
775                     pos += ret;
776           }
777 
778           bss_basic_rate_set = os_malloc(elems.supp_rates_len +
779                     elems.ext_supp_rates_len);
780           if (bss_basic_rate_set == NULL)
781                     return -1;
782 
783           bss_basic_rate_set_len = 0;
784           for (i = 0; i < elems.supp_rates_len; i++) {
785                     if (elems.supp_rates[i] & 0x80) {
786                               bss_basic_rate_set[bss_basic_rate_set_len++] =
787                                         (elems.supp_rates[i] & 0x7f) * 5;
788                     }
789           }
790           for (i = 0; i < elems.ext_supp_rates_len; i++) {
791                     if (elems.ext_supp_rates[i] & 0x80) {
792                               bss_basic_rate_set[bss_basic_rate_set_len++] =
793                                         (elems.ext_supp_rates[i] & 0x7f) * 5;
794                     }
795           }
796           if (bss_basic_rate_set_len > 0) {
797                     ret = os_snprintf(pos, end - pos, "bss_basic_rate_set=%d",
798                                           bss_basic_rate_set[0]);
799                     if (os_snprintf_error(end - pos, ret))
800                               goto fail;
801                     pos += ret;
802 
803                     for (i = 1; i < bss_basic_rate_set_len; i++) {
804                               ret = os_snprintf(pos, end - pos, " %d",
805                                                     bss_basic_rate_set[i]);
806                               if (os_snprintf_error(end - pos, ret))
807                                         goto fail;
808                               pos += ret;
809                     }
810 
811                     ret = os_snprintf(pos, end - pos, "\n");
812                     if (os_snprintf_error(end - pos, ret))
813                               goto fail;
814                     pos += ret;
815           }
816 fail:
817           os_free(bss_basic_rate_set);
818 
819           return pos - buf;
820 }
821 
822 
wpas_mesh_scan_result_text(const u8 * ies,size_t ies_len,char * buf,char * end)823 int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
824                                      char *end)
825 {
826           return mesh_attr_text(ies, ies_len, buf, end);
827 }
828 
829 
wpas_mesh_get_ifname(struct wpa_supplicant * wpa_s,char * ifname,size_t len)830 static int wpas_mesh_get_ifname(struct wpa_supplicant *wpa_s, char *ifname,
831                                         size_t len)
832 {
833           char *ifname_ptr = wpa_s->ifname;
834           int res;
835 
836           res = os_snprintf(ifname, len, "mesh-%s-%d", ifname_ptr,
837                                 wpa_s->mesh_if_idx);
838           if (os_snprintf_error(len, res) ||
839               (os_strlen(ifname) >= IFNAMSIZ &&
840                os_strlen(wpa_s->ifname) < IFNAMSIZ)) {
841                     /* Try to avoid going over the IFNAMSIZ length limit */
842                     res = os_snprintf(ifname, len, "mesh-%d", wpa_s->mesh_if_idx);
843                     if (os_snprintf_error(len, res))
844                               return -1;
845           }
846           wpa_s->mesh_if_idx++;
847           return 0;
848 }
849 
850 
wpas_mesh_add_interface(struct wpa_supplicant * wpa_s,char * ifname,size_t len)851 int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
852                                   size_t len)
853 {
854           struct wpa_interface iface;
855           struct wpa_supplicant *mesh_wpa_s;
856           u8 addr[ETH_ALEN];
857 
858           if (ifname[0] == '\0' && wpas_mesh_get_ifname(wpa_s, ifname, len) < 0)
859                     return -1;
860 
861           if (wpa_drv_if_add(wpa_s, WPA_IF_MESH, ifname, NULL, NULL, NULL, addr,
862                                  NULL) < 0) {
863                     wpa_printf(MSG_ERROR,
864                                  "mesh: Failed to create new mesh interface");
865                     return -1;
866           }
867           wpa_printf(MSG_INFO, "mesh: Created virtual interface %s addr "
868                        MACSTR, ifname, MAC2STR(addr));
869 
870           os_memset(&iface, 0, sizeof(iface));
871           iface.ifname = ifname;
872           iface.driver = wpa_s->driver->name;
873           iface.driver_param = wpa_s->conf->driver_param;
874           iface.ctrl_interface = wpa_s->conf->ctrl_interface;
875 
876           mesh_wpa_s = wpa_supplicant_add_iface(wpa_s->global, &iface, wpa_s);
877           if (!mesh_wpa_s) {
878                     wpa_printf(MSG_ERROR,
879                                  "mesh: Failed to create new wpa_supplicant interface");
880                     wpa_drv_if_remove(wpa_s, WPA_IF_MESH, ifname);
881                     return -1;
882           }
883           mesh_wpa_s->mesh_if_created = 1;
884           return 0;
885 }
886 
887 
wpas_mesh_peer_remove(struct wpa_supplicant * wpa_s,const u8 * addr)888 int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr)
889 {
890           return mesh_mpm_close_peer(wpa_s, addr);
891 }
892 
893 
wpas_mesh_peer_add(struct wpa_supplicant * wpa_s,const u8 * addr,int duration)894 int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr,
895                            int duration)
896 {
897           return mesh_mpm_connect_peer(wpa_s, addr, duration);
898 }
899