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 18 19 static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, u8 chan, 20 unsigned int *flags) 21 { 22 int i; 23 24 for (i = 0; i < mode->num_channels; i++) { 25 if (mode->channels[i].chan == chan) 26 break; 27 } 28 29 if (i == mode->num_channels || 30 (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)) 31 return NOT_ALLOWED; 32 33 if (flags) 34 *flags = mode->channels[i].flag; 35 36 if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR) 37 return NO_IR; 38 39 return ALLOWED; 40 } 41 42 43 static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel) 44 { 45 u8 center_channels[] = { 42, 58, 106, 122, 138, 155 }; 46 size_t i; 47 48 if (mode->mode != HOSTAPD_MODE_IEEE80211A) 49 return 0; 50 51 for (i = 0; i < ARRAY_SIZE(center_channels); i++) { 52 /* 53 * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48), 54 * so the center channel is 6 channels away from the start/end. 55 */ 56 if (channel >= center_channels[i] - 6 && 57 channel <= center_channels[i] + 6) 58 return center_channels[i]; 59 } 60 61 return 0; 62 } 63 64 65 static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, u8 channel) 66 { 67 u8 center_chan; 68 unsigned int i; 69 unsigned int no_ir = 0; 70 71 center_chan = get_center_80mhz(mode, channel); 72 if (!center_chan) 73 return NOT_ALLOWED; 74 75 /* check all the channels are available */ 76 for (i = 0; i < 4; i++) { 77 unsigned int flags; 78 u8 adj_chan = center_chan - 6 + i * 4; 79 80 if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED) 81 return NOT_ALLOWED; 82 83 if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70)) || 84 (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50)) || 85 (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30)) || 86 (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))) 87 return NOT_ALLOWED; 88 89 if (flags & HOSTAPD_CHAN_NO_IR) 90 no_ir = 1; 91 } 92 93 if (no_ir) 94 return NO_IR; 95 96 return ALLOWED; 97 } 98 99 100 static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel) 101 { 102 u8 center_channels[] = { 50, 114 }; 103 unsigned int i; 104 105 if (mode->mode != HOSTAPD_MODE_IEEE80211A) 106 return 0; 107 108 for (i = 0; i < ARRAY_SIZE(center_channels); i++) { 109 /* 110 * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64), 111 * so the center channel is 14 channels away from the start/end. 112 */ 113 if (channel >= center_channels[i] - 14 && 114 channel <= center_channels[i] + 14) 115 return center_channels[i]; 116 } 117 118 return 0; 119 } 120 121 122 static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode, 123 u8 channel) 124 { 125 u8 center_chan; 126 unsigned int i; 127 unsigned int no_ir = 0; 128 129 center_chan = get_center_160mhz(mode, channel); 130 if (!center_chan) 131 return NOT_ALLOWED; 132 133 /* Check all the channels are available */ 134 for (i = 0; i < 8; i++) { 135 unsigned int flags; 136 u8 adj_chan = center_chan - 14 + i * 4; 137 138 if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED) 139 return NOT_ALLOWED; 140 141 if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150)) || 142 (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130)) || 143 (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110)) || 144 (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90)) || 145 (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70)) || 146 (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50)) || 147 (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30)) || 148 (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))) 149 return NOT_ALLOWED; 150 151 if (flags & HOSTAPD_CHAN_NO_IR) 152 no_ir = 1; 153 } 154 155 if (no_ir) 156 return NO_IR; 157 158 return ALLOWED; 159 } 160 161 162 enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel, 163 u8 bw) 164 { 165 unsigned int flag = 0; 166 enum chan_allowed res, res2; 167 168 res2 = res = allow_channel(mode, channel, &flag); 169 if (bw == BW40MINUS) { 170 if (!(flag & HOSTAPD_CHAN_HT40MINUS)) 171 return NOT_ALLOWED; 172 res2 = allow_channel(mode, channel - 4, NULL); 173 } else if (bw == BW40PLUS) { 174 if (!(flag & HOSTAPD_CHAN_HT40PLUS)) 175 return NOT_ALLOWED; 176 res2 = allow_channel(mode, channel + 4, NULL); 177 } else if (bw == BW80) { 178 /* 179 * channel is a center channel and as such, not necessarily a 180 * valid 20 MHz channels. Override earlier allow_channel() 181 * result and use only the 80 MHz specific version. 182 */ 183 res2 = res = verify_80mhz(mode, channel); 184 } else if (bw == BW160) { 185 /* 186 * channel is a center channel and as such, not necessarily a 187 * valid 20 MHz channels. Override earlier allow_channel() 188 * result and use only the 160 MHz specific version. 189 */ 190 res2 = res = verify_160mhz(mode, channel); 191 } else if (bw == BW80P80) { 192 /* 193 * channel is a center channel and as such, not necessarily a 194 * valid 20 MHz channels. Override earlier allow_channel() 195 * result and use only the 80 MHz specific version. 196 */ 197 res2 = res = verify_80mhz(mode, channel); 198 } 199 200 if (res == NOT_ALLOWED || res2 == NOT_ALLOWED) 201 return NOT_ALLOWED; 202 203 if (res == NO_IR || res2 == NO_IR) 204 return NO_IR; 205 206 return ALLOWED; 207 } 208 209 210 static int wpas_op_class_supported(struct wpa_supplicant *wpa_s, 211 struct wpa_ssid *ssid, 212 const struct oper_class_map *op_class) 213 { 214 int chan; 215 size_t i; 216 struct hostapd_hw_modes *mode; 217 int found; 218 int z; 219 int freq2 = 0; 220 int freq5 = 0; 221 222 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode); 223 if (!mode) 224 return 0; 225 226 /* If we are configured to disable certain things, take that into 227 * account here. */ 228 if (ssid->freq_list && ssid->freq_list[0]) { 229 for (z = 0; ; z++) { 230 int f = ssid->freq_list[z]; 231 232 if (f == 0) 233 break; /* end of list */ 234 if (f > 4000 && f < 6000) 235 freq5 = 1; 236 else if (f > 2400 && f < 2500) 237 freq2 = 1; 238 } 239 } else { 240 /* No frequencies specified, can use anything hardware supports. 241 */ 242 freq2 = freq5 = 1; 243 } 244 245 if (op_class->op_class >= 115 && op_class->op_class <= 130 && !freq5) 246 return 0; 247 if (op_class->op_class >= 81 && op_class->op_class <= 84 && !freq2) 248 return 0; 249 250 #ifdef CONFIG_HT_OVERRIDES 251 if (ssid->disable_ht) { 252 switch (op_class->op_class) { 253 case 83: 254 case 84: 255 case 104: 256 case 105: 257 case 116: 258 case 117: 259 case 119: 260 case 120: 261 case 122: 262 case 123: 263 case 126: 264 case 127: 265 case 128: 266 case 129: 267 case 130: 268 /* Disable >= 40 MHz channels if HT is disabled */ 269 return 0; 270 } 271 } 272 #endif /* CONFIG_HT_OVERRIDES */ 273 274 #ifdef CONFIG_VHT_OVERRIDES 275 if (ssid->disable_vht) { 276 if (op_class->op_class >= 128 && op_class->op_class <= 130) { 277 /* Disable >= 80 MHz channels if VHT is disabled */ 278 return 0; 279 } 280 } 281 #endif /* CONFIG_VHT_OVERRIDES */ 282 283 if (op_class->op_class == 128) { 284 u8 channels[] = { 42, 58, 106, 122, 138, 155 }; 285 286 for (i = 0; i < ARRAY_SIZE(channels); i++) { 287 if (verify_channel(mode, channels[i], op_class->bw) != 288 NOT_ALLOWED) 289 return 1; 290 } 291 292 return 0; 293 } 294 295 if (op_class->op_class == 129) { 296 /* Check if either 160 MHz channels is allowed */ 297 return verify_channel(mode, 50, op_class->bw) != NOT_ALLOWED || 298 verify_channel(mode, 114, op_class->bw) != NOT_ALLOWED; 299 } 300 301 if (op_class->op_class == 130) { 302 /* Need at least two non-contiguous 80 MHz segments */ 303 found = 0; 304 305 if (verify_channel(mode, 42, op_class->bw) != NOT_ALLOWED || 306 verify_channel(mode, 58, op_class->bw) != NOT_ALLOWED) 307 found++; 308 if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED || 309 verify_channel(mode, 122, op_class->bw) != NOT_ALLOWED || 310 verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED) 311 found++; 312 if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED && 313 verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED) 314 found++; 315 if (verify_channel(mode, 155, op_class->bw) != NOT_ALLOWED) 316 found++; 317 318 if (found >= 2) 319 return 1; 320 321 return 0; 322 } 323 324 found = 0; 325 for (chan = op_class->min_chan; chan <= op_class->max_chan; 326 chan += op_class->inc) { 327 if (verify_channel(mode, chan, op_class->bw) != NOT_ALLOWED) { 328 found = 1; 329 break; 330 } 331 } 332 333 return found; 334 } 335 336 337 size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, 338 struct wpa_ssid *ssid, 339 int freq, u8 *pos, size_t len) 340 { 341 struct wpabuf *buf; 342 u8 op, current, chan; 343 u8 *ie_len; 344 size_t res; 345 346 /* 347 * Assume 20 MHz channel for now. 348 * TODO: Use the secondary channel and VHT channel width that will be 349 * used after association. 350 */ 351 if (ieee80211_freq_to_channel_ext(freq, 0, CHANWIDTH_USE_HT, 352 ¤t, &chan) == NUM_HOSTAPD_MODES) 353 return 0; 354 355 /* 356 * Need 3 bytes for EID, length, and current operating class, plus 357 * 1 byte for every other supported operating class. 358 */ 359 buf = wpabuf_alloc(global_op_class_size + 3); 360 if (!buf) 361 return 0; 362 363 wpabuf_put_u8(buf, WLAN_EID_SUPPORTED_OPERATING_CLASSES); 364 /* Will set the length later, putting a placeholder */ 365 ie_len = wpabuf_put(buf, 1); 366 wpabuf_put_u8(buf, current); 367 368 for (op = 0; global_op_class[op].op_class; op++) { 369 if (wpas_op_class_supported(wpa_s, ssid, &global_op_class[op])) 370 wpabuf_put_u8(buf, global_op_class[op].op_class); 371 } 372 373 *ie_len = wpabuf_len(buf) - 2; 374 if (*ie_len < 2 || wpabuf_len(buf) > len) { 375 wpa_printf(MSG_ERROR, 376 "Failed to add supported operating classes IE"); 377 res = 0; 378 } else { 379 os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf)); 380 res = wpabuf_len(buf); 381 wpa_hexdump_buf(MSG_DEBUG, 382 "Added supported operating classes IE", buf); 383 } 384 385 wpabuf_free(buf); 386 return res; 387 } 388