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 program is free software; you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License version 2 as
      9  * published by the Free Software Foundation.
     10  *
     11  * Alternatively, this software may be distributed under the terms of BSD
     12  * license.
     13  *
     14  * See README and COPYING for more details.
     15  */
     16 
     17 #include "utils/includes.h"
     18 
     19 #include "utils/common.h"
     20 #include "utils/eloop.h"
     21 #include "common/ieee802_11_defs.h"
     22 #include "common/ieee802_11_common.h"
     23 #include "drivers/driver.h"
     24 #include "hostapd.h"
     25 #include "ap_config.h"
     26 #include "ap_drv_ops.h"
     27 #include "hw_features.h"
     28 
     29 
     30 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
     31 			      size_t num_hw_features)
     32 {
     33 	size_t i;
     34 
     35 	if (hw_features == NULL)
     36 		return;
     37 
     38 	for (i = 0; i < num_hw_features; i++) {
     39 		os_free(hw_features[i].channels);
     40 		os_free(hw_features[i].rates);
     41 	}
     42 
     43 	os_free(hw_features);
     44 }
     45 
     46 
     47 int hostapd_get_hw_features(struct hostapd_iface *iface)
     48 {
     49 	struct hostapd_data *hapd = iface->bss[0];
     50 	int ret = 0, i, j;
     51 	u16 num_modes, flags;
     52 	struct hostapd_hw_modes *modes;
     53 
     54 	if (hostapd_drv_none(hapd))
     55 		return -1;
     56 	modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags);
     57 	if (modes == NULL) {
     58 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
     59 			       HOSTAPD_LEVEL_DEBUG,
     60 			       "Fetching hardware channel/rate support not "
     61 			       "supported.");
     62 		return -1;
     63 	}
     64 
     65 	iface->hw_flags = flags;
     66 
     67 	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
     68 	iface->hw_features = modes;
     69 	iface->num_hw_features = num_modes;
     70 
     71 	for (i = 0; i < num_modes; i++) {
     72 		struct hostapd_hw_modes *feature = &modes[i];
     73 		/* set flag for channels we can use in current regulatory
     74 		 * domain */
     75 		for (j = 0; j < feature->num_channels; j++) {
     76 			/*
     77 			 * Disable all channels that are marked not to allow
     78 			 * IBSS operation or active scanning. In addition,
     79 			 * disable all channels that require radar detection,
     80 			 * since that (in addition to full DFS) is not yet
     81 			 * supported.
     82 			 */
     83 			if (feature->channels[j].flag &
     84 			    (HOSTAPD_CHAN_NO_IBSS |
     85 			     HOSTAPD_CHAN_PASSIVE_SCAN |
     86 			     HOSTAPD_CHAN_RADAR))
     87 				feature->channels[j].flag |=
     88 					HOSTAPD_CHAN_DISABLED;
     89 			if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
     90 				continue;
     91 			wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
     92 				   "chan=%d freq=%d MHz max_tx_power=%d dBm",
     93 				   feature->mode,
     94 				   feature->channels[j].chan,
     95 				   feature->channels[j].freq,
     96 				   feature->channels[j].max_tx_power);
     97 		}
     98 	}
     99 
    100 	return ret;
    101 }
    102 
    103 
    104 int hostapd_prepare_rates(struct hostapd_iface *iface,
    105 			  struct hostapd_hw_modes *mode)
    106 {
    107 	int i, num_basic_rates = 0;
    108 	int basic_rates_a[] = { 60, 120, 240, -1 };
    109 	int basic_rates_b[] = { 10, 20, -1 };
    110 	int basic_rates_g[] = { 10, 20, 55, 110, -1 };
    111 	int *basic_rates;
    112 
    113 	if (iface->conf->basic_rates)
    114 		basic_rates = iface->conf->basic_rates;
    115 	else switch (mode->mode) {
    116 	case HOSTAPD_MODE_IEEE80211A:
    117 		basic_rates = basic_rates_a;
    118 		break;
    119 	case HOSTAPD_MODE_IEEE80211B:
    120 		basic_rates = basic_rates_b;
    121 		break;
    122 	case HOSTAPD_MODE_IEEE80211G:
    123 		basic_rates = basic_rates_g;
    124 		break;
    125 	case HOSTAPD_MODE_IEEE80211AD:
    126 		return 0; /* No basic rates for 11ad */
    127 	default:
    128 		return -1;
    129 	}
    130 
    131 	i = 0;
    132 	while (basic_rates[i] >= 0)
    133 		i++;
    134 	if (i)
    135 		i++; /* -1 termination */
    136 	os_free(iface->basic_rates);
    137 	iface->basic_rates = os_malloc(i * sizeof(int));
    138 	if (iface->basic_rates)
    139 		os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
    140 
    141 	os_free(iface->current_rates);
    142 	iface->num_rates = 0;
    143 
    144 	iface->current_rates =
    145 		os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
    146 	if (!iface->current_rates) {
    147 		wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
    148 			   "table.");
    149 		return -1;
    150 	}
    151 
    152 	for (i = 0; i < mode->num_rates; i++) {
    153 		struct hostapd_rate_data *rate;
    154 
    155 		if (iface->conf->supported_rates &&
    156 		    !hostapd_rate_found(iface->conf->supported_rates,
    157 					mode->rates[i]))
    158 			continue;
    159 
    160 		rate = &iface->current_rates[iface->num_rates];
    161 		rate->rate = mode->rates[i];
    162 		if (hostapd_rate_found(basic_rates, rate->rate)) {
    163 			rate->flags |= HOSTAPD_RATE_BASIC;
    164 			num_basic_rates++;
    165 		}
    166 		wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
    167 			   iface->num_rates, rate->rate, rate->flags);
    168 		iface->num_rates++;
    169 	}
    170 
    171 	if ((iface->num_rates == 0 || num_basic_rates == 0) &&
    172 	    (!iface->conf->ieee80211n || !iface->conf->require_ht)) {
    173 		wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
    174 			   "rate sets (%d,%d).",
    175 			   iface->num_rates, num_basic_rates);
    176 		return -1;
    177 	}
    178 
    179 	return 0;
    180 }
    181 
    182 
    183 #ifdef CONFIG_IEEE80211N
    184 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
    185 {
    186 	int sec_chan, ok, j, first;
    187 	int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
    188 			  184, 192 };
    189 	size_t k;
    190 
    191 	if (!iface->conf->secondary_channel)
    192 		return 1; /* HT40 not used */
    193 
    194 	sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4;
    195 	wpa_printf(MSG_DEBUG, "HT40: control channel: %d  "
    196 		   "secondary channel: %d",
    197 		   iface->conf->channel, sec_chan);
    198 
    199 	/* Verify that HT40 secondary channel is an allowed 20 MHz
    200 	 * channel */
    201 	ok = 0;
    202 	for (j = 0; j < iface->current_mode->num_channels; j++) {
    203 		struct hostapd_channel_data *chan =
    204 			&iface->current_mode->channels[j];
    205 		if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
    206 		    chan->chan == sec_chan) {
    207 			ok = 1;
    208 			break;
    209 		}
    210 	}
    211 	if (!ok) {
    212 		wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed",
    213 			   sec_chan);
    214 		return 0;
    215 	}
    216 
    217 	/*
    218 	 * Verify that HT40 primary,secondary channel pair is allowed per
    219 	 * IEEE 802.11n Annex J. This is only needed for 5 GHz band since
    220 	 * 2.4 GHz rules allow all cases where the secondary channel fits into
    221 	 * the list of allowed channels (already checked above).
    222 	 */
    223 	if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
    224 		return 1;
    225 
    226 	if (iface->conf->secondary_channel > 0)
    227 		first = iface->conf->channel;
    228 	else
    229 		first = sec_chan;
    230 
    231 	ok = 0;
    232 	for (k = 0; k < sizeof(allowed) / sizeof(allowed[0]); k++) {
    233 		if (first == allowed[k]) {
    234 			ok = 1;
    235 			break;
    236 		}
    237 	}
    238 	if (!ok) {
    239 		wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed",
    240 			   iface->conf->channel,
    241 			   iface->conf->secondary_channel);
    242 		return 0;
    243 	}
    244 
    245 	return 1;
    246 }
    247 
    248 
    249 static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
    250 {
    251 	if (iface->conf->secondary_channel > 0) {
    252 		iface->conf->channel += 4;
    253 		iface->conf->secondary_channel = -1;
    254 	} else {
    255 		iface->conf->channel -= 4;
    256 		iface->conf->secondary_channel = 1;
    257 	}
    258 }
    259 
    260 
    261 static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss,
    262 					int *pri_chan, int *sec_chan)
    263 {
    264 	struct ieee80211_ht_operation *oper;
    265 	struct ieee802_11_elems elems;
    266 
    267 	*pri_chan = *sec_chan = 0;
    268 
    269 	ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
    270 	if (elems.ht_operation &&
    271 	    elems.ht_operation_len >= sizeof(*oper)) {
    272 		oper = (struct ieee80211_ht_operation *) elems.ht_operation;
    273 		*pri_chan = oper->control_chan;
    274 		if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) {
    275 			int sec = oper->ht_param &
    276 				HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
    277 			if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
    278 				*sec_chan = *pri_chan + 4;
    279 			else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
    280 				*sec_chan = *pri_chan - 4;
    281 		}
    282 	}
    283 }
    284 
    285 
    286 static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
    287 				     struct wpa_scan_results *scan_res)
    288 {
    289 	int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss;
    290 	int bss_pri_chan, bss_sec_chan;
    291 	size_t i;
    292 	int match;
    293 
    294 	pri_chan = iface->conf->channel;
    295 	sec_chan = iface->conf->secondary_channel * 4;
    296 	pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan);
    297 	if (iface->conf->secondary_channel > 0)
    298 		sec_freq = pri_freq + 20;
    299 	else
    300 		sec_freq = pri_freq - 20;
    301 
    302 	/*
    303 	 * Switch PRI/SEC channels if Beacons were detected on selected SEC
    304 	 * channel, but not on selected PRI channel.
    305 	 */
    306 	pri_bss = sec_bss = 0;
    307 	for (i = 0; i < scan_res->num; i++) {
    308 		struct wpa_scan_res *bss = scan_res->res[i];
    309 		if (bss->freq == pri_freq)
    310 			pri_bss++;
    311 		else if (bss->freq == sec_freq)
    312 			sec_bss++;
    313 	}
    314 	if (sec_bss && !pri_bss) {
    315 		wpa_printf(MSG_INFO, "Switch own primary and secondary "
    316 			   "channel to get secondary channel with no Beacons "
    317 			   "from other BSSes");
    318 		ieee80211n_switch_pri_sec(iface);
    319 	}
    320 
    321 	/*
    322 	 * Match PRI/SEC channel with any existing HT40 BSS on the same
    323 	 * channels that we are about to use (if already mixed order in
    324 	 * existing BSSes, use own preference).
    325 	 */
    326 	match = 0;
    327 	for (i = 0; i < scan_res->num; i++) {
    328 		struct wpa_scan_res *bss = scan_res->res[i];
    329 		ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
    330 		if (pri_chan == bss_pri_chan &&
    331 		    sec_chan == bss_sec_chan) {
    332 			match = 1;
    333 			break;
    334 		}
    335 	}
    336 	if (!match) {
    337 		for (i = 0; i < scan_res->num; i++) {
    338 			struct wpa_scan_res *bss = scan_res->res[i];
    339 			ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan,
    340 						    &bss_sec_chan);
    341 			if (pri_chan == bss_sec_chan &&
    342 			    sec_chan == bss_pri_chan) {
    343 				wpa_printf(MSG_INFO, "Switch own primary and "
    344 					   "secondary channel due to BSS "
    345 					   "overlap with " MACSTR,
    346 					   MAC2STR(bss->bssid));
    347 				ieee80211n_switch_pri_sec(iface);
    348 				break;
    349 			}
    350 		}
    351 	}
    352 
    353 	return 1;
    354 }
    355 
    356 
    357 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
    358 				      struct wpa_scan_results *scan_res)
    359 {
    360 	int pri_freq, sec_freq;
    361 	int affected_start, affected_end;
    362 	size_t i;
    363 
    364 	pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
    365 	if (iface->conf->secondary_channel > 0)
    366 		sec_freq = pri_freq + 20;
    367 	else
    368 		sec_freq = pri_freq - 20;
    369 	affected_start = (pri_freq + sec_freq) / 2 - 25;
    370 	affected_end = (pri_freq + sec_freq) / 2 + 25;
    371 	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
    372 		   affected_start, affected_end);
    373 	for (i = 0; i < scan_res->num; i++) {
    374 		struct wpa_scan_res *bss = scan_res->res[i];
    375 		int pri = bss->freq;
    376 		int sec = pri;
    377 		int sec_chan, pri_chan;
    378 
    379 		ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan);
    380 
    381 		if (sec_chan) {
    382 			if (sec_chan < pri_chan)
    383 				sec = pri - 20;
    384 			else
    385 				sec = pri + 20;
    386 		}
    387 
    388 		if ((pri < affected_start || pri > affected_end) &&
    389 		    (sec < affected_start || sec > affected_end))
    390 			continue; /* not within affected channel range */
    391 
    392 		wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR
    393 			   " freq=%d pri=%d sec=%d",
    394 			   MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan);
    395 
    396 		if (sec_chan) {
    397 			if (pri_freq != pri || sec_freq != sec) {
    398 				wpa_printf(MSG_DEBUG, "40 MHz pri/sec "
    399 					   "mismatch with BSS " MACSTR
    400 					   " <%d,%d> (chan=%d%c) vs. <%d,%d>",
    401 					   MAC2STR(bss->bssid),
    402 					   pri, sec, pri_chan,
    403 					   sec > pri ? '+' : '-',
    404 					   pri_freq, sec_freq);
    405 				return 0;
    406 			}
    407 		}
    408 
    409 		/* TODO: 40 MHz intolerant */
    410 	}
    411 
    412 	return 1;
    413 }
    414 
    415 
    416 static void ieee80211n_check_scan(struct hostapd_iface *iface)
    417 {
    418 	struct wpa_scan_results *scan_res;
    419 	int oper40;
    420 	int res;
    421 
    422 	/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
    423 	 * allowed per IEEE Std 802.11-2012, 10.15.3.2 */
    424 
    425 	iface->scan_cb = NULL;
    426 
    427 	scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
    428 	if (scan_res == NULL) {
    429 		hostapd_setup_interface_complete(iface, 1);
    430 		return;
    431 	}
    432 
    433 	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
    434 		oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
    435 	else
    436 		oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
    437 	wpa_scan_results_free(scan_res);
    438 
    439 	if (!oper40) {
    440 		wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
    441 			   "channel pri=%d sec=%d based on overlapping BSSes",
    442 			   iface->conf->channel,
    443 			   iface->conf->channel +
    444 			   iface->conf->secondary_channel * 4);
    445 		iface->conf->secondary_channel = 0;
    446 	}
    447 
    448 	res = ieee80211n_allowed_ht40_channel_pair(iface);
    449 	hostapd_setup_interface_complete(iface, !res);
    450 }
    451 
    452 
    453 static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
    454 					 struct wpa_driver_scan_params *params)
    455 {
    456 	/* Scan only the affected frequency range */
    457 	int pri_freq, sec_freq;
    458 	int affected_start, affected_end;
    459 	int i, pos;
    460 	struct hostapd_hw_modes *mode;
    461 
    462 	if (iface->current_mode == NULL)
    463 		return;
    464 
    465 	pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel);
    466 	if (iface->conf->secondary_channel > 0)
    467 		sec_freq = pri_freq + 20;
    468 	else
    469 		sec_freq = pri_freq - 20;
    470 	affected_start = (pri_freq + sec_freq) / 2 - 25;
    471 	affected_end = (pri_freq + sec_freq) / 2 + 25;
    472 	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
    473 		   affected_start, affected_end);
    474 
    475 	mode = iface->current_mode;
    476 	params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
    477 	if (params->freqs == NULL)
    478 		return;
    479 	pos = 0;
    480 
    481 	for (i = 0; i < mode->num_channels; i++) {
    482 		struct hostapd_channel_data *chan = &mode->channels[i];
    483 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
    484 			continue;
    485 		if (chan->freq < affected_start ||
    486 		    chan->freq > affected_end)
    487 			continue;
    488 		params->freqs[pos++] = chan->freq;
    489 	}
    490 }
    491 
    492 
    493 static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
    494 {
    495 	struct wpa_driver_scan_params params;
    496 
    497 	if (!iface->conf->secondary_channel)
    498 		return 0; /* HT40 not used */
    499 
    500 	wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
    501 		   "40 MHz channel");
    502 	os_memset(&params, 0, sizeof(params));
    503 	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
    504 		ieee80211n_scan_channels_2g4(iface, &params);
    505 	if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
    506 		wpa_printf(MSG_ERROR, "Failed to request a scan of "
    507 			   "neighboring BSSes");
    508 		os_free(params.freqs);
    509 		return -1;
    510 	}
    511 	os_free(params.freqs);
    512 
    513 	iface->scan_cb = ieee80211n_check_scan;
    514 	return 1;
    515 }
    516 
    517 
    518 static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
    519 {
    520 	u16 hw = iface->current_mode->ht_capab;
    521 	u16 conf = iface->conf->ht_capab;
    522 
    523 	if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
    524 	    !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
    525 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    526 			   "HT capability [LDPC]");
    527 		return 0;
    528 	}
    529 
    530 	if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
    531 	    !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
    532 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    533 			   "HT capability [HT40*]");
    534 		return 0;
    535 	}
    536 
    537 	if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) &&
    538 	    (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) {
    539 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    540 			   "HT capability [SMPS-*]");
    541 		return 0;
    542 	}
    543 
    544 	if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
    545 	    !(hw & HT_CAP_INFO_GREEN_FIELD)) {
    546 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    547 			   "HT capability [GF]");
    548 		return 0;
    549 	}
    550 
    551 	if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) &&
    552 	    !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) {
    553 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    554 			   "HT capability [SHORT-GI-20]");
    555 		return 0;
    556 	}
    557 
    558 	if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) &&
    559 	    !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) {
    560 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    561 			   "HT capability [SHORT-GI-40]");
    562 		return 0;
    563 	}
    564 
    565 	if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) {
    566 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    567 			   "HT capability [TX-STBC]");
    568 		return 0;
    569 	}
    570 
    571 	if ((conf & HT_CAP_INFO_RX_STBC_MASK) >
    572 	    (hw & HT_CAP_INFO_RX_STBC_MASK)) {
    573 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    574 			   "HT capability [RX-STBC*]");
    575 		return 0;
    576 	}
    577 
    578 	if ((conf & HT_CAP_INFO_DELAYED_BA) &&
    579 	    !(hw & HT_CAP_INFO_DELAYED_BA)) {
    580 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    581 			   "HT capability [DELAYED-BA]");
    582 		return 0;
    583 	}
    584 
    585 	if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) &&
    586 	    !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) {
    587 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    588 			   "HT capability [MAX-AMSDU-7935]");
    589 		return 0;
    590 	}
    591 
    592 	if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) &&
    593 	    !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) {
    594 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    595 			   "HT capability [DSSS_CCK-40]");
    596 		return 0;
    597 	}
    598 
    599 	if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) {
    600 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    601 			   "HT capability [PSMP]");
    602 		return 0;
    603 	}
    604 
    605 	if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) &&
    606 	    !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) {
    607 		wpa_printf(MSG_ERROR, "Driver does not support configured "
    608 			   "HT capability [LSIG-TXOP-PROT]");
    609 		return 0;
    610 	}
    611 
    612 	return 1;
    613 }
    614 
    615 #endif /* CONFIG_IEEE80211N */
    616 
    617 
    618 int hostapd_check_ht_capab(struct hostapd_iface *iface)
    619 {
    620 #ifdef CONFIG_IEEE80211N
    621 	int ret;
    622 	if (!iface->conf->ieee80211n)
    623 		return 0;
    624 	if (!ieee80211n_supported_ht_capab(iface))
    625 		return -1;
    626 	ret = ieee80211n_check_40mhz(iface);
    627 	if (ret)
    628 		return ret;
    629 	if (!ieee80211n_allowed_ht40_channel_pair(iface))
    630 		return -1;
    631 #endif /* CONFIG_IEEE80211N */
    632 
    633 	return 0;
    634 }
    635 
    636 
    637 /**
    638  * hostapd_select_hw_mode - Select the hardware mode
    639  * @iface: Pointer to interface data.
    640  * Returns: 0 on success, < 0 on failure
    641  *
    642  * Sets up the hardware mode, channel, rates, and passive scanning
    643  * based on the configuration.
    644  */
    645 int hostapd_select_hw_mode(struct hostapd_iface *iface)
    646 {
    647 	int i, j, ok;
    648 
    649 	if (iface->num_hw_features < 1)
    650 		return -1;
    651 
    652 	iface->current_mode = NULL;
    653 	for (i = 0; i < iface->num_hw_features; i++) {
    654 		struct hostapd_hw_modes *mode = &iface->hw_features[i];
    655 		if (mode->mode == iface->conf->hw_mode) {
    656 			iface->current_mode = mode;
    657 			break;
    658 		}
    659 	}
    660 
    661 	if (iface->current_mode == NULL) {
    662 		wpa_printf(MSG_ERROR, "Hardware does not support configured "
    663 			   "mode");
    664 		hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
    665 			       HOSTAPD_LEVEL_WARNING,
    666 			       "Hardware does not support configured mode "
    667 			       "(%d) (hw_mode in hostapd.conf)",
    668 			       (int) iface->conf->hw_mode);
    669 		return -2;
    670 	}
    671 
    672 	ok = 0;
    673 	for (j = 0; j < iface->current_mode->num_channels; j++) {
    674 		struct hostapd_channel_data *chan =
    675 			&iface->current_mode->channels[j];
    676 		if (chan->chan == iface->conf->channel) {
    677 			if (chan->flag & HOSTAPD_CHAN_DISABLED) {
    678 				wpa_printf(MSG_ERROR,
    679 					   "channel [%i] (%i) is disabled for "
    680 					   "use in AP mode, flags: 0x%x%s%s%s",
    681 					   j, chan->chan, chan->flag,
    682 					   chan->flag & HOSTAPD_CHAN_NO_IBSS ?
    683 					   " NO-IBSS" : "",
    684 					   chan->flag &
    685 					   HOSTAPD_CHAN_PASSIVE_SCAN ?
    686 					   " PASSIVE-SCAN" : "",
    687 					   chan->flag & HOSTAPD_CHAN_RADAR ?
    688 					   " RADAR" : "");
    689 			} else {
    690 				ok = 1;
    691 				break;
    692 			}
    693 		}
    694 	}
    695 	if (ok && iface->conf->secondary_channel) {
    696 		int sec_ok = 0;
    697 		int sec_chan = iface->conf->channel +
    698 			iface->conf->secondary_channel * 4;
    699 		for (j = 0; j < iface->current_mode->num_channels; j++) {
    700 			struct hostapd_channel_data *chan =
    701 				&iface->current_mode->channels[j];
    702 			if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
    703 			    (chan->chan == sec_chan)) {
    704 				sec_ok = 1;
    705 				break;
    706 			}
    707 		}
    708 		if (!sec_ok) {
    709 			hostapd_logger(iface->bss[0], NULL,
    710 				       HOSTAPD_MODULE_IEEE80211,
    711 				       HOSTAPD_LEVEL_WARNING,
    712 				       "Configured HT40 secondary channel "
    713 				       "(%d) not found from the channel list "
    714 				       "of current mode (%d) %s",
    715 				       sec_chan, iface->current_mode->mode,
    716 				       hostapd_hw_mode_txt(
    717 					       iface->current_mode->mode));
    718 			ok = 0;
    719 		}
    720 	}
    721 	if (iface->conf->channel == 0) {
    722 		/* TODO: could request a scan of neighboring BSSes and select
    723 		 * the channel automatically */
    724 		wpa_printf(MSG_ERROR, "Channel not configured "
    725 			   "(hw_mode/channel in hostapd.conf)");
    726 		return -3;
    727 	}
    728 	if (ok == 0 && iface->conf->channel != 0) {
    729 		hostapd_logger(iface->bss[0], NULL,
    730 			       HOSTAPD_MODULE_IEEE80211,
    731 			       HOSTAPD_LEVEL_WARNING,
    732 			       "Configured channel (%d) not found from the "
    733 			       "channel list of current mode (%d) %s",
    734 			       iface->conf->channel,
    735 			       iface->current_mode->mode,
    736 			       hostapd_hw_mode_txt(iface->current_mode->mode));
    737 		iface->current_mode = NULL;
    738 	}
    739 
    740 	if (iface->current_mode == NULL) {
    741 		hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
    742 			       HOSTAPD_LEVEL_WARNING,
    743 			       "Hardware does not support configured channel");
    744 		return -4;
    745 	}
    746 
    747 	return 0;
    748 }
    749 
    750 
    751 const char * hostapd_hw_mode_txt(int mode)
    752 {
    753 	switch (mode) {
    754 	case HOSTAPD_MODE_IEEE80211A:
    755 		return "IEEE 802.11a";
    756 	case HOSTAPD_MODE_IEEE80211B:
    757 		return "IEEE 802.11b";
    758 	case HOSTAPD_MODE_IEEE80211G:
    759 		return "IEEE 802.11g";
    760 	case HOSTAPD_MODE_IEEE80211AD:
    761 		return "IEEE 802.11ad";
    762 	default:
    763 		return "UNKNOWN";
    764 	}
    765 }
    766 
    767 
    768 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
    769 {
    770 	int i;
    771 
    772 	if (!hapd->iface->current_mode)
    773 		return 0;
    774 
    775 	for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
    776 		struct hostapd_channel_data *ch =
    777 			&hapd->iface->current_mode->channels[i];
    778 		if (ch->chan == chan)
    779 			return ch->freq;
    780 	}
    781 
    782 	return 0;
    783 }
    784 
    785 
    786 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
    787 {
    788 	int i;
    789 
    790 	if (!hapd->iface->current_mode)
    791 		return 0;
    792 
    793 	for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
    794 		struct hostapd_channel_data *ch =
    795 			&hapd->iface->current_mode->channels[i];
    796 		if (ch->freq == freq)
    797 			return ch->chan;
    798 	}
    799 
    800 	return 0;
    801 }
    802