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