Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Wireless utility functions
4 : : *
5 : : * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
6 : : * Copyright 2013-2014 Intel Mobile Communications GmbH
7 : : * Copyright 2017 Intel Deutschland GmbH
8 : : * Copyright (C) 2018-2019 Intel Corporation
9 : : */
10 : : #include <linux/export.h>
11 : : #include <linux/bitops.h>
12 : : #include <linux/etherdevice.h>
13 : : #include <linux/slab.h>
14 : : #include <linux/ieee80211.h>
15 : : #include <net/cfg80211.h>
16 : : #include <net/ip.h>
17 : : #include <net/dsfield.h>
18 : : #include <linux/if_vlan.h>
19 : : #include <linux/mpls.h>
20 : : #include <linux/gcd.h>
21 : : #include <linux/bitfield.h>
22 : : #include <linux/nospec.h>
23 : : #include "core.h"
24 : : #include "rdev-ops.h"
25 : :
26 : :
27 : : struct ieee80211_rate *
28 : 0 : ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
29 : : u32 basic_rates, int bitrate)
30 : : {
31 : 0 : struct ieee80211_rate *result = &sband->bitrates[0];
32 : : int i;
33 : :
34 [ # # ]: 0 : for (i = 0; i < sband->n_bitrates; i++) {
35 [ # # ]: 0 : if (!(basic_rates & BIT(i)))
36 : 0 : continue;
37 [ # # ]: 0 : if (sband->bitrates[i].bitrate > bitrate)
38 : 0 : continue;
39 : : result = &sband->bitrates[i];
40 : : }
41 : :
42 : 0 : return result;
43 : : }
44 : : EXPORT_SYMBOL(ieee80211_get_response_rate);
45 : :
46 : 0 : u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,
47 : : enum nl80211_bss_scan_width scan_width)
48 : : {
49 : : struct ieee80211_rate *bitrates;
50 : : u32 mandatory_rates = 0;
51 : : enum ieee80211_rate_flags mandatory_flag;
52 : : int i;
53 : :
54 [ # # # # ]: 0 : if (WARN_ON(!sband))
55 : : return 1;
56 : :
57 [ # # ]: 0 : if (sband->band == NL80211_BAND_2GHZ) {
58 [ # # ]: 0 : if (scan_width == NL80211_BSS_CHAN_WIDTH_5 ||
59 : : scan_width == NL80211_BSS_CHAN_WIDTH_10)
60 : : mandatory_flag = IEEE80211_RATE_MANDATORY_G;
61 : : else
62 : : mandatory_flag = IEEE80211_RATE_MANDATORY_B;
63 : : } else {
64 : : mandatory_flag = IEEE80211_RATE_MANDATORY_A;
65 : : }
66 : :
67 : 0 : bitrates = sband->bitrates;
68 [ # # ]: 0 : for (i = 0; i < sband->n_bitrates; i++)
69 [ # # ]: 0 : if (bitrates[i].flags & mandatory_flag)
70 : 0 : mandatory_rates |= BIT(i);
71 : 0 : return mandatory_rates;
72 : : }
73 : : EXPORT_SYMBOL(ieee80211_mandatory_rates);
74 : :
75 : 0 : int ieee80211_channel_to_frequency(int chan, enum nl80211_band band)
76 : : {
77 : : /* see 802.11 17.3.8.3.2 and Annex J
78 : : * there are overlapping channel numbers in 5GHz and 2GHz bands */
79 [ # # ]: 0 : if (chan <= 0)
80 : : return 0; /* not supported */
81 [ # # # # : 0 : switch (band) {
# ]
82 : : case NL80211_BAND_2GHZ:
83 [ # # ]: 0 : if (chan == 14)
84 : : return 2484;
85 [ # # ]: 0 : else if (chan < 14)
86 : 0 : return 2407 + chan * 5;
87 : : break;
88 : : case NL80211_BAND_5GHZ:
89 [ # # ]: 0 : if (chan >= 182 && chan <= 196)
90 : 0 : return 4000 + chan * 5;
91 : : else
92 : 0 : return 5000 + chan * 5;
93 : : break;
94 : : case NL80211_BAND_6GHZ:
95 : : /* see 802.11ax D4.1 27.3.22.2 */
96 [ # # ]: 0 : if (chan <= 253)
97 : 0 : return 5940 + chan * 5;
98 : : break;
99 : : case NL80211_BAND_60GHZ:
100 [ # # ]: 0 : if (chan < 7)
101 : 0 : return 56160 + chan * 2160;
102 : : break;
103 : : default:
104 : : ;
105 : : }
106 : : return 0; /* not supported */
107 : : }
108 : : EXPORT_SYMBOL(ieee80211_channel_to_frequency);
109 : :
110 : 0 : int ieee80211_frequency_to_channel(int freq)
111 : : {
112 : : /* see 802.11 17.3.8.3.2 and Annex J */
113 [ # # ]: 0 : if (freq == 2484)
114 : : return 14;
115 [ # # ]: 0 : else if (freq < 2484)
116 : 0 : return (freq - 2407) / 5;
117 [ # # ]: 0 : else if (freq >= 4910 && freq <= 4980)
118 : 0 : return (freq - 4000) / 5;
119 [ # # ]: 0 : else if (freq < 5945)
120 : 0 : return (freq - 5000) / 5;
121 [ # # ]: 0 : else if (freq <= 45000) /* DMG band lower limit */
122 : : /* see 802.11ax D4.1 27.3.22.2 */
123 : 0 : return (freq - 5940) / 5;
124 [ # # ]: 0 : else if (freq >= 58320 && freq <= 70200)
125 : 0 : return (freq - 56160) / 2160;
126 : : else
127 : : return 0;
128 : : }
129 : : EXPORT_SYMBOL(ieee80211_frequency_to_channel);
130 : :
131 : 0 : struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy, int freq)
132 : : {
133 : : enum nl80211_band band;
134 : : struct ieee80211_supported_band *sband;
135 : : int i;
136 : :
137 [ # # ]: 0 : for (band = 0; band < NUM_NL80211_BANDS; band++) {
138 : 0 : sband = wiphy->bands[band];
139 : :
140 [ # # ]: 0 : if (!sband)
141 : 0 : continue;
142 : :
143 [ # # ]: 0 : for (i = 0; i < sband->n_channels; i++) {
144 [ # # ]: 0 : if (sband->channels[i].center_freq == freq)
145 : 0 : return &sband->channels[i];
146 : : }
147 : : }
148 : :
149 : : return NULL;
150 : : }
151 : : EXPORT_SYMBOL(ieee80211_get_channel);
152 : :
153 : 0 : static void set_mandatory_flags_band(struct ieee80211_supported_band *sband)
154 : : {
155 : : int i, want;
156 : :
157 [ # # # # ]: 0 : switch (sband->band) {
158 : : case NL80211_BAND_5GHZ:
159 : : case NL80211_BAND_6GHZ:
160 : : want = 3;
161 [ # # ]: 0 : for (i = 0; i < sband->n_bitrates; i++) {
162 [ # # ]: 0 : if (sband->bitrates[i].bitrate == 60 ||
163 [ # # ]: 0 : sband->bitrates[i].bitrate == 120 ||
164 : : sband->bitrates[i].bitrate == 240) {
165 : 0 : sband->bitrates[i].flags |=
166 : : IEEE80211_RATE_MANDATORY_A;
167 : 0 : want--;
168 : : }
169 : : }
170 [ # # ]: 0 : WARN_ON(want);
171 : : break;
172 : : case NL80211_BAND_2GHZ:
173 : : want = 7;
174 [ # # ]: 0 : for (i = 0; i < sband->n_bitrates; i++) {
175 [ # # # ]: 0 : switch (sband->bitrates[i].bitrate) {
176 : : case 10:
177 : : case 20:
178 : : case 55:
179 : : case 110:
180 : 0 : sband->bitrates[i].flags |=
181 : : IEEE80211_RATE_MANDATORY_B |
182 : : IEEE80211_RATE_MANDATORY_G;
183 : 0 : want--;
184 : 0 : break;
185 : : case 60:
186 : : case 120:
187 : : case 240:
188 : 0 : sband->bitrates[i].flags |=
189 : : IEEE80211_RATE_MANDATORY_G;
190 : 0 : want--;
191 : : /* fall through */
192 : : default:
193 : 0 : sband->bitrates[i].flags |=
194 : : IEEE80211_RATE_ERP_G;
195 : 0 : break;
196 : : }
197 : : }
198 [ # # ]: 0 : WARN_ON(want != 0 && want != 3);
199 : : break;
200 : : case NL80211_BAND_60GHZ:
201 : : /* check for mandatory HT MCS 1..4 */
202 [ # # ]: 0 : WARN_ON(!sband->ht_cap.ht_supported);
203 [ # # ]: 0 : WARN_ON((sband->ht_cap.mcs.rx_mask[0] & 0x1e) != 0x1e);
204 : : break;
205 : : case NUM_NL80211_BANDS:
206 : : default:
207 : 0 : WARN_ON(1);
208 : 0 : break;
209 : : }
210 : 0 : }
211 : :
212 : 0 : void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
213 : : {
214 : : enum nl80211_band band;
215 : :
216 [ # # ]: 0 : for (band = 0; band < NUM_NL80211_BANDS; band++)
217 [ # # ]: 0 : if (wiphy->bands[band])
218 : 0 : set_mandatory_flags_band(wiphy->bands[band]);
219 : 0 : }
220 : :
221 : 0 : bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher)
222 : : {
223 : : int i;
224 [ # # # # ]: 0 : for (i = 0; i < wiphy->n_cipher_suites; i++)
225 [ # # # # ]: 0 : if (cipher == wiphy->cipher_suites[i])
226 : : return true;
227 : : return false;
228 : : }
229 : :
230 : 0 : int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
231 : : struct key_params *params, int key_idx,
232 : : bool pairwise, const u8 *mac_addr)
233 : : {
234 [ # # ]: 0 : if (key_idx < 0 || key_idx > 5)
235 : : return -EINVAL;
236 : :
237 [ # # # # ]: 0 : if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
238 : : return -EINVAL;
239 : :
240 [ # # ]: 0 : if (pairwise && !mac_addr)
241 : : return -EINVAL;
242 : :
243 [ # # # # : 0 : switch (params->cipher) {
# ]
244 : : case WLAN_CIPHER_SUITE_TKIP:
245 : : /* Extended Key ID can only be used with CCMP/GCMP ciphers */
246 [ # # # # ]: 0 : if ((pairwise && key_idx) ||
247 : 0 : params->mode != NL80211_KEY_RX_TX)
248 : : return -EINVAL;
249 : : break;
250 : : case WLAN_CIPHER_SUITE_CCMP:
251 : : case WLAN_CIPHER_SUITE_CCMP_256:
252 : : case WLAN_CIPHER_SUITE_GCMP:
253 : : case WLAN_CIPHER_SUITE_GCMP_256:
254 : : /* IEEE802.11-2016 allows only 0 and - when supporting
255 : : * Extended Key ID - 1 as index for pairwise keys.
256 : : * @NL80211_KEY_NO_TX is only allowed for pairwise keys when
257 : : * the driver supports Extended Key ID.
258 : : * @NL80211_KEY_SET_TX can't be set when installing and
259 : : * validating a key.
260 : : */
261 [ # # # # : 0 : if ((params->mode == NL80211_KEY_NO_TX && !pairwise) ||
# # ]
262 : : params->mode == NL80211_KEY_SET_TX)
263 : : return -EINVAL;
264 [ # # ]: 0 : if (wiphy_ext_feature_isset(&rdev->wiphy,
265 : : NL80211_EXT_FEATURE_EXT_KEY_ID)) {
266 [ # # ]: 0 : if (pairwise && (key_idx < 0 || key_idx > 1))
267 : : return -EINVAL;
268 [ # # ]: 0 : } else if (pairwise && key_idx) {
269 : : return -EINVAL;
270 : : }
271 : : break;
272 : : case WLAN_CIPHER_SUITE_AES_CMAC:
273 : : case WLAN_CIPHER_SUITE_BIP_CMAC_256:
274 : : case WLAN_CIPHER_SUITE_BIP_GMAC_128:
275 : : case WLAN_CIPHER_SUITE_BIP_GMAC_256:
276 : : /* Disallow BIP (group-only) cipher as pairwise cipher */
277 [ # # ]: 0 : if (pairwise)
278 : : return -EINVAL;
279 [ # # ]: 0 : if (key_idx < 4)
280 : : return -EINVAL;
281 : : break;
282 : : case WLAN_CIPHER_SUITE_WEP40:
283 : : case WLAN_CIPHER_SUITE_WEP104:
284 [ # # ]: 0 : if (key_idx > 3)
285 : : return -EINVAL;
286 : : default:
287 : : break;
288 : : }
289 : :
290 [ # # # # : 0 : switch (params->cipher) {
# # # # #
# # # ]
291 : : case WLAN_CIPHER_SUITE_WEP40:
292 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_WEP40)
293 : : return -EINVAL;
294 : : break;
295 : : case WLAN_CIPHER_SUITE_TKIP:
296 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_TKIP)
297 : : return -EINVAL;
298 : : break;
299 : : case WLAN_CIPHER_SUITE_CCMP:
300 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_CCMP)
301 : : return -EINVAL;
302 : : break;
303 : : case WLAN_CIPHER_SUITE_CCMP_256:
304 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_CCMP_256)
305 : : return -EINVAL;
306 : : break;
307 : : case WLAN_CIPHER_SUITE_GCMP:
308 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_GCMP)
309 : : return -EINVAL;
310 : : break;
311 : : case WLAN_CIPHER_SUITE_GCMP_256:
312 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_GCMP_256)
313 : : return -EINVAL;
314 : : break;
315 : : case WLAN_CIPHER_SUITE_WEP104:
316 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_WEP104)
317 : : return -EINVAL;
318 : : break;
319 : : case WLAN_CIPHER_SUITE_AES_CMAC:
320 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_AES_CMAC)
321 : : return -EINVAL;
322 : : break;
323 : : case WLAN_CIPHER_SUITE_BIP_CMAC_256:
324 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_BIP_CMAC_256)
325 : : return -EINVAL;
326 : : break;
327 : : case WLAN_CIPHER_SUITE_BIP_GMAC_128:
328 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_BIP_GMAC_128)
329 : : return -EINVAL;
330 : : break;
331 : : case WLAN_CIPHER_SUITE_BIP_GMAC_256:
332 [ # # ]: 0 : if (params->key_len != WLAN_KEY_LEN_BIP_GMAC_256)
333 : : return -EINVAL;
334 : : break;
335 : : default:
336 : : /*
337 : : * We don't know anything about this algorithm,
338 : : * allow using it -- but the driver must check
339 : : * all parameters! We still check below whether
340 : : * or not the driver supports this algorithm,
341 : : * of course.
342 : : */
343 : : break;
344 : : }
345 : :
346 [ # # ]: 0 : if (params->seq) {
347 [ # # # ]: 0 : switch (params->cipher) {
348 : : case WLAN_CIPHER_SUITE_WEP40:
349 : : case WLAN_CIPHER_SUITE_WEP104:
350 : : /* These ciphers do not use key sequence */
351 : : return -EINVAL;
352 : : case WLAN_CIPHER_SUITE_TKIP:
353 : : case WLAN_CIPHER_SUITE_CCMP:
354 : : case WLAN_CIPHER_SUITE_CCMP_256:
355 : : case WLAN_CIPHER_SUITE_GCMP:
356 : : case WLAN_CIPHER_SUITE_GCMP_256:
357 : : case WLAN_CIPHER_SUITE_AES_CMAC:
358 : : case WLAN_CIPHER_SUITE_BIP_CMAC_256:
359 : : case WLAN_CIPHER_SUITE_BIP_GMAC_128:
360 : : case WLAN_CIPHER_SUITE_BIP_GMAC_256:
361 [ # # ]: 0 : if (params->seq_len != 6)
362 : : return -EINVAL;
363 : : break;
364 : : }
365 : : }
366 : :
367 [ # # ]: 0 : if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher))
368 : : return -EINVAL;
369 : :
370 : 0 : return 0;
371 : : }
372 : :
373 : 0 : unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc)
374 : : {
375 : : unsigned int hdrlen = 24;
376 : :
377 [ # # ]: 0 : if (ieee80211_is_data(fc)) {
378 [ # # ]: 0 : if (ieee80211_has_a4(fc))
379 : : hdrlen = 30;
380 [ # # ]: 0 : if (ieee80211_is_data_qos(fc)) {
381 : 0 : hdrlen += IEEE80211_QOS_CTL_LEN;
382 [ # # ]: 0 : if (ieee80211_has_order(fc))
383 : 0 : hdrlen += IEEE80211_HT_CTL_LEN;
384 : : }
385 : : goto out;
386 : : }
387 : :
388 [ # # ]: 0 : if (ieee80211_is_mgmt(fc)) {
389 [ # # ]: 0 : if (ieee80211_has_order(fc))
390 : : hdrlen += IEEE80211_HT_CTL_LEN;
391 : : goto out;
392 : : }
393 : :
394 [ # # ]: 0 : if (ieee80211_is_ctl(fc)) {
395 : : /*
396 : : * ACK and CTS are 10 bytes, all others 16. To see how
397 : : * to get this condition consider
398 : : * subtype mask: 0b0000000011110000 (0x00F0)
399 : : * ACK subtype: 0b0000000011010000 (0x00D0)
400 : : * CTS subtype: 0b0000000011000000 (0x00C0)
401 : : * bits that matter: ^^^ (0x00E0)
402 : : * value of those: 0b0000000011000000 (0x00C0)
403 : : */
404 [ # # ]: 0 : if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0))
405 : : hdrlen = 10;
406 : : else
407 : : hdrlen = 16;
408 : : }
409 : : out:
410 : 0 : return hdrlen;
411 : : }
412 : : EXPORT_SYMBOL(ieee80211_hdrlen);
413 : :
414 : 0 : unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
415 : : {
416 : 0 : const struct ieee80211_hdr *hdr =
417 : : (const struct ieee80211_hdr *)skb->data;
418 : : unsigned int hdrlen;
419 : :
420 [ # # ]: 0 : if (unlikely(skb->len < 10))
421 : : return 0;
422 : 0 : hdrlen = ieee80211_hdrlen(hdr->frame_control);
423 [ # # ]: 0 : if (unlikely(hdrlen > skb->len))
424 : : return 0;
425 : 0 : return hdrlen;
426 : : }
427 : : EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
428 : :
429 : : static unsigned int __ieee80211_get_mesh_hdrlen(u8 flags)
430 : : {
431 : 0 : int ae = flags & MESH_FLAGS_AE;
432 : : /* 802.11-2012, 8.2.4.7.3 */
433 [ # # # # : 0 : switch (ae) {
# # # #
# ]
434 : : default:
435 : : case 0:
436 : : return 6;
437 : : case MESH_FLAGS_AE_A4:
438 : : return 12;
439 : : case MESH_FLAGS_AE_A5_A6:
440 : : return 18;
441 : : }
442 : : }
443 : :
444 : 0 : unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
445 : : {
446 : 0 : return __ieee80211_get_mesh_hdrlen(meshhdr->flags);
447 : : }
448 : : EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
449 : :
450 : 0 : int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
451 : : const u8 *addr, enum nl80211_iftype iftype,
452 : : u8 data_offset)
453 : : {
454 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
455 : : struct {
456 : : u8 hdr[ETH_ALEN] __aligned(2);
457 : : __be16 proto;
458 : : } payload;
459 : : struct ethhdr tmp;
460 : : u16 hdrlen;
461 : 0 : u8 mesh_flags = 0;
462 : :
463 [ # # ]: 0 : if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
464 : : return -1;
465 : :
466 : 0 : hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset;
467 [ # # ]: 0 : if (skb->len < hdrlen + 8)
468 : : return -1;
469 : :
470 : : /* convert IEEE 802.11 header + possible LLC headers into Ethernet
471 : : * header
472 : : * IEEE 802.11 address fields:
473 : : * ToDS FromDS Addr1 Addr2 Addr3 Addr4
474 : : * 0 0 DA SA BSSID n/a
475 : : * 0 1 DA BSSID SA n/a
476 : : * 1 0 BSSID SA DA n/a
477 : : * 1 1 RA TA DA SA
478 : : */
479 : 0 : memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
480 : 0 : memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
481 : :
482 [ # # ]: 0 : if (iftype == NL80211_IFTYPE_MESH_POINT)
483 : 0 : skb_copy_bits(skb, hdrlen, &mesh_flags, 1);
484 : :
485 : 0 : mesh_flags &= MESH_FLAGS_AE;
486 : :
487 [ # # # # : 0 : switch (hdr->frame_control &
# ]
488 : : cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
489 : : case cpu_to_le16(IEEE80211_FCTL_TODS):
490 [ # # ]: 0 : if (unlikely(iftype != NL80211_IFTYPE_AP &&
491 : : iftype != NL80211_IFTYPE_AP_VLAN &&
492 : : iftype != NL80211_IFTYPE_P2P_GO))
493 : : return -1;
494 : : break;
495 : : case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
496 [ # # # # ]: 0 : if (unlikely(iftype != NL80211_IFTYPE_WDS &&
497 : : iftype != NL80211_IFTYPE_MESH_POINT &&
498 : : iftype != NL80211_IFTYPE_AP_VLAN &&
499 : : iftype != NL80211_IFTYPE_STATION))
500 : : return -1;
501 [ # # ]: 0 : if (iftype == NL80211_IFTYPE_MESH_POINT) {
502 [ # # ]: 0 : if (mesh_flags == MESH_FLAGS_AE_A4)
503 : : return -1;
504 [ # # ]: 0 : if (mesh_flags == MESH_FLAGS_AE_A5_A6) {
505 : 0 : skb_copy_bits(skb, hdrlen +
506 : : offsetof(struct ieee80211s_hdr, eaddr1),
507 : : tmp.h_dest, 2 * ETH_ALEN);
508 : : }
509 : 0 : hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
510 : : }
511 : : break;
512 : : case cpu_to_le16(IEEE80211_FCTL_FROMDS):
513 [ # # ]: 0 : if ((iftype != NL80211_IFTYPE_STATION &&
514 [ # # ]: 0 : iftype != NL80211_IFTYPE_P2P_CLIENT &&
515 [ # # ]: 0 : iftype != NL80211_IFTYPE_MESH_POINT) ||
516 [ # # ]: 0 : (is_multicast_ether_addr(tmp.h_dest) &&
517 : : ether_addr_equal(tmp.h_source, addr)))
518 : : return -1;
519 [ # # ]: 0 : if (iftype == NL80211_IFTYPE_MESH_POINT) {
520 [ # # ]: 0 : if (mesh_flags == MESH_FLAGS_AE_A5_A6)
521 : : return -1;
522 [ # # ]: 0 : if (mesh_flags == MESH_FLAGS_AE_A4)
523 : 0 : skb_copy_bits(skb, hdrlen +
524 : : offsetof(struct ieee80211s_hdr, eaddr1),
525 : : tmp.h_source, ETH_ALEN);
526 : 0 : hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
527 : : }
528 : : break;
529 : : case cpu_to_le16(0):
530 [ # # ]: 0 : if (iftype != NL80211_IFTYPE_ADHOC &&
531 : 0 : iftype != NL80211_IFTYPE_STATION &&
532 : 0 : iftype != NL80211_IFTYPE_OCB)
533 : : return -1;
534 : : break;
535 : : }
536 : :
537 : 0 : skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
538 : 0 : tmp.h_proto = payload.proto;
539 : :
540 [ # # # # : 0 : if (likely((ether_addr_equal(payload.hdr, rfc1042_header) &&
# # # # #
# # # ]
541 : : tmp.h_proto != htons(ETH_P_AARP) &&
542 : : tmp.h_proto != htons(ETH_P_IPX)) ||
543 : : ether_addr_equal(payload.hdr, bridge_tunnel_header)))
544 : : /* remove RFC1042 or Bridge-Tunnel encapsulation and
545 : : * replace EtherType */
546 : 0 : hdrlen += ETH_ALEN + 2;
547 : : else
548 : 0 : tmp.h_proto = htons(skb->len - hdrlen);
549 : :
550 : 0 : pskb_pull(skb, hdrlen);
551 : :
552 [ # # ]: 0 : if (!ehdr)
553 : 0 : ehdr = skb_push(skb, sizeof(struct ethhdr));
554 : 0 : memcpy(ehdr, &tmp, sizeof(tmp));
555 : :
556 : 0 : return 0;
557 : : }
558 : : EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr);
559 : :
560 : : static void
561 : 0 : __frame_add_frag(struct sk_buff *skb, struct page *page,
562 : : void *ptr, int len, int size)
563 : : {
564 : : struct skb_shared_info *sh = skb_shinfo(skb);
565 : : int page_offset;
566 : :
567 : 0 : get_page(page);
568 : 0 : page_offset = ptr - page_address(page);
569 : 0 : skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size);
570 : 0 : }
571 : :
572 : : static void
573 : 0 : __ieee80211_amsdu_copy_frag(struct sk_buff *skb, struct sk_buff *frame,
574 : : int offset, int len)
575 : : {
576 : : struct skb_shared_info *sh = skb_shinfo(skb);
577 : 0 : const skb_frag_t *frag = &sh->frags[0];
578 : : struct page *frag_page;
579 : : void *frag_ptr;
580 : : int frag_len, frag_size;
581 : 0 : int head_size = skb->len - skb->data_len;
582 : : int cur_len;
583 : :
584 : 0 : frag_page = virt_to_head_page(skb->head);
585 : 0 : frag_ptr = skb->data;
586 : : frag_size = head_size;
587 : :
588 [ # # ]: 0 : while (offset >= frag_size) {
589 : 0 : offset -= frag_size;
590 : : frag_page = skb_frag_page(frag);
591 : 0 : frag_ptr = skb_frag_address(frag);
592 : 0 : frag_size = skb_frag_size(frag);
593 : 0 : frag++;
594 : : }
595 : :
596 : 0 : frag_ptr += offset;
597 : 0 : frag_len = frag_size - offset;
598 : :
599 : 0 : cur_len = min(len, frag_len);
600 : :
601 : 0 : __frame_add_frag(frame, frag_page, frag_ptr, cur_len, frag_size);
602 : 0 : len -= cur_len;
603 : :
604 [ # # ]: 0 : while (len > 0) {
605 : 0 : frag_len = skb_frag_size(frag);
606 : 0 : cur_len = min(len, frag_len);
607 : 0 : __frame_add_frag(frame, skb_frag_page(frag),
608 : : skb_frag_address(frag), cur_len, frag_len);
609 : 0 : len -= cur_len;
610 : 0 : frag++;
611 : : }
612 : 0 : }
613 : :
614 : : static struct sk_buff *
615 : 0 : __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,
616 : : int offset, int len, bool reuse_frag)
617 : : {
618 : : struct sk_buff *frame;
619 : : int cur_len = len;
620 : :
621 [ # # ]: 0 : if (skb->len - offset < len)
622 : : return NULL;
623 : :
624 : : /*
625 : : * When reusing framents, copy some data to the head to simplify
626 : : * ethernet header handling and speed up protocol header processing
627 : : * in the stack later.
628 : : */
629 [ # # ]: 0 : if (reuse_frag)
630 : 0 : cur_len = min_t(int, len, 32);
631 : :
632 : : /*
633 : : * Allocate and reserve two bytes more for payload
634 : : * alignment since sizeof(struct ethhdr) is 14.
635 : : */
636 : 0 : frame = dev_alloc_skb(hlen + sizeof(struct ethhdr) + 2 + cur_len);
637 [ # # ]: 0 : if (!frame)
638 : : return NULL;
639 : :
640 : 0 : skb_reserve(frame, hlen + sizeof(struct ethhdr) + 2);
641 : 0 : skb_copy_bits(skb, offset, skb_put(frame, cur_len), cur_len);
642 : :
643 : 0 : len -= cur_len;
644 [ # # ]: 0 : if (!len)
645 : : return frame;
646 : :
647 : 0 : offset += cur_len;
648 : 0 : __ieee80211_amsdu_copy_frag(skb, frame, offset, len);
649 : :
650 : 0 : return frame;
651 : : }
652 : :
653 : 0 : void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
654 : : const u8 *addr, enum nl80211_iftype iftype,
655 : : const unsigned int extra_headroom,
656 : : const u8 *check_da, const u8 *check_sa)
657 : : {
658 : 0 : unsigned int hlen = ALIGN(extra_headroom, 4);
659 : : struct sk_buff *frame = NULL;
660 : : u16 ethertype;
661 : : u8 *payload;
662 : : int offset = 0, remaining;
663 : : struct ethhdr eth;
664 [ # # # # ]: 0 : bool reuse_frag = skb->head_frag && !skb_has_frag_list(skb);
665 : : bool reuse_skb = false;
666 : : bool last = false;
667 : :
668 [ # # ]: 0 : while (!last) {
669 : : unsigned int subframe_len;
670 : : int len;
671 : : u8 padding;
672 : :
673 : 0 : skb_copy_bits(skb, offset, ð, sizeof(eth));
674 : 0 : len = ntohs(eth.h_proto);
675 : 0 : subframe_len = sizeof(struct ethhdr) + len;
676 : 0 : padding = (4 - subframe_len) & 0x3;
677 : :
678 : : /* the last MSDU has no padding */
679 : 0 : remaining = skb->len - offset;
680 [ # # ]: 0 : if (subframe_len > remaining)
681 : : goto purge;
682 : :
683 : 0 : offset += sizeof(struct ethhdr);
684 : 0 : last = remaining <= subframe_len + padding;
685 : :
686 : : /* FIXME: should we really accept multicast DA? */
687 [ # # # # : 0 : if ((check_da && !is_multicast_ether_addr(eth.h_dest) &&
# # ]
688 [ # # ]: 0 : !ether_addr_equal(check_da, eth.h_dest)) ||
689 [ # # ]: 0 : (check_sa && !ether_addr_equal(check_sa, eth.h_source))) {
690 : 0 : offset += len + padding;
691 : 0 : continue;
692 : : }
693 : :
694 : : /* reuse skb for the last subframe */
695 [ # # # # ]: 0 : if (!skb_is_nonlinear(skb) && !reuse_frag && last) {
696 : 0 : skb_pull(skb, offset);
697 : : frame = skb;
698 : 0 : reuse_skb = true;
699 : : } else {
700 : 0 : frame = __ieee80211_amsdu_copy(skb, hlen, offset, len,
701 : : reuse_frag);
702 [ # # ]: 0 : if (!frame)
703 : : goto purge;
704 : :
705 : 0 : offset += len + padding;
706 : : }
707 : :
708 : : skb_reset_network_header(frame);
709 : 0 : frame->dev = skb->dev;
710 : 0 : frame->priority = skb->priority;
711 : :
712 : : payload = frame->data;
713 : 0 : ethertype = (payload[6] << 8) | payload[7];
714 [ # # # # : 0 : if (likely((ether_addr_equal(payload, rfc1042_header) &&
# # # # ]
715 : : ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
716 : : ether_addr_equal(payload, bridge_tunnel_header))) {
717 : 0 : eth.h_proto = htons(ethertype);
718 : 0 : skb_pull(frame, ETH_ALEN + 2);
719 : : }
720 : :
721 : 0 : memcpy(skb_push(frame, sizeof(eth)), ð, sizeof(eth));
722 : : __skb_queue_tail(list, frame);
723 : : }
724 : :
725 [ # # ]: 0 : if (!reuse_skb)
726 : 0 : dev_kfree_skb(skb);
727 : :
728 : 0 : return;
729 : :
730 : : purge:
731 : 0 : __skb_queue_purge(list);
732 : 0 : dev_kfree_skb(skb);
733 : : }
734 : : EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
735 : :
736 : : /* Given a data frame determine the 802.1p/1d tag to use. */
737 : 0 : unsigned int cfg80211_classify8021d(struct sk_buff *skb,
738 : : struct cfg80211_qos_map *qos_map)
739 : : {
740 : : unsigned int dscp;
741 : : unsigned char vlan_priority;
742 : : unsigned int ret;
743 : :
744 : : /* skb->priority values from 256->263 are magic values to
745 : : * directly indicate a specific 802.1d priority. This is used
746 : : * to allow 802.1d priority to be passed directly in from VLAN
747 : : * tags, etc.
748 : : */
749 [ # # ]: 0 : if (skb->priority >= 256 && skb->priority <= 263) {
750 : : ret = skb->priority - 256;
751 : : goto out;
752 : : }
753 : :
754 [ # # ]: 0 : if (skb_vlan_tag_present(skb)) {
755 : 0 : vlan_priority = (skb_vlan_tag_get(skb) & VLAN_PRIO_MASK)
756 : 0 : >> VLAN_PRIO_SHIFT;
757 [ # # ]: 0 : if (vlan_priority > 0) {
758 : 0 : ret = vlan_priority;
759 : 0 : goto out;
760 : : }
761 : : }
762 : :
763 [ # # # # : 0 : switch (skb->protocol) {
# ]
764 : : case htons(ETH_P_IP):
765 : 0 : dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;
766 : 0 : break;
767 : : case htons(ETH_P_IPV6):
768 : 0 : dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & 0xfc;
769 : 0 : break;
770 : : case htons(ETH_P_MPLS_UC):
771 : : case htons(ETH_P_MPLS_MC): {
772 : : struct mpls_label mpls_tmp, *mpls;
773 : :
774 : : mpls = skb_header_pointer(skb, sizeof(struct ethhdr),
775 : : sizeof(*mpls), &mpls_tmp);
776 [ # # ]: 0 : if (!mpls)
777 : 0 : return 0;
778 : :
779 : 0 : ret = (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
780 : : >> MPLS_LS_TC_SHIFT;
781 : 0 : goto out;
782 : : }
783 : : case htons(ETH_P_80221):
784 : : /* 802.21 is always network control traffic */
785 : : return 7;
786 : : default:
787 : 0 : return 0;
788 : : }
789 : :
790 [ # # ]: 0 : if (qos_map) {
791 : 0 : unsigned int i, tmp_dscp = dscp >> 2;
792 : :
793 [ # # ]: 0 : for (i = 0; i < qos_map->num_des; i++) {
794 [ # # ]: 0 : if (tmp_dscp == qos_map->dscp_exception[i].dscp) {
795 : 0 : ret = qos_map->dscp_exception[i].up;
796 : 0 : goto out;
797 : : }
798 : : }
799 : :
800 [ # # ]: 0 : for (i = 0; i < 8; i++) {
801 [ # # # # ]: 0 : if (tmp_dscp >= qos_map->up[i].low &&
802 : 0 : tmp_dscp <= qos_map->up[i].high) {
803 : 0 : ret = i;
804 : 0 : goto out;
805 : : }
806 : : }
807 : : }
808 : :
809 : 0 : ret = dscp >> 5;
810 : : out:
811 : 0 : return array_index_nospec(ret, IEEE80211_NUM_TIDS);
812 : : }
813 : : EXPORT_SYMBOL(cfg80211_classify8021d);
814 : :
815 : 0 : const struct element *ieee80211_bss_get_elem(struct cfg80211_bss *bss, u8 id)
816 : : {
817 : : const struct cfg80211_bss_ies *ies;
818 : :
819 : 0 : ies = rcu_dereference(bss->ies);
820 [ # # ]: 0 : if (!ies)
821 : : return NULL;
822 : :
823 : 0 : return cfg80211_find_elem(id, ies->data, ies->len);
824 : : }
825 : : EXPORT_SYMBOL(ieee80211_bss_get_elem);
826 : :
827 : 0 : void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
828 : : {
829 : 0 : struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
830 : 0 : struct net_device *dev = wdev->netdev;
831 : : int i;
832 : :
833 [ # # ]: 0 : if (!wdev->connect_keys)
834 : 0 : return;
835 : :
836 [ # # ]: 0 : for (i = 0; i < CFG80211_MAX_WEP_KEYS; i++) {
837 [ # # ]: 0 : if (!wdev->connect_keys->params[i].cipher)
838 : 0 : continue;
839 [ # # ]: 0 : if (rdev_add_key(rdev, dev, i, false, NULL,
840 : : &wdev->connect_keys->params[i])) {
841 : 0 : netdev_err(dev, "failed to set key %d\n", i);
842 : 0 : continue;
843 : : }
844 [ # # # # ]: 0 : if (wdev->connect_keys->def == i &&
845 : 0 : rdev_set_default_key(rdev, dev, i, true, true)) {
846 : 0 : netdev_err(dev, "failed to set defkey %d\n", i);
847 : 0 : continue;
848 : : }
849 : : }
850 : :
851 : 0 : kzfree(wdev->connect_keys);
852 : 0 : wdev->connect_keys = NULL;
853 : : }
854 : :
855 : 0 : void cfg80211_process_wdev_events(struct wireless_dev *wdev)
856 : : {
857 : : struct cfg80211_event *ev;
858 : : unsigned long flags;
859 : :
860 : 0 : spin_lock_irqsave(&wdev->event_lock, flags);
861 [ # # ]: 0 : while (!list_empty(&wdev->event_list)) {
862 : 0 : ev = list_first_entry(&wdev->event_list,
863 : : struct cfg80211_event, list);
864 : : list_del(&ev->list);
865 : : spin_unlock_irqrestore(&wdev->event_lock, flags);
866 : :
867 : : wdev_lock(wdev);
868 [ # # # # : 0 : switch (ev->type) {
# # # ]
869 : : case EVENT_CONNECT_RESULT:
870 : 0 : __cfg80211_connect_result(
871 : : wdev->netdev,
872 : : &ev->cr,
873 : 0 : ev->cr.status == WLAN_STATUS_SUCCESS);
874 : 0 : break;
875 : : case EVENT_ROAMED:
876 : 0 : __cfg80211_roamed(wdev, &ev->rm);
877 : 0 : break;
878 : : case EVENT_DISCONNECTED:
879 : 0 : __cfg80211_disconnected(wdev->netdev,
880 : : ev->dc.ie, ev->dc.ie_len,
881 : : ev->dc.reason,
882 : 0 : !ev->dc.locally_generated);
883 : 0 : break;
884 : : case EVENT_IBSS_JOINED:
885 : 0 : __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
886 : : ev->ij.channel);
887 : 0 : break;
888 : : case EVENT_STOPPED:
889 : 0 : __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev);
890 : 0 : break;
891 : : case EVENT_PORT_AUTHORIZED:
892 : 0 : __cfg80211_port_authorized(wdev, ev->pa.bssid);
893 : 0 : break;
894 : : }
895 : : wdev_unlock(wdev);
896 : :
897 : 0 : kfree(ev);
898 : :
899 : 0 : spin_lock_irqsave(&wdev->event_lock, flags);
900 : : }
901 : : spin_unlock_irqrestore(&wdev->event_lock, flags);
902 : 0 : }
903 : :
904 : 0 : void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
905 : : {
906 : : struct wireless_dev *wdev;
907 : :
908 [ # # # # ]: 0 : ASSERT_RTNL();
909 : :
910 [ # # ]: 0 : list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
911 : 0 : cfg80211_process_wdev_events(wdev);
912 : 0 : }
913 : :
914 : 0 : int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
915 : : struct net_device *dev, enum nl80211_iftype ntype,
916 : : struct vif_params *params)
917 : : {
918 : : int err;
919 : 0 : enum nl80211_iftype otype = dev->ieee80211_ptr->iftype;
920 : :
921 [ # # # # ]: 0 : ASSERT_RTNL();
922 : :
923 : : /* don't support changing VLANs, you just re-create them */
924 [ # # ]: 0 : if (otype == NL80211_IFTYPE_AP_VLAN)
925 : : return -EOPNOTSUPP;
926 : :
927 : : /* cannot change into P2P device or NAN */
928 [ # # ]: 0 : if (ntype == NL80211_IFTYPE_P2P_DEVICE ||
929 : 0 : ntype == NL80211_IFTYPE_NAN)
930 : : return -EOPNOTSUPP;
931 : :
932 [ # # # # ]: 0 : if (!rdev->ops->change_virtual_intf ||
933 : 0 : !(rdev->wiphy.interface_modes & (1 << ntype)))
934 : : return -EOPNOTSUPP;
935 : :
936 : : /* if it's part of a bridge, reject changing type to station/ibss */
937 [ # # # # ]: 0 : if ((dev->priv_flags & IFF_BRIDGE_PORT) &&
938 : 0 : (ntype == NL80211_IFTYPE_ADHOC ||
939 : 0 : ntype == NL80211_IFTYPE_STATION ||
940 : 0 : ntype == NL80211_IFTYPE_P2P_CLIENT))
941 : : return -EBUSY;
942 : :
943 [ # # ]: 0 : if (ntype != otype) {
944 : 0 : dev->ieee80211_ptr->use_4addr = false;
945 : 0 : dev->ieee80211_ptr->mesh_id_up_len = 0;
946 : 0 : wdev_lock(dev->ieee80211_ptr);
947 : 0 : rdev_set_qos_map(rdev, dev, NULL);
948 : 0 : wdev_unlock(dev->ieee80211_ptr);
949 : :
950 [ # # # # ]: 0 : switch (otype) {
951 : : case NL80211_IFTYPE_AP:
952 : 0 : cfg80211_stop_ap(rdev, dev, true);
953 : 0 : break;
954 : : case NL80211_IFTYPE_ADHOC:
955 : 0 : cfg80211_leave_ibss(rdev, dev, false);
956 : 0 : break;
957 : : case NL80211_IFTYPE_STATION:
958 : : case NL80211_IFTYPE_P2P_CLIENT:
959 : 0 : wdev_lock(dev->ieee80211_ptr);
960 : 0 : cfg80211_disconnect(rdev, dev,
961 : : WLAN_REASON_DEAUTH_LEAVING, true);
962 : 0 : wdev_unlock(dev->ieee80211_ptr);
963 : : break;
964 : : case NL80211_IFTYPE_MESH_POINT:
965 : : /* mesh should be handled? */
966 : : break;
967 : : default:
968 : : break;
969 : : }
970 : :
971 : 0 : cfg80211_process_rdev_events(rdev);
972 : 0 : cfg80211_mlme_purge_registrations(dev->ieee80211_ptr);
973 : : }
974 : :
975 : 0 : err = rdev_change_virtual_intf(rdev, dev, ntype, params);
976 : :
977 [ # # # # : 0 : WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype);
# # ]
978 : :
979 [ # # # # ]: 0 : if (!err && params && params->use_4addr != -1)
980 : 0 : dev->ieee80211_ptr->use_4addr = params->use_4addr;
981 : :
982 [ # # ]: 0 : if (!err) {
983 : 0 : dev->priv_flags &= ~IFF_DONT_BRIDGE;
984 [ # # # # ]: 0 : switch (ntype) {
985 : : case NL80211_IFTYPE_STATION:
986 [ # # ]: 0 : if (dev->ieee80211_ptr->use_4addr)
987 : : break;
988 : : /* fall through */
989 : : case NL80211_IFTYPE_OCB:
990 : : case NL80211_IFTYPE_P2P_CLIENT:
991 : : case NL80211_IFTYPE_ADHOC:
992 : 0 : dev->priv_flags |= IFF_DONT_BRIDGE;
993 : 0 : break;
994 : : case NL80211_IFTYPE_P2P_GO:
995 : : case NL80211_IFTYPE_AP:
996 : : case NL80211_IFTYPE_AP_VLAN:
997 : : case NL80211_IFTYPE_WDS:
998 : : case NL80211_IFTYPE_MESH_POINT:
999 : : /* bridging OK */
1000 : : break;
1001 : : case NL80211_IFTYPE_MONITOR:
1002 : : /* monitor can't bridge anyway */
1003 : : break;
1004 : : case NL80211_IFTYPE_UNSPECIFIED:
1005 : : case NUM_NL80211_IFTYPES:
1006 : : /* not happening */
1007 : : break;
1008 : : case NL80211_IFTYPE_P2P_DEVICE:
1009 : : case NL80211_IFTYPE_NAN:
1010 : 0 : WARN_ON(1);
1011 : 0 : break;
1012 : : }
1013 : : }
1014 : :
1015 [ # # # # ]: 0 : if (!err && ntype != otype && netif_running(dev)) {
1016 : 0 : cfg80211_update_iface_num(rdev, ntype, 1);
1017 : 0 : cfg80211_update_iface_num(rdev, otype, -1);
1018 : : }
1019 : :
1020 : 0 : return err;
1021 : : }
1022 : :
1023 : 0 : static u32 cfg80211_calculate_bitrate_ht(struct rate_info *rate)
1024 : : {
1025 : : int modulation, streams, bitrate;
1026 : :
1027 : : /* the formula below does only work for MCS values smaller than 32 */
1028 [ # # # # : 0 : if (WARN_ON_ONCE(rate->mcs >= 32))
# # ]
1029 : : return 0;
1030 : :
1031 : 0 : modulation = rate->mcs & 7;
1032 : 0 : streams = (rate->mcs >> 3) + 1;
1033 : :
1034 [ # # ]: 0 : bitrate = (rate->bw == RATE_INFO_BW_40) ? 13500000 : 6500000;
1035 : :
1036 [ # # ]: 0 : if (modulation < 4)
1037 : 0 : bitrate *= (modulation + 1);
1038 [ # # ]: 0 : else if (modulation == 4)
1039 : 0 : bitrate *= (modulation + 2);
1040 : : else
1041 : 0 : bitrate *= (modulation + 3);
1042 : :
1043 : 0 : bitrate *= streams;
1044 : :
1045 [ # # ]: 0 : if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
1046 : 0 : bitrate = (bitrate / 9) * 10;
1047 : :
1048 : : /* do NOT round down here */
1049 : 0 : return (bitrate + 50000) / 100000;
1050 : : }
1051 : :
1052 : 0 : static u32 cfg80211_calculate_bitrate_dmg(struct rate_info *rate)
1053 : : {
1054 : : static const u32 __mcs2bitrate[] = {
1055 : : /* control PHY */
1056 : : [0] = 275,
1057 : : /* SC PHY */
1058 : : [1] = 3850,
1059 : : [2] = 7700,
1060 : : [3] = 9625,
1061 : : [4] = 11550,
1062 : : [5] = 12512, /* 1251.25 mbps */
1063 : : [6] = 15400,
1064 : : [7] = 19250,
1065 : : [8] = 23100,
1066 : : [9] = 25025,
1067 : : [10] = 30800,
1068 : : [11] = 38500,
1069 : : [12] = 46200,
1070 : : /* OFDM PHY */
1071 : : [13] = 6930,
1072 : : [14] = 8662, /* 866.25 mbps */
1073 : : [15] = 13860,
1074 : : [16] = 17325,
1075 : : [17] = 20790,
1076 : : [18] = 27720,
1077 : : [19] = 34650,
1078 : : [20] = 41580,
1079 : : [21] = 45045,
1080 : : [22] = 51975,
1081 : : [23] = 62370,
1082 : : [24] = 67568, /* 6756.75 mbps */
1083 : : /* LP-SC PHY */
1084 : : [25] = 6260,
1085 : : [26] = 8340,
1086 : : [27] = 11120,
1087 : : [28] = 12510,
1088 : : [29] = 16680,
1089 : : [30] = 22240,
1090 : : [31] = 25030,
1091 : : };
1092 : :
1093 [ # # # # : 0 : if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate)))
# # ]
1094 : : return 0;
1095 : :
1096 : 0 : return __mcs2bitrate[rate->mcs];
1097 : : }
1098 : :
1099 : 0 : static u32 cfg80211_calculate_bitrate_edmg(struct rate_info *rate)
1100 : : {
1101 : : static const u32 __mcs2bitrate[] = {
1102 : : /* control PHY */
1103 : : [0] = 275,
1104 : : /* SC PHY */
1105 : : [1] = 3850,
1106 : : [2] = 7700,
1107 : : [3] = 9625,
1108 : : [4] = 11550,
1109 : : [5] = 12512, /* 1251.25 mbps */
1110 : : [6] = 13475,
1111 : : [7] = 15400,
1112 : : [8] = 19250,
1113 : : [9] = 23100,
1114 : : [10] = 25025,
1115 : : [11] = 26950,
1116 : : [12] = 30800,
1117 : : [13] = 38500,
1118 : : [14] = 46200,
1119 : : [15] = 50050,
1120 : : [16] = 53900,
1121 : : [17] = 57750,
1122 : : [18] = 69300,
1123 : : [19] = 75075,
1124 : : [20] = 80850,
1125 : : };
1126 : :
1127 [ # # # # : 0 : if (WARN_ON_ONCE(rate->mcs >= ARRAY_SIZE(__mcs2bitrate)))
# # ]
1128 : : return 0;
1129 : :
1130 : 0 : return __mcs2bitrate[rate->mcs] * rate->n_bonded_ch;
1131 : : }
1132 : :
1133 : 0 : static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
1134 : : {
1135 : : static const u32 base[4][10] = {
1136 : : { 6500000,
1137 : : 13000000,
1138 : : 19500000,
1139 : : 26000000,
1140 : : 39000000,
1141 : : 52000000,
1142 : : 58500000,
1143 : : 65000000,
1144 : : 78000000,
1145 : : /* not in the spec, but some devices use this: */
1146 : : 86500000,
1147 : : },
1148 : : { 13500000,
1149 : : 27000000,
1150 : : 40500000,
1151 : : 54000000,
1152 : : 81000000,
1153 : : 108000000,
1154 : : 121500000,
1155 : : 135000000,
1156 : : 162000000,
1157 : : 180000000,
1158 : : },
1159 : : { 29300000,
1160 : : 58500000,
1161 : : 87800000,
1162 : : 117000000,
1163 : : 175500000,
1164 : : 234000000,
1165 : : 263300000,
1166 : : 292500000,
1167 : : 351000000,
1168 : : 390000000,
1169 : : },
1170 : : { 58500000,
1171 : : 117000000,
1172 : : 175500000,
1173 : : 234000000,
1174 : : 351000000,
1175 : : 468000000,
1176 : : 526500000,
1177 : : 585000000,
1178 : : 702000000,
1179 : : 780000000,
1180 : : },
1181 : : };
1182 : : u32 bitrate;
1183 : : int idx;
1184 : :
1185 [ # # ]: 0 : if (rate->mcs > 9)
1186 : : goto warn;
1187 : :
1188 [ # # # # : 0 : switch (rate->bw) {
# ]
1189 : : case RATE_INFO_BW_160:
1190 : : idx = 3;
1191 : : break;
1192 : : case RATE_INFO_BW_80:
1193 : : idx = 2;
1194 : 0 : break;
1195 : : case RATE_INFO_BW_40:
1196 : : idx = 1;
1197 : 0 : break;
1198 : : case RATE_INFO_BW_5:
1199 : : case RATE_INFO_BW_10:
1200 : : default:
1201 : : goto warn;
1202 : : case RATE_INFO_BW_20:
1203 : : idx = 0;
1204 : : }
1205 : :
1206 : 0 : bitrate = base[idx][rate->mcs];
1207 : 0 : bitrate *= rate->nss;
1208 : :
1209 [ # # ]: 0 : if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
1210 : 0 : bitrate = (bitrate / 9) * 10;
1211 : :
1212 : : /* do NOT round down here */
1213 : 0 : return (bitrate + 50000) / 100000;
1214 : : warn:
1215 [ # # ]: 0 : WARN_ONCE(1, "invalid rate bw=%d, mcs=%d, nss=%d\n",
1216 : : rate->bw, rate->mcs, rate->nss);
1217 : : return 0;
1218 : : }
1219 : :
1220 : 0 : static u32 cfg80211_calculate_bitrate_he(struct rate_info *rate)
1221 : : {
1222 : : #define SCALE 2048
1223 : 0 : u16 mcs_divisors[12] = {
1224 : : 34133, /* 16.666666... */
1225 : : 17067, /* 8.333333... */
1226 : : 11378, /* 5.555555... */
1227 : : 8533, /* 4.166666... */
1228 : : 5689, /* 2.777777... */
1229 : : 4267, /* 2.083333... */
1230 : : 3923, /* 1.851851... */
1231 : : 3413, /* 1.666666... */
1232 : : 2844, /* 1.388888... */
1233 : : 2560, /* 1.250000... */
1234 : : 2276, /* 1.111111... */
1235 : : 2048, /* 1.000000... */
1236 : : };
1237 : 0 : u32 rates_160M[3] = { 960777777, 907400000, 816666666 };
1238 : 0 : u32 rates_969[3] = { 480388888, 453700000, 408333333 };
1239 : 0 : u32 rates_484[3] = { 229411111, 216666666, 195000000 };
1240 : 0 : u32 rates_242[3] = { 114711111, 108333333, 97500000 };
1241 : 0 : u32 rates_106[3] = { 40000000, 37777777, 34000000 };
1242 : 0 : u32 rates_52[3] = { 18820000, 17777777, 16000000 };
1243 : 0 : u32 rates_26[3] = { 9411111, 8888888, 8000000 };
1244 : : u64 tmp;
1245 : : u32 result;
1246 : :
1247 [ # # # # : 0 : if (WARN_ON_ONCE(rate->mcs > 11))
# # ]
1248 : : return 0;
1249 : :
1250 [ # # # # : 0 : if (WARN_ON_ONCE(rate->he_gi > NL80211_RATE_INFO_HE_GI_3_2))
# # ]
1251 : : return 0;
1252 [ # # # # : 0 : if (WARN_ON_ONCE(rate->he_ru_alloc >
# # ]
1253 : : NL80211_RATE_INFO_HE_RU_ALLOC_2x996))
1254 : : return 0;
1255 [ # # # # : 0 : if (WARN_ON_ONCE(rate->nss < 1 || rate->nss > 8))
# # ]
1256 : : return 0;
1257 : :
1258 [ # # ]: 0 : if (rate->bw == RATE_INFO_BW_160)
1259 : 0 : result = rates_160M[rate->he_gi];
1260 [ # # # # ]: 0 : else if (rate->bw == RATE_INFO_BW_80 ||
1261 [ # # ]: 0 : (rate->bw == RATE_INFO_BW_HE_RU &&
1262 : 0 : rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_996))
1263 : 0 : result = rates_969[rate->he_gi];
1264 [ # # # # ]: 0 : else if (rate->bw == RATE_INFO_BW_40 ||
1265 [ # # ]: 0 : (rate->bw == RATE_INFO_BW_HE_RU &&
1266 : 0 : rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_484))
1267 : 0 : result = rates_484[rate->he_gi];
1268 [ # # # # ]: 0 : else if (rate->bw == RATE_INFO_BW_20 ||
1269 [ # # ]: 0 : (rate->bw == RATE_INFO_BW_HE_RU &&
1270 : 0 : rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_242))
1271 : 0 : result = rates_242[rate->he_gi];
1272 [ # # # # ]: 0 : else if (rate->bw == RATE_INFO_BW_HE_RU &&
1273 : 0 : rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_106)
1274 : 0 : result = rates_106[rate->he_gi];
1275 [ # # # # ]: 0 : else if (rate->bw == RATE_INFO_BW_HE_RU &&
1276 : 0 : rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_52)
1277 : 0 : result = rates_52[rate->he_gi];
1278 [ # # # # ]: 0 : else if (rate->bw == RATE_INFO_BW_HE_RU &&
1279 : 0 : rate->he_ru_alloc == NL80211_RATE_INFO_HE_RU_ALLOC_26)
1280 : 0 : result = rates_26[rate->he_gi];
1281 : : else {
1282 : 0 : WARN(1, "invalid HE MCS: bw:%d, ru:%d\n",
1283 : : rate->bw, rate->he_ru_alloc);
1284 : 0 : return 0;
1285 : : }
1286 : :
1287 : : /* now scale to the appropriate MCS */
1288 : 0 : tmp = result;
1289 : 0 : tmp *= SCALE;
1290 [ # # # # : 0 : do_div(tmp, mcs_divisors[rate->mcs]);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
1291 : 0 : result = tmp;
1292 : :
1293 : : /* and take NSS, DCM into account */
1294 : 0 : result = (result * rate->nss) / 8;
1295 [ # # ]: 0 : if (rate->he_dcm)
1296 : 0 : result /= 2;
1297 : :
1298 : 0 : return result / 10000;
1299 : : }
1300 : :
1301 : 0 : u32 cfg80211_calculate_bitrate(struct rate_info *rate)
1302 : : {
1303 [ # # ]: 0 : if (rate->flags & RATE_INFO_FLAGS_MCS)
1304 : 0 : return cfg80211_calculate_bitrate_ht(rate);
1305 [ # # ]: 0 : if (rate->flags & RATE_INFO_FLAGS_DMG)
1306 : 0 : return cfg80211_calculate_bitrate_dmg(rate);
1307 [ # # ]: 0 : if (rate->flags & RATE_INFO_FLAGS_EDMG)
1308 : 0 : return cfg80211_calculate_bitrate_edmg(rate);
1309 [ # # ]: 0 : if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
1310 : 0 : return cfg80211_calculate_bitrate_vht(rate);
1311 [ # # ]: 0 : if (rate->flags & RATE_INFO_FLAGS_HE_MCS)
1312 : 0 : return cfg80211_calculate_bitrate_he(rate);
1313 : :
1314 : 0 : return rate->legacy;
1315 : : }
1316 : : EXPORT_SYMBOL(cfg80211_calculate_bitrate);
1317 : :
1318 : 0 : int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
1319 : : enum ieee80211_p2p_attr_id attr,
1320 : : u8 *buf, unsigned int bufsize)
1321 : : {
1322 : : u8 *out = buf;
1323 : : u16 attr_remaining = 0;
1324 : : bool desired_attr = false;
1325 : : u16 desired_len = 0;
1326 : :
1327 [ # # ]: 0 : while (len > 0) {
1328 : : unsigned int iedatalen;
1329 : : unsigned int copy;
1330 : : const u8 *iedata;
1331 : :
1332 [ # # ]: 0 : if (len < 2)
1333 : : return -EILSEQ;
1334 : 0 : iedatalen = ies[1];
1335 [ # # ]: 0 : if (iedatalen + 2 > len)
1336 : : return -EILSEQ;
1337 : :
1338 [ # # ]: 0 : if (ies[0] != WLAN_EID_VENDOR_SPECIFIC)
1339 : : goto cont;
1340 : :
1341 [ # # ]: 0 : if (iedatalen < 4)
1342 : : goto cont;
1343 : :
1344 : : iedata = ies + 2;
1345 : :
1346 : : /* check WFA OUI, P2P subtype */
1347 [ # # # # : 0 : if (iedata[0] != 0x50 || iedata[1] != 0x6f ||
# # ]
1348 [ # # ]: 0 : iedata[2] != 0x9a || iedata[3] != 0x09)
1349 : : goto cont;
1350 : :
1351 : 0 : iedatalen -= 4;
1352 : 0 : iedata += 4;
1353 : :
1354 : : /* check attribute continuation into this IE */
1355 : 0 : copy = min_t(unsigned int, attr_remaining, iedatalen);
1356 [ # # ]: 0 : if (copy && desired_attr) {
1357 : 0 : desired_len += copy;
1358 [ # # ]: 0 : if (out) {
1359 : 0 : memcpy(out, iedata, min(bufsize, copy));
1360 : 0 : out += min(bufsize, copy);
1361 : 0 : bufsize -= min(bufsize, copy);
1362 : : }
1363 : :
1364 : :
1365 [ # # ]: 0 : if (copy == attr_remaining)
1366 : 0 : return desired_len;
1367 : : }
1368 : :
1369 : 0 : attr_remaining -= copy;
1370 [ # # ]: 0 : if (attr_remaining)
1371 : : goto cont;
1372 : :
1373 : 0 : iedatalen -= copy;
1374 : 0 : iedata += copy;
1375 : :
1376 [ # # ]: 0 : while (iedatalen > 0) {
1377 : : u16 attr_len;
1378 : :
1379 : : /* P2P attribute ID & size must fit */
1380 [ # # ]: 0 : if (iedatalen < 3)
1381 : : return -EILSEQ;
1382 : 0 : desired_attr = iedata[0] == attr;
1383 : : attr_len = get_unaligned_le16(iedata + 1);
1384 : 0 : iedatalen -= 3;
1385 : 0 : iedata += 3;
1386 : :
1387 : 0 : copy = min_t(unsigned int, attr_len, iedatalen);
1388 : :
1389 [ # # ]: 0 : if (desired_attr) {
1390 : 0 : desired_len += copy;
1391 [ # # ]: 0 : if (out) {
1392 : 0 : memcpy(out, iedata, min(bufsize, copy));
1393 : 0 : out += min(bufsize, copy);
1394 : 0 : bufsize -= min(bufsize, copy);
1395 : : }
1396 : :
1397 [ # # ]: 0 : if (copy == attr_len)
1398 : 0 : return desired_len;
1399 : : }
1400 : :
1401 : 0 : iedata += copy;
1402 : 0 : iedatalen -= copy;
1403 : 0 : attr_remaining = attr_len - copy;
1404 : : }
1405 : :
1406 : : cont:
1407 : 0 : len -= ies[1] + 2;
1408 : 0 : ies += ies[1] + 2;
1409 : : }
1410 : :
1411 [ # # ]: 0 : if (attr_remaining && desired_attr)
1412 : : return -EILSEQ;
1413 : :
1414 : 0 : return -ENOENT;
1415 : : }
1416 : : EXPORT_SYMBOL(cfg80211_get_p2p_attr);
1417 : :
1418 : 0 : static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id, bool id_ext)
1419 : : {
1420 : : int i;
1421 : :
1422 : : /* Make sure array values are legal */
1423 [ # # # # ]: 0 : if (WARN_ON(ids[n_ids - 1] == WLAN_EID_EXTENSION))
1424 : : return false;
1425 : :
1426 : : i = 0;
1427 [ # # ]: 0 : while (i < n_ids) {
1428 [ # # ]: 0 : if (ids[i] == WLAN_EID_EXTENSION) {
1429 [ # # # # ]: 0 : if (id_ext && (ids[i + 1] == id))
1430 : : return true;
1431 : :
1432 : 0 : i += 2;
1433 : 0 : continue;
1434 : : }
1435 : :
1436 [ # # # # ]: 0 : if (ids[i] == id && !id_ext)
1437 : : return true;
1438 : :
1439 : 0 : i++;
1440 : : }
1441 : : return false;
1442 : : }
1443 : :
1444 : 0 : static size_t skip_ie(const u8 *ies, size_t ielen, size_t pos)
1445 : : {
1446 : : /* we assume a validly formed IEs buffer */
1447 : 0 : u8 len = ies[pos + 1];
1448 : :
1449 : 0 : pos += 2 + len;
1450 : :
1451 : : /* the IE itself must have 255 bytes for fragments to follow */
1452 [ # # ]: 0 : if (len < 255)
1453 : : return pos;
1454 : :
1455 [ # # # # ]: 0 : while (pos < ielen && ies[pos] == WLAN_EID_FRAGMENT) {
1456 : 0 : len = ies[pos + 1];
1457 : 0 : pos += 2 + len;
1458 : : }
1459 : :
1460 : 0 : return pos;
1461 : : }
1462 : :
1463 : 0 : size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
1464 : : const u8 *ids, int n_ids,
1465 : : const u8 *after_ric, int n_after_ric,
1466 : : size_t offset)
1467 : : {
1468 : : size_t pos = offset;
1469 : :
1470 [ # # ]: 0 : while (pos < ielen) {
1471 : : u8 ext = 0;
1472 : :
1473 [ # # ]: 0 : if (ies[pos] == WLAN_EID_EXTENSION)
1474 : : ext = 2;
1475 [ # # ]: 0 : if ((pos + ext) >= ielen)
1476 : : break;
1477 : :
1478 [ # # ]: 0 : if (!ieee80211_id_in_list(ids, n_ids, ies[pos + ext],
1479 : : ies[pos] == WLAN_EID_EXTENSION))
1480 : : break;
1481 : :
1482 [ # # # # ]: 0 : if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
1483 : 0 : pos = skip_ie(ies, ielen, pos);
1484 : :
1485 [ # # ]: 0 : while (pos < ielen) {
1486 [ # # ]: 0 : if (ies[pos] == WLAN_EID_EXTENSION)
1487 : : ext = 2;
1488 : : else
1489 : : ext = 0;
1490 : :
1491 [ # # ]: 0 : if ((pos + ext) >= ielen)
1492 : : break;
1493 : :
1494 [ # # ]: 0 : if (!ieee80211_id_in_list(after_ric,
1495 : : n_after_ric,
1496 : 0 : ies[pos + ext],
1497 : : ext == 2))
1498 : 0 : pos = skip_ie(ies, ielen, pos);
1499 : : else
1500 : : break;
1501 : : }
1502 : : } else {
1503 : 0 : pos = skip_ie(ies, ielen, pos);
1504 : : }
1505 : : }
1506 : :
1507 : 0 : return pos;
1508 : : }
1509 : : EXPORT_SYMBOL(ieee80211_ie_split_ric);
1510 : :
1511 : 0 : bool ieee80211_operating_class_to_band(u8 operating_class,
1512 : : enum nl80211_band *band)
1513 : : {
1514 [ # # # # : 0 : switch (operating_class) {
# ]
1515 : : case 112:
1516 : : case 115 ... 127:
1517 : : case 128 ... 130:
1518 : 0 : *band = NL80211_BAND_5GHZ;
1519 : 0 : return true;
1520 : : case 131 ... 135:
1521 : 0 : *band = NL80211_BAND_6GHZ;
1522 : 0 : return true;
1523 : : case 81:
1524 : : case 82:
1525 : : case 83:
1526 : : case 84:
1527 : 0 : *band = NL80211_BAND_2GHZ;
1528 : 0 : return true;
1529 : : case 180:
1530 : 0 : *band = NL80211_BAND_60GHZ;
1531 : 0 : return true;
1532 : : }
1533 : :
1534 : : return false;
1535 : : }
1536 : : EXPORT_SYMBOL(ieee80211_operating_class_to_band);
1537 : :
1538 : 0 : bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
1539 : : u8 *op_class)
1540 : : {
1541 : : u8 vht_opclass;
1542 : 0 : u32 freq = chandef->center_freq1;
1543 : :
1544 [ # # ]: 0 : if (freq >= 2412 && freq <= 2472) {
1545 [ # # ]: 0 : if (chandef->width > NL80211_CHAN_WIDTH_40)
1546 : : return false;
1547 : :
1548 : : /* 2.407 GHz, channels 1..13 */
1549 [ # # ]: 0 : if (chandef->width == NL80211_CHAN_WIDTH_40) {
1550 [ # # ]: 0 : if (freq > chandef->chan->center_freq)
1551 : 0 : *op_class = 83; /* HT40+ */
1552 : : else
1553 : 0 : *op_class = 84; /* HT40- */
1554 : : } else {
1555 : 0 : *op_class = 81;
1556 : : }
1557 : :
1558 : : return true;
1559 : : }
1560 : :
1561 [ # # ]: 0 : if (freq == 2484) {
1562 : : /* channel 14 is only for IEEE 802.11b */
1563 [ # # ]: 0 : if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT)
1564 : : return false;
1565 : :
1566 : 0 : *op_class = 82; /* channel 14 */
1567 : 0 : return true;
1568 : : }
1569 : :
1570 [ # # # # : 0 : switch (chandef->width) {
# ]
1571 : : case NL80211_CHAN_WIDTH_80:
1572 : : vht_opclass = 128;
1573 : : break;
1574 : : case NL80211_CHAN_WIDTH_160:
1575 : : vht_opclass = 129;
1576 : 0 : break;
1577 : : case NL80211_CHAN_WIDTH_80P80:
1578 : : vht_opclass = 130;
1579 : 0 : break;
1580 : : case NL80211_CHAN_WIDTH_10:
1581 : : case NL80211_CHAN_WIDTH_5:
1582 : : return false; /* unsupported for now */
1583 : : default:
1584 : : vht_opclass = 0;
1585 : 0 : break;
1586 : : }
1587 : :
1588 : : /* 5 GHz, channels 36..48 */
1589 [ # # ]: 0 : if (freq >= 5180 && freq <= 5240) {
1590 [ # # ]: 0 : if (vht_opclass) {
1591 : 0 : *op_class = vht_opclass;
1592 [ # # ]: 0 : } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
1593 [ # # ]: 0 : if (freq > chandef->chan->center_freq)
1594 : 0 : *op_class = 116;
1595 : : else
1596 : 0 : *op_class = 117;
1597 : : } else {
1598 : 0 : *op_class = 115;
1599 : : }
1600 : :
1601 : : return true;
1602 : : }
1603 : :
1604 : : /* 5 GHz, channels 52..64 */
1605 [ # # ]: 0 : if (freq >= 5260 && freq <= 5320) {
1606 [ # # ]: 0 : if (vht_opclass) {
1607 : 0 : *op_class = vht_opclass;
1608 [ # # ]: 0 : } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
1609 [ # # ]: 0 : if (freq > chandef->chan->center_freq)
1610 : 0 : *op_class = 119;
1611 : : else
1612 : 0 : *op_class = 120;
1613 : : } else {
1614 : 0 : *op_class = 118;
1615 : : }
1616 : :
1617 : : return true;
1618 : : }
1619 : :
1620 : : /* 5 GHz, channels 100..144 */
1621 [ # # ]: 0 : if (freq >= 5500 && freq <= 5720) {
1622 [ # # ]: 0 : if (vht_opclass) {
1623 : 0 : *op_class = vht_opclass;
1624 [ # # ]: 0 : } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
1625 [ # # ]: 0 : if (freq > chandef->chan->center_freq)
1626 : 0 : *op_class = 122;
1627 : : else
1628 : 0 : *op_class = 123;
1629 : : } else {
1630 : 0 : *op_class = 121;
1631 : : }
1632 : :
1633 : : return true;
1634 : : }
1635 : :
1636 : : /* 5 GHz, channels 149..169 */
1637 [ # # ]: 0 : if (freq >= 5745 && freq <= 5845) {
1638 [ # # ]: 0 : if (vht_opclass) {
1639 : 0 : *op_class = vht_opclass;
1640 [ # # ]: 0 : } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
1641 [ # # ]: 0 : if (freq > chandef->chan->center_freq)
1642 : 0 : *op_class = 126;
1643 : : else
1644 : 0 : *op_class = 127;
1645 [ # # ]: 0 : } else if (freq <= 5805) {
1646 : 0 : *op_class = 124;
1647 : : } else {
1648 : 0 : *op_class = 125;
1649 : : }
1650 : :
1651 : : return true;
1652 : : }
1653 : :
1654 : : /* 56.16 GHz, channel 1..4 */
1655 [ # # ]: 0 : if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) {
1656 [ # # ]: 0 : if (chandef->width >= NL80211_CHAN_WIDTH_40)
1657 : : return false;
1658 : :
1659 : 0 : *op_class = 180;
1660 : 0 : return true;
1661 : : }
1662 : :
1663 : : /* not supported yet */
1664 : : return false;
1665 : : }
1666 : : EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
1667 : :
1668 : 0 : static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
1669 : : u32 *beacon_int_gcd,
1670 : : bool *beacon_int_different)
1671 : : {
1672 : : struct wireless_dev *wdev;
1673 : :
1674 : 0 : *beacon_int_gcd = 0;
1675 : 0 : *beacon_int_different = false;
1676 : :
1677 [ # # ]: 0 : list_for_each_entry(wdev, &wiphy->wdev_list, list) {
1678 [ # # ]: 0 : if (!wdev->beacon_interval)
1679 : 0 : continue;
1680 : :
1681 [ # # ]: 0 : if (!*beacon_int_gcd) {
1682 : 0 : *beacon_int_gcd = wdev->beacon_interval;
1683 : 0 : continue;
1684 : : }
1685 : :
1686 [ # # ]: 0 : if (wdev->beacon_interval == *beacon_int_gcd)
1687 : 0 : continue;
1688 : :
1689 : 0 : *beacon_int_different = true;
1690 : 0 : *beacon_int_gcd = gcd(*beacon_int_gcd, wdev->beacon_interval);
1691 : : }
1692 : :
1693 [ # # # # ]: 0 : if (new_beacon_int && *beacon_int_gcd != new_beacon_int) {
1694 [ # # ]: 0 : if (*beacon_int_gcd)
1695 : 0 : *beacon_int_different = true;
1696 : 0 : *beacon_int_gcd = gcd(*beacon_int_gcd, new_beacon_int);
1697 : : }
1698 : 0 : }
1699 : :
1700 : 0 : int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
1701 : : enum nl80211_iftype iftype, u32 beacon_int)
1702 : : {
1703 : : /*
1704 : : * This is just a basic pre-condition check; if interface combinations
1705 : : * are possible the driver must already be checking those with a call
1706 : : * to cfg80211_check_combinations(), in which case we'll validate more
1707 : : * through the cfg80211_calculate_bi_data() call and code in
1708 : : * cfg80211_iter_combinations().
1709 : : */
1710 : :
1711 [ # # ]: 0 : if (beacon_int < 10 || beacon_int > 10000)
1712 : : return -EINVAL;
1713 : :
1714 : 0 : return 0;
1715 : : }
1716 : :
1717 : 0 : int cfg80211_iter_combinations(struct wiphy *wiphy,
1718 : : struct iface_combination_params *params,
1719 : : void (*iter)(const struct ieee80211_iface_combination *c,
1720 : : void *data),
1721 : : void *data)
1722 : : {
1723 : : const struct ieee80211_regdomain *regdom;
1724 : : enum nl80211_dfs_regions region = 0;
1725 : : int i, j, iftype;
1726 : : int num_interfaces = 0;
1727 : : u32 used_iftypes = 0;
1728 : : u32 beacon_int_gcd;
1729 : : bool beacon_int_different;
1730 : :
1731 : : /*
1732 : : * This is a bit strange, since the iteration used to rely only on
1733 : : * the data given by the driver, but here it now relies on context,
1734 : : * in form of the currently operating interfaces.
1735 : : * This is OK for all current users, and saves us from having to
1736 : : * push the GCD calculations into all the drivers.
1737 : : * In the future, this should probably rely more on data that's in
1738 : : * cfg80211 already - the only thing not would appear to be any new
1739 : : * interfaces (while being brought up) and channel/radar data.
1740 : : */
1741 : 0 : cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
1742 : : &beacon_int_gcd, &beacon_int_different);
1743 : :
1744 [ # # ]: 0 : if (params->radar_detect) {
1745 : : rcu_read_lock();
1746 : 0 : regdom = rcu_dereference(cfg80211_regdomain);
1747 [ # # ]: 0 : if (regdom)
1748 : 0 : region = regdom->dfs_region;
1749 : : rcu_read_unlock();
1750 : : }
1751 : :
1752 [ # # ]: 0 : for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
1753 : 0 : num_interfaces += params->iftype_num[iftype];
1754 [ # # # # ]: 0 : if (params->iftype_num[iftype] > 0 &&
1755 : 0 : !cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
1756 : 0 : used_iftypes |= BIT(iftype);
1757 : : }
1758 : :
1759 [ # # ]: 0 : for (i = 0; i < wiphy->n_iface_combinations; i++) {
1760 : : const struct ieee80211_iface_combination *c;
1761 : : struct ieee80211_iface_limit *limits;
1762 : : u32 all_iftypes = 0;
1763 : :
1764 : 0 : c = &wiphy->iface_combinations[i];
1765 : :
1766 [ # # ]: 0 : if (num_interfaces > c->max_interfaces)
1767 : 0 : continue;
1768 [ # # ]: 0 : if (params->num_different_channels > c->num_different_channels)
1769 : 0 : continue;
1770 : :
1771 : 0 : limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
1772 : : GFP_KERNEL);
1773 [ # # ]: 0 : if (!limits)
1774 : : return -ENOMEM;
1775 : :
1776 [ # # ]: 0 : for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
1777 [ # # ]: 0 : if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1))
1778 : 0 : continue;
1779 [ # # ]: 0 : for (j = 0; j < c->n_limits; j++) {
1780 : 0 : all_iftypes |= limits[j].types;
1781 [ # # ]: 0 : if (!(limits[j].types & BIT(iftype)))
1782 : 0 : continue;
1783 [ # # ]: 0 : if (limits[j].max < params->iftype_num[iftype])
1784 : : goto cont;
1785 : 0 : limits[j].max -= params->iftype_num[iftype];
1786 : : }
1787 : : }
1788 : :
1789 [ # # ]: 0 : if (params->radar_detect !=
1790 : 0 : (c->radar_detect_widths & params->radar_detect))
1791 : : goto cont;
1792 : :
1793 [ # # # # : 0 : if (params->radar_detect && c->radar_detect_regions &&
# # ]
1794 : 0 : !(c->radar_detect_regions & BIT(region)))
1795 : : goto cont;
1796 : :
1797 : : /* Finally check that all iftypes that we're currently
1798 : : * using are actually part of this combination. If they
1799 : : * aren't then we can't use this combination and have
1800 : : * to continue to the next.
1801 : : */
1802 [ # # ]: 0 : if ((all_iftypes & used_iftypes) != used_iftypes)
1803 : : goto cont;
1804 : :
1805 [ # # ]: 0 : if (beacon_int_gcd) {
1806 [ # # # # ]: 0 : if (c->beacon_int_min_gcd &&
1807 : : beacon_int_gcd < c->beacon_int_min_gcd)
1808 : : goto cont;
1809 [ # # # # ]: 0 : if (!c->beacon_int_min_gcd && beacon_int_different)
1810 : : goto cont;
1811 : : }
1812 : :
1813 : : /* This combination covered all interface types and
1814 : : * supported the requested numbers, so we're good.
1815 : : */
1816 : :
1817 : 0 : (*iter)(c, data);
1818 : : cont:
1819 : 0 : kfree(limits);
1820 : : }
1821 : :
1822 : : return 0;
1823 : : }
1824 : : EXPORT_SYMBOL(cfg80211_iter_combinations);
1825 : :
1826 : : static void
1827 : 0 : cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c,
1828 : : void *data)
1829 : : {
1830 : : int *num = data;
1831 : 0 : (*num)++;
1832 : 0 : }
1833 : :
1834 : 0 : int cfg80211_check_combinations(struct wiphy *wiphy,
1835 : : struct iface_combination_params *params)
1836 : : {
1837 : 0 : int err, num = 0;
1838 : :
1839 : 0 : err = cfg80211_iter_combinations(wiphy, params,
1840 : : cfg80211_iter_sum_ifcombs, &num);
1841 [ # # ]: 0 : if (err)
1842 : : return err;
1843 [ # # ]: 0 : if (num == 0)
1844 : : return -EBUSY;
1845 : :
1846 : 0 : return 0;
1847 : : }
1848 : : EXPORT_SYMBOL(cfg80211_check_combinations);
1849 : :
1850 : 0 : int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
1851 : : const u8 *rates, unsigned int n_rates,
1852 : : u32 *mask)
1853 : : {
1854 : : int i, j;
1855 : :
1856 [ # # ]: 0 : if (!sband)
1857 : : return -EINVAL;
1858 : :
1859 [ # # ]: 0 : if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES)
1860 : : return -EINVAL;
1861 : :
1862 : 0 : *mask = 0;
1863 : :
1864 [ # # ]: 0 : for (i = 0; i < n_rates; i++) {
1865 : 0 : int rate = (rates[i] & 0x7f) * 5;
1866 : : bool found = false;
1867 : :
1868 [ # # ]: 0 : for (j = 0; j < sband->n_bitrates; j++) {
1869 [ # # ]: 0 : if (sband->bitrates[j].bitrate == rate) {
1870 : : found = true;
1871 : 0 : *mask |= BIT(j);
1872 : 0 : break;
1873 : : }
1874 : : }
1875 [ # # ]: 0 : if (!found)
1876 : : return -EINVAL;
1877 : : }
1878 : :
1879 : : /*
1880 : : * mask must have at least one bit set here since we
1881 : : * didn't accept a 0-length rates array nor allowed
1882 : : * entries in the array that didn't exist
1883 : : */
1884 : :
1885 : : return 0;
1886 : : }
1887 : :
1888 : 0 : unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy)
1889 : : {
1890 : : enum nl80211_band band;
1891 : : unsigned int n_channels = 0;
1892 : :
1893 [ # # ]: 0 : for (band = 0; band < NUM_NL80211_BANDS; band++)
1894 [ # # ]: 0 : if (wiphy->bands[band])
1895 : 0 : n_channels += wiphy->bands[band]->n_channels;
1896 : :
1897 : 0 : return n_channels;
1898 : : }
1899 : : EXPORT_SYMBOL(ieee80211_get_num_supported_channels);
1900 : :
1901 : 0 : int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
1902 : : struct station_info *sinfo)
1903 : : {
1904 : : struct cfg80211_registered_device *rdev;
1905 : : struct wireless_dev *wdev;
1906 : :
1907 : 0 : wdev = dev->ieee80211_ptr;
1908 [ # # ]: 0 : if (!wdev)
1909 : : return -EOPNOTSUPP;
1910 : :
1911 : 0 : rdev = wiphy_to_rdev(wdev->wiphy);
1912 [ # # ]: 0 : if (!rdev->ops->get_station)
1913 : : return -EOPNOTSUPP;
1914 : :
1915 : 0 : memset(sinfo, 0, sizeof(*sinfo));
1916 : :
1917 : 0 : return rdev_get_station(rdev, dev, mac_addr, sinfo);
1918 : : }
1919 : : EXPORT_SYMBOL(cfg80211_get_station);
1920 : :
1921 : 0 : void cfg80211_free_nan_func(struct cfg80211_nan_func *f)
1922 : : {
1923 : : int i;
1924 : :
1925 [ # # ]: 0 : if (!f)
1926 : 0 : return;
1927 : :
1928 : 0 : kfree(f->serv_spec_info);
1929 : 0 : kfree(f->srf_bf);
1930 : 0 : kfree(f->srf_macs);
1931 [ # # ]: 0 : for (i = 0; i < f->num_rx_filters; i++)
1932 : 0 : kfree(f->rx_filters[i].filter);
1933 : :
1934 [ # # ]: 0 : for (i = 0; i < f->num_tx_filters; i++)
1935 : 0 : kfree(f->tx_filters[i].filter);
1936 : :
1937 : 0 : kfree(f->rx_filters);
1938 : 0 : kfree(f->tx_filters);
1939 : 0 : kfree(f);
1940 : : }
1941 : : EXPORT_SYMBOL(cfg80211_free_nan_func);
1942 : :
1943 : 0 : bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
1944 : : u32 center_freq_khz, u32 bw_khz)
1945 : : {
1946 : : u32 start_freq_khz, end_freq_khz;
1947 : :
1948 : 0 : start_freq_khz = center_freq_khz - (bw_khz / 2);
1949 : 0 : end_freq_khz = center_freq_khz + (bw_khz / 2);
1950 : :
1951 [ # # # # ]: 0 : if (start_freq_khz >= freq_range->start_freq_khz &&
1952 : 0 : end_freq_khz <= freq_range->end_freq_khz)
1953 : : return true;
1954 : :
1955 : 0 : return false;
1956 : : }
1957 : :
1958 : 0 : int cfg80211_sinfo_alloc_tid_stats(struct station_info *sinfo, gfp_t gfp)
1959 : : {
1960 : 0 : sinfo->pertid = kcalloc(IEEE80211_NUM_TIDS + 1,
1961 : : sizeof(*(sinfo->pertid)),
1962 : : gfp);
1963 [ # # ]: 0 : if (!sinfo->pertid)
1964 : : return -ENOMEM;
1965 : :
1966 : 0 : return 0;
1967 : : }
1968 : : EXPORT_SYMBOL(cfg80211_sinfo_alloc_tid_stats);
1969 : :
1970 : : /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
1971 : : /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
1972 : : const unsigned char rfc1042_header[] __aligned(2) =
1973 : : { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
1974 : : EXPORT_SYMBOL(rfc1042_header);
1975 : :
1976 : : /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
1977 : : const unsigned char bridge_tunnel_header[] __aligned(2) =
1978 : : { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
1979 : : EXPORT_SYMBOL(bridge_tunnel_header);
1980 : :
1981 : : /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
1982 : : struct iapp_layer2_update {
1983 : : u8 da[ETH_ALEN]; /* broadcast */
1984 : : u8 sa[ETH_ALEN]; /* STA addr */
1985 : : __be16 len; /* 6 */
1986 : : u8 dsap; /* 0 */
1987 : : u8 ssap; /* 0 */
1988 : : u8 control;
1989 : : u8 xid_info[3];
1990 : : } __packed;
1991 : :
1992 : 0 : void cfg80211_send_layer2_update(struct net_device *dev, const u8 *addr)
1993 : : {
1994 : : struct iapp_layer2_update *msg;
1995 : : struct sk_buff *skb;
1996 : :
1997 : : /* Send Level 2 Update Frame to update forwarding tables in layer 2
1998 : : * bridge devices */
1999 : :
2000 : : skb = dev_alloc_skb(sizeof(*msg));
2001 [ # # ]: 0 : if (!skb)
2002 : 0 : return;
2003 : 0 : msg = skb_put(skb, sizeof(*msg));
2004 : :
2005 : : /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
2006 : : * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
2007 : :
2008 : 0 : eth_broadcast_addr(msg->da);
2009 : : ether_addr_copy(msg->sa, addr);
2010 : 0 : msg->len = htons(6);
2011 : 0 : msg->dsap = 0;
2012 : 0 : msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
2013 : 0 : msg->control = 0xaf; /* XID response lsb.1111F101.
2014 : : * F=0 (no poll command; unsolicited frame) */
2015 : 0 : msg->xid_info[0] = 0x81; /* XID format identifier */
2016 : 0 : msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
2017 : 0 : msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
2018 : :
2019 : 0 : skb->dev = dev;
2020 : 0 : skb->protocol = eth_type_trans(skb, dev);
2021 : 0 : memset(skb->cb, 0, sizeof(skb->cb));
2022 : 0 : netif_rx_ni(skb);
2023 : : }
2024 : : EXPORT_SYMBOL(cfg80211_send_layer2_update);
2025 : :
2026 : 0 : int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
2027 : : enum ieee80211_vht_chanwidth bw,
2028 : : int mcs, bool ext_nss_bw_capable)
2029 : : {
2030 : 0 : u16 map = le16_to_cpu(cap->supp_mcs.rx_mcs_map);
2031 : : int max_vht_nss = 0;
2032 : : int ext_nss_bw;
2033 : : int supp_width;
2034 : : int i, mcs_encoding;
2035 : :
2036 [ # # ]: 0 : if (map == 0xffff)
2037 : : return 0;
2038 : :
2039 [ # # # # ]: 0 : if (WARN_ON(mcs > 9))
2040 : : return 0;
2041 [ # # ]: 0 : if (mcs <= 7)
2042 : : mcs_encoding = 0;
2043 [ # # ]: 0 : else if (mcs == 8)
2044 : : mcs_encoding = 1;
2045 : : else
2046 : : mcs_encoding = 2;
2047 : :
2048 : : /* find max_vht_nss for the given MCS */
2049 [ # # ]: 0 : for (i = 7; i >= 0; i--) {
2050 : 0 : int supp = (map >> (2 * i)) & 3;
2051 : :
2052 [ # # ]: 0 : if (supp == 3)
2053 : 0 : continue;
2054 : :
2055 [ # # ]: 0 : if (supp >= mcs_encoding) {
2056 : 0 : max_vht_nss = i + 1;
2057 : 0 : break;
2058 : : }
2059 : : }
2060 : :
2061 [ # # ]: 0 : if (!(cap->supp_mcs.tx_mcs_map &
2062 : : cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE)))
2063 : : return max_vht_nss;
2064 : :
2065 : 0 : ext_nss_bw = le32_get_bits(cap->vht_cap_info,
2066 : : IEEE80211_VHT_CAP_EXT_NSS_BW_MASK);
2067 : 0 : supp_width = le32_get_bits(cap->vht_cap_info,
2068 : : IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK);
2069 : :
2070 : : /* if not capable, treat ext_nss_bw as 0 */
2071 [ # # ]: 0 : if (!ext_nss_bw_capable)
2072 : : ext_nss_bw = 0;
2073 : :
2074 : : /* This is invalid */
2075 [ # # ]: 0 : if (supp_width == 3)
2076 : : return 0;
2077 : :
2078 : : /* This is an invalid combination so pretend nothing is supported */
2079 [ # # # # ]: 0 : if (supp_width == 2 && (ext_nss_bw == 1 || ext_nss_bw == 2))
2080 : : return 0;
2081 : :
2082 : : /*
2083 : : * Cover all the special cases according to IEEE 802.11-2016
2084 : : * Table 9-250. All other cases are either factor of 1 or not
2085 : : * valid/supported.
2086 : : */
2087 [ # # # # ]: 0 : switch (bw) {
2088 : : case IEEE80211_VHT_CHANWIDTH_USE_HT:
2089 : : case IEEE80211_VHT_CHANWIDTH_80MHZ:
2090 [ # # # # ]: 0 : if ((supp_width == 1 || supp_width == 2) &&
2091 : : ext_nss_bw == 3)
2092 : 0 : return 2 * max_vht_nss;
2093 : : break;
2094 : : case IEEE80211_VHT_CHANWIDTH_160MHZ:
2095 [ # # # # ]: 0 : if (supp_width == 0 &&
2096 : 0 : (ext_nss_bw == 1 || ext_nss_bw == 2))
2097 : 0 : return max_vht_nss / 2;
2098 [ # # ]: 0 : if (supp_width == 0 &&
2099 : 0 : ext_nss_bw == 3)
2100 : 0 : return (3 * max_vht_nss) / 4;
2101 [ # # ]: 0 : if (supp_width == 1 &&
2102 : : ext_nss_bw == 3)
2103 : 0 : return 2 * max_vht_nss;
2104 : : break;
2105 : : case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
2106 [ # # ]: 0 : if (supp_width == 0 && ext_nss_bw == 1)
2107 : : return 0; /* not possible */
2108 [ # # ]: 0 : if (supp_width == 0 &&
2109 : 0 : ext_nss_bw == 2)
2110 : 0 : return max_vht_nss / 2;
2111 [ # # ]: 0 : if (supp_width == 0 &&
2112 : 0 : ext_nss_bw == 3)
2113 : 0 : return (3 * max_vht_nss) / 4;
2114 [ # # ]: 0 : if (supp_width == 1 &&
2115 : 0 : ext_nss_bw == 0)
2116 : : return 0; /* not possible */
2117 [ # # ]: 0 : if (supp_width == 1 &&
2118 : : ext_nss_bw == 1)
2119 : 0 : return max_vht_nss / 2;
2120 [ # # ]: 0 : if (supp_width == 1 &&
2121 : : ext_nss_bw == 2)
2122 : 0 : return (3 * max_vht_nss) / 4;
2123 : : break;
2124 : : }
2125 : :
2126 : : /* not covered or invalid combination received */
2127 : : return max_vht_nss;
2128 : : }
2129 : : EXPORT_SYMBOL(ieee80211_get_vht_max_nss);
2130 : :
2131 : 0 : bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype,
2132 : : bool is_4addr, u8 check_swif)
2133 : :
2134 : : {
2135 : 0 : bool is_vlan = iftype == NL80211_IFTYPE_AP_VLAN;
2136 : :
2137 [ # # # ]: 0 : switch (check_swif) {
2138 : : case 0:
2139 [ # # ]: 0 : if (is_vlan && is_4addr)
2140 : 0 : return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
2141 : 0 : return wiphy->interface_modes & BIT(iftype);
2142 : : case 1:
2143 [ # # # # ]: 0 : if (!(wiphy->software_iftypes & BIT(iftype)) && is_vlan)
2144 : 0 : return wiphy->flags & WIPHY_FLAG_4ADDR_AP;
2145 : 0 : return wiphy->software_iftypes & BIT(iftype);
2146 : : default:
2147 : : break;
2148 : : }
2149 : :
2150 : : return false;
2151 : : }
2152 : : EXPORT_SYMBOL(cfg80211_iftype_allowed);
|