Cumulative patch from commit 99cd77a8c50413d44f1ebead917310468a8406de
99cd77a tests: Verify reassociate-to-same-BSS commands
e8d70a7 nl80211: Hide deauth event due to forced deauth-during-auth
0f44ec8 Add a reattach command for fast reassociate-back-to-same-BSS
cfc393a hostapd: Document interworking realm EAP Method types
7450c12 DFS: Add extra debugging messages
5d0d72a wpa_supplicant: Put upper bound on initial scan time delay
8c06db7 nl80211: Fix P2P Device handling when starting with RF-kill blocked
5e3ddf4 PNO: Change sched_scan_stopped event to handle pending PNO properly
737e7a0 PNO: Move and rename pno_start()/pno_stop()
1d91f50 hostapd: Process management frames only once per BSS
e070051 hostapd: Allow to switch to usable DFS channels
01b9999 hostapd: Allow to switch to DFS channels if available
70ee1be hostapd: Add config option chanlist for DFS channels
09eef14 Use internal FIPS 186-2 PRF if needed
3b9c517 Fix PTK derivation for CCMP-256 and GCMP-256
e6ef73f nl80211: Add debug print of KEY_DATA and KEY_SEQ
b465f5d Remove unused hostapd_wep_key_cmp()
4fb363c Fix error path handling on radius_accept_attr
Change-Id: I28ecac6cbcc6f71f19a051c12b54668ca6a66e2a
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 888ee2b..b96345f 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -539,7 +539,8 @@
OBJS += src/crypto/crypto_gnutls.c
HOBJS += src/crypto/crypto_gnutls.c
ifdef NEED_FIPS186_2_PRF
-OBJS += src/crypto/fips_prf_gnutls.c
+OBJS += src/crypto/fips_prf_internal.c
+OBJS += src/crypto/sha1-internal.c
endif
LIBS += -lgcrypt
LIBS_h += -lgcrypt
@@ -566,7 +567,8 @@
endif
OBJS += src/crypto/crypto_nss.c
ifdef NEED_FIPS186_2_PRF
-OBJS += src/crypto/fips_prf_nss.c
+OBJS += src/crypto/fips_prf_internal.c
+OBJS += src/crypto/sha1-internal.c
endif
LIBS += -lnss3
LIBS_h += -lnss3
diff --git a/hostapd/Makefile b/hostapd/Makefile
index c541d43..1496888 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -522,7 +522,8 @@
OBJS += ../src/crypto/crypto_gnutls.o
HOBJS += ../src/crypto/crypto_gnutls.o
ifdef NEED_FIPS186_2_PRF
-OBJS += ../src/crypto/fips_prf_gnutls.o
+OBJS += ../src/crypto/fips_prf_internal.o
+SHA1OBJS += ../src/crypto/sha1-internal.o
endif
LIBS += -lgcrypt
LIBS_h += -lgcrypt
@@ -549,7 +550,8 @@
endif
OBJS += ../src/crypto/crypto_nss.o
ifdef NEED_FIPS186_2_PRF
-OBJS += ../src/crypto/fips_prf_nss.o
+OBJS += ../src/crypto/fips_prf_internal.o
+SHA1OBJS += ../src/crypto/sha1-internal.o
endif
LIBS += -lnss3
LIBS_h += -lnss3
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 949a9d1..b6f1d1b 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -257,6 +257,7 @@
if (attr == NULL) {
wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
buf + 19);
+ user = NULL; /* already in the BSS list */
goto failed;
}
if (user->accept_attr == NULL) {
@@ -2485,6 +2486,13 @@
conf->channel = 0;
} else
conf->channel = atoi(pos);
+ } else if (os_strcmp(buf, "chanlist") == 0) {
+ if (hostapd_parse_intlist(&conf->chanlist, pos)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: invalid channel list",
+ line);
+ errors++;
+ }
} else if (os_strcmp(buf, "beacon_int") == 0) {
int val = atoi(pos);
/* MIB defines range as 1..65535, but very small values
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index c745fe8..81ddabc 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -154,6 +154,14 @@
# Defaults:
#acs_num_scans=5
+# Channel list restriction. This option allows hostapd to select one of the
+# provided channels when a channel should be automatically selected. This
+# is currently only used for DFS when the current channels becomes unavailable
+# due to radar interference, and is currently only useful when ieee80211h=1 is
+# set.
+# Default: not set (allow any enabled channel to be selected)
+#chanlist=100 104 108 112 116
+
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
beacon_int=100
@@ -1540,6 +1548,8 @@
# accordance with IETF RFC 4282
# NAI Realm(s): Semi-colon delimited NAI Realm(s)
# EAP Method: <EAP Method>[:<[AuthParam1:Val1]>][<[AuthParam2:Val2]>][...]
+# EAP Method types, see:
+# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-4
# AuthParam (Table 8-188 in IEEE Std 802.11-2012):
# ID 2 = Non-EAP Inner Authentication Type
# 1 = PAP, 2 = CHAP, 3 = MSCHAP, 4 = MSCHAPV2
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index f744985..3ca85a0 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -338,20 +338,6 @@
}
-int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
-{
- int i;
-
- if (a->idx != b->idx || a->default_len != b->default_len)
- return 1;
- for (i = 0; i < NUM_WEP_KEYS; i++)
- if (a->len[i] != b->len[i] ||
- os_memcmp(a->key[i], b->key[i], a->len[i]) != 0)
- return 1;
- return 0;
-}
-
-
static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
int num_servers)
{
@@ -576,6 +562,7 @@
os_free(conf->bss);
os_free(conf->supported_rates);
os_free(conf->basic_rates);
+ os_free(conf->chanlist);
os_free(conf);
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index f6ca8b1..aa3a51a 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -525,6 +525,7 @@
int fragm_threshold;
u8 send_probe_response;
u8 channel;
+ int *chanlist;
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
enum {
LONG_PREAMBLE = 0,
@@ -608,8 +609,6 @@
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
const u8 *addr, int *vlan_id);
int hostapd_rate_found(int *list, int rate);
-int hostapd_wep_key_cmp(struct hostapd_wep_keys *a,
- struct hostapd_wep_keys *b);
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *p2p_dev_addr,
const u8 *prev_psk);
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 92eda21..0f262ce 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -50,9 +50,11 @@
/*
* When radar detection happens, CSA is performed. However, there's no
* time for CAC, so radar channels must be skipped when finding a new
- * channel for CSA.
+ * channel for CSA, unless they are available for immediate use.
*/
- if (skip_radar && chan->flag & HOSTAPD_CHAN_RADAR)
+ if (skip_radar && (chan->flag & HOSTAPD_CHAN_RADAR) &&
+ ((chan->flag & HOSTAPD_CHAN_DFS_MASK) !=
+ HOSTAPD_CHAN_DFS_AVAILABLE))
return 0;
if (chan->flag & HOSTAPD_CHAN_DISABLED)
@@ -139,6 +141,22 @@
}
+static int is_in_chanlist(struct hostapd_iface *iface,
+ struct hostapd_channel_data *chan)
+{
+ int *entry;
+
+ if (!iface->conf->chanlist)
+ return 1;
+
+ for (entry = iface->conf->chanlist; *entry != -1; entry++) {
+ if (*entry == chan->chan)
+ return 1;
+ }
+ return 0;
+}
+
+
/*
* The function assumes HT40+ operation.
* Make sure to adjust the following variables after calling this:
@@ -171,6 +189,9 @@
if (!dfs_chan_range_available(mode, i, n_chans, skip_radar))
continue;
+ if (!is_in_chanlist(iface, chan))
+ continue;
+
if (ret_chan && idx == channel_idx) {
wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan);
*ret_chan = chan;
@@ -267,8 +288,19 @@
}
}
- if (res == -1)
- wpa_printf(MSG_DEBUG, "DFS chan_idx seems wrong: -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",
+ mode->num_channels, channel_no, iface->conf->channel,
+ iface->conf->ieee80211n,
+ iface->conf->secondary_channel,
+ iface->conf->vht_oper_chwidth);
+
+ for (i = 0; i < mode->num_channels; i++) {
+ wpa_printf(MSG_DEBUG, "Available channel: %d",
+ mode->channels[i].chan);
+ }
+ }
return res;
}
@@ -727,9 +759,33 @@
skip_radar);
if (!channel) {
- /* FIXME: Wait for channel(s) to become available */
+ /*
+ * If there is no channel to switch immediately to, check if
+ * there is another channel where we can switch even if it
+ * requires to perform a CAC first.
+ */
+ skip_radar = 0;
+ channel = dfs_get_valid_channel(iface, &secondary_channel,
+ &vht_oper_centr_freq_seg0_idx,
+ &vht_oper_centr_freq_seg1_idx,
+ skip_radar);
+ if (!channel) {
+ /* FIXME: Wait for channel(s) to become available */
+ hostapd_disable_iface(iface);
+ return err;
+ }
+
+ iface->freq = channel->freq;
+ iface->conf->channel = channel->chan;
+ iface->conf->secondary_channel = secondary_channel;
+ iface->conf->vht_oper_centr_freq_seg0_idx =
+ vht_oper_centr_freq_seg0_idx;
+ iface->conf->vht_oper_centr_freq_seg1_idx =
+ vht_oper_centr_freq_seg1_idx;
+
hostapd_disable_iface(iface);
- return err;
+ hostapd_enable_iface(iface);
+ return 0;
}
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 3318f7a..a8c24eb 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -721,6 +721,12 @@
size_t i;
ret = 0;
for (i = 0; i < iface->num_bss; i++) {
+ /* if bss is set, driver will call this function for
+ * each bss individually. */
+ if (rx_mgmt->drv_priv &&
+ (iface->bss[i]->drv_priv != rx_mgmt->drv_priv))
+ continue;
+
if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
rx_mgmt->frame_len, &fi) > 0)
ret = 1;
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index cc64ff1..7d89edf 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1813,7 +1813,7 @@
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk,
struct wpa_ptk *ptk)
{
- size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64;
+ size_t ptk_len = wpa_cipher_key_len(sm->pairwise) + 32;
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len);
diff --git a/src/crypto/Makefile b/src/crypto/Makefile
index fcf9586..2a92109 100644
--- a/src/crypto/Makefile
+++ b/src/crypto/Makefile
@@ -9,6 +9,7 @@
include ../lib.rules
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
#CFLAGS += -DALL_DH_GROUPS
diff --git a/src/crypto/fips_prf_cryptoapi.c b/src/crypto/fips_prf_cryptoapi.c
deleted file mode 100644
index dca93a3..0000000
--- a/src/crypto/fips_prf_cryptoapi.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * FIPS 186-2 PRF for Microsoft CryptoAPI
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-
-#include "common.h"
-#include "crypto.h"
-
-
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
- /* FIX: how to do this with CryptoAPI? */
- return -1;
-}
diff --git a/src/crypto/fips_prf_gnutls.c b/src/crypto/fips_prf_gnutls.c
deleted file mode 100644
index 947e6f6..0000000
--- a/src/crypto/fips_prf_gnutls.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * FIPS 186-2 PRF for libgcrypt
- * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <gcrypt.h>
-
-#include "common.h"
-#include "crypto.h"
-
-
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
- /* FIX: how to do this with libgcrypt? */
- return -1;
-}
diff --git a/src/crypto/fips_prf_nss.c b/src/crypto/fips_prf_nss.c
deleted file mode 100644
index 2c962f4..0000000
--- a/src/crypto/fips_prf_nss.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * FIPS 186-2 PRF for NSS
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include <openssl/sha.h>
-
-#include "common.h"
-#include "crypto.h"
-
-
-int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
-{
- return -1;
-}
diff --git a/src/crypto/sha1-internal.c b/src/crypto/sha1-internal.c
index 10bf153..24bc3ff 100644
--- a/src/crypto/sha1-internal.c
+++ b/src/crypto/sha1-internal.c
@@ -19,6 +19,7 @@
void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
+#ifdef CONFIG_CRYPTO_INTERNAL
/**
* sha1_vector - SHA-1 hash for data vector
* @num_elem: Number of elements in the data vector
@@ -38,6 +39,7 @@
SHA1Final(mac, &ctx);
return 0;
}
+#endif /* CONFIG_CRYPTO_INTERNAL */
/* ===== start - public domain SHA1 implementation ===== */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index a92de56..2eafc14 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -3585,6 +3585,15 @@
u32 datarate;
/**
+ * drv_priv - Pointer to store driver private BSS information
+ *
+ * If not set to NULL, this is used for comparison with
+ * hostapd_data->drv_priv to determine which BSS should process
+ * the frame.
+ */
+ void *drv_priv;
+
+ /**
* freq - Frequency (in MHz) on which the frame was received
*/
int freq;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 9b9e66c..d60f95b 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -302,6 +302,7 @@
unsigned int start_mode_ap:1;
unsigned int start_iface_up:1;
unsigned int test_use_roc_tx:1;
+ unsigned int ignore_deauth_event:1;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
@@ -1681,10 +1682,11 @@
}
-static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
+static void mlme_event_mgmt(struct i802_bss *bss,
struct nlattr *freq, struct nlattr *sig,
const u8 *frame, size_t len)
{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
const struct ieee80211_mgmt *mgmt;
union wpa_event_data event;
u16 fc, stype;
@@ -1715,6 +1717,7 @@
event.rx_mgmt.frame = frame;
event.rx_mgmt.frame_len = len;
event.rx_mgmt.ssi_signal = ssi_signal;
+ event.rx_mgmt.drv_priv = bss;
wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
}
@@ -1825,6 +1828,11 @@
mgmt->u.disassoc.variable;
}
} else {
+ if (drv->ignore_deauth_event) {
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event due to previous forced deauth-during-auth");
+ drv->ignore_deauth_event = 0;
+ return;
+ }
event.deauth_info.locally_generated =
!os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
event.deauth_info.addr = bssid;
@@ -1939,7 +1947,7 @@
nla_data(frame), nla_len(frame));
break;
case NL80211_CMD_FRAME:
- mlme_event_mgmt(drv, freq, sig, nla_data(frame),
+ mlme_event_mgmt(bss, freq, sig, nla_data(frame),
nla_len(frame));
break;
case NL80211_CMD_FRAME_TX_STATUS:
@@ -4640,26 +4648,25 @@
return -1;
}
- if (nlmode == NL80211_IFTYPE_P2P_DEVICE) {
- int ret = nl80211_set_p2pdev(bss, 1);
- if (ret < 0)
- wpa_printf(MSG_ERROR, "nl80211: Could not start P2P device");
+ if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
nl80211_get_macaddr(bss);
- return ret;
- }
- if (linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1)) {
- if (rfkill_is_blocked(drv->rfkill)) {
- wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
- "interface '%s' due to rfkill",
- bss->ifname);
- drv->if_disabled = 1;
- send_rfkill_event = 1;
- } else {
+ if (!rfkill_is_blocked(drv->rfkill)) {
+ int ret = i802_set_iface_flags(bss, 1);
+ if (ret) {
wpa_printf(MSG_ERROR, "nl80211: Could not set "
"interface '%s' UP", bss->ifname);
- return -1;
+ return ret;
}
+ if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
+ return ret;
+ } else {
+ wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
+ "interface '%s' due to rfkill", bss->ifname);
+ if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
+ return 0;
+ drv->if_disabled = 1;
+ send_rfkill_event = 1;
}
if (!drv->hostapd)
@@ -5609,12 +5616,15 @@
} else {
nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_KEY);
NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);
+ wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len);
NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
wpa_alg_to_cipher_suite(alg, key_len));
}
- if (seq && seq_len)
+ if (seq && seq_len) {
NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq);
+ wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
+ }
if (addr && !is_broadcast_ether_addr(addr)) {
wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr));
@@ -5922,6 +5932,7 @@
is_retry = drv->retry_auth;
drv->retry_auth = 0;
+ drv->ignore_deauth_event = 0;
nl80211_mark_disconnected(drv);
os_memset(drv->auth_bssid, 0, ETH_ALEN);
@@ -6023,6 +6034,7 @@
*/
wpa_printf(MSG_DEBUG, "nl80211: Retry authentication "
"after forced deauthentication");
+ drv->ignore_deauth_event = 1;
wpa_driver_nl80211_deauthenticate(
bss, params->bssid,
WLAN_REASON_PREV_AUTH_NOT_VALID);
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index ba50263..de86cdf 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -362,7 +362,7 @@
const struct wpa_eapol_key *key,
struct wpa_ptk *ptk)
{
- size_t ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64;
+ size_t ptk_len = wpa_cipher_key_len(sm->pairwise_cipher) + 32;
#ifdef CONFIG_IEEE80211R
if (wpa_key_mgmt_ft(sm->key_mgmt))
return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len);
@@ -437,10 +437,12 @@
* been verified when processing message 3/4. */
ptk = &sm->tptk;
wpa_derive_ptk(sm, src_addr, key, ptk);
- /* Supplicant: swap tx/rx Mic keys */
- os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
- os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
- os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
+ if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
+ /* Supplicant: swap tx/rx Mic keys */
+ os_memcpy(buf, ptk->u.auth.tx_mic_key, 8);
+ os_memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8);
+ os_memcpy(ptk->u.auth.rx_mic_key, buf, 8);
+ }
sm->tptk_set = 1;
kde = sm->assoc_wpa_ie;
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index c745cb2..b8690f5 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -962,7 +962,8 @@
OBJS += src/crypto/crypto_gnutls.c
OBJS_p += src/crypto/crypto_gnutls.c
ifdef NEED_FIPS186_2_PRF
-OBJS += src/crypto/fips_prf_gnutls.c
+OBJS += src/crypto/fips_prf_internal.c
+OBJS += src/crypto/sha1-internal.c
endif
LIBS += -lgcrypt
LIBS_p += -lgcrypt
@@ -978,7 +979,8 @@
OBJS += src/crypto/crypto_cryptoapi.c
OBJS_p += src/crypto/crypto_cryptoapi.c
ifdef NEED_FIPS186_2_PRF
-OBJS += src/crypto/fips_prf_cryptoapi.c
+OBJS += src/crypto/fips_prf_internal.c
+OBJS += src/crypto/sha1-internal.c
endif
CONFIG_INTERNAL_SHA256=y
CONFIG_INTERNAL_RC4=y
@@ -993,7 +995,8 @@
OBJS += src/crypto/crypto_nss.c
OBJS_p += src/crypto/crypto_nss.c
ifdef NEED_FIPS186_2_PRF
-OBJS += src/crypto/fips_prf_nss.c
+OBJS += src/crypto/fips_prf_internal.c
+OBJS += src/crypto/sha1-internal.c
endif
LIBS += -lnss3
LIBS_p += -lnss3
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 2b8cb93..ce98068 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -967,7 +967,8 @@
OBJS += ../src/crypto/crypto_gnutls.o
OBJS_p += ../src/crypto/crypto_gnutls.o
ifdef NEED_FIPS186_2_PRF
-OBJS += ../src/crypto/fips_prf_gnutls.o
+OBJS += ../src/crypto/fips_prf_internal.o
+SHA1OBJS += ../src/crypto/sha1-internal.o
endif
LIBS += -lgcrypt
LIBS_p += -lgcrypt
@@ -983,7 +984,8 @@
OBJS += ../src/crypto/crypto_cryptoapi.o
OBJS_p += ../src/crypto/crypto_cryptoapi.o
ifdef NEED_FIPS186_2_PRF
-OBJS += ../src/crypto/fips_prf_cryptoapi.o
+OBJS += ../src/crypto/fips_prf_internal.o
+SHA1OBJS += ../src/crypto/sha1-internal.o
endif
CONFIG_INTERNAL_SHA256=y
CONFIG_INTERNAL_RC4=y
@@ -998,7 +1000,8 @@
OBJS += ../src/crypto/crypto_nss.o
OBJS_p += ../src/crypto/crypto_nss.o
ifdef NEED_FIPS186_2_PRF
-OBJS += ../src/crypto/fips_prf_nss.o
+OBJS += ../src/crypto/fips_prf_internal.o
+SHA1OBJS += ../src/crypto/sha1-internal.o
endif
LIBS += -lnss3
LIBS_p += -lnss3
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index fdf8ac3..98c4b65 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -47,108 +47,6 @@
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
char *buf, int len);
-
-static int pno_start(struct wpa_supplicant *wpa_s)
-{
- int ret, interval;
- size_t i, num_ssid;
- struct wpa_ssid *ssid;
- struct wpa_driver_scan_params params;
-
- if (wpa_s->pno || wpa_s->pno_sched_pending)
- return 0;
-
- if ((wpa_s->wpa_state > WPA_SCANNING) &&
- (wpa_s->wpa_state <= WPA_COMPLETED)) {
- wpa_printf(MSG_ERROR, "PNO: In assoc process");
- return -EAGAIN;
- }
-
- if (wpa_s->wpa_state == WPA_SCANNING) {
- wpa_supplicant_cancel_scan(wpa_s);
- if (wpa_s->sched_scanning) {
- wpa_printf(MSG_DEBUG, "Schedule PNO on completion of "
- "ongoing sched scan");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_s->pno_sched_pending = 1;
- return 0;
- }
- }
-
- os_memset(¶ms, 0, sizeof(params));
-
- num_ssid = 0;
- ssid = wpa_s->conf->ssid;
- while (ssid) {
- if (!wpas_network_disabled(wpa_s, ssid))
- num_ssid++;
- ssid = ssid->next;
- }
- if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
- wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
- "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
- num_ssid = WPAS_MAX_SCAN_SSIDS;
- }
-
- if (num_ssid == 0) {
- wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
- return -1;
- }
-
- params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
- num_ssid);
- if (params.filter_ssids == NULL)
- return -1;
- i = 0;
- ssid = wpa_s->conf->ssid;
- while (ssid) {
- if (!wpas_network_disabled(wpa_s, ssid)) {
- params.ssids[i].ssid = ssid->ssid;
- params.ssids[i].ssid_len = ssid->ssid_len;
- params.num_ssids++;
- os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
- ssid->ssid_len);
- params.filter_ssids[i].ssid_len = ssid->ssid_len;
- params.num_filter_ssids++;
- i++;
- if (i == num_ssid)
- break;
- }
- ssid = ssid->next;
- }
-
- if (wpa_s->conf->filter_rssi)
- params.filter_rssi = wpa_s->conf->filter_rssi;
-
- interval = wpa_s->conf->sched_scan_interval ?
- wpa_s->conf->sched_scan_interval : 10;
-
- ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval);
- os_free(params.filter_ssids);
- if (ret == 0)
- wpa_s->pno = 1;
- return ret;
-}
-
-
-static int pno_stop(struct wpa_supplicant *wpa_s)
-{
- int ret = 0;
-
- if (wpa_s->pno || wpa_s->sched_scanning) {
- wpa_s->pno = 0;
- ret = wpa_supplicant_stop_sched_scan(wpa_s);
- }
-
- wpa_s->pno_sched_pending = 0;
-
- if (wpa_s->wpa_state == WPA_SCANNING)
- wpa_supplicant_req_scan(wpa_s, 0, 0);
-
- return ret;
-}
-
-
static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val)
{
char *pos;
@@ -392,9 +290,9 @@
#endif /* CONFIG_TDLS */
} else if (os_strcasecmp(cmd, "pno") == 0) {
if (atoi(value))
- ret = pno_start(wpa_s);
+ ret = wpas_start_pno(wpa_s);
else
- ret = pno_stop(wpa_s);
+ ret = wpas_stop_pno(wpa_s);
} else if (os_strcasecmp(cmd, "radio_disabled") == 0) {
int disabled = atoi(value);
if (wpa_drv_radio_disable(wpa_s, disabled) < 0)
@@ -6065,6 +5963,14 @@
reply_len = -1;
else
wpas_request_connection(wpa_s);
+ } else if (os_strcmp(buf, "REATTACH") == 0) {
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED ||
+ !wpa_s->current_ssid)
+ reply_len = -1;
+ else {
+ wpa_s->reattach = 1;
+ wpas_request_connection(wpa_s);
+ }
} else if (os_strcmp(buf, "RECONNECT") == 0) {
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
reply_len = -1;
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index f40d421..5e02956 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2462,6 +2462,12 @@
END_ARGS
}
},
+ { "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) &wpas_dbus_handler_reattach,
+ {
+ END_ARGS
+ }
+ },
{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
(WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
{
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index bfb33d5..5466d16 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -1487,6 +1487,29 @@
/**
+ * wpas_dbus_handler_reattach - Reattach to current AP
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NotConnected DBus error message if not connected
+ * or NULL otherwise.
+ *
+ * Handler function for "Reattach" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->current_ssid != NULL) {
+ wpa_s->reattach = 1;
+ wpas_request_connection(wpa_s);
+ return NULL;
+ }
+
+ return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
+ "This interface is not connected");
+}
+
+
+/**
* wpas_dbus_handler_remove_network - Remove a configured network
* @message: Pointer to incoming dbus message
* @wpa_s: wpa_supplicant structure for a network interface
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index c066944..461970d 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -101,6 +101,9 @@
DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+
DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 65c162e..1d65245 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3383,15 +3383,11 @@
* Start a new sched scan to continue searching for more SSIDs
* either if timed out or PNO schedule scan is pending.
*/
- if (wpa_s->sched_scan_timed_out || wpa_s->pno_sched_pending) {
-
- if (wpa_supplicant_req_sched_scan(wpa_s) < 0 &&
- wpa_s->pno_sched_pending) {
- wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO");
- } else if (wpa_s->pno_sched_pending) {
- wpa_s->pno_sched_pending = 0;
- wpa_s->pno = 1;
- }
+ if (wpa_s->sched_scan_timed_out) {
+ wpa_supplicant_req_sched_scan(wpa_s);
+ } else if (wpa_s->pno_sched_pending) {
+ wpa_s->pno_sched_pending = 0;
+ wpas_start_pno(wpa_s);
}
break;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index f7eb537..1d8e8a6 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -665,6 +665,36 @@
* wildcard SSID.
*/
ssid = NULL;
+ } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) {
+ /*
+ * Perform single-channel single-SSID scan for
+ * reassociate-to-same-BSS operation.
+ */
+ /* Setup SSID */
+ ssid = wpa_s->current_ssid;
+ wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
+ ssid->ssid, ssid->ssid_len);
+ params.ssids[0].ssid = ssid->ssid;
+ params.ssids[0].ssid_len = ssid->ssid_len;
+ params.num_ssids = 1;
+
+ /*
+ * Allocate memory for frequency array, allocate one extra
+ * slot for the zero-terminator.
+ */
+ params.freqs = os_malloc(sizeof(int) * 2);
+ if (params.freqs == NULL) {
+ wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed");
+ return;
+ }
+ params.freqs[0] = wpa_s->assoc_freq;
+ params.freqs[1] = 0;
+
+ /*
+ * Reset the reattach flag so that we fall back to full scan if
+ * this scan fails.
+ */
+ wpa_s->reattach = 0;
} else {
struct wpa_ssid *start = ssid, *tssid;
int freqs_set = 0;
@@ -1813,3 +1843,110 @@
os_free(params->filter_ssids);
os_free(params);
}
+
+
+int wpas_start_pno(struct wpa_supplicant *wpa_s)
+{
+ int ret, interval;
+ size_t i, num_ssid;
+ struct wpa_ssid *ssid;
+ struct wpa_driver_scan_params params;
+
+ if (!wpa_s->sched_scan_supported)
+ return -1;
+
+ if (wpa_s->pno || wpa_s->pno_sched_pending)
+ return 0;
+
+ if ((wpa_s->wpa_state > WPA_SCANNING) &&
+ (wpa_s->wpa_state <= WPA_COMPLETED)) {
+ wpa_printf(MSG_ERROR, "PNO: In assoc process");
+ return -EAGAIN;
+ }
+
+ if (wpa_s->wpa_state == WPA_SCANNING) {
+ wpa_supplicant_cancel_scan(wpa_s);
+ if (wpa_s->sched_scanning) {
+ wpa_printf(MSG_DEBUG, "Schedule PNO on completion of "
+ "ongoing sched scan");
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_s->pno_sched_pending = 1;
+ return 0;
+ }
+ }
+
+ os_memset(¶ms, 0, sizeof(params));
+
+ num_ssid = 0;
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ if (!wpas_network_disabled(wpa_s, ssid))
+ num_ssid++;
+ ssid = ssid->next;
+ }
+ if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
+ wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
+ "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
+ num_ssid = WPAS_MAX_SCAN_SSIDS;
+ }
+
+ if (num_ssid == 0) {
+ wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
+ return -1;
+ }
+
+ params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
+ num_ssid);
+ if (params.filter_ssids == NULL)
+ return -1;
+ i = 0;
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ if (!wpas_network_disabled(wpa_s, ssid)) {
+ params.ssids[i].ssid = ssid->ssid;
+ params.ssids[i].ssid_len = ssid->ssid_len;
+ params.num_ssids++;
+ os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
+ ssid->ssid_len);
+ params.filter_ssids[i].ssid_len = ssid->ssid_len;
+ params.num_filter_ssids++;
+ i++;
+ if (i == num_ssid)
+ break;
+ }
+ ssid = ssid->next;
+ }
+
+ if (wpa_s->conf->filter_rssi)
+ params.filter_rssi = wpa_s->conf->filter_rssi;
+
+ interval = wpa_s->conf->sched_scan_interval ?
+ wpa_s->conf->sched_scan_interval : 10;
+
+ ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval);
+ os_free(params.filter_ssids);
+ if (ret == 0)
+ wpa_s->pno = 1;
+ else
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO");
+ return ret;
+}
+
+
+int wpas_stop_pno(struct wpa_supplicant *wpa_s)
+{
+ int ret = 0;
+
+ if (!wpa_s->pno)
+ return 0;
+
+ ret = wpa_supplicant_stop_sched_scan(wpa_s);
+
+ wpa_s->pno = 0;
+ wpa_s->pno_sched_pending = 0;
+
+ if (wpa_s->wpa_state == WPA_SCANNING)
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+ return ret;
+}
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index e4c8989..946d2b3 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -46,5 +46,7 @@
struct wpa_driver_scan_params *
wpa_scan_clone_params(const struct wpa_driver_scan_params *src);
void wpa_scan_free_params(struct wpa_driver_scan_params *params);
+int wpas_start_pno(struct wpa_supplicant *wpa_s);
+int wpas_stop_pno(struct wpa_supplicant *wpa_s);
#endif /* SCAN_H */
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 63ea1df..2a9ab7f 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -676,6 +676,12 @@
}
+static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "REATTACH");
+}
+
+
static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -2510,6 +2516,9 @@
{ "reassociate", wpa_cli_cmd_reassociate, NULL,
cli_cmd_flag_none,
"= force reassociation" },
+ { "reattach", wpa_cli_cmd_reattach, NULL,
+ cli_cmd_flag_none,
+ "= force reassociation back to the same BSS" },
{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<BSSID> = force preauthentication" },
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 561099c..6a04e5a 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2687,9 +2687,10 @@
interface_count = 0;
}
if (!wpa_s->p2p_mgmt &&
- wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
+ wpa_supplicant_delayed_sched_scan(wpa_s,
+ interface_count % 3,
100000))
- wpa_supplicant_req_scan(wpa_s, interface_count,
+ wpa_supplicant_req_scan(wpa_s, interface_count % 3,
100000);
interface_count++;
} else
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index fd162d7..739b11f 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -594,6 +594,7 @@
u8 pending_eapol_rx_src[ETH_ALEN];
unsigned int last_eapol_matches_bssid:1;
unsigned int eap_expected_failure:1;
+ unsigned int reattach:1; /* reassociation to the same BSS requested */
struct ibss_rsn *ibss_rsn;