os_free(wpa_s->confanother);
wpa_s->confanother = NULL;
+#ifdef CONFIG_P2P
+ os_free(wpa_s->conf_p2p_dev);
+ wpa_s->conf_p2p_dev = NULL;
+#endif /* CONFIG_P2P */
+
wpa_sm_set_eapol(wpa_s->wpa, NULL);
eapol_sm_deinit(wpa_s->eapol);
wpa_s->eapol = NULL;
os_free(wpa_s->manual_scan_freqs);
wpa_s->manual_scan_freqs = NULL;
+ os_free(wpa_s->manual_sched_scan_freqs);
+ wpa_s->manual_sched_scan_freqs = NULL;
+
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
wpa_s->normal_scans = 0;
}
- if (state == WPA_COMPLETED)
+ if (state == WPA_COMPLETED) {
wpas_connect_work_done(wpa_s);
+ /* Reinitialize normal_scan counter */
+ wpa_s->normal_scans = 0;
+ }
if (state != WPA_SCANNING)
wpa_supplicant_notify_scanning(wpa_s, 0);
wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
"AES-128-CMAC");
+ } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
+ wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
+ "BIP-GMAC-128");
+ } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
+ wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
+ "BIP-GMAC-256");
+ } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
+ wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
+ "BIP-CMAC-256");
} else {
wpa_s->mgmt_group_cipher = 0;
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
struct ieee80211_ht_capabilities htcaps;
struct ieee80211_ht_capabilities htcaps_mask;
#endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+ struct ieee80211_vht_capabilities vhtcaps;
+ struct ieee80211_vht_capabilities vhtcaps_mask;
+#endif /* CONFIG_VHT_OVERRIDES */
if (deinit) {
if (work->started) {
if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
params.freq == 0)
params.freq = ssid->frequency; /* Initial channel for IBSS */
+
+ if (ssid->mode == WPAS_MODE_IBSS) {
+ if (ssid->beacon_int)
+ params.beacon_int = ssid->beacon_int;
+ else
+ params.beacon_int = wpa_s->conf->beacon_int;
+ }
+
params.wpa_ie = wpa_ie;
params.wpa_ie_len = wpa_ie_len;
params.pairwise_suite = cipher_pairwise;
params.htcaps_mask = (u8 *) &htcaps_mask;
wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms);
#endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+ os_memset(&vhtcaps, 0, sizeof(vhtcaps));
+ os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
+ params.vhtcaps = &vhtcaps;
+ params.vhtcaps_mask = &vhtcaps_mask;
+ wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, ¶ms);
+#endif /* CONFIG_VHT_OVERRIDES */
#ifdef CONFIG_P2P
/*
* least prioritized connection.
*/
if (wpa_s->num_multichan_concurrent < 2) {
- int freq = wpa_drv_shared_freq(wpa_s);
- if (freq > 0 && freq != params.freq) {
- wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
+ int freq, num;
+ num = get_shared_radio_freqs(wpa_s, &freq, 1);
+ if (num > 0 && freq > 0 && freq != params.freq) {
+ wpa_printf(MSG_DEBUG,
+ "Assoc conflicting freq found (%d != %d)",
freq, params.freq);
if (wpas_p2p_handle_frequency_conflicts(wpa_s,
params.freq,
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
interface_count = 0;
}
- if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
+ if (!wpa_s->p2p_mgmt &&
+ wpa_supplicant_delayed_sched_scan(wpa_s,
+ interface_count % 3,
100000))
- wpa_supplicant_req_scan(wpa_s, interface_count,
+ wpa_supplicant_req_scan(wpa_s, interface_count % 3,
100000);
interface_count++;
} else
}
+static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s,
+ struct ieee80211_ht_capabilities *htcaps,
+ struct ieee80211_ht_capabilities *htcaps_mask,
+ int disabled)
+{
+ /* Masking these out disables LDPC */
+ u16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
+
+ wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
+
+ if (disabled)
+ htcaps->ht_capabilities_info &= ~msk;
+ else
+ htcaps->ht_capabilities_info |= msk;
+
+ htcaps_mask->ht_capabilities_info |= msk;
+
+ return 0;
+}
+
+
void wpa_supplicant_apply_ht_overrides(
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_driver_associate_params *params)
wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
+ wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
+
+ if (ssid->ht40_intolerant) {
+ u16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
+ htcaps->ht_capabilities_info |= bit;
+ htcaps_mask->ht_capabilities_info |= bit;
+ }
}
#endif /* CONFIG_HT_OVERRIDES */
{
struct ieee80211_vht_capabilities *vhtcaps;
struct ieee80211_vht_capabilities *vhtcaps_mask;
+#ifdef CONFIG_HT_OVERRIDES
+ int max_ampdu;
+ const u32 max_ampdu_mask = VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
+#endif /* CONFIG_HT_OVERRIDES */
if (!ssid)
return;
vhtcaps->vht_capabilities_info = ssid->vht_capa;
vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
+#ifdef CONFIG_HT_OVERRIDES
+ /* if max ampdu is <= 3, we have to make the HT cap the same */
+ if (ssid->vht_capa_mask & max_ampdu_mask) {
+ max_ampdu = (ssid->vht_capa & max_ampdu_mask) >>
+ find_first_bit(max_ampdu_mask);
+
+ max_ampdu = max_ampdu < 3 ? max_ampdu : 3;
+ wpa_set_ampdu_factor(wpa_s,
+ (void *) params->htcaps,
+ (void *) params->htcaps_mask,
+ max_ampdu);
+ }
+#endif /* CONFIG_HT_OVERRIDES */
+
#define OVERRIDE_MCS(i) \
if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
wpa_s->ifname, radio->name);
dl_list_del(&wpa_s->radio_list);
- if (!dl_list_empty(&radio->ifaces)) {
- wpa_s->radio = NULL;
+ radio_remove_works(wpa_s, NULL, 0);
+ wpa_s->radio = NULL;
+ if (!dl_list_empty(&radio->ifaces))
return; /* Interfaces remain for this radio */
- }
wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
- radio_remove_works(wpa_s, NULL, 0);
eloop_cancel_timeout(radio_start_next_work, radio, NULL);
- wpa_s->radio = NULL;
os_free(radio);
}
os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
}
- if (wpa_s->driver->get_radio_name)
- rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
- else
- rn = NULL;
+ rn = wpa_driver_get_radio_name(wpa_s);
if (rn && rn[0] == '\0')
rn = NULL;
wpa_s->confanother = os_rel2abs_path(iface->confanother);
wpa_config_read(wpa_s->confanother, wpa_s->conf);
+#ifdef CONFIG_P2P
+ wpa_s->conf_p2p_dev = os_rel2abs_path(iface->conf_p2p_dev);
+ wpa_config_read(wpa_s->conf_p2p_dev, wpa_s->conf);
+#endif /* CONFIG_P2P */
+
/*
* Override ctrl_interface and driver_param if set on command
* line.
wpa_supplicant_cleanup(wpa_s);
#ifdef CONFIG_P2P
+ if (wpa_s == wpa_s->parent)
+ wpas_p2p_group_remove(wpa_s, "*");
if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
"the management interface is being removed");
}
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
- !ssid->ext_psk)
+ (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
return 1;
return 0;
}
/* If get_radio_name is not supported, use only the local freq */
- if (!wpa_s->driver->get_radio_name) {
+ if (!wpa_driver_get_radio_name(wpa_s)) {
freq = wpa_drv_shared_freq(wpa_s);
if (freq > 0 && idx < len &&
(idx == 0 || freq_array[0] != freq))