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