Cumulative patch from commit 2b6623ab134fff6d96114f5fe329a2f87d5e893a
2b6623a hostapd: Do not terminate process on dynamic interface add failure
217cf49 P2P: Add more debug prints for frequency selection
4dd3f86 P2P: Fix bug in GO frequency selection
9804873 wpa_supplicant: Fix bug in get_shared_radio_freqs
3342c26 wpa_supplicant: Fix updating GO beacons on WFD subelements change
72c12c1 EAPOL: Fix static analyzer warnings for pac_opaque_encr_key
3139270 bgscan: Add global bgscan configuration
efc58df eap_proxy: Re-read IMSI from proxy in Interworking functionality
Change-Id: I006abd3b52fbbd1a7b97059364c72ab0386d5f63
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/README b/README
index 805c6cf..bf0bd83 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
wpa_supplicant and hostapd
--------------------------
-Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
These programs are licensed under the BSD license (the one with
diff --git a/hostapd/main.c b/hostapd/main.c
index bc61db1..4e9fe40 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -693,6 +693,7 @@
* In such case, the interface will be enabled from eloop context within
* hostapd_global_run().
*/
+ interfaces.terminate_on_error = interfaces.count;
for (i = 0; i < interfaces.count; i++) {
if (hostapd_driver_init(interfaces.iface[i]) ||
hostapd_setup_interface(interfaces.iface[i]))
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 5d51c77..52be311 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1082,7 +1082,8 @@
if (err) {
wpa_printf(MSG_ERROR, "Interface initialization failed");
hostapd_set_state(iface, HAPD_IFACE_DISABLED);
- eloop_terminate();
+ if (iface->interfaces && iface->interfaces->terminate_on_error)
+ eloop_terminate();
return -1;
}
@@ -1187,6 +1188,8 @@
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
iface->bss[0]->conf->iface);
+ if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
+ iface->interfaces->terminate_on_error--;
return 0;
}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 05bcb62..adb3728 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -45,6 +45,8 @@
gid_t ctrl_iface_group;
struct hostapd_iface **iface;
struct hostapd_dynamic_iface **dynamic_iface;
+
+ size_t terminate_on_error;
};
enum hostapd_chan_status {
diff --git a/src/eapol_auth/eapol_auth_sm.c b/src/eapol_auth/eapol_auth_sm.c
index 013d781..a257781 100644
--- a/src/eapol_auth/eapol_auth_sm.c
+++ b/src/eapol_auth/eapol_auth_sm.c
@@ -1062,6 +1062,10 @@
}
if (src->pac_opaque_encr_key) {
dst->pac_opaque_encr_key = os_malloc(16);
+ if (dst->pac_opaque_encr_key == NULL) {
+ os_free(dst->eap_req_id_text);
+ return -1;
+ }
os_memcpy(dst->pac_opaque_encr_key, src->pac_opaque_encr_key,
16);
} else
@@ -1070,6 +1074,7 @@
dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len);
if (dst->eap_fast_a_id == NULL) {
os_free(dst->eap_req_id_text);
+ os_free(dst->pac_opaque_encr_key);
return -1;
}
os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id,
@@ -1081,6 +1086,7 @@
dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info);
if (dst->eap_fast_a_id_info == NULL) {
os_free(dst->eap_req_id_text);
+ os_free(dst->pac_opaque_encr_key);
os_free(dst->eap_fast_a_id);
return -1;
}
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 9730282..b09fbac 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -4298,7 +4298,7 @@
for (g = 0; g < p2p->num_groups; g++) {
group = p2p->groups[g];
- p2p_group_update_ies(group);
+ p2p_group_force_beacon_update_ies(group);
}
}
diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c
index 15e7622..92b5583 100644
--- a/src/p2p/p2p_group.c
+++ b/src/p2p/p2p_group.c
@@ -980,3 +980,10 @@
return os_memcmp(group_id + ETH_ALEN, group->cfg->ssid,
group->cfg->ssid_len) == 0;
}
+
+
+void p2p_group_force_beacon_update_ies(struct p2p_group *group)
+{
+ group->beacon_update = 1;
+ p2p_group_update_ies(group);
+}
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index e5d52aa..e4ec6de 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -616,6 +616,7 @@
int p2p_group_is_group_id_match(struct p2p_group *group, const u8 *group_id,
size_t group_id_len);
void p2p_group_update_ies(struct p2p_group *group);
+void p2p_group_force_beacon_update_ies(struct p2p_group *group);
struct wpabuf * p2p_group_get_wfd_ie(struct p2p_group *g);
diff --git a/wpa_supplicant/bgscan.c b/wpa_supplicant/bgscan.c
index 9a9bd52..f74cdbf 100644
--- a/wpa_supplicant/bgscan.c
+++ b/wpa_supplicant/bgscan.c
@@ -31,9 +31,9 @@
};
-int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ const char *name)
{
- const char *name = ssid->bgscan;
const char *params;
size_t nlen;
int i;
@@ -41,7 +41,7 @@
bgscan_deinit(wpa_s);
if (name == NULL)
- return 0;
+ return -1;
params = os_strchr(name, ':');
if (params == NULL) {
diff --git a/wpa_supplicant/bgscan.h b/wpa_supplicant/bgscan.h
index e9d15fc..9131e4e 100644
--- a/wpa_supplicant/bgscan.h
+++ b/wpa_supplicant/bgscan.h
@@ -29,7 +29,8 @@
#ifdef CONFIG_BGSCAN
-int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ const char *name);
void bgscan_deinit(struct wpa_supplicant *wpa_s);
int bgscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
@@ -41,7 +42,7 @@
#else /* CONFIG_BGSCAN */
static inline int bgscan_init(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid)
+ struct wpa_ssid *ssid, const char name)
{
return 0;
}
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 08d2ecd..19bcece 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2848,6 +2848,24 @@
}
+static int wpa_config_process_bgscan(const struct global_parse_data *data,
+ struct wpa_config *config, int line,
+ const char *pos)
+{
+ size_t len;
+ char *tmp;
+
+ tmp = wpa_config_parse_string(pos, &len);
+ if (tmp == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: failed to parse %s",
+ line, data->name);
+ return -1;
+ }
+
+ return wpa_global_config_parse_str(data, config, line, tmp);
+}
+
+
static int wpa_global_config_parse_bin(const struct global_parse_data *data,
struct wpa_config *config, int line,
const char *pos)
@@ -3209,6 +3227,7 @@
#endif /* CONFIG_CTRL_IFACE */
{ INT_RANGE(eapol_version, 1, 2), 0 },
{ INT(ap_scan), 0 },
+ { FUNC(bgscan), 0 },
{ INT(disable_scan_offload), 0 },
{ INT(fast_reauth), 0 },
{ STR(opensc_engine_path), 0 },
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 8cbeb62..55a2d62 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -329,6 +329,18 @@
int ap_scan;
/**
+ * bgscan - Background scan and roaming parameters or %NULL if none
+ *
+ * This is an optional set of parameters for background scanning and
+ * roaming within a network (ESS). For more detailed information see
+ * ssid block documentation.
+ *
+ * The variable defines default bgscan behavior for all BSS station
+ * networks except for those which have their own bgscan configuration.
+ */
+ char *bgscan;
+
+ /**
* disable_scan_offload - Disable automatic offloading of scan requests
*
* By default, %wpa_supplicant tries to offload scanning if the driver
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 067b3bd..8667221 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -18,6 +18,7 @@
#include "eap_common/eap_defs.h"
#include "eap_peer/eap.h"
#include "eap_peer/eap_methods.h"
+#include "eapol_supp/eapol_supp_sm.h"
#include "wpa_supplicant_i.h"
#include "config.h"
#include "config_ssid.h"
@@ -1383,6 +1384,23 @@
if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
return NULL;
+#ifdef CONFIG_EAP_PROXY
+ if (!wpa_s->imsi[0]) {
+ size_t len;
+ wpa_printf(MSG_DEBUG, "Interworking: IMSI not available - try to read again through eap_proxy");
+ wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol,
+ wpa_s->imsi,
+ &len);
+ if (wpa_s->mnc_len > 0) {
+ wpa_s->imsi[len] = '\0';
+ wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
+ wpa_s->imsi, wpa_s->mnc_len);
+ } else {
+ wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
+ }
+ }
+#endif /* CONFIG_EAP_PROXY */
+
for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
char *sep;
const char *imsi;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 4f34b75..a8e003c 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -134,7 +134,7 @@
static int wpas_p2p_num_unused_channels(struct wpa_supplicant *wpa_s)
{
int *freqs;
- int num;
+ int num, unused;
freqs = os_calloc(wpa_s->num_multichan_concurrent, sizeof(int));
if (!freqs)
@@ -144,7 +144,9 @@
wpa_s->num_multichan_concurrent);
os_free(freqs);
- return wpa_s->num_multichan_concurrent - num;
+ unused = wpa_s->num_multichan_concurrent - num;
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: num_unused_channels: %d", unused);
+ return unused;
}
@@ -174,6 +176,8 @@
os_free(freqs);
+ dump_freq_array(wpa_s, "valid for P2P", p2p_freqs, j);
+
return j;
}
@@ -4667,7 +4671,7 @@
}
if (i == num) {
- if (num == wpa_s->num_multichan_concurrent) {
+ if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using");
os_free(freqs);
return -1;
@@ -4682,7 +4686,7 @@
}
if (i == num) {
- if (num == wpa_s->num_multichan_concurrent) {
+ if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on freq (%u MHz) as all the channels are in use", freq);
os_free(freqs);
return -1;
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 1d7fabf..6f21998 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -272,9 +272,8 @@
ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000);
if (ret)
wpa_supplicant_notify_scanning(wpa_s, 0);
- else {
+ else
wpa_s->sched_scanning = 1;
- }
return ret;
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 41ae8f1..27cbd44 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -570,14 +570,22 @@
static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
{
+ const char *name;
+
+ if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
+ name = wpa_s->current_ssid->bgscan;
+ else
+ name = wpa_s->conf->bgscan;
+ if (name == NULL)
+ return;
if (wpas_driver_bss_selection(wpa_s))
return;
if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
return;
bgscan_deinit(wpa_s);
- if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan) {
- if (bgscan_init(wpa_s, wpa_s->current_ssid)) {
+ if (wpa_s->current_ssid) {
+ if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
"bgscan");
/*
@@ -4022,6 +4030,18 @@
}
+void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
+ int *freq_array, unsigned int len)
+{
+ unsigned int i;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
+ len, title);
+ for (i = 0; i < len; i++)
+ wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
+}
+
+
/*
* Find the operating frequencies of any of the virtual interfaces that
* are using the same radio as the current interface.
@@ -4035,6 +4055,8 @@
int freq;
unsigned int idx = 0, i;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Determining shared radio frequencies (max len %u)", len);
os_memset(freq_array, 0, sizeof(int) * len);
/* First add the frequency of the local interface */
@@ -4052,14 +4074,18 @@
if (freq > 0 && idx < len &&
(idx == 0 || freq_array[0] != freq))
freq_array[idx++] = freq;
+ dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
return idx;
}
rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
- if (rn == NULL || rn[0] == '\0')
+ if (rn == NULL || rn[0] == '\0') {
+ dump_freq_array(wpa_s, "get_radio_name failed",
+ freq_array, idx);
return idx;
+ }
- for (ifs = wpa_s->global->ifaces, idx = 0; ifs && idx < len;
+ for (ifs = wpa_s->global->ifaces; ifs && idx < len;
ifs = ifs->next) {
if (wpa_s == ifs || !ifs->driver->get_radio_name)
continue;
@@ -4087,5 +4113,7 @@
if (i == idx)
freq_array[idx++] = freq;
}
+
+ dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
return idx;
}
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 11be8dd..0ecfaa6 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -550,6 +550,10 @@
# <long interval>[:<database file name>]"
# bgscan="learn:30:-45:300:/etc/wpa_supplicant/network1.bgscan"
#
+# This option can also be set outside of all network blocks for the bgscan
+# parameter to apply for all the networks that have no specific bgscan
+# parameter.
+#
# proto: list of accepted protocols
# WPA = WPA/IEEE 802.11i/D3.0
# RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN)
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index da536cb..eed1053 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -863,6 +863,8 @@
int wpas_init_ext_pw(struct wpa_supplicant *wpa_s);
+void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
+ int *freq_array, unsigned int len);
int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
int *freq_array, unsigned int len);