diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index cb995a56f..b559aafb4 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -34,6 +34,8 @@ static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s) wpa_s->current_ssid = NULL; os_free(wpa_s->mesh_rsn); wpa_s->mesh_rsn = NULL; + os_free(wpa_s->mesh_params); + wpa_s->mesh_params = NULL; /* TODO: leave mesh (stop beacon). This will happen on link down * anyway, so it's not urgent */ } @@ -188,6 +190,49 @@ static int wpas_mesh_init_rsn(struct wpa_supplicant *wpa_s) } +static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) +{ + struct hostapd_iface *ifmsh = wpa_s->ifmsh; + struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params; + struct wpa_ssid *ssid = wpa_s->current_ssid; + int ret; + + if (!params || !ssid) { + wpa_printf(MSG_ERROR, "mesh: %s called without active mesh", + __func__); + return -1; + } + + if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { + wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher; + wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher; + wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher; + } + + if (ifmsh) { + params->ies = ifmsh->mconf->rsn_ie; + params->ie_len = ifmsh->mconf->rsn_ie_len; + params->basic_rates = ifmsh->basic_rates; + params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE; + params->conf.ht_opmode = ifmsh->bss[0]->iface->ht_op_mode; + } + + wpa_msg(wpa_s, MSG_INFO, "joining mesh %s", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + ret = wpa_drv_join_mesh(wpa_s, params); + if (ret) + wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret); + + /* hostapd sets the interface down until we associate */ + wpa_drv_set_operstate(wpa_s, 1); + + if (!ret) + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + + return ret; +} + + static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_freq_params *freq) @@ -375,11 +420,13 @@ void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s, int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { - struct wpa_driver_mesh_join_params params; + struct wpa_driver_mesh_join_params *params = os_zalloc(sizeof(*params)); int ret = 0; - if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) { + if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency || + !params) { ret = -ENOENT; + os_free(params); goto out; } @@ -389,22 +436,22 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, wpa_s->group_cipher = WPA_CIPHER_NONE; wpa_s->mgmt_group_cipher = 0; - os_memset(¶ms, 0, sizeof(params)); - params.meshid = ssid->ssid; - params.meshid_len = ssid->ssid_len; - ibss_mesh_setup_freq(wpa_s, ssid, ¶ms.freq); - wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled; - wpa_s->mesh_vht_enabled = !!params.freq.vht_enabled; - if (params.freq.ht_enabled && params.freq.sec_channel_offset) - ssid->ht40 = params.freq.sec_channel_offset; + params->meshid = ssid->ssid; + params->meshid_len = ssid->ssid_len; + ibss_mesh_setup_freq(wpa_s, ssid, ¶ms->freq); + wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled; + wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled; + if (params->freq.ht_enabled && params->freq.sec_channel_offset) + ssid->ht40 = params->freq.sec_channel_offset; + if (wpa_s->mesh_vht_enabled) { ssid->vht = 1; - switch (params.freq.bandwidth) { + switch (params->freq.bandwidth) { case 80: - if (params.freq.center_freq2) { + if (params->freq.center_freq2) { ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ; ssid->vht_center_freq2 = - params.freq.center_freq2; + params->freq.center_freq2; } else { ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ; } @@ -418,67 +465,44 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, } } if (ssid->beacon_int > 0) - params.beacon_int = ssid->beacon_int; + params->beacon_int = ssid->beacon_int; else if (wpa_s->conf->beacon_int > 0) - params.beacon_int = wpa_s->conf->beacon_int; + params->beacon_int = wpa_s->conf->beacon_int; if (ssid->dtim_period > 0) - params.dtim_period = ssid->dtim_period; + params->dtim_period = ssid->dtim_period; else if (wpa_s->conf->dtim_period > 0) - params.dtim_period = wpa_s->conf->dtim_period; - params.conf.max_peer_links = wpa_s->conf->max_peer_links; + params->dtim_period = wpa_s->conf->dtim_period; + params->conf.max_peer_links = wpa_s->conf->max_peer_links; if (ssid->mesh_rssi_threshold < DEFAULT_MESH_RSSI_THRESHOLD) { - params.conf.rssi_threshold = ssid->mesh_rssi_threshold; - params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD; + params->conf.rssi_threshold = ssid->mesh_rssi_threshold; + params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD; } if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { - params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH; - params.flags |= WPA_DRIVER_MESH_FLAG_AMPE; + params->flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH; + params->flags |= WPA_DRIVER_MESH_FLAG_AMPE; wpa_s->conf->user_mpm = 1; } if (wpa_s->conf->user_mpm) { - params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM; - params.conf.auto_plinks = 0; + params->flags |= WPA_DRIVER_MESH_FLAG_USER_MPM; + params->conf.auto_plinks = 0; } else { - params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM; - params.conf.auto_plinks = 1; + params->flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM; + params->conf.auto_plinks = 1; } - params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity; + params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity; - if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms.freq)) { + os_free(wpa_s->mesh_params); + wpa_s->mesh_params = params; + if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) { wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh"); wpa_drv_leave_mesh(wpa_s); ret = -1; goto out; } - if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { - wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher; - wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher; - wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher; - } - - if (wpa_s->ifmsh) { - params.ies = wpa_s->ifmsh->mconf->rsn_ie; - params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len; - params.basic_rates = wpa_s->ifmsh->basic_rates; - params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE; - params.conf.ht_opmode = wpa_s->ifmsh->bss[0]->iface->ht_op_mode; - } - - wpa_msg(wpa_s, MSG_INFO, "joining mesh %s", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - ret = wpa_drv_join_mesh(wpa_s, ¶ms); - if (ret) - wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret); - - /* hostapd sets the interface down until we associate */ - wpa_drv_set_operstate(wpa_s, 1); - - if (!ret) - wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - + ret = wpas_mesh_complete(wpa_s); out: return ret; } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 46c4715df..d5ce1fb17 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -820,6 +820,7 @@ struct wpa_supplicant { unsigned int mesh_if_created:1; unsigned int mesh_ht_enabled:1; unsigned int mesh_vht_enabled:1; + struct wpa_driver_mesh_join_params *mesh_params; #ifdef CONFIG_PMKSA_CACHE_EXTERNAL /* struct external_pmksa_cache::list */ struct dl_list mesh_external_pmksa_cache;