diff --git a/hostapd/config_file.c b/hostapd/config_file.c index b7d1f2f14..b6f1d1b99 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2486,6 +2486,13 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->channel = 0; } else conf->channel = atoi(pos); + } else if (os_strcmp(buf, "chanlist") == 0) { + if (hostapd_parse_intlist(&conf->chanlist, pos)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid channel list", + line); + errors++; + } } 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 c745fe83b..7ea186e8b 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -154,6 +154,14 @@ channel=1 # Defaults: #acs_num_scans=5 +# Channel list restriction. This option allows hostapd to select one of the +# provided channels when a channel should be automatically selected. This +# is currently only used for DFS when the current channels becomes unavailable +# due to radar interference, and is currently only useful when ieee80211h=1 is +# set. +# Default: not set (allow any enabled channel to be selected) +#chanlist=100 104 108 112 116 + # Beacon interval in kus (1.024 ms) (default: 100; range 15..65535) beacon_int=100 diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 5252cbaab..3ca85a0fa 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -562,6 +562,7 @@ void hostapd_config_free(struct hostapd_config *conf) os_free(conf->bss); os_free(conf->supported_rates); os_free(conf->basic_rates); + os_free(conf->chanlist); os_free(conf); } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 638a21c97..aa3a51aee 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -525,6 +525,7 @@ struct hostapd_config { int fragm_threshold; u8 send_probe_response; u8 channel; + int *chanlist; enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ enum { LONG_PREAMBLE = 0, diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 92eda2167..590a03acf 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -139,6 +139,22 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode, } +static int is_in_chanlist(struct hostapd_iface *iface, + struct hostapd_channel_data *chan) +{ + int *entry; + + if (!iface->conf->chanlist) + return 1; + + for (entry = iface->conf->chanlist; *entry != -1; entry++) { + if (*entry == chan->chan) + return 1; + } + return 0; +} + + /* * The function assumes HT40+ operation. * Make sure to adjust the following variables after calling this: @@ -171,6 +187,9 @@ static int dfs_find_channel(struct hostapd_iface *iface, if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) continue; + if (!is_in_chanlist(iface, chan)) + continue; + if (ret_chan && idx == channel_idx) { wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan); *ret_chan = chan;