if (ifmsh->mconf) {
mesh_mpm_deinit(wpa_s, ifmsh);
- if (ifmsh->mconf->ies) {
- ifmsh->mconf->ies = NULL;
+ if (ifmsh->mconf->rsn_ie) {
+ ifmsh->mconf->rsn_ie = NULL;
/* We cannot free this struct
* because wpa_authenticator on
* hostapd side is also using it
}
-static struct mesh_conf * mesh_config_create(struct wpa_ssid *ssid)
+static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
{
struct mesh_conf *conf;
+ int cipher;
conf = os_zalloc(sizeof(struct mesh_conf));
if (!conf)
MESH_CONF_SEC_AMPE;
else
conf->security |= MESH_CONF_SEC_NONE;
+ conf->ieee80211w = ssid->ieee80211w;
+ if (conf->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
+ if (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)
+ conf->ieee80211w = wpa_s->conf->pmf;
+ else
+ conf->ieee80211w = NO_MGMT_FRAME_PROTECTION;
+ }
+
+ cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 0);
+ if (cipher < 0 || cipher == WPA_CIPHER_TKIP) {
+ wpa_msg(wpa_s, MSG_INFO, "mesh: Invalid pairwise cipher");
+ os_free(conf);
+ return NULL;
+ }
+ conf->pairwise_cipher = cipher;
+
+ cipher = wpa_pick_group_cipher(ssid->group_cipher);
+ if (cipher < 0 || cipher == WPA_CIPHER_TKIP ||
+ cipher == WPA_CIPHER_GTK_NOT_USED) {
+ wpa_msg(wpa_s, MSG_INFO, "mesh: Invalid group cipher");
+ os_free(conf);
+ return NULL;
+ }
+
+ conf->group_cipher = cipher;
+ if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
+ conf->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
/* defaults */
conf->mesh_pp_id = MESH_PATH_PROTOCOL_HWMP;
ifmsh->bss[0] = bss = os_zalloc(sizeof(struct hostapd_data));
if (!bss)
goto out_free;
+ dl_list_init(&bss->nr_db);
os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
bss->driver = wpa_s->driver;
ifmsh->conf = conf;
ifmsh->bss[0]->max_plinks = wpa_s->conf->max_peer_links;
+ ifmsh->bss[0]->dot11RSNASAERetransPeriod =
+ wpa_s->conf->dot11RSNASAERetransPeriod;
os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface));
- mconf = mesh_config_create(ssid);
+ mconf = mesh_config_create(wpa_s, ssid);
if (!mconf)
goto out_free;
ifmsh->mconf = mconf;
/* need conf->hw_mode for supported rates. */
- if (ssid->frequency == 0) {
- conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
- conf->channel = 1;
- } else {
- conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
- &conf->channel);
- }
+ conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency, &conf->channel);
if (conf->hw_mode == NUM_HOSTAPD_MODES) {
wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz",
ssid->frequency);
goto out_free;
}
+ if (ssid->ht40)
+ conf->secondary_channel = ssid->ht40;
+ if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
+ conf->vht_oper_chwidth = ssid->max_oper_chwidth;
+ switch (conf->vht_oper_chwidth) {
+ case VHT_CHANWIDTH_80MHZ:
+ case VHT_CHANWIDTH_80P80MHZ:
+ ieee80211_freq_to_chan(
+ ssid->frequency,
+ &conf->vht_oper_centr_freq_seg0_idx);
+ conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
+ break;
+ case VHT_CHANWIDTH_160MHZ:
+ ieee80211_freq_to_chan(
+ ssid->frequency,
+ &conf->vht_oper_centr_freq_seg0_idx);
+ conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
+ conf->vht_oper_centr_freq_seg0_idx += 40 / 5;
+ break;
+ }
+ ieee80211_freq_to_chan(ssid->vht_center_freq2,
+ &conf->vht_oper_centr_freq_seg1_idx);
+ }
if (ssid->mesh_basic_rates == NULL) {
/*
wpa_supplicant_mesh_deinit(wpa_s);
+ wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
+ 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;
+ if (wpa_s->mesh_vht_enabled) {
+ ssid->vht = 1;
+ switch (params.freq.bandwidth) {
+ case 80:
+ if (params.freq.center_freq2) {
+ ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
+ ssid->vht_center_freq2 =
+ params.freq.center_freq2;
+ } else {
+ ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+ }
+ break;
+ case 160:
+ ssid->max_oper_chwidth = VHT_CHANWIDTH_160MHZ;
+ break;
+ default:
+ ssid->max_oper_chwidth = VHT_CHANWIDTH_USE_HT;
+ break;
+ }
+ }
if (ssid->beacon_int > 0)
params.beacon_int = ssid->beacon_int;
else if (wpa_s->conf->beacon_int > 0)
params.beacon_int = wpa_s->conf->beacon_int;
- params.max_peer_links = wpa_s->conf->max_peer_links;
+ if (ssid->dtim_period > 0)
+ 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;
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
if (wpa_s->conf->user_mpm) {
params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
- params.conf.flags &= ~WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
+ params.conf.auto_plinks = 0;
} else {
params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
- params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
+ params.conf.auto_plinks = 1;
}
params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
if (wpa_supplicant_mesh_init(wpa_s, ssid)) {
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->ies;
- params.ie_len = wpa_s->ifmsh->mconf->ie_len;
+ 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\n", 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);
+
out:
return ret;
}
ret = os_snprintf(pos, end - pos, "bss_basic_rate_set=%d",
bss_basic_rate_set[0]);
if (os_snprintf_error(end - pos, ret))
- return pos - buf;
+ goto fail;
pos += ret;
for (i = 1; i < bss_basic_rate_set_len; i++) {
ret = os_snprintf(pos, end - pos, " %d",
bss_basic_rate_set[i]);
if (os_snprintf_error(end - pos, ret))
- return pos - buf;
+ goto fail;
pos += ret;
}
ret = os_snprintf(pos, end - pos, "\n");
if (os_snprintf_error(end - pos, ret))
- return pos - buf;
+ goto fail;
pos += ret;
}
+fail:
os_free(bss_basic_rate_set);
return pos - buf;
if (!mesh_wpa_s) {
wpa_printf(MSG_ERROR,
"mesh: Failed to create new wpa_supplicant interface");
- wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
+ wpa_drv_if_remove(wpa_s, WPA_IF_MESH, ifname);
return -1;
}
mesh_wpa_s->mesh_if_created = 1;
return 0;
}
+
+
+int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr)
+{
+ return mesh_mpm_close_peer(wpa_s, addr);
+}
+
+
+int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int duration)
+{
+ return mesh_mpm_connect_peer(wpa_s, addr, duration);
+}