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