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