static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, struct wpa_driver_scan_params *params) { /* Scan only the affected frequency range */ int pri_freq, sec_freq; int affected_start, affected_end; int i, pos; struct hostapd_hw_modes *mode; if (iface->current_mode == NULL) return; pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); if (iface->conf->secondary_channel > 0) sec_freq = pri_freq + 20; else sec_freq = pri_freq - 20; /* * Note: Need to find the PRI channel also in cases where the affected * channel is the SEC channel of a 40 MHz BSS, so need to include the * scanning coverage here to be 40 MHz from the center frequency. */ affected_start = (pri_freq + sec_freq) / 2 - 40; affected_end = (pri_freq + sec_freq) / 2 + 40; wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", affected_start, affected_end); mode = iface->current_mode; params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); if (params->freqs == NULL) return; pos = 0; for (i = 0; i < mode->num_channels; i++) { struct hostapd_channel_data *chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; if (chan->freq < affected_start || chan->freq > affected_end) continue; params->freqs[pos++] = chan->freq; } }
int hostapd_acs_completed(struct hostapd_iface *iface, int err) { int ret = -1; if (err) goto out; switch (hostapd_check_chans(iface)) { case HOSTAPD_CHAN_VALID: wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_COMPLETED "freq=%d channel=%d", hostapd_hw_get_freq(iface->bss[0], iface->conf->channel), iface->conf->channel); break; case HOSTAPD_CHAN_ACS: wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); hostapd_notify_bad_chans(iface); goto out; case HOSTAPD_CHAN_INVALID: default: wpa_printf(MSG_ERROR, "ACS picked unusable channels"); wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); hostapd_notify_bad_chans(iface); goto out; } ret = hostapd_check_ht_capab(iface); if (ret < 0) goto out; if (ret == 1) { wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); return 0; } ret = 0; out: return hostapd_setup_interface_complete(iface, ret); }
static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, struct wpa_driver_scan_params *params) { /* Scan only the affected frequency range */ int pri_freq; int affected_start, affected_end; int i, pos; struct hostapd_hw_modes *mode; if (iface->current_mode == NULL) { return; } pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); if (iface->conf->secondary_channel > 0) { affected_start = pri_freq - 10; affected_end = pri_freq + 30; } else { affected_start = pri_freq - 30; affected_end = pri_freq + 10; } wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", affected_start, affected_end); mode = iface->current_mode; params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); if (params->freqs == NULL) { return; } pos = 0; for (i = 0; i < mode->num_channels; i++) { struct hostapd_channel_data *chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_DISABLED) { continue; } if (chan->freq < affected_start || chan->freq > affected_end) { continue; } params->freqs[pos++] = chan->freq; } }
static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, struct wpa_driver_scan_params *params) { /* Scan only the affected frequency range */ int pri_freq, sec_freq; int affected_start, affected_end; int i, pos; struct hostapd_hw_modes *mode; if (iface->current_mode == NULL) return; pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); if (iface->conf->secondary_channel > 0) sec_freq = pri_freq + 20; else sec_freq = pri_freq - 20; affected_start = (pri_freq + sec_freq) / 2 - 25; affected_end = (pri_freq + sec_freq) / 2 + 25; wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", affected_start, affected_end); mode = iface->current_mode; params->freqs = os_zalloc((mode->num_channels + 1) * sizeof(int)); if (params->freqs == NULL) return; pos = 0; for (i = 0; i < mode->num_channels; i++) { struct hostapd_channel_data *chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; if (chan->freq < affected_start || chan->freq > affected_end) continue; params->freqs[pos++] = chan->freq; } }
static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, struct wpa_scan_results *scan_res) { int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss; int bss_pri_chan, bss_sec_chan; size_t i; int match; pri_chan = iface->conf->channel; sec_chan = iface->conf->secondary_channel * 4; pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan); if (iface->conf->secondary_channel > 0) sec_freq = pri_freq + 20; else sec_freq = pri_freq - 20; /* * Switch PRI/SEC channels if Beacons were detected on selected SEC * channel, but not on selected PRI channel. */ pri_bss = sec_bss = 0; for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; if (bss->freq == pri_freq) pri_bss++; else if (bss->freq == sec_freq) sec_bss++; } if (sec_bss && !pri_bss) { wpa_printf(MSG_INFO, "Switch own primary and secondary " "channel to get secondary channel with no Beacons " "from other BSSes"); ieee80211n_switch_pri_sec(iface); } /* * Match PRI/SEC channel with any existing HT40 BSS on the same * channels that we are about to use (if already mixed order in * existing BSSes, use own preference). */ match = 0; for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); if (pri_chan == bss_pri_chan && sec_chan == bss_sec_chan) { match = 1; break; } } if (!match) { for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *bss = scan_res->res[i]; ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); if (pri_chan == bss_sec_chan && sec_chan == bss_pri_chan) { wpa_printf(MSG_INFO, "Switch own primary and " "secondary channel due to BSS " "overlap with " MACSTR, MAC2STR(bss->bssid)); ieee80211n_switch_pri_sec(iface); break; } } } return 1; }
void hostapd_acs_channel_selected(struct hostapd_data *hapd, struct acs_selected_channels *acs_res) { int ret, i; int err = 0; if (hapd->iconf->channel) { wpa_printf(MSG_INFO, "ACS: Channel was already set to %d", hapd->iconf->channel); return; } if (!hapd->iface->current_mode) { for (i = 0; i < hapd->iface->num_hw_features; i++) { struct hostapd_hw_modes *mode = &hapd->iface->hw_features[i]; if (mode->mode == acs_res->hw_mode) { hapd->iface->current_mode = mode; break; } } if (!hapd->iface->current_mode) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_WARNING, "driver selected to bad hw_mode"); err = 1; goto out; } } hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel); if (!acs_res->pri_channel) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_WARNING, "driver switched to bad channel"); err = 1; goto out; } hapd->iconf->channel = acs_res->pri_channel; hapd->iconf->acs = 1; if (acs_res->sec_channel == 0) hapd->iconf->secondary_channel = 0; else if (acs_res->sec_channel < acs_res->pri_channel) hapd->iconf->secondary_channel = -1; else if (acs_res->sec_channel > acs_res->pri_channel) hapd->iconf->secondary_channel = 1; else { wpa_printf(MSG_ERROR, "Invalid secondary channel!"); err = 1; goto out; } if (hapd->iface->conf->ieee80211ac) { /* set defaults for backwards compatibility */ hapd->iconf->vht_oper_centr_freq_seg1_idx = 0; hapd->iconf->vht_oper_centr_freq_seg0_idx = 0; hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; if (acs_res->ch_width == 80) { hapd->iconf->vht_oper_centr_freq_seg0_idx = acs_res->vht_seg0_center_ch; hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ; } else if (acs_res->ch_width == 160) { if (acs_res->vht_seg1_center_ch == 0) { hapd->iconf->vht_oper_centr_freq_seg0_idx = acs_res->vht_seg0_center_ch; hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ; } else { hapd->iconf->vht_oper_centr_freq_seg0_idx = acs_res->vht_seg0_center_ch; hapd->iconf->vht_oper_centr_freq_seg1_idx = acs_res->vht_seg1_center_ch; hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80P80MHZ; } } } out: ret = hostapd_acs_completed(hapd->iface, err); if (ret) { wpa_printf(MSG_ERROR, "ACS: Possibly channel configuration is invalid"); } }