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