aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSudhir Sharma <sudhshar@codeaurora.org>2015-03-11 14:49:35 -0700
committerSudhir Sharma <sudhshar@codeaurora.org>2015-03-11 14:50:07 -0700
commit72496cfdb23ceea248638c4dc660cf69e6ba670e (patch)
tree912487ae2887ac2f9acd66be284a4157a5b3c6c4 /src
parentc864c68989f4a594220e0cede848dd49ee5af46b (diff)
parent8ad28599aadb8960cfdb4f4a7c2fdd619fbb2d24 (diff)
downloadandroid_external_wpa_supplicant_8-72496cfdb23ceea248638c4dc660cf69e6ba670e.tar.gz
android_external_wpa_supplicant_8-72496cfdb23ceea248638c4dc660cf69e6ba670e.tar.bz2
android_external_wpa_supplicant_8-72496cfdb23ceea248638c4dc660cf69e6ba670e.zip
Merge tag 'AU_LINUX_ANDROID_LA.BF64.1.2.1_RB2.05.00.02.081.002' into HEAD
"AU_LINUX_ANDROID_LA.BF64.1.2.1_RB2.05.00.02.081.002" Conflicts: src/utils/http_curl.c Change-Id: I31aaf07069a70607c3d0486f505dc89f4062225b
Diffstat (limited to 'src')
-rw-r--r--src/ap/ap_config.c2
-rw-r--r--src/ap/dfs.c70
-rw-r--r--src/ap/drv_callbacks.c5
-rw-r--r--src/ap/hostapd.c47
-rw-r--r--src/ap/ieee802_1x.c10
-rw-r--r--src/ap/pmksa_cache_auth.c65
-rw-r--r--src/ap/sta_info.c2
-rw-r--r--src/ap/sta_info.h3
-rw-r--r--src/ap/wpa_auth.c3
-rw-r--r--src/ap/wpa_auth_ft.c22
-rw-r--r--src/common/qca-vendor.h21
-rw-r--r--src/common/version.h2
-rw-r--r--src/common/wpa_ctrl.h7
-rw-r--r--src/crypto/aes-unwrap.c19
-rw-r--r--src/crypto/aes-wrap.c20
-rw-r--r--src/crypto/aes_wrap.h8
-rw-r--r--src/crypto/crypto_openssl.c9
-rw-r--r--src/crypto/tls_openssl.c34
-rw-r--r--src/drivers/driver.h74
-rw-r--r--src/drivers/driver_common.c21
-rw-r--r--src/drivers/driver_nl80211.c393
-rw-r--r--src/drivers/driver_test.c2
-rw-r--r--src/drivers/driver_wext.c3
-rw-r--r--src/drivers/drivers.mak4
-rw-r--r--src/drivers/drivers.mk4
-rw-r--r--src/drivers/nl80211_copy.h158
-rw-r--r--src/eap_common/eap_pwd_common.c2
-rw-r--r--src/eap_server/eap_server_fast.c8
-rw-r--r--src/eap_server/eap_server_pax.c9
-rw-r--r--src/eapol_supp/eapol_supp_sm.c17
-rw-r--r--src/eapol_supp/eapol_supp_sm.h5
-rw-r--r--src/p2p/p2p.c22
-rw-r--r--src/p2p/p2p_utils.c3
-rw-r--r--src/pae/ieee802_1x_kay.c4
-rw-r--r--src/radius/radius_client.c22
-rw-r--r--src/radius/radius_server.c4
-rw-r--r--src/rsn_supp/pmksa_cache.c2
-rw-r--r--src/rsn_supp/tdls.c60
-rw-r--r--src/rsn_supp/wpa.c5
-rw-r--r--src/rsn_supp/wpa.h4
-rw-r--r--src/rsn_supp/wpa_ft.c5
-rw-r--r--src/rsn_supp/wpa_i.h14
-rw-r--r--src/utils/browser-android.c6
-rw-r--r--src/utils/browser-system.c2
-rw-r--r--src/utils/browser-wpadebug.c13
-rw-r--r--src/utils/common.c24
-rw-r--r--src/utils/common.h3
-rw-r--r--src/utils/http_curl.c3
-rw-r--r--src/wps/wps_enrollee.c12
-rw-r--r--src/wps/wps_registrar.c11
50 files changed, 964 insertions, 304 deletions
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index d1275509..c7da69e0 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -761,7 +761,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
bss->disable_11n = 1;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
- "allowed, disabling HT capabilites");
+ "allowed, disabling HT capabilities");
}
if (full_config && conf->ieee80211n &&
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 20419f32..a6ec20bd 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -18,10 +18,12 @@
#include "dfs.h"
-static int dfs_get_used_n_chans(struct hostapd_iface *iface)
+static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
{
int n_chans = 1;
+ *seg1 = 0;
+
if (iface->conf->ieee80211n && iface->conf->secondary_channel)
n_chans = 2;
@@ -35,6 +37,10 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface)
case VHT_CHANWIDTH_160MHZ:
n_chans = 8;
break;
+ case VHT_CHANWIDTH_80P80MHZ:
+ n_chans = 4;
+ *seg1 = 4;
+ break;
default:
break;
}
@@ -170,10 +176,10 @@ static int dfs_find_channel(struct hostapd_iface *iface,
{
struct hostapd_hw_modes *mode;
struct hostapd_channel_data *chan;
- int i, channel_idx = 0, n_chans;
+ int i, channel_idx = 0, n_chans, n_chans1;
mode = iface->current_mode;
- n_chans = dfs_get_used_n_chans(iface);
+ n_chans = dfs_get_used_n_chans(iface, &n_chans1);
wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans);
for (i = 0; i < mode->num_channels; i++) {
@@ -246,12 +252,15 @@ static void dfs_adjust_vht_center_freq(struct hostapd_iface *iface,
/* Return start channel idx we will use for mode->channels[idx] */
-static int dfs_get_start_chan_idx(struct hostapd_iface *iface)
+static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start)
{
struct hostapd_hw_modes *mode;
struct hostapd_channel_data *chan;
int channel_no = iface->conf->channel;
int res = -1, i;
+ int chan_seg1 = -1;
+
+ *seg1_start = -1;
/* HT40- */
if (iface->conf->ieee80211n && iface->conf->secondary_channel == -1)
@@ -270,9 +279,15 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface)
channel_no =
iface->conf->vht_oper_centr_freq_seg0_idx - 14;
break;
+ case VHT_CHANWIDTH_80P80MHZ:
+ channel_no =
+ iface->conf->vht_oper_centr_freq_seg0_idx - 6;
+ chan_seg1 =
+ iface->conf->vht_oper_centr_freq_seg1_idx - 6;
+ break;
default:
wpa_printf(MSG_INFO,
- "DFS only VHT20/40/80/160 is supported now");
+ "DFS only VHT20/40/80/160/80+80 is supported now");
channel_no = -1;
break;
}
@@ -288,6 +303,23 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface)
}
}
+ if (res != -1 && chan_seg1 > -1) {
+ int found = 0;
+
+ /* Get idx for seg1 */
+ mode = iface->current_mode;
+ for (i = 0; i < mode->num_channels; i++) {
+ chan = &mode->channels[i];
+ if (chan->chan == chan_seg1) {
+ *seg1_start = i;
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ res = -1;
+ }
+
if (res == -1) {
wpa_printf(MSG_DEBUG,
"DFS chan_idx seems wrong; num-ch: %d ch-no: %d conf-ch-no: %d 11n: %d sec-ch: %d vht-oper-width: %d",
@@ -511,17 +543,17 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq,
int chan_width, int cf1, int cf2)
{
- int start_chan_idx;
+ int start_chan_idx, start_chan_idx1;
struct hostapd_hw_modes *mode;
struct hostapd_channel_data *chan;
- int n_chans, i, j, frequency = freq, radar_n_chans = 1;
+ int n_chans, n_chans1, i, j, frequency = freq, radar_n_chans = 1;
u8 radar_chan;
int res = 0;
/* Our configuration */
mode = iface->current_mode;
- start_chan_idx = dfs_get_start_chan_idx(iface);
- n_chans = dfs_get_used_n_chans(iface);
+ start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1);
+ n_chans = dfs_get_used_n_chans(iface, &n_chans1);
/* Check we are on DFS channel(s) */
if (!dfs_check_chans_radar(iface, start_chan_idx, n_chans))
@@ -604,19 +636,20 @@ static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
int hostapd_handle_dfs(struct hostapd_iface *iface)
{
struct hostapd_channel_data *channel;
- int res, n_chans, start_chan_idx;
+ int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
int skip_radar = 0;
iface->cac_started = 0;
do {
/* Get start (first) channel for current configuration */
- start_chan_idx = dfs_get_start_chan_idx(iface);
+ start_chan_idx = dfs_get_start_chan_idx(iface,
+ &start_chan_idx1);
if (start_chan_idx == -1)
return -1;
/* Get number of used channels, depend on width */
- n_chans = dfs_get_used_n_chans(iface);
+ n_chans = dfs_get_used_n_chans(iface, &n_chans1);
/* Setup CAC time */
iface->dfs_cac_ms = dfs_get_cac_time(iface, start_chan_idx,
@@ -928,20 +961,25 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
int hostapd_is_dfs_required(struct hostapd_iface *iface)
{
- int n_chans, start_chan_idx;
+ int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
if (!iface->conf->ieee80211h || !iface->current_mode ||
iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
/* Get start (first) channel for current configuration */
- start_chan_idx = dfs_get_start_chan_idx(iface);
+ start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1);
if (start_chan_idx == -1)
return -1;
/* Get number of used channels, depend on width */
- n_chans = dfs_get_used_n_chans(iface);
+ n_chans = dfs_get_used_n_chans(iface, &n_chans1);
/* Check if any of configured channels require DFS */
- return dfs_check_chans_radar(iface, start_chan_idx, n_chans);
+ res = dfs_check_chans_radar(iface, start_chan_idx, n_chans);
+ if (res)
+ return res;
+ if (start_chan_idx1 >= 0 && n_chans1 > 0)
+ res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1);
+ return res;
}
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index c687ba03..09eb89cf 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -340,6 +340,9 @@ skip_wpa_check:
sta->auth_alg, req_ies, req_ies_len);
hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
+
+ if (sta->auth_alg == WLAN_AUTH_FT)
+ ap_sta_set_authorized(hapd, sta, 1);
#else /* CONFIG_IEEE80211R */
/* Keep compiler silent about unused variables */
if (status) {
@@ -350,6 +353,8 @@ skip_wpa_check:
sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
+ hostapd_set_sta_flags(hapd, sta);
+
if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
else
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 59567dd6..31423915 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -693,10 +693,10 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
u8 if_addr[ETH_ALEN];
wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)",
- __func__, hapd, hapd->conf->iface, first);
+ __func__, hapd, conf->iface, first);
#ifdef EAP_SERVER_TNC
- if (hapd->conf->tnc && tncs_global_init() < 0) {
+ if (conf->tnc && tncs_global_init() < 0) {
wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
return -1;
}
@@ -704,37 +704,37 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
if (hapd->started) {
wpa_printf(MSG_ERROR, "%s: Interface %s was already started",
- __func__, hapd->conf->iface);
+ __func__, conf->iface);
return -1;
}
hapd->started = 1;
if (!first || first == -1) {
- if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
+ if (hostapd_mac_comp_empty(conf->bssid) == 0) {
/* Allocate the next available BSSID. */
do {
inc_byte_array(hapd->own_addr, ETH_ALEN);
} while (mac_in_conf(hapd->iconf, hapd->own_addr));
} else {
/* Allocate the configured BSSID. */
- os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN);
+ os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN);
if (hostapd_mac_comp(hapd->own_addr,
hapd->iface->bss[0]->own_addr) ==
0) {
wpa_printf(MSG_ERROR, "BSS '%s' may not have "
"BSSID set to the MAC address of "
- "the radio", hapd->conf->iface);
+ "the radio", conf->iface);
return -1;
}
}
hapd->interface_added = 1;
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
- hapd->conf->iface, hapd->own_addr, hapd,
+ conf->iface, hapd->own_addr, hapd,
&hapd->drv_priv, force_ifname, if_addr,
- hapd->conf->bridge[0] ? hapd->conf->bridge :
- NULL, first == -1)) {
+ conf->bridge[0] ? conf->bridge : NULL,
+ first == -1)) {
wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
MACSTR ")", MAC2STR(hapd->own_addr));
hapd->interface_added = 0;
@@ -749,7 +749,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
hostapd_set_privacy(hapd, 0);
hostapd_broadcast_wep_clear(hapd);
- if (hostapd_setup_encryption(hapd->conf->iface, hapd))
+ if (hostapd_setup_encryption(conf->iface, hapd))
return -1;
/*
@@ -783,9 +783,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
if (!hostapd_drv_none(hapd)) {
wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
" and ssid \"%s\"",
- hapd->conf->iface, MAC2STR(hapd->own_addr),
- wpa_ssid_txt(hapd->conf->ssid.ssid,
- hapd->conf->ssid.ssid_len));
+ conf->iface, MAC2STR(hapd->own_addr),
+ wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len));
}
if (hostapd_setup_wpa_psk(conf)) {
@@ -810,17 +809,17 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
return -1;
}
- if (hapd->conf->radius_das_port) {
+ if (conf->radius_das_port) {
struct radius_das_conf das_conf;
os_memset(&das_conf, 0, sizeof(das_conf));
- das_conf.port = hapd->conf->radius_das_port;
- das_conf.shared_secret = hapd->conf->radius_das_shared_secret;
+ das_conf.port = conf->radius_das_port;
+ das_conf.shared_secret = conf->radius_das_shared_secret;
das_conf.shared_secret_len =
- hapd->conf->radius_das_shared_secret_len;
- das_conf.client_addr = &hapd->conf->radius_das_client_addr;
- das_conf.time_window = hapd->conf->radius_das_time_window;
+ conf->radius_das_shared_secret_len;
+ das_conf.client_addr = &conf->radius_das_client_addr;
+ das_conf.time_window = conf->radius_das_time_window;
das_conf.require_event_timestamp =
- hapd->conf->radius_das_require_event_timestamp;
+ conf->radius_das_require_event_timestamp;
das_conf.ctx = hapd;
das_conf.disconnect = hostapd_das_disconnect;
hapd->radius_das = radius_das_init(&das_conf);
@@ -847,7 +846,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
return -1;
}
- if ((hapd->conf->wpa || hapd->conf->osen) && hostapd_setup_wpa(hapd))
+ if ((conf->wpa || conf->osen) && hostapd_setup_wpa(hapd))
return -1;
if (accounting_init(hapd)) {
@@ -855,8 +854,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
return -1;
}
- if (hapd->conf->ieee802_11f &&
- (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
+ if (conf->ieee802_11f &&
+ (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) {
wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
"failed.");
return -1;
@@ -881,7 +880,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
return -1;
}
- if (!hapd->conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+ if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
return -1;
if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index e4681e90..2d09b67b 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1622,6 +1622,9 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0)
break;
+ sta->session_timeout_set = !!session_timeout_set;
+ sta->session_timeout = session_timeout;
+
/* RFC 3580, Ch. 3.17 */
if (session_timeout_set && termination_action ==
RADIUS_TERMINATION_ACTION_RADIUS_REQUEST) {
@@ -2396,6 +2399,7 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
size_t len;
/* TODO: get PMKLifetime from WPA parameters */
static const int dot11RSNAConfigPMKLifetime = 43200;
+ unsigned int session_timeout;
#ifdef CONFIG_HS20
if (remediation && !sta->remediation) {
@@ -2430,9 +2434,13 @@ static void ieee802_1x_finished(struct hostapd_data *hapd,
#endif /* CONFIG_HS20 */
key = ieee802_1x_get_key(sta->eapol_sm, &len);
+ if (sta->session_timeout_set)
+ session_timeout = sta->session_timeout;
+ else
+ session_timeout = dot11RSNAConfigPMKLifetime;
if (success && key && len >= PMK_LEN && !sta->remediation &&
!sta->hs20_deauth_requested &&
- wpa_auth_pmksa_add(sta->wpa_sm, key, dot11RSNAConfigPMKLifetime,
+ wpa_auth_pmksa_add(sta->wpa_sm, key, session_timeout,
sta->eapol_sm) == 0) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
HOSTAPD_LEVEL_DEBUG,
diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c
index 4720b59c..9de4cffe 100644
--- a/src/ap/pmksa_cache_auth.c
+++ b/src/ap/pmksa_cache_auth.c
@@ -37,14 +37,12 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
{
- if (entry == NULL)
- return;
os_free(entry->identity);
wpabuf_free(entry->cui);
#ifndef CONFIG_NO_RADIUS
radius_free_class(&entry->radius_class);
#endif /* CONFIG_NO_RADIUS */
- os_free(entry);
+ bin_clear_free(entry, sizeof(*entry));
}
@@ -52,38 +50,42 @@ void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
struct rsn_pmksa_cache_entry *entry)
{
struct rsn_pmksa_cache_entry *pos, *prev;
+ unsigned int hash;
pmksa->pmksa_count--;
pmksa->free_cb(entry, pmksa->ctx);
- pos = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
+
+ /* unlink from hash list */
+ hash = PMKID_HASH(entry->pmkid);
+ pos = pmksa->pmkid[hash];
prev = NULL;
while (pos) {
if (pos == entry) {
- if (prev != NULL) {
- prev->hnext = pos->hnext;
- } else {
- pmksa->pmkid[PMKID_HASH(entry->pmkid)] =
- pos->hnext;
- }
+ if (prev != NULL)
+ prev->hnext = entry->hnext;
+ else
+ pmksa->pmkid[hash] = entry->hnext;
break;
}
prev = pos;
pos = pos->hnext;
}
+ /* unlink from entry list */
pos = pmksa->pmksa;
prev = NULL;
while (pos) {
if (pos == entry) {
if (prev != NULL)
- prev->next = pos->next;
+ prev->next = entry->next;
else
- pmksa->pmksa = pos->next;
+ pmksa->pmksa = entry->next;
break;
}
prev = pos;
pos = pos->next;
}
+
_pmksa_cache_free_entry(entry);
}
@@ -188,6 +190,7 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
struct rsn_pmksa_cache_entry *entry)
{
struct rsn_pmksa_cache_entry *pos, *prev;
+ int hash;
/* Add the new entry; order by expiration time */
pos = pmksa->pmksa;
@@ -205,8 +208,10 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
entry->next = prev->next;
prev->next = entry;
}
- entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
- pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry;
+
+ hash = PMKID_HASH(entry->pmkid);
+ entry->hnext = pmksa->pmkid[hash];
+ pmksa->pmkid[hash] = entry;
pmksa->pmksa_count++;
if (prev == NULL)
@@ -342,6 +347,8 @@ void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa)
_pmksa_cache_free_entry(prev);
}
eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
+ pmksa->pmksa_count = 0;
+ pmksa->pmksa = NULL;
for (i = 0; i < PMKID_HASH_SIZE; i++)
pmksa->pmkid[i] = NULL;
os_free(pmksa);
@@ -361,18 +368,22 @@ pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa,
{
struct rsn_pmksa_cache_entry *entry;
- if (pmkid)
- entry = pmksa->pmkid[PMKID_HASH(pmkid)];
- else
- entry = pmksa->pmksa;
- while (entry) {
- if ((spa == NULL ||
- os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
- (pmkid == NULL ||
- os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0))
- return entry;
- entry = pmkid ? entry->hnext : entry->next;
+ if (pmkid) {
+ for (entry = pmksa->pmkid[PMKID_HASH(pmkid)]; entry;
+ entry = entry->hnext) {
+ if ((spa == NULL ||
+ os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
+ os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)
+ return entry;
+ }
+ } else {
+ for (entry = pmksa->pmksa; entry; entry = entry->next) {
+ if (spa == NULL ||
+ os_memcmp(entry->spa, spa, ETH_ALEN) == 0)
+ return entry;
+ }
}
+
return NULL;
}
@@ -394,15 +405,13 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
struct rsn_pmksa_cache_entry *entry;
u8 new_pmkid[PMKID_LEN];
- entry = pmksa->pmksa;
- while (entry) {
+ for (entry = pmksa->pmksa; entry; entry = entry->next) {
if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
continue;
rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
wpa_key_mgmt_sha256(entry->akmp));
if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
return entry;
- entry = entry->next;
}
return NULL;
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 6a570fa5..f0f01b4a 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -961,12 +961,12 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
dev_addr = addr;
} else
dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr);
-#endif /* CONFIG_P2P */
if (dev_addr)
os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR,
MAC2STR(sta->addr), MAC2STR(dev_addr));
else
+#endif /* CONFIG_P2P */
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr));
if (hapd->sta_authorized_cb)
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 03db98f6..faf32d85 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -60,6 +60,7 @@ struct sta_info {
unsigned int qos_map_enabled:1;
unsigned int remediation:1;
unsigned int hs20_deauth_requested:1;
+ unsigned int session_timeout_set:1;
u16 auth_alg;
@@ -135,6 +136,8 @@ struct sta_info {
#ifdef CONFIG_SAE
struct sae_data *sae;
#endif /* CONFIG_SAE */
+
+ u32 session_timeout; /* valid only if session_timeout_set == 1 */
};
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 2bb8aab8..1a16b5c8 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1390,7 +1390,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN ||
version == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
- if (aes_wrap(sm->PTK.kek, (key_data_len - 8) / 8, buf,
+ if (aes_wrap(sm->PTK.kek, 16,
+ (key_data_len - 8) / 8, buf,
(u8 *) (key + 1))) {
os_free(hdr);
os_free(buf);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 8a6ca71c..781f15fb 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -344,7 +344,8 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN);
os_memset(f.pad, 0, sizeof(f.pad));
- if (aes_wrap(r0kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
+ if (aes_wrap(r0kh->key, sizeof(r0kh->key),
+ (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
f.nonce, frame.nonce) < 0)
return -1;
@@ -459,7 +460,7 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03);
subelem[4] = gsm->GTK_len;
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5);
- if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) {
+ if (aes_wrap(sm->PTK.kek, 16, key_len / 8, key, subelem + 13)) {
os_free(subelem);
return NULL;
}
@@ -491,7 +492,7 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
pos += 6;
*pos++ = WPA_IGTK_LEN;
- if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8,
+ if (aes_wrap(sm->PTK.kek, 16, WPA_IGTK_LEN / 8,
gsm->IGTK[gsm->GN_igtk - 4], pos)) {
os_free(subelem);
return NULL;
@@ -1336,7 +1337,8 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
frame = (struct ft_r0kh_r1kh_pull_frame *) data;
/* aes_unwrap() does not support inplace decryption, so use a temporary
* buffer for the data. */
- if (aes_unwrap(r1kh->key, (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
+ if (aes_unwrap(r1kh->key, sizeof(r1kh->key),
+ (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
frame->nonce, f.nonce) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
"request from " MACSTR, MAC2STR(src_addr));
@@ -1376,7 +1378,8 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
r.pairwise = host_to_le16(pairwise);
os_memset(r.pad, 0, sizeof(r.pad));
- if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
+ if (aes_wrap(r1kh->key, sizeof(r1kh->key),
+ (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
r.nonce, resp.nonce) < 0) {
os_memset(pmk_r0, 0, PMK_LEN);
return -1;
@@ -1464,7 +1467,8 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
frame = (struct ft_r0kh_r1kh_resp_frame *) data;
/* aes_unwrap() does not support inplace decryption, so use a temporary
* buffer for the data. */
- if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
+ if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
+ (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
frame->nonce, f.nonce) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
"response from " MACSTR, MAC2STR(src_addr));
@@ -1530,7 +1534,8 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
frame = (struct ft_r0kh_r1kh_push_frame *) data;
/* aes_unwrap() does not support inplace decryption, so use a temporary
* buffer for the data. */
- if (aes_unwrap(r0kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
+ if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
+ (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
frame->timestamp, f.timestamp) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from "
MACSTR, MAC2STR(src_addr));
@@ -1727,7 +1732,8 @@ static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
WPA_PUT_LE32(f.timestamp, now.sec);
f.pairwise = host_to_le16(pairwise);
os_memset(f.pad, 0, sizeof(f.pad));
- if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
+ if (aes_wrap(r1kh->key, sizeof(r1kh->key),
+ (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
f.timestamp, frame.timestamp) < 0)
return;
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index e4205f49..92d687ac 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -32,6 +32,13 @@ enum qca_radiotap_vendor_ids {
*
* @QCA_NL80211_VENDOR_SUBCMD_TEST: Test command/event
*
+ * @QCA_NL80211_VENDOR_SUBCMD_ROAMING: Set roaming policy for drivers that use
+ * internal BSS-selection. This command uses
+ * @QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY to specify the new roaming policy
+ * for the current connection (i.e., changes policy set by the nl80211
+ * Connect command). @QCA_WLAN_VENDOR_ATTR_MAC_ADDR may optionally be
+ * included to indicate which BSS to use in case roaming is disabled.
+ *
* @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: Recommendation of frequency
* ranges to avoid to reduce issues due to interference or internal
* co-existence information in the driver. The event data structure is
@@ -51,12 +58,13 @@ enum qca_radiotap_vendor_ids {
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
QCA_NL80211_VENDOR_SUBCMD_TEST = 1,
- /* subcmds 2..9 not yet allocated */
+ /* subcmds 2..8 not yet allocated */
+ QCA_NL80211_VENDOR_SUBCMD_ROAMING = 9,
QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10,
QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11,
QCA_NL80211_VENDOR_SUBCMD_NAN = 12,
QCA_NL80211_VENDOR_SUBMCD_STATS_EXT = 13,
- /* 14..33 - reserved for QCA */
+ /* 14..49 - reserved for QCA */
QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54,
};
@@ -71,6 +79,10 @@ enum qca_wlan_vendor_attr {
QCA_WLAN_VENDOR_ATTR_STATS_EXT = 3,
/* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */
QCA_WLAN_VENDOR_ATTR_IFINDEX = 4,
+ /* used by QCA_NL80211_VENDOR_SUBCMD_ROAMING, u32 with values defined
+ * by enum qca_roaming_policy. */
+ QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5,
+ QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
/* keep last */
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
@@ -96,4 +108,9 @@ enum qca_wlan_vendor_acs_hw_mode {
QCA_ACS_MODE_IEEE80211AD,
};
+enum qca_roaming_policy {
+ QCA_ROAMING_NOT_ALLOWED,
+ QCA_ROAMING_ALLOWED_WITHIN_ESS,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/common/version.h b/src/common/version.h
index 1f254329..726289d9 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -5,6 +5,6 @@
#define VERSION_STR_POSTFIX ""
#endif /* VERSION_STR_POSTFIX */
-#define VERSION_STR "2.3-devel" VERSION_STR_POSTFIX
+#define VERSION_STR "2.3" VERSION_STR_POSTFIX
#endif /* VERSION_H */
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index d91594e3..4812f8df 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -345,9 +345,10 @@ int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
* @reply_len: Length of the reply buffer
* Returns: 0 on success, -1 on failure
*
- * This function will receive a pending control interface message. This
- * function will block if no messages are available. The received response will
- * be written to reply and reply_len is set to the actual length of the reply.
+ * This function will receive a pending control interface message. The received
+ * response will be written to reply and reply_len is set to the actual length
+ * of the reply.
+
* wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach()
* must have been used to register the control interface as an event monitor.
*/
diff --git a/src/crypto/aes-unwrap.c b/src/crypto/aes-unwrap.c
index 9dd51602..ec793d9d 100644
--- a/src/crypto/aes-unwrap.c
+++ b/src/crypto/aes-unwrap.c
@@ -1,5 +1,5 @@
/*
- * AES key unwrap (128-bit KEK, RFC3394)
+ * AES key unwrap (RFC3394)
*
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
@@ -14,26 +14,29 @@
#include "aes_wrap.h"
/**
- * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (RFC3394)
* @kek: Key encryption key (KEK)
+ * @kek_len: Length of KEK in octets
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
* bytes
* @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
* @plain: Plaintext key, n * 64 bits
* Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
*/
-int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
+int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
+ u8 *plain)
{
- u8 a[8], *r, b[16];
+ u8 a[8], *r, b[AES_BLOCK_SIZE];
int i, j;
void *ctx;
+ unsigned int t;
/* 1) Initialize variables. */
os_memcpy(a, cipher, 8);
r = plain;
os_memcpy(r, cipher + 8, 8 * n);
- ctx = aes_decrypt_init(kek, 16);
+ ctx = aes_decrypt_init(kek, kek_len);
if (ctx == NULL)
return -1;
@@ -48,7 +51,11 @@ int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
r = plain + (n - 1) * 8;
for (i = n; i >= 1; i--) {
os_memcpy(b, a, 8);
- b[7] ^= n * j + i;
+ t = n * j + i;
+ b[7] ^= t;
+ b[6] ^= t >> 8;
+ b[5] ^= t >> 16;
+ b[4] ^= t >> 24;
os_memcpy(b + 8, r, 8);
aes_decrypt(ctx, b, b);
diff --git a/src/crypto/aes-wrap.c b/src/crypto/aes-wrap.c
index 89d6f94b..7ed34e80 100644
--- a/src/crypto/aes-wrap.c
+++ b/src/crypto/aes-wrap.c
@@ -1,5 +1,5 @@
/*
- * AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * AES Key Wrap Algorithm (RFC3394)
*
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
@@ -14,19 +14,21 @@
#include "aes_wrap.h"
/**
- * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * @kek: 16-octet Key encryption key (KEK)
+ * aes_wrap - Wrap keys with AES Key Wrap Algorithm (RFC3394)
+ * @kek: Key encryption key (KEK)
+ * @kek_len: Length of KEK in octets
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
* bytes
* @plain: Plaintext key to be wrapped, n * 64 bits
* @cipher: Wrapped key, (n + 1) * 64 bits
* Returns: 0 on success, -1 on failure
*/
-int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
+int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
{
- u8 *a, *r, b[16];
+ u8 *a, *r, b[AES_BLOCK_SIZE];
int i, j;
void *ctx;
+ unsigned int t;
a = cipher;
r = cipher + 8;
@@ -35,7 +37,7 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
os_memset(a, 0xa6, 8);
os_memcpy(r, plain, 8 * n);
- ctx = aes_encrypt_init(kek, 16);
+ ctx = aes_encrypt_init(kek, kek_len);
if (ctx == NULL)
return -1;
@@ -53,7 +55,11 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
os_memcpy(b + 8, r, 8);
aes_encrypt(ctx, b, b);
os_memcpy(a, b, 8);
- a[7] ^= n * j + i;
+ t = n * j + i;
+ a[7] ^= t;
+ a[6] ^= t >> 8;
+ a[5] ^= t >> 16;
+ a[4] ^= t >> 24;
os_memcpy(r, b + 8, 8);
r += 8;
}
diff --git a/src/crypto/aes_wrap.h b/src/crypto/aes_wrap.h
index 0433c043..6b3727c7 100644
--- a/src/crypto/aes_wrap.h
+++ b/src/crypto/aes_wrap.h
@@ -1,7 +1,7 @@
/*
* AES-based functions
*
- * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * - AES Key Wrap Algorithm (RFC3394)
* - One-Key CBC MAC (OMAC1) hash with AES-128
* - AES-128 CTR mode encryption
* - AES-128 EAX mode encryption/decryption
@@ -18,8 +18,10 @@
#ifndef AES_WRAP_H
#define AES_WRAP_H
-int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
-int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
+int __must_check aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain,
+ u8 *cipher);
+int __must_check aes_unwrap(const u8 *kek, size_t kek_len, int n,
+ const u8 *cipher, u8 *plain);
int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem,
const u8 *addr[], const size_t *len,
u8 *mac);
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index f02aaacb..b4c59d18 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -40,7 +40,7 @@
static BIGNUM * get_group5_prime(void)
{
-#if OPENSSL_VERSION_NUMBER < 0x00908000
+#if OPENSSL_VERSION_NUMBER < 0x00908000 || defined(OPENSSL_IS_BORINGSSL)
static const unsigned char RFC3526_PRIME_1536[] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
@@ -130,7 +130,7 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
}
pkey[i] = next | 1;
- DES_set_key(&pkey, &ks);
+ DES_set_key((DES_cblock *) &pkey, &ks);
DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
DES_ENCRYPT);
}
@@ -199,8 +199,10 @@ static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen)
switch (keylen) {
case 16:
return EVP_aes_128_ecb();
+#ifndef OPENSSL_IS_BORINGSSL
case 24:
return EVP_aes_192_ecb();
+#endif /* OPENSSL_IS_BORINGSSL */
case 32:
return EVP_aes_256_ecb();
}
@@ -378,9 +380,11 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
case 16:
cipher = EVP_aes_128_cbc();
break;
+#ifndef OPENSSL_IS_BORINGSSL
case 24:
cipher = EVP_aes_192_cbc();
break;
+#endif /* OPENSSL_IS_BORINGSSL */
case 32:
cipher = EVP_aes_256_cbc();
break;
@@ -1067,6 +1071,7 @@ void crypto_ec_deinit(struct crypto_ec *e)
if (e == NULL)
return;
BN_clear_free(e->order);
+ BN_clear_free(e->prime);
EC_GROUP_free(e->group);
BN_CTX_free(e->bnctx);
os_free(e);
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index d2d66003..e1534224 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -38,14 +38,26 @@
#define OPENSSL_SUPPORTS_CTX_APP_DATA
#endif
-#ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT
-#ifdef SSL_OP_NO_TICKET
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
+/* ERR_remove_thread_state replaces ERR_remove_state and the latter is
+ * deprecated. However, OpenSSL 0.9.8 doesn't include
+ * ERR_remove_thread_state. */
+#define ERR_remove_thread_state(tid) ERR_remove_state(0)
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
/*
* Session ticket override patch was merged into OpenSSL 0.9.9 tree on
* 2008-11-15. This version uses a bit different API compared to the old patch.
*/
#define CONFIG_OPENSSL_TICKET_OVERRIDE
#endif
+
+#if defined(OPENSSL_IS_BORINGSSL)
+/* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
+typedef size_t stack_index_t;
+#else
+typedef int stack_index_t;
#endif
#ifdef SSL_set_tlsext_status_type
@@ -853,7 +865,7 @@ void tls_deinit(void *ssl_ctx)
ENGINE_cleanup();
#endif /* OPENSSL_NO_ENGINE */
CRYPTO_cleanup_all_ex_data();
- ERR_remove_state(0);
+ ERR_remove_thread_state(NULL);
ERR_free_strings();
EVP_cleanup();
os_free(tls_global->ocsp_stapling_response);
@@ -1102,7 +1114,8 @@ static int tls_match_altsubject_component(X509 *cert, int type,
{
GENERAL_NAME *gen;
void *ext;
- int i, found = 0;
+ int found = 0;
+ stack_index_t i;
ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
@@ -1204,6 +1217,7 @@ static int tls_match_suffix(X509 *cert, const char *match)
GENERAL_NAME *gen;
void *ext;
int i;
+ stack_index_t j;
int dns_name = 0;
X509_NAME *name;
@@ -1211,8 +1225,8 @@ static int tls_match_suffix(X509 *cert, const char *match)
ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
- for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
- gen = sk_GENERAL_NAME_value(ext, i);
+ for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
+ gen = sk_GENERAL_NAME_value(ext, j);
if (gen->type != GEN_DNS)
continue;
dns_name++;
@@ -1639,7 +1653,7 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
BIO *bio = BIO_from_keystore(&ca_cert[11]);
STACK_OF(X509_INFO) *stack = NULL;
- int i;
+ stack_index_t i;
if (bio) {
stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
@@ -3386,9 +3400,15 @@ unsigned int tls_capabilities(void *tls_ctx)
* commented out unless explicitly needed for EAP-FAST in order to be able to
* build this file with unmodified openssl. */
+#ifdef OPENSSL_IS_BORINGSSL
+static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers,
+ const SSL_CIPHER **cipher, void *arg)
+#else /* OPENSSL_IS_BORINGSSL */
static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
STACK_OF(SSL_CIPHER) *peer_ciphers,
SSL_CIPHER **cipher, void *arg)
+#endif /* OPENSSL_IS_BORINGSSL */
{
struct tls_connection *conn = arg;
int ret;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 1f3693a3..bb57fcf1 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -411,6 +411,25 @@ enum wps_mode {
*/
};
+struct hostapd_freq_params {
+ int mode;
+ int freq;
+ int channel;
+ /* for HT */
+ int ht_enabled;
+ int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled,
+ * secondary channel below primary, 1 = HT40
+ * enabled, secondary channel above primary */
+
+ /* for VHT */
+ int vht_enabled;
+
+ /* valid for both HT and VHT, center_freq2 is non-zero
+ * only for bandwidth 80 and an 80+80 channel */
+ int center_freq1, center_freq2;
+ int bandwidth;
+};
+
/**
* struct wpa_driver_associate_params - Association parameters
* Data for struct wpa_driver_ops::associate().
@@ -443,11 +462,9 @@ struct wpa_driver_associate_params {
size_t ssid_len;
/**
- * freq - Frequency of the channel the selected AP is using
- * Frequency that the selected AP is using (in MHz as
- * reported in the scan results)
+ * freq - channel parameters
*/
- int freq;
+ struct hostapd_freq_params freq;
/**
* freq_hint - Frequency of the channel the proposed AP is using
@@ -1126,25 +1143,6 @@ struct hostapd_sta_add_params {
size_t supp_oper_classes_len;
};
-struct hostapd_freq_params {
- int mode;
- int freq;
- int channel;
- /* for HT */
- int ht_enabled;
- int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled,
- * secondary channel below primary, 1 = HT40
- * enabled, secondary channel above primary */
-
- /* for VHT */
- int vht_enabled;
-
- /* valid for both HT and VHT, center_freq2 is non-zero
- * only for bandwidth 80 and an 80+80 channel */
- int center_freq1, center_freq2;
- int bandwidth;
-};
-
struct mac_address {
u8 addr[ETH_ALEN];
};
@@ -2549,6 +2547,7 @@ struct wpa_driver_ops {
* @dialog_token: Dialog Token to use in the message (if needed)
* @status_code: Status Code or Reason Code to use (if needed)
* @peer_capab: TDLS peer capability (TDLS_PEER_* bitfield)
+ * @initiator: Is the current end the TDLS link initiator
* @buf: TDLS IEs to add to the message
* @len: Length of buf in octets
* Returns: 0 on success, negative (<0) on failure
@@ -2558,7 +2557,7 @@ struct wpa_driver_ops {
*/
int (*send_tdls_mgmt)(void *priv, const u8 *dst, u8 action_code,
u8 dialog_token, u16 status_code, u32 peer_capab,
- const u8 *buf, size_t len);
+ int initiator, const u8 *buf, size_t len);
/**
* tdls_oper - Ask the driver to perform high-level TDLS operations
@@ -2850,6 +2849,30 @@ struct wpa_driver_ops {
*/
int (*status)(void *priv, char *buf, size_t buflen);
+ /**
+ * roaming - Set roaming policy for driver-based BSS selection
+ * @priv: Private driver interface data
+ * @allowed: Whether roaming within ESS is allowed
+ * @bssid: Forced BSSID if roaming is disabled or %NULL if not set
+ * Returns: Length of written status information or -1 on failure
+ *
+ * This optional callback can be used to update roaming policy from the
+ * associate() command (bssid being set there indicates that the driver
+ * should not roam before getting this roaming() call to allow roaming.
+ * If the driver does not indicate WPA_DRIVER_FLAGS_BSS_SELECTION
+ * capability, roaming policy is handled within wpa_supplicant and there
+ * is no need to implement or react to this callback.
+ */
+ int (*roaming)(void *priv, int allowed, const u8 *bssid);
+
+ /**
+ * set_mac_addr - Set MAC address
+ * @priv: Private driver interface data
+ * @addr: MAC address to use or %NULL for setting back to permanent
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*set_mac_addr)(void *priv, const u8 *addr);
+
#ifdef CONFIG_MACSEC
int (*macsec_init)(void *priv, struct macsec_init_params *params);
@@ -4293,6 +4316,9 @@ void wpa_scan_results_free(struct wpa_scan_results *res);
/* Convert wpa_event_type to a string for logging */
const char * event_to_string(enum wpa_event_type event);
+/* Convert chan_width to a string for logging and control interfaces */
+const char * channel_width_to_string(enum chan_width width);
+
/* NULL terminated array of linked in driver wrappers */
extern struct wpa_driver_ops *wpa_drivers[];
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index 413552ca..5c68b464 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -86,3 +86,24 @@ const char * event_to_string(enum wpa_event_type event)
return "UNKNOWN";
#undef E2S
}
+
+
+const char * channel_width_to_string(enum chan_width width)
+{
+ switch (width) {
+ case CHAN_WIDTH_20_NOHT:
+ return "20 MHz (no HT)";
+ case CHAN_WIDTH_20:
+ return "20 MHz";
+ case CHAN_WIDTH_40:
+ return "40 MHz";
+ case CHAN_WIDTH_80:
+ return "80 MHz";
+ case CHAN_WIDTH_80P80:
+ return "80+80 MHz";
+ case CHAN_WIDTH_160:
+ return "160 MHz";
+ default:
+ return "unknown";
+ }
+}
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5f307765..6401087c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -19,6 +19,9 @@
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
+#ifdef CONFIG_LIBNL3_ROUTE
+#include <netlink/route/neighbour.h>
+#endif /* CONFIG_LIBNL3_ROUTE */
#include <linux/rtnetlink.h>
#include <netpacket/packet.h>
#include <linux/filter.h>
@@ -253,6 +256,7 @@ struct wpa_driver_nl80211_data {
struct dl_list list;
struct dl_list wiphy_list;
char phyname[32];
+ u8 perm_addr[ETH_ALEN];
void *ctx;
int ifindex;
int if_removed;
@@ -307,8 +311,11 @@ struct wpa_driver_nl80211_data {
unsigned int start_iface_up:1;
unsigned int test_use_roc_tx:1;
unsigned int ignore_deauth_event:1;
+ unsigned int roaming_vendor_cmd_avail:1;
unsigned int dfs_vendor_cmd_avail:1;
unsigned int have_low_prio_scan:1;
+ unsigned int force_connect_cmd:1;
+ unsigned int addr_changed:1;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
@@ -324,6 +331,8 @@ struct wpa_driver_nl80211_data {
int eapol_sock; /* socket for EAPOL frames */
+ struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
+
int default_if_indices[16];
int *if_indices;
int num_if_indices;
@@ -349,7 +358,8 @@ static void wpa_driver_nl80211_scan_timeout(void *eloop_ctx,
void *timeout_ctx);
static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
enum nl80211_iftype nlmode);
-static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, int freq);
+static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
+ struct hostapd_freq_params *freq);
static int
wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
@@ -420,6 +430,10 @@ static int wpa_driver_nl80211_authenticate_retry(
static int i802_set_freq(void *priv, struct hostapd_freq_params *freq);
static int i802_set_iface_flags(struct i802_bss *bss, int up);
+static struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv,
+ int flags, uint8_t cmd);
+static struct nl_msg * nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv,
+ int ifindex, int flags, uint8_t cmd);
static const char * nl80211_command_to_string(enum nl80211_commands cmd)
{
@@ -580,6 +594,20 @@ static int is_p2p_net_interface(enum nl80211_iftype nlmode)
}
+static struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv,
+ int ifindex)
+{
+ struct i802_bss *bss;
+
+ for (bss = drv->first_bss; bss; bss = bss->next) {
+ if (bss->ifindex == ifindex)
+ return bss;
+ }
+
+ return NULL;
+}
+
+
static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
{
if (drv->associated)
@@ -1244,8 +1272,9 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
}
extra[sizeof(extra) - 1] = '\0';
- wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_flags=0x%x (%s%s%s%s)",
- ifi->ifi_index, ifname, extra, ifi->ifi_flags,
+ wpa_printf(MSG_DEBUG, "RTM_NEWLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
+ ifi->ifi_index, ifname, extra, ifi->ifi_family,
+ ifi->ifi_flags,
(ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
(ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
@@ -1297,6 +1326,28 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx,
"event since interface %s is marked "
"removed", drv->first_bss->ifname);
} else {
+ struct i802_bss *bss;
+ u8 addr[ETH_ALEN];
+
+ /* Re-read MAC address as it may have changed */
+ bss = get_bss_ifindex(drv, ifi->ifi_index);
+ if (bss &&
+ linux_get_ifhwaddr(drv->global->ioctl_sock,
+ bss->ifname, addr) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: %s: failed to re-read MAC address",
+ bss->ifname);
+ } else if (bss &&
+ os_memcmp(addr, bss->addr, ETH_ALEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Own MAC address on ifindex %d (%s) changed from "
+ MACSTR " to " MACSTR,
+ ifi->ifi_index, bss->ifname,
+ MAC2STR(bss->addr),
+ MAC2STR(addr));
+ os_memcpy(bss->addr, addr, ETH_ALEN);
+ }
+
wpa_printf(MSG_DEBUG, "nl80211: Interface up");
drv->if_disabled = 0;
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
@@ -1341,6 +1392,7 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
struct rtattr *attr;
u32 brid = 0;
char ifname[IFNAMSIZ + 1];
+ char extra[100], *pos, *end;
drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
if (!drv) {
@@ -1349,6 +1401,9 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
return;
}
+ extra[0] = '\0';
+ pos = extra;
+ end = pos + sizeof(extra);
ifname[0] = '\0';
attrlen = len;
@@ -1363,10 +1418,28 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx,
break;
case IFLA_MASTER:
brid = nla_get_u32((struct nlattr *) attr);
+ pos += os_snprintf(pos, end - pos, " master=%u", brid);
+ break;
+ case IFLA_OPERSTATE:
+ pos += os_snprintf(pos, end - pos, " operstate=%u",
+ nla_get_u32((struct nlattr *) attr));
+ break;
+ case IFLA_LINKMODE:
+ pos += os_snprintf(pos, end - pos, " linkmode=%u",
+ nla_get_u32((struct nlattr *) attr));
break;
}
attr = RTA_NEXT(attr, attrlen);
}
+ extra[sizeof(extra) - 1] = '\0';
+
+ wpa_printf(MSG_DEBUG, "RTM_DELLINK: ifi_index=%d ifname=%s%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
+ ifi->ifi_index, ifname, extra, ifi->ifi_family,
+ ifi->ifi_flags,
+ (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
+ (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
+ (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
+ (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid))
wpa_driver_nl80211_event_dellink(drv, ifname);
@@ -1388,6 +1461,17 @@ static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
const struct ieee80211_mgmt *mgmt;
union wpa_event_data event;
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
+ drv->force_connect_cmd) {
+ /*
+ * Avoid reporting two association events that would confuse
+ * the core code.
+ */
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignore auth event when using driver SME");
+ return;
+ }
+
wpa_printf(MSG_DEBUG, "nl80211: Authenticate event");
mgmt = (const struct ieee80211_mgmt *) frame;
if (len < 24 + sizeof(mgmt->u.auth)) {
@@ -1454,6 +1538,17 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
union wpa_event_data event;
u16 status;
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
+ drv->force_connect_cmd) {
+ /*
+ * Avoid reporting two association events that would confuse
+ * the core code.
+ */
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignore assoc event when using driver SME");
+ return;
+ }
+
wpa_printf(MSG_DEBUG, "nl80211: Associate event");
mgmt = (const struct ieee80211_mgmt *) frame;
if (len < 24 + sizeof(mgmt->u.assoc_resp)) {
@@ -1656,10 +1751,7 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
return;
ifidx = nla_get_u32(ifindex);
- for (bss = drv->first_bss; bss; bss = bss->next)
- if (bss->ifindex == ifidx)
- break;
-
+ bss = get_bss_ifindex(drv, ifidx);
if (bss == NULL) {
wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch, ignoring",
ifidx);
@@ -3993,12 +4085,16 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
continue;
}
vinfo = nla_data(nl);
- if (vinfo->subcmd ==
- QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY)
+ switch (vinfo->subcmd) {
+ case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
+ drv->roaming_vendor_cmd_avail = 1;
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY:
drv->dfs_vendor_cmd_avail = 1;
- if (vinfo->subcmd ==
- QCA_NL80211_VENDOR_SUBCMD_DO_ACS)
+ case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
drv->capa.flags |= WPA_DRIVER_FLAGS_ACS_OFFLOAD;
+ break;
+ }
wpa_printf(MSG_DEBUG, "nl80211: Supported vendor command: vendor_id=0x%x subcmd=%u",
vinfo->vendor_id, vinfo->subcmd);
@@ -4981,6 +5077,7 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
bss->addr))
return -1;
+ os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
if (send_rfkill_event) {
eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
@@ -5036,6 +5133,8 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
wpa_printf(MSG_INFO, "nl80211: Failed to remove "
"interface %s from bridge %s: %s",
bss->ifname, bss->brname, strerror(errno));
+ if (drv->rtnl_sk)
+ nl80211_handle_destroy(drv->rtnl_sk);
}
if (bss->added_bridge) {
if (linux_br_del(drv->global->ioctl_sock, bss->brname) < 0)
@@ -5069,6 +5168,16 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
if (!drv->start_iface_up)
(void) i802_set_iface_flags(bss, 0);
+
+ if (drv->addr_changed) {
+ linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
+ if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+ drv->perm_addr) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Could not restore permanent MAC address");
+ }
+ }
+
if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE) {
if (!drv->hostapd || !drv->start_mode_ap)
wpa_driver_nl80211_set_mode(bss,
@@ -7845,6 +7954,43 @@ static int wpa_driver_nl80211_sta_add(void *priv,
}
+static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
+{
+#ifdef CONFIG_LIBNL3_ROUTE
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct rtnl_neigh *rn;
+ struct nl_addr *nl_addr;
+ int err;
+
+ rn = rtnl_neigh_alloc();
+ if (!rn)
+ return;
+
+ rtnl_neigh_set_family(rn, AF_BRIDGE);
+ rtnl_neigh_set_ifindex(rn, bss->ifindex);
+ nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
+ if (!nl_addr) {
+ rtnl_neigh_put(rn);
+ return;
+ }
+ rtnl_neigh_set_lladdr(rn, nl_addr);
+
+ err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
+ if (err < 0) {
+ wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
+ MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
+ bss->ifindex, nl_geterror(err));
+ } else {
+ wpa_printf(MSG_DEBUG, "nl80211: deleted bridge FDB entry for "
+ MACSTR, MAC2STR(addr));
+ }
+
+ nl_addr_put(nl_addr);
+ rtnl_neigh_put(rn);
+#endif /* CONFIG_LIBNL3_ROUTE */
+}
+
+
static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr,
int deauth, u16 reason_code)
{
@@ -7874,6 +8020,10 @@ static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr,
wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR
" --> %d (%s)",
bss->ifname, MAC2STR(addr), ret, strerror(-ret));
+
+ if (drv->rtnl_sk)
+ rtnl_neigh_delete_fdb_entry(bss, addr);
+
if (ret == -ENOENT)
return 0;
return ret;
@@ -8648,6 +8798,11 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
struct nlattr *flags;
struct nl80211_sta_flag_update upd;
+ wpa_printf(MSG_DEBUG, "nl80211: Set STA flags - ifname=%s addr=" MACSTR
+ " total_flags=0x%x flags_or=0x%x flags_and=0x%x authorized=%d",
+ bss->ifname, MAC2STR(addr), total_flags, flags_or, flags_and,
+ !!(total_flags & WPA_STA_AUTHORIZED));
+
msg = nlmsg_alloc();
if (!msg)
return -ENOMEM;
@@ -8698,9 +8853,6 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
struct wpa_driver_associate_params *params)
{
enum nl80211_iftype nlmode, old_mode;
- struct hostapd_freq_params freq = {
- .freq = params->freq,
- };
if (params->p2p) {
wpa_printf(MSG_DEBUG, "nl80211: Setup AP operations for P2P "
@@ -8715,7 +8867,7 @@ static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv,
return -1;
}
- if (nl80211_set_channel(drv->first_bss, &freq, 0)) {
+ if (nl80211_set_channel(drv->first_bss, &params->freq, 0)) {
if (old_mode != nlmode)
wpa_driver_nl80211_set_mode(drv->first_bss, old_mode);
nl80211_remove_monitor_interface(drv);
@@ -8769,7 +8921,7 @@ static int wpa_driver_nl80211_ibss(struct wpa_driver_nl80211_data *drv,
wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
- if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, params->freq)) {
+ if (wpa_driver_nl80211_set_mode_ibss(drv->first_bss, &params->freq)) {
wpa_printf(MSG_INFO, "nl80211: Failed to set interface into "
"IBSS mode");
return -1;
@@ -8793,8 +8945,16 @@ retry:
os_memcpy(drv->ssid, params->ssid, params->ssid_len);
drv->ssid_len = params->ssid_len;
- wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
+ wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq);
+ wpa_printf(MSG_DEBUG, " * ht_enabled=%d", params->freq.ht_enabled);
+ wpa_printf(MSG_DEBUG, " * sec_channel_offset=%d",
+ params->freq.sec_channel_offset);
+ wpa_printf(MSG_DEBUG, " * vht_enabled=%d", params->freq.vht_enabled);
+ wpa_printf(MSG_DEBUG, " * center_freq1=%d", params->freq.center_freq1);
+ wpa_printf(MSG_DEBUG, " * center_freq2=%d", params->freq.center_freq2);
+ wpa_printf(MSG_DEBUG, " * bandwidth=%d", params->freq.bandwidth);
+ if (nl80211_put_freq_params(msg, &params->freq) < 0)
+ goto nla_put_failure;
if (params->beacon_int > 0) {
wpa_printf(MSG_DEBUG, " * beacon_int=%d", params->beacon_int);
@@ -8954,10 +9114,10 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
params->bssid_hint);
}
- if (params->freq) {
- wpa_printf(MSG_DEBUG, " * freq=%d", params->freq);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
- drv->assoc_freq = params->freq;
+ if (params->freq.freq) {
+ wpa_printf(MSG_DEBUG, " * freq=%d", params->freq.freq);
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq.freq);
+ drv->assoc_freq = params->freq.freq;
} else
drv->assoc_freq = 0;
@@ -9460,13 +9620,11 @@ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
}
-static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, int freq)
+static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
+ struct hostapd_freq_params *freq)
{
- struct hostapd_freq_params freq_params;
- os_memset(&freq_params, 0, sizeof(freq_params));
- freq_params.freq = freq;
return wpa_driver_nl80211_set_mode_impl(bss, NL80211_IFTYPE_ADHOC,
- &freq_params);
+ freq);
}
@@ -10246,6 +10404,22 @@ static void *i802_init(struct hostapd_data *hapd,
i802_check_bridge(drv, bss, params->bridge[0], params->ifname) < 0)
goto failed;
+#ifdef CONFIG_LIBNL3_ROUTE
+ if (bss->added_if_into_bridge) {
+ drv->rtnl_sk = nl_socket_alloc();
+ if (drv->rtnl_sk == NULL) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
+ goto failed;
+ }
+
+ if (nl_connect(drv->rtnl_sk, NETLINK_ROUTE)) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
+ strerror(errno));
+ goto failed;
+ }
+ }
+#endif /* CONFIG_LIBNL3_ROUTE */
+
drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
if (drv->eapol_sock < 0) {
wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s",
@@ -10262,6 +10436,7 @@ static void *i802_init(struct hostapd_data *hapd,
if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
params->own_addr))
goto failed;
+ os_memcpy(drv->perm_addr, params->own_addr, ETH_ALEN);
memcpy(bss->addr, params->own_addr, ETH_ALEN);
@@ -11221,6 +11396,7 @@ static int nl80211_set_param(void *priv, const char *param)
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
+ drv->force_connect_cmd = 1;
}
if (os_strstr(param, "no_offchannel_tx=1")) {
@@ -11712,60 +11888,18 @@ static int nl80211_start_radar_detection(void *priv,
nl80211_cmd(bss->drv, msg, 0, NL80211_CMD_RADAR_DETECT);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq);
- if (freq->vht_enabled) {
- switch (freq->bandwidth) {
- case 20:
- NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
- NL80211_CHAN_WIDTH_20);
- break;
- case 40:
- NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
- NL80211_CHAN_WIDTH_40);
- break;
- case 80:
- if (freq->center_freq2)
- NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
- NL80211_CHAN_WIDTH_80P80);
- else
- NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
- NL80211_CHAN_WIDTH_80);
- break;
- case 160:
- NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH,
- NL80211_CHAN_WIDTH_160);
- break;
- default:
- return -1;
- }
- NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, freq->center_freq1);
- if (freq->center_freq2)
- NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ2,
- freq->center_freq2);
- } else if (freq->ht_enabled) {
- switch (freq->sec_channel_offset) {
- case -1:
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
- NL80211_CHAN_HT40MINUS);
- break;
- case 1:
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
- NL80211_CHAN_HT40PLUS);
- break;
- default:
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
- NL80211_CHAN_HT20);
- break;
- }
- }
+ if (nl80211_put_freq_params(msg, freq) < 0)
+ goto nla_put_failure;
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
if (ret == 0)
return 0;
wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: "
"%d (%s)", ret, strerror(-ret));
nla_put_failure:
+ nlmsg_free(msg);
return -1;
}
@@ -11773,7 +11907,8 @@ nla_put_failure:
static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
u8 dialog_token, u16 status_code,
- u32 peer_capab, const u8 *buf, size_t len)
+ u32 peer_capab, int initiator, const u8 *buf,
+ size_t len)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
@@ -11804,6 +11939,8 @@ static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code,
*/
NLA_PUT_U32(msg, NL80211_ATTR_TDLS_PEER_CAPABILITY, peer_capab);
}
+ if (initiator)
+ NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_INITIATOR);
NLA_PUT(msg, NL80211_ATTR_IE, len, buf);
return send_and_recv_msgs(drv, msg, NULL, NULL);
@@ -12216,6 +12353,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
res = os_snprintf(pos, end - pos,
"phyname=%s\n"
+ "perm_addr=" MACSTR "\n"
"drv_ifindex=%d\n"
"operstate=%d\n"
"scan_state=%s\n"
@@ -12232,6 +12370,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
"eapol_tx_sock=%d\n"
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
drv->phyname,
+ MAC2STR(drv->perm_addr),
drv->ifindex,
drv->operstate,
scan_state_str(drv->scan_state),
@@ -12629,8 +12768,9 @@ static int nl80211_key_mgmt_set_pmk(void *priv, const u8 *pmk,
wpa_hexdump(MSG_DEBUG, " * PMK", pmk, NL80211_KEY_LEN_PMK);
if (!(drv->capa.key_mgmt_offload_support &
- WPA_DRIVER_KEY_MGMT_OFFLOAD_SUPPORT_PMKSA))
+ WPA_DRIVER_KEY_MGMT_OFFLOAD_SUPPORT_PMKSA)) {
return 0;
+ }
msg = nlmsg_alloc();
if (!msg)
@@ -12720,6 +12860,107 @@ nla_put_failure:
}
+static int nl80211_roaming(void *priv, int allowed, const u8 *bssid)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *params;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Roaming policy: allowed=%d", allowed);
+
+ if (!drv->roaming_vendor_cmd_avail) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignore roaming policy change since driver does not provide command for setting it");
+ return -1;
+ }
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_ROAMING) ||
+ !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY,
+ allowed ? QCA_ROAMING_ALLOWED_WITHIN_ESS :
+ QCA_ROAMING_NOT_ALLOWED) ||
+ (bssid &&
+ nla_put(msg, QCA_WLAN_VENDOR_ATTR_MAC_ADDR, ETH_ALEN, bssid))) {
+ nlmsg_free(msg);
+ return -1;
+ }
+ nla_nest_end(msg, params);
+
+ return send_and_recv_msgs(drv, msg, NULL, NULL);
+}
+
+
+static int nl80211_set_mac_addr(void *priv, const u8 *addr)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ int new_addr = addr != NULL;
+
+ if (!addr)
+ addr = drv->perm_addr;
+
+ if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0) < 0)
+ return -1;
+
+ if (linux_set_ifhwaddr(drv->global->ioctl_sock, bss->ifname, addr) < 0)
+ {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: failed to set_mac_addr for %s to " MACSTR,
+ bss->ifname, MAC2STR(addr));
+ if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname,
+ 1) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Could not restore interface UP after failed set_mac_addr");
+ }
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "nl80211: set_mac_addr for %s to " MACSTR,
+ bss->ifname, MAC2STR(addr));
+ drv->addr_changed = new_addr;
+ os_memcpy(bss->addr, addr, ETH_ALEN);
+
+ if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1) < 0)
+ {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Could not restore interface UP after set_mac_addr");
+ }
+
+ return 0;
+}
+
+
+static struct nl_msg *
+nl80211_ifindex_msg(struct wpa_driver_nl80211_data *drv, int ifindex,
+ int flags, uint8_t cmd)
+{
+ struct nl_msg *msg;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return NULL;
+
+ if (!nl80211_cmd(drv, msg, flags, cmd) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifindex)) {
+ nlmsg_free(msg);
+ return NULL;
+ }
+
+ return msg;
+}
+
+
+static struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags,
+ uint8_t cmd)
+{
+ return nl80211_ifindex_msg(drv, drv->ifindex, flags, cmd);
+}
+
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@@ -12813,4 +13054,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.set_wowlan = nl80211_set_wowlan,
.key_mgmt_set_pmk = nl80211_key_mgmt_set_pmk,
.do_acs = wpa_driver_do_acs,
+ .roaming = nl80211_roaming,
+ .set_mac_addr = nl80211_set_mac_addr,
};
diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c
index 3608b522..66edfa73 100644
--- a/src/drivers/driver_test.c
+++ b/src/drivers/driver_test.c
@@ -1478,7 +1478,7 @@ static int wpa_driver_test_associate(
struct wpa_driver_test_data *drv = dbss->drv;
wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d "
"group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d",
- __func__, priv, params->freq, params->pairwise_suite,
+ __func__, priv, params->freq.freq, params->pairwise_suite,
params->group_suite, params->key_mgmt_suite,
params->auth_alg, params->mode);
wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP);
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 8d354244..50aa5208 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -2120,7 +2120,8 @@ int wpa_driver_wext_associate(void *priv,
if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_MFP, value) < 0)
ret = -1;
#endif /* CONFIG_IEEE80211W */
- if (params->freq && wpa_driver_wext_set_freq(drv, params->freq) < 0)
+ if (params->freq.freq &&
+ wpa_driver_wext_set_freq(drv, params->freq.freq) < 0)
ret = -1;
if (!drv->cfg80211 &&
wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len) < 0)
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index 40aaba59..cdb913e3 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -36,6 +36,10 @@ ifdef CONFIG_LIBNL32
DRV_LIBS += -lnl-3
DRV_LIBS += -lnl-genl-3
DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3
+ifdef CONFIG_LIBNL3_ROUTE
+ DRV_LIBS += -lnl-route-3
+ DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE
+endif
else
ifdef CONFIG_LIBNL_TINY
DRV_LIBS += -lnl-tiny
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index db8561ae..9fa70d9c 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -31,6 +31,10 @@ ifdef CONFIG_LIBNL32
DRV_LIBS += -lnl-3
DRV_LIBS += -lnl-genl-3
DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3
+ifdef CONFIG_LIBNL3_ROUTE
+ DRV_LIBS += -lnl-route-3
+ DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE
+endif
else
ifdef CONFIG_LIBNL_TINY
DRV_LIBS += -lnl-tiny
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 735ca3aa..a39fbc3b 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -503,6 +503,9 @@
* TX status event pertaining to the TX request.
* %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
* management frames at CCK rate or not in 2GHz band.
+ * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA
+ * counters which will be updated to the current value. This attribute
+ * is used during CSA period.
* @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
* command may be used with the corresponding cookie to cancel the wait
* time if it is known that it is no longer necessary.
@@ -719,6 +722,22 @@
* QoS mapping is relevant for IP packets, it is only valid during an
* association. This is cleared on disassociation and AP restart.
*
+ * @NL80211_CMD_ADD_TX_TS: Ask the kernel to add a traffic stream for the given
+ * %NL80211_ATTR_TSID and %NL80211_ATTR_MAC with %NL80211_ATTR_USER_PRIO
+ * and %NL80211_ATTR_ADMITTED_TIME parameters.
+ * Note that the action frame handshake with the AP shall be handled by
+ * userspace via the normal management RX/TX framework, this only sets
+ * up the TX TS in the driver/device.
+ * If the admitted time attribute is not added then the request just checks
+ * if a subsequent setup could be successful, the intent is to use this to
+ * avoid setting up a session with the AP when local restrictions would
+ * make that impossible. However, the subsequent "real" setup may still
+ * fail even if the check was successful.
+ * @NL80211_CMD_DEL_TX_TS: Remove an existing TS with the %NL80211_ATTR_TSID
+ * and %NL80211_ATTR_MAC parameters. It isn't necessary to call this
+ * before removing a station entry entirely, or before disassociating
+ * or similar, cleanup will happen in the driver/device in this case.
+ *
* @NL80211_CMD_AUTHORIZATION_EVENT: Indicates that the device offloaded
* the establishment of temporal keys for an RSN connection. This is
* used as part of key managment offload, where a device operating as a
@@ -910,7 +929,10 @@ enum nl80211_commands {
NL80211_CMD_SET_QOS_MAP,
- NL80211_CMD_AUTHORIZATION_EVENT,
+ NL80211_CMD_ADD_TX_TS,
+ NL80211_CMD_DEL_TX_TS,
+
+ NL80211_CMD_AUTHORIZATION_EVENT,
NL80211_CMD_KEY_MGMT_SET_PMK,
/* add new commands above here */
@@ -1548,10 +1570,10 @@ enum nl80211_commands {
* operation).
* @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
* for the time while performing a channel switch.
- * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter
- * field in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
- * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter
- * field in the probe response (%NL80211_ATTR_PROBE_RESP).
+ * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel
+ * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
+ * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel
+ * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP).
*
* @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
* As specified in the &enum nl80211_rxmgmt_flags.
@@ -1599,6 +1621,11 @@ enum nl80211_commands {
* advertise values that cannot always be met. In such cases, an attempt
* to add a new station entry with @NL80211_CMD_NEW_STATION may fail.
*
+ * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which
+ * should be updated when the frame is transmitted.
+ * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum
+ * supported number of csa counters.
+ *
* @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32.
* As specified in the &enum nl80211_tdls_peer_capability.
*
@@ -1606,6 +1633,34 @@ enum nl80211_commands {
* creation then the new interface will be owned by the netlink socket
* that created it and will be destroyed when the socket is closed
*
+ * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
+ * the TDLS link initiator.
+ *
+ * @NL80211_ATTR_USE_RRM: flag for indicating whether the current connection
+ * shall support Radio Resource Measurements (11k). This attribute can be
+ * used with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests.
+ * User space applications are expected to use this flag only if the
+ * underlying device supports these minimal RRM features:
+ * %NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES,
+ * %NL80211_FEATURE_QUIET,
+ * If this flag is used, driver must add the Power Capabilities IE to the
+ * association request. In addition, it must also set the RRM capability
+ * flag in the association request's Capability Info field.
+ *
+ * @NL80211_ATTR_WIPHY_DYN_ACK: flag attribute used to enable ACK timeout
+ * estimation algorithm (dynack). In order to activate dynack
+ * %NL80211_FEATURE_ACKTO_ESTIMATION feature flag must be set by lower
+ * drivers to indicate dynack capability. Dynack is automatically disabled
+ * setting valid value for coverage class.
+ *
+ * @NL80211_ATTR_TSID: a TSID value (u8 attribute)
+ * @NL80211_ATTR_USER_PRIO: user priority value (u8 attribute)
+ * @NL80211_ATTR_ADMITTED_TIME: admitted time in units of 32 microseconds
+ * (per second) (u16 attribute)
+ *
+ * @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see
+ * &enum nl80211_smps_mode.
+ *
* @NL80211_ATTR_AUTHORIZATION_STATUS: Status of key management offload.
* @NL80211_ATTR_KEY_REPLAY_CTR: Key Replay Counter value last used in a
* valid EAPOL-Key frame.
@@ -1957,6 +2012,23 @@ enum nl80211_attrs {
NL80211_ATTR_TDLS_PEER_CAPABILITY,
+ NL80211_ATTR_IFACE_SOCKET_OWNER,
+
+ NL80211_ATTR_CSA_C_OFFSETS_TX,
+ NL80211_ATTR_MAX_CSA_COUNTERS,
+
+ NL80211_ATTR_TDLS_INITIATOR,
+
+ NL80211_ATTR_USE_RRM,
+
+ NL80211_ATTR_WIPHY_DYN_ACK,
+
+ NL80211_ATTR_TSID,
+ NL80211_ATTR_USER_PRIO,
+ NL80211_ATTR_ADMITTED_TIME,
+
+ NL80211_ATTR_SMPS_MODE,
+
NL80211_ATTR_AUTHORIZATION_STATUS,
NL80211_ATTR_KEY_REPLAY_CTR,
NL80211_ATTR_PSK,
@@ -1968,9 +2040,7 @@ enum nl80211_attrs {
NL80211_ATTR_PTK_KCK,
NL80211_ATTR_PTK_KEK,
- NL80211_ATTR_IFACE_SOCKET_OWNER,
-
- /* add attributes here, update the policy in nl80211.c */
+ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -2238,6 +2308,8 @@ enum nl80211_sta_bss_param {
* Contains a nested array of signal strength attributes (u8, dBm)
* @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
* Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
+ * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the
+ * 802.11 header (u32, kbps)
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
@@ -2269,6 +2341,7 @@ enum nl80211_sta_info {
NL80211_STA_INFO_TX_BYTES64,
NL80211_STA_INFO_CHAIN_SIGNAL,
NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
+ NL80211_STA_INFO_EXPECTED_THROUGHPUT,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
@@ -3086,14 +3159,20 @@ enum nl80211_bss_scan_width {
* @NL80211_BSS_BSSID: BSSID of the BSS (6 octets)
* @NL80211_BSS_FREQUENCY: frequency in MHz (u32)
* @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64)
+ * (if @NL80211_BSS_PRESP_DATA is present then this is known to be
+ * from a probe response, otherwise it may be from the same beacon
+ * that the NL80211_BSS_BEACON_TSF will be from)
* @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
* @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
* @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
* raw information elements from the probe response/beacon (bin);
- * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are
- * from a Probe Response frame; otherwise they are from a Beacon frame.
+ * if the %NL80211_BSS_BEACON_IES attribute is present and the data is
+ * different then the IEs here are from a Probe Response frame; otherwise
+ * they are from a Beacon frame.
* However, if the driver does not indicate the source of the IEs, these
* IEs may be from either frame subtype.
+ * If present, the @NL80211_BSS_PRESP_DATA attribute indicates that the
+ * data here is known to be from a probe response, without any heuristics.
* @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
* in mBm (100 * dBm) (s32)
* @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
@@ -3105,6 +3184,10 @@ enum nl80211_bss_scan_width {
* yet been received
* @NL80211_BSS_CHAN_WIDTH: channel width of the control channel
* (u32, enum nl80211_bss_scan_width)
+ * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64)
+ * (not present if no beacon frame has been received yet)
+ * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
+ * @NL80211_BSS_TSF is known to be from a probe response (flag attribute)
* @__NL80211_BSS_AFTER_LAST: internal
* @NL80211_BSS_MAX: highest BSS attribute
*/
@@ -3122,6 +3205,8 @@ enum nl80211_bss {
NL80211_BSS_SEEN_MS_AGO,
NL80211_BSS_BEACON_IES,
NL80211_BSS_CHAN_WIDTH,
+ NL80211_BSS_BEACON_TSF,
+ NL80211_BSS_PRESP_DATA,
/* keep last */
__NL80211_BSS_AFTER_LAST,
@@ -3738,6 +3823,8 @@ enum nl80211_iface_limit_attrs {
* different channels may be used within this group.
* @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap
* of supported channel widths for radar detection.
+ * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
+ * of supported regulatory regions for radar detection.
* @NUM_NL80211_IFACE_COMB: number of attributes
* @MAX_NL80211_IFACE_COMB: highest attribute number
*
@@ -3771,6 +3858,7 @@ enum nl80211_if_combination_attrs {
NL80211_IFACE_COMB_STA_AP_BI_MATCH,
NL80211_IFACE_COMB_NUM_CHANNELS,
NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
+ NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
/* keep last */
NUM_NL80211_IFACE_COMB,
@@ -3944,6 +4032,8 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
* to work properly to suppport receiving regulatory hints from
* cellular base stations.
+ * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only
+ * here to reserve the value for API/ABI compatibility)
* @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of
* equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station
* mode
@@ -3982,13 +4072,33 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE: This driver supports dynamic
* channel bandwidth change (e.g., HT 20 <-> 40 MHz channel) during the
* lifetime of a BSS.
+ * @NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES: This device adds a DS Parameter
+ * Set IE to probe requests.
+ * @NL80211_FEATURE_WFA_TPC_IE_IN_PROBES: This device adds a WFA TPC Report IE
+ * to probe requests.
+ * @NL80211_FEATURE_QUIET: This device, in client mode, supports Quiet Period
+ * requests sent to it by an AP.
+ * @NL80211_FEATURE_TX_POWER_INSERTION: This device is capable of inserting the
+ * current tx power value into the TPC Report IE in the spectrum
+ * management TPC Report action frame, and in the Radio Measurement Link
+ * Measurement Report action frame.
+ * @NL80211_FEATURE_ACKTO_ESTIMATION: This driver supports dynamic ACK timeout
+ * estimation (dynack). %NL80211_ATTR_WIPHY_DYN_ACK flag attribute is used
+ * to enable dynack.
+ * @NL80211_FEATURE_STATIC_SMPS: Device supports static spatial
+ * multiplexing powersave, ie. can turn off all but one chain
+ * even on HT connections that should be using more chains.
+ * @NL80211_FEATURE_DYNAMIC_SMPS: Device supports dynamic spatial
+ * multiplexing powersave, ie. can turn off all but one chain
+ * and then wake the rest up as required after, for example,
+ * rts/cts handshake.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
NL80211_FEATURE_HT_IBSS = 1 << 1,
NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
- /* bit 4 is reserved - don't use */
+ NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4,
NL80211_FEATURE_SAE = 1 << 5,
NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6,
NL80211_FEATURE_SCAN_FLUSH = 1 << 7,
@@ -4003,6 +4113,13 @@ enum nl80211_feature_flags {
NL80211_FEATURE_USERSPACE_MPM = 1 << 16,
NL80211_FEATURE_ACTIVE_MONITOR = 1 << 17,
NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE = 1 << 18,
+ NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES = 1 << 19,
+ NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = 1 << 20,
+ NL80211_FEATURE_QUIET = 1 << 21,
+ NL80211_FEATURE_TX_POWER_INSERTION = 1 << 22,
+ NL80211_FEATURE_ACKTO_ESTIMATION = 1 << 23,
+ NL80211_FEATURE_STATIC_SMPS = 1 << 24,
+ NL80211_FEATURE_DYNAMIC_SMPS = 1 << 25,
};
/**
@@ -4077,6 +4194,25 @@ enum nl80211_acl_policy {
};
/**
+ * enum nl80211_smps_mode - SMPS mode
+ *
+ * Requested SMPS mode (for AP mode)
+ *
+ * @NL80211_SMPS_OFF: SMPS off (use all antennas).
+ * @NL80211_SMPS_STATIC: static SMPS (use a single antenna)
+ * @NL80211_SMPS_DYNAMIC: dynamic smps (start with a single antenna and
+ * turn on other antennas after CTS/RTS).
+ */
+enum nl80211_smps_mode {
+ NL80211_SMPS_OFF,
+ NL80211_SMPS_STATIC,
+ NL80211_SMPS_DYNAMIC,
+
+ __NL80211_SMPS_AFTER_LAST,
+ NL80211_SMPS_MAX = __NL80211_SMPS_AFTER_LAST - 1
+};
+
+/**
* enum nl80211_radar_event - type of radar event for DFS operation
*
* Type of event to be used with NL80211_ATTR_RADAR_EVENT to inform userspace
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index fdcff7fa..631c363f 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -106,9 +106,11 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
case 21:
nid = NID_secp521r1;
break;
+#ifndef OPENSSL_IS_BORINGSSL
case 25:
nid = NID_X9_62_prime192v1;
break;
+#endif /* OPENSSL_IS_BORINGSSL */
case 26:
nid = NID_secp224r1;
break;
diff --git a/src/eap_server/eap_server_fast.c b/src/eap_server/eap_server_fast.c
index 4691e722..2692bced 100644
--- a/src/eap_server/eap_server_fast.c
+++ b/src/eap_server/eap_server_fast.c
@@ -161,8 +161,8 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len,
return 0;
}
- if (aes_unwrap(data->pac_opaque_encr, (pac_opaque_len - 8) / 8,
- pac_opaque, buf) < 0) {
+ if (aes_unwrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
+ (pac_opaque_len - 8) / 8, pac_opaque, buf) < 0) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to decrypt "
"PAC-Opaque");
os_free(buf);
@@ -731,8 +731,8 @@ static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
os_free(pac_buf);
return NULL;
}
- if (aes_wrap(data->pac_opaque_encr, pac_len / 8, pac_buf,
- pac_opaque) < 0) {
+ if (aes_wrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr),
+ pac_len / 8, pac_buf, pac_opaque) < 0) {
os_free(pac_buf);
os_free(pac_opaque);
return NULL;
diff --git a/src/eap_server/eap_server_pax.c b/src/eap_server/eap_server_pax.c
index c87848c4..d9d4375a 100644
--- a/src/eap_server/eap_server_pax.c
+++ b/src/eap_server/eap_server_pax.c
@@ -287,7 +287,7 @@ static void eap_pax_process_std_2(struct eap_sm *sm,
struct eap_pax_hdr *resp;
u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN];
const u8 *pos;
- size_t len, left;
+ size_t len, left, cid_len;
int i;
if (data->state != PAX_STD_1)
@@ -320,7 +320,12 @@ static void eap_pax_process_std_2(struct eap_sm *sm,
wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)");
return;
}
- data->cid_len = WPA_GET_BE16(pos);
+ cid_len = WPA_GET_BE16(pos);
+ if (cid_len > 1500) {
+ wpa_printf(MSG_INFO, "EAP-PAX: Too long CID");
+ return;
+ }
+ data->cid_len = cid_len;
os_free(data->cid);
data->cid = os_malloc(data->cid_len);
if (data->cid == NULL) {
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index cf3506d9..70258be2 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -255,12 +255,14 @@ SM_STATE(SUPP_PAE, CONNECTING)
* delay authentication. Use a short timeout to send the first
* EAPOL-Start if Authenticator does not start authentication.
*/
-#ifdef CONFIG_WPS
- /* Reduce latency on starting WPS negotiation. */
- sm->startWhen = 1;
-#else /* CONFIG_WPS */
- sm->startWhen = 3;
-#endif /* CONFIG_WPS */
+ if (sm->conf.wps) {
+ /* Reduce latency on starting WPS negotiation. */
+ wpa_printf(MSG_DEBUG,
+ "EAPOL: Using shorter startWhen for WPS");
+ sm->startWhen = 1;
+ } else {
+ sm->startWhen = 2;
+ }
}
eapol_enable_timer_tick(sm);
sm->eapolEap = FALSE;
@@ -1242,7 +1244,7 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
return 0;
}
#ifdef CONFIG_WPS
- if (sm->conf.workaround &&
+ if (sm->conf.wps && sm->conf.workaround &&
plen < len - sizeof(*hdr) &&
hdr->type == IEEE802_1X_TYPE_EAP_PACKET &&
len - sizeof(*hdr) > sizeof(struct eap_hdr)) {
@@ -1491,6 +1493,7 @@ void eapol_sm_notify_config(struct eapol_sm *sm,
sm->conf.required_keys = conf->required_keys;
sm->conf.fast_reauth = conf->fast_reauth;
sm->conf.workaround = conf->workaround;
+ sm->conf.wps = conf->wps;
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
/* Using EAP Proxy, so skip EAP state machine update */
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index d76c8c21..5b37314f 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -58,6 +58,11 @@ struct eapol_config {
* external_sim - Use external processing for SIM/USIM operations
*/
int external_sim;
+
+ /**
+ * wps - Whether this connection is used for WPS
+ */
+ int wps;
};
struct eapol_sm;
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 43264caa..4305bbeb 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -267,7 +267,8 @@ static void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc)
return;
}
- os_get_random((u8 *) &r, sizeof(r));
+ if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+ r = 0;
tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
p2p->min_disc_int) * 100;
if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu)
@@ -1837,8 +1838,17 @@ static void p2p_go_neg_start(void *eloop_ctx, void *timeout_ctx)
struct p2p_data *p2p = eloop_ctx;
if (p2p->go_neg_peer == NULL)
return;
+ if (p2p->pending_listen_freq) {
+ p2p_dbg(p2p, "Clear pending_listen_freq for p2p_go_neg_start");
+ p2p->pending_listen_freq = 0;
+ }
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
p2p->go_neg_peer->status = P2P_SC_SUCCESS;
+ /*
+ * Set new timeout to make sure a previously set one does not expire
+ * too quickly while waiting for the GO Negotiation to complete.
+ */
+ p2p_set_timeout(p2p, 0, 500000);
p2p_connect_send(p2p, p2p->go_neg_peer);
}
@@ -1848,6 +1858,10 @@ static void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
struct p2p_data *p2p = eloop_ctx;
if (p2p->invite_peer == NULL)
return;
+ if (p2p->pending_listen_freq) {
+ p2p_dbg(p2p, "Clear pending_listen_freq for p2p_invite_start");
+ p2p->pending_listen_freq = 0;
+ }
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr,
p2p->invite_dev_pw_id);
@@ -2493,7 +2507,8 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
p2p->max_disc_int = 3;
p2p->max_disc_tu = -1;
- os_get_random(&p2p->next_tie_breaker, 1);
+ if (os_get_random(&p2p->next_tie_breaker, 1) < 0)
+ p2p->next_tie_breaker = 0;
p2p->next_tie_breaker &= 0x01;
if (cfg->sd_request)
p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY;
@@ -3070,7 +3085,8 @@ static void p2p_go_neg_req_cb(struct p2p_data *p2p, int success)
* make it less likely to hit cases where we could end up in
* sync with peer not listening.
*/
- os_get_random((u8 *) &r, sizeof(r));
+ if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+ r = 0;
timeout += r % 100000;
}
p2p_set_timeout(p2p, 0, timeout);
diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c
index df540ef5..23acce76 100644
--- a/src/p2p/p2p_utils.c
+++ b/src/p2p/p2p_utils.c
@@ -450,7 +450,8 @@ void p2p_channels_dump(struct p2p_data *p2p, const char *title,
static u8 p2p_channel_pick_random(const u8 *channels, unsigned int num_channels)
{
unsigned int r;
- os_get_random((u8 *) &r, sizeof(r));
+ if (os_get_random((u8 *) &r, sizeof(r)) < 0)
+ r = 0;
r %= num_channels;
return channels[r];
}
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
index 0f961282..c8fa2651 100644
--- a/src/pae/ieee802_1x_kay.c
+++ b/src/pae/ieee802_1x_kay.c
@@ -1451,7 +1451,7 @@ ieee802_1x_mka_encode_dist_sak_body(
os_memcpy(body->sak, cipher_suite_tbl[cs_index].id, CS_ID_LEN);
sak_pos = CS_ID_LEN;
}
- if (aes_wrap(participant->kek.key,
+ if (aes_wrap(participant->kek.key, 16,
cipher_suite_tbl[cs_index].sak_len / 8,
sak->key, body->sak + sak_pos)) {
wpa_printf(MSG_ERROR, "KaY: AES wrap failed");
@@ -1611,7 +1611,7 @@ ieee802_1x_mka_decode_dist_sak_body(
wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
return -1;
}
- if (aes_unwrap(participant->kek.key, sak_len >> 3, wrap_sak,
+ if (aes_unwrap(participant->kek.key, 16, sak_len >> 3, wrap_sak,
unwrap_sak)) {
wpa_printf(MSG_ERROR, "KaY: AES unwrap failed");
os_free(unwrap_sak);
diff --git a/src/radius/radius_client.c b/src/radius/radius_client.c
index 10056a64..e2766e2f 100644
--- a/src/radius/radius_client.c
+++ b/src/radius/radius_client.c
@@ -1080,19 +1080,23 @@ radius_change_server(struct radius_client_data *radius,
switch (nserv->addr.af) {
case AF_INET:
claddrlen = sizeof(claddr);
- getsockname(sel_sock, (struct sockaddr *) &claddr, &claddrlen);
- wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
- inet_ntoa(claddr.sin_addr), ntohs(claddr.sin_port));
+ if (getsockname(sel_sock, (struct sockaddr *) &claddr,
+ &claddrlen) == 0) {
+ wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
+ inet_ntoa(claddr.sin_addr),
+ ntohs(claddr.sin_port));
+ }
break;
#ifdef CONFIG_IPV6
case AF_INET6: {
claddrlen = sizeof(claddr6);
- getsockname(sel_sock, (struct sockaddr *) &claddr6,
- &claddrlen);
- wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
- inet_ntop(AF_INET6, &claddr6.sin6_addr,
- abuf, sizeof(abuf)),
- ntohs(claddr6.sin6_port));
+ if (getsockname(sel_sock, (struct sockaddr *) &claddr6,
+ &claddrlen) == 0) {
+ wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
+ inet_ntop(AF_INET6, &claddr6.sin6_addr,
+ abuf, sizeof(abuf)),
+ ntohs(claddr6.sin6_port));
+ }
break;
}
#endif /* CONFIG_IPV6 */
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index 24348a39..00394b49 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -1926,7 +1926,7 @@ int radius_server_get_mib(struct radius_server_data *data, char *buf,
if (inet_ntop(AF_INET6, &cli->addr6, abuf,
sizeof(abuf)) == NULL)
abuf[0] = '\0';
- if (inet_ntop(AF_INET6, &cli->mask6, abuf,
+ if (inet_ntop(AF_INET6, &cli->mask6, mbuf,
sizeof(mbuf)) == NULL)
mbuf[0] = '\0';
}
@@ -2048,8 +2048,6 @@ void radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx)
sess = s;
break;
}
- if (sess)
- break;
}
if (sess)
break;
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index b5a87fc5..885291a2 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -35,7 +35,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
{
- os_free(entry);
+ bin_clear_free(entry, sizeof(*entry));
}
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 93ae1432..c4e5fedc 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -218,26 +218,29 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
u8 action_code, u8 dialog_token,
u16 status_code, u32 peer_capab,
- const u8 *buf, size_t len)
+ int initiator, const u8 *buf, size_t len)
{
return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
- status_code, peer_capab, buf, len);
+ status_code, peer_capab, initiator, buf,
+ len);
}
static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
u8 dialog_token, u16 status_code, u32 peer_capab,
- const u8 *msg, size_t msg_len)
+ int initiator, const u8 *msg, size_t msg_len)
{
struct wpa_tdls_peer *peer;
wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
- "dialog_token=%u status_code=%u peer_capab=%u msg_len=%u",
+ "dialog_token=%u status_code=%u peer_capab=%u initiator=%d "
+ "msg_len=%u",
MAC2STR(dest), action_code, dialog_token, status_code,
- peer_capab, (unsigned int) msg_len);
+ peer_capab, initiator, (unsigned int) msg_len);
if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
- status_code, peer_capab, msg, msg_len)) {
+ status_code, peer_capab, initiator, msg,
+ msg_len)) {
wpa_printf(MSG_INFO, "TDLS: Failed to send message "
"(action_code=%u)", action_code);
return -1;
@@ -333,6 +336,7 @@ static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
peer->sm_tmr.dialog_token,
peer->sm_tmr.status_code,
peer->sm_tmr.peer_capab,
+ peer->initiator,
peer->sm_tmr.buf,
peer->sm_tmr.buf_len)) {
wpa_printf(MSG_INFO, "TDLS: Failed to retry "
@@ -793,7 +797,7 @@ skip_ies:
/* request driver to send Teardown using this FTIE */
wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
- reason_code, 0, rbuf, pos - rbuf);
+ reason_code, 0, peer->initiator, rbuf, pos - rbuf);
os_free(rbuf);
return 0;
@@ -968,17 +972,19 @@ skip_ftie:
* appropriate status code mentioning reason for error/failure.
* @dst - MAC addr of Peer station
* @tdls_action - TDLS frame type for which error code is sent
+ * @initiator - was this end the initiator of the connection
* @status - status code mentioning reason
*/
static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
- u8 tdls_action, u8 dialog_token, u16 status)
+ u8 tdls_action, u8 dialog_token, int initiator,
+ u16 status)
{
wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
" (action=%u status=%u)",
MAC2STR(dst), tdls_action, status);
return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
- 0, NULL, 0);
+ 0, initiator, NULL, 0);
}
@@ -1184,7 +1190,7 @@ skip_ies:
MAC2STR(peer->addr));
status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST,
- 1, 0, 0, rbuf, pos - rbuf);
+ 1, 0, 0, peer->initiator, rbuf, pos - rbuf);
os_free(rbuf);
return status;
@@ -1274,7 +1280,8 @@ static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
skip_ies:
status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE,
- dtoken, 0, 0, rbuf, pos - rbuf);
+ dtoken, 0, 0, peer->initiator, rbuf,
+ pos - rbuf);
os_free(rbuf);
return status;
@@ -1371,7 +1378,8 @@ skip_ies:
peer_capab |= TDLS_PEER_WMM;
status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
- dtoken, 0, peer_capab, rbuf, pos - rbuf);
+ dtoken, 0, peer_capab, peer->initiator,
+ rbuf, pos - rbuf);
os_free(rbuf);
return status;
@@ -1430,8 +1438,8 @@ static int wpa_tdls_send_discovery_response(struct wpa_sm *sm,
hdr->len = (pos - (u8 *) hdr) - 2;
peer->rsnie_i_len = pos - peer->rsnie_i;
- wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response",
- (u8 *) hdr, hdr->len + 2);
+ wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response",
+ (u8 *) hdr, hdr->len + 2);
skip_rsn_ies:
buf_len = 0;
if (wpa_tdls_get_privacy(sm)) {
@@ -1457,7 +1465,7 @@ skip_rsn_ies:
wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
skip_ies:
status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
- dialog_token, 0, 0, rbuf, pos - rbuf);
+ dialog_token, 0, 0, 0, rbuf, pos - rbuf);
os_free(rbuf);
return status;
@@ -1528,7 +1536,7 @@ int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
MACSTR, MAC2STR(addr));
return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
- 1, 0, 0, NULL, 0);
+ 1, 0, 0, 1, NULL, 0);
}
@@ -1713,8 +1721,8 @@ static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
peer->supp_rates, peer->supp_rates_len,
peer->ht_capabilities,
peer->vht_capabilities,
- peer->qos_info, peer->ext_capab,
- peer->ext_capab_len,
+ peer->qos_info, peer->wmm_capable,
+ peer->ext_capab, peer->ext_capab_len,
peer->supp_channels,
peer->supp_channels_len,
peer->supp_oper_classes,
@@ -1858,6 +1866,8 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
"TDLS setup - send own request");
peer->initiator = 1;
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
+ NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0);
wpa_tdls_send_tpk_m1(sm, peer);
}
@@ -2036,10 +2046,18 @@ skip_rsn:
wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
skip_rsn_check:
+#ifdef CONFIG_TDLS_TESTING
+ if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT)
+ goto skip_add_peer;
+#endif /* CONFIG_TDLS_TESTING */
+
/* add supported rates, capabilities, and qos_info to the TDLS peer */
if (wpa_tdls_addset_peer(sm, peer, 1) < 0)
goto error;
+#ifdef CONFIG_TDLS_TESTING
+skip_add_peer:
+#endif /* CONFIG_TDLS_TESTING */
peer->tpk_in_progress = 1;
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
@@ -2051,7 +2069,7 @@ skip_rsn_check:
return 0;
error:
- wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken,
+ wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
status);
if (peer)
wpa_tdls_peer_free(sm, peer);
@@ -2362,7 +2380,7 @@ skip_rsn:
return ret;
error:
- wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken,
+ wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1,
status);
wpa_tdls_disable_peer_link(sm, peer);
return -1;
@@ -2587,7 +2605,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
/* add the peer to the driver as a "setup in progress" peer */
if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
- NULL, 0, NULL, 0, NULL, 0, NULL, 0)) {
+ NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
wpa_tdls_disable_peer_link(sm, peer);
return -1;
}
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 56718b1b..7c89473e 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -1311,7 +1311,8 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
(unsigned long) maxkeylen);
return -1;
}
- if (aes_unwrap(sm->ptk.kek, maxkeylen / 8, key_data, gd->gtk)) {
+ if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, key_data,
+ gd->gtk)) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: AES unwrap failed - could not decrypt "
"GTK");
@@ -1519,7 +1520,7 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
"WPA: No memory for AES-UNWRAP buffer");
return -1;
}
- if (aes_unwrap(sm->ptk.kek, *key_data_len / 8,
+ if (aes_unwrap(sm->ptk.kek, 16, *key_data_len / 8,
key_data, buf)) {
os_free(buf);
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 413b46e6..0b5b97de 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -55,14 +55,14 @@ struct wpa_sm_ctx {
int (*send_tdls_mgmt)(void *ctx, const u8 *dst,
u8 action_code, u8 dialog_token,
u16 status_code, u32 peer_capab,
- const u8 *buf, size_t len);
+ int initiator, const u8 *buf, size_t len);
int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid,
u16 capability, const u8 *supp_rates,
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
- u8 qosinfo, const u8 *ext_capab,
+ u8 qosinfo, int wmm, const u8 *ext_capab,
size_t ext_capab_len, const u8 *supp_channels,
size_t supp_channels_len,
const u8 *supp_oper_classes,
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 4a75b926..3b3c9d0d 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -566,7 +566,7 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
return -1;
}
gtk_len = gtk_elem_len - 19;
- if (aes_unwrap(sm->ptk.kek, gtk_len / 8, gtk_elem + 11, gtk)) {
+ if (aes_unwrap(sm->ptk.kek, 16, gtk_len / 8, gtk_elem + 11, gtk)) {
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
"decrypt GTK");
return -1;
@@ -645,7 +645,8 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
return -1;
}
- if (aes_unwrap(sm->ptk.kek, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk)) {
+ if (aes_unwrap(sm->ptk.kek, 16, WPA_IGTK_LEN / 8, igtk_elem + 9, igtk))
+ {
wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
"decrypt IGTK");
return -1;
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 03892af3..aeabc244 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -268,12 +268,14 @@ static inline int wpa_sm_tdls_get_capa(struct wpa_sm *sm,
static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst,
u8 action_code, u8 dialog_token,
u16 status_code, u32 peer_capab,
- const u8 *buf, size_t len)
+ int initiator, const u8 *buf,
+ size_t len)
{
if (sm->ctx->send_tdls_mgmt)
return sm->ctx->send_tdls_mgmt(sm->ctx->ctx, dst, action_code,
dialog_token, status_code,
- peer_capab, buf, len);
+ peer_capab, initiator, buf,
+ len);
return -1;
}
@@ -291,16 +293,16 @@ wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
- u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len,
- const u8 *supp_channels, size_t supp_channels_len,
- const u8 *supp_oper_classes,
+ u8 qosinfo, int wmm, const u8 *ext_capab,
+ size_t ext_capab_len, const u8 *supp_channels,
+ size_t supp_channels_len, const u8 *supp_oper_classes,
size_t supp_oper_classes_len)
{
if (sm->ctx->tdls_peer_addset)
return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
aid, capability, supp_rates,
supp_rates_len, ht_capab,
- vht_capab, qosinfo,
+ vht_capab, qosinfo, wmm,
ext_capab, ext_capab_len,
supp_channels,
supp_channels_len,
diff --git a/src/utils/browser-android.c b/src/utils/browser-android.c
index a0663925..d5ff5b5c 100644
--- a/src/utils/browser-android.c
+++ b/src/utils/browser-android.c
@@ -75,7 +75,7 @@ int hs20_web_browser(const char *url)
os_memset(&data, 0, sizeof(data));
ret = os_snprintf(cmd, sizeof(cmd),
- "am start -a android.intent.action.VIEW -d '%s' "
+ "start -a android.intent.action.VIEW -d %s "
"-n com.android.browser/.BrowserActivity", url);
if (ret < 0 || (size_t) ret >= sizeof(cmd)) {
wpa_printf(MSG_ERROR, "Too long URL");
@@ -94,7 +94,7 @@ int hs20_web_browser(const char *url)
return -1;
}
- if (system(cmd) != 0) {
+ if (os_exec("/system/bin/am", cmd, 1) != 0) {
wpa_printf(MSG_INFO, "Failed to launch Android browser");
eloop_cancel_timeout(browser_timeout, NULL, NULL);
http_server_deinit(http);
@@ -109,7 +109,7 @@ int hs20_web_browser(const char *url)
eloop_destroy();
wpa_printf(MSG_INFO, "Closing Android browser");
- if (system("input keyevent 3") != 0) {
+ if (os_exec("/system/bin/input", "keyevent 3", 1) != 0) {
wpa_printf(MSG_INFO, "Failed to inject keyevent");
}
diff --git a/src/utils/browser-system.c b/src/utils/browser-system.c
index 2884d341..a080e2cb 100644
--- a/src/utils/browser-system.c
+++ b/src/utils/browser-system.c
@@ -92,7 +92,7 @@ int hs20_web_browser(const char *url)
return -1;
}
- if (system(cmd) != 0) {
+ if (os_exec("/usr/bin/x-www-browser", url, 0) != 0) {
wpa_printf(MSG_INFO, "Failed to launch browser");
eloop_cancel_timeout(browser_timeout, NULL, NULL);
http_server_deinit(http);
diff --git a/src/utils/browser-wpadebug.c b/src/utils/browser-wpadebug.c
index eeb8f650..ce3054bb 100644
--- a/src/utils/browser-wpadebug.c
+++ b/src/utils/browser-wpadebug.c
@@ -76,7 +76,7 @@ int hs20_web_browser(const char *url)
os_memset(&data, 0, sizeof(data));
ret = os_snprintf(cmd, sizeof(cmd),
- "am start -a android.action.MAIN "
+ "start -a android.action.MAIN "
"-c android.intent.category.LAUNCHER "
"-n w1.fi.wpadebug/.WpaWebViewActivity "
"-e w1.fi.wpadebug.URL '%s'", url);
@@ -97,7 +97,7 @@ int hs20_web_browser(const char *url)
return -1;
}
- if (system(cmd) != 0) {
+ if (os_exec("/system/bin/am", cmd, 1) != 0) {
wpa_printf(MSG_INFO, "Failed to launch wpadebug browser");
eloop_cancel_timeout(browser_timeout, NULL, NULL);
http_server_deinit(http);
@@ -112,10 +112,11 @@ int hs20_web_browser(const char *url)
eloop_destroy();
wpa_printf(MSG_INFO, "Closing Android browser");
- if (system("am start -a android.action.MAIN "
- "-c android.intent.category.LAUNCHER "
- "-n w1.fi.wpadebug/.WpaWebViewActivity "
- "-e w1.fi.wpadebug.URL FINISH") != 0) {
+ if (os_exec("/system/bin/am",
+ "start -a android.action.MAIN "
+ "-c android.intent.category.LAUNCHER "
+ "-n w1.fi.wpadebug/.WpaWebViewActivity "
+ "-e w1.fi.wpadebug.URL FINISH", 1) != 0) {
wpa_printf(MSG_INFO, "Failed to close wpadebug browser");
}
diff --git a/src/utils/common.c b/src/utils/common.c
index 5b017e57..99020049 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -362,7 +362,7 @@ void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
*txt++ = '\\';
*txt++ = '\\';
break;
- case '\e':
+ case '\033':
*txt++ = '\\';
*txt++ = 'e';
break;
@@ -427,7 +427,7 @@ size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
pos++;
break;
case 'e':
- buf[len++] = '\e';
+ buf[len++] = '\033';
pos++;
break;
case 'x':
@@ -846,3 +846,23 @@ void bin_clear_free(void *bin, size_t len)
os_free(bin);
}
}
+
+
+int random_mac_addr(u8 *addr)
+{
+ if (os_get_random(addr, ETH_ALEN) < 0)
+ return -1;
+ addr[0] &= 0xfe; /* unicast */
+ addr[0] |= 0x02; /* locally administered */
+ return 0;
+}
+
+
+int random_mac_addr_keep_oui(u8 *addr)
+{
+ if (os_get_random(addr + 3, 3) < 0)
+ return -1;
+ addr[0] &= 0xfe; /* unicast */
+ addr[0] |= 0x02; /* locally administered */
+ return 0;
+}
diff --git a/src/utils/common.h b/src/utils/common.h
index 2bc8fe14..14d9ad1e 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -538,6 +538,9 @@ void int_array_add_unique(int **res, int a);
void str_clear_free(char *str);
void bin_clear_free(void *bin, size_t len);
+int random_mac_addr(u8 *addr);
+int random_mac_addr_keep_oui(u8 *addr);
+
/*
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
diff --git a/src/utils/http_curl.c b/src/utils/http_curl.c
index 8692f9f8..3a042f93 100644
--- a/src/utils/http_curl.c
+++ b/src/utils/http_curl.c
@@ -1177,9 +1177,10 @@ static int ocsp_resp_cb(SSL *s, void *arg)
if (status == V_OCSP_CERTSTATUS_GOOD)
return 1;
- if (status == V_OCSP_CERTSTATUS_REVOKED)
+ if (status == V_OCSP_CERTSTATUS_REVOKED) {
ctx->last_err = "Server certificate has been revoked";
return 0;
+ }
if (ctx->ocsp == MANDATORY_OCSP) {
wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
ctx->last_err = "OCSP status unknown";
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index f7d41b4d..9f5a90ce 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -175,6 +175,12 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps)
}
wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
+ if (wps->wps->ap && random_pool_ready() != 1) {
+ wpa_printf(MSG_INFO,
+ "WPS: Not enough entropy in random pool to proceed - do not allow AP PIN to be used");
+ return NULL;
+ }
+
msg = wpabuf_alloc(1000);
if (msg == NULL)
return NULL;
@@ -268,8 +274,12 @@ static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg)
char hex[65];
u8 psk[32];
/* Generate a random per-device PSK */
- if (random_get_bytes(psk, sizeof(psk)) < 0)
+ if (random_pool_ready() != 1 ||
+ random_get_bytes(psk, sizeof(psk)) < 0) {
+ wpa_printf(MSG_INFO,
+ "WPS: Could not generate random PSK");
return -1;
+ }
wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK",
psk, sizeof(psk));
wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%u)",
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 00c8299a..b90cc25e 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1640,8 +1640,12 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
!wps->wps->registrar->disable_auto_conf) {
u8 r[16];
/* Generate a random passphrase */
- if (random_get_bytes(r, sizeof(r)) < 0)
+ if (random_pool_ready() != 1 ||
+ random_get_bytes(r, sizeof(r)) < 0) {
+ wpa_printf(MSG_INFO,
+ "WPS: Could not generate random PSK");
return -1;
+ }
os_free(wps->new_psk);
wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len);
if (wps->new_psk == NULL)
@@ -1674,7 +1678,10 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
wps->new_psk = os_malloc(wps->new_psk_len);
if (wps->new_psk == NULL)
return -1;
- if (random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) {
+ if (random_pool_ready() != 1 ||
+ random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) {
+ wpa_printf(MSG_INFO,
+ "WPS: Could not generate random PSK");
os_free(wps->new_psk);
wps->new_psk = NULL;
return -1;