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, ¤t, &chan) < 0 && 540 1.4 christos ieee80211_freq_to_channel_ext(bss->freq, 0, 541 1.4 christos CONF_OPER_CHWIDTH_USE_HT, ¤t, 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