xref: /freebsd/contrib/wpa/wpa_supplicant/op_classes.c (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
1 /*
2  * Operating classes
3  * Copyright(c) 2015 Intel Deutschland GmbH
4  * Contact Information:
5  * Intel Linux Wireless <ilw@linux.intel.com>
6  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
7  *
8  * This software may be distributed under the terms of the BSD license.
9  * See README for more details.
10  */
11 
12 #include "utils/includes.h"
13 
14 #include "utils/common.h"
15 #include "common/ieee802_11_common.h"
16 #include "wpa_supplicant_i.h"
17 #include "bss.h"
18 
19 
20 static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode,
21 				       u8 op_class, u8 chan,
22 				       unsigned int *flags)
23 {
24 	int i;
25 	bool is_6ghz = is_6ghz_op_class(op_class);
26 
27 	for (i = 0; i < mode->num_channels; i++) {
28 		bool chan_is_6ghz;
29 
30 		chan_is_6ghz = is_6ghz_freq(mode->channels[i].freq);
31 		if (is_6ghz == chan_is_6ghz && mode->channels[i].chan == chan)
32 			break;
33 	}
34 
35 	if (i == mode->num_channels ||
36 	    (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED))
37 		return NOT_ALLOWED;
38 
39 	if (flags)
40 		*flags = mode->channels[i].flag;
41 
42 	if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR)
43 		return NO_IR;
44 
45 	return ALLOWED;
46 }
47 
48 
49 static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel,
50 			    const u8 *center_channels, size_t num_chan)
51 {
52 	size_t i;
53 
54 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
55 		return 0;
56 
57 	for (i = 0; i < num_chan; i++) {
58 		/*
59 		 * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
60 		 * so the center channel is 6 channels away from the start/end.
61 		 */
62 		if (channel >= center_channels[i] - 6 &&
63 		    channel <= center_channels[i] + 6)
64 			return center_channels[i];
65 	}
66 
67 	return 0;
68 }
69 
70 
71 static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode,
72 				      u8 op_class, u8 channel)
73 {
74 	u8 center_chan;
75 	unsigned int i;
76 	unsigned int no_ir = 0;
77 	const u8 *center_channels;
78 	size_t num_chan;
79 	const u8 center_channels_5ghz[] = { 42, 58, 106, 122, 138, 155, 171 };
80 	const u8 center_channels_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119,
81 					    135, 151, 167, 183, 199, 215 };
82 
83 	if (is_6ghz_op_class(op_class)) {
84 		center_channels = center_channels_6ghz;
85 		num_chan = ARRAY_SIZE(center_channels_6ghz);
86 	} else {
87 		center_channels = center_channels_5ghz;
88 		num_chan = ARRAY_SIZE(center_channels_5ghz);
89 	}
90 
91 	center_chan = get_center_80mhz(mode, channel, center_channels,
92 				       num_chan);
93 	if (!center_chan)
94 		return NOT_ALLOWED;
95 
96 	/* check all the channels are available */
97 	for (i = 0; i < 4; i++) {
98 		unsigned int flags;
99 		u8 adj_chan = center_chan - 6 + i * 4;
100 
101 		if (allow_channel(mode, op_class, adj_chan, &flags) ==
102 		    NOT_ALLOWED)
103 			return NOT_ALLOWED;
104 
105 		if (!(flags & HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL))
106 			return NOT_ALLOWED;
107 
108 		if (flags & HOSTAPD_CHAN_NO_IR)
109 			no_ir = 1;
110 	}
111 
112 	if (no_ir)
113 		return NO_IR;
114 
115 	return ALLOWED;
116 }
117 
118 
119 static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel,
120 			     const u8 *center_channels, size_t num_chan)
121 {
122 	unsigned int i;
123 
124 	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
125 		return 0;
126 
127 	for (i = 0; i < num_chan; i++) {
128 		/*
129 		 * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
130 		 * so the center channel is 14 channels away from the start/end.
131 		 */
132 		if (channel >= center_channels[i] - 14 &&
133 		    channel <= center_channels[i] + 14)
134 			return center_channels[i];
135 	}
136 
137 	return 0;
138 }
139 
140 
141 static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode,
142 				       u8 op_class, u8 channel)
143 {
144 	u8 center_chan;
145 	unsigned int i;
146 	unsigned int no_ir = 0;
147 	const u8 *center_channels;
148 	size_t num_chan;
149 	const u8 center_channels_5ghz[] = { 50, 114, 163 };
150 	const u8 center_channels_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 };
151 
152 	if (is_6ghz_op_class(op_class)) {
153 		center_channels = center_channels_6ghz;
154 		num_chan = ARRAY_SIZE(center_channels_6ghz);
155 	} else {
156 		center_channels = center_channels_5ghz;
157 		num_chan = ARRAY_SIZE(center_channels_5ghz);
158 	}
159 
160 	center_chan = get_center_160mhz(mode, channel, center_channels,
161 					num_chan);
162 	if (!center_chan)
163 		return NOT_ALLOWED;
164 
165 	/* Check all the channels are available */
166 	for (i = 0; i < 8; i++) {
167 		unsigned int flags;
168 		u8 adj_chan = center_chan - 14 + i * 4;
169 
170 		if (allow_channel(mode, op_class, adj_chan, &flags) ==
171 		    NOT_ALLOWED)
172 			return NOT_ALLOWED;
173 
174 		if (!(flags & HOSTAPD_CHAN_VHT_80MHZ_SUBCHANNEL) ||
175 		    !(flags & HOSTAPD_CHAN_VHT_160MHZ_SUBCHANNEL))
176 			return NOT_ALLOWED;
177 
178 		if (flags & HOSTAPD_CHAN_NO_IR)
179 			no_ir = 1;
180 	}
181 
182 	if (no_ir)
183 		return NO_IR;
184 
185 	return ALLOWED;
186 }
187 
188 
189 static int get_center_320mhz(struct hostapd_hw_modes *mode, u8 channel,
190 			     const u8 *center_channels, size_t num_chan)
191 {
192 	unsigned int i;
193 
194 	if (mode->mode != HOSTAPD_MODE_IEEE80211A || !mode->is_6ghz)
195 		return 0;
196 
197 	for (i = 0; i < num_chan; i++) {
198 		/*
199 		* In 320 MHz, the bandwidth "spans" 60 channels (e.g., 65-125),
200 		* so the center channel is 30 channels away from the start/end.
201 		*/
202 		if (channel >= center_channels[i] - 30 &&
203 		    channel <= center_channels[i] + 30)
204 			return center_channels[i];
205 	}
206 
207 	return 0;
208 }
209 
210 
211 static enum chan_allowed verify_320mhz(struct hostapd_hw_modes *mode,
212 				       u8 op_class, u8 channel)
213 {
214 	u8 center_chan;
215 	unsigned int i;
216 	bool no_ir = false;
217 	const u8 *center_channels;
218 	size_t num_chan;
219 	const u8 center_channels_6ghz[] = { 31, 63, 95, 127, 159, 191 };
220 
221 	center_channels = center_channels_6ghz;
222 	num_chan = ARRAY_SIZE(center_channels_6ghz);
223 
224 	center_chan = get_center_320mhz(mode, channel, center_channels,
225 					num_chan);
226 	if (!center_chan)
227 		return NOT_ALLOWED;
228 
229 	/* Check all the channels are available */
230 	for (i = 0; i < 16; i++) {
231 		unsigned int flags;
232 		u8 adj_chan = center_chan - 30 + i * 4;
233 
234 		if (allow_channel(mode, op_class, adj_chan, &flags) ==
235 		    NOT_ALLOWED)
236 			return NOT_ALLOWED;
237 
238 		if (!(flags & HOSTAPD_CHAN_EHT_320MHZ_SUBCHANNEL))
239 			return NOT_ALLOWED;
240 
241 		if (flags & HOSTAPD_CHAN_NO_IR)
242 			no_ir = true;
243 	}
244 
245 	if (no_ir)
246 		return NO_IR;
247 
248 	return ALLOWED;
249 }
250 
251 
252 enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
253 				 u8 channel, u8 bw)
254 {
255 	unsigned int flag = 0;
256 	enum chan_allowed res, res2;
257 
258 	res2 = res = allow_channel(mode, op_class, channel, &flag);
259 	if (bw == BW40MINUS || (bw == BW40 && (((channel - 1) / 4) % 2))) {
260 		if (!(flag & HOSTAPD_CHAN_HT40MINUS))
261 			return NOT_ALLOWED;
262 		res2 = allow_channel(mode, op_class, channel - 4, NULL);
263 	} else if (bw == BW40PLUS) {
264 		if (!(flag & HOSTAPD_CHAN_HT40PLUS))
265 			return NOT_ALLOWED;
266 		res2 = allow_channel(mode, op_class, channel + 4, NULL);
267 	} else if (is_6ghz_op_class(op_class) && bw == BW40) {
268 		if (get_6ghz_sec_channel(channel) < 0)
269 			res2 = allow_channel(mode, op_class, channel - 4, NULL);
270 		else
271 			res2 = allow_channel(mode, op_class, channel + 4, NULL);
272 	} else if (bw == BW80) {
273 		/*
274 		 * channel is a center channel and as such, not necessarily a
275 		 * valid 20 MHz channels. Override earlier allow_channel()
276 		 * result and use only the 80 MHz specific version.
277 		 */
278 		res2 = res = verify_80mhz(mode, op_class, channel);
279 	} else if (bw == BW160) {
280 		/*
281 		 * channel is a center channel and as such, not necessarily a
282 		 * valid 20 MHz channels. Override earlier allow_channel()
283 		 * result and use only the 160 MHz specific version.
284 		 */
285 		res2 = res = verify_160mhz(mode, op_class, channel);
286 	} else if (bw == BW80P80) {
287 		/*
288 		 * channel is a center channel and as such, not necessarily a
289 		 * valid 20 MHz channels. Override earlier allow_channel()
290 		 * result and use only the 80 MHz specific version.
291 		 */
292 		res2 = res = verify_80mhz(mode, op_class, channel);
293 	} else if (bw == BW320) {
294 		/*
295 		 * channel is a center channel and as such, not necessarily a
296 		 * valid 20 MHz channels. Override earlier allow_channel()
297 		 * result and use only the 320 MHz specific version.
298 		 */
299 		res2= res = verify_320mhz(mode, op_class, channel);
300 	}
301 
302 	if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
303 		return NOT_ALLOWED;
304 
305 	if (res == NO_IR || res2 == NO_IR)
306 		return NO_IR;
307 
308 	return ALLOWED;
309 }
310 
311 
312 static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
313 				   struct wpa_ssid *ssid,
314 				   const struct oper_class_map *op_class)
315 {
316 	int chan;
317 	size_t i;
318 	struct hostapd_hw_modes *mode;
319 	int found;
320 	int z;
321 	int freq2 = 0;
322 	int freq5 = 0;
323 	bool freq6 = false;
324 
325 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode,
326 			is_6ghz_op_class(op_class->op_class));
327 	if (!mode)
328 		return 0;
329 
330 	/* If we are configured to disable certain things, take that into
331 	 * account here. */
332 	if (ssid && ssid->freq_list && ssid->freq_list[0]) {
333 		for (z = 0; ; z++) {
334 			int f = ssid->freq_list[z];
335 
336 			if (f == 0)
337 				break; /* end of list */
338 			if (is_6ghz_freq(f))
339 				freq6 = true;
340 			else if (f > 4000 && f < 6000)
341 				freq5 = 1;
342 			else if (f > 2400 && f < 2500)
343 				freq2 = 1;
344 		}
345 	} else {
346 		/* No frequencies specified, can use anything hardware supports.
347 		 */
348 		freq2 = freq5 = 1;
349 		freq6 = true;
350 	}
351 
352 	if (is_6ghz_op_class(op_class->op_class) && !freq6)
353 		return 0;
354 	if (op_class->op_class >= 115 && op_class->op_class <= 130 && !freq5)
355 		return 0;
356 	if (op_class->op_class >= 81 && op_class->op_class <= 84 && !freq2)
357 		return 0;
358 
359 #ifdef CONFIG_HT_OVERRIDES
360 	if (ssid && ssid->disable_ht) {
361 		switch (op_class->op_class) {
362 		case 83:
363 		case 84:
364 		case 104:
365 		case 105:
366 		case 116:
367 		case 117:
368 		case 119:
369 		case 120:
370 		case 122:
371 		case 123:
372 		case 126:
373 		case 127:
374 		case 128:
375 		case 129:
376 		case 130:
377 			/* Disable >= 40 MHz channels if HT is disabled */
378 			return 0;
379 		}
380 	}
381 #endif /* CONFIG_HT_OVERRIDES */
382 
383 #ifdef CONFIG_VHT_OVERRIDES
384 	if (ssid && ssid->disable_vht) {
385 		if (op_class->op_class >= 128 && op_class->op_class <= 130) {
386 			/* Disable >= 80 MHz channels if VHT is disabled */
387 			return 0;
388 		}
389 	}
390 #endif /* CONFIG_VHT_OVERRIDES */
391 
392 	if (op_class->op_class == 128) {
393 		u8 channels[] = { 42, 58, 106, 122, 138, 155, 171 };
394 
395 		for (i = 0; i < ARRAY_SIZE(channels); i++) {
396 			if (verify_channel(mode, op_class->op_class,
397 					   channels[i], op_class->bw) !=
398 			    NOT_ALLOWED)
399 				return 1;
400 		}
401 
402 		return 0;
403 	}
404 
405 	if (op_class->op_class == 129) {
406 		/* Check if either 160 MHz channels is allowed */
407 		return verify_channel(mode, op_class->op_class, 50,
408 				      op_class->bw) != NOT_ALLOWED ||
409 			verify_channel(mode, op_class->op_class, 114,
410 				       op_class->bw) != NOT_ALLOWED ||
411 			verify_channel(mode, op_class->op_class, 163,
412 				       op_class->bw) != NOT_ALLOWED;
413 	}
414 
415 	if (op_class->op_class == 130) {
416 		/* Need at least two non-contiguous 80 MHz segments */
417 		found = 0;
418 
419 		if (verify_channel(mode, op_class->op_class, 42,
420 				   op_class->bw) != NOT_ALLOWED ||
421 		    verify_channel(mode, op_class->op_class, 58,
422 				   op_class->bw) != NOT_ALLOWED)
423 			found++;
424 		if (verify_channel(mode, op_class->op_class, 106,
425 				   op_class->bw) != NOT_ALLOWED ||
426 		    verify_channel(mode, op_class->op_class, 122,
427 				   op_class->bw) != NOT_ALLOWED ||
428 		    verify_channel(mode, op_class->op_class, 138,
429 				   op_class->bw) != NOT_ALLOWED ||
430 		    verify_channel(mode, op_class->op_class, 155,
431 				   op_class->bw) != NOT_ALLOWED ||
432 		    verify_channel(mode, op_class->op_class, 171,
433 				   op_class->bw) != NOT_ALLOWED)
434 			found++;
435 		if (verify_channel(mode, op_class->op_class, 106,
436 				   op_class->bw) != NOT_ALLOWED &&
437 		    verify_channel(mode, op_class->op_class, 138,
438 				   op_class->bw) != NOT_ALLOWED)
439 			found++;
440 		if (verify_channel(mode, op_class->op_class, 122,
441 				   op_class->bw) != NOT_ALLOWED &&
442 		    verify_channel(mode, op_class->op_class, 155,
443 				   op_class->bw) != NOT_ALLOWED)
444 			found++;
445 		if (verify_channel(mode, op_class->op_class, 138,
446 				   op_class->bw) != NOT_ALLOWED &&
447 		    verify_channel(mode, op_class->op_class, 171,
448 				   op_class->bw) != NOT_ALLOWED)
449 			found++;
450 
451 		if (found >= 2)
452 			return 1;
453 
454 		return 0;
455 	}
456 
457 	if (op_class->op_class == 135) {
458 		/* Need at least two 80 MHz segments which do not fall under the
459 		 * same 160 MHz segment to support 80+80 in 6 GHz.
460 		 */
461 		int first_seg = 0;
462 		int curr_seg = 0;
463 
464 		for (chan = op_class->min_chan; chan <= op_class->max_chan;
465 		     chan += op_class->inc) {
466 			curr_seg++;
467 			if (verify_channel(mode, op_class->op_class, chan,
468 					   op_class->bw) != NOT_ALLOWED) {
469 				if (!first_seg) {
470 					first_seg = curr_seg;
471 					continue;
472 				}
473 
474 				/* Supported if at least two non-consecutive 80
475 				 * MHz segments allowed.
476 				 */
477 				if ((curr_seg - first_seg) > 1)
478 					return 1;
479 
480 				/* Supported even if the 80 MHz segments are
481 				 * consecutive when they do not fall under the
482 				 * same 160 MHz segment.
483 				 */
484 				if ((first_seg % 2) == 0)
485 					return 1;
486 			}
487 		}
488 
489 		return 0;
490 	}
491 
492 	found = 0;
493 	for (chan = op_class->min_chan; chan <= op_class->max_chan;
494 	     chan += op_class->inc) {
495 		if (verify_channel(mode, op_class->op_class, chan,
496 				   op_class->bw) != NOT_ALLOWED) {
497 			found = 1;
498 			break;
499 		}
500 	}
501 
502 	return found;
503 }
504 
505 
506 static int wpas_sta_secondary_channel_offset(struct wpa_bss *bss, u8 *current,
507 					     u8 *channel)
508 {
509 
510 	const u8 *ies;
511 	u8 phy_type;
512 	size_t ies_len;
513 
514 	if (!bss)
515 		return -1;
516 	ies = wpa_bss_ie_ptr(bss);
517 	ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
518 	return wpas_get_op_chan_phy(bss->freq, ies, ies_len, current,
519 				    channel, &phy_type);
520 }
521 
522 
523 size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
524 			     struct wpa_ssid *ssid,
525 			     struct wpa_bss *bss, u8 *pos, size_t len)
526 {
527 	struct wpabuf *buf;
528 	u8 op, current, chan;
529 	u8 *ie_len;
530 	size_t res;
531 	bool op128 = false, op130 = false, op133 = false, op135 = false;
532 
533 	/*
534 	 * Determine the current operating class correct mode based on
535 	 * advertised BSS capabilities, if available. Fall back to a less
536 	 * accurate guess based on frequency if the needed IEs are not available
537 	 * or used.
538 	 */
539 	if (wpas_sta_secondary_channel_offset(bss, &current, &chan) < 0 &&
540 	    ieee80211_freq_to_channel_ext(bss->freq, 0,
541 					  CONF_OPER_CHWIDTH_USE_HT, &current,
542 					  &chan) == NUM_HOSTAPD_MODES)
543 		return 0;
544 
545 	/*
546 	 * Need 3 bytes for EID, length, and current operating class, plus
547 	 * 1 byte for every other supported operating class.
548 	 */
549 	buf = wpabuf_alloc(global_op_class_size + 3);
550 	if (!buf)
551 		return 0;
552 
553 	wpabuf_put_u8(buf, WLAN_EID_SUPPORTED_OPERATING_CLASSES);
554 	/* Will set the length later, putting a placeholder */
555 	ie_len = wpabuf_put(buf, 1);
556 	wpabuf_put_u8(buf, current);
557 
558 	for (op = 0; global_op_class[op].op_class; op++) {
559 		bool supp;
560 		u8 op_class = global_op_class[op].op_class;
561 
562 		supp = wpas_op_class_supported(wpa_s, ssid,
563 					       &global_op_class[op]);
564 		if (!supp)
565 			continue;
566 		switch (op_class) {
567 		case 128:
568 			op128 = true;
569 			break;
570 		case 130:
571 			op130 = true;
572 			break;
573 		case 133:
574 			op133 = true;
575 			break;
576 		case 135:
577 			op135 = true;
578 			break;
579 		}
580 		if (is_80plus_op_class(op_class))
581 			continue;
582 
583 		/* Add a 1-octet operating class to the Operating Class field */
584 		wpabuf_put_u8(buf, global_op_class[op].op_class);
585 	}
586 
587 	/* Add the 2-octet operating classes (i.e., 80+80 MHz cases), if any */
588 	if ((op128 && op130) || (op133 && op135)) {
589 		/* Operating Class Duple Sequence field */
590 
591 		/* Zero Delimiter */
592 		wpabuf_put_u8(buf, 0);
593 
594 		/* Operating Class Duple List */
595 		if (op128 && op130) {
596 			wpabuf_put_u8(buf, 130);
597 			wpabuf_put_u8(buf, 128);
598 		}
599 		if (op133 && op135) {
600 			wpabuf_put_u8(buf, 135);
601 			wpabuf_put_u8(buf, 133);
602 		}
603 	}
604 
605 	*ie_len = wpabuf_len(buf) - 2;
606 	if (*ie_len < 2) {
607 		wpa_printf(MSG_DEBUG,
608 			   "No supported operating classes IE to add");
609 		res = 0;
610 	} else if (wpabuf_len(buf) > len) {
611 		wpa_printf(MSG_ERROR,
612 			   "Supported operating classes IE exceeds maximum buffer length");
613 		res = 0;
614 	} else {
615 		os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf));
616 		res = wpabuf_len(buf);
617 		wpa_hexdump_buf(MSG_DEBUG,
618 				"Added supported operating classes IE", buf);
619 	}
620 
621 	wpabuf_free(buf);
622 	return res;
623 }
624 
625 
626 int * wpas_supp_op_classes(struct wpa_supplicant *wpa_s)
627 {
628 	int op;
629 	unsigned int pos, max_num = 0;
630 	int *classes;
631 
632 	for (op = 0; global_op_class[op].op_class; op++)
633 		max_num++;
634 	classes = os_zalloc((max_num + 1) * sizeof(int));
635 	if (!classes)
636 		return NULL;
637 
638 	for (op = 0, pos = 0; global_op_class[op].op_class; op++) {
639 		if (wpas_op_class_supported(wpa_s, NULL, &global_op_class[op]))
640 			classes[pos++] = global_op_class[op].op_class;
641 	}
642 
643 	return classes;
644 }
645