aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hostapd/Android.mk21
-rw-r--r--hostapd/config_file.c2
-rw-r--r--hostapd/ctrl_iface.c8
-rw-r--r--hostapd/hostapd.conf7
-rw-r--r--src/ap/ap_config.h1
-rw-r--r--src/ap/gas_serv.c2
-rw-r--r--src/ap/hostapd.c135
-rw-r--r--src/ap/hostapd.h2
-rw-r--r--src/ap/ieee802_11_ht.c16
-rw-r--r--src/ap/sta_info.c12
-rw-r--r--src/ap/sta_info.h2
-rw-r--r--src/ap/wps_hostapd.c6
-rw-r--r--src/common/ieee802_11_defs.h11
-rw-r--r--src/common/wpa_ctrl.h1
-rw-r--r--src/drivers/driver_atheros.c9
-rw-r--r--src/drivers/driver_madwifi.c9
-rw-r--r--src/drivers/driver_nl80211.c11
-rw-r--r--src/p2p/p2p_build.c1
-rw-r--r--src/radius/radius_das.c3
-rw-r--r--src/utils/eloop.c31
-rw-r--r--src/utils/eloop.h16
-rw-r--r--src/utils/eloop_win.c31
-rw-r--r--src/wps/wps_attr_build.c6
-rw-r--r--src/wps/wps_registrar.c5
-rw-r--r--wpa_supplicant/Android.mk5
-rw-r--r--wpa_supplicant/config.c47
-rw-r--r--wpa_supplicant/config_file.c10
-rw-r--r--wpa_supplicant/config_ssid.h5
-rw-r--r--wpa_supplicant/events.c26
-rw-r--r--wpa_supplicant/interworking.c124
30 files changed, 470 insertions, 95 deletions
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 980a5513..bc0273e0 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -105,7 +105,6 @@ NEED_RC4=y
NEED_AES=y
NEED_MD5=y
NEED_SHA1=y
-NEED_SHA256=y
OBJS += src/drivers/drivers.c
L_CFLAGS += -DHOSTAPD
@@ -528,10 +527,6 @@ ifeq ($(CONFIG_TLS), gnutls)
ifdef TLS_FUNCS
OBJS += src/crypto/tls_gnutls.c
LIBS += -lgnutls -lgpg-error
-ifdef CONFIG_GNUTLS_EXTRA
-L_CFLAGS += -DCONFIG_GNUTLS_EXTRA
-LIBS += -lgnutls-extra
-endif
endif
OBJS += src/crypto/crypto_gnutls.c
HOBJS += src/crypto/crypto_gnutls.c
@@ -858,10 +853,20 @@ endif
OBJS += src/drivers/driver_common.c
+ifdef CONFIG_ACS
+L_CFLAGS += -DCONFIG_ACS
+OBJS += src/ap/acs.c
+LIBS += -lm
+endif
+
ifdef CONFIG_NO_STDOUT_DEBUG
L_CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
endif
+ifdef CONFIG_DEBUG_LINUX_TRACING
+L_CFLAGS += -DCONFIG_DEBUG_LINUX_TRACING
+endif
+
ifdef CONFIG_DEBUG_FILE
L_CFLAGS += -DCONFIG_DEBUG_FILE
endif
@@ -882,12 +887,6 @@ else
OBJS_c += src/utils/edit_simple.c
endif
-ifdef CONFIG_ACS
-L_CFLAGS += -DCONFIG_ACS
-OBJS += src/ap/acs.c
-LIBS += -lm
-endif
-
########################
include $(CLEAR_VARS)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index ef0d647e..ae059176 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2422,6 +2422,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
} else if (os_strcmp(buf, "require_ht") == 0) {
conf->require_ht = atoi(pos);
+ } else if (os_strcmp(buf, "obss_interval") == 0) {
+ conf->obss_interval = atoi(pos);
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
} else if (os_strcmp(buf, "ieee80211ac") == 0) {
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index cea96eb6..3f181fa8 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -82,15 +82,15 @@ static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
os_memcmp(from->sun_path, dst->addr.sun_path,
fromlen - offsetof(struct sockaddr_un, sun_path))
== 0) {
+ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
+ (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
if (prev == NULL)
hapd->ctrl_dst = dst->next;
else
prev->next = dst->next;
os_free(dst);
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
- (u8 *) from->sun_path,
- fromlen -
- offsetof(struct sockaddr_un, sun_path));
return 0;
}
prev = dst;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index eeb00551..9b70d0fb 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -468,6 +468,13 @@ wmm_ac_vo_acm=0
# Require stations to support HT PHY (reject association if they do not)
#require_ht=1
+# If set non-zero, require stations to perform scans of overlapping
+# channels to test for stations which would be affected by 40 MHz traffic.
+# This parameter sets the interval in seconds between these scans. This
+# is useful only for testing that stations properly set the OBSS interval,
+# since the other parameters in the OBSS scan parameters IE are set to 0.
+#obss_interval=0
+
##### IEEE 802.11ac related configuration #####################################
# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 8b737248..09b2778e 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -530,6 +530,7 @@ struct hostapd_config {
int ieee80211n;
int secondary_channel;
int require_ht;
+ int obss_interval;
u32 vht_capab;
int ieee80211ac;
int require_vht;
diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
index b3574ba6..8349c4dd 100644
--- a/src/ap/gas_serv.c
+++ b/src/ap/gas_serv.c
@@ -46,6 +46,8 @@ gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token)
* it to be that long.
*/
ap_sta_session_timeout(hapd, sta, 5);
+ } else {
+ ap_sta_replenish_timeout(hapd, sta, 5);
}
if (sta->gas_dialog == NULL) {
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 52be3110..60224ccb 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -243,6 +243,7 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
static void hostapd_free_hapd_data(struct hostapd_data *hapd)
{
+ wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
iapp_deinit(hapd->iapp);
hapd->iapp = NULL;
accounting_deinit(hapd);
@@ -260,7 +261,8 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
authsrv_deinit(hapd);
- if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
+ if (hapd->interface_added &&
+ hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
hapd->conf->iface);
}
@@ -293,34 +295,24 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
* @hapd: Pointer to BSS data
*
* This function is used to free all per-BSS data structures and resources.
- * This gets called in a loop for each BSS between calls to
- * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface
- * is deinitialized. Most of the modules that are initialized in
- * hostapd_setup_bss() are deinitialized here.
+ * Most of the modules that are initialized in hostapd_setup_bss() are
+ * deinitialized here.
*/
static void hostapd_cleanup(struct hostapd_data *hapd)
{
+ wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s))", __func__, hapd,
+ hapd->conf->iface);
if (hapd->iface->interfaces &&
hapd->iface->interfaces->ctrl_iface_deinit)
hapd->iface->interfaces->ctrl_iface_deinit(hapd);
hostapd_free_hapd_data(hapd);
-}
-
-
-/**
- * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup
- * @iface: Pointer to interface data
- *
- * This function is called before per-BSS data structures are deinitialized
- * with hostapd_cleanup().
- */
-static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface)
-{
+ hapd->started = 0;
}
static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
{
+ wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
iface->hw_features = NULL;
os_free(iface->current_rates);
@@ -340,6 +332,7 @@ static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
*/
static void hostapd_cleanup_iface(struct hostapd_iface *iface)
{
+ wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
hostapd_cleanup_iface_partial(iface);
@@ -348,6 +341,7 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface)
os_free(iface->config_fname);
os_free(iface->bss);
+ wpa_printf(MSG_DEBUG, "%s: free iface=%p", __func__, iface);
os_free(iface);
}
@@ -629,6 +623,16 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
char force_ifname[IFNAMSIZ];
u8 if_addr[ETH_ALEN];
+ wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)",
+ __func__, hapd, hapd->conf->iface, first);
+
+ if (hapd->started) {
+ wpa_printf(MSG_ERROR, "%s: Interface %s was already started",
+ __func__, hapd->conf->iface);
+ return -1;
+ }
+ hapd->started = 1;
+
if (!first || first == -1) {
if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
/* Allocate the next available BSSID. */
@@ -649,6 +653,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
}
}
+ hapd->interface_added = 1;
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
hapd->conf->iface, hapd->own_addr, hapd,
&hapd->drv_priv, force_ifname, if_addr,
@@ -1259,32 +1264,42 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
}
+static void hostapd_bss_deinit(struct hostapd_data *hapd)
+{
+ wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__,
+ hapd->conf->iface);
+ hostapd_free_stas(hapd);
+ hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
+ hostapd_clear_wep(hapd);
+ hostapd_cleanup(hapd);
+}
+
+
void hostapd_interface_deinit(struct hostapd_iface *iface)
{
int j;
+ wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
if (iface == NULL)
return;
eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
iface->wait_channel_update = 0;
- hostapd_cleanup_iface_pre(iface);
- for (j = iface->num_bss - 1; j >= 0; j--) {
- struct hostapd_data *hapd = iface->bss[j];
- hostapd_free_stas(hapd);
- hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
- hostapd_clear_wep(hapd);
- hostapd_cleanup(hapd);
- }
+ for (j = iface->num_bss - 1; j >= 0; j--)
+ hostapd_bss_deinit(iface->bss[j]);
}
void hostapd_interface_free(struct hostapd_iface *iface)
{
size_t j;
- for (j = 0; j < iface->num_bss; j++)
+ wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+ for (j = 0; j < iface->num_bss; j++) {
+ wpa_printf(MSG_DEBUG, "%s: free hapd %p",
+ __func__, iface->bss[j]);
os_free(iface->bss[j]);
+ }
hostapd_cleanup_iface(iface);
}
@@ -1344,6 +1359,8 @@ fail:
if (hapd_iface) {
os_free(hapd_iface->config_fname);
os_free(hapd_iface->bss);
+ wpa_printf(MSG_DEBUG, "%s: free iface %p",
+ __func__, hapd_iface);
os_free(hapd_iface);
}
return NULL;
@@ -1488,11 +1505,18 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface)
{
const struct wpa_driver_ops *driver;
void *drv_priv;
+
+ wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
if (iface == NULL)
return;
+ wpa_printf(MSG_DEBUG, "%s: num_bss=%u conf->num_bss=%u",
+ __func__, (unsigned int) iface->num_bss,
+ (unsigned int) iface->conf->num_bss);
driver = iface->bss[0]->driver;
drv_priv = iface->bss[0]->drv_priv;
hostapd_interface_deinit(iface);
+ wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
+ __func__, driver, drv_priv);
if (driver && driver->hapd_deinit && drv_priv)
driver->hapd_deinit(drv_priv);
hostapd_interface_free(iface);
@@ -1521,6 +1545,8 @@ int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
driver = hapd_iface->bss[0]->driver;
drv_priv = hapd_iface->bss[0]->drv_priv;
+ wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
+ __func__, driver, drv_priv);
if (driver && driver->hapd_deinit && drv_priv) {
driver->hapd_deinit(drv_priv);
hapd_iface->bss[0]->drv_priv = NULL;
@@ -1573,6 +1599,8 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
hostapd_free_hapd_data(hapd);
}
+ wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
+ __func__, driver, drv_priv);
if (driver && driver->hapd_deinit && drv_priv) {
driver->hapd_deinit(drv_priv);
hapd_iface->bss[0]->drv_priv = NULL;
@@ -1740,9 +1768,12 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
ETH_ALEN);
if (start_ctrl_iface_bss(hapd) < 0 ||
- hostapd_setup_bss(hapd, -1)) {
+ (hapd_iface->state == HAPD_IFACE_ENABLED &&
+ hostapd_setup_bss(hapd, -1))) {
hapd_iface->conf->num_bss--;
hapd_iface->num_bss--;
+ wpa_printf(MSG_DEBUG, "%s: free hapd %p %s",
+ __func__, hapd, hapd->conf->iface);
os_free(hapd);
return -1;
}
@@ -1806,10 +1837,21 @@ fail:
hostapd_config_free(conf);
if (hapd_iface) {
if (hapd_iface->bss) {
- for (i = 0; i < hapd_iface->num_bss; i++)
+ for (i = 0; i < hapd_iface->num_bss; i++) {
+ hapd = hapd_iface->bss[i];
+ if (hapd && hapd_iface->interfaces &&
+ hapd_iface->interfaces->ctrl_iface_deinit)
+ hapd_iface->interfaces->
+ ctrl_iface_deinit(hapd);
+ wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
+ __func__, hapd_iface->bss[i],
+ hapd_iface->bss[i]->conf->iface);
os_free(hapd_iface->bss[i]);
+ }
os_free(hapd_iface->bss);
}
+ wpa_printf(MSG_DEBUG, "%s: free iface %p",
+ __func__, hapd_iface);
os_free(hapd_iface);
}
return -1;
@@ -1818,27 +1860,31 @@ fail:
static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx)
{
- struct hostapd_data *hapd;
size_t i;
- if (idx > iface->num_bss || idx > iface->conf->num_bss)
- return -1;
- hapd = iface->bss[idx];
- wpa_printf(MSG_INFO, "Remove BSS '%s'", hapd->conf->iface);
+ wpa_printf(MSG_INFO, "Remove BSS '%s'", iface->conf->bss[idx]->iface);
- hostapd_free_stas(hapd);
- hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
- hostapd_clear_wep(hapd);
- hostapd_cleanup(hapd);
- hostapd_config_free_bss(hapd->conf);
- os_free(hapd);
+ /* Remove hostapd_data only if it has already been initialized */
+ if (idx < iface->num_bss) {
+ struct hostapd_data *hapd = iface->bss[idx];
- iface->num_bss--;
- for (i = idx; i < iface->num_bss; i++)
- iface->bss[i] = iface->bss[i + 1];
+ hostapd_bss_deinit(hapd);
+ wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
+ __func__, hapd, hapd->conf->iface);
+ hostapd_config_free_bss(hapd->conf);
+ os_free(hapd);
+
+ iface->num_bss--;
+
+ for (i = idx; i < iface->num_bss; i++)
+ iface->bss[i] = iface->bss[i + 1];
+ } else {
+ hostapd_config_free_bss(iface->conf->bss[idx]);
+ iface->conf->bss[idx] = NULL;
+ }
iface->conf->num_bss--;
- for (i = idx; i < iface->num_bss; i++)
+ for (i = idx; i < iface->conf->num_bss; i++)
iface->conf->bss[i] = iface->conf->bss[i + 1];
return 0;
@@ -1854,8 +1900,7 @@ int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
hapd_iface = interfaces->iface[i];
if (hapd_iface == NULL)
return -1;
- if (hapd_iface->conf->num_bss == 1 &&
- !os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
+ if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
hostapd_interface_deinit_free(hapd_iface);
k = i;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index adb3728d..1887531f 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -101,6 +101,8 @@ struct hostapd_data {
struct hostapd_iface *iface;
struct hostapd_config *iconf;
struct hostapd_bss_config *conf;
+ int interface_added; /* virtual interface added for this BSS */
+ unsigned int started:1;
u8 own_addr[ETH_ALEN];
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 6483e1c3..2d53648c 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -50,6 +50,22 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid)
pos += sizeof(*cap);
+ if (hapd->iconf->obss_interval) {
+ struct ieee80211_obss_scan_parameters *scan_params;
+
+ *pos++ = WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS;
+ *pos++ = sizeof(*scan_params);
+
+ scan_params = (struct ieee80211_obss_scan_parameters *) pos;
+ os_memset(scan_params, 0, sizeof(*scan_params));
+ scan_params->width_trigger_scan_interval =
+ host_to_le16(hapd->iconf->obss_interval);
+
+ /* TODO: Fill in more parameters (supplicant ignores them) */
+
+ pos += sizeof(*scan_params);
+ }
+
return pos;
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 016b9b6a..a6775f3f 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -490,6 +490,18 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx)
}
+void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta,
+ u32 session_timeout)
+{
+ if (eloop_replenish_timeout(session_timeout, 0,
+ ap_handle_session_timer, hapd, sta)) {
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG, "setting session timeout "
+ "to %d seconds", session_timeout);
+ }
+}
+
+
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
u32 session_timeout)
{
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 197e46bc..dc742195 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -162,6 +162,8 @@ void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
void hostapd_free_stas(struct hostapd_data *hapd);
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
+void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta,
+ u32 session_timeout);
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
u32 session_timeout);
void ap_sta_no_session_timeout(struct hostapd_data *hapd,
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index eb300f19..294a39d6 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1211,6 +1211,7 @@ int hostapd_init_wps_complete(struct hostapd_data *hapd)
static void hostapd_wps_nfc_clear(struct wps_context *wps)
{
#ifdef CONFIG_WPS_NFC
+ wpa_printf(MSG_DEBUG, "WPS: Clear NFC Tag context %p", wps);
wps->ap_nfc_dev_pw_id = 0;
wpabuf_free(wps->ap_nfc_dh_pubkey);
wps->ap_nfc_dh_pubkey = NULL;
@@ -1823,6 +1824,9 @@ int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd)
return -1;
hostapd_wps_nfc_clear(wps);
+ wpa_printf(MSG_DEBUG,
+ "WPS: Enable NFC Tag (Dev Pw Id %u) for AP interface %s (context %p)",
+ hapd->conf->wps_nfc_dev_pw_id, hapd->conf->iface, wps);
wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id;
wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
@@ -1849,6 +1853,8 @@ int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd)
void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd)
{
+ wpa_printf(MSG_DEBUG, "WPS: Disable NFC token for AP interface %s",
+ hapd->conf->iface);
hostapd_wps_nfc_clear(hapd->wps);
}
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 8ce1bfb2..ca122d93 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -587,6 +587,17 @@ struct ieee80211_ht_operation {
} STRUCT_PACKED;
+struct ieee80211_obss_scan_parameters {
+ le16 scan_passive_dwell;
+ le16 scan_active_dwell;
+ le16 width_trigger_scan_interval;
+ le16 scan_passive_total_per_channel;
+ le16 scan_active_total_per_channel;
+ le16 channel_transition_delay_factor;
+ le16 scan_activity_threshold;
+} STRUCT_PACKED;
+
+
struct ieee80211_vht_capabilities {
le32 vht_capabilities_info;
struct {
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 862f881b..2a4f3016 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -149,6 +149,7 @@ extern "C" {
#define INTERWORKING_AP "INTERWORKING-AP "
#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
+#define INTERWORKING_ALREADY_CONNECTED "INTERWORKING-ALREADY-CONNECTED "
#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO "
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index 2547a43d..7d301f79 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -354,19 +354,16 @@ atheros_set_ieee8021x(void *priv, struct wpa_bss_params *params)
return atheros_set_privacy(drv, 0);
}
if (!params->wpa && !params->ieee802_1x) {
- hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
- HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
+ wpa_printf(MSG_WARNING, "No 802.1X or WPA enabled!");
return -1;
}
if (params->wpa && atheros_configure_wpa(drv, params) != 0) {
- hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
- HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
+ wpa_printf(MSG_WARNING, "Error configuring WPA state!");
return -1;
}
if (set80211param(priv, IEEE80211_PARAM_AUTHMODE,
(params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
- hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
- HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
+ wpa_printf(MSG_WARNING, "Error enabling WPA/802.1X!");
return -1;
}
diff --git a/src/drivers/driver_madwifi.c b/src/drivers/driver_madwifi.c
index d3379270..09308347 100644
--- a/src/drivers/driver_madwifi.c
+++ b/src/drivers/driver_madwifi.c
@@ -322,19 +322,16 @@ madwifi_set_ieee8021x(void *priv, struct wpa_bss_params *params)
IEEE80211_AUTH_AUTO);
}
if (!params->wpa && !params->ieee802_1x) {
- hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
- HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!");
+ wpa_printf(MSG_WARNING, "No 802.1X or WPA enabled!");
return -1;
}
if (params->wpa && madwifi_configure_wpa(drv, params) != 0) {
- hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
- HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!");
+ wpa_printf(MSG_WARNING, "Error configuring WPA state!");
return -1;
}
if (set80211param(priv, IEEE80211_PARAM_AUTHMODE,
(params->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) {
- hostapd_logger(drv->hapd, NULL, HOSTAPD_MODULE_DRIVER,
- HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!");
+ wpa_printf(MSG_WARNING, "Error enabling WPA/802.1X!");
return -1;
}
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c4273246..a1d81714 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -109,6 +109,17 @@ static void nl80211_handle_destroy(struct nl_handle *handle)
#endif /* CONFIG_LIBNL20 */
+#ifdef ANDROID
+/* system/core/libnl_2 does not include nl_socket_set_nonblocking() */
+static int android_nl_socket_set_nonblocking(struct nl_handle *handle)
+{
+ return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
+}
+#undef nl_socket_set_nonblocking
+#define nl_socket_set_nonblocking(h) android_nl_socket_set_nonblocking(h)
+#endif /* ANDROID */
+
+
static struct nl_handle * nl_create_handle(struct nl_cb *cb, const char *dbg)
{
struct nl_handle *handle;
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index 3c819ff4..42c02326 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -258,6 +258,7 @@ void p2p_buf_add_group_id(struct wpabuf *buf, const u8 *dev_addr,
wpabuf_put_data(buf, ssid, ssid_len);
wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR,
MAC2STR(dev_addr));
+ wpa_hexdump_ascii(MSG_DEBUG, "P2P: P2P Group ID SSID", ssid, ssid_len);
}
diff --git a/src/radius/radius_das.c b/src/radius/radius_das.c
index 8e5988dd..418b1605 100644
--- a/src/radius/radius_das.c
+++ b/src/radius/radius_das.c
@@ -200,7 +200,8 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
(u8 *) &val, 4);
if (res == 4) {
u32 timestamp = ntohl(val);
- if (abs(now.sec - timestamp) > das->time_window) {
+ if ((unsigned int) abs(now.sec - timestamp) >
+ das->time_window) {
wpa_printf(MSG_DEBUG, "DAS: Unacceptable "
"Event-Timestamp (%u; local time %u) in "
"packet from %s:%d - drop",
diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index 12aa1251..ddddcf17 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -599,6 +599,37 @@ int eloop_is_timeout_registered(eloop_timeout_handler handler,
}
+int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
+ eloop_timeout_handler handler, void *eloop_data,
+ void *user_data)
+{
+ struct os_time now, requested, remaining;
+ struct eloop_timeout *tmp;
+
+ dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
+ if (tmp->handler == handler &&
+ tmp->eloop_data == eloop_data &&
+ tmp->user_data == user_data) {
+ requested.sec = req_secs;
+ requested.usec = req_usecs;
+ os_get_time(&now);
+ os_time_sub(&tmp->time, &now, &remaining);
+ if (os_time_before(&remaining, &requested)) {
+ eloop_cancel_timeout(handler, eloop_data,
+ user_data);
+ eloop_register_timeout(requested.sec,
+ requested.usec,
+ handler, eloop_data,
+ user_data);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
#ifndef CONFIG_NATIVE_WINDOWS
static void eloop_handle_alarm(int sig)
{
diff --git a/src/utils/eloop.h b/src/utils/eloop.h
index 0037c635..befb0703 100644
--- a/src/utils/eloop.h
+++ b/src/utils/eloop.h
@@ -223,6 +223,22 @@ int eloop_is_timeout_registered(eloop_timeout_handler handler,
void *eloop_data, void *user_data);
/**
+ * eloop_replenish_timeout - Replenish a timeout that is already registered
+ * @req_secs: Requested number of seconds to the timeout
+ * @req_usecs: Requested number of microseconds to the timeout
+ * @handler: Matching callback function
+ * @eloop_data: Matching eloop_data
+ * @user_data: Matching user_data
+ * Returns: 1 if the timeout is replenished, 0 if no change is made
+ *
+ * Find a registered matching <handler,eloop_data,user_data> timeout. If found,
+ * replenish the timeout if remaining time is less than the requested time.
+ */
+int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
+ eloop_timeout_handler handler, void *eloop_data,
+ void *user_data);
+
+/**
* eloop_register_signal - Register handler for signals
* @sig: Signal number (e.g., SIGHUP)
* @handler: Callback function to be called when the signal is received
diff --git a/src/utils/eloop_win.c b/src/utils/eloop_win.c
index eda412f1..1f40530c 100644
--- a/src/utils/eloop_win.c
+++ b/src/utils/eloop_win.c
@@ -354,6 +354,37 @@ int eloop_is_timeout_registered(eloop_timeout_handler handler,
}
+int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs,
+ eloop_timeout_handler handler, void *eloop_data,
+ void *user_data)
+{
+ struct os_time now, requested, remaining;
+ struct eloop_timeout *tmp;
+
+ dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) {
+ if (tmp->handler == handler &&
+ tmp->eloop_data == eloop_data &&
+ tmp->user_data == user_data) {
+ requested.sec = req_secs;
+ requested.usec = req_usecs;
+ os_get_time(&now);
+ os_time_sub(&tmp->time, &now, &remaining);
+ if (os_time_before(&remaining, &requested)) {
+ eloop_cancel_timeout(handler, eloop_data,
+ user_data);
+ eloop_register_timeout(requested.sec,
+ requested.usec,
+ handler, eloop_data,
+ user_data);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
/* TODO: replace with suitable signal handler */
#if 0
static void eloop_handle_signal(int sig)
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index 3be89453..b2327544 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -382,14 +382,20 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
const u8 *addr[1];
u8 pubkey_hash[WPS_HASH_LEN];
+ wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password (dev_pw_id=%u)",
+ dev_pw_id);
addr[0] = wpabuf_head(pubkey);
hash_len = wpabuf_len(pubkey);
sha256_vector(1, addr, &hash_len, pubkey_hash);
wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD);
wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len);
+ wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash",
+ pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
wpabuf_put_be16(msg, dev_pw_id);
+ wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password",
+ dev_pw, dev_pw_len);
wpabuf_put_data(msg, dev_pw, dev_pw_len);
return 0;
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index b7fcd9ce..7cb583cf 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -1379,7 +1379,8 @@ static int wps_get_dev_password(struct wps_data *wps)
}
if (pin == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Device Password available for "
- "the Enrollee");
+ "the Enrollee (context %p registrar %p)",
+ wps->wps, wps->wps->registrar);
wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e,
&wps->peer_dev);
return -1;
@@ -2541,6 +2542,8 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
const u8 *addr[1];
u8 hash[WPS_HASH_LEN];
+ wpa_printf(MSG_DEBUG, "WPS: Searching for NFC token match for id=%d (ctx %p registrar %p)",
+ wps->dev_pw_id, wps->wps, wps->wps->registrar);
token = wps_get_nfc_pw_token(
&wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id);
if (token) {
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index f480277e..373a344b 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -1175,7 +1175,10 @@ SHA1OBJS += src/crypto/sha1-tlsprf.c
endif
endif
-MD5OBJS = src/crypto/md5.c
+MD5OBJS =
+ifndef CONFIG_FIPS
+MD5OBJS += src/crypto/md5.c
+endif
ifdef NEED_MD5
ifdef CONFIG_INTERNAL_MD5
MD5OBJS += src/crypto/md5-internal.c
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 19bceceb..18082736 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1321,6 +1321,52 @@ static char * wpa_config_write_wep_key3(const struct parse_data *data,
#ifdef CONFIG_P2P
+static int wpa_config_parse_go_p2p_dev_addr(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 ||
+ os_strcmp(value, "any") == 0) {
+ os_memset(ssid->go_p2p_dev_addr, 0, ETH_ALEN);
+ wpa_printf(MSG_MSGDUMP, "GO P2P Device Address any");
+ return 0;
+ }
+ if (hwaddr_aton(value, ssid->go_p2p_dev_addr)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid GO P2P Device Address '%s'.",
+ line, value);
+ return -1;
+ }
+ ssid->bssid_set = 1;
+ wpa_printf(MSG_MSGDUMP, "GO P2P Device Address " MACSTR,
+ MAC2STR(ssid->go_p2p_dev_addr));
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_go_p2p_dev_addr(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *value;
+ int res;
+
+ if (is_zero_ether_addr(ssid->go_p2p_dev_addr))
+ return NULL;
+
+ value = os_malloc(20);
+ if (value == NULL)
+ return NULL;
+ res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->go_p2p_dev_addr));
+ if (res < 0 || res >= 20) {
+ os_free(value);
+ return NULL;
+ }
+ value[20 - 1] = '\0';
+ return value;
+}
+#endif /* NO_CONFIG_WRITE */
+
+
static int wpa_config_parse_p2p_client_list(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
@@ -1632,6 +1678,7 @@ static const struct parse_data ssid_fields[] = {
{ STR(bgscan) },
{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
#ifdef CONFIG_P2P
+ { FUNC(go_p2p_dev_addr) },
{ FUNC(p2p_client_list) },
{ FUNC(psk_list) },
#endif /* CONFIG_P2P */
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index cb2dde8e..ed5cdfff 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -606,6 +606,15 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid)
#ifdef CONFIG_P2P
+static void write_go_p2p_dev_addr(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value = wpa_config_get(ssid, "go_p2p_dev_addr");
+ if (value == NULL)
+ return;
+ fprintf(f, "\tgo_p2p_dev_addr=%s\n", value);
+ os_free(value);
+}
+
static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid)
{
char *value = wpa_config_get(ssid, "p2p_client_list");
@@ -714,6 +723,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
#endif /* CONFIG_IEEE80211W */
STR(id_str);
#ifdef CONFIG_P2P
+ write_go_p2p_dev_addr(f, ssid);
write_p2p_client_list(f, ssid);
write_psk_list(f, ssid);
#endif /* CONFIG_P2P */
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 3d008ca5..9c2cf66e 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -131,6 +131,11 @@ struct wpa_ssid {
int bssid_set;
/**
+ * go_p2p_dev_addr - GO's P2P Device Address or all zeros if not set
+ */
+ u8 go_p2p_dev_addr[ETH_ALEN];
+
+ /**
* psk - WPA pre-shared key (256 bits)
*/
u8 psk[32];
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index bffcd1a1..daabecba 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -869,6 +869,32 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
continue;
}
+ if (!is_zero_ether_addr(ssid->go_p2p_dev_addr)) {
+ struct wpabuf *p2p_ie;
+ u8 dev_addr[ETH_ALEN];
+
+ ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
+ if (ie == NULL) {
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P element");
+ continue;
+ }
+ p2p_ie = wpa_bss_get_vendor_ie_multi(
+ bss, P2P_IE_VENDOR_TYPE);
+ if (p2p_ie == NULL) {
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - could not fetch P2P element");
+ continue;
+ }
+
+ if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0
+ || os_memcmp(dev_addr, ssid->go_p2p_dev_addr,
+ ETH_ALEN) != 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - no matching GO P2P Device Address in P2P element");
+ wpabuf_free(p2p_ie);
+ continue;
+ }
+ wpabuf_free(p2p_ie);
+ }
+
/*
* TODO: skip the AP if its P2P IE has Group Formation
* bit set in the P2P Group Capability Bitmap and we
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 86672219..93652d8f 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -1,6 +1,6 @@
/*
* Interworking (IEEE 802.11u)
- * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -19,6 +19,7 @@
#include "eap_peer/eap.h"
#include "eap_peer/eap_methods.h"
#include "eapol_supp/eapol_supp_sm.h"
+#include "rsn_supp/wpa.h"
#include "wpa_supplicant_i.h"
#include "config.h"
#include "config_ssid.h"
@@ -750,6 +751,59 @@ static int set_root_nai(struct wpa_ssid *ssid, const char *imsi, char prefix)
#endif /* INTERWORKING_3GPP */
+static int already_connected(struct wpa_supplicant *wpa_s,
+ struct wpa_cred *cred, struct wpa_bss *bss)
+{
+ struct wpa_ssid *ssid;
+
+ if (wpa_s->wpa_state < WPA_ASSOCIATED || wpa_s->current_ssid == NULL)
+ return 0;
+
+ ssid = wpa_s->current_ssid;
+ if (ssid->parent_cred != cred)
+ return 0;
+
+ if (ssid->ssid_len != bss->ssid_len ||
+ os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0)
+ return 0;
+
+ return 1;
+}
+
+
+static void remove_duplicate_network(struct wpa_supplicant *wpa_s,
+ struct wpa_cred *cred,
+ struct wpa_bss *bss)
+{
+ struct wpa_ssid *ssid;
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (ssid->parent_cred != cred)
+ continue;
+ if (ssid->ssid_len != bss->ssid_len ||
+ os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) != 0)
+ continue;
+
+ break;
+ }
+
+ if (ssid == NULL)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Interworking: Remove duplicate network entry for the same credential");
+
+ if (ssid == wpa_s->current_ssid) {
+ wpa_sm_set_config(wpa_s->wpa, NULL);
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ }
+
+ wpas_notify_network_removed(wpa_s, ssid);
+ wpa_config_remove_network(wpa_s->conf, ssid->id);
+}
+
+
static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
@@ -771,7 +825,6 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
{
#ifdef INTERWORKING_3GPP
struct wpa_ssid *ssid;
- const u8 *ie;
int eap_type;
int res;
char prefix;
@@ -779,12 +832,17 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
return -1;
- ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
- if (ie == NULL)
- return -1;
wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " (3GPP)",
MAC2STR(bss->bssid));
+ if (already_connected(wpa_s, cred, bss)) {
+ wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
+ MAC2STR(bss->bssid));
+ return 0;
+ }
+
+ remove_duplicate_network(wpa_s, cred, bss);
+
ssid = wpa_config_add_network(wpa_s->conf);
if (ssid == NULL)
return -1;
@@ -794,11 +852,11 @@ static int interworking_connect_3gpp(struct wpa_supplicant *wpa_s,
wpa_config_set_network_defaults(ssid);
ssid->priority = cred->priority;
ssid->temporary = 1;
- ssid->ssid = os_zalloc(ie[1] + 1);
+ ssid->ssid = os_zalloc(bss->ssid_len + 1);
if (ssid->ssid == NULL)
goto fail;
- os_memcpy(ssid->ssid, ie + 2, ie[1]);
- ssid->ssid_len = ie[1];
+ os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
+ ssid->ssid_len = bss->ssid_len;
if (interworking_set_hs20_params(wpa_s, ssid) < 0)
goto fail;
@@ -1137,13 +1195,21 @@ static int interworking_set_eap_params(struct wpa_ssid *ssid,
static int interworking_connect_roaming_consortium(
struct wpa_supplicant *wpa_s, struct wpa_cred *cred,
- struct wpa_bss *bss, const u8 *ssid_ie)
+ struct wpa_bss *bss)
{
struct wpa_ssid *ssid;
wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR " based on "
"roaming consortium match", MAC2STR(bss->bssid));
+ if (already_connected(wpa_s, cred, bss)) {
+ wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
+ MAC2STR(bss->bssid));
+ return 0;
+ }
+
+ remove_duplicate_network(wpa_s, cred, bss);
+
ssid = wpa_config_add_network(wpa_s->conf);
if (ssid == NULL)
return -1;
@@ -1152,11 +1218,11 @@ static int interworking_connect_roaming_consortium(
wpa_config_set_network_defaults(ssid);
ssid->priority = cred->priority;
ssid->temporary = 1;
- ssid->ssid = os_zalloc(ssid_ie[1] + 1);
+ ssid->ssid = os_zalloc(bss->ssid_len + 1);
if (ssid->ssid == NULL)
goto fail;
- os_memcpy(ssid->ssid, ssid_ie + 2, ssid_ie[1]);
- ssid->ssid_len = ssid_ie[1];
+ os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
+ ssid->ssid_len = bss->ssid_len;
if (interworking_set_hs20_params(wpa_s, ssid) < 0)
goto fail;
@@ -1193,13 +1259,12 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
struct nai_realm_eap *eap = NULL;
u16 count, i;
char buf[100];
- const u8 *ie;
if (wpa_s->conf->cred == NULL || bss == NULL)
return -1;
- ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
- if (ie == NULL || ie[1] == 0) {
- wpa_printf(MSG_DEBUG, "Interworking: No SSID known for "
+ if (disallowed_bssid(wpa_s, bss->bssid) ||
+ disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
+ wpa_printf(MSG_DEBUG, "Interworking: Reject connection to disallowed BSS "
MACSTR, MAC2STR(bss->bssid));
return -1;
}
@@ -1239,7 +1304,7 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
(cred == NULL || cred_rc->priority >= cred->priority) &&
(cred_3gpp == NULL || cred_rc->priority >= cred_3gpp->priority))
return interworking_connect_roaming_consortium(wpa_s, cred_rc,
- bss, ie);
+ bss);
if (cred_3gpp &&
(cred == NULL || cred_3gpp->priority >= cred->priority)) {
@@ -1279,6 +1344,15 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
wpa_printf(MSG_DEBUG, "Interworking: Connect with " MACSTR,
MAC2STR(bss->bssid));
+ if (already_connected(wpa_s, cred, bss)) {
+ wpa_msg(wpa_s, MSG_INFO, INTERWORKING_ALREADY_CONNECTED MACSTR,
+ MAC2STR(bss->bssid));
+ nai_realm_free(realm, count);
+ return 0;
+ }
+
+ remove_duplicate_network(wpa_s, cred, bss);
+
ssid = wpa_config_add_network(wpa_s->conf);
if (ssid == NULL) {
nai_realm_free(realm, count);
@@ -1289,11 +1363,11 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
wpa_config_set_network_defaults(ssid);
ssid->priority = cred->priority;
ssid->temporary = 1;
- ssid->ssid = os_zalloc(ie[1] + 1);
+ ssid->ssid = os_zalloc(bss->ssid_len + 1);
if (ssid->ssid == NULL)
goto fail;
- os_memcpy(ssid->ssid, ie + 2, ie[1]);
- ssid->ssid_len = ie[1];
+ os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
+ ssid->ssid_len = bss->ssid_len;
if (interworking_set_hs20_params(wpa_s, ssid) < 0)
goto fail;
@@ -1518,6 +1592,13 @@ static struct wpa_cred * interworking_credentials_available(
{
struct wpa_cred *cred, *cred2;
+ if (disallowed_bssid(wpa_s, bss->bssid) ||
+ disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
+ wpa_printf(MSG_DEBUG, "Interworking: Ignore disallowed BSS "
+ MACSTR, MAC2STR(bss->bssid));
+ return NULL;
+ }
+
cred = interworking_credentials_available_realm(wpa_s, bss);
cred2 = interworking_credentials_available_3gpp(wpa_s, bss);
if (cred && cred2 && cred2->priority >= cred->priority)
@@ -1804,6 +1885,9 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s)
ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80))
continue; /* AP does not support Interworking */
+ if (disallowed_bssid(wpa_s, bss->bssid) ||
+ disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len))
+ continue; /* Disallowed BSS */
if (!(bss->flags & WPA_BSS_ANQP_FETCH_TRIED)) {
if (bss->anqp == NULL) {