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 const struct oper_class_map *op_class) 212 { 213 int chan; 214 size_t i; 215 struct hostapd_hw_modes *mode; 216 int found; 217 218 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode); 219 if (!mode) 220 return 0; 221 222 if (op_class->op_class == 128) { 223 u8 channels[] = { 42, 58, 106, 122, 138, 155 }; 224 225 for (i = 0; i < ARRAY_SIZE(channels); i++) { 226 if (verify_channel(mode, channels[i], op_class->bw) != 227 NOT_ALLOWED) 228 return 1; 229 } 230 231 return 0; 232 } 233 234 if (op_class->op_class == 129) { 235 /* Check if either 160 MHz channels is allowed */ 236 return verify_channel(mode, 50, op_class->bw) != NOT_ALLOWED || 237 verify_channel(mode, 114, op_class->bw) != NOT_ALLOWED; 238 } 239 240 if (op_class->op_class == 130) { 241 /* Need at least two non-contiguous 80 MHz segments */ 242 found = 0; 243 244 if (verify_channel(mode, 42, op_class->bw) != NOT_ALLOWED || 245 verify_channel(mode, 58, op_class->bw) != NOT_ALLOWED) 246 found++; 247 if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED || 248 verify_channel(mode, 122, op_class->bw) != NOT_ALLOWED || 249 verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED) 250 found++; 251 if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED && 252 verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED) 253 found++; 254 if (verify_channel(mode, 155, op_class->bw) != NOT_ALLOWED) 255 found++; 256 257 if (found >= 2) 258 return 1; 259 260 return 0; 261 } 262 263 found = 0; 264 for (chan = op_class->min_chan; chan <= op_class->max_chan; 265 chan += op_class->inc) { 266 if (verify_channel(mode, chan, op_class->bw) != NOT_ALLOWED) { 267 found = 1; 268 break; 269 } 270 } 271 272 return found; 273 } 274 275 276 size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos, 277 size_t len) 278 { 279 struct wpabuf *buf; 280 u8 op, current, chan; 281 u8 *ie_len; 282 size_t res; 283 284 /* 285 * Assume 20 MHz channel for now. 286 * TODO: Use the secondary channel and VHT channel width that will be 287 * used after association. 288 */ 289 if (ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT, 290 ¤t, &chan) == NUM_HOSTAPD_MODES) 291 return 0; 292 293 /* 294 * Need 3 bytes for EID, length, and current operating class, plus 295 * 1 byte for every other supported operating class. 296 */ 297 buf = wpabuf_alloc(global_op_class_size + 3); 298 if (!buf) 299 return 0; 300 301 wpabuf_put_u8(buf, WLAN_EID_SUPPORTED_OPERATING_CLASSES); 302 /* Will set the length later, putting a placeholder */ 303 ie_len = wpabuf_put(buf, 1); 304 wpabuf_put_u8(buf, current); 305 306 for (op = 0; global_op_class[op].op_class; op++) { 307 if (wpas_op_class_supported(wpa_s, &global_op_class[op])) 308 wpabuf_put_u8(buf, global_op_class[op].op_class); 309 } 310 311 *ie_len = wpabuf_len(buf) - 2; 312 if (*ie_len < 2 || wpabuf_len(buf) > len) { 313 wpa_printf(MSG_ERROR, 314 "Failed to add supported operating classes IE"); 315 res = 0; 316 } else { 317 os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf)); 318 res = wpabuf_len(buf); 319 wpa_hexdump_buf(MSG_DEBUG, 320 "Added supported operating classes IE", buf); 321 } 322 323 wpabuf_free(buf); 324 return res; 325 } 326