Cumulative patch from commit f51f54a007e0de1d413dee3523472d3bbeed2ecc
f51f54a nl80211: Resubscribe to nl80211 events on global nl_event socket
48ec694 Fix Linux packet socket workaround to not close the socket too easily
0d2030e Use estimated throughput to improve roaming selection
1d747e2 Add snr and est_throughput to the BSS entries
a1b790e Select AP based on estimated maximum throughput
ab647ff Add wpa_supplicant Makefile target libwpa_ctrl.a
abae2d1 trace: Initialize alloc_list even without os_program_init() call
891dfb3 Add helper function to clear and free wpa_psk list
71d77ad Update current BSS level when signal change event occurs
f1609f1 wpa_supplicant: Cancel sched_scan when stopping countermeasures
abb8d08 nl80211: Add support for configuring P2P GO CTWindow
0b8bcaa P2P: Allow configuring CTWindow when working as GO
c77ffc6 TDLS: Ignore extra padding in all packets
5ce6ac1 Inteworking: Add support to update the ANQP Capability List into the BSS
185ada4 HS 2.0: Add support to update the HS20 Capability List into the BSS
7fe7a3a wpa_gui: Debug enhancement
2b892d4 Add forgotten network profile parameters to config file writing
563ee18 IBSS: Add support for VHT80 configuration
ada157f Make hostapd_set_freq_params() common
98479dc IBSS: Update operating frequency if joining an existing IBSS
4d9e6fb IBSS: Add fixed_freq network parameter
6f5e1b0 Use priority list instead of global for PNO
97fc2dc Allow libnl-3.0 include path be specified
f92446f P2PS: Add P2PS interface info
59b416c Add optional reassoc-to-same-BSS optimization
c4da67d Fix passive_scan config parameter writing
715d5c4 hs20-osu-client: Ensure NULL checks are done before dereferencing
58d405f Fix OCSP debug messages
710dfb4 OpenSSL: Fix OCSP error path
bd7bb43 HTTP: Fix OCSP error path
946572c Android: Remove commented out non-Android build parameters
15ada7f Android: Remove libxml2 config defines
ebe8d3f Android: Silence unused function parameter warnings
dbd10da Android: Fix hs20-osu-client build on Android 5.0
a926295 HS 2.0R2: Fix permissions for SP/<fqdn> directory on Android
480994d nl80211: Allocate QCA vendor subcmds for DFS radar detected and CAC events
c165cb4 Drop all hostapd STA entries on interface disabled event
106fa1e nl80211: Indicate interface-down event only for the main netdev
eeb1cb2 VLAN: Clean up RTM_NEW/DELLINK processing
47e5fbd hostapd: Avoid sending client probe on removed client
3478273 Re-configure WPA2 group keys on hostapd interface re-enable
f33c860 Re-enable beaconing on interface disable+enable
fc99fab nl80211: Print a debug log entry on NL80211_CMD_PROBE_CLIENT failures
0d2f324 P2P: Fix send_action_in_progress clearing in corner cases
9ff8dda Add hostapd UPDATE_BEACON ctrl_iface command
e0761c5 nl80211: Allocate QCA vendor subcmd for DFS CAC Start event
1db718b nl80211: Test vendor command and event
10263dc Add control interface commands for fetching wpa_config values
f91a512 Add INTERWORKING_ADD_NETWORK command
c612ae9 AP: Do not reply to Probe Request frames with DS Params mismatch
5b74e08 P2P: Document P2P_CONNECT-auto
99650ca Add STOP_AP control interface command
6b00512 P2P: Add event messages for P2P_CONNECT-fallback-to-GO-Neg
b0e669b P2P: Fix P2P_CONNECT-auto fallback to GO Neg with group interface
bf51f4f mesh: Fix remaining BLOCKED state after SAE auth failure
79ddb20 mesh: Add a monitor event on SAE authentication getting blocked
dd2cbaf mesh: Add a monitor event for SAE authentication failure
0cb5f8d mesh: Fix inactivity timer for 32 bit system
11e2ddb mesh: Remove duplicated no_auto_peer update
1e52983 D-Bus: Fix network block type change
4fada12 Fix HT40 co-ex scanning issue on hostapd error path
23ed011 Fix Linux packat socket regression work around
663ae2f Don't write to wpa_supplicant.conf directly
d9a9bc0 IBSS: Do not enable HT with WEP or TKIP
0d7eb43 ACS: Accept channel if any (rather than all) survey results are valid
68fa00c ACS: Allow specific channels to be preferred
6f41a25 ACS: Use weighted average for 2.4 GHz adjacent channel interference
Change-Id: Ie1cabd28dcfdefafa02e81477e34badae6f7e629
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/acs.c b/src/ap/acs.c
index e4c834c..ae7f6c3 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -242,6 +242,7 @@
static int acs_request_scan(struct hostapd_iface *iface);
+static int acs_survey_is_sufficient(struct freq_survey *survey);
static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
@@ -328,6 +329,7 @@
struct freq_survey *survey;
unsigned int i = 0;
long double int_factor = 0;
+ unsigned count = 0;
if (dl_list_empty(&chan->survey_list))
return;
@@ -339,18 +341,27 @@
dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list)
{
+ i++;
+
+ if (!acs_survey_is_sufficient(survey)) {
+ wpa_printf(MSG_DEBUG, "ACS: %d: insufficient data", i);
+ continue;
+ }
+
+ count++;
int_factor = acs_survey_interference_factor(survey,
iface->lowest_nf);
chan->interference_factor += int_factor;
wpa_printf(MSG_DEBUG, "ACS: %d: min_nf=%d interference_factor=%Lg nf=%d time=%lu busy=%lu rx=%lu",
- ++i, chan->min_nf, int_factor,
+ i, chan->min_nf, int_factor,
survey->nf, (unsigned long) survey->channel_time,
(unsigned long) survey->channel_time_busy,
(unsigned long) survey->channel_time_rx);
}
- chan->interference_factor = chan->interference_factor /
- dl_list_len(&chan->survey_list);
+ if (!count)
+ return;
+ chan->interference_factor /= count;
}
@@ -384,18 +395,19 @@
static int acs_survey_is_sufficient(struct freq_survey *survey)
{
if (!(survey->filled & SURVEY_HAS_NF)) {
- wpa_printf(MSG_ERROR, "ACS: Survey is missing noise floor");
+ wpa_printf(MSG_INFO, "ACS: Survey is missing noise floor");
return 0;
}
if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) {
- wpa_printf(MSG_ERROR, "ACS: Survey is missing channel time");
+ wpa_printf(MSG_INFO, "ACS: Survey is missing channel time");
return 0;
}
if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) &&
!(survey->filled & SURVEY_HAS_CHAN_TIME_RX)) {
- wpa_printf(MSG_ERROR, "ACS: Survey is missing RX and busy time (at least one is required)");
+ wpa_printf(MSG_INFO,
+ "ACS: Survey is missing RX and busy time (at least one is required)");
return 0;
}
@@ -406,18 +418,27 @@
static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan)
{
struct freq_survey *survey;
+ int ret = -1;
dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list)
{
- if (!acs_survey_is_sufficient(survey)) {
- wpa_printf(MSG_ERROR, "ACS: Channel %d has insufficient survey data",
- chan->chan);
- return 0;
+ if (acs_survey_is_sufficient(survey)) {
+ ret = 1;
+ break;
}
+ ret = 0;
}
- return 1;
+ if (ret == -1)
+ ret = 1; /* no survey list entries */
+ if (!ret) {
+ wpa_printf(MSG_INFO,
+ "ACS: Channel %d has insufficient survey data",
+ chan->chan);
+ }
+
+ return ret;
}
@@ -517,6 +538,36 @@
}
+static int is_24ghz_mode(enum hostapd_hw_mode mode)
+{
+ return mode == HOSTAPD_MODE_IEEE80211B ||
+ mode == HOSTAPD_MODE_IEEE80211G;
+}
+
+
+static int is_common_24ghz_chan(int chan)
+{
+ return chan == 1 || chan == 6 || chan == 11;
+}
+
+
+#ifndef ACS_ADJ_WEIGHT
+#define ACS_ADJ_WEIGHT 0.85
+#endif /* ACS_ADJ_WEIGHT */
+
+#ifndef ACS_NEXT_ADJ_WEIGHT
+#define ACS_NEXT_ADJ_WEIGHT 0.55
+#endif /* ACS_NEXT_ADJ_WEIGHT */
+
+#ifndef ACS_24GHZ_PREFER_1_6_11
+/*
+ * Select commonly used channels 1, 6, 11 by default even if a neighboring
+ * channel has a smaller interference factor as long as it is not better by more
+ * than this multiplier.
+ */
+#define ACS_24GHZ_PREFER_1_6_11 0.8
+#endif /* ACS_24GHZ_PREFER_1_6_11 */
+
/*
* At this point it's assumed chan->interface_factor has been computed.
* This function should be reusable regardless of interference computation
@@ -531,6 +582,7 @@
long double factor, ideal_factor = 0;
int i, j;
int n_chans = 1;
+ unsigned int k;
/* TODO: HT40- support */
@@ -557,6 +609,9 @@
-1);
for (i = 0; i < iface->current_mode->num_channels; i++) {
+ double total_weight;
+ struct acs_bias *bias, tmp_bias;
+
chan = &iface->current_mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_DISABLED)
@@ -588,14 +643,17 @@
factor = 0;
if (acs_usable_chan(chan))
factor = chan->interference_factor;
+ total_weight = 1;
for (j = 1; j < n_chans; j++) {
adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
if (!adj_chan)
break;
- if (acs_usable_chan(adj_chan))
+ if (acs_usable_chan(adj_chan)) {
factor += adj_chan->interference_factor;
+ total_weight += 1;
+ }
}
if (j != n_chans) {
@@ -606,36 +664,69 @@
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
* channel interference factor. */
- if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B ||
- iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) {
+ if (is_24ghz_mode(iface->current_mode->mode)) {
for (j = 0; j < n_chans; j++) {
- /* TODO: perhaps a multiplier should be used
- * here? */
-
adj_chan = acs_find_chan(iface, chan->freq +
(j * 20) - 5);
- if (adj_chan && acs_usable_chan(adj_chan))
- factor += adj_chan->interference_factor;
+ if (adj_chan && acs_usable_chan(adj_chan)) {
+ factor += ACS_ADJ_WEIGHT *
+ adj_chan->interference_factor;
+ total_weight += ACS_ADJ_WEIGHT;
+ }
adj_chan = acs_find_chan(iface, chan->freq +
(j * 20) - 10);
- if (adj_chan && acs_usable_chan(adj_chan))
- factor += adj_chan->interference_factor;
+ if (adj_chan && acs_usable_chan(adj_chan)) {
+ factor += ACS_NEXT_ADJ_WEIGHT *
+ adj_chan->interference_factor;
+ total_weight += ACS_NEXT_ADJ_WEIGHT;
+ }
adj_chan = acs_find_chan(iface, chan->freq +
(j * 20) + 5);
- if (adj_chan && acs_usable_chan(adj_chan))
- factor += adj_chan->interference_factor;
+ if (adj_chan && acs_usable_chan(adj_chan)) {
+ factor += ACS_ADJ_WEIGHT *
+ adj_chan->interference_factor;
+ total_weight += ACS_ADJ_WEIGHT;
+ }
adj_chan = acs_find_chan(iface, chan->freq +
(j * 20) + 10);
- if (adj_chan && acs_usable_chan(adj_chan))
- factor += adj_chan->interference_factor;
+ if (adj_chan && acs_usable_chan(adj_chan)) {
+ factor += ACS_NEXT_ADJ_WEIGHT *
+ adj_chan->interference_factor;
+ total_weight += ACS_NEXT_ADJ_WEIGHT;
+ }
}
}
- wpa_printf(MSG_DEBUG, "ACS: * channel %d: total interference = %Lg",
- chan->chan, factor);
+ factor /= total_weight;
+
+ bias = NULL;
+ if (iface->conf->acs_chan_bias) {
+ for (k = 0; k < iface->conf->num_acs_chan_bias; k++) {
+ bias = &iface->conf->acs_chan_bias[k];
+ if (bias->channel == chan->chan)
+ break;
+ bias = NULL;
+ }
+ } else if (is_24ghz_mode(iface->current_mode->mode) &&
+ is_common_24ghz_chan(chan->chan)) {
+ tmp_bias.channel = chan->chan;
+ tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
+ bias = &tmp_bias;
+ }
+
+ if (bias) {
+ factor *= bias->bias;
+ wpa_printf(MSG_DEBUG,
+ "ACS: * channel %d: total interference = %Lg (%f bias)",
+ chan->chan, factor, bias->bias);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "ACS: * channel %d: total interference = %Lg",
+ chan->chan, factor);
+ }
if (acs_usable_chan(chan) &&
(!ideal_chan || factor < ideal_factor)) {
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 1c0ed7a..76011dc 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -394,20 +394,27 @@
}
+void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
+{
+ struct hostapd_wpa_psk *psk, *tmp;
+
+ for (psk = *l; psk;) {
+ tmp = psk;
+ psk = psk->next;
+ bin_clear_free(tmp, sizeof(*tmp));
+ }
+ *l = NULL;
+}
+
+
void hostapd_config_free_bss(struct hostapd_bss_config *conf)
{
- struct hostapd_wpa_psk *psk, *prev;
struct hostapd_eap_user *user, *prev_user;
if (conf == NULL)
return;
- psk = conf->ssid.wpa_psk;
- while (psk) {
- prev = psk;
- psk = psk->next;
- bin_clear_free(prev, sizeof(*prev));
- }
+ hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
str_clear_free(conf->ssid.wpa_passphrase);
os_free(conf->ssid.wpa_psk_file);
@@ -574,6 +581,9 @@
os_free(conf->basic_rates);
os_free(conf->chanlist);
os_free(conf->driver_params);
+#ifdef CONFIG_ACS
+ os_free(conf->acs_chan_bias);
+#endif /* CONFIG_ACS */
os_free(conf);
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index e5215c5..961d2dd 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -629,6 +629,10 @@
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
+#ifdef CONFIG_P2P
+ u8 p2p_go_ctwindow;
+#endif /* CONFIG_P2P */
+
#ifdef CONFIG_TESTING_OPTIONS
double ignore_probe_probability;
double ignore_auth_probability;
@@ -639,6 +643,11 @@
#ifdef CONFIG_ACS
unsigned int acs_num_scans;
+ struct acs_bias {
+ int channel;
+ double bias;
+ } *acs_chan_bias;
+ unsigned int num_acs_chan_bias;
#endif /* CONFIG_ACS */
};
@@ -648,6 +657,7 @@
struct hostapd_config * hostapd_config_defaults(void);
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
+void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p);
void hostapd_config_free_bss(struct hostapd_bss_config *conf);
void hostapd_config_free(struct hostapd_config *conf);
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 8514cbe..e16306c 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -10,6 +10,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
+#include "common/hw_features_common.h"
#include "wps/wps.h"
#include "p2p/p2p.h"
#include "hostapd.h"
@@ -477,92 +478,6 @@
}
-int hostapd_set_freq_params(struct hostapd_freq_params *data,
- enum hostapd_hw_mode mode,
- int freq, int channel, int ht_enabled,
- int vht_enabled, int sec_channel_offset,
- int vht_oper_chwidth, int center_segment0,
- int center_segment1, u32 vht_caps)
-{
- int tmp;
-
- os_memset(data, 0, sizeof(*data));
- data->mode = mode;
- data->freq = freq;
- data->channel = channel;
- data->ht_enabled = ht_enabled;
- data->vht_enabled = vht_enabled;
- data->sec_channel_offset = sec_channel_offset;
- data->center_freq1 = freq + sec_channel_offset * 10;
- data->center_freq2 = 0;
- data->bandwidth = sec_channel_offset ? 40 : 20;
-
- /*
- * This validation code is probably misplaced, maybe it should be
- * in src/ap/hw_features.c and check the hardware support as well.
- */
- if (data->vht_enabled) switch (vht_oper_chwidth) {
- case VHT_CHANWIDTH_USE_HT:
- if (center_segment1)
- return -1;
- if (center_segment0 != 0 &&
- 5000 + center_segment0 * 5 != data->center_freq1 &&
- 2407 + center_segment0 * 5 != data->center_freq1)
- return -1;
- break;
- case VHT_CHANWIDTH_80P80MHZ:
- if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) {
- wpa_printf(MSG_ERROR,
- "80+80 channel width is not supported!");
- return -1;
- }
- if (center_segment1 == center_segment0 + 4 ||
- center_segment1 == center_segment0 - 4)
- return -1;
- data->center_freq2 = 5000 + center_segment1 * 5;
- /* fall through */
- case VHT_CHANWIDTH_80MHZ:
- data->bandwidth = 80;
- if (vht_oper_chwidth == 1 && center_segment1)
- return -1;
- if (vht_oper_chwidth == 3 && !center_segment1)
- return -1;
- if (!sec_channel_offset)
- return -1;
- /* primary 40 part must match the HT configuration */
- tmp = (30 + freq - 5000 - center_segment0 * 5)/20;
- tmp /= 2;
- if (data->center_freq1 != 5000 +
- center_segment0 * 5 - 20 + 40 * tmp)
- return -1;
- data->center_freq1 = 5000 + center_segment0 * 5;
- break;
- case VHT_CHANWIDTH_160MHZ:
- data->bandwidth = 160;
- if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
- VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
- wpa_printf(MSG_ERROR,
- "160MHZ channel width is not supported!");
- return -1;
- }
- if (center_segment1)
- return -1;
- if (!sec_channel_offset)
- return -1;
- /* primary 40 part must match the HT configuration */
- tmp = (70 + freq - 5000 - center_segment0 * 5)/20;
- tmp /= 2;
- if (data->center_freq1 != 5000 +
- center_segment0 * 5 - 60 + 40 * tmp)
- return -1;
- data->center_freq1 = 5000 + center_segment0 * 5;
- break;
- }
-
- return 0;
-}
-
-
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
int freq, int channel, int ht_enabled, int vht_enabled,
int sec_channel_offset, int vht_oper_chwidth,
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index c133be7..5d07e71 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -107,12 +107,6 @@
int channel, int ht_enabled, int vht_enabled,
int sec_channel_offset, int vht_oper_chwidth,
int center_segment0, int center_segment1);
-int hostapd_set_freq_params(struct hostapd_freq_params *data,
- enum hostapd_hw_mode mode,
- int freq, int channel, int ht_enabled,
- int vht_enabled, int sec_channel_offset,
- int vht_oper_chwidth, int center_segment0,
- int center_segment1, u32 vht_caps);
int hostapd_drv_do_acs(struct hostapd_data *hapd);
@@ -335,4 +329,11 @@
data_len, buf);
}
+static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
+{
+ if (hapd->driver == NULL || hapd->driver->stop_ap == NULL)
+ return 0;
+ return hapd->driver->stop_ap(hapd->drv_priv);
+}
+
#endif /* AP_DRV_OPS */
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index b0a74e0..e575b65 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -15,6 +15,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
+#include "common/hw_features_common.h"
#include "wps/wps_defs.h"
#include "p2p/p2p.h"
#include "hostapd.h"
@@ -579,6 +580,27 @@
return;
}
+ /*
+ * No need to reply if the Probe Request frame was sent on an adjacent
+ * channel. IEEE Std 802.11-2012 describes this as a requirement for an
+ * AP with dot11RadioMeasurementActivated set to true, but strictly
+ * speaking does not allow such ignoring of Probe Request frames if
+ * dot11RadioMeasurementActivated is false. Anyway, this can help reduce
+ * number of unnecessary Probe Response frames for cases where the STA
+ * is less likely to see them (Probe Request frame sent on a
+ * neighboring, but partially overlapping, channel).
+ */
+ if (elems.ds_params && elems.ds_params_len == 1 &&
+ hapd->iface->current_mode &&
+ (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G ||
+ hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B) &&
+ hapd->iconf->channel != elems.ds_params[0]) {
+ wpa_printf(MSG_DEBUG,
+ "Ignore Probe Request due to DS Params mismatch: chan=%u != ds.chan=%u",
+ hapd->iconf->channel, elems.ds_params[0]);
+ return;
+ }
+
#ifdef CONFIG_P2P
if (hapd->p2p && elems.wps_ie) {
struct wpabuf *wps;
@@ -986,6 +1008,9 @@
params->hessid = hapd->conf->hessid;
params->access_network_type = hapd->conf->access_network_type;
params->ap_max_inactivity = hapd->conf->ap_max_inactivity;
+#ifdef CONFIG_P2P
+ params->p2p_go_ctwindow = hapd->iconf->p2p_go_ctwindow;
+#endif /* CONFIG_P2P */
#ifdef CONFIG_HS20
params->disable_dgaf = hapd->conf->disable_dgaf;
if (hapd->conf->osen) {
@@ -1034,6 +1059,8 @@
params.beacon_ies = beacon;
params.proberesp_ies = proberesp;
params.assocresp_ies = assocresp;
+ params.reenable = hapd->reenable_beacon;
+ hapd->reenable_beacon = 0;
if (iface->current_mode &&
hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 8c84e3e..41ab988 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -537,3 +537,9 @@
return 0;
}
+
+
+int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd)
+{
+ return hostapd_drv_stop_ap(hapd);
+}
diff --git a/src/ap/ctrl_iface_ap.h b/src/ap/ctrl_iface_ap.h
index ee58b4c..e5297d0 100644
--- a/src/ap/ctrl_iface_ap.h
+++ b/src/ap/ctrl_iface_ap.h
@@ -23,6 +23,6 @@
size_t buflen);
int hostapd_parse_csa_settings(const char *pos,
struct csa_settings *settings);
-
+int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd);
#endif /* CTRL_IFACE_AP_H */
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 0db5ef6..fc8d7ad 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -11,6 +11,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
+#include "common/hw_features_common.h"
#include "common/wpa_ctrl.h"
#include "hostapd.h"
#include "ap_drv_ops.h"
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 40a2a9c..c39989c 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -1210,9 +1210,21 @@
#endif /* NEED_AP_MLME */
case EVENT_INTERFACE_ENABLED:
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
+ if (hapd->disabled && hapd->started) {
+ hapd->disabled = 0;
+ /*
+ * Try to re-enable interface if the driver stopped it
+ * when the interface got disabled.
+ */
+ wpa_auth_reconfig_group_keys(hapd->wpa_auth);
+ hapd->reenable_beacon = 1;
+ ieee802_11_set_beacon(hapd);
+ }
break;
case EVENT_INTERFACE_DISABLED:
+ hostapd_free_stas(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
+ hapd->disabled = 1;
break;
#ifdef CONFIG_ACS
case EVENT_ACS_CHANNEL_SELECTED:
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index b641503..e641b12 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -82,8 +82,7 @@
* Force PSK to be derived again since SSID or passphrase may
* have changed.
*/
- os_free(ssid->wpa_psk);
- ssid->wpa_psk = NULL;
+ hostapd_config_clear_wpa_psk(&hapd->conf->ssid.wpa_psk);
}
if (hostapd_setup_wpa_psk(hapd->conf)) {
wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
@@ -357,6 +356,11 @@
static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
{
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+#ifdef CONFIG_IEEE80211N
+#ifdef NEED_AP_MLME
+ hostapd_stop_setup_timers(iface);
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_IEEE80211N */
hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
iface->hw_features = NULL;
os_free(iface->current_rates);
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 8e2c70e..75cc24e 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -105,6 +105,8 @@
struct hostapd_bss_config *conf;
int interface_added; /* virtual interface added for this BSS */
unsigned int started:1;
+ unsigned int disabled:1;
+ unsigned int reenable_beacon:1;
u8 own_addr[ETH_ALEN];
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index eebaa3c..7e75e1a 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -375,8 +375,9 @@
"Station " MACSTR " has lost its driver entry",
MAC2STR(sta->addr));
- if (hapd->conf->skip_inactivity_poll)
- sta->timeout_next = STA_DISASSOC;
+ /* Avoid sending client probe on removed client */
+ sta->timeout_next = STA_DISASSOC;
+ goto skip_poll;
} else if (inactive_sec < hapd->conf->ap_max_inactivity) {
/* station activity detected; reset timeout state */
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
@@ -409,6 +410,7 @@
next_time = hapd->conf->ap_max_inactivity;
}
+skip_poll:
if (next_time) {
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
"for " MACSTR " (%lu seconds)",
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 2af2cbc..dc65019 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -617,6 +617,7 @@
struct ifinfomsg *ifi;
int attrlen, nlmsg_len, rta_len;
struct rtattr *attr;
+ char ifname[IFNAMSIZ + 1];
if (len < sizeof(*ifi))
return;
@@ -631,29 +632,39 @@
attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+ os_memset(ifname, 0, sizeof(ifname));
rta_len = RTA_ALIGN(sizeof(struct rtattr));
while (RTA_OK(attr, attrlen)) {
- char ifname[IFNAMSIZ + 1];
-
if (attr->rta_type == IFLA_IFNAME) {
int n = attr->rta_len - rta_len;
if (n < 0)
break;
- os_memset(ifname, 0, sizeof(ifname));
-
- if ((size_t) n > sizeof(ifname))
- n = sizeof(ifname);
+ if ((size_t) n >= sizeof(ifname))
+ n = sizeof(ifname) - 1;
os_memcpy(ifname, ((char *) attr) + rta_len, n);
- if (del)
- vlan_dellink(ifname, hapd);
- else
- vlan_newlink(ifname, hapd);
}
attr = RTA_NEXT(attr, attrlen);
}
+
+ if (!ifname[0])
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
+ del ? "DEL" : "NEW",
+ ifi->ifi_index, ifname, 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 (del)
+ vlan_dellink(ifname, hapd);
+ else
+ vlan_newlink(ifname, hapd);
}
@@ -677,7 +688,7 @@
}
h = (struct nlmsghdr *) buf;
- while (left >= (int) sizeof(*h)) {
+ while (NLMSG_OK(h, left)) {
int len, plen;
len = h->nlmsg_len;
@@ -698,9 +709,7 @@
break;
}
- len = NLMSG_ALIGN(len);
- left -= len;
- h = (struct nlmsghdr *) ((char *) h + len);
+ h = NLMSG_NEXT(h, left);
}
if (left > 0) {
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 668cb42..9c5f609 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -3387,3 +3387,14 @@
{
return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr);
}
+
+
+void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth)
+{
+ struct wpa_group *group;
+
+ if (!wpa_auth)
+ return;
+ for (group = wpa_auth->group; group; group = group->next)
+ wpa_group_config_group_keys(wpa_auth, group);
+}
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index b34b84d..2788e65 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -318,5 +318,6 @@
struct radius_das_attrs;
int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
struct radius_das_attrs *attr);
+void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth);
#endif /* WPA_AUTH_H */
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 9ba7aba..b0e8b0b 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -362,10 +362,9 @@
if (bss->ssid.wpa_passphrase)
os_memcpy(bss->ssid.wpa_passphrase, cred->key,
cred->key_len);
- os_free(bss->ssid.wpa_psk);
- bss->ssid.wpa_psk = NULL;
+ hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
} else if (cred->key_len == 64) {
- os_free(bss->ssid.wpa_psk);
+ hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
bss->ssid.wpa_psk =
os_zalloc(sizeof(struct hostapd_wpa_psk));
if (bss->ssid.wpa_psk &&
diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
index 942380b..e8babb5 100644
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -354,3 +354,85 @@
return 1;
}
+
+
+int hostapd_set_freq_params(struct hostapd_freq_params *data,
+ enum hostapd_hw_mode mode,
+ int freq, int channel, int ht_enabled,
+ int vht_enabled, int sec_channel_offset,
+ int vht_oper_chwidth, int center_segment0,
+ int center_segment1, u32 vht_caps)
+{
+ int tmp;
+
+ os_memset(data, 0, sizeof(*data));
+ data->mode = mode;
+ data->freq = freq;
+ data->channel = channel;
+ data->ht_enabled = ht_enabled;
+ data->vht_enabled = vht_enabled;
+ data->sec_channel_offset = sec_channel_offset;
+ data->center_freq1 = freq + sec_channel_offset * 10;
+ data->center_freq2 = 0;
+ data->bandwidth = sec_channel_offset ? 40 : 20;
+
+ if (data->vht_enabled) switch (vht_oper_chwidth) {
+ case VHT_CHANWIDTH_USE_HT:
+ if (center_segment1)
+ return -1;
+ if (center_segment0 != 0 &&
+ 5000 + center_segment0 * 5 != data->center_freq1 &&
+ 2407 + center_segment0 * 5 != data->center_freq1)
+ return -1;
+ break;
+ case VHT_CHANWIDTH_80P80MHZ:
+ if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) {
+ wpa_printf(MSG_ERROR,
+ "80+80 channel width is not supported!");
+ return -1;
+ }
+ if (center_segment1 == center_segment0 + 4 ||
+ center_segment1 == center_segment0 - 4)
+ return -1;
+ data->center_freq2 = 5000 + center_segment1 * 5;
+ /* fall through */
+ case VHT_CHANWIDTH_80MHZ:
+ data->bandwidth = 80;
+ if (vht_oper_chwidth == 1 && center_segment1)
+ return -1;
+ if (vht_oper_chwidth == 3 && !center_segment1)
+ return -1;
+ if (!sec_channel_offset)
+ return -1;
+ /* primary 40 part must match the HT configuration */
+ tmp = (30 + freq - 5000 - center_segment0 * 5) / 20;
+ tmp /= 2;
+ if (data->center_freq1 != 5000 +
+ center_segment0 * 5 - 20 + 40 * tmp)
+ return -1;
+ data->center_freq1 = 5000 + center_segment0 * 5;
+ break;
+ case VHT_CHANWIDTH_160MHZ:
+ data->bandwidth = 160;
+ if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
+ VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) {
+ wpa_printf(MSG_ERROR,
+ "160MHZ channel width is not supported!");
+ return -1;
+ }
+ if (center_segment1)
+ return -1;
+ if (!sec_channel_offset)
+ return -1;
+ /* primary 40 part must match the HT configuration */
+ tmp = (70 + freq - 5000 - center_segment0 * 5) / 20;
+ tmp /= 2;
+ if (data->center_freq1 != 5000 +
+ center_segment0 * 5 - 60 + 40 * tmp)
+ return -1;
+ data->center_freq1 = 5000 + center_segment0 * 5;
+ break;
+ }
+
+ return 0;
+}
diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h
index 046fccd..7f43d00 100644
--- a/src/common/hw_features_common.h
+++ b/src/common/hw_features_common.h
@@ -30,5 +30,11 @@
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
struct wpa_scan_results *scan_res, int pri_chan,
int sec_chan);
+int hostapd_set_freq_params(struct hostapd_freq_params *data,
+ enum hostapd_hw_mode mode,
+ int freq, int channel, int ht_enabled,
+ int vht_enabled, int sec_channel_offset,
+ int vht_oper_chwidth, int center_segment0,
+ int center_segment1, u32 vht_caps);
#endif /* HW_FEATURES_COMMON_H */
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index ec1be86..cf04193 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -1,6 +1,6 @@
/*
* Qualcomm Atheros OUI and vendor specific assignments
- * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2015, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -69,6 +69,26 @@
* @QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: Command to get the features
* supported by the driver. enum qca_wlan_vendor_features defines
* the possible features.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED: Event used by driver,
+ * which supports DFS offloading, to indicate a channel availability check
+ * start.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED: Event used by driver,
+ * which supports DFS offloading, to indicate a channel availability check
+ * completion.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED: Event used by driver,
+ * which supports DFS offloading, to indicate that the channel availability
+ * check aborted, no change to the channel status.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED: Event used by
+ * driver, which supports DFS offloading, to indicate that the
+ * Non-Occupancy Period for this channel is over, channel becomes usable.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED: Event used by driver,
+ * which supports DFS offloading, to indicate a radar pattern has been
+ * detected. The channel is now unusable.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -115,6 +135,11 @@
/* 53 - reserved for QCA */
QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54,
QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES = 55,
+ QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED = 56,
+ QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED = 57,
+ QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED = 58,
+ QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED = 59,
+ QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60,
};
@@ -134,6 +159,7 @@
QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7,
+ QCA_WLAN_VENDOR_ATTR_TEST = 8,
/* keep last */
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index c8e302a..1d19fc5 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -127,6 +127,9 @@
#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "
#define MESH_PEER_CONNECTED "MESH-PEER-CONNECTED "
#define MESH_PEER_DISCONNECTED "MESH-PEER-DISCONNECTED "
+/** Mesh SAE authentication failure. Wrong password suspected. */
+#define MESH_SAE_AUTH_FAILURE "MESH-SAE-AUTH-FAILURE "
+#define MESH_SAE_AUTH_BLOCKED "MESH-SAE-AUTH-BLOCKED "
/* WMM AC events */
#define WMM_AC_EVENT_TSPEC_ADDED "TSPEC-ADDED "
@@ -173,6 +176,8 @@
#define P2P_EVENT_NFC_BOTH_GO "P2P-NFC-BOTH-GO "
#define P2P_EVENT_NFC_PEER_CLIENT "P2P-NFC-PEER-CLIENT "
#define P2P_EVENT_NFC_WHILE_CLIENT "P2P-NFC-WHILE-CLIENT "
+#define P2P_EVENT_FALLBACK_TO_GO_NEG "P2P-FALLBACK-TO-GO-NEG "
+#define P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED "P2P-FALLBACK-TO-GO-NEG-ENABLED "
/* parameters: <PMF enabled> <timeout in ms> <Session Information URL> */
#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
@@ -269,6 +274,8 @@
#define WPA_BSS_MASK_WIFI_DISPLAY BIT(16)
#define WPA_BSS_MASK_DELIM BIT(17)
#define WPA_BSS_MASK_MESH_SCAN BIT(18)
+#define WPA_BSS_MASK_SNR BIT(19)
+#define WPA_BSS_MASK_EST_THROUGHPUT BIT(20)
/* VENDOR_ELEM_* frame id values */
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index d8c8c56..46c4a46 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -3153,7 +3153,7 @@
if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
tls_show_errors(MSG_INFO, __func__,
- "OpenSSL: Could not add issuer to certificate store\n");
+ "OpenSSL: Could not add issuer to certificate store");
}
certs = sk_X509_new_null();
if (certs) {
@@ -3162,17 +3162,17 @@
if (cert && !sk_X509_push(certs, cert)) {
tls_show_errors(
MSG_INFO, __func__,
- "OpenSSL: Could not add issuer to OCSP responder trust store\n");
+ "OpenSSL: Could not add issuer to OCSP responder trust store");
X509_free(cert);
sk_X509_free(certs);
certs = NULL;
}
- if (conn->peer_issuer_issuer) {
+ if (certs && conn->peer_issuer_issuer) {
cert = X509_dup(conn->peer_issuer_issuer);
if (cert && !sk_X509_push(certs, cert)) {
tls_show_errors(
MSG_INFO, __func__,
- "OpenSSL: Could not add issuer to OCSP responder trust store\n");
+ "OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
X509_free(cert);
}
}
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index c9e860f..d35309a 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -213,6 +213,9 @@
* @tsf: Timestamp
* @age: Age of the information in milliseconds (i.e., how many milliseconds
* ago the last Beacon or Probe Response frame was received)
+ * @est_throughput: Estimated throughput in kbps (this is calculated during
+ * scan result processing if left zero by the driver wrapper)
+ * @snr: Signal-to-noise ratio in dB (calculated during scan result processing)
* @ie_len: length of the following IE field in octets
* @beacon_ie_len: length of the following Beacon IE field in octets
*
@@ -241,6 +244,8 @@
int level;
u64 tsf;
unsigned int age;
+ unsigned int est_throughput;
+ int snr;
size_t ie_len;
size_t beacon_ie_len;
/* Followed by ie_len + beacon_ie_len octets of IE data */
@@ -767,6 +772,14 @@
int fixed_bssid;
/**
+ * fixed_freq - Fix control channel in IBSS mode
+ * 0 = don't fix control channel (default)
+ * 1 = fix control channel; this prevents IBSS merging with another
+ * channel
+ */
+ int fixed_freq;
+
+ /**
* disable_ht - Disable HT (IEEE 802.11n) for this connection
*/
int disable_ht;
@@ -1010,6 +1023,11 @@
int ap_max_inactivity;
/**
+ * ctwindow - Client Traffic Window (in TUs)
+ */
+ u8 p2p_go_ctwindow;
+
+ /**
* smps_mode - SMPS mode
*
* SMPS mode to be used by the AP, specified as the relevant bits of
@@ -1031,6 +1049,11 @@
* freq - Channel parameters for dynamic bandwidth changes
*/
struct hostapd_freq_params *freq;
+
+ /**
+ * reenable - Whether this is to re-enable beaconing
+ */
+ int reenable;
};
struct wpa_driver_mesh_bss_params {
@@ -1186,6 +1209,8 @@
#define WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH 0x0000000800000000ULL
/** Driver supports IBSS with HT datarates */
#define WPA_DRIVER_FLAGS_HT_IBSS 0x0000001000000000ULL
+/** Driver supports IBSS with VHT datarates */
+#define WPA_DRIVER_FLAGS_VHT_IBSS 0x0000002000000000ULL
u64 flags;
#define WPA_DRIVER_SMPS_MODE_STATIC 0x00000001
@@ -3758,7 +3783,7 @@
EVENT_CONNECT_FAILED_REASON,
/**
- * EVENT_RADAR_DETECTED - Notify of radar detection
+ * EVENT_DFS_RADAR_DETECTED - Notify of radar detection
*
* A radar has been detected on the supplied frequency, hostapd should
* react accordingly (e.g., change channel).
@@ -3766,14 +3791,14 @@
EVENT_DFS_RADAR_DETECTED,
/**
- * EVENT_CAC_FINISHED - Notify that channel availability check has been completed
+ * EVENT_DFS_CAC_FINISHED - Notify that channel availability check has been completed
*
* After a successful CAC, the channel can be marked clear and used.
*/
EVENT_DFS_CAC_FINISHED,
/**
- * EVENT_CAC_ABORTED - Notify that channel availability check has been aborted
+ * EVENT_DFS_CAC_ABORTED - Notify that channel availability check has been aborted
*
* The CAC was not successful, and the channel remains in the previous
* state. This may happen due to a radar beeing detected or other
@@ -3782,7 +3807,7 @@
EVENT_DFS_CAC_ABORTED,
/**
- * EVENT_DFS_CAC_NOP_FINISHED - Notify that non-occupancy period is over
+ * EVENT_DFS_NOP_FINISHED - Notify that non-occupancy period is over
*
* The channel which was previously unavailable is now available again.
*/
@@ -3831,6 +3856,15 @@
* in device.
*/
EVENT_ACS_CHANNEL_SELECTED,
+
+ /**
+ * EVENT_DFS_CAC_STARTED - Notify that channel availability check has
+ * been started.
+ *
+ * This event indicates that channel availability check has been started
+ * on a DFS frequency by a driver that supports DFS Offload.
+ */
+ EVENT_DFS_CAC_STARTED,
};
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index f897c11..aebea8c 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -79,6 +79,7 @@
E2S(AVOID_FREQUENCIES);
E2S(NEW_PEER_CANDIDATE);
E2S(ACS_CHANNEL_SELECTED);
+ E2S(DFS_CAC_STARTED);
}
return "UNKNOWN";
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index d681ea6..2dce242 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -164,6 +164,7 @@
static void nl80211_global_deinit(void *priv);
+static void nl80211_check_global(struct nl80211_global *global);
static void wpa_driver_nl80211_deinit(struct i802_bss *bss);
static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss,
@@ -864,6 +865,7 @@
return 1;
if (drv->if_removed && wpa_driver_nl80211_own_ifname(drv, buf, len)) {
+ nl80211_check_global(drv->global);
wpa_printf(MSG_DEBUG, "nl80211: Update ifindex for a removed "
"interface");
wpa_driver_nl80211_finish_drv_init(drv, NULL, 0, NULL);
@@ -952,16 +954,21 @@
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
+ namebuf[0] = '\0';
if (if_indextoname(ifi->ifi_index, namebuf) &&
- linux_iface_up(drv->global->ioctl_sock,
- drv->first_bss->ifname) > 0) {
+ linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) {
wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
"event since interface %s is up", namebuf);
drv->ignore_if_down_event = 0;
return;
}
- wpa_printf(MSG_DEBUG, "nl80211: Interface down");
- if (drv->ignore_if_down_event) {
+ wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
+ namebuf, ifname);
+ if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Not the main interface (%s) - do not indicate interface down",
+ drv->first_bss->ifname);
+ } else if (drv->ignore_if_down_event) {
wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down "
"event generated by mode change");
drv->ignore_if_down_event = 0;
@@ -984,8 +991,7 @@
if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {
if (if_indextoname(ifi->ifi_index, namebuf) &&
- linux_iface_up(drv->global->ioctl_sock,
- drv->first_bss->ifname) == 0) {
+ linux_iface_up(drv->global->ioctl_sock, namebuf) == 0) {
wpa_printf(MSG_DEBUG, "nl80211: Ignore interface up "
"event since interface %s is down",
namebuf);
@@ -1477,6 +1483,33 @@
}
+static void nl80211_check_global(struct nl80211_global *global)
+{
+ struct nl_handle *handle;
+ const char *groups[] = { "scan", "mlme", "regulatory", "vendor", NULL };
+ int ret;
+ unsigned int i;
+
+ /*
+ * Try to re-add memberships to handle case of cfg80211 getting reloaded
+ * and all registration having been cleared.
+ */
+ handle = (void *) (((intptr_t) global->nl_event) ^
+ ELOOP_SOCKET_INVALID);
+
+ for (i = 0; groups[i]; i++) {
+ ret = nl_get_multicast_id(global, "nl80211", groups[i]);
+ if (ret >= 0)
+ ret = nl_socket_add_membership(handle, ret);
+ if (ret < 0) {
+ wpa_printf(MSG_INFO,
+ "nl80211: Could not re-add multicast membership for %s events: %d (%s)",
+ groups[i], ret, strerror(-ret));
+ }
+ }
+}
+
+
static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
{
wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
@@ -1670,6 +1703,7 @@
}
if (drv->global) {
+ nl80211_check_global(drv->global);
dl_list_add(&drv->global->interfaces, &drv->list);
drv->in_interface_list = 1;
}
@@ -2065,6 +2099,60 @@
}
+#ifdef CONFIG_TESTING_OPTIONS
+static int qca_vendor_test_cmd_handler(struct nl_msg *msg, void *arg)
+{
+ /* struct wpa_driver_nl80211_data *drv = arg; */
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: QCA vendor test command response received");
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+ if (!tb[NL80211_ATTR_VENDOR_DATA]) {
+ wpa_printf(MSG_DEBUG, "nl80211: No vendor data attribute");
+ return NL_SKIP;
+ }
+
+ wpa_hexdump(MSG_DEBUG,
+ "nl80211: Received QCA vendor test command response",
+ nla_data(tb[NL80211_ATTR_VENDOR_DATA]),
+ nla_len(tb[NL80211_ATTR_VENDOR_DATA]));
+
+ return NL_SKIP;
+}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
+static void qca_vendor_test(struct wpa_driver_nl80211_data *drv)
+{
+#ifdef CONFIG_TESTING_OPTIONS
+ struct nl_msg *msg;
+ struct nlattr *params;
+ int ret;
+
+ 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_TEST) ||
+ !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_TEST, 123)) {
+ nlmsg_free(msg);
+ return;
+ }
+ nla_nest_end(msg, params);
+
+ ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv);
+ wpa_printf(MSG_DEBUG,
+ "nl80211: QCA vendor test command returned %d (%s)",
+ ret, strerror(-ret));
+#endif /* CONFIG_TESTING_OPTIONS */
+}
+
+
static int
wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv,
const u8 *set_addr, int first,
@@ -2151,6 +2239,9 @@
drv, drv->ctx);
}
+ if (drv->vendor_cmd_test_avail)
+ qca_vendor_test(drv);
+
return 0;
}
@@ -3213,7 +3304,7 @@
u32 suites[10], suite;
u32 ver;
- beacon_set = bss->beacon_set;
+ beacon_set = params->reenable ? 0 : bss->beacon_set;
wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
beacon_set);
@@ -3378,6 +3469,21 @@
goto fail;
}
+#ifdef CONFIG_P2P
+ if (params->p2p_go_ctwindow > 0) {
+ if (drv->p2p_go_ctwindow_supported) {
+ wpa_printf(MSG_DEBUG, "nl80211: P2P GO ctwindow=%d",
+ params->p2p_go_ctwindow);
+ if (nla_put_u8(msg, NL80211_ATTR_P2P_CTWINDOW,
+ params->p2p_go_ctwindow))
+ goto fail;
+ } else {
+ wpa_printf(MSG_INFO,
+ "nl80211: Driver does not support CTWindow configuration - ignore this parameter");
+ }
+ }
+#endif /* CONFIG_P2P */
+
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
@@ -4317,6 +4423,12 @@
goto fail;
}
+ if (params->fixed_freq) {
+ wpa_printf(MSG_DEBUG, " * fixed_freq");
+ if (nla_put_flag(msg, NL80211_ATTR_FREQ_FIXED))
+ goto fail;
+ }
+
if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X ||
params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 ||
@@ -6867,6 +6979,7 @@
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
+ int ret;
if (!drv->poll_command_supported) {
nl80211_send_null_frame(bss, own_addr, addr, qos);
@@ -6879,7 +6992,12 @@
return;
}
- send_and_recv_msgs(drv, msg, NULL, NULL);
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret < 0) {
+ wpa_printf(MSG_DEBUG, "nl80211: Client probe request for "
+ MACSTR " failed: ret=%d (%s)",
+ MAC2STR(addr), ret, strerror(-ret));
+ }
}
@@ -7849,16 +7967,13 @@
}
-static int
-wpa_driver_nl80211_join_mesh(void *priv,
+static int nl80211_join_mesh(struct i802_bss *bss,
struct wpa_driver_mesh_join_params *params)
{
- struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
struct nlattr *container;
int ret = -1;
- u32 timeout;
wpa_printf(MSG_DEBUG, "nl80211: mesh join (ifindex=%d)", drv->ifindex);
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_JOIN_MESH);
@@ -7910,14 +8025,9 @@
/*
* Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because
* the timer could disconnect stations even in that case.
- *
- * Set 0xffffffff instead of 0 because NL80211_MESHCONF_PLINK_TIMEOUT
- * does not allow 0.
*/
- timeout = params->conf.peer_link_timeout;
- if ((params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM) || timeout == 0)
- timeout = 0xffffffff;
- if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT, timeout)) {
+ if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
+ params->conf.peer_link_timeout)) {
wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT");
goto fail;
}
@@ -7941,6 +8051,37 @@
}
+static int
+wpa_driver_nl80211_join_mesh(void *priv,
+ struct wpa_driver_mesh_join_params *params)
+{
+ struct i802_bss *bss = priv;
+ int ret, timeout;
+
+ timeout = params->conf.peer_link_timeout;
+
+ /* Disable kernel inactivity timer */
+ if (params->flags & WPA_DRIVER_MESH_FLAG_USER_MPM)
+ params->conf.peer_link_timeout = 0;
+
+ ret = nl80211_join_mesh(bss, params);
+ if (ret == -EINVAL && params->conf.peer_link_timeout == 0) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Mesh join retry for peer_link_timeout");
+ /*
+ * Old kernel does not support setting
+ * NL80211_MESHCONF_PLINK_TIMEOUT to zero, so set 60 seconds
+ * into future from peer_link_timeout.
+ */
+ params->conf.peer_link_timeout = timeout + 60;
+ ret = nl80211_join_mesh(priv, params);
+ }
+
+ params->conf.peer_link_timeout = timeout;
+ return ret;
+}
+
+
static int wpa_driver_nl80211_leave_mesh(void *priv)
{
struct i802_bss *bss = priv;
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 4567f42..802589a 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -136,6 +136,7 @@
unsigned int start_iface_up:1;
unsigned int test_use_roc_tx:1;
unsigned int ignore_deauth_event:1;
+ unsigned int vendor_cmd_test_avail:1;
unsigned int roaming_vendor_cmd_avail:1;
unsigned int dfs_vendor_cmd_avail:1;
unsigned int have_low_prio_scan:1;
@@ -143,6 +144,7 @@
unsigned int addr_changed:1;
unsigned int get_features_vendor_cmd_avail:1;
unsigned int set_rekey_offload:1;
+ unsigned int p2p_go_ctwindow_supported:1;
u64 remain_on_chan_cookie;
u64 send_action_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 36c8ce2..e0d1d23 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -71,6 +71,7 @@
unsigned int connect_supported:1;
unsigned int p2p_go_supported:1;
unsigned int p2p_client_supported:1;
+ unsigned int p2p_go_ctwindow_supported:1;
unsigned int p2p_concurrent:1;
unsigned int channel_switch_supported:1;
unsigned int set_qos_map_supported:1;
@@ -365,6 +366,9 @@
capa->flags |= WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH;
}
+ if (flags & NL80211_FEATURE_P2P_GO_CTWIN)
+ info->p2p_go_ctwindow_supported = 1;
+
if (flags & NL80211_FEATURE_LOW_PRIORITY_SCAN)
info->have_low_prio_scan = 1;
@@ -544,6 +548,9 @@
}
vinfo = nla_data(nl);
switch (vinfo->subcmd) {
+ case QCA_NL80211_VENDOR_SUBCMD_TEST:
+ drv->vendor_cmd_test_avail = 1;
+ break;
case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
drv->roaming_vendor_cmd_avail = 1;
break;
@@ -824,6 +831,7 @@
drv->device_ap_sme = info.device_ap_sme;
drv->poll_command_supported = info.poll_command_supported;
drv->data_tx_status = info.data_tx_status;
+ drv->p2p_go_ctwindow_supported = info.p2p_go_ctwindow_supported;
if (info.set_qos_map_supported)
drv->capa.flags |= WPA_DRIVER_FLAGS_QOS_MAPPING;
drv->have_low_prio_scan = info.have_low_prio_scan;
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index d555033..6a7b509 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -1535,6 +1535,9 @@
u32 subcmd, u8 *data, size_t len)
{
switch (subcmd) {
+ case QCA_NL80211_VENDOR_SUBCMD_TEST:
+ wpa_hexdump(MSG_DEBUG, "nl80211: QCA test event", data, len);
+ break;
case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY:
qca_nl80211_avoid_freq(drv, data, len);
break;
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index ab392bc..9434078 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -39,7 +39,13 @@
ifdef CONFIG_LIBNL32
DRV_LIBS += -lnl-3
DRV_LIBS += -lnl-genl-3
- DRV_CFLAGS += -DCONFIG_LIBNL20 -I/usr/include/libnl3
+ DRV_CFLAGS += -DCONFIG_LIBNL20
+ ifdef LIBNL_INC
+ DRV_CFLAGS += -I$(LIBNL_INC)
+ else
+ PKG_CONFIG ?= pkg-config
+ DRV_CFLAGS += $(shell $(PKG_CONFIG) --cflags libnl-3.0)
+ endif
ifdef CONFIG_LIBNL3_ROUTE
DRV_LIBS += -lnl-route-3
DRV_CFLAGS += -DCONFIG_LIBNL3_ROUTE
diff --git a/src/l2_packet/l2_packet_linux.c b/src/l2_packet/l2_packet_linux.c
index 68b2008..41de2f8 100644
--- a/src/l2_packet/l2_packet_linux.c
+++ b/src/l2_packet/l2_packet_linux.c
@@ -14,6 +14,8 @@
#include "common.h"
#include "eloop.h"
+#include "crypto/sha1.h"
+#include "crypto/crypto.h"
#include "l2_packet.h"
@@ -30,6 +32,9 @@
/* For working around Linux packet socket behavior and regression. */
int fd_br_rx;
+ int last_from_br;
+ u8 last_hash[SHA1_MAC_LEN];
+ unsigned int num_rx, num_rx_br;
};
/* Generated by 'sudo tcpdump -s 3000 -dd greater 278 and ip and udp and
@@ -122,6 +127,7 @@
struct sockaddr_ll ll;
socklen_t fromlen;
+ l2->num_rx++;
os_memset(&ll, 0, sizeof(ll));
fromlen = sizeof(ll);
res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
@@ -132,15 +138,42 @@
return;
}
- l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
+ wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d",
+ __func__, MAC2STR(ll.sll_addr), (int) res);
if (l2->fd_br_rx >= 0) {
- wpa_printf(MSG_DEBUG, "l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket",
- l2->ifname);
- eloop_unregister_read_sock(l2->fd_br_rx);
- close(l2->fd_br_rx);
- l2->fd_br_rx = -1;
+ u8 hash[SHA1_MAC_LEN];
+ const u8 *addr[1];
+ size_t len[1];
+
+ /*
+ * Close the workaround socket if the kernel version seems to be
+ * able to deliver packets through the packet socket before
+ * authorization has been completed (in dormant state).
+ */
+ if (l2->num_rx_br <= 1) {
+ wpa_printf(MSG_DEBUG,
+ "l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket",
+ l2->ifname);
+ eloop_unregister_read_sock(l2->fd_br_rx);
+ close(l2->fd_br_rx);
+ l2->fd_br_rx = -1;
+ }
+
+ addr[0] = buf;
+ len[0] = res;
+ sha1_vector(1, addr, len, hash);
+ if (l2->last_from_br &&
+ os_memcmp(hash, l2->last_hash, SHA1_MAC_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX",
+ __func__);
+ return;
+ }
+ os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
}
+
+ l2->last_from_br = 0;
+ l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
}
@@ -151,7 +184,11 @@
int res;
struct sockaddr_ll ll;
socklen_t fromlen;
+ u8 hash[SHA1_MAC_LEN];
+ const u8 *addr[1];
+ size_t len[1];
+ l2->num_rx_br++;
os_memset(&ll, 0, sizeof(ll));
fromlen = sizeof(ll);
res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
@@ -162,6 +199,19 @@
return;
}
+ wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d",
+ __func__, MAC2STR(ll.sll_addr), (int) res);
+
+ addr[0] = buf;
+ len[0] = res;
+ sha1_vector(1, addr, len, hash);
+ if (!l2->last_from_br &&
+ os_memcmp(hash, l2->last_hash, SHA1_MAC_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", __func__);
+ return;
+ }
+ l2->last_from_br = 1;
+ os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
}
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 602aa36..d9f97ed 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1279,6 +1279,7 @@
p2p->sd_peer = NULL;
p2p->invite_peer = NULL;
p2p_stop_listen_for_freq(p2p, freq);
+ p2p->send_action_in_progress = 0;
}
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 10413ed..c1d7749 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -939,10 +939,15 @@
" (reason code %u)", MAC2STR(src_addr), reason_code);
ielen = len - (pos - buf); /* start of IE in buf */
- if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
- wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in Teardown");
- return -1;
- }
+
+ /*
+ * Don't reject the message if failing to parse IEs. The IEs we need are
+ * explicitly checked below. Some APs may add arbitrary padding to the
+ * end of short TDLS frames and that would look like invalid IEs.
+ */
+ if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0)
+ wpa_printf(MSG_DEBUG,
+ "TDLS: Failed to parse IEs in Teardown - ignore as an interop workaround");
if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS "
@@ -1823,10 +1828,15 @@
cpos += 2;
ielen = len - (cpos - buf); /* start of IE in buf */
- if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) {
- wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M1");
- goto error;
- }
+
+ /*
+ * Don't reject the message if failing to parse IEs. The IEs we need are
+ * explicitly checked below. Some APs may add arbitrary padding to the
+ * end of short TDLS frames and that would look like invalid IEs.
+ */
+ if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0)
+ wpa_printf(MSG_DEBUG,
+ "TDLS: Failed to parse IEs in TPK M1 - ignore as an interop workaround");
if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
@@ -2199,10 +2209,15 @@
pos += 2;
ielen = len - (pos - buf); /* start of IE in buf */
- if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) {
- wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M2");
- goto error;
- }
+
+ /*
+ * Don't reject the message if failing to parse IEs. The IEs we need are
+ * explicitly checked below. Some APs may add arbitrary padding to the
+ * end of short TDLS frames and that would look like invalid IEs.
+ */
+ if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0)
+ wpa_printf(MSG_DEBUG,
+ "TDLS: Failed to parse IEs in TPK M2 - ignore as an interop workaround");
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_DECLINE_RESP) {
diff --git a/src/utils/http_curl.c b/src/utils/http_curl.c
index 0c18269..b38cf79 100644
--- a/src/utils/http_curl.c
+++ b/src/utils/http_curl.c
@@ -1084,7 +1084,7 @@
if (X509_STORE_add_cert(store, ctx->peer_issuer) != 1) {
tls_show_errors(__func__,
- "OpenSSL: Could not add issuer to certificate store\n");
+ "OpenSSL: Could not add issuer to certificate store");
}
certs = sk_X509_new_null();
if (certs) {
@@ -1093,17 +1093,17 @@
if (cert && !sk_X509_push(certs, cert)) {
tls_show_errors(
__func__,
- "OpenSSL: Could not add issuer to OCSP responder trust store\n");
+ "OpenSSL: Could not add issuer to OCSP responder trust store");
X509_free(cert);
sk_X509_free(certs);
certs = NULL;
}
- if (ctx->peer_issuer_issuer) {
+ if (certs && ctx->peer_issuer_issuer) {
cert = X509_dup(ctx->peer_issuer_issuer);
if (cert && !sk_X509_push(certs, cert)) {
tls_show_errors(
__func__,
- "OpenSSL: Could not add issuer to OCSP responder trust store\n");
+ "OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
X509_free(cert);
}
}
diff --git a/src/utils/list.h b/src/utils/list.h
index 6881130..ee2f485 100644
--- a/src/utils/list.h
+++ b/src/utils/list.h
@@ -17,6 +17,8 @@
struct dl_list *prev;
};
+#define DL_LIST_HEAD_INIT(l) { &(l), &(l) }
+
static inline void dl_list_init(struct dl_list *list)
{
list->next = list;
diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c
index 86fbd0a..e0c1125 100644
--- a/src/utils/os_unix.c
+++ b/src/utils/os_unix.c
@@ -26,7 +26,7 @@
#include "trace.h"
#include "list.h"
-static struct dl_list alloc_list;
+static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
#define ALLOC_MAGIC 0xa84ef1b2
#define FREED_MAGIC 0x67fd487a
@@ -321,9 +321,6 @@
capset(&header, &cap);
#endif /* ANDROID */
-#ifdef WPA_TRACE
- dl_list_init(&alloc_list);
-#endif /* WPA_TRACE */
return 0;
}