diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 25dc1fade..e489ec706 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3162,6 +3162,13 @@ static int hostapd_config_fill(struct hostapd_config *conf, line); return 1; } + } else if (os_strcmp(buf, "freqlist") == 0) { + if (freq_range_list_parse(&conf->acs_freq_list, pos)) { + wpa_printf(MSG_ERROR, "Line %d: invalid frequency list", + line); + return 1; + } + conf->acs_freq_list_present = 1; } else if (os_strcmp(buf, "beacon_int") == 0) { int val = atoi(pos); /* MIB defines range as 1..65535, but very small values diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 4cbe45190..591386311 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -205,6 +205,14 @@ channel=1 #chanlist=100 104 108 112 116 #chanlist=1 6 11-13 +# Frequency list restriction. This option allows hostapd to select one of the +# provided frequencies when a frequency should be automatically selected. +# Frequency list can be provided as range using hyphen ('-') or individual +# frequencies can be specified by comma (',') separated values +# Default: all frequencies allowed in selected hw_mode +#freqlist=2437,5945,5965 +#freqlist=2437,5985-6105 + # Exclude DFS channels from ACS # This option can be used to exclude all DFS channels from the ACS channel list # in cases where the driver supports DFS channels. diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 70829679d..68af3c1d1 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -936,6 +936,7 @@ void hostapd_config_free(struct hostapd_config *conf) os_free(conf->supported_rates); os_free(conf->basic_rates); os_free(conf->acs_ch_list.range); + os_free(conf->acs_freq_list.range); os_free(conf->driver_params); #ifdef CONFIG_ACS os_free(conf->acs_chan_bias); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 23416c6eb..a3b9b5d50 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -882,6 +882,8 @@ struct hostapd_config { u8 edmg_channel; u8 acs; struct wpa_freq_range_list acs_ch_list; + struct wpa_freq_range_list acs_freq_list; + u8 acs_freq_list_present; int acs_exclude_dfs; enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ enum { diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 991e9ad62..bcacf8cc3 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/ieee802_11_common.h" #include "common/hw_features_common.h" #include "wps/wps.h" #include "p2p/p2p.h" @@ -855,10 +856,20 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, for (i = 0; i < mode->num_channels; i++) { struct hostapd_channel_data *chan = &mode->channels[i]; - if ((acs_ch_list_all || - freq_range_list_includes(&hapd->iface->conf->acs_ch_list, - chan->chan)) && - !(chan->flag & HOSTAPD_CHAN_DISABLED) && + if (!acs_ch_list_all && + (hapd->iface->conf->acs_freq_list.num && + !freq_range_list_includes( + &hapd->iface->conf->acs_freq_list, + chan->freq))) + continue; + if (!acs_ch_list_all && + (!hapd->iface->conf->acs_freq_list_present && + hapd->iface->conf->acs_ch_list.num && + !freq_range_list_includes( + &hapd->iface->conf->acs_ch_list, + chan->chan))) + continue; + if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && !(hapd->iface->conf->acs_exclude_dfs && (chan->flag & HOSTAPD_CHAN_RADAR))) int_array_add_unique(freq_list, chan->freq); @@ -898,8 +909,10 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd) * If no chanlist config parameter is provided, include all enabled * channels of the selected hw_mode. */ - if (!hapd->iface->conf->acs_ch_list.num) - acs_ch_list_all = 1; + if (hapd->iface->conf->acs_freq_list_present) + acs_ch_list_all = !hapd->iface->conf->acs_freq_list.num; + else + acs_ch_list_all = !hapd->iface->conf->acs_ch_list.num; if (hapd->iface->current_mode) selected_mode = hapd->iface->current_mode->mode;