From 6a398ddc9ae2a4f2d60abebaacce083d264270b5 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 31 Oct 2013 14:48:34 +0200 Subject: [PATCH] DFS: Sanitize channel availability checks Fixes corner case of holes in channel list and simplifies availability checks. Signed-hostap: Michal Kazior --- src/ap/dfs.c | 52 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 6a16306c5..736f2344d 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -94,6 +94,31 @@ static int dfs_is_chan_allowed(struct hostapd_channel_data *chan, int n_chans) } +static int dfs_chan_range_available(struct hostapd_hw_modes *mode, + int first_chan_idx, int num_chans) +{ + struct hostapd_channel_data *first_chan, *chan; + int i; + + if (first_chan_idx + num_chans >= mode->num_channels) + return 0; + + first_chan = &mode->channels[first_chan_idx]; + + for (i = 0; i < num_chans; i++) { + chan = &mode->channels[first_chan_idx + i]; + + if (first_chan->freq + i * 20 != chan->freq) + return 0; + + if (!dfs_channel_available(chan)) + return 0; + } + + return 1; +} + + /* * The function assumes HT40+ operation. * Make sure to adjust the following variables after calling this: @@ -106,8 +131,8 @@ static int dfs_find_channel(struct hostapd_data *hapd, int idx) { struct hostapd_hw_modes *mode; - struct hostapd_channel_data *chan, *next_chan; - int i, j, channel_idx = 0, n_chans; + struct hostapd_channel_data *chan; + int i, channel_idx = 0, n_chans; mode = hapd->iface->current_mode; n_chans = dfs_get_used_n_chans(hapd); @@ -116,24 +141,15 @@ static int dfs_find_channel(struct hostapd_data *hapd, for (i = 0; i < mode->num_channels; i++) { chan = &mode->channels[i]; - /* Skip not available channels */ - if (!dfs_channel_available(chan)) + /* Skip HT40/VHT incompatible channels */ + if (hapd->iconf->ieee80211n && + hapd->iconf->secondary_channel && + !dfs_is_chan_allowed(chan, n_chans)) continue; - /* Skip HT40/VHT uncompatible channels */ - if (hapd->iconf->ieee80211n && - hapd->iconf->secondary_channel) { - if (!dfs_is_chan_allowed(chan, n_chans)) - continue; - - for (j = 1; j < n_chans; j++) { - next_chan = &mode->channels[i + j]; - if (!dfs_channel_available(next_chan)) - break; - } - if (j != n_chans) - continue; - } + /* Skip incompatible chandefs */ + if (!dfs_chan_range_available(mode, i, n_chans)) + continue; if (ret_chan && idx == channel_idx) { wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan);