diff options
| author | Dmitry Shmidt <dimitrysh@google.com> | 2015-02-25 14:36:37 -0800 |
|---|---|---|
| committer | Dmitry Shmidt <dimitrysh@google.com> | 2015-03-10 11:04:32 -0700 |
| commit | 7f65602d49069f96a7bb44da8bd79ffe8d4c6a98 (patch) | |
| tree | 0f5470742861a3ea4efb80552c3f8282fb79092c /src/ap | |
| parent | 912d96b4e283c9bc0633a065901153bf74e1f911 (diff) | |
| download | android_external_wpa_supplicant_8-7f65602d49069f96a7bb44da8bd79ffe8d4c6a98.tar.gz android_external_wpa_supplicant_8-7f65602d49069f96a7bb44da8bd79ffe8d4c6a98.tar.bz2 android_external_wpa_supplicant_8-7f65602d49069f96a7bb44da8bd79ffe8d4c6a98.zip | |
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>
Diffstat (limited to 'src/ap')
| -rw-r--r-- | src/ap/acs.c | 145 | ||||
| -rw-r--r-- | src/ap/ap_config.c | 24 | ||||
| -rw-r--r-- | src/ap/ap_config.h | 10 | ||||
| -rw-r--r-- | src/ap/ap_drv_ops.c | 87 | ||||
| -rw-r--r-- | src/ap/ap_drv_ops.h | 13 | ||||
| -rw-r--r-- | src/ap/beacon.c | 27 | ||||
| -rw-r--r-- | src/ap/ctrl_iface_ap.c | 6 | ||||
| -rw-r--r-- | src/ap/ctrl_iface_ap.h | 2 | ||||
| -rw-r--r-- | src/ap/dfs.c | 1 | ||||
| -rw-r--r-- | src/ap/drv_callbacks.c | 12 | ||||
| -rw-r--r-- | src/ap/hostapd.c | 8 | ||||
| -rw-r--r-- | src/ap/hostapd.h | 2 | ||||
| -rw-r--r-- | src/ap/sta_info.c | 6 | ||||
| -rw-r--r-- | src/ap/vlan_init.c | 37 | ||||
| -rw-r--r-- | src/ap/wpa_auth.c | 11 | ||||
| -rw-r--r-- | src/ap/wpa_auth.h | 1 | ||||
| -rw-r--r-- | src/ap/wps_hostapd.c | 5 |
17 files changed, 249 insertions, 148 deletions
diff --git a/src/ap/acs.c b/src/ap/acs.c index e4c834ce..ae7f6c30 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 @@ acs_survey_chan_interference_factor(struct hostapd_iface *iface, 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 @@ acs_survey_chan_interference_factor(struct hostapd_iface *iface, 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_usable_vht80_chan(struct hostapd_channel_data *chan) 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_is_sufficient(struct freq_survey *survey) 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 struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, } +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 @@ acs_find_ideal_chan(struct hostapd_iface *iface) long double factor, ideal_factor = 0; int i, j; int n_chans = 1; + unsigned int k; /* TODO: HT40- support */ @@ -557,6 +609,9 @@ acs_find_ideal_chan(struct hostapd_iface *iface) -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 @@ acs_find_ideal_chan(struct hostapd_iface *iface) 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 @@ acs_find_ideal_chan(struct hostapd_iface *iface) /* 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; + } + } + } + + 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; } - wpa_printf(MSG_DEBUG, "ACS: * channel %d: total interference = %Lg", - chan->chan, factor); + 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 1c0ed7aa..76011dc0 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -394,20 +394,27 @@ static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) } +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 @@ void hostapd_config_free(struct hostapd_config *conf) 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 e5215c52..961d2dd3 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -629,6 +629,10 @@ struct hostapd_config { 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 @@ struct hostapd_config { #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 @@ int hostapd_mac_comp_empty(const void *a); 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 8514cbe7..e16306c4 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_flush(struct hostapd_data *hapd) } -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 c133be75..5d07e71f 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -107,12 +107,6 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, 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 @@ static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd, 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 b0a74e01..e575b65c 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 @@ void handle_probe_req(struct hostapd_data *hapd, 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 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, 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 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd) 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 8c84e3ef..41ab9882 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -537,3 +537,9 @@ int hostapd_parse_csa_settings(const char *pos, 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 ee58b4c9..e5297d03 100644 --- a/src/ap/ctrl_iface_ap.h +++ b/src/ap/ctrl_iface_ap.h @@ -23,6 +23,6 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, 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 0db5ef69..fc8d7adf 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 40a2a9c7..c39989c3 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1210,9 +1210,21 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, #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 b641503c..e641b129 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -82,8 +82,7 @@ static void hostapd_reload_bss(struct hostapd_data *hapd) * 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(struct hostapd_data *hapd) 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 8e2c70ec..75cc24ed 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -105,6 +105,8 @@ struct hostapd_data { 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 eebaa3ce..7e75e1a6 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -375,8 +375,9 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) "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 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) 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 2af2cbce..dc650199 100644 --- a/src/ap/vlan_init.c +++ b/src/ap/vlan_init.c @@ -617,6 +617,7 @@ vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, 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 @@ vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, 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 @@ static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) } 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 @@ static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) 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 668cb429..9c5f6094 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3387,3 +3387,14 @@ int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth, { 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 b34b84dd..2788e657 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -318,5 +318,6 @@ int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr); 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 9ba7aba8..b0e8b0bf 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -362,10 +362,9 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, 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 && |
