/*
* WPA Supplicant
- * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include "rsn_supp/pmksa_cache.h"
#include "common/wpa_ctrl.h"
#include "common/ieee802_11_defs.h"
+#include "common/hw_features_common.h"
#include "p2p/p2p.h"
#include "blacklist.h"
#include "wpas_glue.h"
const char *wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> and contributors";
const char *wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
wpa_tdls_deinit(wpa_s->wpa);
#endif /* CONFIG_TDLS */
+ wmm_ac_clear_saved_tspecs(wpa_s);
pmksa_candidate_free(wpa_s->wpa);
wpa_sm_deinit(wpa_s->wpa);
wpa_s->wpa = NULL;
os_free(wpa_s->manual_sched_scan_freqs);
wpa_s->manual_sched_scan_freqs = NULL;
+ wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL);
+
gas_query_deinit(wpa_s->gas);
wpa_s->gas = NULL;
#ifdef CONFIG_IEEE80211W
if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
- (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
- wpa_s->conf->pmf : ssid->ieee80211w) ==
- MGMT_FRAME_PROTECTION_REQUIRED) {
+ wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
"that does not support management frame protection - "
"reject");
sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
#endif /* CONFIG_SAE */
if (0) {
+#ifdef CONFIG_SUITEB192
+ } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
+ wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WPA: using KEY_MGMT 802.1X with Suite B (192-bit)");
+#endif /* CONFIG_SUITEB192 */
+#ifdef CONFIG_SUITEB
} else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B;
wpa_dbg(wpa_s, MSG_DEBUG,
"WPA: using KEY_MGMT 802.1X with Suite B");
+#endif /* CONFIG_SUITEB */
#ifdef CONFIG_IEEE80211R
} else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
#ifdef CONFIG_IEEE80211W
sel = ie.mgmt_group_cipher;
- if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
- wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
+ if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
!(ie.capabilities & WPA_CAPABILITY_MFPC))
sel = 0;
if (sel & WPA_CIPHER_AES_128_CMAC) {
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
wpa_s->mgmt_group_cipher);
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
- (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
- wpa_s->conf->pmf : ssid->ieee80211w));
+ wpas_get_ssid_pmf(wpa_s, ssid));
#endif /* CONFIG_IEEE80211W */
if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
else
rand_style = ssid->mac_addr;
+ wmm_ac_clear_saved_tspecs(wpa_s);
+ wpa_s->reassoc_same_bss = 0;
+
if (wpa_s->last_ssid == ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
+ if (wpa_s->current_bss && wpa_s->current_bss == bss) {
+ wmm_ac_save_tspecs(wpa_s);
+ wpa_s->reassoc_same_bss = 1;
+ }
} else if (rand_style > 0) {
if (wpas_update_random_addr(wpa_s, rand_style) < 0)
return;
}
+void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
+ const struct wpa_ssid *ssid,
+ struct hostapd_freq_params *freq)
+{
+ enum hostapd_hw_mode hw_mode;
+ struct hostapd_hw_modes *mode = NULL;
+ int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
+ 184, 192 };
+ struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
+ u8 channel;
+ int i, chan_idx, ht40 = -1, res;
+ unsigned int j;
+
+ freq->freq = ssid->frequency;
+
+ /* For IBSS check HT_IBSS flag */
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS))
+ return;
+
+ hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
+ for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
+ if (wpa_s->hw.modes[i].mode == hw_mode) {
+ mode = &wpa_s->hw.modes[i];
+ break;
+ }
+ }
+
+ if (!mode)
+ return;
+
+ freq->ht_enabled = ht_supported(mode);
+ if (!freq->ht_enabled)
+ return;
+
+ /* Setup higher BW only for 5 GHz */
+ if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return;
+
+ for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
+ pri_chan = &mode->channels[chan_idx];
+ if (pri_chan->chan == channel)
+ break;
+ pri_chan = NULL;
+ }
+ if (!pri_chan)
+ return;
+
+ /* Check primary channel flags */
+ if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
+ return;
+
+ /* Check/setup HT40+/HT40- */
+ for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
+ if (ht40plus[j] == channel) {
+ ht40 = 1;
+ break;
+ }
+ }
+
+ /* Find secondary channel */
+ for (i = 0; i < mode->num_channels; i++) {
+ sec_chan = &mode->channels[i];
+ if (sec_chan->chan == channel + ht40 * 4)
+ break;
+ sec_chan = NULL;
+ }
+ if (!sec_chan)
+ return;
+
+ /* Check secondary channel flags */
+ if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
+ return;
+
+ freq->channel = pri_chan->chan;
+
+ switch (ht40) {
+ case -1:
+ if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
+ return;
+ freq->sec_channel_offset = -1;
+ break;
+ case 1:
+ if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
+ return;
+ freq->sec_channel_offset = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (freq->sec_channel_offset) {
+ struct wpa_scan_results *scan_res;
+
+ scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
+ if (scan_res == NULL) {
+ /* Back to HT20 */
+ freq->sec_channel_offset = 0;
+ return;
+ }
+
+ res = check_40mhz_5g(mode, scan_res, pri_chan->chan,
+ sec_chan->chan);
+ switch (res) {
+ case 0:
+ /* Back to HT20 */
+ freq->sec_channel_offset = 0;
+ break;
+ case 1:
+ /* Configuration allowed */
+ break;
+ case 2:
+ /* Switch pri/sec channels */
+ freq->freq = hw_get_freq(mode, sec_chan->chan);
+ freq->sec_channel_offset = -freq->sec_channel_offset;
+ freq->channel = sec_chan->chan;
+ break;
+ default:
+ freq->sec_channel_offset = 0;
+ break;
+ }
+
+ wpa_scan_results_free(scan_res);
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
+ freq->channel, freq->sec_channel_offset);
+}
+
+
static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
{
struct wpa_connect_work *cwork = work->ctx;
}
}
+ if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
+ struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
+ size_t len;
+
+ len = sizeof(wpa_ie) - wpa_ie_len;
+ if (wpabuf_len(buf) <= len) {
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(buf), wpabuf_len(buf));
+ wpa_ie_len += wpabuf_len(buf);
+ }
+ }
+
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher;
/* Initial frequency for IBSS/mesh */
if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) &&
- ssid->frequency > 0 && params.freq.freq == 0) {
- enum hostapd_hw_mode hw_mode;
- u8 channel;
-
- params.freq.freq = ssid->frequency;
-
- hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
- for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
- if (wpa_s->hw.modes[i].mode == hw_mode) {
- struct hostapd_hw_modes *mode;
-
- mode = &wpa_s->hw.modes[i];
- params.freq.ht_enabled = ht_supported(mode);
- break;
- }
- }
- }
+ ssid->frequency > 0 && params.freq.freq == 0)
+ ibss_mesh_setup_freq(wpa_s, ssid, ¶ms.freq);
if (ssid->mode == WPAS_MODE_IBSS) {
if (ssid->beacon_int)
if (wpa_s->conf->key_mgmt_offload) {
if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
- params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B)
+ params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B ||
+ params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
params.req_key_mgmt_offload =
ssid->proactive_key_caching < 0 ?
wpa_s->conf->okc : ssid->proactive_key_caching;
params.drop_unencrypted = use_crypt;
#ifdef CONFIG_IEEE80211W
- params.mgmt_frame_protection =
- ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
- wpa_s->conf->pmf : ssid->ieee80211w;
+ params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid);
if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
struct wpa_ie_data ie;
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);
+ wpa_supplicant_apply_vht_overrides(wpa_s, ssid, ¶ms);
#endif /* CONFIG_VHT_OVERRIDES */
#ifdef CONFIG_P2P
wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
radio_list);
- if (wpa_s && wpa_s->external_scan_running) {
+ if (wpa_s && wpa_s->radio->external_scan_running) {
wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
return;
}
wpa_s->num_multichan_concurrent =
capa.num_multichan_concurrent;
wpa_s->wmm_ac_supported = capa.wmm_ac_supported;
+
+ if (capa.mac_addr_rand_scan_supported)
+ wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN;
+ if (wpa_s->sched_scan_supported &&
+ capa.mac_addr_rand_sched_scan_supported)
+ wpa_s->mac_addr_rand_supported |=
+ (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO);
}
if (wpa_s->max_remain_on_chan == 0)
wpa_s->max_remain_on_chan = 1000;
}
+int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+#ifdef CONFIG_IEEE80211W
+ if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
+ if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL &&
+ !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) {
+ /*
+ * Driver does not support BIP -- ignore pmf=1 default
+ * since the connection with PMF would fail and the
+ * configuration does not require PMF to be enabled.
+ */
+ return NO_MGMT_FRAME_PROTECTION;
+ }
+
+ return wpa_s->conf->pmf;
+ }
+
+ return ssid->ieee80211w;
+#else /* CONFIG_IEEE80211W */
+ return NO_MGMT_FRAME_PROTECTION;
+#endif /* CONFIG_IEEE80211W */
+}
+
+
int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
{
if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
if (wpa_supplicant_fast_associate(wpa_s) != 1)
wpa_supplicant_req_scan(wpa_s, 0, 0);
+ else
+ wpa_s->reattach = 0;
}
}
+#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
+/* Workaround different, undefined for Windows, error codes used here */
+#define ENOTCONN -1
+#define EOPNOTSUPP -1
+#define ECANCELED -1
+#endif
+
/**
* wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
* @wpa_s: Pointer to wpa_supplicant