Home | History | Annotate | Download | only in ap
      1 /*
      2  * hostapd / Hardware feature query and different modes
      3  * Copyright 2002-2003, Instant802 Networks, Inc.
      4  * Copyright 2005-2006, Devicescape Software, Inc.
      5  * Copyright (c) 2008-2012, Jouni Malinen <j (at) w1.fi>
      6  *
      7  * This software may be distributed under the terms of the BSD license.
      8  * See README for more details.
      9  */
     10 
     11 #include "utils/includes.h"
     12 
     13 #include "utils/common.h"
     14 #include "utils/eloop.h"
     15 #include "common/ieee802_11_defs.h"
     16 #include "common/ieee802_11_common.h"
     17 #include "common/wpa_ctrl.h"
     18 #include "hostapd.h"
     19 #include "ap_config.h"
     20 #include "ap_drv_ops.h"
     21 #include "acs.h"
     22 #include "ieee802_11.h"
     23 #include "beacon.h"
     24 #include "hw_features.h"
     25 
     26 
     27 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
     28 			      size_t num_hw_features)
     29 {
     30 	size_t i;
     31 
     32 	if (hw_features == NULL)
     33 		return;
     34 
     35 	for (i = 0; i < num_hw_features; i++) {
     36 		os_free(hw_features[i].channels);
     37 		os_free(hw_features[i].rates);
     38 	}
     39 
     40 	os_free(hw_features);
     41 }
     42 
     43 
     44 #ifndef CONFIG_NO_STDOUT_DEBUG
     45 static char * dfs_info(struct hostapd_channel_data *chan)
     46 {
     47 	static char info[256];
     48 	char *state;
     49 
     50 	switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) {
     51 	case HOSTAPD_CHAN_DFS_UNKNOWN:
     52 		state = "unknown";
     53 		break;
     54 	case HOSTAPD_CHAN_DFS_USABLE:
     55 		state = "usable";
     56 		break;
     57 	case HOSTAPD_CHAN_DFS_UNAVAILABLE:
     58 		state = "unavailable";
     59 		break;
     60 	case HOSTAPD_CHAN_DFS_AVAILABLE:
     61 		state = "available";
     62 		break;
     63 	default:
     64 		return "";
     65 	}
     66 	os_snprintf(info, sizeof(info), " (DFS state = %s)", state);
     67 	info[sizeof(info) - 1] = '\0';
     68 
     69 	return info;
     70 }
     71 #endif /* CONFIG_NO_STDOUT_DEBUG */
     72 
     73 
     74 int hostapd_get_hw_features(struct hostapd_iface *iface)
     75 {
     76 	struct hostapd_data *hapd = iface->bss[0];
     77 	int ret = 0, i, j;
     78 	u16 num_modes, flags;
     79 	struct hostapd_hw_modes *modes;
     80 
     81 	if (hostapd_drv_none(hapd))
     82 		return -1;
     83 	modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags);
     84 	if (modes == NULL) {
     85 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
     86 			       HOSTAPD_LEVEL_DEBUG,
     87 			       "Fetching hardware channel/rate support not "
     88 			       "supported.");
     89 		return -1;
     90 	}
     91 
     92 	iface->hw_flags = flags;
     93 
     94 	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
     95 	iface->hw_features = modes;
     96 	iface->num_hw_features = num_modes;
     97 
     98 	for (i = 0; i < num_modes; i++) {
     99 		struct hostapd_hw_modes *feature = &modes[i];
    100 		int dfs_enabled = hapd->iconf->ieee80211h &&
    101 			(iface->drv_flags & WPA_DRIVER_FLAGS_RADAR);
    102 
    103 		/* set flag for channels we can use in current regulatory
    104 		 * domain */
    105 		for (j = 0; j < feature->num_channels; j++) {
    106 			int dfs = 0;
    107 
    108 			/*
    109 			 * Disable all channels that are marked not to allow
    110 			 * IBSS operation or active scanning.
    111 			 * Use radar channels only if the driver supports DFS.
    112 			 */
    113 			if ((feature->channels[j].flag &
    114 			     HOSTAPD_CHAN_RADAR) && dfs_enabled) {
    115 				dfs = 1;
    116 			} else if (((feature->channels[j].flag &
    117 				     HOSTAPD_CHAN_RADAR) &&
    118 				    !(iface->drv_flags &
    119 				      WPA_DRIVER_FLAGS_DFS_OFFLOAD)) ||
    120 				   (feature->channels[j].flag &
    121 				    (HOSTAPD_CHAN_NO_IBSS |
    122 				     HOSTAPD_CHAN_PASSIVE_SCAN))) {
    123 				feature->channels[j].flag |=
    124 					HOSTAPD_CHAN_DISABLED;
    125 			}
    126 
    127 			if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
    128 				continue;
    129 
    130 			wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
    131 				   "chan=%d freq=%d MHz max_tx_power=%d dBm%s",
    132 				   feature->mode,
    133 				   feature->channels[j].chan,
    134 				   feature->channels[j].freq,
    135 				   feature->channels[j].max_tx_power,
    136 				   dfs ? dfs_info(&feature->channels[j]) : "");
    137 		}
    138 	}
    139 
    140 	return ret;
    141 }
    142 
    143 
    144 int hostapd_prepare_rates(struct hostapd_iface *iface,
    145 			  struct hostapd_hw_modes *mode)
    146 {
    147 	int i, num_basic_rates = 0;
    148 	int basic_rates_a[] = { 60, 120, 240, -1 };
    149 	int basic_rates_b[] = { 10, 20, -1 };
    150 	int basic_rates_g[] = { 10, 20, 55, 110, -1 };
    151 	int *basic_rates;
    152 
    153 	if (iface->conf->basic_rates)
    154 		basic_rates = iface->conf->basic_rates;
    155 	else switch (mode->mode) {
    156 	case HOSTAPD_MODE_IEEE80211A:
    157 		basic_rates = basic_rates_a;
    158 		break;
    159 	case HOSTAPD_MODE_IEEE80211B:
    160 		basic_rates = basic_rates_b;
    161 		break;
    162 	case HOSTAPD_MODE_IEEE80211G:
    163 		basic_rates = basic_rates_g;
    164 		break;
    165 	case HOSTAPD_MODE_IEEE80211AD:
    166 		return 0; /* No basic rates for 11ad */
    167 	default:
    168 		return -1;
    169 	}
    170 
    171 	i = 0;
    172 	while (basic_rates[i] >= 0)
    173 		i++;
    174 	if (i)
    175 		i++; /* -1 termination */
    176 	os_free(iface->basic_rates);
    177 	iface->basic_rates = os_malloc(i * sizeof(int));
    178 	if (iface->basic_rates)
    179 		os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
    180 
    181 	os_free(iface->current_rates);
    182 	iface->num_rates = 0;
    183 
    184 	iface->current_rates =
    185 		os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
    186 	if (!iface->current_rates) {
    187 		wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
    188 			   "table.");
    189 		return -1;
    190 	}
    191 
    192 	for (i = 0; i < mode->num_rates; i++) {
    193 		struct hostapd_rate_data *rate;
    194 
    195 		if (iface->conf->supported_rates &&
    196 		    !hostapd_rate_found(iface->conf->supported_rates,
    197 					mode->rates[i]))
    198 			continue;
    199 
    200 		rate = &iface->current_rates[iface->num_rates];
    201 		rate->rate = mode->rates[i];
    202 		if (hostapd_rate_found(basic_rates, rate->rate)) {
    203 			rate->flags |= HOSTAPD_RATE_BASIC;
    204 			num_basic_rates++;
    205 		}
    206 		wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
    207 			   iface->num_rates, rate->rate, rate->flags);
    208 		iface->num_rates++;
    209 	}
    210 
    211 	if ((iface->num_rates == 0 || num_basic_rates == 0) &&
    212 	    (!iface->conf->ieee80211n || !iface->conf->require_ht)) {
    213 		wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
    214 			   "rate sets (%d,%d).",
    215 			   iface->num_rates, num_basic_rates);
    216 		return -1;
    217 	}
    218 
    219 	return 0;
    220 }
    221 
    222 
    223 #ifdef CONFIG_IEEE80211N
    224 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
    225 {
    226 	int sec_chan, ok, j, first;
    227 	int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
    228 			  184, 192 };
    229 	size_t k;
    230 
    231 	if (!iface->conf->secondary_channel)
    232 		return 1; /* HT40 not used */
    233 
    234 	sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4;
    235 	wpa_printf(MSG_DEBUG, "HT40: control channel: %d  "
    236 		   "secondary channel: %d",
    237 		   iface->conf->channel, sec_chan);
    238 
    239 	/* Verify that HT40 secondary channel is an allowed 20 MHz
    240 	 * channel */
    241 	ok = 0;
    242 	for (j = 0; j < iface->current_mode->num_channels; j++) {
    243 		struct hostapd_channel_data *chan =
    244 			&iface->current_mode->channels[j];
    245 		if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
    246 		    chan->chan == sec_chan) {
    247 			ok = 1;
    248 			break;
    249 		}
    250 	}
    251 	if (!ok) {
    252 		wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
    253 			   sec_chan);
    254 		return 0;
    255 	}
    256 
    257 	/*
    258 	 * Verify that HT40 primary,secondary channel pair is allowed per
    259 	 * IEEE 802.11n Annex J. This is only needed for 5 GHz band since
    260 	 * 2.4 GHz rules allow all cases where the secondary channel fits into
    261 	 * the list of allowed channels (already checked above).
    262 	 */
    263 	if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
    264 		return 1;
    265 
    266 	if (iface->conf->secondary_channel > 0)
    267 		first = iface->conf->channel;
    268 	else
    269 		first = sec_chan;
    270 
    271 	ok = 0;
    272 	for (k = 0; k < ARRAY_SIZE(allowed); k++) {
    273 		if (first == allowed[k]) {
    274 			ok = 1;
    275 			break;
    276 		}
    277 	}
    278 	if (!ok) {
    279 		wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed",
    280 			   iface->conf->channel,
    281 			   iface->conf->secondary_channel);
    282 		return 0;
    283 	}
    284 
    285 	return 1;
    286 }
    287 
    288 
    289 static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
    290 {
    291 	if (iface->conf->secondary_channel > 0) {
    292 		iface->conf->channel += 4;
    293 		iface->conf->secondary_channel = -1;
    294 	} else {
    295 		iface->conf->channel -= 4;
    296 		iface->conf->secondary_channel = 1;
    297 	}
    298 }
    299 
    300 
    301 static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
    302 					int *pri_chan, int *sec_chan)
    303 {
    304 	struct ieee80211_ht_operation *oper;
    305 	struct ieee802_11_elems elems;
    306 
    307 	*pri_chan = *sec_chan = 0;
    308 
    309 	ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
    310 	if (elems.ht_operation &&
    311 	    elems.ht_operation_len >= sizeof(*oper)) {
    312 		oper = (struct ieee80211_ht_operation *) elems.ht_operation;
    313 		*pri_chan = oper->primary_chan;
    314 		if (oper->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) {
    315 			int sec = oper->ht_param &
    316 				HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
    317 			if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
    318 				*sec_chan = *pri_chan + 4;
    319 			else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
    320 				*sec_chan = *pri_chan - 4;
    321 		}
    322 	}
    323 }
    324 
    325 
    326 static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
    327 				     struct wpa_scan_results *scan_res)
    328 {
    329 	int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss;
    330 	int bss_pri_chan, bss_sec_chan;
    331 	size_t i;
    332 	int match;
    333 
    334 	pri_chan = iface->conf->channel;
    335 	sec_chan = pri_chan + iface->conf->secondary_channel * 4;
    336 	pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan);
    337 	if (iface->conf->secondary_channel > 0)
    338 		sec_freq = pri_freq + 20;
    339 	else
    340 		sec_freq = pri_freq - 20;
    341 
    342 	/*
    343 	 * Switch PRI/SEC channels if Beacons were detected on selected SEC
    344 	 * channel, but not on selected PRI channel.
    345 	 */
    346 	pri_bss = sec_bss = 0;
    347 	for (i = 0; i < scan_res->num; i++) {
    348 		struct wpa_scan_res *bss = scan_res->res[i];
    349 		if (bss->freq == pri_freq)
    350 			pri_bss++;
    351 		else if (bss->freq == sec_freq)
    352 			sec_bss++;
    353 	}
    354 	if (sec_bss && !pri_bss) {
    355 		wpa_printf(MSG_INFO, "Switch own primary and secondary "
    356 			   "channel to get secondary channel with no Beacons "
    357 			   "from other BSSes");
    358 		ieee80211n_switch_pri_sec(iface);
    359 		return 1;
    360 	}
    361 
    362 	/*
    363 	 * Match PRI/SEC channel with any existing HT40 BSS on the same
    364 	 * channels that we are about to use (if already mixed order in
    365 	 * existing BSSes, use own preference).
    366 	 */
    367 	match = 0;
    368 	for (i = 0; i < scan_res->num; i++) {
    369 		struct wpa_scan_res *bss = scan_res->res[i];
    370 		ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
    371 		if (pri_chan == bss_pri_chan &&
    372 		    sec_chan == bss_sec_chan) {
    373 			match = 1;
    374 			break;
    375 		}
    376 	}
    377 	if (!match) {
    378 		for (i = 0; i < scan_res->num; i++) {
    379 			struct wpa_scan_res *bss = scan_res->res[i];
    380 			ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan,
    381 						    &bss_sec_chan);
    382 			if (pri_chan == bss_sec_chan &&
    383 			    sec_chan == bss_pri_chan) {
    384 				wpa_printf(MSG_INFO, "Switch own primary and "
    385 					   "secondary channel due to BSS "
    386 					   "overlap with " MACSTR,
    387 					   MAC2STR(bss->bssid));
    388 				ieee80211n_switch_pri_sec(iface);
    389 				break;
    390 			}
    391 		}
    392 	}
    393 
    394 	return 1;
    395 }
    396 
    397 
    398 static int ieee80211n_check_20mhz_bss(struct wpa_scan_res *bss, int pri_freq,
    399 				      int start, int end)
    400 {
    401 	struct ieee802_11_elems elems;
    402 	struct ieee80211_ht_operation *oper;
    403 
    404 	if (bss->freq < start || bss->freq > end || bss->freq == pri_freq)
    405 		return 0;
    406 
    407 	ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
    408 	if (!elems.ht_capabilities) {
    409 		wpa_printf(MSG_DEBUG, "Found overlapping legacy BSS: "
    410 			   MACSTR " freq=%d", MAC2STR(bss->bssid), bss->freq);
    411 		return 1;
    412 	}
    413 
    414 	if (elems.ht_operation &&
    415 	    elems.ht_operation_len >= sizeof(*oper)) {
    416 		oper = (struct ieee80211_ht_operation *) elems.ht_operation;
    417 		if (oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)
    418 			return 0;
    419 
    420 		wpa_printf(MSG_DEBUG, "Found overlapping 20 MHz HT BSS: "
    421 			   MACSTR " freq=%d", MAC2STR(bss->bssid), bss->freq);
    422 		return 1;
    423 	}
    424 	return 0;
    425 }
    426 
    427 
    428 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
    429 				      struct wpa_scan_results *scan_res)
    430 {
    431 	int pri_freq, sec_freq;
    432 	int affected_start, affected_end;
    433 	size_t i;
    434 
    435 	pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
    436 	if (iface->conf->secondary_channel > 0)
    437 		sec_freq = pri_freq + 20;
    438 	else
    439 		sec_freq = pri_freq - 20;
    440 	affected_start = (pri_freq + sec_freq) / 2 - 25;
    441 	affected_end = (pri_freq + sec_freq) / 2 + 25;
    442 	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
    443 		   affected_start, affected_end);
    444 	for (i = 0; i < scan_res->num; i++) {
    445 		struct wpa_scan_res *bss = scan_res->res[i];
    446 		int pri = bss->freq;
    447 		int sec = pri;
    448 		int sec_chan, pri_chan;
    449 		struct ieee802_11_elems elems;
    450 
    451 		/* Check for overlapping 20 MHz BSS */
    452 		if (ieee80211n_check_20mhz_bss(bss, pri_freq, affected_start,
    453 					       affected_end)) {
    454 			wpa_printf(MSG_DEBUG,
    455 				   "Overlapping 20 MHz BSS is found");
    456 			return 0;
    457 		}
    458 
    459 		ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan);
    460 
    461 		if (sec_chan) {
    462 			if (sec_chan < pri_chan)
    463 				sec = pri - 20;
    464 			else
    465 				sec = pri + 20;
    466 		}
    467 
    468 		if ((pri < affected_start || pri > affected_end) &&
    469 		    (sec < affected_start || sec > affected_end))
    470 			continue; /* not within affected channel range */
    471 
    472 		wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
    473 			   " freq=%d pri=%d sec=%d",
    474 			   MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
    475 
    476 		if (sec_chan) {
    477 			if (pri_freq != pri || sec_freq != sec) {
    478 				wpa_printf(MSG_DEBUG, "40 MHz pri/sec "
    479 					   "mismatch with BSS " MACSTR
    480 					   " <%d,%d> (chan=%d%c) vs. <%d,%d>",
    481 					   MAC2STR(bss->bssid),
    482 					   pri, sec, pri_chan,
    483 					   sec > pri ? '+' : '-',
    484 					   pri_freq, sec_freq);
    485 				return 0;
    486 			}
    487 		}
    488 
    489 		ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems,
    490 				       0);
    491 		if (elems.ht_capabilities &&
    492 		    elems.ht_capabilities_len >=
    493 		    sizeof(struct ieee80211_ht_capabilities)) {
    494 			struct ieee80211_ht_capabilities *ht_cap =
    495 				(struct ieee80211_ht_capabilities *)
    496 				elems.ht_capabilities;
    497 
    498 			if (le_to_host16(ht_cap->ht_capabilities_info) &
    499 			    HT_CAP_INFO_40MHZ_INTOLERANT) {
    500 				wpa_printf(MSG_DEBUG,
    501 					   "40 MHz Intolerant is set on channel %d in BSS "
    502 					   MACSTR, pri, MAC2STR(bss->bssid));
    503 				return 0;
    504 			}
    505 		}
    506 	}
    507 
    508 	return 1;
    509 }
    510 
    511 
    512 static void ieee80211n_check_scan(struct hostapd_iface *iface)
    513 {
    514 	struct wpa_scan_results *scan_res;
    515 	int oper40;
    516 	int res;
    517 
    518 	/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
    519 	 * allowed per IEEE Std 802.11-2012, 10.15.3.2 */
    520 
    521 	iface->scan_cb = NULL;
    522 
    523 	scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
    524 	if (scan_res == NULL) {
    525 		hostapd_setup_interface_complete(iface, 1);
    526 		return;
    527 	}
    528 
    529 	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
    530 		oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
    531 	else
    532 		oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
    533 	wpa_scan_results_free(scan_res);
    534 
    535 	iface->secondary_ch = iface->conf->secondary_channel;
    536 	if (!oper40) {
    537 		wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
    538 			   "channel pri=%d sec=%d based on overlapping BSSes",
    539 			   iface->conf->channel,
    540 			   iface->conf->channel +
    541 			   iface->conf->secondary_channel * 4);
    542 		iface->conf->secondary_channel = 0;
    543 		if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
    544 			/*
    545 			 * TODO: Could consider scheduling another scan to check
    546 			 * if channel width can be changed if no coex reports
    547 			 * are received from associating stations.
    548 			 */
    549 		}
    550 	}
    551 
    552 	res = ieee80211n_allowed_ht40_channel_pair(iface);
    553 	if (!res) {
    554 		iface->conf->secondary_channel = 0;
    555 		wpa_printf(MSG_INFO, "Fallback to 20 MHz");
    556 	}
    557 
    558 	hostapd_setup_interface_complete(iface, !res);
    559 }
    560 
    561 
    562 static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
    563 					 struct wpa_driver_scan_params *params)
    564 {
    565 	/* Scan only the affected frequency range */
    566 	int pri_freq, sec_freq;
    567 	int affected_start, affected_end;
    568 	int i, pos;
    569 	struct hostapd_hw_modes *mode;
    570 
    571 	if (iface->current_mode == NULL)
    572 		return;
    573 
    574 	pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
    575 	if (iface->conf->secondary_channel > 0)
    576 		sec_freq = pri_freq + 20;
    577 	else
    578 		sec_freq = pri_freq - 20;
    579 	affected_start = (pri_freq + sec_freq) / 2 - 25;
    580 	affected_end = (pri_freq + sec_freq) / 2 + 25;
    581 	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
    582 		   affected_start, affected_end);
    583 
    584 	mode = iface->current_mode;
    585 	params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
    586 	if (params->freqs == NULL)
    587 		return;
    588 	pos = 0;
    589 
    590 	for (i = 0; i < mode->num_channels; i++) {
    591 		struct hostapd_channel_data *chan = &mode->channels[i];
    592 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
    593 			continue;
    594 		if (chan->freq < affected_start ||
    595 		    chan->freq > affected_end)
    596 			continue;
    597 		params->freqs[pos++] = chan->freq;
    598 	}
    599 }
    600 
    601 
    602 static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface,
    603 					struct wpa_driver_scan_params *params)
    604 {
    605 	/* Scan only the affected frequency range */
    606 	int pri_freq;
    607 	int affected_start, affected_end;
    608 	int i, pos;
    609 	struct hostapd_hw_modes *mode;
    610 
    611 	if (iface->current_mode == NULL)
    612 		return;
    613 
    614 	pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
    615 	if (iface->conf->secondary_channel > 0) {
    616 		affected_start = pri_freq - 10;
    617 		affected_end = pri_freq + 30;
    618 	} else {
    619 		affected_start = pri_freq - 30;
    620 		affected_end = pri_freq + 10;
    621 	}
    622 	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
    623 		   affected_start, affected_end);
    624 
    625 	mode = iface->current_mode;
    626 	params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
    627 	if (params->freqs == NULL)
    628 		return;
    629 	pos = 0;
    630 
    631 	for (i = 0; i < mode->num_channels; i++) {
    632 		struct hostapd_channel_data *chan = &mode->channels[i];
    633 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
    634 			continue;
    635 		if (chan->freq < affected_start ||
    636 		    chan->freq > affected_end)
    637 			continue;
    638 		params->freqs[pos++] = chan->freq;
    639 	}
    640 }
    641 
    642 
    643 static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
    644 {
    645 #define HT2040_COEX_SCAN_RETRY 15
    646 	struct hostapd_iface *iface = eloop_data;
    647 	struct wpa_driver_scan_params params;
    648 	int ret;
    649 
    650 	os_memset(&params, 0, sizeof(params));
    651 	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
    652 		ieee80211n_scan_channels_2g4(iface, &params);
    653 	else
    654 		ieee80211n_scan_channels_5g(iface, &params);
    655 
    656 	ret = hostapd_driver_scan(iface->bss[0], &params);
    657 	iface->num_ht40_scan_tries++;
    658 	os_free(params.freqs);
    659 
    660 	if (ret == -EBUSY &&
    661 	    iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) {
    662 		wpa_printf(MSG_ERROR,
    663 			   "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)",
    664 			   ret, strerror(-ret), iface->num_ht40_scan_tries);
    665 		eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
    666 		return;
    667 	}
    668 
    669 	if (ret == 0) {
    670 		iface->scan_cb = ieee80211n_check_scan;
    671 		return;
    672 	}
    673 
    674 	wpa_printf(MSG_DEBUG,
    675 		   "Failed to request a scan in device, bringing up in HT20 mode");
    676 	iface->conf->secondary_channel = 0;
    677 	iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
    678 	hostapd_setup_interface_complete(iface, 0);
    679 }
    680 
    681 
    682 void hostapd_stop_setup_timers(struct hostapd_iface *iface)
    683 {
    684 	eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
    685 }
    686 
    687 
    688 static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
    689 {
    690 	struct wpa_driver_scan_params params;
    691 	int ret;
    692 
    693 	if (!iface->conf->secondary_channel)
    694 		return 0; /* HT40 not used */
    695 
    696 	hostapd_set_state(iface, HAPD_IFACE_HT_SCAN);
    697 	wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
    698 		   "40 MHz channel");
    699 	os_memset(&params, 0, sizeof(params));
    700 	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
    701 		ieee80211n_scan_channels_2g4(iface, &params);
    702 	else
    703 		ieee80211n_scan_channels_5g(iface, &params);
    704 
    705 	ret = hostapd_driver_scan(iface->bss[0], &params);
    706 	os_free(params.freqs);
    707 
    708 	if (ret == -EBUSY) {
    709 		wpa_printf(MSG_ERROR,
    710 			   "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again",
    711 			   ret, strerror(-ret));
    712 		iface->num_ht40_scan_tries = 1;
    713 		eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
    714 		eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
    715 		return 1;
    716 	}
    717 
    718 	if (ret < 0) {
    719 		wpa_printf(MSG_ERROR,
    720 			   "Failed to request a scan of neighboring BSSes ret=%d (%s)",
    721 			   ret, strerror(-ret));
    722 		return -1;
    723 	}
    724 
    725 	iface->scan_cb = ieee80211n_check_scan;
    726 	return 1;
    727 }
    728 
    729 
    730 static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
    731 {
    732 	u16 hw = iface->current_mode->ht_capab;
    733 	u16 conf = iface->conf->ht_capab;
    734 
    735 	if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
    736 	    !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
    737 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    738 			   "HT capability [LDPC]");
    739 		return 0;
    740 	}
    741 
    742 	if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
    743 	    !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
    744 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    745 			   "HT capability [HT40*]");
    746 		return 0;
    747 	}
    748 
    749 	if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) &&
    750 	    (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) {
    751 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    752 			   "HT capability [SMPS-*]");
    753 		return 0;
    754 	}
    755 
    756 	if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
    757 	    !(hw & HT_CAP_INFO_GREEN_FIELD)) {
    758 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    759 			   "HT capability [GF]");
    760 		return 0;
    761 	}
    762 
    763 	if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) &&
    764 	    !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) {
    765 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    766 			   "HT capability [SHORT-GI-20]");
    767 		return 0;
    768 	}
    769 
    770 	if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) &&
    771 	    !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) {
    772 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    773 			   "HT capability [SHORT-GI-40]");
    774 		return 0;
    775 	}
    776 
    777 	if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) {
    778 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    779 			   "HT capability [TX-STBC]");
    780 		return 0;
    781 	}
    782 
    783 	if ((conf & HT_CAP_INFO_RX_STBC_MASK) >
    784 	    (hw & HT_CAP_INFO_RX_STBC_MASK)) {
    785 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    786 			   "HT capability [RX-STBC*]");
    787 		return 0;
    788 	}
    789 
    790 	if ((conf & HT_CAP_INFO_DELAYED_BA) &&
    791 	    !(hw & HT_CAP_INFO_DELAYED_BA)) {
    792 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    793 			   "HT capability [DELAYED-BA]");
    794 		return 0;
    795 	}
    796 
    797 	if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) &&
    798 	    !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) {
    799 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    800 			   "HT capability [MAX-AMSDU-7935]");
    801 		return 0;
    802 	}
    803 
    804 	if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) &&
    805 	    !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) {
    806 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    807 			   "HT capability [DSSS_CCK-40]");
    808 		return 0;
    809 	}
    810 
    811 	if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) &&
    812 	    !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) {
    813 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    814 			   "HT capability [LSIG-TXOP-PROT]");
    815 		return 0;
    816 	}
    817 
    818 	return 1;
    819 }
    820 
    821 
    822 #ifdef CONFIG_IEEE80211AC
    823 
    824 static int ieee80211ac_cap_check(u32 hw, u32 conf, u32 cap, const char *name)
    825 {
    826 	u32 req_cap = conf & cap;
    827 
    828 	/*
    829 	 * Make sure we support all requested capabilities.
    830 	 * NOTE: We assume that 'cap' represents a capability mask,
    831 	 * not a discrete value.
    832 	 */
    833 	if ((hw & req_cap) != req_cap) {
    834 		wpa_printf(MSG_ERROR, "Driver does not support configured VHT capability [%s]",
    835 			   name);
    836 		return 0;
    837 	}
    838 	return 1;
    839 }
    840 
    841 
    842 static int ieee80211ac_cap_check_max(u32 hw, u32 conf, u32 cap,
    843 				     const char *name)
    844 {
    845 	u32 hw_max = hw & cap;
    846 	u32 conf_val = conf & cap;
    847 
    848 	if (conf_val > hw_max) {
    849 		int offset = find_first_bit(cap);
    850 		wpa_printf(MSG_ERROR, "Configured VHT capability [%s] exceeds max value supported by the driver (%d > %d)",
    851 			   name, conf_val >> offset, hw_max >> offset);
    852 		return 0;
    853 	}
    854 	return 1;
    855 }
    856 
    857 
    858 static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface)
    859 {
    860 	u32 hw = iface->current_mode->vht_capab;
    861 	u32 conf = iface->conf->vht_capab;
    862 
    863 	wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x",
    864 		   hw, conf);
    865 
    866 #define VHT_CAP_CHECK(cap) \
    867 	do { \
    868 		if (!ieee80211ac_cap_check(hw, conf, cap, #cap)) \
    869 			return 0; \
    870 	} while (0)
    871 
    872 #define VHT_CAP_CHECK_MAX(cap) \
    873 	do { \
    874 		if (!ieee80211ac_cap_check_max(hw, conf, cap, #cap)) \
    875 			return 0; \
    876 	} while (0)
    877 
    878 	VHT_CAP_CHECK_MAX(VHT_CAP_MAX_MPDU_LENGTH_MASK);
    879 	VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ);
    880 	VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ);
    881 	VHT_CAP_CHECK(VHT_CAP_RXLDPC);
    882 	VHT_CAP_CHECK(VHT_CAP_SHORT_GI_80);
    883 	VHT_CAP_CHECK(VHT_CAP_SHORT_GI_160);
    884 	VHT_CAP_CHECK(VHT_CAP_TXSTBC);
    885 	VHT_CAP_CHECK_MAX(VHT_CAP_RXSTBC_MASK);
    886 	VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMER_CAPABLE);
    887 	VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMEE_CAPABLE);
    888 	VHT_CAP_CHECK_MAX(VHT_CAP_BEAMFORMEE_STS_MAX);
    889 	VHT_CAP_CHECK_MAX(VHT_CAP_SOUNDING_DIMENSION_MAX);
    890 	VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMER_CAPABLE);
    891 	VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE);
    892 	VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS);
    893 	VHT_CAP_CHECK(VHT_CAP_HTC_VHT);
    894 	VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX);
    895 	VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB);
    896 	VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB);
    897 	VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN);
    898 	VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN);
    899 
    900 #undef VHT_CAP_CHECK
    901 #undef VHT_CAP_CHECK_MAX
    902 
    903 	return 1;
    904 }
    905 #endif /* CONFIG_IEEE80211AC */
    906 
    907 #endif /* CONFIG_IEEE80211N */
    908 
    909 
    910 int hostapd_check_ht_capab(struct hostapd_iface *iface)
    911 {
    912 #ifdef CONFIG_IEEE80211N
    913 	int ret;
    914 	if (!iface->conf->ieee80211n)
    915 		return 0;
    916 	if (!ieee80211n_supported_ht_capab(iface))
    917 		return -1;
    918 #ifdef CONFIG_IEEE80211AC
    919 	if (!ieee80211ac_supported_vht_capab(iface))
    920 		return -1;
    921 #endif /* CONFIG_IEEE80211AC */
    922 	ret = ieee80211n_check_40mhz(iface);
    923 	if (ret)
    924 		return ret;
    925 	if (!ieee80211n_allowed_ht40_channel_pair(iface))
    926 		return -1;
    927 #endif /* CONFIG_IEEE80211N */
    928 
    929 	return 0;
    930 }
    931 
    932 
    933 static int hostapd_is_usable_chan(struct hostapd_iface *iface,
    934 				  int channel, int primary)
    935 {
    936 	int i;
    937 	struct hostapd_channel_data *chan;
    938 
    939 	for (i = 0; i < iface->current_mode->num_channels; i++) {
    940 		chan = &iface->current_mode->channels[i];
    941 		if (chan->chan != channel)
    942 			continue;
    943 
    944 		if (!(chan->flag & HOSTAPD_CHAN_DISABLED))
    945 			return 1;
    946 
    947 		wpa_printf(MSG_DEBUG,
    948 			   "%schannel [%i] (%i) is disabled for use in AP mode, flags: 0x%x%s%s%s",
    949 			   primary ? "" : "Configured HT40 secondary ",
    950 			   i, chan->chan, chan->flag,
    951 			   chan->flag & HOSTAPD_CHAN_NO_IBSS ? " NO-IBSS" : "",
    952 			   chan->flag & HOSTAPD_CHAN_PASSIVE_SCAN ?
    953 			   " PASSIVE-SCAN" : "",
    954 			   chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : "");
    955 	}
    956 
    957 	return 0;
    958 }
    959 
    960 
    961 static int hostapd_is_usable_chans(struct hostapd_iface *iface)
    962 {
    963 	if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1))
    964 		return 0;
    965 
    966 	if (!iface->conf->secondary_channel)
    967 		return 1;
    968 
    969 	return hostapd_is_usable_chan(iface, iface->conf->channel +
    970 				      iface->conf->secondary_channel * 4, 0);
    971 }
    972 
    973 
    974 static enum hostapd_chan_status
    975 hostapd_check_chans(struct hostapd_iface *iface)
    976 {
    977 	if (iface->conf->channel) {
    978 		if (hostapd_is_usable_chans(iface))
    979 			return HOSTAPD_CHAN_VALID;
    980 		else
    981 			return HOSTAPD_CHAN_INVALID;
    982 	}
    983 
    984 	/*
    985 	 * The user set channel=0 or channel=acs_survey
    986 	 * which is used to trigger ACS.
    987 	 */
    988 
    989 	switch (acs_init(iface)) {
    990 	case HOSTAPD_CHAN_ACS:
    991 		return HOSTAPD_CHAN_ACS;
    992 	case HOSTAPD_CHAN_VALID:
    993 	case HOSTAPD_CHAN_INVALID:
    994 	default:
    995 		return HOSTAPD_CHAN_INVALID;
    996 	}
    997 }
    998 
    999 
   1000 static void hostapd_notify_bad_chans(struct hostapd_iface *iface)
   1001 {
   1002 	hostapd_logger(iface->bss[0], NULL,
   1003 		       HOSTAPD_MODULE_IEEE80211,
   1004 		       HOSTAPD_LEVEL_WARNING,
   1005 		       "Configured channel (%d) not found from the "
   1006 		       "channel list of current mode (%d) %s",
   1007 		       iface->conf->channel,
   1008 		       iface->current_mode->mode,
   1009 		       hostapd_hw_mode_txt(iface->current_mode->mode));
   1010 	hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
   1011 		       HOSTAPD_LEVEL_WARNING,
   1012 		       "Hardware does not support configured channel");
   1013 }
   1014 
   1015 
   1016 int hostapd_acs_completed(struct hostapd_iface *iface, int err)
   1017 {
   1018 	int ret = -1;
   1019 
   1020 	if (err)
   1021 		goto out;
   1022 
   1023 	switch (hostapd_check_chans(iface)) {
   1024 	case HOSTAPD_CHAN_VALID:
   1025 		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
   1026 			ACS_EVENT_COMPLETED "freq=%d channel=%d",
   1027 			hostapd_hw_get_freq(iface->bss[0],
   1028 					    iface->conf->channel),
   1029 			iface->conf->channel);
   1030 		break;
   1031 	case HOSTAPD_CHAN_ACS:
   1032 		wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available");
   1033 		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED);
   1034 		hostapd_notify_bad_chans(iface);
   1035 		goto out;
   1036 	case HOSTAPD_CHAN_INVALID:
   1037 	default:
   1038 		wpa_printf(MSG_ERROR, "ACS picked unusable channels");
   1039 		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED);
   1040 		hostapd_notify_bad_chans(iface);
   1041 		goto out;
   1042 	}
   1043 
   1044 	ret = hostapd_check_ht_capab(iface);
   1045 	if (ret < 0)
   1046 		goto out;
   1047 	if (ret == 1) {
   1048 		wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback");
   1049 		return 0;
   1050 	}
   1051 
   1052 	ret = 0;
   1053 out:
   1054 	return hostapd_setup_interface_complete(iface, ret);
   1055 }
   1056 
   1057 
   1058 /**
   1059  * hostapd_select_hw_mode - Select the hardware mode
   1060  * @iface: Pointer to interface data.
   1061  * Returns: 0 on success, < 0 on failure
   1062  *
   1063  * Sets up the hardware mode, channel, rates, and passive scanning
   1064  * based on the configuration.
   1065  */
   1066 int hostapd_select_hw_mode(struct hostapd_iface *iface)
   1067 {
   1068 	int i;
   1069 
   1070 	if (iface->num_hw_features < 1)
   1071 		return -1;
   1072 
   1073 	if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G ||
   1074 	     iface->conf->ieee80211n || iface->conf->ieee80211ac) &&
   1075 	    iface->conf->channel == 14) {
   1076 		wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT on channel 14");
   1077 		iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
   1078 		iface->conf->ieee80211n = 0;
   1079 		iface->conf->ieee80211ac = 0;
   1080 	}
   1081 
   1082 	iface->current_mode = NULL;
   1083 	for (i = 0; i < iface->num_hw_features; i++) {
   1084 		struct hostapd_hw_modes *mode = &iface->hw_features[i];
   1085 		if (mode->mode == iface->conf->hw_mode) {
   1086 			iface->current_mode = mode;
   1087 			break;
   1088 		}
   1089 	}
   1090 
   1091 	if (iface->current_mode == NULL) {
   1092 		wpa_printf(MSG_ERROR, "Hardware does not support configured "
   1093 			   "mode");
   1094 		hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
   1095 			       HOSTAPD_LEVEL_WARNING,
   1096 			       "Hardware does not support configured mode "
   1097 			       "(%d) (hw_mode in hostapd.conf)",
   1098 			       (int) iface->conf->hw_mode);
   1099 		return -2;
   1100 	}
   1101 
   1102 	switch (hostapd_check_chans(iface)) {
   1103 	case HOSTAPD_CHAN_VALID:
   1104 		return 0;
   1105 	case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */
   1106 		return 1;
   1107 	case HOSTAPD_CHAN_INVALID:
   1108 	default:
   1109 		hostapd_notify_bad_chans(iface);
   1110 		return -3;
   1111 	}
   1112 }
   1113 
   1114 
   1115 const char * hostapd_hw_mode_txt(int mode)
   1116 {
   1117 	switch (mode) {
   1118 	case HOSTAPD_MODE_IEEE80211A:
   1119 		return "IEEE 802.11a";
   1120 	case HOSTAPD_MODE_IEEE80211B:
   1121 		return "IEEE 802.11b";
   1122 	case HOSTAPD_MODE_IEEE80211G:
   1123 		return "IEEE 802.11g";
   1124 	case HOSTAPD_MODE_IEEE80211AD:
   1125 		return "IEEE 802.11ad";
   1126 	default:
   1127 		return "UNKNOWN";
   1128 	}
   1129 }
   1130 
   1131 
   1132 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
   1133 {
   1134 	int i;
   1135 
   1136 	if (!hapd->iface->current_mode)
   1137 		return 0;
   1138 
   1139 	for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
   1140 		struct hostapd_channel_data *ch =
   1141 			&hapd->iface->current_mode->channels[i];
   1142 		if (ch->chan == chan)
   1143 			return ch->freq;
   1144 	}
   1145 
   1146 	return 0;
   1147 }
   1148 
   1149 
   1150 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
   1151 {
   1152 	int i;
   1153 
   1154 	if (!hapd->iface->current_mode)
   1155 		return 0;
   1156 
   1157 	for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
   1158 		struct hostapd_channel_data *ch =
   1159 			&hapd->iface->current_mode->channels[i];
   1160 		if (ch->freq == freq)
   1161 			return ch->chan;
   1162 	}
   1163 
   1164 	return 0;
   1165 }
   1166