Exemple #1
0
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;
	}
}
Exemple #2
0
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);
}
Exemple #3
0
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");
	}
}