xref: /aosp_15_r20/external/wpa_supplicant_8/src/ap/hw_features.c (revision 03f9172ca588f91df233974f4258bab95191f931)
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 <[email protected]>
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 "common/hw_features_common.h"
19 #include "hostapd.h"
20 #include "ap_config.h"
21 #include "ap_drv_ops.h"
22 #include "acs.h"
23 #include "ieee802_11.h"
24 #include "beacon.h"
25 #include "hw_features.h"
26 
27 
hostapd_free_hw_features(struct hostapd_hw_modes * hw_features,size_t num_hw_features)28 void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
29 			      size_t num_hw_features)
30 {
31 	size_t i;
32 
33 	if (hw_features == NULL)
34 		return;
35 
36 	for (i = 0; i < num_hw_features; i++) {
37 		os_free(hw_features[i].channels);
38 		os_free(hw_features[i].rates);
39 	}
40 
41 	os_free(hw_features);
42 }
43 
44 
45 #ifndef CONFIG_NO_STDOUT_DEBUG
dfs_info(struct hostapd_channel_data * chan)46 static char * dfs_info(struct hostapd_channel_data *chan)
47 {
48 	static char info[256];
49 	char *state;
50 
51 	switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) {
52 	case HOSTAPD_CHAN_DFS_UNKNOWN:
53 		state = "unknown";
54 		break;
55 	case HOSTAPD_CHAN_DFS_USABLE:
56 		state = "usable";
57 		break;
58 	case HOSTAPD_CHAN_DFS_UNAVAILABLE:
59 		state = "unavailable";
60 		break;
61 	case HOSTAPD_CHAN_DFS_AVAILABLE:
62 		state = "available";
63 		break;
64 	default:
65 		return "";
66 	}
67 	os_snprintf(info, sizeof(info), " (DFS state = %s)", state);
68 	info[sizeof(info) - 1] = '\0';
69 
70 	return info;
71 }
72 #endif /* CONFIG_NO_STDOUT_DEBUG */
73 
74 
hostapd_get_hw_features(struct hostapd_iface * iface)75 int hostapd_get_hw_features(struct hostapd_iface *iface)
76 {
77 	struct hostapd_data *hapd = iface->bss[0];
78 	int i, j;
79 	unsigned int k;
80 	u16 num_modes, flags;
81 	struct hostapd_hw_modes *modes;
82 	u8 dfs_domain;
83 	enum hostapd_hw_mode mode = HOSTAPD_MODE_IEEE80211ANY;
84 	bool is_6ghz = false;
85 	bool orig_mode_valid = false;
86 	struct hostapd_multi_hw_info *multi_hw_info;
87 	unsigned int num_multi_hws;
88 
89 	if (hostapd_drv_none(hapd))
90 		return -1;
91 	modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags,
92 					    &dfs_domain);
93 	if (modes == NULL) {
94 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
95 			       HOSTAPD_LEVEL_DEBUG,
96 			       "Fetching hardware channel/rate support not "
97 			       "supported.");
98 		return -1;
99 	}
100 
101 	iface->hw_flags = flags;
102 	iface->dfs_domain = dfs_domain;
103 
104 	if (iface->current_mode) {
105 		/*
106 		 * Received driver event CHANNEL_LIST_CHANGED when the current
107 		 * hw mode is valid. Clear iface->current_mode temporarily as
108 		 * the mode instance will be replaced with a new instance and
109 		 * the current pointer would be pointing to freed memory.
110 		 */
111 		orig_mode_valid = true;
112 		mode = iface->current_mode->mode;
113 		is_6ghz = iface->current_mode->is_6ghz;
114 		iface->current_mode = NULL;
115 	}
116 	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
117 	iface->hw_features = modes;
118 	iface->num_hw_features = num_modes;
119 
120 	for (i = 0; i < num_modes; i++) {
121 		struct hostapd_hw_modes *feature = &modes[i];
122 		int dfs_enabled = hapd->iconf->ieee80211h &&
123 			(iface->drv_flags & WPA_DRIVER_FLAGS_RADAR);
124 
125 		/* Restore orignal mode if possible */
126 		if (orig_mode_valid && feature->mode == mode &&
127 		    feature->num_channels > 0 &&
128 		    is_6ghz == is_6ghz_freq(feature->channels[0].freq))
129 			iface->current_mode = feature;
130 
131 		/* set flag for channels we can use in current regulatory
132 		 * domain */
133 		for (j = 0; j < feature->num_channels; j++) {
134 			int dfs = 0;
135 
136 			/*
137 			 * Disable all channels that are marked not to allow
138 			 * to initiate radiation (a.k.a. passive scan and no
139 			 * IBSS).
140 			 * Use radar channels only if the driver supports DFS.
141 			 */
142 			if ((feature->channels[j].flag &
143 			     HOSTAPD_CHAN_RADAR) && dfs_enabled) {
144 				dfs = 1;
145 			} else if (((feature->channels[j].flag &
146 				     HOSTAPD_CHAN_RADAR) &&
147 				    !(iface->drv_flags &
148 				      WPA_DRIVER_FLAGS_DFS_OFFLOAD)) ||
149 				   (feature->channels[j].flag &
150 				    HOSTAPD_CHAN_NO_IR)) {
151 				feature->channels[j].flag |=
152 					HOSTAPD_CHAN_DISABLED;
153 			}
154 
155 			if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
156 				continue;
157 
158 			wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
159 				   "chan=%d freq=%d MHz max_tx_power=%d dBm%s",
160 				   feature->mode,
161 				   feature->channels[j].chan,
162 				   feature->channels[j].freq,
163 				   feature->channels[j].max_tx_power,
164 				   dfs ? dfs_info(&feature->channels[j]) : "");
165 		}
166 	}
167 
168 	if (orig_mode_valid && !iface->current_mode) {
169 		wpa_printf(MSG_ERROR,
170 			   "%s: Could not update iface->current_mode",
171 			   __func__);
172 	}
173 
174 	multi_hw_info = hostapd_get_multi_hw_info(hapd, &num_multi_hws);
175 	if (!multi_hw_info)
176 		return 0;
177 
178 	hostapd_free_multi_hw_info(iface->multi_hw_info);
179 	iface->multi_hw_info = multi_hw_info;
180 	iface->num_multi_hws = num_multi_hws;
181 
182 	wpa_printf(MSG_DEBUG, "Multiple underlying hardwares info:");
183 
184 	for (k = 0; k < num_multi_hws; k++) {
185 		struct hostapd_multi_hw_info *hw_info = &multi_hw_info[k];
186 
187 		wpa_printf(MSG_DEBUG,
188 			   "  %d. hw_idx=%u, frequency range: %d-%d MHz",
189 			   k + 1, hw_info->hw_idx, hw_info->start_freq,
190 			   hw_info->end_freq);
191 	}
192 
193 	return 0;
194 }
195 
196 
hostapd_prepare_rates(struct hostapd_iface * iface,struct hostapd_hw_modes * mode)197 int hostapd_prepare_rates(struct hostapd_iface *iface,
198 			  struct hostapd_hw_modes *mode)
199 {
200 	int i, num_basic_rates = 0;
201 	int basic_rates_a[] = { 60, 120, 240, -1 };
202 	int basic_rates_b[] = { 10, 20, -1 };
203 	int basic_rates_g[] = { 10, 20, 55, 110, -1 };
204 	int *basic_rates;
205 
206 	if (iface->conf->basic_rates)
207 		basic_rates = iface->conf->basic_rates;
208 	else switch (mode->mode) {
209 	case HOSTAPD_MODE_IEEE80211A:
210 		basic_rates = basic_rates_a;
211 		break;
212 	case HOSTAPD_MODE_IEEE80211B:
213 		basic_rates = basic_rates_b;
214 		break;
215 	case HOSTAPD_MODE_IEEE80211G:
216 		basic_rates = basic_rates_g;
217 		break;
218 	case HOSTAPD_MODE_IEEE80211AD:
219 		return 0; /* No basic rates for 11ad */
220 	default:
221 		return -1;
222 	}
223 
224 	i = 0;
225 	while (basic_rates[i] >= 0)
226 		i++;
227 	if (i)
228 		i++; /* -1 termination */
229 	os_free(iface->basic_rates);
230 	iface->basic_rates = os_malloc(i * sizeof(int));
231 	if (iface->basic_rates)
232 		os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int));
233 
234 	os_free(iface->current_rates);
235 	iface->num_rates = 0;
236 
237 	iface->current_rates =
238 		os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
239 	if (!iface->current_rates) {
240 		wpa_printf(MSG_ERROR, "Failed to allocate memory for rate "
241 			   "table.");
242 		return -1;
243 	}
244 
245 	for (i = 0; i < mode->num_rates; i++) {
246 		struct hostapd_rate_data *rate;
247 
248 		if (iface->conf->supported_rates &&
249 		    !hostapd_rate_found(iface->conf->supported_rates,
250 					mode->rates[i]))
251 			continue;
252 
253 		rate = &iface->current_rates[iface->num_rates];
254 		rate->rate = mode->rates[i];
255 		if (hostapd_rate_found(basic_rates, rate->rate)) {
256 			rate->flags |= HOSTAPD_RATE_BASIC;
257 			num_basic_rates++;
258 		}
259 		wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
260 			   iface->num_rates, rate->rate, rate->flags);
261 		iface->num_rates++;
262 	}
263 
264 	if ((iface->num_rates == 0 || num_basic_rates == 0) &&
265 	    (!iface->conf->ieee80211n || !iface->conf->require_ht)) {
266 		wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
267 			   "rate sets (%d,%d).",
268 			   iface->num_rates, num_basic_rates);
269 		return -1;
270 	}
271 
272 	return 0;
273 }
274 
275 
ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface * iface)276 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
277 {
278 	int pri_freq, sec_freq;
279 	struct hostapd_channel_data *p_chan, *s_chan;
280 
281 	pri_freq = iface->freq;
282 	sec_freq = pri_freq + iface->conf->secondary_channel * 20;
283 
284 	if (!iface->current_mode)
285 		return 0;
286 
287 	p_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq, NULL,
288 				     iface->hw_features,
289 				     iface->num_hw_features);
290 
291 	s_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq, NULL,
292 				     iface->hw_features,
293 				     iface->num_hw_features);
294 
295 	return allowed_ht40_channel_pair(iface->current_mode->mode,
296 					 p_chan, s_chan);
297 }
298 
299 
ieee80211n_switch_pri_sec(struct hostapd_iface * iface)300 static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
301 {
302 	if (iface->conf->secondary_channel > 0) {
303 		iface->conf->channel += 4;
304 		iface->freq += 20;
305 		iface->conf->secondary_channel = -1;
306 	} else {
307 		iface->conf->channel -= 4;
308 		iface->freq -= 20;
309 		iface->conf->secondary_channel = 1;
310 	}
311 }
312 
313 
ieee80211n_check_40mhz_5g(struct hostapd_iface * iface,struct wpa_scan_results * scan_res)314 static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
315 				     struct wpa_scan_results *scan_res)
316 {
317 	unsigned int pri_freq, sec_freq;
318 	int res;
319 	struct hostapd_channel_data *pri_chan, *sec_chan;
320 
321 	pri_freq = iface->freq;
322 	sec_freq = pri_freq + iface->conf->secondary_channel * 20;
323 
324 	if (!iface->current_mode)
325 		return 0;
326 	pri_chan = hw_get_channel_freq(iface->current_mode->mode, pri_freq,
327 				       NULL, iface->hw_features,
328 				       iface->num_hw_features);
329 	sec_chan = hw_get_channel_freq(iface->current_mode->mode, sec_freq,
330 				       NULL, iface->hw_features,
331 				       iface->num_hw_features);
332 
333 	res = check_40mhz_5g(scan_res, pri_chan, sec_chan);
334 
335 	if (res == 2) {
336 		if (iface->conf->no_pri_sec_switch) {
337 			wpa_printf(MSG_DEBUG,
338 				   "Cannot switch PRI/SEC channels due to local constraint");
339 		} else {
340 			ieee80211n_switch_pri_sec(iface);
341 		}
342 	}
343 
344 	return !!res;
345 }
346 
347 
ieee80211n_check_40mhz_2g4(struct hostapd_iface * iface,struct wpa_scan_results * scan_res)348 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
349 				      struct wpa_scan_results *scan_res)
350 {
351 	int pri_chan, sec_chan;
352 
353 	pri_chan = iface->conf->channel;
354 	sec_chan = pri_chan + iface->conf->secondary_channel * 4;
355 
356 	return check_40mhz_2g4(iface->current_mode, scan_res, pri_chan,
357 			       sec_chan);
358 }
359 
360 
ieee80211n_check_scan(struct hostapd_iface * iface)361 static void ieee80211n_check_scan(struct hostapd_iface *iface)
362 {
363 	struct wpa_scan_results *scan_res;
364 	int oper40;
365 	int res = 0;
366 
367 	/* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
368 	 * allowed per IEEE Std 802.11-2012, 10.15.3.2 */
369 
370 	iface->scan_cb = NULL;
371 
372 	scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
373 	if (scan_res == NULL) {
374 		hostapd_setup_interface_complete(iface, 1);
375 		return;
376 	}
377 
378 	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
379 		oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
380 	else
381 		oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
382 	wpa_scan_results_free(scan_res);
383 
384 	iface->secondary_ch = iface->conf->secondary_channel;
385 	if (!oper40) {
386 		wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
387 			   "channel pri=%d sec=%d based on overlapping BSSes",
388 			   iface->conf->channel,
389 			   iface->conf->channel +
390 			   iface->conf->secondary_channel * 4);
391 		iface->conf->secondary_channel = 0;
392 		if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) {
393 			/*
394 			 * TODO: Could consider scheduling another scan to check
395 			 * if channel width can be changed if no coex reports
396 			 * are received from associating stations.
397 			 */
398 		}
399 	}
400 
401 #ifdef CONFIG_IEEE80211AX
402 	if (iface->conf->secondary_channel &&
403 	    iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
404 	    iface->conf->ieee80211ax) {
405 		struct he_capabilities *he_cap;
406 
407 		he_cap = &iface->current_mode->he_capab[IEEE80211_MODE_AP];
408 		if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
409 		      HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) {
410 			wpa_printf(MSG_DEBUG,
411 				   "HE: 40 MHz channel width is not supported in 2.4 GHz; clear secondary channel configuration");
412 			iface->conf->secondary_channel = 0;
413 		}
414 	}
415 #endif /* CONFIG_IEEE80211AX */
416 
417 	if (iface->conf->secondary_channel)
418 		res = ieee80211n_allowed_ht40_channel_pair(iface);
419 	if (!res) {
420 		iface->conf->secondary_channel = 0;
421 		hostapd_set_oper_centr_freq_seg0_idx(iface->conf, 0);
422 		hostapd_set_oper_centr_freq_seg1_idx(iface->conf, 0);
423 		hostapd_set_oper_chwidth(iface->conf, CONF_OPER_CHWIDTH_USE_HT);
424 		res = 1;
425 		wpa_printf(MSG_INFO, "Fallback to 20 MHz");
426 	}
427 
428 	hostapd_setup_interface_complete(iface, !res);
429 }
430 
431 
ieee80211n_scan_channels_2g4(struct hostapd_iface * iface,struct wpa_driver_scan_params * params)432 static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
433 					 struct wpa_driver_scan_params *params)
434 {
435 	/* Scan only the affected frequency range */
436 	int pri_freq, sec_freq;
437 	int affected_start, affected_end;
438 	int i, pos;
439 	struct hostapd_hw_modes *mode;
440 
441 	if (iface->current_mode == NULL)
442 		return;
443 
444 	pri_freq = iface->freq;
445 	if (iface->conf->secondary_channel > 0)
446 		sec_freq = pri_freq + 20;
447 	else
448 		sec_freq = pri_freq - 20;
449 	/*
450 	 * Note: Need to find the PRI channel also in cases where the affected
451 	 * channel is the SEC channel of a 40 MHz BSS, so need to include the
452 	 * scanning coverage here to be 40 MHz from the center frequency.
453 	 */
454 	affected_start = (pri_freq + sec_freq) / 2 - 40;
455 	affected_end = (pri_freq + sec_freq) / 2 + 40;
456 	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
457 		   affected_start, affected_end);
458 
459 	mode = iface->current_mode;
460 	params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
461 	if (params->freqs == NULL)
462 		return;
463 	pos = 0;
464 
465 	for (i = 0; i < mode->num_channels; i++) {
466 		struct hostapd_channel_data *chan = &mode->channels[i];
467 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
468 			continue;
469 		if (chan->freq < affected_start ||
470 		    chan->freq > affected_end)
471 			continue;
472 		params->freqs[pos++] = chan->freq;
473 	}
474 }
475 
476 
ieee80211n_scan_channels_5g(struct hostapd_iface * iface,struct wpa_driver_scan_params * params)477 static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface,
478 					struct wpa_driver_scan_params *params)
479 {
480 	/* Scan only the affected frequency range */
481 	int pri_freq;
482 	int affected_start, affected_end;
483 	int i, pos;
484 	struct hostapd_hw_modes *mode;
485 
486 	if (iface->current_mode == NULL)
487 		return;
488 
489 	pri_freq = iface->freq;
490 	if (iface->conf->secondary_channel > 0) {
491 		affected_start = pri_freq - 10;
492 		affected_end = pri_freq + 30;
493 	} else {
494 		affected_start = pri_freq - 30;
495 		affected_end = pri_freq + 10;
496 	}
497 	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
498 		   affected_start, affected_end);
499 
500 	mode = iface->current_mode;
501 	params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
502 	if (params->freqs == NULL)
503 		return;
504 	pos = 0;
505 
506 	for (i = 0; i < mode->num_channels; i++) {
507 		struct hostapd_channel_data *chan = &mode->channels[i];
508 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
509 			continue;
510 		if (chan->freq < affected_start ||
511 		    chan->freq > affected_end)
512 			continue;
513 		params->freqs[pos++] = chan->freq;
514 	}
515 }
516 
517 
ap_ht40_scan_retry(void * eloop_data,void * user_data)518 static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
519 {
520 #define HT2040_COEX_SCAN_RETRY 15
521 	struct hostapd_iface *iface = eloop_data;
522 	struct wpa_driver_scan_params params;
523 	int ret;
524 
525 	os_memset(&params, 0, sizeof(params));
526 	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
527 		ieee80211n_scan_channels_2g4(iface, &params);
528 	else
529 		ieee80211n_scan_channels_5g(iface, &params);
530 
531 	params.link_id = -1;
532 #ifdef CONFIG_IEEE80211BE
533 	if (iface->bss[0]->conf->mld_ap)
534 		params.link_id = iface->bss[0]->mld_link_id;
535 #endif /* CONFIG_IEEE80211BE */
536 
537 	ret = hostapd_driver_scan(iface->bss[0], &params);
538 	iface->num_ht40_scan_tries++;
539 	os_free(params.freqs);
540 
541 	if (ret == -EBUSY &&
542 	    iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) {
543 		wpa_printf(MSG_ERROR,
544 			   "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)",
545 			   ret, strerror(-ret), iface->num_ht40_scan_tries);
546 		eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
547 		return;
548 	}
549 
550 	if (ret == 0) {
551 		iface->scan_cb = ieee80211n_check_scan;
552 		iface->bss[0]->scan_cookie = params.scan_cookie;
553 		return;
554 	}
555 
556 	wpa_printf(MSG_DEBUG,
557 		   "Failed to request a scan in device, bringing up in HT20 mode");
558 	iface->conf->secondary_channel = 0;
559 	iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
560 	hostapd_setup_interface_complete(iface, 0);
561 }
562 
563 
hostapd_stop_setup_timers(struct hostapd_iface * iface)564 void hostapd_stop_setup_timers(struct hostapd_iface *iface)
565 {
566 	eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
567 }
568 
569 
ieee80211n_check_40mhz(struct hostapd_iface * iface)570 static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
571 {
572 	struct wpa_driver_scan_params params;
573 	int ret;
574 
575 	/* Check that HT40 is used and PRI / SEC switch is allowed */
576 	if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch)
577 		return 0;
578 
579 	hostapd_set_state(iface, HAPD_IFACE_HT_SCAN);
580 	wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
581 		   "40 MHz channel");
582 	os_memset(&params, 0, sizeof(params));
583 	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
584 		ieee80211n_scan_channels_2g4(iface, &params);
585 	else
586 		ieee80211n_scan_channels_5g(iface, &params);
587 
588 	params.link_id = -1;
589 #ifdef CONFIG_IEEE80211BE
590 	if (iface->bss[0]->conf->mld_ap)
591 		params.link_id = iface->bss[0]->mld_link_id;
592 #endif /* CONFIG_IEEE80211BE */
593 	ret = hostapd_driver_scan(iface->bss[0], &params);
594 	os_free(params.freqs);
595 
596 	if (ret == -EBUSY) {
597 		wpa_printf(MSG_ERROR,
598 			   "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again",
599 			   ret, strerror(-ret));
600 		iface->num_ht40_scan_tries = 1;
601 		eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
602 		eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
603 		return 1;
604 	}
605 
606 	if (ret < 0) {
607 		wpa_printf(MSG_ERROR,
608 			   "Failed to request a scan of neighboring BSSes ret=%d (%s)",
609 			   ret, strerror(-ret));
610 		return -1;
611 	}
612 
613 	iface->scan_cb = ieee80211n_check_scan;
614 	iface->bss[0]->scan_cookie = params.scan_cookie;
615 	return 1;
616 }
617 
618 
ieee80211n_supported_ht_capab(struct hostapd_iface * iface)619 static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
620 {
621 	u16 hw = iface->current_mode->ht_capab;
622 	u16 conf = iface->conf->ht_capab;
623 
624 	if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) &&
625 	    !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) {
626 		wpa_printf(MSG_ERROR, "Driver does not support configured "
627 			   "HT capability [LDPC]");
628 		return 0;
629 	}
630 
631 	/*
632 	 * Driver ACS chosen channel may not be HT40 due to internal driver
633 	 * restrictions.
634 	 */
635 	if (!iface->conf->acs && (conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
636 	    !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
637 		wpa_printf(MSG_ERROR, "Driver does not support configured "
638 			   "HT capability [HT40*]");
639 		return 0;
640 	}
641 
642 	if ((conf & HT_CAP_INFO_GREEN_FIELD) &&
643 	    !(hw & HT_CAP_INFO_GREEN_FIELD)) {
644 		wpa_printf(MSG_ERROR, "Driver does not support configured "
645 			   "HT capability [GF]");
646 		return 0;
647 	}
648 
649 	if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) &&
650 	    !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) {
651 		wpa_printf(MSG_ERROR, "Driver does not support configured "
652 			   "HT capability [SHORT-GI-20]");
653 		return 0;
654 	}
655 
656 	if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) &&
657 	    !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) {
658 		wpa_printf(MSG_ERROR, "Driver does not support configured "
659 			   "HT capability [SHORT-GI-40]");
660 		return 0;
661 	}
662 
663 	if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) {
664 		wpa_printf(MSG_ERROR, "Driver does not support configured "
665 			   "HT capability [TX-STBC]");
666 		return 0;
667 	}
668 
669 	if ((conf & HT_CAP_INFO_RX_STBC_MASK) >
670 	    (hw & HT_CAP_INFO_RX_STBC_MASK)) {
671 		wpa_printf(MSG_ERROR, "Driver does not support configured "
672 			   "HT capability [RX-STBC*]");
673 		return 0;
674 	}
675 
676 	if ((conf & HT_CAP_INFO_DELAYED_BA) &&
677 	    !(hw & HT_CAP_INFO_DELAYED_BA)) {
678 		wpa_printf(MSG_ERROR, "Driver does not support configured "
679 			   "HT capability [DELAYED-BA]");
680 		return 0;
681 	}
682 
683 	if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) &&
684 	    !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) {
685 		wpa_printf(MSG_ERROR, "Driver does not support configured "
686 			   "HT capability [MAX-AMSDU-7935]");
687 		return 0;
688 	}
689 
690 	if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) &&
691 	    !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) {
692 		wpa_printf(MSG_ERROR, "Driver does not support configured "
693 			   "HT capability [DSSS_CCK-40]");
694 		return 0;
695 	}
696 
697 	if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) &&
698 	    !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) {
699 		wpa_printf(MSG_ERROR, "Driver does not support configured "
700 			   "HT capability [LSIG-TXOP-PROT]");
701 		return 0;
702 	}
703 
704 	return 1;
705 }
706 
707 
708 #ifdef CONFIG_IEEE80211AC
ieee80211ac_supported_vht_capab(struct hostapd_iface * iface)709 static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface)
710 {
711 	struct hostapd_hw_modes *mode = iface->current_mode;
712 	u32 hw = mode->vht_capab;
713 	u32 conf = iface->conf->vht_capab;
714 
715 	wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x",
716 		   hw, conf);
717 
718 	if (mode->mode == HOSTAPD_MODE_IEEE80211G &&
719 	    iface->conf->bss[0]->vendor_vht &&
720 	    mode->vht_capab == 0 && iface->hw_features) {
721 		int i;
722 
723 		for (i = 0; i < iface->num_hw_features; i++) {
724 			if (iface->hw_features[i].mode ==
725 			    HOSTAPD_MODE_IEEE80211A) {
726 				mode = &iface->hw_features[i];
727 				hw = mode->vht_capab;
728 				wpa_printf(MSG_DEBUG,
729 					   "update hw vht capab based on 5 GHz band: 0x%x",
730 					   hw);
731 				break;
732 			}
733 		}
734 	}
735 
736 	return ieee80211ac_cap_check(hw, conf);
737 }
738 #endif /* CONFIG_IEEE80211AC */
739 
740 
741 #ifdef CONFIG_IEEE80211AX
ieee80211ax_supported_he_capab(struct hostapd_iface * iface)742 static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
743 {
744 	return 1;
745 }
746 #endif /* CONFIG_IEEE80211AX */
747 
748 
hostapd_check_ht_capab(struct hostapd_iface * iface)749 int hostapd_check_ht_capab(struct hostapd_iface *iface)
750 {
751 	int ret;
752 
753 	if (is_6ghz_freq(iface->freq))
754 		return 0;
755 	if (!iface->conf->ieee80211n)
756 		return 0;
757 
758 	if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211B &&
759 	    iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G &&
760 	    (iface->conf->ht_capab & HT_CAP_INFO_DSSS_CCK40MHZ)) {
761 		wpa_printf(MSG_DEBUG,
762 			   "Disable HT capability [DSSS_CCK-40] on 5 GHz band");
763 		iface->conf->ht_capab &= ~HT_CAP_INFO_DSSS_CCK40MHZ;
764 	}
765 
766 	if (!ieee80211n_supported_ht_capab(iface))
767 		return -1;
768 #ifdef CONFIG_IEEE80211AX
769 	if (iface->conf->ieee80211ax &&
770 	    !ieee80211ax_supported_he_capab(iface))
771 		return -1;
772 #endif /* CONFIG_IEEE80211AX */
773 #ifdef CONFIG_IEEE80211AC
774 	if (iface->conf->ieee80211ac &&
775 	    !ieee80211ac_supported_vht_capab(iface))
776 		return -1;
777 #endif /* CONFIG_IEEE80211AC */
778 	ret = ieee80211n_check_40mhz(iface);
779 	if (ret)
780 		return ret;
781 	if (!ieee80211n_allowed_ht40_channel_pair(iface))
782 		return -1;
783 
784 	return 0;
785 }
786 
787 
hostapd_check_edmg_capab(struct hostapd_iface * iface)788 int hostapd_check_edmg_capab(struct hostapd_iface *iface)
789 {
790 	struct hostapd_hw_modes *mode = iface->hw_features;
791 	struct ieee80211_edmg_config edmg;
792 
793 	if (!iface->conf->enable_edmg)
794 		return 0;
795 
796 	hostapd_encode_edmg_chan(iface->conf->enable_edmg,
797 				 iface->conf->edmg_channel,
798 				 iface->conf->channel,
799 				 &edmg);
800 
801 	if (mode->edmg.channels && ieee802_edmg_is_allowed(mode->edmg, edmg))
802 		return 0;
803 
804 	wpa_printf(MSG_WARNING, "Requested EDMG configuration is not valid");
805 	wpa_printf(MSG_INFO, "EDMG capab: channels 0x%x, bw_config %d",
806 		   mode->edmg.channels, mode->edmg.bw_config);
807 	wpa_printf(MSG_INFO,
808 		   "Requested EDMG configuration: channels 0x%x, bw_config %d",
809 		   edmg.channels, edmg.bw_config);
810 	return -1;
811 }
812 
813 
hostapd_check_he_6ghz_capab(struct hostapd_iface * iface)814 int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface)
815 {
816 #ifdef CONFIG_IEEE80211AX
817 	struct he_capabilities *he_cap;
818 	u16 hw;
819 
820 	if (!iface->current_mode || !is_6ghz_freq(iface->freq))
821 		return 0;
822 
823 	he_cap = &iface->current_mode->he_capab[IEEE80211_MODE_AP];
824 	hw = he_cap->he_6ghz_capa;
825 	if (iface->conf->he_6ghz_max_mpdu >
826 	    ((hw & HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK) >>
827 	     HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT)) {
828 		wpa_printf(MSG_ERROR,
829 			   "The driver does not support the configured HE 6 GHz Max MPDU length");
830 		return -1;
831 	}
832 
833 	if (iface->conf->he_6ghz_max_ampdu_len_exp >
834 	    ((hw & HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK) >>
835 	     HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT)) {
836 		wpa_printf(MSG_ERROR,
837 			   "The driver does not support the configured HE 6 GHz Max AMPDU Length Exponent");
838 		return -1;
839 	}
840 
841 	if (iface->conf->he_6ghz_rx_ant_pat &&
842 	    !(hw & HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS)) {
843 		wpa_printf(MSG_ERROR,
844 			   "The driver does not support the configured HE 6 GHz Rx Antenna Pattern");
845 		return -1;
846 	}
847 
848 	if (iface->conf->he_6ghz_tx_ant_pat &&
849 	    !(hw & HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS)) {
850 		wpa_printf(MSG_ERROR,
851 			   "The driver does not support the configured HE 6 GHz Tx Antenna Pattern");
852 		return -1;
853 	}
854 #endif /* CONFIG_IEEE80211AX */
855 	return 0;
856 }
857 
858 
859 /* Returns:
860  * 1 = usable
861  * 0 = not usable
862  * -1 = not currently usable due to 6 GHz NO-IR
863  */
hostapd_is_usable_chan(struct hostapd_iface * iface,int frequency,int primary)864 static int hostapd_is_usable_chan(struct hostapd_iface *iface,
865 				  int frequency, int primary)
866 {
867 	struct hostapd_channel_data *chan;
868 
869 	if (!iface->current_mode)
870 		return 0;
871 
872 	chan = hw_get_channel_freq(iface->current_mode->mode, frequency, NULL,
873 				   iface->hw_features, iface->num_hw_features);
874 	if (!chan)
875 		return 0;
876 
877 	if ((primary && chan_pri_allowed(chan)) ||
878 	    (!primary && !(chan->flag & HOSTAPD_CHAN_DISABLED)))
879 		return 1;
880 
881 	wpa_printf(MSG_INFO,
882 		   "Frequency %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
883 		   frequency, primary ? "primary" : "secondary",
884 		   chan->flag,
885 		   chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "",
886 		   chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : "");
887 
888 	if (is_6ghz_freq(chan->freq) && (chan->flag & HOSTAPD_CHAN_NO_IR))
889 		return -1;
890 
891 	return 0;
892 }
893 
894 
hostapd_is_usable_edmg(struct hostapd_iface * iface)895 static int hostapd_is_usable_edmg(struct hostapd_iface *iface)
896 {
897 	int i, contiguous = 0;
898 	int num_of_enabled = 0;
899 	int max_contiguous = 0;
900 	int err;
901 	struct ieee80211_edmg_config edmg;
902 	struct hostapd_channel_data *pri_chan;
903 
904 	if (!iface->conf->enable_edmg)
905 		return 1;
906 
907 	if (!iface->current_mode)
908 		return 0;
909 	pri_chan = hw_get_channel_freq(iface->current_mode->mode,
910 				       iface->freq, NULL,
911 				       iface->hw_features,
912 				       iface->num_hw_features);
913 	if (!pri_chan)
914 		return 0;
915 	hostapd_encode_edmg_chan(iface->conf->enable_edmg,
916 				 iface->conf->edmg_channel,
917 				 pri_chan->chan,
918 				 &edmg);
919 	if (!(edmg.channels & BIT(pri_chan->chan - 1)))
920 		return 0;
921 
922 	/* 60 GHz channels 1..6 */
923 	for (i = 0; i < 6; i++) {
924 		int freq = 56160 + 2160 * (i + 1);
925 
926 		if (edmg.channels & BIT(i)) {
927 			contiguous++;
928 			num_of_enabled++;
929 		} else {
930 			contiguous = 0;
931 			continue;
932 		}
933 
934 		/* P802.11ay defines that the total number of subfields
935 		 * set to one does not exceed 4.
936 		 */
937 		if (num_of_enabled > 4)
938 			return 0;
939 
940 		err = hostapd_is_usable_chan(iface, freq, 1);
941 		if (err <= 0)
942 			return err;
943 
944 		if (contiguous > max_contiguous)
945 			max_contiguous = contiguous;
946 	}
947 
948 	/* Check if the EDMG configuration is valid under the limitations
949 	 * of P802.11ay.
950 	 */
951 	/* check bw_config against contiguous EDMG channels */
952 	switch (edmg.bw_config) {
953 	case EDMG_BW_CONFIG_4:
954 		if (!max_contiguous)
955 			return 0;
956 		break;
957 	case EDMG_BW_CONFIG_5:
958 		if (max_contiguous < 2)
959 			return 0;
960 		break;
961 	default:
962 		return 0;
963 	}
964 
965 	return 1;
966 }
967 
968 
hostapd_is_usable_punct_bitmap(struct hostapd_iface * iface)969 static bool hostapd_is_usable_punct_bitmap(struct hostapd_iface *iface)
970 {
971 #ifdef CONFIG_IEEE80211BE
972 	struct hostapd_config *conf = iface->conf;
973 	u16 bw;
974 	u8 start_chan;
975 
976 	if (!conf->punct_bitmap)
977 		return true;
978 
979 	if (!conf->ieee80211be) {
980 		wpa_printf(MSG_ERROR,
981 			   "Currently RU puncturing is supported only if ieee80211be is enabled");
982 		return false;
983 	}
984 
985 	if (iface->freq >= 2412 && iface->freq <= 2484) {
986 		wpa_printf(MSG_ERROR,
987 			   "RU puncturing not supported in 2.4 GHz");
988 		return false;
989 	}
990 
991 	/*
992 	 * In the 6 GHz band, eht_oper_chwidth is ignored. Use operating class
993 	 * to determine channel width.
994 	 */
995 	if (conf->op_class == 137) {
996 		bw = 320;
997 		start_chan = conf->eht_oper_centr_freq_seg0_idx - 30;
998 	} else {
999 		switch (conf->eht_oper_chwidth) {
1000 		case 0:
1001 			wpa_printf(MSG_ERROR,
1002 				   "RU puncturing is supported only in 80 MHz and 160 MHz");
1003 			return false;
1004 		case 1:
1005 			bw = 80;
1006 			start_chan = conf->eht_oper_centr_freq_seg0_idx - 6;
1007 			break;
1008 		case 2:
1009 			bw = 160;
1010 			start_chan = conf->eht_oper_centr_freq_seg0_idx - 14;
1011 			break;
1012 		default:
1013 			return false;
1014 		}
1015 	}
1016 
1017 	if (!is_punct_bitmap_valid(bw, (conf->channel - start_chan) / 4,
1018 				   conf->punct_bitmap)) {
1019 		wpa_printf(MSG_ERROR, "Invalid puncturing bitmap");
1020 		return false;
1021 	}
1022 #endif /* CONFIG_IEEE80211BE */
1023 
1024 	return true;
1025 }
1026 
1027 
1028 /* Returns:
1029  * 1 = usable
1030  * 0 = not usable
1031  * -1 = not currently usable due to 6 GHz NO-IR
1032  */
hostapd_is_usable_chans(struct hostapd_iface * iface)1033 static int hostapd_is_usable_chans(struct hostapd_iface *iface)
1034 {
1035 	int secondary_freq;
1036 	struct hostapd_channel_data *pri_chan;
1037 	int err, err2;
1038 
1039 	if (!iface->current_mode)
1040 		return 0;
1041 	pri_chan = hw_get_channel_freq(iface->current_mode->mode,
1042 				       iface->freq, NULL,
1043 				       iface->hw_features,
1044 				       iface->num_hw_features);
1045 	if (!pri_chan) {
1046 		wpa_printf(MSG_ERROR, "Primary frequency not present");
1047 		return 0;
1048 	}
1049 
1050 	err = hostapd_is_usable_chan(iface, pri_chan->freq, 1);
1051 	if (err <= 0) {
1052 		wpa_printf(MSG_ERROR, "Primary frequency not allowed");
1053 		return err;
1054 	}
1055 	err = hostapd_is_usable_edmg(iface);
1056 	if (err <= 0)
1057 		return err;
1058 
1059 	if (!hostapd_is_usable_punct_bitmap(iface))
1060 		return 0;
1061 
1062 	if (!iface->conf->secondary_channel)
1063 		return 1;
1064 
1065 	err = hostapd_is_usable_chan(iface, iface->freq +
1066 				     iface->conf->secondary_channel * 20, 0);
1067 	if (err > 0) {
1068 		if (iface->conf->secondary_channel == 1 &&
1069 		    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))
1070 			return 1;
1071 		if (iface->conf->secondary_channel == -1 &&
1072 		    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M))
1073 			return 1;
1074 	}
1075 	if (!iface->conf->ht40_plus_minus_allowed)
1076 		return err;
1077 
1078 	/* Both HT40+ and HT40- are set, pick a valid secondary channel */
1079 	secondary_freq = iface->freq + 20;
1080 	err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
1081 	if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
1082 		iface->conf->secondary_channel = 1;
1083 		return 1;
1084 	}
1085 
1086 	secondary_freq = iface->freq - 20;
1087 	err2 = hostapd_is_usable_chan(iface, secondary_freq, 0);
1088 	if (err2 > 0 && (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
1089 		iface->conf->secondary_channel = -1;
1090 		return 1;
1091 	}
1092 
1093 	return err;
1094 }
1095 
1096 
skip_mode(struct hostapd_iface * iface,struct hostapd_hw_modes * mode)1097 static bool skip_mode(struct hostapd_iface *iface,
1098 		      struct hostapd_hw_modes *mode)
1099 {
1100 	int chan;
1101 
1102 	if (iface->freq > 0 && !hw_mode_get_channel(mode, iface->freq, &chan))
1103 		return true;
1104 
1105 	if (is_6ghz_op_class(iface->conf->op_class) && iface->freq == 0 &&
1106 	    !mode->is_6ghz)
1107 		return true;
1108 
1109 	return false;
1110 }
1111 
1112 
hostapd_determine_mode(struct hostapd_iface * iface)1113 int hostapd_determine_mode(struct hostapd_iface *iface)
1114 {
1115 	int i;
1116 	enum hostapd_hw_mode target_mode;
1117 
1118 	if (iface->current_mode ||
1119 	    iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
1120 		return 0;
1121 
1122 	if (iface->freq < 4000)
1123 		target_mode = HOSTAPD_MODE_IEEE80211G;
1124 	else if (iface->freq > 50000)
1125 		target_mode = HOSTAPD_MODE_IEEE80211AD;
1126 	else
1127 		target_mode = HOSTAPD_MODE_IEEE80211A;
1128 
1129 	for (i = 0; i < iface->num_hw_features; i++) {
1130 		struct hostapd_hw_modes *mode;
1131 
1132 		mode = &iface->hw_features[i];
1133 		if (mode->mode == target_mode) {
1134 			if (skip_mode(iface, mode))
1135 				continue;
1136 
1137 			iface->current_mode = mode;
1138 			iface->conf->hw_mode = mode->mode;
1139 			break;
1140 		}
1141 	}
1142 
1143 	if (!iface->current_mode) {
1144 		wpa_printf(MSG_ERROR, "ACS/CSA: Cannot decide mode");
1145 		return -1;
1146 	}
1147 	return 0;
1148 }
1149 
1150 
1151 static enum hostapd_chan_status
hostapd_check_chans(struct hostapd_iface * iface)1152 hostapd_check_chans(struct hostapd_iface *iface)
1153 {
1154 	if (iface->freq) {
1155 		int err;
1156 
1157 		hostapd_determine_mode(iface);
1158 
1159 		err = hostapd_is_usable_chans(iface);
1160 		if (err <= 0) {
1161 			if (!err)
1162 				return HOSTAPD_CHAN_INVALID;
1163 			return HOSTAPD_CHAN_INVALID_NO_IR;
1164 		}
1165 		return HOSTAPD_CHAN_VALID;
1166 	}
1167 
1168 	/*
1169 	 * The user set channel=0 or channel=acs_survey
1170 	 * which is used to trigger ACS.
1171 	 */
1172 
1173 	switch (acs_init(iface)) {
1174 	case HOSTAPD_CHAN_ACS:
1175 		return HOSTAPD_CHAN_ACS;
1176 	case HOSTAPD_CHAN_INVALID_NO_IR:
1177 		return HOSTAPD_CHAN_INVALID_NO_IR;
1178 	case HOSTAPD_CHAN_VALID:
1179 	case HOSTAPD_CHAN_INVALID:
1180 	default:
1181 		return HOSTAPD_CHAN_INVALID;
1182 	}
1183 }
1184 
1185 
hostapd_notify_bad_chans(struct hostapd_iface * iface)1186 static void hostapd_notify_bad_chans(struct hostapd_iface *iface)
1187 {
1188 	if (!iface->current_mode) {
1189 		hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
1190 			       HOSTAPD_LEVEL_WARNING,
1191 			       "Hardware does not support configured mode");
1192 		return;
1193 	}
1194 	hostapd_logger(iface->bss[0], NULL,
1195 		       HOSTAPD_MODULE_IEEE80211,
1196 		       HOSTAPD_LEVEL_WARNING,
1197 		       "Configured channel (%d) or frequency (%d) (secondary_channel=%d) not found from the channel list of the current mode (%d) %s",
1198 		       iface->conf->channel,
1199 		       iface->freq, iface->conf->secondary_channel,
1200 		       iface->current_mode->mode,
1201 		       hostapd_hw_mode_txt(iface->current_mode->mode));
1202 	hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
1203 		       HOSTAPD_LEVEL_WARNING,
1204 		       "Hardware does not support configured channel");
1205 }
1206 
1207 
hostapd_acs_completed(struct hostapd_iface * iface,int err)1208 int hostapd_acs_completed(struct hostapd_iface *iface, int err)
1209 {
1210 	int ret = -1;
1211 
1212 	if (err)
1213 		goto out;
1214 
1215 	switch (hostapd_check_chans(iface)) {
1216 	case HOSTAPD_CHAN_VALID:
1217 		iface->is_no_ir = false;
1218 		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
1219 			ACS_EVENT_COMPLETED "freq=%d channel=%d",
1220 			iface->freq, iface->conf->channel);
1221 		break;
1222 	case HOSTAPD_CHAN_ACS:
1223 		wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available");
1224 		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED);
1225 		hostapd_notify_bad_chans(iface);
1226 		goto out;
1227 	case HOSTAPD_CHAN_INVALID_NO_IR:
1228 		iface->is_no_ir = true;
1229 		/* fall through */
1230 	case HOSTAPD_CHAN_INVALID:
1231 	default:
1232 		wpa_printf(MSG_ERROR, "ACS picked unusable channels");
1233 		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED);
1234 		hostapd_notify_bad_chans(iface);
1235 		goto out;
1236 	}
1237 
1238 	ret = hostapd_check_ht_capab(iface);
1239 	if (ret < 0)
1240 		goto out;
1241 	if (ret == 1) {
1242 		wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback");
1243 		return 0;
1244 	}
1245 
1246 	ret = 0;
1247 out:
1248 	return hostapd_setup_interface_complete(iface, ret);
1249 }
1250 
1251 
1252 /**
1253  * hostapd_csa_update_hwmode - Update hardware mode
1254  * @iface: Pointer to interface data.
1255  * Returns: 0 on success, < 0 on failure
1256  *
1257  * Update hardware mode when the operating channel changed because of CSA.
1258  */
hostapd_csa_update_hwmode(struct hostapd_iface * iface)1259 int hostapd_csa_update_hwmode(struct hostapd_iface *iface)
1260 {
1261 	if (!iface || !iface->conf)
1262 		return -1;
1263 
1264 	iface->current_mode = NULL;
1265 	iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY;
1266 
1267 	return hostapd_determine_mode(iface);
1268 }
1269 
1270 
1271 /**
1272  * hostapd_select_hw_mode - Select the hardware mode
1273  * @iface: Pointer to interface data.
1274  * Returns: 0 on success, < 0 on failure
1275  *
1276  * Sets up the hardware mode, channel, rates, and passive scanning
1277  * based on the configuration.
1278  */
hostapd_select_hw_mode(struct hostapd_iface * iface)1279 int hostapd_select_hw_mode(struct hostapd_iface *iface)
1280 {
1281 	int i;
1282 
1283 	if (iface->num_hw_features < 1)
1284 		return -1;
1285 
1286 	if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G ||
1287 	     iface->conf->ieee80211n || iface->conf->ieee80211ac ||
1288 	     iface->conf->ieee80211ax || iface->conf->ieee80211be) &&
1289 	    iface->conf->channel == 14) {
1290 		wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT/HE/EHT on channel 14");
1291 		iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
1292 		iface->conf->ieee80211n = 0;
1293 		iface->conf->ieee80211ac = 0;
1294 		iface->conf->ieee80211ax = 0;
1295 		iface->conf->ieee80211be = 0;
1296 	}
1297 
1298 	iface->current_mode = NULL;
1299 	for (i = 0; i < iface->num_hw_features; i++) {
1300 		struct hostapd_hw_modes *mode = &iface->hw_features[i];
1301 
1302 		if (mode->mode == iface->conf->hw_mode) {
1303 			if (skip_mode(iface, mode))
1304 				continue;
1305 
1306 			iface->current_mode = mode;
1307 			break;
1308 		}
1309 	}
1310 
1311 	if (iface->current_mode == NULL) {
1312 		if ((iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
1313 		    (iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) {
1314 			wpa_printf(MSG_DEBUG,
1315 				   "Using offloaded hw_mode=any ACS");
1316 		} else if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) &&
1317 			   iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211ANY) {
1318 			wpa_printf(MSG_DEBUG,
1319 				   "Using internal ACS for hw_mode=any");
1320 		} else {
1321 			wpa_printf(MSG_ERROR,
1322 				   "Hardware does not support configured mode");
1323 			hostapd_logger(iface->bss[0], NULL,
1324 				       HOSTAPD_MODULE_IEEE80211,
1325 				       HOSTAPD_LEVEL_WARNING,
1326 				       "Hardware does not support configured mode (%d) (hw_mode in hostapd.conf)",
1327 				       (int) iface->conf->hw_mode);
1328 			return -2;
1329 		}
1330 	}
1331 
1332 	switch (hostapd_check_chans(iface)) {
1333 	case HOSTAPD_CHAN_VALID:
1334 		iface->is_no_ir = false;
1335 		return 0;
1336 	case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */
1337 		return 1;
1338 	case HOSTAPD_CHAN_INVALID_NO_IR:
1339 		iface->is_no_ir = true;
1340 		/* fall through */
1341 	case HOSTAPD_CHAN_INVALID:
1342 	default:
1343 		hostapd_notify_bad_chans(iface);
1344 		return -3;
1345 	}
1346 }
1347 
1348 
hostapd_hw_mode_txt(int mode)1349 const char * hostapd_hw_mode_txt(int mode)
1350 {
1351 	switch (mode) {
1352 	case HOSTAPD_MODE_IEEE80211A:
1353 		return "IEEE 802.11a";
1354 	case HOSTAPD_MODE_IEEE80211B:
1355 		return "IEEE 802.11b";
1356 	case HOSTAPD_MODE_IEEE80211G:
1357 		return "IEEE 802.11g";
1358 	case HOSTAPD_MODE_IEEE80211AD:
1359 		return "IEEE 802.11ad";
1360 	default:
1361 		return "UNKNOWN";
1362 	}
1363 }
1364 
1365 
hostapd_hw_get_freq(struct hostapd_data * hapd,int chan)1366 int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
1367 {
1368 	return hw_get_freq(hapd->iface->current_mode, chan);
1369 }
1370 
1371 
hostapd_hw_get_channel(struct hostapd_data * hapd,int freq)1372 int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
1373 {
1374 	int i, channel;
1375 	struct hostapd_hw_modes *mode;
1376 
1377 	if (hapd->iface->current_mode) {
1378 		channel = hw_get_chan(hapd->iface->current_mode->mode, freq,
1379 				      hapd->iface->hw_features,
1380 				      hapd->iface->num_hw_features);
1381 		if (channel)
1382 			return channel;
1383 	}
1384 
1385 	/* Check other available modes since the channel list for the current
1386 	 * mode did not include the specified frequency. */
1387 	if (!hapd->iface->hw_features)
1388 		return 0;
1389 	for (i = 0; i < hapd->iface->num_hw_features; i++) {
1390 		mode = &hapd->iface->hw_features[i];
1391 		channel = hw_get_chan(mode->mode, freq,
1392 				      hapd->iface->hw_features,
1393 				      hapd->iface->num_hw_features);
1394 		if (channel)
1395 			return channel;
1396 	}
1397 	return 0;
1398 }
1399 
1400 
hostapd_hw_skip_mode(struct hostapd_iface * iface,struct hostapd_hw_modes * mode)1401 int hostapd_hw_skip_mode(struct hostapd_iface *iface,
1402 			 struct hostapd_hw_modes *mode)
1403 {
1404 	int i;
1405 
1406 	if (iface->current_mode)
1407 		return mode != iface->current_mode;
1408 	if (mode->mode != HOSTAPD_MODE_IEEE80211B)
1409 		return 0;
1410 	for (i = 0; i < iface->num_hw_features; i++) {
1411 		if (iface->hw_features[i].mode == HOSTAPD_MODE_IEEE80211G)
1412 			return 1;
1413 	}
1414 	return 0;
1415 }
1416 
1417 
hostapd_free_multi_hw_info(struct hostapd_multi_hw_info * multi_hw_info)1418 void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info)
1419 {
1420 	os_free(multi_hw_info);
1421 }
1422 
1423 
hostapd_set_current_hw_info(struct hostapd_iface * iface,int oper_freq)1424 int hostapd_set_current_hw_info(struct hostapd_iface *iface, int oper_freq)
1425 {
1426 	struct hostapd_multi_hw_info *hw_info;
1427 	unsigned int i;
1428 
1429 	if (!iface->num_multi_hws)
1430 		return 0;
1431 
1432 	for (i = 0; i < iface->num_multi_hws; i++) {
1433 		hw_info = &iface->multi_hw_info[i];
1434 
1435 		if (hw_info->start_freq <= oper_freq &&
1436 		    hw_info->end_freq >= oper_freq) {
1437 			iface->current_hw_info = hw_info;
1438 			wpa_printf(MSG_DEBUG,
1439 				   "Mode: Selected underlying hardware: hw_idx=%u",
1440 				   iface->current_hw_info->hw_idx);
1441 			return 0;
1442 		}
1443 	}
1444 
1445 	return -1;
1446 }
1447