diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 57ccbc6e9..82ac61d77 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3406,6 +3406,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) { os_free(bss->no_probe_resp_if_seen_on); bss->no_probe_resp_if_seen_on = os_strdup(pos); + } else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) { + os_free(bss->no_auth_if_seen_on); + bss->no_auth_if_seen_on = os_strdup(pos); } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 43e81caea..a0071f7d8 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1304,6 +1304,19 @@ own_ip_addr=127.0.0.1 # discovering the AP. #no_probe_resp_if_seen_on=wlan1 +# Reject authentication from a station that was seen on another radio. +# Default: Disabled +# +# This can be used with enabled track_sta_max_num configuration on another +# interface controlled by the same hostapd process to reject authentication +# attempts from a station that has been detected to be capable of operating on +# another band, e.g., to try to reduce likelihood of the station selecting a +# 2.4 GHz BSS when the AP operates both a 2.4 GHz and 5 GHz BSS concurrently. +# +# Note: Enabling this can cause connectivity issues and increase latency for +# connecting with the AP. +#no_auth_if_seen_on=wlan1 + ##### Wi-Fi Protected Setup (WPS) ############################################# # WPS state diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 96f86517c..75804a069 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -567,6 +567,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) #endif /* CONFIG_TESTING_OPTIONS */ os_free(conf->no_probe_resp_if_seen_on); + os_free(conf->no_auth_if_seen_on); os_free(conf); } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index d821f273b..5e83cdc3f 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -556,6 +556,7 @@ struct hostapd_bss_config { int vendor_vht; char *no_probe_resp_if_seen_on; + char *no_auth_if_seen_on; }; diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 651ee744b..85c6ef3cf 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -622,26 +622,29 @@ static void sta_track_add(struct hostapd_iface *iface, const u8 *addr) } -static int sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr, - const char *ifname) +struct hostapd_data * +sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr, + const char *ifname) { struct hapd_interfaces *interfaces = iface->interfaces; size_t i, j; for (i = 0; i < interfaces->count; i++) { + struct hostapd_data *hapd = NULL; + iface = interfaces->iface[i]; for (j = 0; j < iface->num_bss; j++) { - struct hostapd_data *hapd = iface->bss[j]; - + hapd = iface->bss[j]; if (os_strcmp(ifname, hapd->conf->iface) == 0) break; + hapd = NULL; } - if (j < iface->num_bss && sta_track_get(iface, addr)) - return 1; + if (hapd && sta_track_get(iface, addr)) + return hapd; } - return 0; + return NULL; } diff --git a/src/ap/beacon.h b/src/ap/beacon.h index 21df9fae8..e183cde25 100644 --- a/src/ap/beacon.h +++ b/src/ap/beacon.h @@ -22,5 +22,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, struct wpa_driver_ap_params *params); void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params); void sta_track_expire(struct hostapd_iface *iface, int force); +struct hostapd_data * +sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr, + const char *ifname); #endif /* BEACON_H */ diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 2a3041108..78355d660 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -39,6 +39,7 @@ #include "p2p_hostapd.h" #include "ap_drv_ops.h" #include "wnm_ap.h" +#include "hw_features.h" #include "ieee802_11.h" #include "dfs.h" @@ -977,6 +978,61 @@ static void handle_auth(struct hostapd_data *hapd, goto fail; } + if (hapd->conf->no_auth_if_seen_on) { + struct hostapd_data *other; + + other = sta_track_seen_on(hapd->iface, mgmt->sa, + hapd->conf->no_auth_if_seen_on); + if (other) { + u8 *pos; + u32 info; + u8 op_class, channel, phytype; + + wpa_printf(MSG_DEBUG, "%s: Reject authentication from " + MACSTR " since STA has been seen on %s", + hapd->conf->iface, MAC2STR(mgmt->sa), + hapd->conf->no_auth_if_seen_on); + + resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION; + pos = &resp_ies[0]; + *pos++ = WLAN_EID_NEIGHBOR_REPORT; + *pos++ = 13; + os_memcpy(pos, other->own_addr, ETH_ALEN); + pos += ETH_ALEN; + info = 0; /* TODO: BSSID Information */ + WPA_PUT_LE32(pos, info); + pos += 4; + if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD) + phytype = 8; /* dmg */ + else if (other->iconf->ieee80211ac) + phytype = 9; /* vht */ + else if (other->iconf->ieee80211n) + phytype = 7; /* ht */ + else if (other->iconf->hw_mode == + HOSTAPD_MODE_IEEE80211A) + phytype = 4; /* ofdm */ + else if (other->iconf->hw_mode == + HOSTAPD_MODE_IEEE80211G) + phytype = 6; /* erp */ + else + phytype = 5; /* hrdsss */ + if (ieee80211_freq_to_channel_ext( + hostapd_hw_get_freq(other, + other->iconf->channel), + other->iconf->secondary_channel, + other->iconf->ieee80211ac, + &op_class, &channel) == NUM_HOSTAPD_MODES) { + op_class = 0; + channel = other->iconf->channel; + } + *pos++ = op_class; + *pos++ = channel; + *pos++ = phytype; + resp_ies_len = pos - &resp_ies[0]; + goto fail; + } + } + res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, &session_timeout, &acct_interim_interval, &vlan_id, diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 5ac69e647..44530ce3c 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -165,6 +165,7 @@ #define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76 #define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77 #define WLAN_STATUS_TRANSMISSION_FAILURE 79 +#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION 82 #define WLAN_STATUS_PENDING_ADMITTING_FST_SESSION 86 #define WLAN_STATUS_QUERY_RESP_OUTSTANDING 95 #define WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL 99